aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2018-08-29 14:22:34 +0930
committerAlan Modra <amodra@gmail.com>2019-05-24 10:27:49 +0930
commit5663e321848545857a690f30a780187e3366bd2d (patch)
treec9b730b7593a41e9927039f6fa277610b468d260 /gas/config
parent8acf14351c818d956babe50e61711740f378c941 (diff)
downloadgdb-5663e321848545857a690f30a780187e3366bd2d.zip
gdb-5663e321848545857a690f30a780187e3366bd2d.tar.gz
gdb-5663e321848545857a690f30a780187e3366bd2d.tar.bz2
PowerPC relocations for prefix insns
include/ * elf/ppc64.h (R_PPC64_PLTSEQ_NOTOC, R_PPC64_PLTCALL_NOTOC), (R_PPC64_PCREL_OPT, R_PPC64_D34, R_PPC64_D34_LO, R_PPC64_D34_HI30), (R_PPC64_D34_HA30, R_PPC64_PCREL34, R_PPC64_GOT_PCREL34), (R_PPC64_PLT_PCREL34, R_PPC64_PLT_PCREL34_NOTOC), (R_PPC64_ADDR16_HIGHER34, R_PPC64_ADDR16_HIGHERA34), (R_PPC64_ADDR16_HIGHEST34, R_PPC64_ADDR16_HIGHESTA34), (R_PPC64_REL16_HIGHER34, R_PPC64_REL16_HIGHERA34), (R_PPC64_REL16_HIGHEST34, R_PPC64_REL16_HIGHESTA34), (R_PPC64_D28, R_PPC64_PCREL28): Define. bfd/ * reloc.c (BFD_RELOC_PPC64_D34, BFD_RELOC_PPC64_D34_LO), (BFD_RELOC_PPC64_D34_HI30, BFD_RELOC_PPC64_D34_HA30), (BFD_RELOC_PPC64_PCREL34, BFD_RELOC_PPC64_GOT_PCREL34), (BFD_RELOC_PPC64_PLT_PCREL34), (BFD_RELOC_PPC64_ADDR16_HIGHER34, BFD_RELOC_PPC64_ADDR16_HIGHERA34), (BFD_RELOC_PPC64_ADDR16_HIGHEST34, BFD_RELOC_PPC64_ADDR16_HIGHESTA34), (BFD_RELOC_PPC64_REL16_HIGHER34, BFD_RELOC_PPC64_REL16_HIGHERA34), (BFD_RELOC_PPC64_REL16_HIGHEST34, BFD_RELOC_PPC64_REL16_HIGHESTA34), (BFD_RELOC_PPC64_D28, BFD_RELOC_PPC64_PCREL28): New reloc enums. * elf64-ppc.c (PNOP): Define. (ppc64_elf_howto_raw): Add reloc howtos for new relocations. (ppc64_elf_reloc_type_lookup): Translate new bfd reloc numbers. (ppc64_elf_ha_reloc): Adjust addend for highera34 and highesta34 relocs. (ppc64_elf_prefix_reloc): New function. (struct ppc_link_hash_table): Add notoc_plt. (is_branch_reloc): Add R_PPC64_PLTCALL_NOTOC. (is_plt_seq_reloc): Add R_PPC64_PLT_PCREL34, R_PPC64_PLT_PCREL34_NOTOC, and R_PPC64_PLTSEQ_NOTOC. (ppc64_elf_check_relocs): Handle pcrel got and plt relocs. Set has_pltcall for section on seeing R_PPC64_PLTCALL_NOTOC. Handle possible need for dynamic relocs on non-pcrel powerxx relocs. (dec_dynrel_count): Handle non-pcrel powerxx relocs. (ppc64_elf_inline_plt): Handle R_PPC64_PLTCALL_NOTOC. (toc_adjusting_stub_needed): Likewise. (ppc64_elf_tls_optimize): Handle R_PPC64_PLTSEQ_NOTOC. (ppc64_elf_relocate_section): Handle new powerxx relocs. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. gas/ * config/tc-ppc.c (ppc_elf_suffix): Support @pcrel, @got@pcrel, @plt@pcrel, @higher34, @highera34, @highest34, and @highesta34. (fixup_size): Handle new powerxx relocs. (md_assemble): Warn for @pcrel on non-prefix insns. Accept @l, @h and @ha on prefix insns, and infer reloc without any @ suffix. Translate powerxx relocs to suit DQ and DS field instructions. Include operand tests as well as opcode test to translate BFD_RELOC_HI16_S to BFD_RELOC_PPC_16DX_HA. (ppc_fix_adjustable): Return false for pcrel GOT and PLT relocs. (md_apply_fix): Handle new powerxx relocs. * config/tc-ppc.h (TC_FORCE_RELOCATION_SUB_LOCAL): Accept BFD_RELOC_PPC64_ADDR16_HIGHER34, BFD_RELOC_PPC64_ADDR16_HIGHERA34, BFD_RELOC_PPC64_ADDR16_HIGHEST34, BFD_RELOC_PPC64_ADDR16_HIGHESTA34, BFD_RELOC_PPC64_D34, and BFD_RELOC_PPC64_D28. * testsuite/gas/ppc/prefix-reloc.d, * testsuite/gas/ppc/prefix-reloc.s: New test. * testsuite/gas/ppc/ppc.exp: Run it.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-ppc.c164
-rw-r--r--gas/config/tc-ppc.h8
2 files changed, 149 insertions, 23 deletions
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index 4026c72..64ff149 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -2151,6 +2151,13 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p)
MAP64 ("tprel@highest", BFD_RELOC_PPC64_TPREL16_HIGHEST),
MAP64 ("tprel@highesta", BFD_RELOC_PPC64_TPREL16_HIGHESTA),
MAP64 ("notoc", BFD_RELOC_PPC64_REL24_NOTOC),
+ MAP64 ("pcrel", BFD_RELOC_PPC64_PCREL34),
+ MAP64 ("got@pcrel", BFD_RELOC_PPC64_GOT_PCREL34),
+ MAP64 ("plt@pcrel", BFD_RELOC_PPC64_PLT_PCREL34),
+ MAP64 ("higher34", BFD_RELOC_PPC64_ADDR16_HIGHER34),
+ MAP64 ("highera34", BFD_RELOC_PPC64_ADDR16_HIGHERA34),
+ MAP64 ("highest34", BFD_RELOC_PPC64_ADDR16_HIGHEST34),
+ MAP64 ("highesta34", BFD_RELOC_PPC64_ADDR16_HIGHESTA34),
{ (char *) 0, 0, 0, 0, BFD_RELOC_NONE }
};
@@ -2931,6 +2938,10 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
case BFD_RELOC_PPC64_ADDR16_DS:
case BFD_RELOC_PPC64_ADDR16_HIGH:
case BFD_RELOC_PPC64_ADDR16_HIGHA:
+ case BFD_RELOC_PPC64_ADDR16_HIGHER34:
+ case BFD_RELOC_PPC64_ADDR16_HIGHERA34:
+ case BFD_RELOC_PPC64_ADDR16_HIGHEST34:
+ case BFD_RELOC_PPC64_ADDR16_HIGHESTA34:
case BFD_RELOC_PPC64_ADDR16_LO_DS:
case BFD_RELOC_PPC64_DTPREL16_DS:
case BFD_RELOC_PPC64_DTPREL16_HIGH:
@@ -3018,9 +3029,13 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
case BFD_RELOC_PPC64_REL16_HIGH:
case BFD_RELOC_PPC64_REL16_HIGHA:
case BFD_RELOC_PPC64_REL16_HIGHER:
+ case BFD_RELOC_PPC64_REL16_HIGHER34:
case BFD_RELOC_PPC64_REL16_HIGHERA:
+ case BFD_RELOC_PPC64_REL16_HIGHERA34:
case BFD_RELOC_PPC64_REL16_HIGHEST:
+ case BFD_RELOC_PPC64_REL16_HIGHEST34:
case BFD_RELOC_PPC64_REL16_HIGHESTA:
+ case BFD_RELOC_PPC64_REL16_HIGHESTA34:
#ifdef OBJ_XCOFF
case BFD_RELOC_PPC_B16:
#endif
@@ -3100,12 +3115,21 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
case BFD_RELOC_64:
case BFD_RELOC_64_PLTOFF:
case BFD_RELOC_PPC64_ADDR64_LOCAL:
+ case BFD_RELOC_PPC64_D28:
+ case BFD_RELOC_PPC64_D34:
+ case BFD_RELOC_PPC64_D34_LO:
+ case BFD_RELOC_PPC64_D34_HI30:
+ case BFD_RELOC_PPC64_D34_HA30:
case BFD_RELOC_PPC64_TOC:
size = 8;
break;
case BFD_RELOC_64_PCREL:
case BFD_RELOC_64_PLT_PCREL:
+ case BFD_RELOC_PPC64_GOT_PCREL34:
+ case BFD_RELOC_PPC64_PCREL28:
+ case BFD_RELOC_PPC64_PCREL34:
+ case BFD_RELOC_PPC64_PLT_PCREL34:
size = 8;
pcrel = TRUE;
break;
@@ -3665,24 +3689,47 @@ md_assemble (char *str)
reloc = BFD_RELOC_PPC_TPREL16;
break;
- case BFD_RELOC_LO16:
- if ((operand->bitm | 0xf) != 0xffff
- || operand->shift != 0
+ case BFD_RELOC_PPC64_PCREL34:
+ if (operand->bitm == 0xfffffffULL)
+ {
+ reloc = BFD_RELOC_PPC64_PCREL28;
+ break;
+ }
+ /* Fall through. */
+ case BFD_RELOC_PPC64_GOT_PCREL34:
+ case BFD_RELOC_PPC64_PLT_PCREL34:
+ if (operand->bitm != 0x3ffffffffULL
|| (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
+ as_warn (_("%s unsupported on this instruction"), "@pcrel");
+ break;
+
+ case BFD_RELOC_LO16:
+ if (operand->bitm == 0x3ffffffffULL
+ && (operand->flags & PPC_OPERAND_NEGATIVE) == 0)
+ reloc = BFD_RELOC_PPC64_D34_LO;
+ else if ((operand->bitm | 0xf) != 0xffff
+ || operand->shift != 0
+ || (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
as_warn (_("%s unsupported on this instruction"), "@l");
break;
case BFD_RELOC_HI16:
- if (operand->bitm != 0xffff
- || operand->shift != 0
- || (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
+ if (operand->bitm == 0x3ffffffffULL
+ && (operand->flags & PPC_OPERAND_NEGATIVE) == 0)
+ reloc = BFD_RELOC_PPC64_D34_HI30;
+ else if (operand->bitm != 0xffff
+ || operand->shift != 0
+ || (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
as_warn (_("%s unsupported on this instruction"), "@h");
break;
case BFD_RELOC_HI16_S:
- if (operand->bitm == 0xffff
- && operand->shift == (int) PPC_OPSHIFT_INV
- && opcode->opcode == (19 << 26) + (2 << 1))
+ if (operand->bitm == 0x3ffffffffULL
+ && (operand->flags & PPC_OPERAND_NEGATIVE) == 0)
+ reloc = BFD_RELOC_PPC64_D34_HA30;
+ else if (operand->bitm == 0xffff
+ && operand->shift == (int) PPC_OPSHIFT_INV
+ && opcode->opcode == (19 << 26) + (2 << 1))
/* addpcis. */
reloc = BFD_RELOC_PPC_16DX_HA;
else if (operand->bitm != 0xffff
@@ -3738,6 +3785,10 @@ md_assemble (char *str)
}
#endif
}
+ else if (operand->bitm == 0x3ffffffffULL)
+ reloc = BFD_RELOC_PPC64_D34;
+ else if (operand->bitm == 0xfffffffULL)
+ reloc = BFD_RELOC_PPC64_D28;
/* For the absolute forms of branches, convert the PC
relative form back into the absolute. */
@@ -3787,53 +3838,69 @@ md_assemble (char *str)
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;
@@ -6903,6 +6970,7 @@ ppc_fix_adjustable (fixS *fix)
&& fix->fx_r_type != BFD_RELOC_PPC64_GOT16_LO_DS
&& fix->fx_r_type != BFD_RELOC_16_GOT_PCREL
&& fix->fx_r_type != BFD_RELOC_32_GOTOFF
+ && fix->fx_r_type != BFD_RELOC_PPC64_GOT_PCREL34
&& fix->fx_r_type != BFD_RELOC_24_PLT_PCREL
&& fix->fx_r_type != BFD_RELOC_32_PLTOFF
&& fix->fx_r_type != BFD_RELOC_32_PLT_PCREL
@@ -6912,6 +6980,7 @@ ppc_fix_adjustable (fixS *fix)
&& fix->fx_r_type != BFD_RELOC_64_PLTOFF
&& fix->fx_r_type != BFD_RELOC_64_PLT_PCREL
&& fix->fx_r_type != BFD_RELOC_PPC64_PLT16_LO_DS
+ && fix->fx_r_type != BFD_RELOC_PPC64_PLT_PCREL34
&& fix->fx_r_type != BFD_RELOC_PPC64_PLTGOT16
&& fix->fx_r_type != BFD_RELOC_PPC64_PLTGOT16_LO
&& fix->fx_r_type != BFD_RELOC_PPC64_PLTGOT16_HI
@@ -7120,10 +7189,34 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHESTA;
break;
+ case BFD_RELOC_PPC64_ADDR16_HIGHER34:
+ fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHER34;
+ break;
+
+ case BFD_RELOC_PPC64_ADDR16_HIGHERA34:
+ fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHERA34;
+ break;
+
+ case BFD_RELOC_PPC64_ADDR16_HIGHEST34:
+ fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHEST34;
+ break;
+
+ case BFD_RELOC_PPC64_ADDR16_HIGHESTA34:
+ fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHESTA34;
+ break;
+
case BFD_RELOC_PPC_16DX_HA:
fixP->fx_r_type = BFD_RELOC_PPC_REL16DX_HA;
break;
+ case BFD_RELOC_PPC64_D34:
+ fixP->fx_r_type = BFD_RELOC_PPC64_PCREL34;
+ break;
+
+ case BFD_RELOC_PPC64_D28:
+ fixP->fx_r_type = BFD_RELOC_PPC64_PCREL28;
+ break;
+
default:
break;
}
@@ -7370,6 +7463,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
case BFD_RELOC_PPC_VLE_SDAREL_HI16D:
case BFD_RELOC_PPC_VLE_SDAREL_HA16A:
case BFD_RELOC_PPC_VLE_SDAREL_HA16D:
+ case BFD_RELOC_PPC64_GOT_PCREL34:
+ case BFD_RELOC_PPC64_PLT_PCREL34:
gas_assert (fixP->fx_addsy != NULL);
/* Fallthru */
@@ -7421,9 +7516,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
#else
#define APPLY_RELOC 1
#endif
+ /* We need to call the insert function even when fieldval is
+ zero if the insert function would translate that zero to a
+ bit pattern other than all zeros. */
if ((fieldval != 0 && APPLY_RELOC) || operand->insert != NULL)
{
- unsigned long insn;
+ uint64_t insn;
unsigned char *where;
/* Fetch the instruction, insert the fully resolved operand
@@ -7431,34 +7529,56 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
where = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
if (target_big_endian)
{
- if (fixP->fx_size == 4)
- insn = bfd_getb32 (where);
- else
+ if (fixP->fx_size < 4)
insn = bfd_getb16 (where);
+ else
+ {
+ insn = bfd_getb32 (where);
+ if (fixP->fx_size > 4)
+ insn = insn << 32 | bfd_getb32 (where + 4);
+ }
}
else
{
- if (fixP->fx_size == 4)
- insn = bfd_getl32 (where);
- else
+ if (fixP->fx_size < 4)
insn = bfd_getl16 (where);
+ else
+ {
+ insn = bfd_getl32 (where);
+ if (fixP->fx_size > 4)
+ insn = insn << 32 | bfd_getl32 (where + 4);
+ }
}
insn = ppc_insert_operand (insn, operand, fieldval,
fixP->tc_fix_data.ppc_cpu,
fixP->fx_file, fixP->fx_line);
if (target_big_endian)
{
- if (fixP->fx_size == 4)
- bfd_putb32 (insn, where);
- else
+ if (fixP->fx_size < 4)
bfd_putb16 (insn, where);
+ else
+ {
+ if (fixP->fx_size > 4)
+ {
+ bfd_putb32 (insn, where + 4);
+ insn >>= 32;
+ }
+ bfd_putb32 (insn, where);
+ }
}
else
{
- if (fixP->fx_size == 4)
- bfd_putl32 (insn, where);
- else
+ if (fixP->fx_size < 4)
bfd_putl16 (insn, where);
+ else
+ {
+ if (fixP->fx_size > 4)
+ {
+ bfd_putl32 (insn, where + 4);
+ insn >>= 32;
+ }
+ bfd_putl32 (insn, where);
+ }
}
}
diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h
index 08e381e..9de5c08 100644
--- a/gas/config/tc-ppc.h
+++ b/gas/config/tc-ppc.h
@@ -273,7 +273,13 @@ extern int ppc_force_relocation (struct fix *);
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHER_S \
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHEST \
|| (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHEST_S \
- || (FIX)->fx_r_type == BFD_RELOC_PPC_16DX_HA))
+ || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHER34 \
+ || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHERA34 \
+ || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHEST34 \
+ || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHESTA34 \
+ || (FIX)->fx_r_type == BFD_RELOC_PPC_16DX_HA \
+ || (FIX)->fx_r_type == BFD_RELOC_PPC64_D34 \
+ || (FIX)->fx_r_type == BFD_RELOC_PPC64_D28))
#endif
#define TC_VALIDATE_FIX_SUB(FIX, SEG) 0