For the Thumb BLX reloc round the relocation up rather than down.
authorNick Clifton <nickc@redhat.com>
Thu, 23 May 2002 12:37:57 +0000 (12:37 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 23 May 2002 12:37:57 +0000 (12:37 +0000)
bfd/ChangeLog
bfd/coff-arm.c
bfd/elf32-arm.h
gas/ChangeLog
gas/config/tc-arm.c

index 25af58b..0f2d311 100644 (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
index 1619e67..5e7f907 100644 (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);
index 91ea63b..8b9bf07 100644 (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;
 
-       /* 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);
index 3970519..9d8b183 100644 (file)
@@ -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
index b76ee21..39f1b65 100644 (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);
       }