summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2002-05-23 12:37:57 +0000
committerNick Clifton <nickc@redhat.com>2002-05-23 12:37:57 +0000
commit35d220b53c6e263772ff133f3e81777ce552f6a7 (patch)
tree4300fe55fe33bb2ec9331b33cb4047d438b43b3b
parent92138e1da3128a75ba8cb49579fea1ed158564a8 (diff)
downloadbinutils-redhat-35d220b53c6e263772ff133f3e81777ce552f6a7.tar.gz
For the Thumb BLX reloc round the relocation up rather than down.
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/coff-arm.c28
-rw-r--r--bfd/elf32-arm.h21
-rw-r--r--gas/ChangeLog5
-rw-r--r--gas/config/tc-arm.c24
5 files changed, 46 insertions, 38 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 25af58b079..0f2d311a65 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/coff-arm.c b/bfd/coff-arm.c
index 1619e670c3..5e7f907a95 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 91ea63b38b..8b9bf073f1 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 39705193d1..9d8b1839db 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,10 @@
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'
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 b76ee213d9..39f1b65495 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);
}