For the Thumb BLX reloc round the relocation up rather than down.

This commit is contained in:
Nick Clifton 2002-05-23 12:37:57 +00:00
parent 6ff96af674
commit c62e1cc30f
5 changed files with 46 additions and 38 deletions

View File

@ -1,3 +1,9 @@
2002-05-23 Nick Clifton <nickc@cambridge.redhat.com>
* 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

View File

@ -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);

View File

@ -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;
#ifndef OLD_ARM_ABI
if (r_type == R_ARM_THM_XPC22
&& ((lower_insn & 0x1800) == 0x0800))
/* 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);
#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;
#endif
/* 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);

View File

@ -1,3 +1,8 @@
2002-05-23 Nick Clifton <nickc@cambridge.redhat.com>
* config/tc-arm.c (md_apply_fix3): For the Thumb BLX reloc
round the relocation up rather than down.
2002-05-23 Nick Clifton <nickc@cambridge.redhat.com>
* config/obj-coff.c (obj_coff_section): Silently ignore an 'a'

View File

@ -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);
}