From 6f7349082d53fcf2d42ffe655cff938d3da173f9 Mon Sep 17 00:00:00 2001 From: Richard Earnshaw Date: Wed, 8 Apr 1998 06:19:00 +0000 Subject: * arm.h (LEGITIMIZE_RELOAD_ADDRESS): Define. From-SVN: r19039 --- gcc/ChangeLog | 4 ++++ gcc/config/arm/arm.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) (limited to 'gcc') 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 */ -- cgit v1.1