diff options
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-ppc.c | 139 |
1 files changed, 103 insertions, 36 deletions
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 6b54f5a..34afc91 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -86,7 +86,11 @@ static int set_target_endian = 0; compensating for #lo being treated as a signed number. */ #define PPC_HIGHESTA(v) PPC_HIGHEST ((v) + 0x8000) -#define SEX16(val) ((((val) & 0xffff) ^ 0x8000) - 0x8000) +#define SEX16(val) (((val) ^ 0x8000) - 0x8000) + +/* For the time being on ppc64, don't report overflow on @h and @ha + applied to constants. */ +#define REPORT_OVERFLOW_HI 0 static bfd_boolean reg_names_p = TARGET_REG_NAMES_P; @@ -1923,6 +1927,8 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p) MAP32 ("bitfld", BFD_RELOC_PPC_EMB_BIT_FLD), MAP32 ("relsda", BFD_RELOC_PPC_EMB_RELSDA), MAP32 ("xgot", BFD_RELOC_PPC_TOC16), + MAP64 ("high", BFD_RELOC_PPC64_ADDR16_HIGH), + MAP64 ("higha", BFD_RELOC_PPC64_ADDR16_HIGHA), MAP64 ("higher", BFD_RELOC_PPC64_HIGHER), MAP64 ("highera", BFD_RELOC_PPC64_HIGHER_S), MAP64 ("highest", BFD_RELOC_PPC64_HIGHEST), @@ -1932,10 +1938,14 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p) MAP64 ("toc@l", BFD_RELOC_PPC64_TOC16_LO), MAP64 ("toc@h", BFD_RELOC_PPC64_TOC16_HI), MAP64 ("toc@ha", BFD_RELOC_PPC64_TOC16_HA), + MAP64 ("dtprel@high", BFD_RELOC_PPC64_DTPREL16_HIGH), + MAP64 ("dtprel@higha", BFD_RELOC_PPC64_DTPREL16_HIGHA), MAP64 ("dtprel@higher", BFD_RELOC_PPC64_DTPREL16_HIGHER), MAP64 ("dtprel@highera", BFD_RELOC_PPC64_DTPREL16_HIGHERA), MAP64 ("dtprel@highest", BFD_RELOC_PPC64_DTPREL16_HIGHEST), MAP64 ("dtprel@highesta", BFD_RELOC_PPC64_DTPREL16_HIGHESTA), + MAP64 ("tprel@high", BFD_RELOC_PPC64_TPREL16_HIGH), + MAP64 ("tprel@higha", BFD_RELOC_PPC64_TPREL16_HIGHA), MAP64 ("tprel@higher", BFD_RELOC_PPC64_TPREL16_HIGHER), MAP64 ("tprel@highera", BFD_RELOC_PPC64_TPREL16_HIGHERA), MAP64 ("tprel@highest", BFD_RELOC_PPC64_TPREL16_HIGHEST), @@ -2810,55 +2820,76 @@ md_assemble (char *str) break; case BFD_RELOC_LO16: - /* X_unsigned is the default, so if the user has done - something which cleared it, we always produce a - signed value. */ - if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED)) - ex.X_add_number &= 0xffff; - else + ex.X_add_number &= 0xffff; + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) ex.X_add_number = SEX16 (ex.X_add_number); break; case BFD_RELOC_HI16: - if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED)) - ex.X_add_number = PPC_HI (ex.X_add_number); - else - ex.X_add_number = SEX16 (PPC_HI (ex.X_add_number)); + if (REPORT_OVERFLOW_HI && ppc_obj64) + { + /* PowerPC64 @h is tested for overflow. */ + ex.X_add_number = (addressT) ex.X_add_number >> 16; + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) + { + addressT sign = (((addressT) -1 >> 16) + 1) >> 1; + ex.X_add_number + = ((addressT) ex.X_add_number ^ sign) - sign; + } + break; + } + /* Fall thru */ + + case BFD_RELOC_PPC64_ADDR16_HIGH: + ex.X_add_number = PPC_HI (ex.X_add_number); + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) + ex.X_add_number = SEX16 (ex.X_add_number); break; case BFD_RELOC_HI16_S: - if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED)) - ex.X_add_number = PPC_HA (ex.X_add_number); - else - ex.X_add_number = SEX16 (PPC_HA (ex.X_add_number)); + if (REPORT_OVERFLOW_HI && ppc_obj64) + { + /* PowerPC64 @ha is tested for overflow. */ + ex.X_add_number + = ((addressT) ex.X_add_number + 0x8000) >> 16; + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) + { + addressT sign = (((addressT) -1 >> 16) + 1) >> 1; + ex.X_add_number + = ((addressT) ex.X_add_number ^ sign) - sign; + } + break; + } + /* Fall thru */ + + case BFD_RELOC_PPC64_ADDR16_HIGHA: + ex.X_add_number = PPC_HA (ex.X_add_number); + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) + ex.X_add_number = SEX16 (ex.X_add_number); break; case BFD_RELOC_PPC64_HIGHER: - if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED)) - ex.X_add_number = PPC_HIGHER (ex.X_add_number); - else - ex.X_add_number = SEX16 (PPC_HIGHER (ex.X_add_number)); + ex.X_add_number = PPC_HIGHER (ex.X_add_number); + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) + ex.X_add_number = SEX16 (ex.X_add_number); break; case BFD_RELOC_PPC64_HIGHER_S: - if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED)) - ex.X_add_number = PPC_HIGHERA (ex.X_add_number); - else - ex.X_add_number = SEX16 (PPC_HIGHERA (ex.X_add_number)); + ex.X_add_number = PPC_HIGHERA (ex.X_add_number); + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) + ex.X_add_number = SEX16 (ex.X_add_number); break; case BFD_RELOC_PPC64_HIGHEST: - if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED)) - ex.X_add_number = PPC_HIGHEST (ex.X_add_number); - else - ex.X_add_number = SEX16 (PPC_HIGHEST (ex.X_add_number)); + ex.X_add_number = PPC_HIGHEST (ex.X_add_number); + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) + ex.X_add_number = SEX16 (ex.X_add_number); break; case BFD_RELOC_PPC64_HIGHEST_S: - if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED)) - ex.X_add_number = PPC_HIGHESTA (ex.X_add_number); - else - ex.X_add_number = SEX16 (PPC_HIGHESTA (ex.X_add_number)); + ex.X_add_number = PPC_HIGHESTA (ex.X_add_number); + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) + ex.X_add_number = SEX16 (ex.X_add_number); break; } #endif /* OBJ_ELF */ @@ -6390,25 +6421,51 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) fieldval = value & 0xffff; sign_extend_16: if (operand != NULL && (operand->flags & PPC_OPERAND_SIGNED) != 0) - fieldval = (fieldval ^ 0x8000) - 0x8000; + fieldval = SEX16 (fieldval); fixP->fx_no_overflow = 1; break; + case BFD_RELOC_HI16: + case BFD_RELOC_HI16_PCREL: #ifdef OBJ_ELF + if (REPORT_OVERFLOW_HI && ppc_obj64) + { + fieldval = value >> 16; + if (operand != NULL && (operand->flags & PPC_OPERAND_SIGNED) != 0) + { + valueT sign = (((valueT) -1 >> 16) + 1) >> 1; + fieldval = ((valueT) fieldval ^ sign) - sign; + } + break; + } + /* Fall thru */ + case BFD_RELOC_PPC_VLE_HI16A: case BFD_RELOC_PPC_VLE_HI16D: + case BFD_RELOC_PPC64_ADDR16_HIGH: #endif - case BFD_RELOC_HI16: - case BFD_RELOC_HI16_PCREL: fieldval = PPC_HI (value); goto sign_extend_16; + case BFD_RELOC_HI16_S: + case BFD_RELOC_HI16_S_PCREL: #ifdef OBJ_ELF + if (REPORT_OVERFLOW_HI && ppc_obj64) + { + fieldval = (value + 0x8000) >> 16; + if (operand != NULL && (operand->flags & PPC_OPERAND_SIGNED) != 0) + { + valueT sign = (((valueT) -1 >> 16) + 1) >> 1; + fieldval = ((valueT) fieldval ^ sign) - sign; + } + break; + } + /* Fall thru */ + case BFD_RELOC_PPC_VLE_HA16A: case BFD_RELOC_PPC_VLE_HA16D: + case BFD_RELOC_PPC64_ADDR16_HIGHA: #endif - case BFD_RELOC_HI16_S: - case BFD_RELOC_HI16_S_PCREL: fieldval = PPC_HA (value); goto sign_extend_16; @@ -6471,10 +6528,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_PPC_GOT_DTPREL16_HA: case BFD_RELOC_PPC64_TPREL16_DS: case BFD_RELOC_PPC64_TPREL16_LO_DS: + case BFD_RELOC_PPC64_TPREL16_HIGH: + case BFD_RELOC_PPC64_TPREL16_HIGHA: case BFD_RELOC_PPC64_TPREL16_HIGHER: case BFD_RELOC_PPC64_TPREL16_HIGHERA: case BFD_RELOC_PPC64_TPREL16_HIGHEST: case BFD_RELOC_PPC64_TPREL16_HIGHESTA: + case BFD_RELOC_PPC64_DTPREL16_HIGH: + case BFD_RELOC_PPC64_DTPREL16_HIGHA: case BFD_RELOC_PPC64_DTPREL16_DS: case BFD_RELOC_PPC64_DTPREL16_LO_DS: case BFD_RELOC_PPC64_DTPREL16_HIGHER: @@ -6660,6 +6721,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_PPC64_HIGHER_S: case BFD_RELOC_PPC64_HIGHEST: case BFD_RELOC_PPC64_HIGHEST_S: + case BFD_RELOC_PPC64_ADDR16_HIGH: + case BFD_RELOC_PPC64_ADDR16_HIGHA: break; case BFD_RELOC_PPC_DTPMOD: @@ -6736,10 +6799,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_PPC64_TOC16_LO: case BFD_RELOC_PPC64_TOC16_HI: case BFD_RELOC_PPC64_TOC16_HA: + case BFD_RELOC_PPC64_DTPREL16_HIGH: + case BFD_RELOC_PPC64_DTPREL16_HIGHA: case BFD_RELOC_PPC64_DTPREL16_HIGHER: case BFD_RELOC_PPC64_DTPREL16_HIGHERA: case BFD_RELOC_PPC64_DTPREL16_HIGHEST: case BFD_RELOC_PPC64_DTPREL16_HIGHESTA: + case BFD_RELOC_PPC64_TPREL16_HIGH: + case BFD_RELOC_PPC64_TPREL16_HIGHA: case BFD_RELOC_PPC64_TPREL16_HIGHER: case BFD_RELOC_PPC64_TPREL16_HIGHERA: case BFD_RELOC_PPC64_TPREL16_HIGHEST: |