aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>1998-04-08 06:19:00 +0000
committerRichard Earnshaw <rearnsha@gcc.gnu.org>1998-04-08 06:19:00 +0000
commit6f7349082d53fcf2d42ffe655cff938d3da173f9 (patch)
tree4f60f1c7a4f7acdcb97f22d0b15bf952aa23b9fe
parent56c0e996b8de532db95bbca19548ffb92e242a0b (diff)
downloadgcc-6f7349082d53fcf2d42ffe655cff938d3da173f9.zip
gcc-6f7349082d53fcf2d42ffe655cff938d3da173f9.tar.gz
gcc-6f7349082d53fcf2d42ffe655cff938d3da173f9.tar.bz2
* arm.h (LEGITIMIZE_RELOAD_ADDRESS): Define.
From-SVN: r19039
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/config/arm/arm.h53
2 files changed, 57 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4e7744c..5707a6d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 0adf6dc..dab507f 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -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 */