diff -Nrup a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c --- a/gas/config/tc-ppc.c 2015-05-07 09:21:42.738374151 -0600 +++ b/gas/config/tc-ppc.c 2015-05-07 14:58:51.607894208 -0600 @@ -3143,103 +3143,6 @@ md_assemble (char *str) break; } } - - /* For the absolute forms of branches, convert the PC - relative form back into the absolute. */ - if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) - { - switch (reloc) - { - case BFD_RELOC_PPC_B26: - reloc = BFD_RELOC_PPC_BA26; - break; - case BFD_RELOC_PPC_B16: - reloc = BFD_RELOC_PPC_BA16; - break; - case BFD_RELOC_PPC_B16_BRTAKEN: - reloc = BFD_RELOC_PPC_BA16_BRTAKEN; - break; - case BFD_RELOC_PPC_B16_BRNTAKEN: - reloc = BFD_RELOC_PPC_BA16_BRNTAKEN; - break; - default: - break; - } - } - - switch (reloc) - { - case BFD_RELOC_PPC_TOC16: - toc_reloc_types |= has_small_toc_reloc; - break; - case BFD_RELOC_PPC64_TOC16_LO: - case BFD_RELOC_PPC64_TOC16_HI: - case BFD_RELOC_PPC64_TOC16_HA: - toc_reloc_types |= has_large_toc_reloc; - break; - default: - break; - } - - if ((operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0) - { - switch (reloc) - { - case BFD_RELOC_16: - reloc = BFD_RELOC_PPC64_ADDR16_DS; - break; - case BFD_RELOC_LO16: - reloc = BFD_RELOC_PPC64_ADDR16_LO_DS; - break; - case BFD_RELOC_16_GOTOFF: - reloc = BFD_RELOC_PPC64_GOT16_DS; - break; - case BFD_RELOC_LO16_GOTOFF: - reloc = BFD_RELOC_PPC64_GOT16_LO_DS; - break; - case BFD_RELOC_LO16_PLTOFF: - reloc = BFD_RELOC_PPC64_PLT16_LO_DS; - break; - case BFD_RELOC_16_BASEREL: - reloc = BFD_RELOC_PPC64_SECTOFF_DS; - break; - case BFD_RELOC_LO16_BASEREL: - reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS; - break; - case BFD_RELOC_PPC_TOC16: - reloc = BFD_RELOC_PPC64_TOC16_DS; - break; - case BFD_RELOC_PPC64_TOC16_LO: - reloc = BFD_RELOC_PPC64_TOC16_LO_DS; - break; - case BFD_RELOC_PPC64_PLTGOT16: - reloc = BFD_RELOC_PPC64_PLTGOT16_DS; - break; - case BFD_RELOC_PPC64_PLTGOT16_LO: - reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS; - break; - case BFD_RELOC_PPC_DTPREL16: - reloc = BFD_RELOC_PPC64_DTPREL16_DS; - break; - case BFD_RELOC_PPC_DTPREL16_LO: - reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS; - break; - case BFD_RELOC_PPC_TPREL16: - reloc = BFD_RELOC_PPC64_TPREL16_DS; - break; - case BFD_RELOC_PPC_TPREL16_LO: - reloc = BFD_RELOC_PPC64_TPREL16_LO_DS; - break; - case BFD_RELOC_PPC_GOT_DTPREL16: - case BFD_RELOC_PPC_GOT_DTPREL16_LO: - case BFD_RELOC_PPC_GOT_TPREL16: - case BFD_RELOC_PPC_GOT_TPREL16_LO: - break; - default: - as_bad (_("unsupported relocation for DS offset field")); - break; - } - } } #endif /* OBJ_ELF */ @@ -3248,11 +3151,13 @@ md_assemble (char *str) /* Determine a BFD reloc value based on the operand information. We are only prepared to turn a few of the operands into relocs. */ - else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0 + else if ((operand->flags & (PPC_OPERAND_RELATIVE + | PPC_OPERAND_ABSOLUTE)) != 0 && operand->bitm == 0x3fffffc && operand->shift == 0) reloc = BFD_RELOC_PPC_B26; - else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0 + else if ((operand->flags & (PPC_OPERAND_RELATIVE + | PPC_OPERAND_ABSOLUTE)) != 0 && operand->bitm == 0xfffc && operand->shift == 0) reloc = BFD_RELOC_PPC_B16; @@ -3268,40 +3173,126 @@ md_assemble (char *str) && operand->bitm == 0x1fffffe && operand->shift == 0) reloc = BFD_RELOC_PPC_VLE_REL24; - else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0 - && operand->bitm == 0x3fffffc - && operand->shift == 0) - reloc = BFD_RELOC_PPC_BA26; - else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0 - && operand->bitm == 0xfffc - && operand->shift == 0) - reloc = BFD_RELOC_PPC_BA16; -#if defined (OBJ_XCOFF) || defined (OBJ_ELF) - else if ((operand->flags & PPC_OPERAND_PARENS) != 0 + else if ((operand->flags & PPC_OPERAND_NEGATIVE) == 0 && (operand->bitm & 0xfff0) == 0xfff0 && operand->shift == 0) { + reloc = BFD_RELOC_16; +#if defined OBJ_XCOFF || defined OBJ_ELF /* Note: the symbol may be not yet defined. */ - if (ppc_is_toc_sym (ex.X_add_symbol)) + if ((operand->flags & PPC_OPERAND_PARENS) != 0 + && ppc_is_toc_sym (ex.X_add_symbol)) { reloc = BFD_RELOC_PPC_TOC16; #ifdef OBJ_ELF - if (ppc_obj64 - && (operand->flags & PPC_OPERAND_DS) != 0) - reloc = BFD_RELOC_PPC64_TOC16_DS; + as_warn (_("assuming %s on symbol"), + ppc_obj64 ? "@toc" : "@xgot"); #endif } - else +#endif + } + + /* For the absolute forms of branches, convert the PC + relative form back into the absolute. */ + if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) + { + switch (reloc) { - reloc = BFD_RELOC_16; + case BFD_RELOC_PPC_B26: + reloc = BFD_RELOC_PPC_BA26; + break; + case BFD_RELOC_PPC_B16: + reloc = BFD_RELOC_PPC_BA16; + break; #ifdef OBJ_ELF - if (ppc_obj64 - && (operand->flags & PPC_OPERAND_DS) != 0) - reloc = BFD_RELOC_PPC64_ADDR16_DS; + case BFD_RELOC_PPC_B16_BRTAKEN: + reloc = BFD_RELOC_PPC_BA16_BRTAKEN; + break; + case BFD_RELOC_PPC_B16_BRNTAKEN: + reloc = BFD_RELOC_PPC_BA16_BRNTAKEN; + break; #endif + default: + break; + } + } + +#ifdef OBJ_ELF + switch (reloc) + { + case BFD_RELOC_PPC_TOC16: + toc_reloc_types |= has_small_toc_reloc; + break; + case BFD_RELOC_PPC64_TOC16_LO: + case BFD_RELOC_PPC64_TOC16_HI: + case BFD_RELOC_PPC64_TOC16_HA: + toc_reloc_types |= has_large_toc_reloc; + break; + default: + break; + } + + if (ppc_obj64 + && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0) + { + switch (reloc) + { + case BFD_RELOC_16: + reloc = BFD_RELOC_PPC64_ADDR16_DS; + break; + case BFD_RELOC_LO16: + reloc = BFD_RELOC_PPC64_ADDR16_LO_DS; + break; + case BFD_RELOC_16_GOTOFF: + reloc = BFD_RELOC_PPC64_GOT16_DS; + break; + case BFD_RELOC_LO16_GOTOFF: + reloc = BFD_RELOC_PPC64_GOT16_LO_DS; + break; + case BFD_RELOC_LO16_PLTOFF: + reloc = BFD_RELOC_PPC64_PLT16_LO_DS; + break; + case BFD_RELOC_16_BASEREL: + reloc = BFD_RELOC_PPC64_SECTOFF_DS; + break; + case BFD_RELOC_LO16_BASEREL: + reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS; + break; + case BFD_RELOC_PPC_TOC16: + reloc = BFD_RELOC_PPC64_TOC16_DS; + break; + case BFD_RELOC_PPC64_TOC16_LO: + reloc = BFD_RELOC_PPC64_TOC16_LO_DS; + break; + case BFD_RELOC_PPC64_PLTGOT16: + reloc = BFD_RELOC_PPC64_PLTGOT16_DS; + break; + case BFD_RELOC_PPC64_PLTGOT16_LO: + reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS; + break; + case BFD_RELOC_PPC_DTPREL16: + reloc = BFD_RELOC_PPC64_DTPREL16_DS; + break; + case BFD_RELOC_PPC_DTPREL16_LO: + reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS; + break; + case BFD_RELOC_PPC_TPREL16: + reloc = BFD_RELOC_PPC64_TPREL16_DS; + break; + case BFD_RELOC_PPC_TPREL16_LO: + reloc = BFD_RELOC_PPC64_TPREL16_LO_DS; + break; + case BFD_RELOC_PPC_GOT_DTPREL16: + case BFD_RELOC_PPC_GOT_DTPREL16_LO: + case BFD_RELOC_PPC_GOT_TPREL16: + case BFD_RELOC_PPC_GOT_TPREL16_LO: + break; + default: + as_bad (_("unsupported relocation for DS offset field")); + break; } } -#endif /* defined (OBJ_XCOFF) || defined (OBJ_ELF) */ +#endif /* We need to generate a fixup for this expression. */ if (fc >= MAX_INSN_FIXUPS) diff -Nrup a/ld/testsuite/ld-powerpc/elfv2exe.d b/ld/testsuite/ld-powerpc/elfv2exe.d --- a/ld/testsuite/ld-powerpc/elfv2exe.d 2015-05-07 09:21:42.727374395 -0600 +++ b/ld/testsuite/ld-powerpc/elfv2exe.d 2015-05-07 09:26:49.048581753 -0600 @@ -21,7 +21,7 @@ Disassembly of section \.text: 0+100000e0 <_start>: .*: (02 10 40 3c|3c 40 10 02) lis r2,4098 -.*: (40 81 42 38|38 42 81 40) addi r2,r2,-32448 +.*: (38 81 42 38|38 42 81 38) addi r2,r2,-32456 .*: (a6 02 08 7c|7c 08 02 a6) mflr r0 .*: (e1 ff 21 f8|f8 21 ff e1) stdu r1,-32\(r1\) .*: (30 00 01 f8|f8 01 00 30) std r0,48\(r1\) diff -Nrup a/ld/testsuite/ld-powerpc/elfv2so.d b/ld/testsuite/ld-powerpc/elfv2so.d --- a/ld/testsuite/ld-powerpc/elfv2so.d 2015-05-07 09:21:42.688375260 -0600 +++ b/ld/testsuite/ld-powerpc/elfv2so.d 2015-05-07 09:26:49.048581753 -0600 @@ -7,33 +7,33 @@ Disassembly of section \.text: -0+300 <.*\.plt_call\.f4>: +0+320 <.*\.plt_call\.f4>: .*: (18 00 41 f8|f8 41 00 18) std r2,24\(r1\) .*: (38 80 82 e9|e9 82 80 38) ld r12,-32712\(r2\) .*: (a6 03 89 7d|7d 89 03 a6) mtctr r12 .*: (20 04 80 4e|4e 80 04 20) bctr -0+310 <.*\.plt_call\.f3>: +0+330 <.*\.plt_call\.f3>: .*: (18 00 41 f8|f8 41 00 18) std r2,24\(r1\) .*: (28 80 82 e9|e9 82 80 28) ld r12,-32728\(r2\) .*: (a6 03 89 7d|7d 89 03 a6) mtctr r12 .*: (20 04 80 4e|4e 80 04 20) bctr -0+320 <.*\.plt_call\.f2>: +0+340 <.*\.plt_call\.f2>: .*: (18 00 41 f8|f8 41 00 18) std r2,24\(r1\) .*: (30 80 82 e9|e9 82 80 30) ld r12,-32720\(r2\) .*: (a6 03 89 7d|7d 89 03 a6) mtctr r12 .*: (20 04 80 4e|4e 80 04 20) bctr -0+330 <.*\.plt_call\.f1>: +0+350 <.*\.plt_call\.f1>: .*: (18 00 41 f8|f8 41 00 18) std r2,24\(r1\) .*: (40 80 82 e9|e9 82 80 40) ld r12,-32704\(r2\) .*: (a6 03 89 7d|7d 89 03 a6) mtctr r12 .*: (20 04 80 4e|4e 80 04 20) bctr -0+340 : +0+360 : .*: (02 00 4c 3c|3c 4c 00 02) addis r2,r12,2 -.*: (e0 81 42 38|38 42 81 e0) addi r2,r2,-32288 +.*: (d8 81 42 38|38 42 81 d8) addi r2,r2,-32296 .*: (a6 02 08 7c|7c 08 02 a6) mflr r0 .*: (e1 ff 21 f8|f8 21 ff e1) stdu r1,-32\(r1\) .*: (30 00 01 f8|f8 01 00 30) std r0,48\(r1\) @@ -50,10 +50,10 @@ Disassembly of section \.text: .*: (20 00 21 38|38 21 00 20) addi r1,r1,32 .*: (a6 03 08 7c|7c 08 03 a6) mtlr r0 .*: (20 00 80 4e|4e 80 00 20) blr -.*: (a0 01 01 00|00 00 00 00) .* -.*: (00 00 00 00|00 01 01 a0) .* +.*: (98 01 01 00|00 00 00 00) .* +.*: (00 00 00 00|00 01 01 98) .* -0+390 <__glink_PLTresolve>: +0+3b0 <__glink_PLTresolve>: .*: (a6 02 08 7c|7c 08 02 a6) mflr r0 .*: (05 00 9f 42|42 9f 00 05) bcl .* .*: (a6 02 68 7d|7d 68 02 a6) mflr r11