The value of a bignum expression is held in a single global array. This means
that if multiple bignum values are encountered only the most recent is valid. If such expressions are cached, eg to be emitted into a literal pool later on in the assembly, then only one expression - the last - will be correct. This patch fixes the problem for the AArch64 target by caching each bignum value locally. PR gas/16688 * config/tc-aarch64.c (literal_expression): New structure. (literal_pool): Replace exp array with literal_expression array. (add_to_lit_pool): When adding a bignum cache the big value. (s_ltorg): When emitting a bignum initialise the global bignum array from the cached value. * gas/aarch64/litpool.s: New test case. * gas/aarch64/litpool.d: Expected disassembly.
This commit is contained in:
parent
646f441776
commit
55d9b4c146
|
@ -1,3 +1,12 @@
|
|||
2014-03-12 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR gas/16688
|
||||
* config/tc-aarch64.c (literal_expression): New structure.
|
||||
(literal_pool): Replace exp array with literal_expression array.
|
||||
(add_to_lit_pool): When adding a bignum cache the big value.
|
||||
(s_ltorg): When emitting a bignum initialise the global bignum
|
||||
array from the cached value.
|
||||
|
||||
2014-03-12 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* Makefile.in: Regenerate.
|
||||
|
|
|
@ -435,9 +435,16 @@ static symbolS *last_label_seen;
|
|||
and per-sub-section basis. */
|
||||
|
||||
#define MAX_LITERAL_POOL_SIZE 1024
|
||||
typedef struct literal_expression
|
||||
{
|
||||
expressionS exp;
|
||||
/* If exp.op == O_big then this bignum holds a copy of the global bignum value. */
|
||||
LITTLENUM_TYPE * bignum;
|
||||
} literal_expression;
|
||||
|
||||
typedef struct literal_pool
|
||||
{
|
||||
expressionS literals[MAX_LITERAL_POOL_SIZE];
|
||||
literal_expression literals[MAX_LITERAL_POOL_SIZE];
|
||||
unsigned int next_free_entry;
|
||||
unsigned int id;
|
||||
symbolS *symbol;
|
||||
|
@ -1616,17 +1623,19 @@ add_to_lit_pool (expressionS *exp, int size)
|
|||
/* Check if this literal value is already in the pool. */
|
||||
for (entry = 0; entry < pool->next_free_entry; entry++)
|
||||
{
|
||||
if ((pool->literals[entry].X_op == exp->X_op)
|
||||
expressionS * litexp = & pool->literals[entry].exp;
|
||||
|
||||
if ((litexp->X_op == exp->X_op)
|
||||
&& (exp->X_op == O_constant)
|
||||
&& (pool->literals[entry].X_add_number == exp->X_add_number)
|
||||
&& (pool->literals[entry].X_unsigned == exp->X_unsigned))
|
||||
&& (litexp->X_add_number == exp->X_add_number)
|
||||
&& (litexp->X_unsigned == exp->X_unsigned))
|
||||
break;
|
||||
|
||||
if ((pool->literals[entry].X_op == exp->X_op)
|
||||
if ((litexp->X_op == exp->X_op)
|
||||
&& (exp->X_op == O_symbol)
|
||||
&& (pool->literals[entry].X_add_number == exp->X_add_number)
|
||||
&& (pool->literals[entry].X_add_symbol == exp->X_add_symbol)
|
||||
&& (pool->literals[entry].X_op_symbol == exp->X_op_symbol))
|
||||
&& (litexp->X_add_number == exp->X_add_number)
|
||||
&& (litexp->X_add_symbol == exp->X_add_symbol)
|
||||
&& (litexp->X_op_symbol == exp->X_op_symbol))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1639,8 +1648,18 @@ add_to_lit_pool (expressionS *exp, int size)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
pool->literals[entry] = *exp;
|
||||
pool->literals[entry].exp = *exp;
|
||||
pool->next_free_entry += 1;
|
||||
if (exp->X_op == O_big)
|
||||
{
|
||||
/* PR 16688: Bignums are held in a single global array. We must
|
||||
copy and preserve that value now, before it is overwritten. */
|
||||
pool->literals[entry].bignum = xmalloc (CHARS_PER_LITTLENUM * exp->X_add_number);
|
||||
memcpy (pool->literals[entry].bignum, generic_bignum,
|
||||
CHARS_PER_LITTLENUM * exp->X_add_number);
|
||||
}
|
||||
else
|
||||
pool->literals[entry].bignum = NULL;
|
||||
}
|
||||
|
||||
exp->X_op = O_symbol;
|
||||
|
@ -1734,8 +1753,26 @@ s_ltorg (int ignored ATTRIBUTE_UNUSED)
|
|||
symbol_table_insert (pool->symbol);
|
||||
|
||||
for (entry = 0; entry < pool->next_free_entry; entry++)
|
||||
/* First output the expression in the instruction to the pool. */
|
||||
emit_expr (&(pool->literals[entry]), size); /* .word|.xword */
|
||||
{
|
||||
expressionS * exp = & pool->literals[entry].exp;
|
||||
|
||||
if (exp->X_op == O_big)
|
||||
{
|
||||
/* PR 16688: Restore the global bignum value. */
|
||||
gas_assert (pool->literals[entry].bignum != NULL);
|
||||
memcpy (generic_bignum, pool->literals[entry].bignum,
|
||||
CHARS_PER_LITTLENUM * exp->X_add_number);
|
||||
}
|
||||
|
||||
/* First output the expression in the instruction to the pool. */
|
||||
emit_expr (exp, size); /* .word|.xword */
|
||||
|
||||
if (exp->X_op == O_big)
|
||||
{
|
||||
free (pool->literals[entry].bignum);
|
||||
pool->literals[entry].bignum = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark the pool as empty. */
|
||||
pool->next_free_entry = 0;
|
||||
|
@ -2815,7 +2852,7 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand,
|
|||
if (**str == '\0')
|
||||
return TRUE;
|
||||
|
||||
/* Otherwise, we have a shifted reloc modifier, so rewind to
|
||||
/* Otherwise, we have a shifted reloc modifier, so rewind to
|
||||
recover the variable name and continue parsing for the shifter. */
|
||||
*str = p;
|
||||
return parse_shifter_operand_imm (str, operand, mode);
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2014-03-12 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR gas/16688
|
||||
* gas/aarch64/litpool.s: New test case.
|
||||
* gas/aarch64/litpool.d: Expected disassembly.
|
||||
|
||||
2014-03-05 Alan Modra <amodra@gmail.com>
|
||||
|
||||
Update copyright years.
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#objdump: -d
|
||||
#name: AArch64 Bignums in Literal Pool (PR 16688)
|
||||
# This test is only valid on ELF based ports.
|
||||
#not-target: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
|
||||
|
||||
.*: +file format.*aarch64.*
|
||||
|
||||
Disassembly of section \.text:
|
||||
|
||||
00+00 <.*>:
|
||||
0: 9c000080 ldr q0, 10 <\.text\+0x10>
|
||||
4: 9c0000e1 ldr q1, 20 <\.text\+0x20>
|
||||
8: 9c000142 ldr q2, 30 <\.text\+0x30>
|
||||
c: 9c0001a3 ldr q3, 40 <\.text\+0x40>
|
||||
10: 00000000 .word 0x00000000
|
||||
14: 5a827999 .word 0x5a827999
|
||||
18: 5a827999 .word 0x5a827999
|
||||
1c: 5a827999 .word 0x5a827999
|
||||
20: 6ed9eba1 .word 0x6ed9eba1
|
||||
24: 6ed9eba1 .word 0x6ed9eba1
|
||||
28: 6ed9eba1 .word 0x6ed9eba1
|
||||
2c: 6ed9eba1 .word 0x6ed9eba1
|
||||
30: 11223344 .word 0x11223344
|
||||
34: 8f1bbcdc .word 0x8f1bbcdc
|
||||
38: 8f1bbcdc .word 0x8f1bbcdc
|
||||
3c: 8f1bbcdc .word 0x8f1bbcdc
|
||||
40: ca62c1d6 .word 0xca62c1d6
|
||||
44: ca62c1d6 .word 0xca62c1d6
|
||||
48: ca62c1d6 .word 0xca62c1d6
|
||||
4c: ca62c1d6 .word 0xca62c1d6
|
|
@ -0,0 +1,7 @@
|
|||
# Based on PR 16688 this test checks that bignums are correctly added to the literal pool
|
||||
.text
|
||||
|
||||
ldr q0, =0x5a8279995a8279995a82799900000000
|
||||
ldr q1, =0x6ed9eba16ed9eba16ed9eba16ed9eba1
|
||||
ldr q2, =0x8f1bbcdc8f1bbcdc8f1bbcdc11223344
|
||||
ldr q3, =0xca62c1d6ca62c1d6ca62c1d6ca62c1d6
|
Loading…
Reference in New Issue