diff options
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 28 | ||||
-rw-r--r-- | gas/ChangeLog | 6 | ||||
-rw-r--r-- | gas/config/tc-ppc.c | 88 | ||||
-rw-r--r-- | include/ChangeLog | 4 | ||||
-rw-r--r-- | include/opcode/ppc.h | 5 |
6 files changed, 97 insertions, 41 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index de468a4..8a37271 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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'. diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index c31e26e..6b6043a 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -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); } diff --git a/gas/ChangeLog b/gas/ChangeLog index a4e0767..72ae3bc 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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 diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index a8eda5d..cebbd42 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -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 */ diff --git a/include/ChangeLog b/include/ChangeLog index b3fd56b..3b7c66d 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -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. diff --git a/include/opcode/ppc.h b/include/opcode/ppc.h index 2b7f51e..c7262f1 100644 --- a/include/opcode/ppc.h +++ b/include/opcode/ppc.h @@ -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 |