aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2007-03-01 22:58:40 +0000
committerPaul Brook <pbrook@gcc.gnu.org>2007-03-01 22:58:40 +0000
commitfe2d934b4b7bdb0e3f72b575f90041e4e9b7e140 (patch)
treeea80e92e5fd211797f4d35d15f47aa342c1aa013 /gcc
parent2711355fbc306e7e0f59b3247943614eba4a382b (diff)
downloadgcc-fe2d934b4b7bdb0e3f72b575f90041e4e9b7e140.zip
gcc-fe2d934b4b7bdb0e3f72b575f90041e4e9b7e140.tar.gz
gcc-fe2d934b4b7bdb0e3f72b575f90041e4e9b7e140.tar.bz2
arm.c (arm_legitimate_index_p): Limit iWMMXt addressing modes to LDRD for DImode.
2007-03-01 Paul Brook <paul@codesourcery.com> * config/arm/arm.c (arm_legitimate_index_p): Limit iWMMXt addressing modes to LDRD for DImode. (output_move_double): Fixup out of range ldrd/strd. (vfp_secondary_reload_class): Rename... (coproc_secondary_reload_class): ... to this. Add wb argument. * config/arm/arm.h (SECONDARY_OUTPUT_RELOAD_CLASS): Use coproc_secondary_reload_class for CLASS_IWMMXT. (SECONDARY_INPUT_RELOAD_CLASS): Ditto. * arm-protos.h (coproc_secondary_reload_class): Update prototype. From-SVN: r122437
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/arm/arm-protos.h3
-rw-r--r--gcc/config/arm/arm.c74
-rw-r--r--gcc/config/arm/arm.h12
4 files changed, 85 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9c75bc2..c3d0a7e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2007-03-01 Paul Brook <paul@codesourcery.com>
+
+ * config/arm/arm.c (arm_legitimate_index_p): Limit iWMMXt addressing
+ modes to LDRD for DImode.
+ (output_move_double): Fixup out of range ldrd/strd.
+ (vfp_secondary_reload_class): Rename...
+ (coproc_secondary_reload_class): ... to this. Add wb argument.
+ * config/arm/arm.h (SECONDARY_OUTPUT_RELOAD_CLASS): Use
+ coproc_secondary_reload_class for CLASS_IWMMXT.
+ (SECONDARY_INPUT_RELOAD_CLASS): Ditto.
+ * arm-protos.h (coproc_secondary_reload_class): Update prototype.
+
2007-03-01 Zdenek Dvorak <dvorakz@suse.cz>
* tree-ssa-loop-prefetch.c (determine_unroll_factor): Bound the unroll
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 6a9a549..9d24cd2 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -68,7 +68,8 @@ extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int,
int);
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);
+extern enum reg_class coproc_secondary_reload_class (enum machine_mode, rtx,
+ bool);
extern bool arm_tls_referenced_p (rtx);
extern int cirrus_memory_offset (rtx);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 6998332..74a9e00 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -3922,10 +3922,15 @@ thumb2_legitimate_index_p (enum machine_mode mode, rtx index, int strict_p)
&& (INTVAL (index) & 3) == 0);
if (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (mode))
- return (code == CONST_INT
- && INTVAL (index) < 1024
- && INTVAL (index) > -1024
- && (INTVAL (index) & 3) == 0);
+ {
+ /* For DImode assume values will usually live in core regs
+ and only allow LDRD addressing modes. */
+ if (!TARGET_LDRD || mode != DImode)
+ 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))
@@ -5764,12 +5769,12 @@ arm_eliminable_register (rtx x)
}
/* Return GENERAL_REGS if a scratch register required to reload x to/from
- VFP registers. Otherwise return NO_REGS. */
+ coprocessor registers. Otherwise return NO_REGS. */
enum reg_class
-vfp_secondary_reload_class (enum machine_mode mode, rtx x)
+coproc_secondary_reload_class (enum machine_mode mode, rtx x, bool wb)
{
- if (arm_coproc_mem_operand (x, FALSE) || s_register_operand (x, mode))
+ if (arm_coproc_mem_operand (x, wb) || s_register_operand (x, mode))
return NO_REGS;
return GENERAL_REGS;
@@ -9146,12 +9151,37 @@ output_move_double (rtx *operands)
output_asm_insn ("ldr%(d%)\t%0, [%1] @split", otherops);
}
else
- output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops);
+ {
+ /* IWMMXT allows offsets larger than ldrd can handle,
+ fix these up with a pair of ldr. */
+ if (GET_CODE (otherops[2]) == CONST_INT
+ && (INTVAL(otherops[2]) <= -256
+ || INTVAL(otherops[2]) >= 256))
+ {
+ output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
+ otherops[0] = gen_rtx_REG (SImode, 1 + reg0);
+ output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+ }
+ else
+ output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops);
+ }
}
else
{
- /* We only allow constant increments, so this is safe. */
- output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops);
+ /* IWMMXT allows offsets larger than ldrd can handle,
+ fix these up with a pair of ldr. */
+ if (GET_CODE (otherops[2]) == CONST_INT
+ && (INTVAL(otherops[2]) <= -256
+ || INTVAL(otherops[2]) >= 256))
+ {
+ otherops[0] = gen_rtx_REG (SImode, 1 + reg0);
+ output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+ otherops[0] = operands[0];
+ output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
+ }
+ else
+ /* We only allow constant increments, so this is safe. */
+ output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops);
}
break;
@@ -9289,7 +9319,29 @@ output_move_double (rtx *operands)
otherops[1] = XEXP (XEXP (XEXP (operands[0], 0), 1), 0);
otherops[2] = XEXP (XEXP (XEXP (operands[0], 0), 1), 1);
- if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
+ /* IWMMXT allows offsets larger than ldrd can handle,
+ fix these up with a pair of ldr. */
+ if (GET_CODE (otherops[2]) == CONST_INT
+ && (INTVAL(otherops[2]) <= -256
+ || INTVAL(otherops[2]) >= 256))
+ {
+ rtx reg1;
+ reg1 = gen_rtx_REG (SImode, 1 + REGNO (operands[1]));
+ if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
+ {
+ output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
+ otherops[0] = reg1;
+ output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+ }
+ else
+ {
+ otherops[0] = reg1;
+ output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+ otherops[0] = operands[1];
+ output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
+ }
+ }
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
output_asm_insn ("str%(d%)\t%0, [%1, %2]!", otherops);
else
output_asm_insn ("str%(d%)\t%0, [%1], %2", otherops);
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 318d4f4..d09bb73 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1121,10 +1121,12 @@ enum reg_class
or out of a register in CLASS in MODE. If it can be done directly,
NO_REGS is returned. */
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
- /* Restrict which direct reloads are allowed for VFP regs. */ \
+ /* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \
((TARGET_VFP && TARGET_HARD_FLOAT \
&& (CLASS) == VFP_REGS) \
- ? vfp_secondary_reload_class (MODE, X) \
+ ? coproc_secondary_reload_class (MODE, X, FALSE) \
+ : (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) \
+ ? coproc_secondary_reload_class (MODE, X, TRUE) \
: TARGET_32BIT \
? (((MODE) == HImode && ! arm_arch4 && true_regnum (X) == -1) \
? GENERAL_REGS : NO_REGS) \
@@ -1132,10 +1134,12 @@ enum reg_class
/* If we need to load shorts byte-at-a-time, then we need a scratch. */
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
- /* Restrict which direct reloads are allowed for VFP regs. */ \
+ /* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \
((TARGET_VFP && TARGET_HARD_FLOAT \
&& (CLASS) == VFP_REGS) \
- ? vfp_secondary_reload_class (MODE, X) : \
+ ? coproc_secondary_reload_class (MODE, X, FALSE) : \
+ (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) ? \
+ coproc_secondary_reload_class (MODE, X, TRUE) : \
/* Cannot load constants into Cirrus registers. */ \
(TARGET_MAVERICK && TARGET_HARD_FLOAT \
&& (CLASS) == CIRRUS_REGS \