PowerPC @l, @h and @ha warnings, plus VLE e_li
This patch started off just adding the warnings in tc-ppc.c about incorrect usage of @l, @h and @ha in instructions that don't have 16-bit D-form fields. That unfortunately showed up three warnings in ld/testsuite/ld-powerpc/vle-multiseg.s on instructions like e_li r3, IV_table@l+0x00 which was being assembled to 8: 70 60 00 00 e_li r3,0 a: R_PPC_ADDR16_LO IV_table The ADDR16_LO reloc is of course completely bogus on e_li, which has a split 20-bit signed integer field in bits 0x1f7fff, the low 11 bit in 0x7ff, the next 5 bits in 0x1f0000, and the high 4 bits in 0x7800. Applying an ADDR16_LO reloc to the instruction potentially changes the e_li instruction to e_add2i., e_add2is, e_cmp16i, e_mull2i, e_cmpl16i, e_cmph16i, e_cmphl16i, e_or2i, e_and2i., e_or2is, e_lis, e_and2is, or some invalid encodings. Now there is a relocation that suits e_li, R_PPC_VLE_ADDR20, which was added 2017-09-05 but I can't see code in gas to generate the relocation. In any case, VLE_ADDR20 probably doesn't have the correct semantics for @l since ideally you'd want an @l to pair with @h or @ha to generate a 32-bit constant. Thus @l should only produce a 16-bit value, I think. So we need some more relocations to handle e_li it seems, or as I do in this patch, modify the behaviour of existing relocations when applied to e_li instructions. include/ * opcode/ppc.h (E_OPCODE_MASK, E_LI_MASK, E_LI_INSN): Define. bfd/ * elf32-ppc.c (ppc_elf_howto_raw <R_PPC_VLE_ADDR20>): Correct mask and shift value. (ppc_elf_vle_split16): Use E_OPCODE_MASK. Handle e_li specially. gas/ * config/tc-ppc.c (md_assemble): Adjust relocs for VLE before TLS tweaks. Handle e_li. Warn on unexpected operand field for lo16/hi16/ha16 relocs.
This commit is contained in:
parent
23ebf37881
commit
bb6bf75e7a
6 changed files with 97 additions and 41 deletions
|
@ -1,3 +1,10 @@
|
|||
2018-12-06 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf32-ppc.c (ppc_elf_howto_raw <R_PPC_VLE_ADDR20>): Correct
|
||||
mask and shift value.
|
||||
(ppc_elf_vle_split16): Use E_OPCODE_MASK. Handle e_li
|
||||
specially.
|
||||
|
||||
2018-12-05 Sam Tebbs <sam.tebbs@arm.com>
|
||||
|
||||
* elf-eh-frame.c (_bfd_elf_parse_eh_frame): Add check for 'B'.
|
||||
|
|
|
@ -649,8 +649,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
|
|||
ppc_elf_unhandled_reloc),
|
||||
|
||||
/* e_li split20 format. */
|
||||
HOW (R_PPC_VLE_ADDR20, 2, 20, 0x1f07ff, 16, FALSE, dont,
|
||||
bfd_elf_generic_reloc),
|
||||
HOW (R_PPC_VLE_ADDR20, 2, 20, 0x1f7fff, 0, FALSE, dont,
|
||||
ppc_elf_unhandled_reloc),
|
||||
|
||||
HOW (R_PPC_IRELATIVE, 2, 32, 0xffffffff, 0, FALSE, dont,
|
||||
ppc_elf_unhandled_reloc),
|
||||
|
@ -3886,10 +3886,10 @@ ppc_elf_vle_split16 (bfd *input_bfd,
|
|||
split16_format_type split16_format,
|
||||
bfd_boolean fixup)
|
||||
{
|
||||
unsigned int insn, opcode, top5;
|
||||
unsigned int insn, opcode;
|
||||
|
||||
insn = bfd_get_32 (input_bfd, loc);
|
||||
opcode = insn & 0xfc00f800;
|
||||
opcode = insn & E_OPCODE_MASK;
|
||||
if (opcode == E_OR2I_INSN
|
||||
|| opcode == E_AND2I_DOT_INSN
|
||||
|| opcode == E_OR2IS_INSN
|
||||
|
@ -3926,10 +3926,22 @@ ppc_elf_vle_split16 (bfd *input_bfd,
|
|||
input_bfd, input_section, offset, opcode);
|
||||
}
|
||||
}
|
||||
top5 = value & 0xf800;
|
||||
top5 = top5 << (split16_format == split16a_type ? 5 : 10);
|
||||
insn &= (split16_format == split16a_type ? ~0x1f07ff : ~0x3e007ff);
|
||||
insn |= top5;
|
||||
if (split16_format == split16a_type)
|
||||
{
|
||||
insn &= ~((0xf800 << 5) | 0x7ff);
|
||||
insn |= (value & 0xf800) << 5;
|
||||
if ((insn & E_LI_MASK) == E_LI_INSN)
|
||||
{
|
||||
/* Hack for e_li. Extend sign. */
|
||||
insn &= ~(0xf0000 >> 5);
|
||||
insn |= (-(value & 0x8000) & 0xf0000) >> 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
insn &= ~((0xf800 << 10) | 0x7ff);
|
||||
insn |= (value & 0xf800) << 10;
|
||||
}
|
||||
insn |= value & 0x7ff;
|
||||
bfd_put_32 (input_bfd, insn, loc);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2018-12-06 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* config/tc-ppc.c (md_assemble): Adjust relocs for VLE before
|
||||
TLS tweaks. Handle e_li. Warn on unexpected operand field
|
||||
for lo16/hi16/ha16 relocs.
|
||||
|
||||
2018-12-06 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
* config/tc-riscv.h (FAKE_LABEL_NAME): Define as
|
||||
|
|
|
@ -3433,39 +3433,6 @@ md_assemble (char *str)
|
|||
|
||||
if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_NONE)
|
||||
{
|
||||
/* Some TLS tweaks. */
|
||||
switch (reloc)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_TLS:
|
||||
if (!_bfd_elf_ppc_at_tls_transform (opcode->opcode, 0))
|
||||
as_bad (_("@tls may not be used with \"%s\" operands"),
|
||||
opcode->name);
|
||||
else if (operand->shift != 11)
|
||||
as_bad (_("@tls may only be used in last operand"));
|
||||
else
|
||||
insn = ppc_insert_operand (insn, operand,
|
||||
ppc_obj64 ? 13 : 2,
|
||||
ppc_cpu, (char *) NULL, 0);
|
||||
break;
|
||||
|
||||
/* We'll only use the 32 (or 64) bit form of these relocations
|
||||
in constants. Instructions get the 16 bit form. */
|
||||
case BFD_RELOC_PPC_DTPREL:
|
||||
reloc = BFD_RELOC_PPC_DTPREL16;
|
||||
break;
|
||||
case BFD_RELOC_PPC_TPREL:
|
||||
reloc = BFD_RELOC_PPC_TPREL16;
|
||||
break;
|
||||
}
|
||||
|
||||
/* addpcis. */
|
||||
if (opcode->opcode == (19 << 26) + (2 << 1)
|
||||
&& reloc == BFD_RELOC_HI16_S)
|
||||
reloc = BFD_RELOC_PPC_16DX_HA;
|
||||
|
||||
/* If VLE-mode convert LO/HI/HA relocations. */
|
||||
if (opcode->flags & PPC_OPCODE_VLE)
|
||||
{
|
||||
|
@ -3474,6 +3441,7 @@ md_assemble (char *str)
|
|||
int use_a_reloc = (tmp_insn == E_OR2I_INSN
|
||||
|| tmp_insn == E_AND2I_DOT_INSN
|
||||
|| tmp_insn == E_OR2IS_INSN
|
||||
|| tmp_insn == E_LI_INSN
|
||||
|| tmp_insn == E_LIS_INSN
|
||||
|| tmp_insn == E_AND2IS_DOT_INSN);
|
||||
|
||||
|
@ -3532,6 +3500,60 @@ md_assemble (char *str)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* TLS and other tweaks. */
|
||||
switch (reloc)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_TLS:
|
||||
if (!_bfd_elf_ppc_at_tls_transform (opcode->opcode, 0))
|
||||
as_bad (_("@tls may not be used with \"%s\" operands"),
|
||||
opcode->name);
|
||||
else if (operand->shift != 11)
|
||||
as_bad (_("@tls may only be used in last operand"));
|
||||
else
|
||||
insn = ppc_insert_operand (insn, operand,
|
||||
ppc_obj64 ? 13 : 2,
|
||||
ppc_cpu, (char *) NULL, 0);
|
||||
break;
|
||||
|
||||
/* We'll only use the 32 (or 64) bit form of these relocations
|
||||
in constants. Instructions get the 16 bit form. */
|
||||
case BFD_RELOC_PPC_DTPREL:
|
||||
reloc = BFD_RELOC_PPC_DTPREL16;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_TPREL:
|
||||
reloc = BFD_RELOC_PPC_TPREL16;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_LO16:
|
||||
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)
|
||||
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))
|
||||
/* addpcis. */
|
||||
reloc = BFD_RELOC_PPC_16DX_HA;
|
||||
else if (operand->bitm != 0xffff
|
||||
|| operand->shift != 0
|
||||
|| (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
|
||||
as_warn (_("%s unsupported on this instruction"), "@ha");
|
||||
}
|
||||
}
|
||||
#endif /* OBJ_ELF */
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2018-12-06 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* opcode/ppc.h (E_OPCODE_MASK, E_LI_MASK, E_LI_INSN): Define.
|
||||
|
||||
2018-12-06 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
* dis-asm.h (riscv_symbol_is_valid): Declare.
|
||||
|
|
|
@ -476,6 +476,8 @@ ppc_optional_operand_value (const struct powerpc_operand *operand,
|
|||
}
|
||||
|
||||
/* PowerPC VLE insns. */
|
||||
#define E_OPCODE_MASK 0xfc00f800
|
||||
|
||||
/* Form I16L, uses 16A relocs. */
|
||||
#define E_OR2I_INSN 0x7000C000
|
||||
#define E_AND2I_DOT_INSN 0x7000C800
|
||||
|
@ -492,6 +494,9 @@ ppc_optional_operand_value (const struct powerpc_operand *operand,
|
|||
#define E_CMPH16I_INSN 0x7000B000
|
||||
#define E_CMPHL16I_INSN 0x7000B800
|
||||
|
||||
#define E_LI_INSN 0x70000000
|
||||
#define E_LI_MASK 0xfc008000
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue