This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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))]
   ""
   ""

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]