diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 5 | ||||
-rw-r--r-- | bfd/elfxx-mips.c | 6 |
2 files changed, 10 insertions, 1 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4882260..f52e75d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2017-08-30 Maciej W. Rozycki <macro@imgtec.com> + + * elfxx-mips.c (mips_elf_perform_relocation): Correct microMIPS + branch offset interpretation. + 2017-08-30 H.J. Lu <hongjiu.lu@intel.com> PR binutils/22032 diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index fddf68c..6a4d3e1 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -6414,6 +6414,7 @@ mips_elf_perform_relocation (struct bfd_link_info *info, bfd_boolean ok = FALSE; bfd_vma opcode = x >> 16; bfd_vma jalx_opcode = 0; + bfd_vma sign_bit = 0; bfd_vma addr; bfd_vma dest; @@ -6421,12 +6422,14 @@ mips_elf_perform_relocation (struct bfd_link_info *info, { ok = opcode == 0x4060; jalx_opcode = 0x3c; + sign_bit = 0x10000; value <<= 1; } else if (r_type == R_MIPS_PC16 || r_type == R_MIPS_GNU_REL16_S2) { ok = opcode == 0x411; jalx_opcode = 0x1d; + sign_bit = 0x20000; value <<= 2; } @@ -6436,7 +6439,8 @@ mips_elf_perform_relocation (struct bfd_link_info *info, + input_section->output_offset + relocation->r_offset + 4); - dest = addr + (((value & 0x3ffff) ^ 0x20000) - 0x20000); + dest = (addr + + (((value & ((sign_bit << 1) - 1)) ^ sign_bit) - sign_bit)); if ((addr >> 28) << 28 != (dest >> 28) << 28) { |