diff options
author | Maciej W. Rozycki <macro@imgtec.com> | 2016-07-19 16:19:19 +0100 |
---|---|---|
committer | Maciej W. Rozycki <macro@imgtec.com> | 2016-07-19 16:22:53 +0100 |
commit | a6ebf6169a1bd14724b9ac49990089542396f576 (patch) | |
tree | 4b6f6a0e2fe8f81127178b480df5c7c9591eb8bd /bfd/elfxx-mips.c | |
parent | 9d862524f6ae9703fe8e264dd4785756d358570a (diff) | |
download | gdb-a6ebf6169a1bd14724b9ac49990089542396f576.zip gdb-a6ebf6169a1bd14724b9ac49990089542396f576.tar.gz gdb-a6ebf6169a1bd14724b9ac49990089542396f576.tar.bz2 |
MIPS: Convert cross-mode BAL to JALX
Convert cross-mode regular MIPS and microMIPS BAL instructions to JALX,
similarly to how JAL instructions are converted.
bfd/
* elfxx-mips.c (mips_elf_perform_relocation): Convert cross-mode
BAL to JALX.
(_bfd_mips_elf_relocate_section) <bfd_reloc_outofrange>: Add a
corresponding error message.
gas/
* config/tc-mips.c (mips_force_relocation, mips_fix_adjustable):
Adjust comments for BAL to JALX linker conversion.
(fix_bad_cross_mode_branch_p): Accept cross-mode BAL.
* testsuite/gas/mips/unaligned-branch-1.l: Update error messages
expected.
* testsuite/gas/mips/unaligned-branch-micromips-1.l: Likewise.
* testsuite/gas/mips/branch-local-4.d: New test.
* testsuite/gas/mips/branch-local-n32-4.d: New test.
* testsuite/gas/mips/branch-local-n64-4.d: New test.
* testsuite/gas/mips/branch-addend.d: New test.
* testsuite/gas/mips/branch-addend-n32.d: New test.
* testsuite/gas/mips/branch-addend-n64.d: New test.
* testsuite/gas/mips/branch-local-4.s: New test source.
* testsuite/gas/mips/branch-addend.s: New test source.
* testsuite/gas/mips/mips.exp: Run the new tests.
ld/
* testsuite/ld-mips-elf/unaligned-branch-2.d: Update error
messages expected.
* testsuite/ld-mips-elf/unaligned-branch-r6-1.d: Likewise.
* testsuite/ld-mips-elf/unaligned-branch-mips16.d: Likewise.
* testsuite/ld-mips-elf/unaligned-branch-micromips.d: Likewise.
* testsuite/ld-mips-elf/bal-jalx-addend.d: New test.
* testsuite/ld-mips-elf/bal-jalx-local.d: New test.
* testsuite/ld-mips-elf/bal-jalx-pic.d: New test.
* testsuite/ld-mips-elf/bal-jalx-addend-n32.d: New test.
* testsuite/ld-mips-elf/bal-jalx-local-n32.d: New test.
* testsuite/ld-mips-elf/bal-jalx-pic-n32.d: New test.
* testsuite/ld-mips-elf/bal-jalx-addend-n64.d: New test.
* testsuite/ld-mips-elf/bal-jalx-local-n64.d: New test.
* testsuite/ld-mips-elf/bal-jalx-pic-n64.d: New test.
* testsuite/ld-mips-elf/unaligned-jalx-2.d: New test.
* testsuite/ld-mips-elf/unaligned-jalx-3.d: New test.
* testsuite/ld-mips-elf/unaligned-jalx-addend-2.d: New test.
* testsuite/ld-mips-elf/unaligned-jalx-addend-3.d: New test.
* testsuite/ld-mips-elf/unaligned-jalx-2.s: New test source.
* testsuite/ld-mips-elf/unaligned-jalx-3.s: New test source.
* testsuite/ld-mips-elf/unaligned-jalx-addend-2.s: New test
source.
* testsuite/ld-mips-elf/unaligned-jalx-addend-3.s: New test
source.
* testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
Diffstat (limited to 'bfd/elfxx-mips.c')
-rw-r--r-- | bfd/elfxx-mips.c | 55 |
1 files changed, 49 insertions, 6 deletions
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index fa99c9d..5dcbcf9 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -6339,7 +6339,7 @@ mips_elf_perform_relocation (struct bfd_link_info *info, /* Set the field. */ x |= (value & howto->dst_mask); - /* Detect incorrect JALX usage. If required, turn JAL into JALX. */ + /* Detect incorrect JALX usage. If required, turn JAL or BAL into JALX. */ if (!cross_mode_jump_p && jal_reloc_p (r_type)) { bfd_vma opcode = x >> 26; @@ -6393,10 +6393,50 @@ mips_elf_perform_relocation (struct bfd_link_info *info, } else if (cross_mode_jump_p && b_reloc_p (r_type)) { - info->callbacks->einfo - (_("%X%H: Unsupported branch between ISA modes\n"), - input_bfd, input_section, relocation->r_offset); - return TRUE; + bfd_boolean ok = FALSE; + bfd_vma opcode = x >> 16; + bfd_vma jalx_opcode = 0; + bfd_vma addr; + bfd_vma dest; + + if (r_type == R_MICROMIPS_PC16_S1) + { + ok = opcode == 0x4060; + jalx_opcode = 0x3c; + value <<= 1; + } + else if (r_type == R_MIPS_PC16 || r_type == R_MIPS_GNU_REL16_S2) + { + ok = opcode == 0x411; + jalx_opcode = 0x1d; + value <<= 2; + } + + if (bfd_link_pic (info) || !ok) + { + info->callbacks->einfo + (_("%X%H: Unsupported branch between ISA modes\n"), + input_bfd, input_section, relocation->r_offset); + return TRUE; + } + + addr = (input_section->output_section->vma + + input_section->output_offset + + relocation->r_offset + + 4); + dest = addr + (((value & 0x3ffff) ^ 0x20000) - 0x20000); + + if ((addr >> 28) << 28 != (dest >> 28) << 28) + { + info->callbacks->einfo + (_("%X%H: Cannot convert branch between ISA modes " + "to JALX: relocation out of range\n"), + input_bfd, input_section, relocation->r_offset); + return TRUE; + } + + /* Make this the JALX opcode. */ + x = ((dest >> 2) & 0x3ffffff) | jalx_opcode << 26; } /* Try converting JAL to BAL and J(AL)R to B(AL), if the target is in @@ -10390,7 +10430,10 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, ? _("Jump to a non-word-aligned address") : _("Jump to a non-instruction-aligned address"))); else if (b_reloc_p (howto->type)) - msg = _("Branch to a non-instruction-aligned address"); + msg = (cross_mode_jump_p + ? _("Cannot convert a branch to JALX " + "for a non-word-aligned address") + : _("Branch to a non-instruction-aligned address")); else if (aligned_pcrel_reloc_p (howto->type)) msg = _("PC-relative load from unaligned address"); if (msg) |