From c62e1cc30f77e49b15d48d4d32c7f6c1e6827163 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 23 May 2002 12:37:57 +0000 Subject: For the Thumb BLX reloc round the relocation up rather than down. --- bfd/ChangeLog | 6 ++++++ bfd/coff-arm.c | 28 +++++++++++++++------------- bfd/elf32-arm.h | 21 +++++++++------------ gas/ChangeLog | 5 +++++ gas/config/tc-arm.c | 24 +++++++++++------------- 5 files changed, 46 insertions(+), 38 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 25af58b..0f2d311 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2002-05-23 Nick Clifton + + * elf32-arm.h (elf32_arm_final_link_relocate): For the Thumb + BLX reloc round the relocation up rather than down. + * coff-arm.c (coff_arm_relocate_section): Likewise. + 2002-05-21 H.J. Lu (hjl@gnu.org) * linker.c (_bfd_generic_link_add_one_symbol): Allow multiple diff --git a/bfd/coff-arm.c b/bfd/coff-arm.c index 1619e67..5e7f907 100644 --- a/bfd/coff-arm.c +++ b/bfd/coff-arm.c @@ -1701,21 +1701,23 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section, || signed_check < reloc_signed_min) overflow = true; - /* For the BLX(1) instruction remove bit 0 of the adjusted offset. - Bit 0 can only be set if the upper insn is at a half-word boundary, - since the destination address, an ARM instruction, must always be - on a word boundary. The semantics of the BLX (1) instruction, - however, are that bit 0 in the offset must always be 0, and the - corresponding bit 1 in the target address will be set from bit - 1 of the source address. */ - if ((x & 0x18000000) == 0x08000000) - relocation &= ~0x2; - - /* Put the relocation into the correct bits. */ + /* Put the relocation into the correct bits. + For a BLX instruction, make sure that the relocation is rounded up + to a word boundary. This follows the semantics of the instruction + which specifies that bit 1 of the target address will come from bit + 1 of the base address. */ if (bfd_big_endian (input_bfd)) - relocation = (((relocation & 0xffe) >> 1) | ((relocation << 4) & 0x07ff0000)); + { + if ((x & 0x1800) == 0x0800 && (relocation & 0x02)) + relocation += 2; + relocation = (((relocation & 0xffe) >> 1) | ((relocation << 4) & 0x07ff0000)); + } else - relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff)); + { + if ((x & 0x18000000) == 0x08000000 && (relocation & 0x02)) + relocation += 2; + relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff)); + } /* Add the relocation to the correct bits of X. */ x = ((x & ~howto->dst_mask) | relocation); diff --git a/bfd/elf32-arm.h b/bfd/elf32-arm.h index 91ea63b..8b9bf07 100644 --- a/bfd/elf32-arm.h +++ b/bfd/elf32-arm.h @@ -1471,22 +1471,19 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, if (signed_check > reloc_signed_max || signed_check < reloc_signed_min) overflow = true; - /* Put RELOCATION back into the insn. */ - upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff); - lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff); - #ifndef OLD_ARM_ABI if (r_type == R_ARM_THM_XPC22 && ((lower_insn & 0x1800) == 0x0800)) - /* Remove bit zero of the adjusted offset. Bit zero can only be - set if the upper insn is at a half-word boundary, since the - destination address, an ARM instruction, must always be on a - word boundary. The semantics of the BLX (1) instruction, however, - are that bit zero in the offset must always be zero, and the - corresponding bit one in the target address will be set from bit - one of the source address. */ - lower_insn &= ~1; + /* For a BLX instruction, make sure that the relocation is rounded up + to a word boundary. This follows the semantics of the instruction + which specifies that bit 1 of the target address will come from bit + 1 of the base address. */ + relocation = (relocation + 2) & ~ 3; #endif + /* Put RELOCATION back into the insn. */ + upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff); + lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff); + /* Put the relocated value back in the object file: */ bfd_put_16 (input_bfd, upper_insn, hit_data); bfd_put_16 (input_bfd, lower_insn, hit_data + 2); diff --git a/gas/ChangeLog b/gas/ChangeLog index 3970519..9d8b183 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,10 @@ 2002-05-23 Nick Clifton + * config/tc-arm.c (md_apply_fix3): For the Thumb BLX reloc + round the relocation up rather than down. + +2002-05-23 Nick Clifton + * config/obj-coff.c (obj_coff_section): Silently ignore an 'a' flag. * doc/as.texinfo: Document that the COFF version of .section diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index b76ee21..39f1b65 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -2227,7 +2227,7 @@ symbol_locate (symbolP, name, segment, valu, frag) S_SET_SEGMENT (symbolP, segment); S_SET_VALUE (symbolP, valu); - symbol_clear_list_pointers(symbolP); + symbol_clear_list_pointers (symbolP); symbol_set_frag (symbolP, frag); @@ -6963,7 +6963,7 @@ vfp_sp_reg_list (str, pos) /* Sanity check -- should have raised a parse error above. */ if (count == 0 || count > 32) - abort(); + abort (); /* Final test -- the registers must be consecutive. */ while (count--) @@ -7076,7 +7076,7 @@ vfp_dp_reg_list (str) /* Sanity check -- should have raised a parse error above. */ if (count == 0 || count > 16) - abort(); + abort (); /* Final test -- the registers must be consecutive. */ while (count--) @@ -7093,7 +7093,7 @@ vfp_dp_reg_list (str) } static void -vfp_sp_ldstm(str, ldstm_type) +vfp_sp_ldstm (str, ldstm_type) char *str; enum vfp_ldstm_type ldstm_type; { @@ -7130,7 +7130,7 @@ vfp_sp_ldstm(str, ldstm_type) } static void -vfp_dp_ldstm(str, ldstm_type) +vfp_dp_ldstm (str, ldstm_type) char *str; enum vfp_ldstm_type ldstm_type; { @@ -9939,6 +9939,7 @@ md_apply_fix3 (fixP, valP, seg) value = fixP->fx_offset; #endif value += diff; + if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff)) as_bad_where (fixP->fx_file, fixP->fx_line, _("branch with link out of range")); @@ -9946,14 +9947,11 @@ md_apply_fix3 (fixP, valP, seg) newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12); newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1); if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX) - /* Remove bit zero of the adjusted offset. Bit zero can only be - set if the upper insn is at a half-word boundary, since the - destination address, an ARM instruction, must always be on a - word boundary. The semantics of the BLX (1) instruction, however, - are that bit zero in the offset must always be zero, and the - corresponding bit one in the target address will be set from bit - one of the source address. */ - newval2 &= ~1; + /* For a BLX instruction, make sure that the relocation is rounded up + to a word boundary. This follows the semantics of the instruction + which specifies that bit 1 of the target address will come from bit + 1 of the base address. */ + newval2 = (newval2 + 1) & ~ 1; md_number_to_chars (buf, newval, THUMB_SIZE); md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE); } -- cgit v1.1