arm.c (thumb_legitimize_address): New function.

* arm.c (thumb_legitimize_address): New function.
* arm-protos.h: Prototype it.
* arm.h (THUMB_LEGITIMIZE_ADDRESS): Define.
(LEGITIMIZE_ADDRESS): Use it.

From-SVN: r78437
This commit is contained in:
Richard Earnshaw 2004-02-25 17:03:27 +00:00 committed by Richard Earnshaw
parent 8a7988f51a
commit 6f5b4f3e5a
4 changed files with 82 additions and 7 deletions

View file

@ -1,3 +1,10 @@
2004-02-25 Richard Earnshaw <rearnsha@arm.com>
* arm.c (thumb_legitimize_address): New function.
* arm-protos.h: Prototype it.
* arm.h (THUMB_LEGITIMIZE_ADDRESS): Define.
(LEGITIMIZE_ADDRESS): Use it.
2004-02-25 J"orn Rennecke <joern.rennecke@superh.com>
* reload1.c (reload): Only spill eliminable register with multiple

View file

@ -54,6 +54,7 @@ extern int arm_legitimate_address_p (enum machine_mode, rtx, int);
extern int thumb_legitimate_address_p (enum machine_mode, rtx, int);
extern int thumb_legitimate_offset_p (enum machine_mode, HOST_WIDE_INT);
extern rtx arm_legitimize_address (rtx, rtx, enum machine_mode);
extern rtx thumb_legitimize_address (rtx, rtx, enum machine_mode);
extern int arm_const_double_rtx (rtx);
extern int neg_const_double_rtx_ok_for_fpa (rtx);
extern enum reg_class vfp_secondary_reload_class (enum machine_mode, rtx);

View file

@ -3232,6 +3232,74 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
return x;
}
/* Try machine-dependent ways of modifying an illegitimate Thumb address
to be legitimate. If we find one, return the new, valid address. */
rtx
thumb_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
{
if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& (INTVAL (XEXP (x, 1)) >= 32 * GET_MODE_SIZE (mode)
|| INTVAL (XEXP (x, 1)) < 0))
{
rtx xop0 = XEXP (x, 0);
rtx xop1 = XEXP (x, 1);
HOST_WIDE_INT offset = INTVAL (xop1);
/* Try and fold the offset into a biasing of the base register and
then offsetting that. Don't do this when optimizing for space
since it can cause too many CSEs. */
if (optimize_size && offset >= 0
&& offset < 256 + 31 * GET_MODE_SIZE (mode))
{
HOST_WIDE_INT delta;
if (offset >= 256)
delta = offset - (256 - GET_MODE_SIZE (mode));
else if (offset < 32 * GET_MODE_SIZE (mode) + 8)
delta = 31 * GET_MODE_SIZE (mode);
else
delta = offset & (~31 * GET_MODE_SIZE (mode));
xop0 = force_operand (plus_constant (xop0, offset - delta),
NULL_RTX);
x = plus_constant (xop0, delta);
}
else if (offset < 0 && offset > -256)
/* Small negative offsets are best done with a subtract before the
dereference, forcing these into a register normally takes two
instructions. */
x = force_operand (x, NULL_RTX);
else
{
/* For the remaining cases, force the constant into a register. */
xop1 = force_reg (SImode, xop1);
x = gen_rtx_PLUS (SImode, xop0, xop1);
}
}
else if (GET_CODE (x) == PLUS
&& s_register_operand (XEXP (x, 1), SImode)
&& !s_register_operand (XEXP (x, 0), SImode))
{
rtx xop0 = force_operand (XEXP (x, 0), NULL_RTX);
x = gen_rtx_PLUS (SImode, xop0, XEXP (x, 1));
}
if (flag_pic)
{
/* We need to find and carefully transform any SYMBOL and LABEL
references; so go back to the original address expression. */
rtx new_x = legitimize_pic_address (orig_x, mode, NULL_RTX);
if (new_x != orig_x)
x = new_x;
}
return x;
}
#define REG_OR_SUBREG_REG(X) \

View file

@ -2361,15 +2361,11 @@ typedef struct
#define ARM_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
do { \
X = arm_legitimize_address (X, OLDX, MODE); \
\
if (memory_address_p (MODE, X)) \
goto WIN; \
} while (0)
#define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
do { \
if (flag_pic) \
(X) = legitimize_pic_address (OLDX, MODE, NULL_RTX); \
#define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
do { \
X = thumb_legitimize_address (X, OLDX, MODE); \
} while (0)
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
@ -2378,6 +2374,9 @@ do { \
ARM_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN); \
else \
THUMB_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN); \
\
if (memory_address_p (MODE, X)) \
goto WIN; \
} while (0)
/* Go to LABEL if ADDR (a legitimate address expression)