diff options
author | Alan Modra <amodra@gmail.com> | 2021-04-12 09:02:46 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2021-04-12 11:57:03 +0930 |
commit | 32d715691aa037f2838b41fa257c2e239d67c134 (patch) | |
tree | 15950d786cf30650203914068f191717acacae46 /gas/expr.c | |
parent | fc304b889106f6d1bd720e969b95615992bf1961 (diff) | |
download | binutils-32d715691aa037f2838b41fa257c2e239d67c134.zip binutils-32d715691aa037f2838b41fa257c2e239d67c134.tar.gz binutils-32d715691aa037f2838b41fa257c2e239d67c134.tar.bz2 |
Power10 bignum operands
When built on a 32-bit host without --enable-64-bit-bfd, powerpc-linux
and other 32-bit powerpc targeted binutils fail to assemble some
power10 prefixed instructions with 34-bit fields. A typical error
seen when running the testsuite is
.../gas/testsuite/gas/ppc/prefix-pcrel.s:10: Error: bignum invalid
In practice this doesn't matter for addresses: 32-bit programs don't
need or use the top 2 bits of a d34 field when calculating addresses.
However it may matter when loading or adding 64-bit constants with
paddi. A power10 processor in 32-bit mode still has 64-bit wide GPRs.
So this patch enables limited support for O_big PowerPC operands, and
corrects sign extension of 32-bit constants using X_extrabit.
* config/tc-ppc.c (insn_validate): Use uint64_t for operand values.
(md_assemble): Likewise. Handle bignum operands.
(ppc_elf_suffix): Handle O_big. Remove unnecessary input_line_pointer
check.
* expr.c: Delete unnecessary forward declarations.
(generic_bignum_to_int32): Return uint32_t.
(generic_bignum_to_int64): Return uint64_t. Compile always.
(operand): Twiddle X_extrabit for unary '~'. Set X_unsigned and
clear X_extrabit for unary '!'.
* expr.h (generic_bignum_to_int32): Declare.
(generic_bignum_to_int64): Declare.
* testsuite/gas/ppc/prefix-pcrel.s,
* testsuite/gas/ppc/prefix-pcrel.d: Add more instructions.
Diffstat (limited to 'gas/expr.c')
-rw-r--r-- | gas/expr.c | 50 |
1 files changed, 21 insertions, 29 deletions
@@ -35,16 +35,7 @@ bool literal_prefix_dollar_hex = false; -static void floating_constant (expressionS * expressionP); -static valueT generic_bignum_to_int32 (void); -#ifdef BFD64 -static valueT generic_bignum_to_int64 (void); -#endif -static void integer_constant (int radix, expressionS * expressionP); -static void mri_char_constant (expressionS *); static void clean_up_expression (expressionS * expressionP); -static segT operand (expressionS *, enum expr_mode); -static operatorT operatorf (int *); /* We keep a mapping of expression symbols to file positions, so that we can provide better error messages. */ @@ -218,31 +209,25 @@ floating_constant (expressionS *expressionP) expressionP->X_add_number = -1; } -static valueT +uint32_t generic_bignum_to_int32 (void) { - valueT number = - ((((valueT) generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS) - | ((valueT) generic_bignum[0] & LITTLENUM_MASK)); - number &= 0xffffffff; - return number; + return ((((uint32_t) generic_bignum[1] & LITTLENUM_MASK) + << LITTLENUM_NUMBER_OF_BITS) + | ((uint32_t) generic_bignum[0] & LITTLENUM_MASK)); } -#ifdef BFD64 -static valueT +uint64_t generic_bignum_to_int64 (void) { - valueT number = - ((((((((valueT) generic_bignum[3] & LITTLENUM_MASK) - << LITTLENUM_NUMBER_OF_BITS) - | ((valueT) generic_bignum[2] & LITTLENUM_MASK)) - << LITTLENUM_NUMBER_OF_BITS) - | ((valueT) generic_bignum[1] & LITTLENUM_MASK)) - << LITTLENUM_NUMBER_OF_BITS) - | ((valueT) generic_bignum[0] & LITTLENUM_MASK)); - return number; + return ((((((((uint64_t) generic_bignum[3] & LITTLENUM_MASK) + << LITTLENUM_NUMBER_OF_BITS) + | ((uint64_t) generic_bignum[2] & LITTLENUM_MASK)) + << LITTLENUM_NUMBER_OF_BITS) + | ((uint64_t) generic_bignum[1] & LITTLENUM_MASK)) + << LITTLENUM_NUMBER_OF_BITS) + | ((uint64_t) generic_bignum[0] & LITTLENUM_MASK)); } -#endif static void integer_constant (int radix, expressionS *expressionP) @@ -1031,9 +1016,16 @@ operand (expressionS *expressionP, enum expr_mode mode) expressionP->X_extrabit ^= 1; } else if (c == '~' || c == '"') - expressionP->X_add_number = ~ expressionP->X_add_number; + { + expressionP->X_add_number = ~ expressionP->X_add_number; + expressionP->X_extrabit ^= 1; + } else if (c == '!') - expressionP->X_add_number = ! expressionP->X_add_number; + { + expressionP->X_add_number = ! expressionP->X_add_number; + expressionP->X_unsigned = 1; + expressionP->X_extrabit = 0; + } } else if (expressionP->X_op == O_big && expressionP->X_add_number <= 0 |