From 6b990f6b63181e0dad5e6b9d18bf62f51a3ebc4d Mon Sep 17 00:00:00 2001 From: Richard Earnshaw Date: Wed, 22 Jan 2003 16:01:43 +0000 Subject: [PATCH] arm.c (arm_address_register_rtx_p): New function. * arm.c (arm_address_register_rtx_p): New function. (arm_legitimate_address_p): New function. (arm_legitimate_index_p): New function. (legitimize_pic_address): Use arm_legitimate_index_p. * arm-protos.h (arm_legtimate_address_p): Add prototype. * arm.h (ARM_GO_IF_LEGITIMATE_INDEX): Delete. (ARM_GO_IF_LEGITIMATE_ADDRESS): Call arm_legitimate_address_p. From-SVN: r61592 --- gcc/ChangeLog | 10 ++ gcc/config/arm/arm-protos.h | 1 + gcc/config/arm/arm.c | 186 ++++++++++++++++++++++++++++++++++-- gcc/config/arm/arm.h | 141 +++------------------------ 4 files changed, 203 insertions(+), 135 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bc7370cc20c..e110c0e3d76 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2003-01-22 Richard Earnshaw + + * arm.c (arm_address_register_rtx_p): New function. + (arm_legitimate_address_p): New function. + (arm_legitimate_index_p): New function. + (legitimize_pic_address): Use arm_legitimate_index_p. + * arm-protos.h (arm_legtimate_address_p): Add prototype. + * arm.h (ARM_GO_IF_LEGITIMATE_INDEX): Delete. + (ARM_GO_IF_LEGITIMATE_ADDRESS): Call arm_legitimate_address_p. + 2003-01-22 Hartmut Penner * config/s390/s390.md (floatdfdi2): Insn has type 'itof'. diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 861642a1dda..83788a0529f 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -52,6 +52,7 @@ extern int arm_split_constant PARAMS ((RTX_CODE, enum machine_mode, extern RTX_CODE arm_canonicalize_comparison PARAMS ((RTX_CODE, rtx *)); extern int legitimate_pic_operand_p PARAMS ((rtx)); extern rtx legitimize_pic_address PARAMS ((rtx, enum machine_mode, rtx)); +extern int arm_legitimate_address_p PARAMS ((enum machine_mode, rtx, int)); extern int arm_rtx_costs PARAMS ((rtx, RTX_CODE, RTX_CODE)); extern int const_double_rtx_ok_for_fpu PARAMS ((rtx)); extern int neg_const_double_rtx_ok_for_fpu PARAMS ((rtx)); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 9f65028b73b..4a8d85a2146 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -68,6 +68,9 @@ const struct attribute_spec arm_attribute_table[]; static void arm_add_gc_roots PARAMS ((void)); static int arm_gen_constant PARAMS ((enum rtx_code, Mmode, Hint, rtx, rtx, int, int)); static unsigned bit_count PARAMS ((Ulong)); +static int arm_address_register_rtx_p PARAMS ((rtx, int)); +static int arm_legitimate_index_p PARAMS ((enum machine_mode, + rtx, int)); static int const_ok_for_op PARAMS ((Hint, enum rtx_code)); static int eliminate_lr2ip PARAMS ((rtx *)); static rtx emit_multi_reg_push PARAMS ((int)); @@ -2357,6 +2360,10 @@ arm_function_ok_for_sibcall (decl, exp) } +/* Addressing mode support functions. */ + +/* Return non-zero if X is a legitimate immediate operand when compiling + for PIC. */ int legitimate_pic_operand_p (x) rtx x; @@ -2463,14 +2470,14 @@ legitimize_pic_address (orig, mode, reg) { /* The base register doesn't really matter, we only want to test the index for the appropriate mode. */ - ARM_GO_IF_LEGITIMATE_INDEX (mode, 0, offset, win); + if (!arm_legitimate_index_p (mode, offset, 0)) + { + if (!no_new_pseudos) + offset = force_reg (Pmode, offset); + else + abort (); + } - if (!no_new_pseudos) - offset = force_reg (Pmode, offset); - else - abort (); - - win: if (GET_CODE (offset) == CONST_INT) return plus_constant (base, INTVAL (offset)); } @@ -2548,6 +2555,171 @@ arm_finalize_pic (prologue) #endif /* AOF_ASSEMBLER */ } +/* Return nonzero if X is valid as an ARM state addressing register. */ +static int +arm_address_register_rtx_p (x, strict_p) + rtx x; + int strict_p; +{ + int regno; + + if (GET_CODE (x) != REG) + return 0; + + regno = REGNO (x); + + if (strict_p) + return ARM_REGNO_OK_FOR_BASE_P (regno); + + return (regno <= LAST_ARM_REGNUM + || regno >= FIRST_PSEUDO_REGISTER + || regno == FRAME_POINTER_REGNUM + || regno == ARG_POINTER_REGNUM); +} + +/* Return nonzero if X is a valid ARM state address operand. */ +int +arm_legitimate_address_p (mode, x, strict_p) + enum machine_mode mode; + rtx x; + int strict_p; +{ + if (arm_address_register_rtx_p (x, strict_p)) + return 1; + + else if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_DEC) + return arm_address_register_rtx_p (XEXP (x, 0), strict_p); + + else if ((GET_CODE (x) == POST_MODIFY || GET_CODE (x) == PRE_MODIFY) + && GET_MODE_SIZE (mode) <= 4 + && arm_address_register_rtx_p (XEXP (x, 0), strict_p) + && GET_CODE (XEXP (x, 1)) == PLUS + && XEXP (XEXP (x, 1), 0) == XEXP (x, 0)) + return arm_legitimate_index_p (mode, XEXP (XEXP (x, 1), 1), strict_p); + + /* After reload constants split into minipools will have addresses + from a LABEL_REF. */ + else if (GET_MODE_SIZE (mode) >= 4 && reload_completed + && (GET_CODE (x) == LABEL_REF + || (GET_CODE (x) == CONST + && GET_CODE (XEXP (x, 0)) == PLUS + && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF + && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))) + return 1; + + else if (mode == TImode) + return 0; + + else if (mode == DImode || (TARGET_SOFT_FLOAT && mode == DFmode)) + { + if (GET_CODE (x) == PLUS + && arm_address_register_rtx_p (XEXP (x, 0), strict_p) + && GET_CODE (XEXP (x, 1)) == CONST_INT) + { + HOST_WIDE_INT val = INTVAL (XEXP (x, 1)); + + if (val == 4 || val == -4 || val == -8) + return 1; + } + } + + else if (GET_CODE (x) == PLUS) + { + rtx xop0 = XEXP (x, 0); + rtx xop1 = XEXP (x, 1); + + return ((arm_address_register_rtx_p (xop0, strict_p) + && arm_legitimate_index_p (mode, xop1, strict_p)) + || (arm_address_register_rtx_p (xop1, strict_p) + && arm_legitimate_index_p (mode, xop0, strict_p))); + } + +#if 0 + /* Reload currently can't handle MINUS, so disable this for now */ + else if (GET_CODE (x) == MINUS) + { + rtx xop0 = XEXP (x, 0); + rtx xop1 = XEXP (x, 1); + + return (arm_address_register_rtx_p (xop0, strict_p) + && arm_legitimate_index_p (mode, xop1, strict_p)); + } +#endif + + else if (GET_MODE_CLASS (mode) != MODE_FLOAT + && GET_CODE (x) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (x) + && ! (flag_pic + && symbol_mentioned_p (get_pool_constant (x)))) + return 1; + + else if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == POST_DEC) + && (GET_MODE_SIZE (mode) <= 4) + && arm_address_register_rtx_p (XEXP (x, 0), strict_p)) + return 1; + + return 0; +} + +/* Return nonzero if INDEX is valid for an address index operand in + ARM state. */ +static int +arm_legitimate_index_p (mode, index, strict_p) + enum machine_mode mode; + rtx index; + int strict_p; +{ + HOST_WIDE_INT range; + enum rtx_code code = GET_CODE (index); + + if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) + return (code == CONST_INT && INTVAL (index) < 1024 + && INTVAL (index) > -1024 + && (INTVAL (index) & 3) == 0); + + if (arm_address_register_rtx_p (index, strict_p) + && GET_MODE_SIZE (mode) <= 4) + return 1; + + /* XXX What about ldrsb? */ + if (GET_MODE_SIZE (mode) <= 4 && code == MULT + && (!arm_arch4 || (mode) != HImode)) + { + rtx xiop0 = XEXP (index, 0); + rtx xiop1 = XEXP (index, 1); + + return ((arm_address_register_rtx_p (xiop0, strict_p) + && power_of_two_operand (xiop1, SImode)) + || (arm_address_register_rtx_p (xiop1, strict_p) + && power_of_two_operand (xiop0, SImode))); + } + + if (GET_MODE_SIZE (mode) <= 4 + && (code == LSHIFTRT || code == ASHIFTRT + || code == ASHIFT || code == ROTATERT) + && (!arm_arch4 || (mode) != HImode)) + { + rtx op = XEXP (index, 1); + + return (arm_address_register_rtx_p (XEXP (index, 0), strict_p) + && GET_CODE (op) == CONST_INT + && INTVAL (op) > 0 + && INTVAL (op) <= 31); + } + + /* XXX For ARM v4 we may be doing a sign-extend operation during the + load, but that has a restricted addressing range and we are unable + to tell here whether that is the case. To be safe we restrict all + loads to that range. */ + range = ((mode) == HImode || (mode) == QImode) + ? (arm_arch4 ? 256 : 4095) : 4096; + + return (code == CONST_INT + && INTVAL (index) < range + && INTVAL (index) > -range); +} + + #define REG_OR_SUBREG_REG(X) \ (GET_CODE (X) == REG \ || (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG)) diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 48292a4c77a..c0708016d16 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1943,134 +1943,19 @@ typedef struct #define ARM_INDEX_REGISTER_RTX_P(X) \ (GET_CODE (X) == REG && ARM_REG_OK_FOR_INDEX_P (X)) -/* A C statement (sans semicolon) to jump to LABEL for legitimate index RTXs - used by the macro GO_IF_LEGITIMATE_ADDRESS. Floating point indices can - only be small constants. */ -#define ARM_GO_IF_LEGITIMATE_INDEX(MODE, BASE_REGNO, INDEX, LABEL) \ - do \ - { \ - HOST_WIDE_INT range; \ - enum rtx_code code = GET_CODE (INDEX); \ - \ - if (TARGET_HARD_FLOAT && GET_MODE_CLASS (MODE) == MODE_FLOAT) \ - { \ - if (code == CONST_INT && INTVAL (INDEX) < 1024 \ - && INTVAL (INDEX) > -1024 \ - && (INTVAL (INDEX) & 3) == 0) \ - goto LABEL; \ - } \ - else \ - { \ - if (ARM_INDEX_REGISTER_RTX_P (INDEX) \ - && GET_MODE_SIZE (MODE) <= 4) \ - goto LABEL; \ - if (GET_MODE_SIZE (MODE) <= 4 && code == MULT \ - && (! arm_arch4 || (MODE) != HImode)) \ - { \ - rtx xiop0 = XEXP (INDEX, 0); \ - rtx xiop1 = XEXP (INDEX, 1); \ - if (ARM_INDEX_REGISTER_RTX_P (xiop0) \ - && power_of_two_operand (xiop1, SImode)) \ - goto LABEL; \ - if (ARM_INDEX_REGISTER_RTX_P (xiop1) \ - && power_of_two_operand (xiop0, SImode)) \ - goto LABEL; \ - } \ - if (GET_MODE_SIZE (MODE) <= 4 \ - && (code == LSHIFTRT || code == ASHIFTRT \ - || code == ASHIFT || code == ROTATERT) \ - && (! arm_arch4 || (MODE) != HImode)) \ - { \ - rtx op = XEXP (INDEX, 1); \ - if (ARM_INDEX_REGISTER_RTX_P (XEXP (INDEX, 0)) \ - && GET_CODE (op) == CONST_INT && INTVAL (op) > 0 \ - && INTVAL (op) <= 31) \ - goto LABEL; \ - } \ - /* NASTY: Since this limits the addressing of unsigned \ - byte loads. */ \ - range = ((MODE) == HImode || (MODE) == QImode) \ - ? (arm_arch4 ? 256 : 4095) : 4096; \ - if (code == CONST_INT && INTVAL (INDEX) < range \ - && INTVAL (INDEX) > -range) \ - goto LABEL; \ - } \ - } \ - while (0) - -/* Jump to LABEL if X is a valid address RTX. This must take - REG_OK_STRICT into account when deciding about valid registers. - - Allow REG, REG+REG, REG+INDEX, INDEX+REG, REG-INDEX, and non - floating SYMBOL_REF to the constant pool. Allow REG-only and - AUTINC-REG if handling TImode or HImode. Other symbol refs must be - forced though a static cell to ensure addressability. */ -#define ARM_GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \ -{ \ - if (ARM_BASE_REGISTER_RTX_P (X)) \ - goto LABEL; \ - else if ((GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC) \ - && GET_CODE (XEXP (X, 0)) == REG \ - && ARM_REG_OK_FOR_BASE_P (XEXP (X, 0))) \ - goto LABEL; \ - else if ((GET_CODE (X) == POST_MODIFY || GET_CODE (X) == PRE_MODIFY) \ - && GET_MODE_SIZE (MODE) <= 4 \ - && GET_CODE (XEXP (X, 0)) == REG \ - && ARM_REG_OK_FOR_BASE_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 1)) == PLUS \ - && XEXP (XEXP (X, 1), 0) == XEXP (X, 0)) \ - ARM_GO_IF_LEGITIMATE_INDEX (MODE, REGNO (XEXP (X, 0)), \ - XEXP (XEXP (X, 1), 1), LABEL); \ - else if (GET_MODE_SIZE (MODE) >= 4 && reload_completed \ - && (GET_CODE (X) == LABEL_REF \ - || (GET_CODE (X) == CONST \ - && GET_CODE (XEXP ((X), 0)) == PLUS \ - && GET_CODE (XEXP (XEXP ((X), 0), 0)) == LABEL_REF \ - && GET_CODE (XEXP (XEXP ((X), 0), 1)) == CONST_INT))) \ - goto LABEL; \ - else if ((MODE) == TImode) \ - ; \ - else if ((MODE) == DImode || (TARGET_SOFT_FLOAT && (MODE) == DFmode)) \ - { \ - if (GET_CODE (X) == PLUS && ARM_BASE_REGISTER_RTX_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT) \ - { \ - HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \ - if (val == 4 || val == -4 || val == -8) \ - goto LABEL; \ - } \ - } \ - else if (GET_CODE (X) == PLUS) \ - { \ - rtx xop0 = XEXP (X, 0); \ - rtx xop1 = XEXP (X, 1); \ - \ - if (ARM_BASE_REGISTER_RTX_P (xop0)) \ - ARM_GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop0), xop1, LABEL); \ - else if (ARM_BASE_REGISTER_RTX_P (xop1)) \ - ARM_GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop1), xop0, LABEL); \ - } \ - /* Reload currently can't handle MINUS, so disable this for now */ \ - /* else if (GET_CODE (X) == MINUS) \ - { \ - rtx xop0 = XEXP (X,0); \ - rtx xop1 = XEXP (X,1); \ - \ - if (ARM_BASE_REGISTER_RTX_P (xop0)) \ - ARM_GO_IF_LEGITIMATE_INDEX (MODE, -1, xop1, LABEL); \ - } */ \ - else if (GET_MODE_CLASS (MODE) != MODE_FLOAT \ - && GET_CODE (X) == SYMBOL_REF \ - && CONSTANT_POOL_ADDRESS_P (X) \ - && ! (flag_pic \ - && symbol_mentioned_p (get_pool_constant (X)))) \ - goto LABEL; \ - else if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == POST_DEC) \ - && (GET_MODE_SIZE (MODE) <= 4) \ - && GET_CODE (XEXP (X, 0)) == REG \ - && ARM_REG_OK_FOR_BASE_P (XEXP (X, 0))) \ - goto LABEL; \ -} +#ifdef REG_OK_STRICT +#define ARM_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \ + { \ + if (arm_legitimate_address_p (MODE, X, 1)) \ + goto WIN; \ + } +#else +#define ARM_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \ + { \ + if (arm_legitimate_address_p (MODE, X, 0)) \ + goto WIN; \ + } +#endif /* ---------------------thumb version----------------------------------*/ #define THUMB_LEGITIMATE_OFFSET(MODE, VAL) \