OSDN Git Service

* arm.c (thumb_legitimize_address): New function.
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Feb 2004 17:03:27 +0000 (17:03 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Feb 2004 17:03:27 +0000 (17:03 +0000)
* arm-protos.h: Prototype it.
* arm.h (THUMB_LEGITIMIZE_ADDRESS): Define.
(LEGITIMIZE_ADDRESS): Use it.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@78437 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/arm.h

index 4405cd9..8f405e7 100644 (file)
@@ -1,3 +1,10 @@
+2004-02-25  Richard Earnshaw  <rearnsha@arm.com>
+
+       * arm.c (thumb_legitimize_address): New function.
+       * arm-protos.h: Prototype it.
+       * arm.h (THUMB_LEGITIMIZE_ADDRESS): Define.
+       (LEGITIMIZE_ADDRESS): Use it.
+
 2004-02-25  J"orn Rennecke <joern.rennecke@superh.com>
 
        * reload1.c (reload): Only spill eliminable register with multiple
index 25f5631..4c0575d 100644 (file)
@@ -54,6 +54,7 @@ extern int arm_legitimate_address_p  (enum machine_mode, rtx, int);
 extern int thumb_legitimate_address_p (enum machine_mode, rtx, int);
 extern int thumb_legitimate_offset_p (enum machine_mode, HOST_WIDE_INT);
 extern rtx arm_legitimize_address (rtx, rtx, enum machine_mode);
+extern rtx thumb_legitimize_address (rtx, rtx, enum machine_mode);
 extern int arm_const_double_rtx (rtx);
 extern int neg_const_double_rtx_ok_for_fpa (rtx);
 extern enum reg_class vfp_secondary_reload_class (enum machine_mode, rtx);
index 98c05cb..0a61e1b 100644 (file)
@@ -3232,6 +3232,74 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
   return x;
 }
 
+
+/* Try machine-dependent ways of modifying an illegitimate Thumb address
+   to be legitimate.  If we find one, return the new, valid address.  */
+rtx
+thumb_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
+{
+  if (GET_CODE (x) == PLUS
+      && GET_CODE (XEXP (x, 1)) == CONST_INT
+      && (INTVAL (XEXP (x, 1)) >= 32 * GET_MODE_SIZE (mode)
+         || INTVAL (XEXP (x, 1)) < 0))
+    {
+      rtx xop0 = XEXP (x, 0);
+      rtx xop1 = XEXP (x, 1);
+      HOST_WIDE_INT offset = INTVAL (xop1);
+
+      /* Try and fold the offset into a biasing of the base register and
+        then offsetting that.  Don't do this when optimizing for space
+        since it can cause too many CSEs.  */
+      if (optimize_size && offset >= 0
+         && offset < 256 + 31 * GET_MODE_SIZE (mode))
+       {
+         HOST_WIDE_INT delta;
+
+         if (offset >= 256)
+           delta = offset - (256 - GET_MODE_SIZE (mode));
+         else if (offset < 32 * GET_MODE_SIZE (mode) + 8)
+           delta = 31 * GET_MODE_SIZE (mode);
+         else
+           delta = offset & (~31 * GET_MODE_SIZE (mode));
+
+         xop0 = force_operand (plus_constant (xop0, offset - delta),
+                               NULL_RTX);
+         x = plus_constant (xop0, delta);
+       }
+      else if (offset < 0 && offset > -256)
+       /* Small negative offsets are best done with a subtract before the
+          dereference, forcing these into a register normally takes two
+          instructions.  */
+       x = force_operand (x, NULL_RTX);
+      else
+       {
+         /* For the remaining cases, force the constant into a register.  */
+         xop1 = force_reg (SImode, xop1);
+         x = gen_rtx_PLUS (SImode, xop0, xop1);
+       }
+    }
+  else if (GET_CODE (x) == PLUS
+          && s_register_operand (XEXP (x, 1), SImode)
+          && !s_register_operand (XEXP (x, 0), SImode))
+    {
+      rtx xop0 = force_operand (XEXP (x, 0), NULL_RTX);
+
+      x = gen_rtx_PLUS (SImode, xop0, XEXP (x, 1));
+    }
+
+  if (flag_pic)
+    {
+      /* We need to find and carefully transform any SYMBOL and LABEL
+        references; so go back to the original address expression.  */
+      rtx new_x = legitimize_pic_address (orig_x, mode, NULL_RTX);
+
+      if (new_x != orig_x)
+       x = new_x;
+    }
+
+  return x;
+}
+
 \f
 
 #define REG_OR_SUBREG_REG(X)                                           \
index 320bee0..5b85e75 100644 (file)
@@ -2361,15 +2361,11 @@ typedef struct
 #define ARM_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)     \
 do {                                                   \
   X = arm_legitimize_address (X, OLDX, MODE);          \
-                                                       \
-  if (memory_address_p (MODE, X))                      \
-    goto WIN;                                          \
 } while (0)
 
-#define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)           \
-do {                                                           \
-  if (flag_pic)                                                        \
-    (X) = legitimize_pic_address (OLDX, MODE, NULL_RTX);       \
+#define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)   \
+do {                                                   \
+  X = thumb_legitimize_address (X, OLDX, MODE);                \
 } while (0)
 
 #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)         \
@@ -2378,6 +2374,9 @@ do {                                                      \
     ARM_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN);       \
   else                                                 \
     THUMB_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN);     \
+                                                       \
+  if (memory_address_p (MODE, X))                      \
+    goto WIN;                                          \
 } while (0)
      
 /* Go to LABEL if ADDR (a legitimate address expression)