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
This commit is contained in:
Richard Earnshaw 2003-01-22 16:01:43 +00:00 committed by Richard Earnshaw
parent f0bf127006
commit 6b990f6b63
4 changed files with 203 additions and 135 deletions

View File

@ -1,3 +1,13 @@
2003-01-22 Richard Earnshaw <rearnsha@arm.com>
* 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 <hpenner@de.ibm.com>
* config/s390/s390.md (floatdfdi2): Insn has type 'itof'.

View File

@ -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));

View File

@ -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))

View File

@ -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) \