mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-12 21:33:54 +08:00
arm.c (thumb_base_register_rtx_p): New function.
* arm.c (thumb_base_register_rtx_p): New function. (thumb_index_register_rtx_p): New function. (thumb_legitimate_address_p): New function. (thumb_legitimate_offset_p): New function. * arm.h (REG_STRICT_P): Define according to setting of REG_OK_STRICT. (ARM_GO_IF_LEGITIMATE_ADDRESS): Use REG_STRICT_P to avoid dumplicate definitions. (THUMB_GO_IF_LEGITIMATE_ADDRESS): Use thumb_legitimate_address_p. (THUMB_LEGITIMATE_OFFSET): Delte. (THUMB_LEGITIMIZE_RELOAD_ADDRESS): Use thumb_legitimate_offset. * arm-protos.h (thumb_legitimate_address_p): Add prototype. (thumb_legitimate_offset_p): Likewise. From-SVN: r61662
This commit is contained in:
parent
0f0ff6ec54
commit
76a318e977
@ -1,3 +1,18 @@
|
|||||||
|
2003-01-23 Richard Earnshaw <rearnsha@arm.com>
|
||||||
|
|
||||||
|
* arm.c (thumb_base_register_rtx_p): New function.
|
||||||
|
(thumb_index_register_rtx_p): New function.
|
||||||
|
(thumb_legitimate_address_p): New function.
|
||||||
|
(thumb_legitimate_offset_p): New function.
|
||||||
|
* arm.h (REG_STRICT_P): Define according to setting of REG_OK_STRICT.
|
||||||
|
(ARM_GO_IF_LEGITIMATE_ADDRESS): Use REG_STRICT_P to avoid dumplicate
|
||||||
|
definitions.
|
||||||
|
(THUMB_GO_IF_LEGITIMATE_ADDRESS): Use thumb_legitimate_address_p.
|
||||||
|
(THUMB_LEGITIMATE_OFFSET): Delte.
|
||||||
|
(THUMB_LEGITIMIZE_RELOAD_ADDRESS): Use thumb_legitimate_offset.
|
||||||
|
* arm-protos.h (thumb_legitimate_address_p): Add prototype.
|
||||||
|
(thumb_legitimate_offset_p): Likewise.
|
||||||
|
|
||||||
2003-01-23 Andreas Schwab <schwab@suse.de>
|
2003-01-23 Andreas Schwab <schwab@suse.de>
|
||||||
|
|
||||||
* unwind.h (_Unwind_GetTextRelBase): Mark parameter as unused.
|
* unwind.h (_Unwind_GetTextRelBase): Mark parameter as unused.
|
||||||
|
@ -53,6 +53,10 @@ extern RTX_CODE arm_canonicalize_comparison PARAMS ((RTX_CODE, rtx *));
|
|||||||
extern int legitimate_pic_operand_p PARAMS ((rtx));
|
extern int legitimate_pic_operand_p PARAMS ((rtx));
|
||||||
extern rtx legitimize_pic_address PARAMS ((rtx, enum machine_mode, 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_legitimate_address_p PARAMS ((enum machine_mode, rtx, int));
|
||||||
|
extern int thumb_legitimate_address_p PARAMS ((enum machine_mode, rtx,
|
||||||
|
int));
|
||||||
|
extern int thumb_legitimate_offset_p PARAMS ((enum machine_mode,
|
||||||
|
HOST_WIDE_INT));
|
||||||
extern int arm_rtx_costs PARAMS ((rtx, RTX_CODE, RTX_CODE));
|
extern int arm_rtx_costs PARAMS ((rtx, RTX_CODE, RTX_CODE));
|
||||||
extern int const_double_rtx_ok_for_fpu PARAMS ((rtx));
|
extern int const_double_rtx_ok_for_fpu PARAMS ((rtx));
|
||||||
extern int neg_const_double_rtx_ok_for_fpu PARAMS ((rtx));
|
extern int neg_const_double_rtx_ok_for_fpu PARAMS ((rtx));
|
||||||
|
@ -71,6 +71,10 @@ static unsigned bit_count PARAMS ((Ulong));
|
|||||||
static int arm_address_register_rtx_p PARAMS ((rtx, int));
|
static int arm_address_register_rtx_p PARAMS ((rtx, int));
|
||||||
static int arm_legitimate_index_p PARAMS ((enum machine_mode,
|
static int arm_legitimate_index_p PARAMS ((enum machine_mode,
|
||||||
rtx, int));
|
rtx, int));
|
||||||
|
static int thumb_base_register_rtx_p PARAMS ((rtx,
|
||||||
|
enum machine_mode,
|
||||||
|
int));
|
||||||
|
inline static int thumb_index_register_rtx_p PARAMS ((rtx, int));
|
||||||
static int const_ok_for_op PARAMS ((Hint, enum rtx_code));
|
static int const_ok_for_op PARAMS ((Hint, enum rtx_code));
|
||||||
static int eliminate_lr2ip PARAMS ((rtx *));
|
static int eliminate_lr2ip PARAMS ((rtx *));
|
||||||
static rtx emit_multi_reg_push PARAMS ((int));
|
static rtx emit_multi_reg_push PARAMS ((int));
|
||||||
@ -2717,7 +2721,177 @@ arm_legitimate_index_p (mode, index, strict_p)
|
|||||||
return (code == CONST_INT
|
return (code == CONST_INT
|
||||||
&& INTVAL (index) < range
|
&& INTVAL (index) < range
|
||||||
&& INTVAL (index) > -range);
|
&& INTVAL (index) > -range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return nonzero if X is valid as an ARM state addressing register. */
|
||||||
|
static int
|
||||||
|
thumb_base_register_rtx_p (x, mode, strict_p)
|
||||||
|
rtx x;
|
||||||
|
enum machine_mode mode;
|
||||||
|
int strict_p;
|
||||||
|
{
|
||||||
|
int regno;
|
||||||
|
|
||||||
|
if (GET_CODE (x) != REG)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
regno = REGNO (x);
|
||||||
|
|
||||||
|
if (strict_p)
|
||||||
|
return THUMB_REGNO_MODE_OK_FOR_BASE_P (regno, mode);
|
||||||
|
|
||||||
|
return (regno <= LAST_LO_REGNUM
|
||||||
|
|| regno >= FIRST_PSEUDO_REGISTER
|
||||||
|
|| regno == FRAME_POINTER_REGNUM
|
||||||
|
|| (GET_MODE_SIZE (mode) >= 4
|
||||||
|
&& (regno == STACK_POINTER_REGNUM
|
||||||
|
|| x == hard_frame_pointer_rtx
|
||||||
|
|| x == arg_pointer_rtx)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return nonzero if x is a legitimate index register. This is the case
|
||||||
|
for any base register that can access a QImode object. */
|
||||||
|
inline static int
|
||||||
|
thumb_index_register_rtx_p (x, strict_p)
|
||||||
|
rtx x;
|
||||||
|
int strict_p;
|
||||||
|
{
|
||||||
|
return thumb_base_register_rtx_p (x, QImode, strict_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return nonzero if x is a legitimate Thumb-state address.
|
||||||
|
|
||||||
|
The AP may be eliminated to either the SP or the FP, so we use the
|
||||||
|
least common denominator, e.g. SImode, and offsets from 0 to 64.
|
||||||
|
|
||||||
|
??? Verify whether the above is the right approach.
|
||||||
|
|
||||||
|
??? Also, the FP may be eliminated to the SP, so perhaps that
|
||||||
|
needs special handling also.
|
||||||
|
|
||||||
|
??? Look at how the mips16 port solves this problem. It probably uses
|
||||||
|
better ways to solve some of these problems.
|
||||||
|
|
||||||
|
Although it is not incorrect, we don't accept QImode and HImode
|
||||||
|
addresses based on the frame pointer or arg pointer until the
|
||||||
|
reload pass starts. This is so that eliminating such addresses
|
||||||
|
into stack based ones won't produce impossible code. */
|
||||||
|
int
|
||||||
|
thumb_legitimate_address_p (mode, x, strict_p)
|
||||||
|
enum machine_mode mode;
|
||||||
|
rtx x;
|
||||||
|
int strict_p;
|
||||||
|
{
|
||||||
|
/* ??? Not clear if this is right. Experiment. */
|
||||||
|
if (GET_MODE_SIZE (mode) < 4
|
||||||
|
&& !(reload_in_progress || reload_completed)
|
||||||
|
&& (reg_mentioned_p (frame_pointer_rtx, x)
|
||||||
|
|| reg_mentioned_p (arg_pointer_rtx, x)
|
||||||
|
|| reg_mentioned_p (virtual_incoming_args_rtx, x)
|
||||||
|
|| reg_mentioned_p (virtual_outgoing_args_rtx, x)
|
||||||
|
|| reg_mentioned_p (virtual_stack_dynamic_rtx, x)
|
||||||
|
|| reg_mentioned_p (virtual_stack_vars_rtx, x)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Accept any base register. SP only in SImode or larger. */
|
||||||
|
else if (thumb_base_register_rtx_p (x, mode, strict_p))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* This is PC relative data before MACHINE_DEPENDENT_REORG runs. */
|
||||||
|
else if (GET_MODE_SIZE (mode) >= 4 && CONSTANT_P (x)
|
||||||
|
&& GET_CODE (x) == SYMBOL_REF
|
||||||
|
&& CONSTANT_POOL_ADDRESS_P (x) && ! flag_pic)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* This is PC relative data after MACHINE_DEPENDENT_REORG runs. */
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* Post-inc indexing only supported for SImode and larger. */
|
||||||
|
else if (GET_CODE (x) == POST_INC && GET_MODE_SIZE (mode) >= 4
|
||||||
|
&& thumb_index_register_rtx_p (XEXP (x, 0), strict_p))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
else if (GET_CODE (x) == PLUS)
|
||||||
|
{
|
||||||
|
/* REG+REG address can be any two index registers. */
|
||||||
|
/* We disallow FRAME+REG addressing since we know that FRAME
|
||||||
|
will be replaced with STACK, and SP relative addressing only
|
||||||
|
permits SP+OFFSET. */
|
||||||
|
if (GET_MODE_SIZE (mode) <= 4
|
||||||
|
&& XEXP (x, 0) != frame_pointer_rtx
|
||||||
|
&& XEXP (x, 1) != frame_pointer_rtx
|
||||||
|
&& XEXP (x, 0) != virtual_stack_vars_rtx
|
||||||
|
&& XEXP (x, 1) != virtual_stack_vars_rtx
|
||||||
|
&& thumb_index_register_rtx_p (XEXP (x, 0), strict_p)
|
||||||
|
&& thumb_index_register_rtx_p (XEXP (x, 1), strict_p))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* REG+const has 5-7 bit offset for non-SP registers. */
|
||||||
|
else if ((thumb_index_register_rtx_p (XEXP (x, 0), strict_p)
|
||||||
|
|| XEXP (x, 0) == arg_pointer_rtx)
|
||||||
|
&& GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||||
|
&& thumb_legitimate_offset_p (mode, INTVAL (XEXP (x, 1))))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* REG+const has 10 bit offset for SP, but only SImode and
|
||||||
|
larger is supported. */
|
||||||
|
/* ??? Should probably check for DI/DFmode overflow here
|
||||||
|
just like GO_IF_LEGITIMATE_OFFSET does. */
|
||||||
|
else if (GET_CODE (XEXP (x, 0)) == REG
|
||||||
|
&& REGNO (XEXP (x, 0)) == STACK_POINTER_REGNUM
|
||||||
|
&& GET_MODE_SIZE (mode) >= 4
|
||||||
|
&& GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||||
|
&& INTVAL (XEXP (x, 1)) >= 0
|
||||||
|
&& INTVAL (XEXP (x, 1)) + GET_MODE_SIZE (mode) <= 1024
|
||||||
|
&& (INTVAL (XEXP (x, 1)) & 3) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
else if (GET_CODE (XEXP (x, 0)) == REG
|
||||||
|
&& REGNO (XEXP (x, 0)) == FRAME_POINTER_REGNUM
|
||||||
|
&& GET_MODE_SIZE (mode) >= 4
|
||||||
|
&& GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||||
|
&& (INTVAL (XEXP (x, 1)) & 3) == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return nonzero if VAL can be used as an offset in a Thumb-state address
|
||||||
|
instruction of mode MODE. */
|
||||||
|
int
|
||||||
|
thumb_legitimate_offset_p (mode, val)
|
||||||
|
enum machine_mode mode;
|
||||||
|
HOST_WIDE_INT val;
|
||||||
|
{
|
||||||
|
switch (GET_MODE_SIZE (mode))
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return val >= 0 && val < 32;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return val >= 0 && val < 64 && (val & 1) == 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (val >= 0
|
||||||
|
&& (val + GET_MODE_SIZE (mode)) <= 128
|
||||||
|
&& (val & 3) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define REG_OR_SUBREG_REG(X) \
|
#define REG_OR_SUBREG_REG(X) \
|
||||||
|
@ -1268,7 +1268,7 @@ enum reg_class
|
|||||||
&& GET_CODE (XEXP (X, 0)) == REG \
|
&& GET_CODE (XEXP (X, 0)) == REG \
|
||||||
&& XEXP (X, 0) == stack_pointer_rtx \
|
&& XEXP (X, 0) == stack_pointer_rtx \
|
||||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
|
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||||
&& ! THUMB_LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
|
&& ! thumb_legitimate_offset_p (MODE, INTVAL (XEXP (X, 1)))) \
|
||||||
{ \
|
{ \
|
||||||
rtx orig_X = X; \
|
rtx orig_X = X; \
|
||||||
X = copy_rtx (X); \
|
X = copy_rtx (X); \
|
||||||
@ -1897,6 +1897,8 @@ typedef struct
|
|||||||
|| (X) == hard_frame_pointer_rtx \
|
|| (X) == hard_frame_pointer_rtx \
|
||||||
|| (X) == arg_pointer_rtx)))
|
|| (X) == arg_pointer_rtx)))
|
||||||
|
|
||||||
|
#define REG_STRICT_P 0
|
||||||
|
|
||||||
#else /* REG_OK_STRICT */
|
#else /* REG_OK_STRICT */
|
||||||
|
|
||||||
#define ARM_REG_OK_FOR_BASE_P(X) \
|
#define ARM_REG_OK_FOR_BASE_P(X) \
|
||||||
@ -1905,6 +1907,8 @@ typedef struct
|
|||||||
#define THUMB_REG_MODE_OK_FOR_BASE_P(X, MODE) \
|
#define THUMB_REG_MODE_OK_FOR_BASE_P(X, MODE) \
|
||||||
THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
|
THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
|
||||||
|
|
||||||
|
#define REG_STRICT_P 1
|
||||||
|
|
||||||
#endif /* REG_OK_STRICT */
|
#endif /* REG_OK_STRICT */
|
||||||
|
|
||||||
/* Now define some helpers in terms of the above. */
|
/* Now define some helpers in terms of the above. */
|
||||||
@ -1932,145 +1936,32 @@ typedef struct
|
|||||||
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
|
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
|
||||||
that is a valid memory address for an instruction.
|
that is a valid memory address for an instruction.
|
||||||
The MODE argument is the machine mode for the MEM expression
|
The MODE argument is the machine mode for the MEM expression
|
||||||
that wants to use this address.
|
that wants to use this address. */
|
||||||
|
|
||||||
The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */
|
|
||||||
|
|
||||||
/* --------------------------------arm version----------------------------- */
|
|
||||||
#define ARM_BASE_REGISTER_RTX_P(X) \
|
#define ARM_BASE_REGISTER_RTX_P(X) \
|
||||||
(GET_CODE (X) == REG && ARM_REG_OK_FOR_BASE_P (X))
|
(GET_CODE (X) == REG && ARM_REG_OK_FOR_BASE_P (X))
|
||||||
|
|
||||||
#define ARM_INDEX_REGISTER_RTX_P(X) \
|
#define ARM_INDEX_REGISTER_RTX_P(X) \
|
||||||
(GET_CODE (X) == REG && ARM_REG_OK_FOR_INDEX_P (X))
|
(GET_CODE (X) == REG && ARM_REG_OK_FOR_INDEX_P (X))
|
||||||
|
|
||||||
#ifdef REG_OK_STRICT
|
#define ARM_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
|
||||||
#define ARM_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
|
{ \
|
||||||
{ \
|
if (arm_legitimate_address_p (MODE, X, REG_STRICT_P)) \
|
||||||
if (arm_legitimate_address_p (MODE, X, 1)) \
|
goto WIN; \
|
||||||
goto WIN; \
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define ARM_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
|
#define THUMB_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
|
||||||
{ \
|
{ \
|
||||||
if (arm_legitimate_address_p (MODE, X, 0)) \
|
if (thumb_legitimate_address_p (MODE, X, REG_STRICT_P)) \
|
||||||
goto WIN; \
|
goto WIN; \
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ---------------------thumb version----------------------------------*/
|
|
||||||
#define THUMB_LEGITIMATE_OFFSET(MODE, VAL) \
|
|
||||||
(GET_MODE_SIZE (MODE) == 1 ? ((unsigned HOST_WIDE_INT) (VAL) < 32) \
|
|
||||||
: GET_MODE_SIZE (MODE) == 2 ? ((unsigned HOST_WIDE_INT) (VAL) < 64 \
|
|
||||||
&& ((VAL) & 1) == 0) \
|
|
||||||
: ((VAL) >= 0 && ((VAL) + GET_MODE_SIZE (MODE)) <= 128 \
|
|
||||||
&& ((VAL) & 3) == 0))
|
|
||||||
|
|
||||||
/* The AP may be eliminated to either the SP or the FP, so we use the
|
|
||||||
least common denominator, e.g. SImode, and offsets from 0 to 64. */
|
|
||||||
|
|
||||||
/* ??? Verify whether the above is the right approach. */
|
|
||||||
|
|
||||||
/* ??? Also, the FP may be eliminated to the SP, so perhaps that
|
|
||||||
needs special handling also. */
|
|
||||||
|
|
||||||
/* ??? Look at how the mips16 port solves this problem. It probably uses
|
|
||||||
better ways to solve some of these problems. */
|
|
||||||
|
|
||||||
/* Although it is not incorrect, we don't accept QImode and HImode
|
|
||||||
addresses based on the frame pointer or arg pointer until the
|
|
||||||
reload pass starts. This is so that eliminating such addresses
|
|
||||||
into stack based ones won't produce impossible code. */
|
|
||||||
#define THUMB_GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN) \
|
|
||||||
{ \
|
|
||||||
/* ??? Not clear if this is right. Experiment. */ \
|
|
||||||
if (GET_MODE_SIZE (MODE) < 4 \
|
|
||||||
&& ! (reload_in_progress || reload_completed) \
|
|
||||||
&& ( reg_mentioned_p (frame_pointer_rtx, X) \
|
|
||||||
|| reg_mentioned_p (arg_pointer_rtx, X) \
|
|
||||||
|| reg_mentioned_p (virtual_incoming_args_rtx, X) \
|
|
||||||
|| reg_mentioned_p (virtual_outgoing_args_rtx, X) \
|
|
||||||
|| reg_mentioned_p (virtual_stack_dynamic_rtx, X) \
|
|
||||||
|| reg_mentioned_p (virtual_stack_vars_rtx, X))) \
|
|
||||||
; \
|
|
||||||
/* Accept any base register. SP only in SImode or larger. */ \
|
|
||||||
else if (GET_CODE (X) == REG \
|
|
||||||
&& THUMB_REG_MODE_OK_FOR_BASE_P (X, MODE)) \
|
|
||||||
goto WIN; \
|
|
||||||
/* This is PC relative data before MACHINE_DEPENDENT_REORG runs. */ \
|
|
||||||
else if (GET_MODE_SIZE (MODE) >= 4 && CONSTANT_P (X) \
|
|
||||||
&& GET_CODE (X) == SYMBOL_REF \
|
|
||||||
&& CONSTANT_POOL_ADDRESS_P (X) && ! flag_pic) \
|
|
||||||
goto WIN; \
|
|
||||||
/* This is PC relative data after MACHINE_DEPENDENT_REORG runs. */ \
|
|
||||||
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 WIN; \
|
|
||||||
/* Post-inc indexing only supported for SImode and larger. */ \
|
|
||||||
else if (GET_CODE (X) == POST_INC && GET_MODE_SIZE (MODE) >= 4 \
|
|
||||||
&& GET_CODE (XEXP (X, 0)) == REG \
|
|
||||||
&& THUMB_REG_OK_FOR_INDEX_P (XEXP (X, 0))) \
|
|
||||||
goto WIN; \
|
|
||||||
else if (GET_CODE (X) == PLUS) \
|
|
||||||
{ \
|
|
||||||
/* REG+REG address can be any two index registers. */ \
|
|
||||||
/* We disallow FRAME+REG addressing since we know that FRAME \
|
|
||||||
will be replaced with STACK, and SP relative addressing only \
|
|
||||||
permits SP+OFFSET. */ \
|
|
||||||
if (GET_MODE_SIZE (MODE) <= 4 \
|
|
||||||
&& GET_CODE (XEXP (X, 0)) == REG \
|
|
||||||
&& GET_CODE (XEXP (X, 1)) == REG \
|
|
||||||
&& XEXP (X, 0) != frame_pointer_rtx \
|
|
||||||
&& XEXP (X, 1) != frame_pointer_rtx \
|
|
||||||
&& XEXP (X, 0) != virtual_stack_vars_rtx \
|
|
||||||
&& XEXP (X, 1) != virtual_stack_vars_rtx \
|
|
||||||
&& THUMB_REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
|
|
||||||
&& THUMB_REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
|
|
||||||
goto WIN; \
|
|
||||||
/* REG+const has 5-7 bit offset for non-SP registers. */ \
|
|
||||||
else if (GET_CODE (XEXP (X, 0)) == REG \
|
|
||||||
&& (THUMB_REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
|
|
||||||
|| XEXP (X, 0) == arg_pointer_rtx) \
|
|
||||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
|
|
||||||
&& THUMB_LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
|
|
||||||
goto WIN; \
|
|
||||||
/* REG+const has 10 bit offset for SP, but only SImode and \
|
|
||||||
larger is supported. */ \
|
|
||||||
/* ??? Should probably check for DI/DFmode overflow here \
|
|
||||||
just like GO_IF_LEGITIMATE_OFFSET does. */ \
|
|
||||||
else if (GET_CODE (XEXP (X, 0)) == REG \
|
|
||||||
&& REGNO (XEXP (X, 0)) == STACK_POINTER_REGNUM \
|
|
||||||
&& GET_MODE_SIZE (MODE) >= 4 \
|
|
||||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
|
|
||||||
&& ((unsigned HOST_WIDE_INT) INTVAL (XEXP (X, 1)) \
|
|
||||||
+ GET_MODE_SIZE (MODE)) <= 1024 \
|
|
||||||
&& (INTVAL (XEXP (X, 1)) & 3) == 0) \
|
|
||||||
goto WIN; \
|
|
||||||
else if (GET_CODE (XEXP (X, 0)) == REG \
|
|
||||||
&& REGNO (XEXP (X, 0)) == FRAME_POINTER_REGNUM \
|
|
||||||
&& GET_MODE_SIZE (MODE) >= 4 \
|
|
||||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
|
|
||||||
&& (INTVAL (XEXP (X, 1)) & 3) == 0) \
|
|
||||||
goto WIN; \
|
|
||||||
} \
|
|
||||||
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 WIN; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
|
||||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN) \
|
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN) \
|
||||||
if (TARGET_ARM) \
|
if (TARGET_ARM) \
|
||||||
ARM_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN) \
|
ARM_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN) \
|
||||||
else /* if (TARGET_THUMB) */ \
|
else /* if (TARGET_THUMB) */ \
|
||||||
THUMB_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN)
|
THUMB_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN)
|
||||||
/* ------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* Try machine-dependent ways of modifying an illegitimate address
|
/* Try machine-dependent ways of modifying an illegitimate address
|
||||||
to be legitimate. If we find one, return the new, valid address.
|
to be legitimate. If we find one, return the new, valid address.
|
||||||
|
Loading…
Reference in New Issue
Block a user