OSDN Git Service

Fix Thumb2 bl range options.
authorramana <ramana>
Mon, 21 Dec 2009 21:56:41 +0000 (21:56 +0000)
committerramana <ramana>
Mon, 21 Dec 2009 21:56:41 +0000 (21:56 +0000)
2009-12-21  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
            Richard Earnshaw  <richard.earnshaw@arm.com>

        * config/tc-arm.c (encode_thumb2_b_bl_offset): New. Refactored
        from md_apply_fix.
        (md_apply_fix): Fixup range checks for Thumb2 version
        of unconditional calls. Call encode_thumb2_b_bl_offset for
        unconditional branches / function calls.

gas/ChangeLog
gas/config/tc-arm.c

index 2de5f40..5301e06 100644 (file)
@@ -1,3 +1,12 @@
+2009-12-21  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
+            Richard Earnshaw  <richard.earnshaw@arm.com>
+
+        * config/tc-arm.c (encode_thumb2_b_bl_offset): New. Refactored
+        from md_apply_fix.
+        (md_apply_fix): Fixup range checks for Thumb2 version
+        of unconditional calls. Call encode_thumb2_b_bl_offset for
+        unconditional branches / function calls.
+
 2009-12-19  H.J. Lu  <hongjiu.lu@intel.com>
 
        * config/tc-i386.c (process_operands): Check vexvvvv instead
index c88e5f8..b7e8204 100644 (file)
@@ -19536,6 +19536,31 @@ arm_optimize_expr (expressionS *l, operatorT op, expressionS *r)
   return FALSE;
 }
 
+/* Encode Thumb2 unconditional branches and calls. The encoding
+   for the 2 are identical for the immediate values.  */
+
+static void
+encode_thumb2_b_bl_offset (char * buf, offsetT value)
+{
+#define T2I1I2MASK  ((1 << 13) | (1 << 11))
+  offsetT newval;
+  offsetT newval2;
+  addressT S, I1, I2, lo, hi;
+
+  S = (value >> 24) & 0x01;
+  I1 = (value >> 23) & 0x01;
+  I2 = (value >> 22) & 0x01;
+  hi = (value >> 12) & 0x3ff;
+  lo = (value >> 1) & 0x7ff; 
+  newval   = md_chars_to_number (buf, THUMB_SIZE);
+  newval2  = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
+  newval  |= (S << 10) | hi;
+  newval2 &=  ~T2I1I2MASK;
+  newval2 |= (((I1 ^ S) << 13) | ((I2 ^ S) << 11) | lo) ^ T2I1I2MASK;
+  md_number_to_chars (buf, newval, THUMB_SIZE);
+  md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
+}
+
 void
 md_apply_fix (fixS *   fixP,
               valueT * valP,
@@ -20228,10 +20253,6 @@ md_apply_fix (fixS *   fixP,
         fixP->fx_r_type = BFD_RELOC_THUMB_PCREL_BRANCH23;
 #endif
 
-      if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
-       as_bad_where (fixP->fx_file, fixP->fx_line,
-                     _("branch out of range"));
-
       if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
        /* For a BLX instruction, make sure that the relocation is rounded up
           to a word boundary.  This follows the semantics of the instruction
@@ -20239,17 +20260,25 @@ md_apply_fix (fixS *  fixP,
           1 of the base address.  */
        value = (value + 1) & ~ 1;
 
-      if (fixP->fx_done || !seg->use_rela_p)
-       {
-         offsetT newval2;
 
-         newval   = md_chars_to_number (buf, THUMB_SIZE);
-         newval2  = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
-         newval  |= (value & 0x7fffff) >> 12;
-         newval2 |= (value & 0xfff) >> 1;
-         md_number_to_chars (buf, newval, THUMB_SIZE);
-         md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
+       if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
+       {
+         if (!(ARM_CPU_HAS_FEATURE (cpu_variant, arm_arch_t2)))
+           {
+             as_bad_where (fixP->fx_file, fixP->fx_line,
+                           _("branch out of range"));
+           }
+         else if ((value & ~0x1ffffff)
+                  && ((value & ~0x1ffffff) != ~0x1ffffff))
+             {
+               as_bad_where (fixP->fx_file, fixP->fx_line,
+                           _("Thumb2 branch out of range"));
+             }
        }
+
+      if (fixP->fx_done || !seg->use_rela_p)
+       encode_thumb2_b_bl_offset (buf, value);
+
       break;
 
     case BFD_RELOC_THUMB_PCREL_BRANCH25:
@@ -20258,26 +20287,8 @@ md_apply_fix (fixS *   fixP,
                      _("branch out of range"));
 
       if (fixP->fx_done || !seg->use_rela_p)
-       {
-         offsetT newval2;
-         addressT S, I1, I2, lo, hi;
+         encode_thumb2_b_bl_offset (buf, value);
 
-         S  = (value & 0x01000000) >> 24;
-         I1 = (value & 0x00800000) >> 23;
-         I2 = (value & 0x00400000) >> 22;
-         hi = (value & 0x003ff000) >> 12;
-         lo = (value & 0x00000ffe) >> 1;
-
-         I1 = !(I1 ^ S);
-         I2 = !(I2 ^ S);
-
-         newval   = md_chars_to_number (buf, THUMB_SIZE);
-         newval2  = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
-         newval  |= (S << 10) | hi;
-         newval2 |= (I1 << 13) | (I2 << 11) | lo;
-         md_number_to_chars (buf, newval, THUMB_SIZE);
-         md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
-       }
       break;
 
     case BFD_RELOC_8: