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]

[arm] Fix invalid store instructions


In an arm store instruction the source register must not be the same as the 
base address register when base writeback is enabled.

Some of the gcc regression tests cause this through the use of uninitialized 
variables. It turns out it's also possible to cause this with the following 
code:

foo(int a, char * b)
{
  register char * p asm("r2");

  p = b;
  while (a--)
    {
      *p = (char)(int)p;
      p++;
    }
}

The same restriction applies at stores of all widths, although I've only 
managed to reproduce the bad code generation with byte stores.

The attached patch fixes the invalid instructions by outputting a seperate add 
instructions. I also added an extra memory constraint and instruction 
alternative to avoid pessimizing the non-writeback case.

Tested with cross to arm-none-elf.
Ok?
The test above is somewhat sensitive to the behaviour of the optimizers, 
should I add it anyway?

Paul

2004-06-18  Paul Brook  <paul@codesourcery.com>

	* config/arm/arm-protos.h (arm_store_mem_op, arm_output_store): Add
	prototypes.
	* config/arm/arm.c (arm_store_mem_op, arm_output_store): New functions.
	* config/arm/arm.h (EXTRA_CONSTRAINT_STR_ARM): Handle 'Us'.
	* config/arm/arm.md (arm_movsi_insn, movhi_insn_arch4, arm_movqi_insn,
	arm_movsf_soft_insn): Add writeback alternative.
	* config/arm/iwmmxt.md (iwmmxt_movsi_insn, cond_iwmmxt_movsi_insn):
	Ditto.
	* config/arm/vfp.md (arm_movsi_vfp, movsf_vfp): Ditto.
	* doc/md.texi: Document 'Us' constraint.
Index: config/arm/arm-protos.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/arm/arm-protos.h,v
retrieving revision 1.68
diff -u -p -r1.68 arm-protos.h
--- config/arm/arm-protos.h	5 May 2004 23:11:52 -0000	1.68
+++ config/arm/arm-protos.h	18 Jun 2004 16:24:30 -0000
@@ -73,6 +73,7 @@ extern int arm_add_operand (rtx, enum ma
 extern int arm_addimm_operand (rtx, enum machine_mode);
 extern int arm_not_operand (rtx, enum machine_mode);
 extern int arm_extendqisi_mem_op (rtx, enum machine_mode);
+extern int arm_store_mem_op (rtx, enum machine_mode);
 extern int offsettable_memory_operand (rtx, enum machine_mode);
 extern int alignable_memory_operand (rtx, enum machine_mode);
 extern int arm_float_rhs_operand (rtx, enum machine_mode);
@@ -151,6 +152,7 @@ extern int arm_is_longcall_p (rtx, int, 
 extern int    arm_emit_vector_const (FILE *, rtx);
 extern const char * arm_output_load_gr (rtx *);
 extern const char *vfp_output_fstmx (rtx *);
+extern const char * arm_output_store (rtx *);
 
 #if defined TREE_CODE
 extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
Index: config/arm/arm.c
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.365
diff -u -p -r1.365 arm.c
--- config/arm/arm.c	28 May 2004 16:00:00 -0000	1.365
+++ config/arm/arm.c	18 Jun 2004 15:44:25 -0000
@@ -4545,6 +4545,28 @@ arm_extendqisi_mem_op (rtx op, enum mach
   return arm_legitimate_address_p (mode, XEXP (op, 0), SIGN_EXTEND, 0);
 }
 
+
+/* Return nonzero if OP is a valid destinationfor a store  instruction, and
+   does not use a writeback addressing mode.  */
+
+int
+arm_store_mem_op (rtx op, enum machine_mode mode)
+{
+  enum rtx_code code;
+
+  if (!memory_operand (op, mode))
+    return 0;
+
+  /* Disallow writeback addressing modes.  */
+  code = GET_CODE (XEXP (op, 0));
+  if (code == POST_INC || code == PRE_INC
+      || code == POST_DEC || code == PRE_DEC)
+    return 0;
+
+  return 1;
+}
+
+
 /* Return nonzero if OP is a Cirrus or general register.  */
 int
 cirrus_register_operand (rtx op, enum machine_mode mode)
@@ -7892,6 +7914,90 @@ arm_output_fldmx (FILE * stream, unsigne
 }
 
 
+/* Output a store instruction.  Invalid writeback addressing modes will be
+   fixed up with an add instruction.  */
+
+const char *
+arm_output_store (rtx * operands)
+{
+  rtx op0;
+  rtx op1;
+  enum rtx_code code;
+  const char *s;
+  rtx otherop[3];
+  HOST_WIDE_INT size;
+
+  size = GET_MODE_SIZE (GET_MODE (operands[0]));
+  op0 = XEXP (operands[0], 0);
+  op1 = operands[1];
+
+  switch (size)
+    {
+    case 1:
+      s = "str%?b\t%1, %0";
+      break;
+
+    case 2:
+      s = "str%?h\t%1, %0";
+      break;
+
+    case 4:
+      s = "str%?\t%1, %0";
+      break;
+
+    default:
+      abort ();
+    }
+
+  code = GET_CODE (op0);
+  if (code == POST_INC || code == PRE_INC
+      || code == POST_DEC || code == PRE_DEC)
+    {
+      op0 = XEXP (op0, 0);
+      if (REGNO (op0) == REGNO (op1))
+	{
+	  /* Fixup the illegal cases.  */
+	  otherop[0] = op0;
+	  otherop[1] = GEN_INT (size);
+
+	  switch (code)
+	    {
+	    case PRE_INC:
+	      XEXP (operands[0], 0) = gen_rtx_MINUS (SImode, op0,
+						     GEN_INT (-size));
+	      output_asm_insn ("add%?\t%0, %0, %1", otherop);
+	      output_asm_insn (s, operands);
+	      break;
+
+	    case PRE_DEC:
+	      XEXP (operands[0], 0) = gen_rtx_MINUS (SImode, op0,
+						     GEN_INT (size));
+	      output_asm_insn ("sub%?\t%0, %0, %1", otherop);
+	      output_asm_insn (s, operands);
+	      break;
+
+	    case POST_INC:
+	      XEXP (operands[0], 0) = op0;
+	      output_asm_insn (s, operands);
+	      output_asm_insn ("add%?\t%0, %0, %1", otherop);
+	      break;
+
+	    case POST_DEC:
+	      XEXP (operands[0], 0) = op0;
+	      output_asm_insn (s, operands);
+	      output_asm_insn ("sub%?\t%0, %0, %1", otherop);
+	      break;
+
+	    default:
+	      abort ();
+	    }
+	  return "";
+	}
+    }
+  return s;
+}
+
+
 /* Output the assembly for a store multiple.  */
 
 const char *
Index: config/arm/arm.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.237
diff -u -p -r1.237 arm.h
--- config/arm/arm.h	21 May 2004 01:03:16 -0000	1.237
+++ config/arm/arm.h	18 Jun 2004 15:44:25 -0000
@@ -1275,7 +1275,8 @@ enum reg_class
    '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.  */
+   'Uq' is an address valid for ldrsb.
+   'Us' is an address valid for arm store insns without base writeback.  */
 
 #define EXTRA_CONSTRAINT_STR_ARM(OP, C, STR)			\
   (((C) == 'Q') ? (GET_CODE (OP) == MEM				\
@@ -1288,8 +1289,9 @@ enum reg_class
    ((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)
+    ? arm_extendqisi_mem_op (OP, GET_MODE (OP)) :		\
+   ((C) == 'U' && (STR)[1] == 's') ? arm_store_mem_op (OP, GET_MODE(OP)) : \
+    0)
 
 #define CONSTRAINT_LEN(C,STR)				\
   ((C) == 'U' ? 2 : DEFAULT_CONSTRAINT_LEN (C, STR))
Index: config/arm/arm.md
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/arm/arm.md,v
retrieving revision 1.169
diff -u -p -r1.169 arm.md
--- config/arm/arm.md	20 May 2004 14:59:43 -0000	1.169
+++ config/arm/arm.md	18 Jun 2004 16:24:10 -0000
@@ -4280,22 +4280,29 @@
   "
 )
 
+;; We have two store alternatives to avoid pessimizing the non-writeback case.
 (define_insn "*arm_movsi_insn"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
-	(match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,Us,m")
+	(match_operand:SI 1 "general_operand"      "rI,K,mi,r,r"))]
   "TARGET_ARM && ! TARGET_IWMMXT
    && !(TARGET_HARD_FLOAT && TARGET_VFP)
    && (   register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode))"
-  "@
-   mov%?\\t%0, %1
-   mvn%?\\t%0, #%B1
-   ldr%?\\t%0, %1
-   str%?\\t%1, %0"
-  [(set_attr "type" "*,*,load1,store1")
+  "*
+  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 arm_output_store (operands);
+    default: abort ();
+    }"
+  [(set_attr "type" "*,*,load1,store1,store1")
+   (set_attr "length" "4,4,4,8,8")
    (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
@@ -4853,22 +4860,28 @@
 
 ;; Pattern to recognize insn generated default case above
 (define_insn "*movhi_insn_arch4"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
-	(match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,Us,m,r")    
+	(match_operand:HI 1 "general_operand"      "rI,K,r,r,m"))]
   "TARGET_ARM
    && arm_arch4
    && (GET_CODE (operands[1]) != CONST_INT
        || const_ok_for_arm (INTVAL (operands[1]))
        || const_ok_for_arm (~INTVAL (operands[1])))"
-  "@
-   mov%?\\t%0, %1\\t%@ movhi
-   mvn%?\\t%0, #%B1\\t%@ movhi
-   str%?h\\t%1, %0\\t%@ movhi 
-   ldr%?h\\t%0, %1\\t%@ movhi"
-  [(set_attr "type" "*,*,store1,load1")
+  "*
+  switch (which_alternative)
+    {
+    case 0: return \"mov%?\\t%0, %1\\t%@ movhi\";
+    case 1: return \"mvn%?\\t%0, #%B1\\t%@ movhi\";
+    case 2: return \"str%?h\\t%1, %0\\t%@ movhi\";
+    case 3: return arm_output_store (operands);
+    case 4: return \"ldr%?h\\t%0, %1\\t%@ movhi\";
+    default: abort ();
+    }"
+  [(set_attr "type" "*,*,store1,store1,load1")
    (set_attr "predicable" "yes")
-   (set_attr "pool_range" "*,*,*,256")
-   (set_attr "neg_pool_range" "*,*,*,244")]
+   (set_attr "length" "4,4,4,8,4")
+   (set_attr "pool_range" "*,*,*,*,256")
+   (set_attr "neg_pool_range" "*,*,*,*,244")]
 )
 
 (define_insn "*movhi_bytes"
@@ -4995,17 +5008,23 @@
 
 
 (define_insn "*arm_movqi_insn"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
-	(match_operand:QI 1 "general_operand" "rI,K,m,r"))]
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,Us,m")
+	(match_operand:QI 1 "general_operand" "rI,K,m,r,r"))]
   "TARGET_ARM
    && (   register_operand (operands[0], QImode)
        || register_operand (operands[1], QImode))"
-  "@
-   mov%?\\t%0, %1
-   mvn%?\\t%0, #%B1
-   ldr%?b\\t%0, %1
-   str%?b\\t%1, %0"
-  [(set_attr "type" "*,*,load1,store1")
+  "*
+  switch (which_alternative)
+    {
+    case 0: return \"mov%?\\t%0, %1\";
+    case 1: return \"mvn%?\\t%0, #%B1\";
+    case 2: return \"ldr%?b\\t%0, %1\";
+    case 3: return \"str%?b\\t%1, %0\";
+    case 4: return arm_output_store (operands);
+    default: abort ();
+    }"
+  [(set_attr "type" "*,*,load1,store1,store1")
+   (set_attr "length" "4,4,4,4,8")
    (set_attr "predicable" "yes")]
 )
 
@@ -5065,21 +5084,26 @@
 )
 
 (define_insn "*arm_movsf_soft_insn"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
-	(match_operand:SF 1 "general_operand"  "r,mE,r"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,Us,m")
+	(match_operand:SF 1 "general_operand"  "r,mE,r,r"))]
   "TARGET_ARM
    && TARGET_SOFT_FLOAT
    && (GET_CODE (operands[0]) != MEM
        || register_operand (operands[1], SFmode))"
-  "@
-   mov%?\\t%0, %1
-   ldr%?\\t%0, %1\\t%@ float
-   str%?\\t%1, %0\\t%@ float"
-  [(set_attr "length" "4,4,4")
+  "*
+  switch (which_alternative)
+    {
+    case 0: return \"mov%?\\t%0, %1\";
+    case 1: return \"ldr%?\\t%0, %1\\t%@ float\";
+    case 2: return \"str%?\\t%1, %0\\t%@ float\";
+    case 3: return arm_output_store (operands);
+    default: abort ();
+    }"
+  [(set_attr "length" "4,4,8,4")
    (set_attr "predicable" "yes")
-   (set_attr "type" "*,load1,store1")
-   (set_attr "pool_range" "*,4096,*")
-   (set_attr "neg_pool_range" "*,4084,*")]
+   (set_attr "type" "*,load1,store1,store1")
+   (set_attr "pool_range" "*,4096,*,*")
+   (set_attr "neg_pool_range" "*,4084,*,*")]
 )
 
 ;;; ??? This should have alternatives for constants.
Index: config/arm/iwmmxt.md
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/arm/iwmmxt.md,v
retrieving revision 1.6
diff -u -p -r1.6 iwmmxt.md
--- config/arm/iwmmxt.md	5 May 2004 23:11:54 -0000	1.6
+++ config/arm/iwmmxt.md	18 Jun 2004 16:05:41 -0000
@@ -92,8 +92,8 @@
 )
 
 (define_insn "*iwmmxt_movsi_insn"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m,z,r,?z,m,z")
-	(match_operand:SI 1 "general_operand"      "rI,K,mi,r,r,z,m,z,z"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,Us,m,z,r,?z,m,z")
+	(match_operand:SI 1 "general_operand"      "rI,K,mi,r,r,r,z,m,z,z"))]
   "TARGET_REALLY_IWMMXT
    && (   register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode))"
@@ -104,16 +104,17 @@
    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 4: return arm_output_store (operands);
+   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,store1,*,*,load1,store1,*")
+   (set_attr "length"         "*,*,    *,     *,     8,*,*,   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,
@@ -133,8 +134,8 @@
      (match_operator 2 "arm_comparison_operator"
       [(match_operand 3 "cc_register" "")
       (const_int 0)])
-     (set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m,z,r")
-	  (match_operand:SI 1 "general_operand"      "rI,K,mi,r,r,z")))]
+     (set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,Us,m,z,r")
+	  (match_operand:SI 1 "general_operand"      "rI,K,mi,r,r,r,z")))]
   "TARGET_REALLY_IWMMXT
    && (   register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode))"
@@ -145,12 +146,14 @@
    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 4: return arm_output_store (operands);
+   case 5: return \"tmcr%?\\t%0, %1\";
    default: return \"tmrc%?\\t%0, %1\";
   }"
-  [(set_attr "type"           "*,*,load1,store1,*,*")
-   (set_attr "pool_range"     "*,*,4096,     *,*,*")
-   (set_attr "neg_pool_range" "*,*,4084,     *,*,*")]
+  [(set_attr "type"           "*,*,load1,store1,store1,*,*")
+   (set_attr "length"	      "*,*,    *,     *,     8,*,*")
+   (set_attr "pool_range"     "*,*, 4096,     *,     *,*,*")
+   (set_attr "neg_pool_range" "*,*, 4084,     *,     *,*,*")]
 )
 
 (define_insn "movv8qi_internal"
Index: config/arm/vfp.md
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/arm/vfp.md,v
retrieving revision 1.6
diff -u -p -r1.6 vfp.md
--- config/arm/vfp.md	5 May 2004 23:11:54 -0000	1.6
+++ config/arm/vfp.md	18 Jun 2004 15:44:25 -0000
@@ -111,25 +111,31 @@
 ;; ??? 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 ,m,!w,r,!w,!w,  Uv")
-      (match_operand:SI 1 "general_operand"	   "rI,K,mi,r,r,!w,!w,Uvi,!w"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,Us,m,!w,r,!w,!w,  Uv")
+      (match_operand:SI 1 "general_operand"	   "rI,K,mi,r,r,r,!w,!w,Uvi,!w"))]
   "TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT
    && (   s_register_operand (operands[0], SImode)
        || s_register_operand (operands[1], SImode))"
-  "@
-  mov%?\\t%0, %1
-  mvn%?\\t%0, #%B1
-  ldr%?\\t%0, %1
-  str%?\\t%1, %0
-  fmsr%?\\t%0, %1\\t%@ int
-  fmrs%?\\t%0, %1\\t%@ int
-  fcpys%?\\t%0, %1\\t%@ int
-  flds%?\\t%0, %1\\t%@ int
-  fsts%?\\t%1, %0\\t%@ int"
-  [(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" "*,*,4084,*,*,*,*,1008,*")]
+  "*
+  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 arm_output_store (operands);
+    case 5: return \"fmsr%?\\t%0, %1\\t%@ int\";
+    case 6: return \"fmrs%?\\t%0, %1\\t%@ int\";
+    case 7: return \"fcpys%?\\t%0, %1\\t%@ int\";
+    case 8: return \"flds%?\\t%0, %1\\t%@ int\";
+    case 9: return \"fsts%?\\t%1, %0\\t%@ int\";
+    default: abort();
+    }"
+  [(set_attr "predicable" "yes")
+   (set_attr "type" "*,*,load1,store1,store1,r_2_f,f_2_r,ffarith,f_load,f_store")
+   (set_attr "length" "4,4,4,4,8,4,4,4,4,4")
+   (set_attr "pool_range"     "*,*,4096,*,*,*,*,*,1020,*")
+   (set_attr "neg_pool_range" "*,*,4084,*,*,*,*,*,1008,*")]
 )
 
 
@@ -168,24 +174,30 @@
 ;; SFmode moves
 
 (define_insn "*movsf_vfp"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=w,r,w  ,Uv,r ,m,w,r")
-	(match_operand:SF 1 "general_operand"	   " r,w,UvE,w, mE,r,w,r"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=w,r,w  ,Uv,r,Us,m,w,r")
+	(match_operand:SF 1 "general_operand"	   " r,w,UvE,w, mE,r,r,w,r"))]
   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
    && (   s_register_operand (operands[0], SFmode)
        || s_register_operand (operands[1], SFmode))"
-  "@
-  fmsr%?\\t%0, %1
-  fmrs%?\\t%0, %1
-  flds%?\\t%0, %1
-  fsts%?\\t%1, %0
-  ldr%?\\t%0, %1\\t%@ float
-  str%?\\t%1, %0\\t%@ float
-  fcpys%?\\t%0, %1
-  mov%?\\t%0, %1\\t%@ float"
-  [(set_attr "predicable" "yes")
-   (set_attr "type" "r_2_f,f_2_r,ffarith,*,f_load,f_store,load1,store1")
-   (set_attr "pool_range" "*,*,1020,*,4096,*,*,*")
-   (set_attr "neg_pool_range" "*,*,1008,*,4080,*,*,*")]
+  "*
+  switch (which_alternative)
+    {
+    case 0: return\"fmsr%?\\t%0, %1\";
+    case 1: return \"fmrs%?\\t%0, %1\";
+    case 2: return \"flds%?\\t%0, %1\";
+    case 3: return \"fsts%?\\t%1, %0\";
+    case 4: return \"ldr%?\\t%0, %1\\t%@ float\";
+    case 5: return \"str%?\\t%1, %0\\t%@ float\";
+    case 6: return arm_output_store (operands);
+    case 7: return \"fcpys%?\\t%0, %1\";
+    case 8: return \"mov%?\\t%0, %1\\t%@ float\";
+    default: abort ();
+    }"
+  [(set_attr "predicable" "yes")
+   (set_attr "type" "r_2_f,f_2_r,f_load,f_store,load1,store1,store1,ffarith,*")
+   (set_attr "length" "4,4,4,4,4,4,8,4,4")
+   (set_attr "pool_range" "*,*,1020,*,4096,*,*,*,*")
+   (set_attr "neg_pool_range" "*,*,1008,*,4080,*,*,*,*")]
 )
 
 
Index: doc/md.texi
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/doc/md.texi,v
retrieving revision 1.100
diff -u -p -r1.100 md.texi
--- doc/md.texi	11 May 2004 23:35:57 -0000	1.100
+++ doc/md.texi	18 Jun 2004 16:19:53 -0000
@@ -1369,6 +1369,11 @@ A memory reference suitable for iWMMXt l
 @item Uq
 A memory reference suitable for for the ARMv4 ldrsb instruction.
 
+@item Us
+A memory reference suitable for arm store insns, and does not use writeback
+addressing modes.  Writeback addressing modes may need fixing up with an extra
+instruction so this is used to avoid pessimizing the normal case.
+
 @item AVR family---@file{avr.h}
 @table @code
 @item l

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