Index: config/arm/arm-protos.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/arm/arm-protos.h,v retrieving revision 1.62 diff -p -r1.62 arm-protos.h *** config/arm/arm-protos.h 3 Feb 2004 14:44:10 -0000 1.62 --- config/arm/arm-protos.h 25 Feb 2004 16:59:53 -0000 *************** extern int arm_legitimate_address_p (en *** 54,59 **** --- 54,60 ---- 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); Index: config/arm/arm.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v retrieving revision 1.334 diff -p -r1.334 arm.c *** config/arm/arm.c 25 Feb 2004 12:30:13 -0000 1.334 --- config/arm/arm.c 25 Feb 2004 16:59:54 -0000 *************** arm_legitimize_address (rtx x, rtx orig_ *** 3232,3237 **** --- 3232,3305 ---- 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) \ Index: config/arm/arm.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.h,v retrieving revision 1.223 diff -p -r1.223 arm.h *** config/arm/arm.h 19 Feb 2004 10:56:55 -0000 1.223 --- config/arm/arm.h 25 Feb 2004 16:59:54 -0000 *************** typedef struct *** 2361,2375 **** #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); \ } while (0) #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ --- 2361,2371 ---- #define ARM_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ do { \ X = arm_legitimize_address (X, OLDX, MODE); \ } while (0) ! #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) \ *************** do { \ *** 2378,2383 **** --- 2374,2382 ---- 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)