diff options
author | Maciej W. Rozycki <macro@imgtec.com> | 2016-06-28 01:23:36 +0100 |
---|---|---|
committer | Maciej W. Rozycki <macro@imgtec.com> | 2016-06-28 01:29:56 +0100 |
commit | c9775dde32773c57d4eb5dfb4265eda9cb8adbe8 (patch) | |
tree | 59735930ba2df8d7a5e885c7d388b45e341ecd04 /gas/config/tc-mips.c | |
parent | bac13b9c13a0169aea400335776310b1f1ff2d16 (diff) | |
download | binutils-c9775dde32773c57d4eb5dfb4265eda9cb8adbe8.zip binutils-c9775dde32773c57d4eb5dfb4265eda9cb8adbe8.tar.gz binutils-c9775dde32773c57d4eb5dfb4265eda9cb8adbe8.tar.bz2 |
MIPS16: Add R_MIPS16_PC16_S1 branch relocation support
For R_MIPS16_PC16_S1 the calculation is `(sign_extend(A) + S - P) >> 1'
and the usual MIPS16 bit shuffling applies to relocated field handling,
as per the encoding of the branch target in the extended form of the
MIPS16 B, BEQZ, BNEZ, BTEQZ and BTNEZ instructions.
include/
* elf/mips.h (R_MIPS16_PC16_S1): New relocation.
bfd/
* elf32-mips.c (elf_mips16_howto_table_rel): Add
R_MIPS16_PC16_S1.
(mips16_reloc_map): Likewise.
* elf64-mips.c (mips16_elf64_howto_table_rel): Likewise.
(mips16_elf64_howto_table_rela): Likewise.
(mips16_reloc_map): Likewise.
* elfn32-mips.c (elf_mips16_howto_table_rel): Likewise.
(elf_mips16_howto_table_rela): Likewise.
(mips16_reloc_map): Likewise.
* elfxx-mips.c (mips16_branch_reloc_p): New function.
(mips16_reloc_p): Handle R_MIPS16_PC16_S1.
(b_reloc_p): Likewise.
(mips_elf_calculate_relocation): Likewise.
(_bfd_mips_elf_check_relocs): Likewise.
* reloc.c (BFD_RELOC_MIPS16_16_PCREL_S1): New relocation.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-mips.c (mips16_reloc_p): Handle
BFD_RELOC_MIPS16_16_PCREL_S1.
(b_reloc_p): Likewise.
(limited_pcrel_reloc_p): Likewise.
(md_pcrel_from): Likewise.
(md_apply_fix): Likewise.
(tc_gen_reloc): Likewise.
(md_convert_frag): Likewise.
(mips_fix_adjustable): Update comment.
* testsuite/gas/mips/mips16-branch-reloc-2.d: Remove error
output, add dump patterns.
* testsuite/gas/mips/mips16-branch-reloc-3.d: Remove error
output, add dump patterns.
* testsuite/gas/mips/mips16-branch-addend-2.d: Remove error
output, add dump patterns.
* testsuite/gas/mips/mips16-branch-addend-3.d: Remove error
output, add dump patterns.
* testsuite/gas/mips/mips16-branch-absolute.d: Remove error
output, add dump patterns.
* testsuite/gas/mips/mips16-branch-reloc-2.l: Remove file.
* testsuite/gas/mips/mips16-branch-reloc-3.l: Remove file.
* testsuite/gas/mips/mips16-branch-addend-2.l: Remove file.
* testsuite/gas/mips/mips16-branch-addend-3.l: Remove file.
* testsuite/gas/mips/mips16-branch-absolute.l: Remove file.
* testsuite/gas/mips/mips16-branch-addend-2.s: Add padding.
* testsuite/gas/mips/branch-weak.s: Adjust alignment, avoid
implicit instruction padding, avoid MIPS16 JR->JRC conversion.
* testsuite/gas/mips/branch-weak-6.d: New test.
* testsuite/gas/mips/branch-weak-7.d: New test.
* testsuite/gas/mips/mips.exp: Run the new tests.
ld/
* testsuite/ld-mips-elf/mips16-branch-2.d: New test.
* testsuite/ld-mips-elf/mips16-branch-3.d: New test.
* testsuite/ld-mips-elf/mips16-branch-addend-2.d: New test.
* testsuite/ld-mips-elf/mips16-branch-addend-3.d: New test.
* testsuite/ld-mips-elf/mips16-branch.s: New test source.
* testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
Diffstat (limited to 'gas/config/tc-mips.c')
-rw-r--r-- | gas/config/tc-mips.c | 54 |
1 files changed, 47 insertions, 7 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index ab2ea0c..092e7b4 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -4060,6 +4060,7 @@ mips16_reloc_p (bfd_reloc_code_real_type reloc) case BFD_RELOC_MIPS16_HI16_S: case BFD_RELOC_MIPS16_HI16: case BFD_RELOC_MIPS16_LO16: + case BFD_RELOC_MIPS16_16_PCREL_S1: return TRUE; default: @@ -4114,6 +4115,7 @@ b_reloc_p (bfd_reloc_code_real_type reloc) return (reloc == BFD_RELOC_MIPS_26_PCREL_S2 || reloc == BFD_RELOC_MIPS_21_PCREL_S2 || reloc == BFD_RELOC_16_PCREL_S2 + || reloc == BFD_RELOC_MIPS16_16_PCREL_S1 || reloc == BFD_RELOC_MICROMIPS_16_PCREL_S1 || reloc == BFD_RELOC_MICROMIPS_10_PCREL_S1 || reloc == BFD_RELOC_MICROMIPS_7_PCREL_S1); @@ -4162,6 +4164,7 @@ limited_pcrel_reloc_p (bfd_reloc_code_real_type reloc) switch (reloc) { case BFD_RELOC_16_PCREL_S2: + case BFD_RELOC_MIPS16_16_PCREL_S1: case BFD_RELOC_MICROMIPS_7_PCREL_S1: case BFD_RELOC_MICROMIPS_10_PCREL_S1: case BFD_RELOC_MICROMIPS_16_PCREL_S1: @@ -14628,6 +14631,7 @@ md_pcrel_from (fixS *fixP) case BFD_RELOC_MICROMIPS_16_PCREL_S1: case BFD_RELOC_MICROMIPS_JMP: + case BFD_RELOC_MIPS16_16_PCREL_S1: case BFD_RELOC_16_PCREL_S2: case BFD_RELOC_MIPS_21_PCREL_S2: case BFD_RELOC_MIPS_26_PCREL_S2: @@ -14852,6 +14856,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) switch (fixP->fx_r_type) { case BFD_RELOC_16_PCREL_S2: + case BFD_RELOC_MIPS16_16_PCREL_S1: case BFD_RELOC_MICROMIPS_7_PCREL_S1: case BFD_RELOC_MICROMIPS_10_PCREL_S1: case BFD_RELOC_MICROMIPS_16_PCREL_S1: @@ -15184,6 +15189,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) } break; + case BFD_RELOC_MIPS16_16_PCREL_S1: case BFD_RELOC_MICROMIPS_7_PCREL_S1: case BFD_RELOC_MICROMIPS_10_PCREL_S1: case BFD_RELOC_MICROMIPS_16_PCREL_S1: @@ -17216,11 +17222,11 @@ mips_fix_adjustable (fixS *fixp) 5. We cannot reduce jump relocations (R_MIPS_26, R_MIPS16_26 or R_MICROMIPS_26_S1) or branch relocations (R_MIPS_PC26_S2, - R_MIPS_PC21_S2, R_MIPS_PC16, R_MICROMIPS_PC16_S1, - R_MICROMIPS_PC10_S1 or R_MICROMIPS_PC7_S1) against MIPS16 or - microMIPS symbols because we need to keep the MIPS16 or - microMIPS symbol for the purpose of mode mismatch detection - and JAL to JALX instruction conversion in the linker. + R_MIPS_PC21_S2, R_MIPS_PC16, R_MIPS16_PC16_S1, + R_MICROMIPS_PC16_S1, R_MICROMIPS_PC10_S1 or R_MICROMIPS_PC7_S1) + against MIPS16 or microMIPS symbols because we need to keep the + MIPS16 or microMIPS symbol for the purpose of mode mismatch + detection and JAL to JALX instruction conversion in the linker. For simplicity, we deal with (3)-(4) by not reducing _any_ relocation against a MIPS16 symbol. We deal with (5) by additionally leaving @@ -17263,6 +17269,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) if (fixp->fx_pcrel) { gas_assert (fixp->fx_r_type == BFD_RELOC_16_PCREL_S2 + || fixp->fx_r_type == BFD_RELOC_MIPS16_16_PCREL_S1 || fixp->fx_r_type == BFD_RELOC_MICROMIPS_7_PCREL_S1 || fixp->fx_r_type == BFD_RELOC_MICROMIPS_10_PCREL_S1 || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1 @@ -17870,8 +17877,41 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) || (operand->root.type == OP_PCREL ? asec != symsec : !bfd_is_abs_section (symsec))) - as_bad_where (fragp->fr_file, fragp->fr_line, - _("unsupported relocation")); + { + bfd_reloc_code_real_type reloc = BFD_RELOC_NONE; + expressionS exp; + fixS *fixp; + + switch (type) + { + case 'p': + case 'q': + reloc = BFD_RELOC_MIPS16_16_PCREL_S1; + break; + default: + as_bad_where (fragp->fr_file, fragp->fr_line, + _("unsupported relocation")); + break; + } + if (reloc != BFD_RELOC_NONE) + { + gas_assert (ext); + + exp.X_op = O_symbol; + exp.X_add_symbol = fragp->fr_symbol; + exp.X_add_number = fragp->fr_offset; + + fixp = fix_new_exp (fragp, buf - fragp->fr_literal, 2, &exp, + TRUE, reloc); + + fixp->fx_file = fragp->fr_file; + fixp->fx_line = fragp->fr_line; + + /* These relocations can have an addend that won't fit + in 2 octets. */ + fixp->fx_no_overflow = 1; + } + } else mips16_immed (fragp->fr_file, fragp->fr_line, type, BFD_RELOC_UNUSED, val, user_length, &insn); |