aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2004-05-05 23:11:55 +0000
committerPaul Brook <pbrook@gcc.gnu.org>2004-05-05 23:11:55 +0000
commitfdd695fdb4650c6221ed38e952fa0fe00a214afa (patch)
tree55df21a18e500fcafb6fcaf071eb2fc50186dc76 /gcc
parent74e94435cc57b47e9cd2a30e3bccd73c2b719102 (diff)
downloadgcc-fdd695fdb4650c6221ed38e952fa0fe00a214afa.zip
gcc-fdd695fdb4650c6221ed38e952fa0fe00a214afa.tar.gz
gcc-fdd695fdb4650c6221ed38e952fa0fe00a214afa.tar.bz2
arm-protots.h (vfp_mem_operand): Rename ...
* config/arm/arm-protots.h (vfp_mem_operand): Rename ... (arm_coproc_mem_operand): ... To this. * config/arm/arm.c (arm_legitimate_address_p): Allow ldrd modes. (arm_legitimate_index_p): Ditto. (vfp_mem_operand): Rename ... (arm_coproc_mem_operand): ... To this. Handle writeback modes. (vfp_secondary_reload_class): Use it. (output_move_double): Use doubleword load/store instructions. (arm_hard_regno_mode_ok): Only allow even reg pairs for ldrd. * config/arm/arm.h (TARGET_LDRD): Define. (EXTRA_CONSTRAINT_STR_ARM): Add 'Uy'. * config/gcc/arm/arm.md (arm_movdi): Allow all valid memory operands. New splitter for invalid doubleword loads. * config/arm/iwmmxt.md (iwmmxt_arm_movdi): Use Uy constraint. * config/arm/vfp.md (arm_movdi_vfp): Allow all valid memory operands. * doc/md.texi: Document Uy constraint. From-SVN: r81543
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/config/arm/arm-protos.h2
-rw-r--r--gcc/config/arm/arm.c281
-rw-r--r--gcc/config/arm/arm.h5
-rw-r--r--gcc/config/arm/arm.md22
-rw-r--r--gcc/config/arm/iwmmxt.md4
-rw-r--r--gcc/config/arm/vfp.md4
-rw-r--r--gcc/doc/md.texi3
8 files changed, 245 insertions, 95 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 44e58d7..05aa794 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,22 @@
+2004-05-06 Paul Brook <paul@codesourcery.com>
+
+ * config/arm/arm-protots.h (vfp_mem_operand): Rename ...
+ (arm_coproc_mem_operand): ... To this.
+ * config/arm/arm.c (arm_legitimate_address_p): Allow ldrd modes.
+ (arm_legitimate_index_p): Ditto.
+ (vfp_mem_operand): Rename ...
+ (arm_coproc_mem_operand): ... To this. Handle writeback modes.
+ (vfp_secondary_reload_class): Use it.
+ (output_move_double): Use doubleword load/store instructions.
+ (arm_hard_regno_mode_ok): Only allow even reg pairs for ldrd.
+ * config/arm/arm.h (TARGET_LDRD): Define.
+ (EXTRA_CONSTRAINT_STR_ARM): Add 'Uy'.
+ * config/gcc/arm/arm.md (arm_movdi): Allow all valid memory operands.
+ New splitter for invalid doubleword loads.
+ * config/arm/iwmmxt.md (iwmmxt_arm_movdi): Use Uy constraint.
+ * config/arm/vfp.md (arm_movdi_vfp): Allow all valid memory operands.
+ * doc/md.texi: Document Uy constraint.
+
2004-05-05 Jan Hubicka <jh@suse.cz>
PR opt/14980
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 0359fe7..0605803 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -100,7 +100,7 @@ extern int cirrus_general_operand (rtx, enum machine_mode);
extern int cirrus_register_operand (rtx, enum machine_mode);
extern int cirrus_shift_const (rtx, enum machine_mode);
extern int cirrus_memory_offset (rtx);
-extern int vfp_mem_operand (rtx);
+extern int arm_coproc_mem_operand (rtx, bool);
extern int vfp_compare_operand (rtx, enum machine_mode);
extern int arm_float_compare_operand (rtx, enum machine_mode);
extern int arm_no_early_store_addr_dep (rtx, rtx);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 02864fb..961dff2 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -2983,25 +2983,44 @@ int
arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer,
int strict_p)
{
+ bool use_ldrd;
+ enum rtx_code code = GET_CODE (x);
+
if (arm_address_register_rtx_p (x, strict_p))
return 1;
- else if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_DEC)
+ use_ldrd = (TARGET_LDRD
+ && (mode == DImode
+ || (mode == DFmode && (TARGET_SOFT_FLOAT || TARGET_VFP))));
+
+ if (code == POST_INC || code == PRE_DEC
+ || ((code == PRE_INC || code == POST_DEC)
+ && (use_ldrd || GET_MODE_SIZE (mode) <= 4)))
return arm_address_register_rtx_p (XEXP (x, 0), strict_p);
- else if ((GET_CODE (x) == POST_MODIFY || GET_CODE (x) == PRE_MODIFY)
- && GET_MODE_SIZE (mode) <= 4
+ else if ((code == POST_MODIFY || code == PRE_MODIFY)
&& arm_address_register_rtx_p (XEXP (x, 0), strict_p)
&& GET_CODE (XEXP (x, 1)) == PLUS
&& rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
- return arm_legitimate_index_p (mode, XEXP (XEXP (x, 1), 1), outer,
- strict_p);
+ {
+ rtx addend = XEXP (XEXP (x, 1), 1);
+
+ /* Don't allow ldrd post increment by register becuase it's hard
+ to fixup invalid register choices. */
+ if (use_ldrd
+ && GET_CODE (x) == POST_MODIFY
+ && GET_CODE (addend) == REG)
+ return 0;
+
+ return ((use_ldrd || GET_MODE_SIZE (mode) <= 4)
+ && arm_legitimate_index_p (mode, addend, outer, strict_p));
+ }
/* After reload constants split into minipools will have addresses
from a LABEL_REF. */
else if (reload_completed
- && (GET_CODE (x) == LABEL_REF
- || (GET_CODE (x) == CONST
+ && (code == LABEL_REF
+ || (code == 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)))
@@ -3010,38 +3029,7 @@ arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer,
else if (mode == TImode)
return 0;
- else if (mode == DImode || (TARGET_SOFT_FLOAT && mode == DFmode))
- {
- if (GET_CODE (x) == PLUS
- && arm_address_register_rtx_p (XEXP (x, 0), strict_p)
- && GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
-
- if (val == 4 || val == -4 || val == -8)
- return 1;
- }
- }
-
- else if (TARGET_HARD_FLOAT && TARGET_VFP && mode == DFmode)
- {
- if (GET_CODE (x) == PLUS
- && arm_address_register_rtx_p (XEXP (x, 0), strict_p)
- && GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
-
- /* ??? valid arm offsets are a subset of VFP offsets.
- For now only allow this subset. Proper fix is to add an
- additional memory constraint for arm address modes.
- Alternatively allow full vfp addressing and let
- output_move_double fix it up with a sub-optimal sequence. */
- if (val == 4 || val == -4 || val == -8)
- return 1;
- }
- }
-
- else if (GET_CODE (x) == PLUS)
+ else if (code == PLUS)
{
rtx xop0 = XEXP (x, 0);
rtx xop1 = XEXP (x, 1);
@@ -3065,17 +3053,12 @@ arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer,
#endif
else if (GET_MODE_CLASS (mode) != MODE_FLOAT
- && GET_CODE (x) == SYMBOL_REF
+ && code == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (x)
&& ! (flag_pic
&& symbol_mentioned_p (get_pool_constant (x))))
return 1;
- else if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == POST_DEC)
- && (GET_MODE_SIZE (mode) <= 4)
- && arm_address_register_rtx_p (XEXP (x, 0), strict_p))
- return 1;
-
return 0;
}
@@ -3097,16 +3080,31 @@ arm_legitimate_index_p (enum machine_mode mode, rtx index, RTX_CODE outer,
&& INTVAL (index) > -1024
&& (INTVAL (index) & 3) == 0);
- if (arm_address_register_rtx_p (index, strict_p)
- && GET_MODE_SIZE (mode) <= 4)
- return 1;
-
if (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (mode))
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))
+ return 1;
+
+ if (mode == DImode || mode == DFmode)
+ {
+ if (code == CONST_INT)
+ {
+ HOST_WIDE_INT val = INTVAL (index);
+
+ if (TARGET_LDRD)
+ return val > -256 && val < 256;
+ else
+ return val == 4 || val == -4 || val == -8;
+ }
+
+ return TARGET_LDRD && arm_address_register_rtx_p (index, strict_p);
+ }
+
if (GET_MODE_SIZE (mode) <= 4
&& ! (arm_arch4
&& (mode == HImode
@@ -4614,14 +4612,15 @@ cirrus_shift_const (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
}
-/* Return TRUE if OP is a valid VFP memory address pattern. */
-/* Copied from cirrus_memory_offset but with restricted offset range. */
+/* Return TRUE if OP is a valid VFP memory address pattern.
+ WB if true if writeback address modes are allowed. */
int
-vfp_mem_operand (rtx op)
+arm_coproc_mem_operand (rtx op, bool wb)
{
- /* Reject eliminable registers. */
+ rtx ind;
+ /* Reject eliminable registers. */
if (! (reload_in_progress || reload_completed)
&& ( reg_mentioned_p (frame_pointer_rtx, op)
|| reg_mentioned_p (arg_pointer_rtx, op)
@@ -4632,35 +4631,49 @@ vfp_mem_operand (rtx op)
return FALSE;
/* Constants are converted into offsets from labels. */
- if (GET_CODE (op) == MEM)
- {
- rtx ind;
-
- ind = XEXP (op, 0);
+ if (GET_CODE (op) != MEM)
+ return FALSE;
- if (reload_completed
- && (GET_CODE (ind) == LABEL_REF
- || (GET_CODE (ind) == CONST
- && GET_CODE (XEXP (ind, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (ind, 0), 0)) == LABEL_REF
- && GET_CODE (XEXP (XEXP (ind, 0), 1)) == CONST_INT)))
- return TRUE;
+ ind = XEXP (op, 0);
- /* Match: (mem (reg)). */
- if (GET_CODE (ind) == REG)
- return arm_address_register_rtx_p (ind, 0);
+ if (reload_completed
+ && (GET_CODE (ind) == LABEL_REF
+ || (GET_CODE (ind) == CONST
+ && GET_CODE (XEXP (ind, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (ind, 0), 0)) == LABEL_REF
+ && GET_CODE (XEXP (XEXP (ind, 0), 1)) == CONST_INT)))
+ return TRUE;
- /* Match:
- (mem (plus (reg)
- (const))). */
- if (GET_CODE (ind) == PLUS
- && GET_CODE (XEXP (ind, 0)) == REG
- && REG_MODE_OK_FOR_BASE_P (XEXP (ind, 0), VOIDmode)
- && GET_CODE (XEXP (ind, 1)) == CONST_INT
- && INTVAL (XEXP (ind, 1)) > -1024
- && INTVAL (XEXP (ind, 1)) < 1024)
- return TRUE;
- }
+ /* Match: (mem (reg)). */
+ if (GET_CODE (ind) == REG)
+ return arm_address_register_rtx_p (ind, 0);
+
+ /* Autoincremment addressing modes. */
+ if (wb
+ && (GET_CODE (ind) == PRE_INC
+ || GET_CODE (ind) == POST_INC
+ || GET_CODE (ind) == PRE_DEC
+ || GET_CODE (ind) == POST_DEC))
+ return arm_address_register_rtx_p (XEXP (ind, 0), 0);
+
+ if (wb
+ && (GET_CODE (ind) == POST_MODIFY || GET_CODE (ind) == PRE_MODIFY)
+ && arm_address_register_rtx_p (XEXP (ind, 0), 0)
+ && GET_CODE (XEXP (ind, 1)) == PLUS
+ && rtx_equal_p (XEXP (XEXP (ind, 1), 0), XEXP (ind, 0)))
+ ind = XEXP (ind, 1);
+
+ /* Match:
+ (plus (reg)
+ (const)). */
+ if (GET_CODE (ind) == PLUS
+ && GET_CODE (XEXP (ind, 0)) == REG
+ && REG_MODE_OK_FOR_BASE_P (XEXP (ind, 0), VOIDmode)
+ && GET_CODE (XEXP (ind, 1)) == CONST_INT
+ && INTVAL (XEXP (ind, 1)) > -1024
+ && INTVAL (XEXP (ind, 1)) < 1024
+ && (INTVAL (XEXP (ind, 1)) & 3) == 0)
+ return TRUE;
return FALSE;
}
@@ -4684,7 +4697,7 @@ vfp_compare_operand (rtx op, enum machine_mode mode)
enum reg_class
vfp_secondary_reload_class (enum machine_mode mode, rtx x)
{
- if (vfp_mem_operand (x) || s_register_operand (x, mode))
+ if (arm_coproc_mem_operand (x, FALSE) || s_register_operand (x, mode))
return NO_REGS;
return GENERAL_REGS;
@@ -8384,7 +8397,9 @@ output_move_double (rtx *operands)
break;
case PRE_INC:
- abort (); /* Should never happen now. */
+ if (!TARGET_LDRD)
+ abort (); /* Should never happen now. */
+ output_asm_insn ("ldr%?d\t%0, [%m1, #8]!", operands);
break;
case PRE_DEC:
@@ -8396,7 +8411,33 @@ output_move_double (rtx *operands)
break;
case POST_DEC:
- abort (); /* Should never happen now. */
+ if (!TARGET_LDRD)
+ abort (); /* Should never happen now. */
+ output_asm_insn ("ldr%?d\t%0, [%m1], #-8", operands);
+ break;
+
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ otherops[0] = operands[0];
+ otherops[1] = XEXP (XEXP (XEXP (operands[1], 0), 1), 0);
+ otherops[2] = XEXP (XEXP (XEXP (operands[1], 0), 1), 1);
+
+ if (GET_CODE (XEXP (operands[1], 0)) == PRE_MODIFY)
+ {
+ if (reg_overlap_mentioned_p (otherops[0], otherops[2]))
+ {
+ /* Registers overlap so split out the increment. */
+ output_asm_insn ("add%?\t%1, %1, %2", otherops);
+ output_asm_insn ("ldr%?d\t%0, [%1] @split", 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);
+ }
break;
case LABEL_REF:
@@ -8429,7 +8470,41 @@ output_move_double (rtx *operands)
output_asm_insn ("ldm%?ib\t%1, %M0", otherops);
return "";
}
-
+ }
+ if (TARGET_LDRD
+ && (GET_CODE (otherops[2]) == REG
+ || (GET_CODE (otherops[2]) == CONST_INT
+ && INTVAL (otherops[2]) > -256
+ && INTVAL (otherops[2]) < 256)))
+ {
+ if (reg_overlap_mentioned_p (otherops[0],
+ otherops[2]))
+ {
+ /* Swap base and index registers over to
+ avoid a conflict. */
+ otherops[1] = XEXP (XEXP (operands[1], 0), 1);
+ otherops[2] = XEXP (XEXP (operands[1], 0), 0);
+
+ }
+ /* If both registers conflict, it will usually
+ have been fixed by a splitter. */
+ if (reg_overlap_mentioned_p (otherops[0],
+ otherops[2]))
+ {
+ output_asm_insn ("add%?\t%1, %1, %2", otherops);
+ output_asm_insn ("ldr%?d\t%0, [%1]",
+ otherops);
+ return "";
+ }
+ else
+ {
+ output_asm_insn ("ldr%?d\t%0, [%1, %2]",
+ otherops);
+ return "";
+ }
+ }
+ if (GET_CODE (otherops[2]) == CONST_INT)
+ {
if (!(const_ok_for_arm (INTVAL (otherops[2]))))
output_asm_insn ("sub%?\t%0, %1, #%n2", otherops);
else
@@ -8475,7 +8550,9 @@ output_move_double (rtx *operands)
break;
case PRE_INC:
- abort (); /* Should never happen now. */
+ if (!TARGET_LDRD)
+ abort (); /* Should never happen now. */
+ output_asm_insn ("str%?d\t%1, [%m0, #8]!", operands);
break;
case PRE_DEC:
@@ -8487,11 +8564,26 @@ output_move_double (rtx *operands)
break;
case POST_DEC:
- abort (); /* Should never happen now. */
+ if (!TARGET_LDRD)
+ abort (); /* Should never happen now. */
+ output_asm_insn ("str%?d\t%1, [%m0], #-8", operands);
+ break;
+
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ otherops[0] = operands[1];
+ 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)
+ output_asm_insn ("str%?d\t%0, [%1, %2]!", otherops);
+ else
+ output_asm_insn ("str%?d\t%0, [%1], %2", otherops);
break;
case PLUS:
- if (GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT)
+ otherops[2] = XEXP (XEXP (operands[0], 0), 1);
+ if (GET_CODE (otherops[2]) == CONST_INT)
{
switch ((int) INTVAL (XEXP (XEXP (operands[0], 0), 1)))
{
@@ -8508,6 +8600,17 @@ output_move_double (rtx *operands)
return "";
}
}
+ if (TARGET_LDRD
+ && (GET_CODE (otherops[2]) == REG
+ || (GET_CODE (otherops[2]) == CONST_INT
+ && INTVAL (otherops[2]) > -256
+ && INTVAL (otherops[2]) < 256)))
+ {
+ otherops[0] = operands[1];
+ otherops[1] = XEXP (XEXP (operands[0], 0), 0);
+ output_asm_insn ("str%?d\t%0, [%1, %2]", otherops);
+ return "";
+ }
/* Fall through */
default:
@@ -11393,9 +11496,11 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
if (IS_IWMMXT_REGNUM (regno))
return VALID_IWMMXT_REG_MODE (mode);
+ /* We allow any value to be stored in the general registers.
+ Restrict doubleword quantities to even register pairs so that we can
+ use ldrd. */
if (regno <= LAST_ARM_REGNUM)
- /* We allow any value to be stored in the general registers. */
- return 1;
+ return !(TARGET_LDRD && GET_MODE_SIZE (mode) > 4 && (regno & 1) != 0);
if ( regno == FRAME_POINTER_REGNUM
|| regno == ARG_POINTER_REGNUM)
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index f64d338..c870af0 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -306,6 +306,7 @@ extern GTY(()) rtx aof_pic_label;
? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \
: (target_flags & THUMB_FLAG_BACKTRACE))
#define TARGET_CIRRUS_FIX_INVALID_INSNS (target_flags & CIRRUS_FIX_INVALID_INSNS)
+#define TARGET_LDRD (arm_arch5e && ARM_DOUBLEWORD_ALIGN)
/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */
#ifndef SUBTARGET_SWITCHES
@@ -1292,6 +1293,7 @@ enum reg_class
accessed without using a load.
'U' Prefixes an extended memory constraint where:
'Uv' is an address valid for VFP load/store insns.
+ 'Uy' is an address valid for iwmmxt load/store insns.
'Uq' is an address valid for ldrsb. */
#define EXTRA_CONSTRAINT_STR_ARM(OP, C, STR) \
@@ -1302,7 +1304,8 @@ enum reg_class
&& CONSTANT_POOL_ADDRESS_P (XEXP (OP, 0))) : \
((C) == 'S') ? (optimize > 0 && CONSTANT_ADDRESS_P (OP)) : \
((C) == 'T') ? cirrus_memory_offset (OP) : \
- ((C) == 'U' && (STR)[1] == 'v') ? vfp_mem_operand (OP) : \
+ ((C) == 'U' && (STR)[1] == 'v') ? arm_coproc_mem_operand (OP, FALSE) : \
+ ((C) == 'U' && (STR)[1] == 'y') ? arm_coproc_mem_operand (OP, TRUE) : \
((C) == 'U' && (STR)[1] == 'q') \
? arm_extendqisi_mem_op (OP, GET_MODE (OP)) \
: 0)
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 7255b32..554b332 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -4073,7 +4073,7 @@
)
(define_insn "*arm_movdi"
- [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
+ [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
(match_operand:DI 1 "di_operand" "rIK,mi,r"))]
"TARGET_ARM
&& !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
@@ -4087,6 +4087,26 @@
(set_attr "neg_pool_range" "*,1008,*")]
)
+;; We can't actually do base+index doubleword loads if the index and
+;; destination overlap. Split here so that we at least have chance to
+;; schedule.
+(define_split
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "s_register_operand" ""))))]
+ "TARGET_LDRD
+ && reg_overlap_mentioned_p (operands[0], operands[1])
+ && reg_overlap_mentioned_p (operands[0], operands[2])"
+ [(set (match_dup 4)
+ (plus:SI (match_dup 1)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (mem:DI (match_dup 4)))]
+ "
+ operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
+ "
+)
+
;;; ??? This should have alternatives for constants.
;;; ??? This was originally identical to the movdf_insn pattern.
;;; ??? The 'i' constraint looks funny, but it should always be replaced by
diff --git a/gcc/config/arm/iwmmxt.md b/gcc/config/arm/iwmmxt.md
index e1b0053..758847f 100644
--- a/gcc/config/arm/iwmmxt.md
+++ b/gcc/config/arm/iwmmxt.md
@@ -64,8 +64,8 @@
[(set_attr "predicable" "yes")])
(define_insn "*iwmmxt_arm_movdi"
- [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>,y,y,yr,y,yrm")
- (match_operand:DI 1 "di_operand" "rIK,mi,r ,y,yr,y,yrm,y"))]
+ [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, m,y,y,yr,y,yrUy")
+ (match_operand:DI 1 "di_operand" "rIK,mi,r,y,yr,y,yrUy,y"))]
"TARGET_REALLY_IWMMXT"
"*
{
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index 6f7e2a7..7008ab4 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -136,8 +136,8 @@
;; DImode moves
(define_insn "*arm_movdi_vfp"
- [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r,o<>,w,r,w,w ,Uv")
- (match_operand:DI 1 "di_operand" "rIK,mi,r ,r,w,w,Uvi,w"))]
+ [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r,m,w,r,w,w, Uv")
+ (match_operand:DI 1 "di_operand" "rIK,mi,r,r,w,w,Uvi,w"))]
"TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
"*
switch (which_alternative)
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 5cff95b..b29f8b5 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -1363,6 +1363,9 @@ A symbol in the text segment of the current file
@item Uv
A memory reference suitable for VFP load/store insns (reg+constant offset)
+@item Uy
+A memory reference suitable for iWMMXt load/store instructions.
+
@item Uq
A memory reference suitable for for the ARMv4 ldrsb instruction.