From bca653c58c8d45e2bd6ccb482ea52f6355aef8ea Mon Sep 17 00:00:00 2001 From: rearnsha Date: Wed, 25 Feb 2004 17:03:27 +0000 Subject: [PATCH] * arm.c (thumb_legitimize_address): New function. * arm-protos.h: Prototype it. * arm.h (THUMB_LEGITIMIZE_ADDRESS): Define. (LEGITIMIZE_ADDRESS): Use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@78437 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 +++++ gcc/config/arm/arm-protos.h | 1 + gcc/config/arm/arm.c | 68 +++++++++++++++++++++++++++++++++++++++++++++ gcc/config/arm/arm.h | 13 ++++----- 4 files changed, 82 insertions(+), 7 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4405cd97140..8f405e75787 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2004-02-25 Richard Earnshaw + + * 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 * reload1.c (reload): Only spill eliminable register with multiple diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 25f563109ab..4c0575d5664 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -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); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 98c05cb6228..0a61e1bc654 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -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) \ diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 320bee05299..5b85e75cdbf 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -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) -- 2.11.4.GIT