diff options
author | Richard Earnshaw <rearnsha@arm.com> | 1998-04-08 06:19:00 +0000 |
---|---|---|
committer | Richard Earnshaw <rearnsha@gcc.gnu.org> | 1998-04-08 06:19:00 +0000 |
commit | 6f7349082d53fcf2d42ffe655cff938d3da173f9 (patch) | |
tree | 4f60f1c7a4f7acdcb97f22d0b15bf952aa23b9fe | |
parent | 56c0e996b8de532db95bbca19548ffb92e242a0b (diff) | |
download | gcc-6f7349082d53fcf2d42ffe655cff938d3da173f9.zip gcc-6f7349082d53fcf2d42ffe655cff938d3da173f9.tar.gz gcc-6f7349082d53fcf2d42ffe655cff938d3da173f9.tar.bz2 |
* arm.h (LEGITIMIZE_RELOAD_ADDRESS): Define.
From-SVN: r19039
-rw-r--r-- | gcc/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 53 |
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 */ |