This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Thumb-2 SP use
- From: Paul Brook <paul at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 26 Feb 2008 22:19:22 +0000
- Subject: Thumb-2 SP use
The ARM Thumb-2 instruction set only permits use of SP (aka r13) in a subset
of instructions. Roughly speaking SP is only valid in a mov, as the
destination or first source operand of an add, and as the base register in a
memory address. In particular it is not valid as an index register in a
load/store, or in a BIC instruction.
The attached patch makes gcc honor this restriction by removing SP from
GENERAL_REGS, and adding STACK_REG alternatives where appropriate.
For simplicity of implementation this effects both conventional ARM and
Thumb-2. In practice this has very little impact on the generated code.
I've also heard rumours that future ARM architecture revisions may
discourage/deprecate use of r13 as a general register.
Thumb-1 is unaffected as most instructions access high registers at all.
Tested on arm-none-eabi.
Applied to svn trunk.
Paul
2008-02-26 Paul Brook <paul@codesourcery.com>
* config/arm/arm.c (thumb_set_frame_pointer): Ensure SP is first
operand for Thumb-2.
* config/arm/arm.h (reg_class): Add CORE_REGS.
(REG_CLASS_NAMES, REG_CLASS_CONTENTS): Ditto.
(BASE_REG_CLASS): Use CORE_REGS.
(PREFERRED_RELOAD_CLASS): Add STACK_REG.
(REGNO_MODE_OK_FOR_REG_BASE_P): Use REGNO_MODE_OK_FOR_BASE_P.
(REGNO_OK_FOR_INDEX_P): Exclude SP.
(ARM_REG_OK_FOR_INDEX_P): Always define. Use
ARM_REGNO_OK_FOR_INDEX_P.
(ARM_PRINT_OPERAND_ADDRESS): Swap operands for [reg, sp].
* config/arm/arm.md (arm_addsi3, thumb1_addsi3, arm_subsi3_insn,
arm_movsi_insn, thumb1_movsi_insni, stack_tie): Add "k" alternatives.
(ldm/stm peepholes): Ditto.
* config/arm/thumb2.md (thumb2_movdi): Add "k" alternatives.
* config/arm/vfp.md (arm_movsi_vfp, thumb2_movsi_vfp): Ditto.
* config/arm/iwmmxt.md (iwmmxt_movsi_insn): Ditto.
* config/arm/constraints.md: Enable "k" constraint on ARM.
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c (revision 132488)
+++ gcc/config/arm/arm.c (working copy)
@@ -12229,9 +12229,20 @@ thumb_set_frame_pointer (arm_stack_offse
else
{
emit_insn (gen_movsi (hard_frame_pointer_rtx, GEN_INT (amount)));
- insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
- hard_frame_pointer_rtx,
- stack_pointer_rtx));
+ /* Thumb-2 RTL patterns expect sp as the first input. Thumb-1
+ expects the first two operands to be the same. */
+ if (TARGET_THUMB2)
+ {
+ insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
+ stack_pointer_rtx,
+ hard_frame_pointer_rtx));
+ }
+ else
+ {
+ insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
+ hard_frame_pointer_rtx,
+ stack_pointer_rtx));
+ }
dwarf = gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx,
plus_constant (stack_pointer_rtx, amount));
RTX_FRAME_RELATED_P (dwarf) = 1;
Index: gcc/config/arm/thumb2.md
===================================================================
--- gcc/config/arm/thumb2.md (revision 132488)
+++ gcc/config/arm/thumb2.md (working copy)
@@ -224,22 +224,23 @@ (define_insn "*thumb2_movdi"
)
(define_insn "*thumb2_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r, m")
- (match_operand:SI 1 "general_operand" "rI,K,N,mi,r"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
+ (match_operand:SI 1 "general_operand" "rk ,I,K,N,mi,rk"))]
"TARGET_THUMB2 && ! TARGET_IWMMXT
&& !(TARGET_HARD_FLOAT && TARGET_VFP)
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
"@
mov%?\\t%0, %1
+ mov%?\\t%0, %1
mvn%?\\t%0, #%B1
movw%?\\t%0, %1
ldr%?\\t%0, %1
str%?\\t%1, %0"
- [(set_attr "type" "*,*,*,load1,store1")
+ [(set_attr "type" "*,*,*,*,load1,store1")
(set_attr "predicable" "yes")
- (set_attr "pool_range" "*,*,*,4096,*")
- (set_attr "neg_pool_range" "*,*,*,0,*")]
+ (set_attr "pool_range" "*,*,*,*,4096,*")
+ (set_attr "neg_pool_range" "*,*,*,*,0,*")]
)
;; ??? We can probably do better with thumb2
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h (revision 132488)
+++ gcc/config/arm/arm.h (working copy)
@@ -1106,6 +1106,7 @@ enum reg_class
CC_REG,
VFPCC_REG,
GENERAL_REGS,
+ CORE_REGS,
ALL_REGS,
LIM_REG_CLASSES
};
@@ -1131,6 +1132,7 @@ enum reg_class
"CC_REG", \
"VFPCC_REG", \
"GENERAL_REGS", \
+ "CORE_REGS", \
"ALL_REGS", \
}
@@ -1151,10 +1153,11 @@ enum reg_class
{ 0x000000FF, 0x00000000, 0x00000000, 0x00000000 }, /* LO_REGS */ \
{ 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
{ 0x000020FF, 0x00000000, 0x00000000, 0x00000000 }, /* BASE_REGS */ \
- { 0x0000FF00, 0x00000000, 0x00000000, 0x00000000 }, /* HI_REGS */ \
+ { 0x0000DF00, 0x00000000, 0x00000000, 0x00000000 }, /* HI_REGS */ \
{ 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, /* CC_REG */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x80000000 }, /* VFPCC_REG */ \
- { 0x0200FFFF, 0x00000000, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
+ { 0x0200DFFF, 0x00000000, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
+ { 0x0200FFFF, 0x00000000, 0x00000000, 0x00000000 }, /* CORE_REGS */ \
{ 0xFAFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF } /* ALL_REGS */ \
}
@@ -1187,13 +1190,13 @@ enum reg_class
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS (TARGET_THUMB1 ? LO_REGS : GENERAL_REGS)
-#define BASE_REG_CLASS (TARGET_THUMB1 ? LO_REGS : GENERAL_REGS)
+#define BASE_REG_CLASS (TARGET_THUMB1 ? LO_REGS : CORE_REGS)
/* For the Thumb the high registers cannot be used as base registers
when addressing quantities in QI or HI mode; if we don't know the
mode, then we must be conservative. */
#define MODE_BASE_REG_CLASS(MODE) \
- (TARGET_32BIT ? GENERAL_REGS : \
+ (TARGET_32BIT ? CORE_REGS : \
(((MODE) == SImode) ? BASE_REGS : LO_REGS))
/* For Thumb we can not support SP+reg addressing, so we return LO_REGS
@@ -1213,7 +1216,8 @@ enum reg_class
#define PREFERRED_RELOAD_CLASS(X, CLASS) \
(TARGET_ARM ? (CLASS) : \
((CLASS) == GENERAL_REGS || (CLASS) == HI_REGS \
- || (CLASS) == NO_REGS ? LO_REGS : (CLASS)))
+ || (CLASS) == NO_REGS || (CLASS) == STACK_REG \
+ ? LO_REGS : (CLASS)))
/* Must leave BASE_REGS reloads alone */
#define THUMB_SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
@@ -1908,12 +1912,13 @@ typedef struct
/* Nonzero if X can be the base register in a reg+reg addressing mode.
For Thumb, we can not use SP + reg, so reject SP. */
#define REGNO_MODE_OK_FOR_REG_BASE_P(X, MODE) \
- REGNO_OK_FOR_INDEX_P (X)
+ REGNO_MODE_OK_FOR_BASE_P (X, QImode)
/* For ARM code, we don't care about the mode, but for Thumb, the index
must be suitable for use in a QImode load. */
#define REGNO_OK_FOR_INDEX_P(REGNO) \
- REGNO_MODE_OK_FOR_BASE_P (REGNO, QImode)
+ (REGNO_MODE_OK_FOR_BASE_P (REGNO, QImode) \
+ && !TEST_REGNO (REGNO, ==, STACK_POINTER_REGNUM))
/* Maximum number of registers that can appear in a valid memory address.
Shifts in addresses can't be by a register. */
@@ -2051,6 +2056,13 @@ typedef struct
|| REGNO (X) == FRAME_POINTER_REGNUM \
|| REGNO (X) == ARG_POINTER_REGNUM)
+#define ARM_REG_OK_FOR_INDEX_P(X) \
+ ((REGNO (X) <= LAST_ARM_REGNUM \
+ && REGNO (X) != STACK_POINTER_REGNUM) \
+ || REGNO (X) >= FIRST_PSEUDO_REGISTER \
+ || REGNO (X) == FRAME_POINTER_REGNUM \
+ || REGNO (X) == ARG_POINTER_REGNUM)
+
#define THUMB1_REG_MODE_OK_FOR_BASE_P(X, MODE) \
(REGNO (X) <= LAST_LO_REGNUM \
|| REGNO (X) >= FIRST_PSEUDO_REGISTER \
@@ -2066,6 +2078,9 @@ typedef struct
#define ARM_REG_OK_FOR_BASE_P(X) \
ARM_REGNO_OK_FOR_BASE_P (REGNO (X))
+#define ARM_REG_OK_FOR_INDEX_P(X) \
+ ARM_REGNO_OK_FOR_INDEX_P (REGNO (X))
+
#define THUMB1_REG_MODE_OK_FOR_BASE_P(X, MODE) \
THUMB1_REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
@@ -2080,8 +2095,6 @@ typedef struct
? THUMB1_REG_MODE_OK_FOR_BASE_P (X, MODE) \
: ARM_REG_OK_FOR_BASE_P (X))
-#define ARM_REG_OK_FOR_INDEX_P(X) ARM_REG_OK_FOR_BASE_P (X)
-
/* For 16-bit Thumb, a valid index register is anything that can be used in
a byte load instruction. */
#define THUMB1_REG_OK_FOR_INDEX_P(X) \
@@ -2479,10 +2492,12 @@ extern int making_const_table;
rtx base = XEXP (X, 0); \
rtx index = XEXP (X, 1); \
HOST_WIDE_INT offset = 0; \
- if (GET_CODE (base) != REG) \
+ if (GET_CODE (base) != REG \
+ || (GET_CODE (index) == REG && REGNO (index) == SP_REGNUM)) \
{ \
/* Ensure that BASE is a register. */ \
/* (one of them must be). */ \
+ /* Also ensure the SP is not used as in index register. */ \
rtx temp = base; \
base = index; \
index = temp; \
Index: gcc/config/arm/vfp.md
===================================================================
--- gcc/config/arm/vfp.md (revision 132488)
+++ gcc/config/arm/vfp.md (working copy)
@@ -120,77 +120,77 @@ (define_insn_reservation "vfp_to_cpsr" 4
;; ??? For now do not allow loading constants into vfp regs. This causes
;; problems because small constants get converted into adds.
(define_insn "*arm_movsi_vfp"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r ,m,*t,r,*t,*t, *Uv")
- (match_operand:SI 1 "general_operand" "rI,K,N,mi,r,r,*t,*t,*Uvi,*t"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m ,*t,r,*t,*t, *Uv")
+ (match_operand:SI 1 "general_operand" "rk, I,K,N,mi,rk,r,*t,*t,*Uvi,*t"))]
"TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT
&& ( s_register_operand (operands[0], SImode)
|| s_register_operand (operands[1], SImode))"
"*
switch (which_alternative)
{
- case 0:
+ case 0: case 1:
return \"mov%?\\t%0, %1\";
- case 1:
- return \"mvn%?\\t%0, #%B1\";
case 2:
- return \"movw%?\\t%0, %1\";
+ return \"mvn%?\\t%0, #%B1\";
case 3:
- return \"ldr%?\\t%0, %1\";
+ return \"movw%?\\t%0, %1\";
case 4:
- return \"str%?\\t%1, %0\";
+ return \"ldr%?\\t%0, %1\";
case 5:
- return \"fmsr%?\\t%0, %1\\t%@ int\";
+ return \"str%?\\t%1, %0\";
case 6:
- return \"fmrs%?\\t%0, %1\\t%@ int\";
+ return \"fmsr%?\\t%0, %1\\t%@ int\";
case 7:
+ return \"fmrs%?\\t%0, %1\\t%@ int\";
+ case 8:
return \"fcpys%?\\t%0, %1\\t%@ int\";
- case 8: case 9:
+ case 9: case 10:
return output_move_vfp (operands);
default:
gcc_unreachable ();
}
"
[(set_attr "predicable" "yes")
- (set_attr "type" "*,*,*,load1,store1,r_2_f,f_2_r,ffarith,f_loads,f_stores")
- (set_attr "pool_range" "*,*,*,4096,*,*,*,*,1020,*")
- (set_attr "neg_pool_range" "*,*,*,4084,*,*,*,*,1008,*")]
+ (set_attr "type" "*,*,*,*,load1,store1,r_2_f,f_2_r,ffarith,f_loads,f_stores")
+ (set_attr "pool_range" "*,*,*,*,4096,*,*,*,*,1020,*")
+ (set_attr "neg_pool_range" "*,*,*,*,4084,*,*,*,*,1008,*")]
)
(define_insn "*thumb2_movsi_vfp"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,*t,r,*t,*t, *Uv")
- (match_operand:SI 1 "general_operand" "rI,K,N,mi,r,r,*t,*t,*Uvi,*t"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m,*t,r, *t,*t, *Uv")
+ (match_operand:SI 1 "general_operand" "rk, I,K,N,mi,rk,r,*t,*t,*Uvi,*t"))]
"TARGET_THUMB2 && TARGET_VFP && TARGET_HARD_FLOAT
&& ( s_register_operand (operands[0], SImode)
|| s_register_operand (operands[1], SImode))"
"*
switch (which_alternative)
{
- case 0:
+ case 0: case 1:
return \"mov%?\\t%0, %1\";
- case 1:
- return \"mvn%?\\t%0, #%B1\";
case 2:
- return \"movw%?\\t%0, %1\";
+ return \"mvn%?\\t%0, #%B1\";
case 3:
- return \"ldr%?\\t%0, %1\";
+ return \"movw%?\\t%0, %1\";
case 4:
- return \"str%?\\t%1, %0\";
+ return \"ldr%?\\t%0, %1\";
case 5:
- return \"fmsr%?\\t%0, %1\\t%@ int\";
+ return \"str%?\\t%1, %0\";
case 6:
- return \"fmrs%?\\t%0, %1\\t%@ int\";
+ return \"fmsr%?\\t%0, %1\\t%@ int\";
case 7:
+ return \"fmrs%?\\t%0, %1\\t%@ int\";
+ case 8:
return \"fcpys%?\\t%0, %1\\t%@ int\";
- case 8: case 9:
+ case 9: case 10:
return output_move_vfp (operands);
default:
gcc_unreachable ();
}
"
[(set_attr "predicable" "yes")
- (set_attr "type" "*,*,*,load1,store1,r_2_f,f_2_r,ffarith,f_load,f_store")
- (set_attr "pool_range" "*,*,*,4096,*,*,*,*,1020,*")
- (set_attr "neg_pool_range" "*,*,*, 0,*,*,*,*,1008,*")]
+ (set_attr "type" "*,*,*,*,load1,store1,r_2_f,f_2_r,ffarith,f_load,f_store")
+ (set_attr "pool_range" "*,*,*,*,4096,*,*,*,*,1020,*")
+ (set_attr "neg_pool_range" "*,*,*,*, 0,*,*,*,*,1008,*")]
)
Index: gcc/config/arm/constraints.md
===================================================================
--- gcc/config/arm/constraints.md (revision 132488)
+++ gcc/config/arm/constraints.md (working copy)
@@ -20,8 +20,8 @@
;; The following register constraints have been used:
;; - in ARM/Thumb-2 state: f, t, v, w, x, y, z
-;; - in Thumb state: h, k, b
-;; - in both states: l, c
+;; - in Thumb state: h, b
+;; - in both states: l, c, k
;; In ARM state, 'l' is an alias for 'r'
;; The following normal constraints have been used:
@@ -65,9 +65,8 @@ (define_register_constraint "l" "TARGET_
(define_register_constraint "h" "TARGET_THUMB ? HI_REGS : NO_REGS"
"In Thumb state the core registers @code{r8}-@code{r15}.")
-(define_register_constraint "k" "TARGET_THUMB ? STACK_REG : NO_REGS"
- "@internal
- Thumb only. The stack register.")
+(define_register_constraint "k" "STACK_REG"
+ "@internal The stack register.")
(define_register_constraint "b" "TARGET_THUMB ? BASE_REGS : NO_REGS"
"@internal
Index: gcc/config/arm/iwmmxt.md
===================================================================
--- gcc/config/arm/iwmmxt.md (revision 132488)
+++ gcc/config/arm/iwmmxt.md (working copy)
@@ -105,8 +105,8 @@ (define_insn "*iwmmxt_arm_movdi"
)
(define_insn "*iwmmxt_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m,z,r,?z,Uy,z")
- (match_operand:SI 1 "general_operand" "rI,K,mi,r,r,z,Uy,z,z"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,rk, m,z,r,?z,Uy,z")
+ (match_operand:SI 1 "general_operand" "rk, I,K,mi,rk,r,z,Uy,z, z"))]
"TARGET_REALLY_IWMMXT
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
@@ -114,19 +114,20 @@ (define_insn "*iwmmxt_movsi_insn"
switch (which_alternative)
{
case 0: return \"mov\\t%0, %1\";
- case 1: return \"mvn\\t%0, #%B1\";
- case 2: return \"ldr\\t%0, %1\";
- case 3: return \"str\\t%1, %0\";
- case 4: return \"tmcr\\t%0, %1\";
- case 5: return \"tmrc\\t%0, %1\";
- case 6: return arm_output_load_gr (operands);
- case 7: return \"wstrw\\t%1, %0\";
+ case 1: return \"mov\\t%0, %1\";
+ case 2: return \"mvn\\t%0, #%B1\";
+ case 3: return \"ldr\\t%0, %1\";
+ case 4: return \"str\\t%1, %0\";
+ case 5: return \"tmcr\\t%0, %1\";
+ case 6: return \"tmrc\\t%0, %1\";
+ case 7: return arm_output_load_gr (operands);
+ case 8: return \"wstrw\\t%1, %0\";
default:return \"wstrw\\t%1, [sp, #-4]!\;wldrw\\t%0, [sp], #4\\t@move CG reg\";
}"
- [(set_attr "type" "*,*,load1,store1,*,*,load1,store1,*")
- (set_attr "length" "*,*,*, *,*,*, 16, *,8")
- (set_attr "pool_range" "*,*,4096, *,*,*,1024, *,*")
- (set_attr "neg_pool_range" "*,*,4084, *,*,*, *, 1012,*")
+ [(set_attr "type" "*,*,*,load1,store1,*,*,load1,store1,*")
+ (set_attr "length" "*,*,*,*, *,*,*, 16, *,8")
+ (set_attr "pool_range" "*,*,*,4096, *,*,*,1024, *,*")
+ (set_attr "neg_pool_range" "*,*,*,4084, *,*,*, *, 1012,*")
;; Note - the "predicable" attribute is not allowed to have alternatives.
;; Since the wSTRw wCx instruction is not predicable, we cannot support
;; predicating any of the alternatives in this template. Instead,
Index: gcc/config/arm/arm.md
===================================================================
--- gcc/config/arm/arm.md (revision 132488)
+++ gcc/config/arm/arm.md (working copy)
@@ -517,12 +517,14 @@ (define_peephole2
)
(define_insn_and_split "*arm_addsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
- (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
+ [(set (match_operand:SI 0 "s_register_operand" "=r, !k,r, !k,r")
+ (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,!k,rk,!k,r")
+ (match_operand:SI 2 "reg_or_int_operand" "rI, rI,L, L,?n")))]
"TARGET_32BIT"
"@
add%?\\t%0, %1, %2
+ add%?\\t%0, %1, %2
+ sub%?\\t%0, %1, #%n2
sub%?\\t%0, %1, #%n2
#"
"TARGET_32BIT &&
@@ -536,7 +538,7 @@ (define_insn_and_split "*arm_addsi3"
operands[1], 0);
DONE;
"
- [(set_attr "length" "4,4,16")
+ [(set_attr "length" "4,4,4,4,16")
(set_attr "predicable" "yes")]
)
@@ -545,9 +547,9 @@ (define_insn_and_split "*arm_addsi3"
;; so never allow those alternatives to match if reloading is needed.
(define_insn "*thumb1_addsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
+ [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
+ (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O")))]
"TARGET_THUMB1"
"*
static const char * const asms[] =
@@ -991,12 +993,13 @@ (define_insn "*thumb1_subsi3_insn"
; ??? Check Thumb-2 split length
(define_insn_and_split "*arm_subsi3_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
- (match_operand:SI 2 "s_register_operand" "r,r")))]
+ [(set (match_operand:SI 0 "s_register_operand" "=r,rk,r")
+ (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,!k,?n")
+ (match_operand:SI 2 "s_register_operand" "r, r, r")))]
"TARGET_32BIT"
"@
rsb%?\\t%0, %2, %1
+ sub%?\\t%0, %1, %2
#"
"TARGET_32BIT
&& GET_CODE (operands[1]) == CONST_INT
@@ -1007,7 +1010,7 @@ (define_insn_and_split "*arm_subsi3_insn
INTVAL (operands[1]), operands[0], operands[2], 0);
DONE;
"
- [(set_attr "length" "4,16")
+ [(set_attr "length" "4,4,16")
(set_attr "predicable" "yes")]
)
@@ -4786,22 +4789,23 @@ (define_expand "movsi"
)
(define_insn "*arm_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r, m")
- (match_operand:SI 1 "general_operand" "rI,K,N,mi,r"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
+ (match_operand:SI 1 "general_operand" "rk, I,K,N,mi,rk"))]
"TARGET_ARM && ! TARGET_IWMMXT
&& !(TARGET_HARD_FLOAT && TARGET_VFP)
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
"@
mov%?\\t%0, %1
+ mov%?\\t%0, %1
mvn%?\\t%0, #%B1
movw%?\\t%0, %1
ldr%?\\t%0, %1
str%?\\t%1, %0"
- [(set_attr "type" "*,*,*,load1,store1")
+ [(set_attr "type" "*,*,*,*,load1,store1")
(set_attr "predicable" "yes")
- (set_attr "pool_range" "*,*,*,4096,*")
- (set_attr "neg_pool_range" "*,*,*,4084,*")]
+ (set_attr "pool_range" "*,*,*,*,4096,*")
+ (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
)
(define_split
@@ -4819,8 +4823,8 @@ (define_split
)
(define_insn "*thumb1_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
- (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
+ (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
"TARGET_THUMB1
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
@@ -10181,13 +10185,13 @@ (define_peephole2
; reversed, check that the memory references aren't volatile.
(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "=rk")
(match_operand:SI 4 "memory_operand" "m"))
- (set (match_operand:SI 1 "s_register_operand" "=r")
+ (set (match_operand:SI 1 "s_register_operand" "=rk")
(match_operand:SI 5 "memory_operand" "m"))
- (set (match_operand:SI 2 "s_register_operand" "=r")
+ (set (match_operand:SI 2 "s_register_operand" "=rk")
(match_operand:SI 6 "memory_operand" "m"))
- (set (match_operand:SI 3 "s_register_operand" "=r")
+ (set (match_operand:SI 3 "s_register_operand" "=rk")
(match_operand:SI 7 "memory_operand" "m"))]
"TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
"*
@@ -10196,11 +10200,11 @@ (define_peephole
)
(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "=rk")
(match_operand:SI 3 "memory_operand" "m"))
- (set (match_operand:SI 1 "s_register_operand" "=r")
+ (set (match_operand:SI 1 "s_register_operand" "=rk")
(match_operand:SI 4 "memory_operand" "m"))
- (set (match_operand:SI 2 "s_register_operand" "=r")
+ (set (match_operand:SI 2 "s_register_operand" "=rk")
(match_operand:SI 5 "memory_operand" "m"))]
"TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
"*
@@ -10209,9 +10213,9 @@ (define_peephole
)
(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "=rk")
(match_operand:SI 2 "memory_operand" "m"))
- (set (match_operand:SI 1 "s_register_operand" "=r")
+ (set (match_operand:SI 1 "s_register_operand" "=rk")
(match_operand:SI 3 "memory_operand" "m"))]
"TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
"*
@@ -10221,13 +10225,13 @@ (define_peephole
(define_peephole
[(set (match_operand:SI 4 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "r"))
+ (match_operand:SI 0 "s_register_operand" "rk"))
(set (match_operand:SI 5 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "r"))
+ (match_operand:SI 1 "s_register_operand" "rk"))
(set (match_operand:SI 6 "memory_operand" "=m")
- (match_operand:SI 2 "s_register_operand" "r"))
+ (match_operand:SI 2 "s_register_operand" "rk"))
(set (match_operand:SI 7 "memory_operand" "=m")
- (match_operand:SI 3 "s_register_operand" "r"))]
+ (match_operand:SI 3 "s_register_operand" "rk"))]
"TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
"*
return emit_stm_seq (operands, 4);
@@ -10236,11 +10240,11 @@ (define_peephole
(define_peephole
[(set (match_operand:SI 3 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "r"))
+ (match_operand:SI 0 "s_register_operand" "rk"))
(set (match_operand:SI 4 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "r"))
+ (match_operand:SI 1 "s_register_operand" "rk"))
(set (match_operand:SI 5 "memory_operand" "=m")
- (match_operand:SI 2 "s_register_operand" "r"))]
+ (match_operand:SI 2 "s_register_operand" "rk"))]
"TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
"*
return emit_stm_seq (operands, 3);
@@ -10249,9 +10253,9 @@ (define_peephole
(define_peephole
[(set (match_operand:SI 2 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "r"))
+ (match_operand:SI 0 "s_register_operand" "rk"))
(set (match_operand:SI 3 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "r"))]
+ (match_operand:SI 1 "s_register_operand" "rk"))]
"TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
"*
return emit_stm_seq (operands, 2);
@@ -10610,8 +10614,8 @@ (define_insn "*push_multi"
(define_insn "stack_tie"
[(set (mem:BLK (scratch))
- (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
- (match_operand:SI 1 "s_register_operand" "r")]
+ (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
+ (match_operand:SI 1 "s_register_operand" "rk")]
UNSPEC_PRLG_STK))]
""
""