]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* arm.h (LEGITIMIZE_RELOAD_ADDRESS): Define.
authorRichard Earnshaw <rearnsha@arm.com>
Wed, 8 Apr 1998 06:19:00 +0000 (06:19 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Wed, 8 Apr 1998 06:19:00 +0000 (06:19 +0000)
From-SVN: r19039

gcc/ChangeLog
gcc/config/arm/arm.h

index 4e7744c0cfb1c78dddca3154c9a14fb0d06ac6d5..5707a6d3922c39caac913ca385f1c3c33afb0f28 100644 (file)
@@ -1,3 +1,7 @@
+Wed Apr  8 06:16:45 1998  Richard Earnshaw (rearnsha@arm.com)
+
+       * arm.h (LEGITIMIZE_RELOAD_ADDRESS): Define.
+
 Wed Apr  8 00:44:18 1998  Bernd Schmidt (crux@pool.informatik.rwth-aachen.de>
 
        * c-lex.c (is_class_name): Delete declaration.
index 0adf6dc6eabfbf45bdaffb503a234f077ee532b9..dab507f2e79cd6b178d16cc32ff67762f5b8ec7c 100644 (file)
@@ -877,6 +877,59 @@ enum reg_class
   (((MODE) == HImode && TARGET_SHORT_BY_BYTES && true_regnum (X) == -1)        \
    ? GENERAL_REGS : NO_REGS)
 
+/* Try a machine-dependent way of reloading an illegitimate address
+   operand.  If we find one, push the reload and jump to WIN.  This
+   macro is used in only one place: `find_reloads_address' in reload.c.
+
+   For the ARM, we wish to handle large displacements off a base
+   register by splitting the addend across a MOV and the mem insn.
+   This can cut the number of reloads needed. */
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)    \
+do {                                                                   \
+  if (GET_CODE (X) == PLUS                                             \
+      && GET_CODE (XEXP (X, 0)) == REG                                 \
+      && REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER                   \
+      && REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE)                    \
+      && GET_CODE (XEXP (X, 1)) == CONST_INT)                          \
+    {                                                                  \
+      HOST_WIDE_INT val = INTVAL (XEXP (X, 1));                                \
+      HOST_WIDE_INT low, high;                                         \
+                                                                       \
+      if (MODE == DImode || (TARGET_SOFT_FLOAT && MODE == DFmode))     \
+       low = ((val & 0xf) ^ 0x8) - 0x8;                                \
+      else if (MODE == SImode || MODE == QImode                                \
+              || (MODE == SFmode && TARGET_SOFT_FLOAT)                 \
+              || (MODE == HImode && ! arm_arch4))                      \
+       /* Need to be careful, -4096 is not a valid offset */           \
+       low = val >= 0 ? (val & 0xfff) : -((-val) & 0xfff);             \
+      else if (MODE == HImode && arm_arch4)                            \
+       /* Need to be careful, -256 is not a valid offset */            \
+       low = val >= 0 ? (val & 0xff) : -((-val) & 0xff);               \
+      else if (GET_MODE_CLASS (MODE) == MODE_FLOAT                     \
+              && TARGET_HARD_FLOAT)                                    \
+       /* Need to be careful, -1024 is not a valid offset */           \
+       low = val >= 0 ? (val & 0x3ff) : -((-val) & 0x3ff);             \
+      else                                                             \
+       break;                                                          \
+                                                                       \
+      high = ((((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000); \
+      /* Check for overflow or zero */                                 \
+      if (low == 0 || high == 0 || (high + low != val))                        \
+       break;                                                          \
+                                                                       \
+      /* Reload the high part into a base reg; leave the low part      \
+        in the mem.  */                                                \
+      X = gen_rtx_PLUS (GET_MODE (X),                                  \
+                       gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0),        \
+                                     GEN_INT (high)),                  \
+                       GEN_INT (low));                                 \
+      push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR,      \
+                  BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0,        \
+                  OPNUM, TYPE);                                        \
+      goto WIN;                                                                \
+    }                                                                  \
+} while (0)
+
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
    ARM regs are UNITS_PER_WORD bits while FPU regs can hold any FP mode */