OSDN Git Service

Hunk of m32r changes
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 8 May 1998 15:46:05 +0000 (15:46 +0000)
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 8 May 1998 15:46:05 +0000 (15:46 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@19636 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/m32r/m32r.c
gcc/config/m32r/m32r.h
gcc/config/m32r/m32r.md

index ad7a87e..105e4f6 100644 (file)
@@ -3,6 +3,54 @@ Fri May  8 18:23:08 1998  Michael Meissner  <meissner@cygnus.com>
        * final.c (final_scan_insn): Call fatal_insn instead of abort if
        we could not split an insn when required to.
 
+       * m32r.md ({add,sub}di3): Add define_splits and appropriate low
+       level insns.
+       (peepholes): Disable peepholes that call dead_or_set_p.
+       (movsi): Rewrite to handle addresses better after last change.
+       Add define_split to split load of addresses in large/medium modes.
+       (prologue): Call m32r_expand_prologue.
+       (movsi_{push,pop}): Generators for push/pop.
+       (movsi): Support PRE_{INC,DEC}, POST_INC.
+       (mov{di,df}): Rewrite.  Always split the insns.
+       (movsf): Add define_split to get register load in correct mode.
+       (cmp_ne_small_const_insn): Use 'N' instead of 'S' constraint.
+       (attributes): Rewrite attributes so that type indicates both the
+       type and the length of the insn directly.
+       (all insns): Change to use new type attributes.
+       (debug): New attribute to convey whether -mdebug was used.
+       (opt_space): New attribute to convey whether -Os was used.
+       (function units): Loads are 3 cycles, not 2.  Better classify all
+       insns into short/long.
+       (load/store/extend insns): Add separate case for load/store
+       indirect operations without an offset.
+       (divsi3): Division is a long operation, not short.
+
+       * m32r.h (LEGITIMATE_LO_SUM_ADDRESS_P): Do not allow LO_SUM for
+       modes > 1 word.
+       (GO_IF_MODE_DEPENDENT_ADDRESS): LO_SUM is now mode dependent.
+       (CONST_OK_FOR_LETTER_P): Make 'N' handle reverse 8 bit compares.
+       (EXTRA_CONSTRAINT): Remove 'S' special support.  Add 'U' for
+       operands with PRE_{INC,DEC}, POST_INC.
+       (FUNCTION_PROFILER): Call abort instead of doing nothing.
+       (GO_IF_LEGITIMATE_ADDRESS): Allow PRE_{INC,DEC}, POST_INC of
+       SImode variables.
+       (gen_split_move_double): Declare.
+       (EXTRA_CONSTRAINT): Add 'T' for memory reference with no offset.
+
+       * m32r.c (gen_split_move_double): Fix typo.  Also, don't call
+       emit_move_insn, build up SET's directly.
+       (toplevel): Include system.h, not stdio.h.
+       (move_double_src_operand): Allow any DF or DI mode constant.
+       (gen_split_move_double): Split moves of DI or DF values into the
+       appropriate moves, loads, or stores.  Don't handle use of auto
+       inc/dec if using dead index.  Do handle overlapping moves, etc.
+       (m32r_frame_info): Remove prologue_size field.
+       (m32r_compute_frame_size): Don't calculate prologue size.
+       (m32r_output_function_prologue): Change to pretty much a NOP.
+       (m32r_expand_prologue): Expand prologue as a series of INSNs.
+       (m32r_print_operand): Add support for PRE_{INC,DEC}, POST_INC.
+       (m32r_print_operand_address): Ditto.
+       
 Fri May  8 14:13:21 1998  H.J. Lu  (hjl@gnu.org)
 
        * reload1.c (emit_reload_insns): When performing expensive
index 3f80057..a667dbd 100644 (file)
@@ -19,7 +19,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
-#include <stdio.h>
+#include "system.h"
 #include "tree.h"
 #include "rtl.h"
 #include "regs.h"
@@ -729,10 +729,7 @@ move_double_src_operand (op, int_mode)
     {
     case CONST_INT :
     case CONST_DOUBLE :
-      if (mode == DFmode)
-       return easy_df_const (op);
-      else
-       return easy_di_const (op);
+      return 1;
     case REG :
       return register_operand (op, mode);
     case SUBREG :
@@ -1115,6 +1112,123 @@ gen_compare (int_code, x, y, need_compare)
   return gen_rtx (branch_code, VOIDmode, cc_reg, CONST0_RTX (mode));
 }
 \f
+/* Split a 2 word move (DI or DF) into component parts.  */
+
+rtx
+gen_split_move_double (operands)
+     rtx operands[];
+{
+  enum machine_mode mode = GET_MODE (operands[0]);
+  rtx dest = operands[0];
+  rtx src  = operands[1];
+  rtx val;
+
+  start_sequence ();
+  if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG)
+    {
+      /* reg = reg */
+      if (GET_CODE (src) == REG || GET_CODE (src) == SUBREG)
+       {
+         /* We normally copy the low-numbered register first.  However, if
+            the first register operand 0 is the same as the second register of
+            operand 1, we must copy in the opposite order.  */
+         int reverse = (REGNO (operands[0]) == REGNO (operands[1]) + 1);
+         emit_insn (gen_rtx_SET (VOIDmode,
+                                 operand_subword (dest, reverse, TRUE, mode),
+                                 operand_subword (src,  reverse, TRUE, mode)));
+
+         emit_insn (gen_rtx_SET (VOIDmode,
+                                 operand_subword (dest, !reverse, TRUE, mode),
+                                 operand_subword (src,  !reverse, TRUE, mode)));
+       }
+
+      /* reg = constant */
+      else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
+       {
+         rtx words[2];
+         split_double (src, &words[0], &words[1]);
+         emit_insn (gen_rtx_SET (VOIDmode,
+                                 operand_subword (dest, 0, TRUE, mode),
+                                 words[0]));
+
+         emit_insn (gen_rtx_SET (VOIDmode,
+                                 operand_subword (dest, 1, TRUE, mode),
+                                 words[1]));
+       }
+
+      /* reg = mem */
+      else if (GET_CODE (src) == MEM)
+       {
+         /* If the high-address word is used in the address, we must load it
+            last.  Otherwise, load it first.  */
+         rtx addr = XEXP (src, 0);
+         int reverse = (refers_to_regno_p (REGNO (dest), REGNO (dest)+1,
+                                           addr, 0) != 0);
+
+         /* We used to optimize loads from single registers as
+
+               ld r1,r3+; ld r2,r3
+
+            if r3 were not used subsequently.  However, the REG_NOTES aren't
+            propigated correctly by the reload phase, and it can cause bad
+            code to be generated.  We could still try:
+
+               ld r1,r3+; ld r2,r3; addi r3,-4
+
+            which saves 2 bytes and doesn't force longword alignment.  */
+         emit_insn (gen_rtx_SET (VOIDmode,
+                                 operand_subword (dest, reverse, TRUE, mode),
+                                 change_address (src, SImode,
+                                                 plus_constant (addr,
+                                                                reverse * UNITS_PER_WORD))));
+
+         emit_insn (gen_rtx_SET (VOIDmode,
+                                 operand_subword (dest, !reverse, TRUE, mode),
+                                 change_address (src, SImode,
+                                                 plus_constant (addr,
+                                                                (!reverse) * UNITS_PER_WORD))));
+       }
+
+      else
+       abort ();
+    }
+
+  /* mem = reg */
+  /* We used to optimize loads from single registers as
+
+       st r1,r3; st r2,+r3
+
+     if r3 were not used subsequently.  However, the REG_NOTES aren't
+     propigated correctly by the reload phase, and it can cause bad
+     code to be generated.  We could still try:
+
+       st r1,r3; st r2,+r3; addi r3,-4
+
+     which saves 2 bytes and doesn't force longword alignment.  */
+  else if (GET_CODE (dest) == MEM
+          && (GET_CODE (src) == REG || GET_CODE (src) == SUBREG))
+    {
+      rtx addr = XEXP (dest, 0);
+
+      emit_insn (gen_rtx_SET (VOIDmode,
+                             change_address (dest, SImode, addr),
+                             operand_subword (src, 0, TRUE, mode)));
+
+      emit_insn (gen_rtx_SET (VOIDmode,
+                             change_address (dest, SImode,
+                                             plus_constant (addr, UNITS_PER_WORD)),
+                             operand_subword (src, 1, TRUE, mode)));
+    }
+
+  else
+    abort ();
+
+  val = gen_sequence ();
+  end_sequence ();
+  return val;
+}
+
+\f
 /* Implements the FUNCTION_ARG_PARTIAL_NREGS macro.  */
 
 int
@@ -1298,7 +1412,6 @@ struct m32r_frame_info
   unsigned int args_size;      /* # bytes that outgoing arguments take up */
   unsigned int reg_size;       /* # bytes needed to store regs */
   unsigned int var_size;       /* # bytes that variables take up */
-  unsigned int prolog_size;    /* # bytes that the prologue takes up */
   unsigned int gmask;          /* mask of saved gp registers */
   unsigned int save_fp;                /* nonzero if fp must be saved */
   unsigned int save_lr;                /* nonzero if lr (return addr) must be saved */
@@ -1322,7 +1435,7 @@ static struct m32r_frame_info zero_frame_info;
  && (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_p)))
 
 #define MUST_SAVE_FRAME_POINTER (regs_ever_live[FRAME_POINTER_REGNUM])
-#define MUST_SAVE_RETURN_ADDR (regs_ever_live[RETURN_ADDR_REGNUM])
+#define MUST_SAVE_RETURN_ADDR (regs_ever_live[RETURN_ADDR_REGNUM] || profile_flag)
 
 #define SHORT_INSN_SIZE 2      /* size of small instructions */
 #define LONG_INSN_SIZE 4       /* size of long instructions */
@@ -1338,7 +1451,7 @@ m32r_compute_frame_size (size)
 {
   int regno;
   unsigned int total_size, var_size, args_size, pretend_size, extra_size;
-  unsigned int reg_size, prolog_size, frame_size;
+  unsigned int reg_size, frame_size;
   unsigned int gmask;
   enum m32r_function_type fn_type;
   int interrupt_p;
@@ -1349,7 +1462,6 @@ m32r_compute_frame_size (size)
   extra_size   = FIRST_PARM_OFFSET (0);
   total_size   = extra_size + pretend_size + args_size + var_size;
   reg_size     = 0;
-  prolog_size  = 0;
   gmask                = 0;
 
   /* See if this is an interrupt handler.  Call used registers must be saved
@@ -1379,33 +1491,8 @@ m32r_compute_frame_size (size)
      handler will do the right thing if this changes total_size.  */
   total_size = M32R_STACK_ALIGN (total_size);
 
-  /* Calculate prologue size.  Obviously any changes to
-     m32r_output_function_prologue must be mirrored here.  */
-  if (pretend_size)
-    prolog_size += SHORT_INSN_SIZE;            /* addi sp,-pretend_size */
-
-  prolog_size += SHORT_INSN_SIZE * (reg_size / UNITS_PER_WORD);        /* pushes */
   frame_size = total_size - (pretend_size + reg_size);
 
-  if (frame_size == 0)
-    ;                                          /* nothing to do */
-  else if (frame_size <= 128)
-    prolog_size += SHORT_INSN_SIZE;            /* addi sp,-<frame> */
-  else
-    {
-      if ((prolog_size % LONG_INSN_SIZE) != 0)
-       prolog_size += SHORT_INSN_SIZE;         /* nop */
-
-      if (frame_size <= 32768)
-       prolog_size += LONG_INSN_SIZE;          /* add3 sp,sp,-<frame> */
-      else
-       prolog_size += (LONG_INSN_SIZE          /* ld24 tmp,<frame>/sub sp,tmp */
-                       + SHORT_INSN_SIZE);
-    }
-
-  if (frame_pointer_needed)
-    prolog_size += SHORT_INSN_SIZE;            /* mv fp,sp */
-
   /* Save computed information.  */
   current_frame_info.total_size   = total_size;
   current_frame_info.extra_size   = extra_size;
@@ -1413,7 +1500,6 @@ m32r_compute_frame_size (size)
   current_frame_info.var_size     = var_size;
   current_frame_info.args_size    = args_size;
   current_frame_info.reg_size    = reg_size;
-  current_frame_info.prolog_size  = prolog_size;
   current_frame_info.gmask       = gmask;
   current_frame_info.initialized  = reload_completed;
 
@@ -1431,74 +1517,37 @@ m32r_first_insn_address ()
   if (! current_frame_info.initialized)
     m32r_compute_frame_size (get_frame_size ());
 
-  return current_frame_info.prolog_size;
+  return 0;
 }
 \f
-/* Set up the stack and frame pointer (if desired) for the function.
-   Note, if this is changed, you need to mirror the changes in
-   m32r_compute_frame_size which calculates the prolog size.  */
+/* Expand the m32r prologue as a series of insns.  */
 
 void
-m32r_output_function_prologue (file, size)
-     FILE * file;
-     int    size;
+m32r_expand_prologue ()
 {
   int regno;
-  int total_size, frame_size;
-  char *sp_str = reg_names[STACK_POINTER_REGNUM];
-  char *fp_str = reg_names[FRAME_POINTER_REGNUM];
+  int frame_size;
   unsigned int gmask = current_frame_info.gmask;
-  enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl);
 
-  /* If this is an interrupt handler, mark it as such.  */
-  if (M32R_INTERRUPT_P (fn_type))
-    {
-      fprintf (file, "\t%s interrupt handler\n",
-              ASM_COMMENT_START);
-    }
-
-  total_size = (! current_frame_info.initialized
-               ? m32r_compute_frame_size (size)
-               : current_frame_info.total_size);
+  if (! current_frame_info.initialized)
+    m32r_compute_frame_size (get_frame_size ());
 
-  /* This is only for the human reader.  */
-  fprintf (file,
-          "\t%s BEGIN PROLOGUE, vars= %d, regs= %d, args= %d, extra= %d, prolog= %d\n",
-          ASM_COMMENT_START,
-          current_frame_info.var_size,
-          current_frame_info.reg_size / 4,
-          current_frame_info.args_size,
-          current_frame_info.extra_size,
-          current_frame_info.prolog_size);
+  gmask = current_frame_info.gmask;
 
   /* These cases shouldn't happen.  Catch them now.  */
-  if (total_size == 0 && gmask)
+  if (current_frame_info.total_size == 0 && gmask)
     abort ();
 
-#if 1
   /* Allocate space for register arguments if this is a variadic function.  */
   if (current_frame_info.pretend_size != 0)
-    fprintf (file, "\taddi %s,%s%d\n",
-            sp_str, IMMEDIATE_PREFIX,
-            -current_frame_info.pretend_size);
-#else
-  /* If there are unnamed args in registers, save them.  */
-  if (current_function_stdarg || current_function_varargs)
-    {
-      int i;
-      fprintf (file, "\taddi %s,%s%d\n",
-              sp_str, IMMEDIATE_PREFIX,
-              - M32R_MAX_PARM_REGS * UNITS_PER_WORD);
-      for (i = 0; i < M32R_MAX_PARM_REGS; ++i)
-       fprintf (file, "\tst %s,@(sp,%d)\n",
-                reg_names[i], i * UNITS_PER_WORD);
-    }
-#endif
+    emit_insn (gen_addsi3 (stack_pointer_rtx,
+                          stack_pointer_rtx,
+                          GEN_INT (-current_frame_info.pretend_size)));
 
   /* Save any registers we need to and set up fp.  */
 
   if (current_frame_info.save_fp)
-    fprintf (file, "\tpush %s\n", fp_str);
+    emit_insn (gen_movsi_push (stack_pointer_rtx, frame_pointer_rtx));
 
   gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK);
 
@@ -1507,33 +1556,68 @@ m32r_output_function_prologue (file, size)
   for (regno = 0; regno <= M32R_MAX_INT_REGS; ++regno)
     {
       if ((gmask & (1 << regno)) != 0)
-       fprintf (file, "\tpush %s\n", reg_names[regno]);
+       emit_insn (gen_movsi_push (stack_pointer_rtx,
+                                  gen_rtx_REG (Pmode, regno)));
     }
 
   if (current_frame_info.save_lr)
-    fprintf (file, "\tpush %s\n", reg_names[RETURN_ADDR_REGNUM]);
+    emit_insn (gen_movsi_push (stack_pointer_rtx,
+                              gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM)));
 
   /* Allocate the stack frame.  */
-  frame_size = total_size - (current_frame_info.pretend_size
-                            + current_frame_info.reg_size);
+  frame_size = (current_frame_info.total_size
+               - (current_frame_info.pretend_size
+                  + current_frame_info.reg_size));
+
   if (frame_size == 0)
     ; /* nothing to do */
-  else if (frame_size <= 128)
-    fprintf (file, "\taddi %s,%s%d\n",
-            sp_str, IMMEDIATE_PREFIX, -frame_size);
   else if (frame_size <= 32768)
-    fprintf (file, "\tadd3 %s,%s,%s%d\n",
-            sp_str, sp_str, IMMEDIATE_PREFIX, -frame_size);
+    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+                          GEN_INT (-frame_size)));
   else
-    fprintf (file, "\tld24 %s,%s%d\n\tsub %s,%s\n",
-            reg_names[PROLOGUE_TMP_REGNUM],
-            IMMEDIATE_PREFIX, frame_size,
-            sp_str, reg_names[PROLOGUE_TMP_REGNUM]);
+    {
+      rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
+      emit_insn (gen_movsi (tmp, GEN_INT (frame_size)));
+      emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
+    }
 
   if (frame_pointer_needed)
-    fprintf (file, "\tmv %s,%s\n", fp_str, sp_str);
+    emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
+
+  if (profile_flag || profile_block_flag)
+    emit_insn (gen_blockage ());
+}
+
+\f
+/* Set up the stack and frame pointer (if desired) for the function.
+   Note, if this is changed, you need to mirror the changes in
+   m32r_compute_frame_size which calculates the prolog size.  */
+
+void
+m32r_output_function_prologue (file, size)
+     FILE * file;
+     int    size;
+{
+  enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl);
+
+  /* If this is an interrupt handler, mark it as such.  */
+  if (M32R_INTERRUPT_P (fn_type))
+    {
+      fprintf (file, "\t%s interrupt handler\n",
+              ASM_COMMENT_START);
+    }
+
+  if (! current_frame_info.initialized)
+    m32r_compute_frame_size (size);
 
-  fprintf (file, "\t%s END PROLOGUE\n", ASM_COMMENT_START);
+  /* This is only for the human reader.  */
+  fprintf (file,
+          "\t%s PROLOGUE, vars= %d, regs= %d, args= %d, extra= %d\n",
+          ASM_COMMENT_START,
+          current_frame_info.var_size,
+          current_frame_info.reg_size / 4,
+          current_frame_info.args_size,
+          current_frame_info.extra_size);
 }
 \f
 /* Do any necessary cleanup after a function to restore stack, frame,
@@ -1695,6 +1779,8 @@ m32r_print_operand (file, x, code)
      rtx    x;
      int    code;
 {
+  rtx addr;
+
   switch (code)
     {
     case 'R' :
@@ -1866,16 +1952,34 @@ m32r_print_operand (file, x, code)
       break;
 
     case MEM :
-      fprintf (file, "@(");
-      if (GET_CODE (XEXP (x, 0)) == PRE_INC)
-       output_address (plus_constant (XEXP (XEXP (x, 0), 0),
-                                      GET_MODE_SIZE (GET_MODE (x))));
-      else if (GET_CODE (XEXP (x, 0)) == PRE_DEC)
-       output_address (plus_constant (XEXP (XEXP (x, 0), 0),
-                                      - GET_MODE_SIZE (GET_MODE (x))));
+      addr = XEXP (x, 0);
+      if (GET_CODE (addr) == PRE_INC)
+       {
+         if (GET_CODE (XEXP (addr, 0)) != REG)
+           abort ();
+
+         fprintf (file, "@+%s", reg_names[REGNO (XEXP (addr, 0))]);
+       }
+      else if (GET_CODE (addr) == PRE_DEC)
+       {
+         if (GET_CODE (XEXP (addr, 0)) != REG)
+           abort ();
+
+         fprintf (file, "@-%s", reg_names[REGNO (XEXP (addr, 0))]);
+       }
+      else if (GET_CODE (addr) == POST_INC)
+       {
+         if (GET_CODE (XEXP (addr, 0)) != REG)
+           abort ();
+
+         fprintf (file, "@%s+", reg_names[REGNO (XEXP (addr, 0))]);
+       }
       else
-       output_address (XEXP (x, 0));
-      fputc (')', file);
+       {
+         fputs ("@(", file);
+         output_address (XEXP (x, 0));
+         fputc (')', file);
+       }
       break;
 
     case CONST_DOUBLE :
@@ -1975,11 +2079,16 @@ m32r_print_operand_address (file, addr)
       fputs (reg_names[REGNO (XEXP (addr, 0))], file);
       break;
 
-    case PRE_INC :
-    case PRE_DEC :
-      /* We shouldn't get here as we've lost the mode of the memory object
-        (which says how much to inc/dec by).  */
-      abort ();
+    case PRE_INC :     /* Assume SImode */
+      fprintf (file, "+%s", reg_names[REGNO (XEXP (addr, 0))]);
+      break;
+
+    case PRE_DEC :     /* Assume SImode */
+      fprintf (file, "-%s", reg_names[REGNO (XEXP (addr, 0))]);
+      break;
+
+    case POST_INC :    /* Assume SImode */
+      fprintf (file, "%s+", reg_names[REGNO (XEXP (addr, 0))]);
       break;
 
     default :
index e5dfc20..4e14770 100644 (file)
@@ -606,16 +606,17 @@ extern enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER];
 #define INT32_P(X) ((X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \
                    && (X) <= (unsigned HOST_WIDE_INT) 0xffffffff)
 #define UINT5_P(X) ((unsigned) (X) < 32)
+#define INVERTED_SIGNED_8BIT(VAL) ((VAL) >= -127 && (VAL) <= 128)
 
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
-((C) == 'I' ? INT8_P (VALUE)           \
- : (C) == 'J' ? INT16_P (VALUE)        \
- : (C) == 'K' ? UINT16_P (VALUE)       \
- : (C) == 'L' ? UPPER16_P (VALUE)      \
- : (C) == 'M' ? UINT24_P (VALUE)       \
- : (C) == 'N' ? INT32_P (VALUE)                \
- : (C) == 'O' ? UINT5_P (VALUE)                \
- : (C) == 'P' ? CMP_INT16_P (VALUE)    \
+#define CONST_OK_FOR_LETTER_P(VALUE, C)                                        \
+((C) == 'I' ? INT8_P (VALUE)                                           \
+ : (C) == 'J' ? INT16_P (VALUE)                                                \
+ : (C) == 'K' ? UINT16_P (VALUE)                                       \
+ : (C) == 'L' ? UPPER16_P (VALUE)                                      \
+ : (C) == 'M' ? UINT24_P (VALUE)                                       \
+ : (C) == 'N' ? INVERTED_SIGNED_8BIT (VALUE)                           \
+ : (C) == 'O' ? UINT5_P (VALUE)                                                \
+ : (C) == 'P' ? CMP_INT16_P (VALUE)                                    \
  : 0)
 
 /* Similar, but for floating constants, and defining letters G and H.
@@ -623,8 +624,8 @@ extern enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER];
    For the m32r, handle a few constants inline.
    ??? We needn't treat DI and DF modes differently, but for now we do.  */
 #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
-((C) == 'G' ? easy_di_const (VALUE) \
- : (C) == 'H' ? easy_df_const (VALUE) \
+((C) == 'G' ? easy_di_const (VALUE)                                    \
+ : (C) == 'H' ? easy_df_const (VALUE)                                  \
  : 0)
 
 /* A C expression that defines the optional machine-dependent constraint
@@ -635,19 +636,25 @@ extern enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER];
    be 0 regardless of VALUE.  */
 /* Q is for symbolic addresses loadable with ld24.
    R is for symbolic addresses when ld24 can't be used.
-   S is for an 8 bit signed integer in the range +128 to -127 */
-
-#define INVERTED_SIGNED_8BIT(VAL) ((VAL) >= -127 && (VAL) <= 128)
-
-#define EXTRA_CONSTRAINT(VALUE, C) \
-((C) == 'Q' \
- ? ((TARGET_ADDR24 && GET_CODE (VALUE) == LABEL_REF) \
-    || addr24_operand (VALUE, VOIDmode)) \
- : (C) == 'R' \
- ? ((TARGET_ADDR32 && GET_CODE (VALUE) == LABEL_REF) \
-    || addr32_operand (VALUE, VOIDmode)) \
- : (C) == 'S' \
- ?  ((GET_CODE (VALUE) == CONST_INT) && INVERTED_SIGNED_8BIT (INTVAL (VALUE))) \
+   S is unused.
+   T is for indirect of a pointer.
+   U is for pushes and pops of the stack pointer.  */
+
+#define EXTRA_CONSTRAINT(VALUE, C)                                     \
+((C) == 'Q'                                                            \
+ ? ((TARGET_ADDR24 && GET_CODE (VALUE) == LABEL_REF)                   \
+    || addr24_operand (VALUE, VOIDmode))                               \
+ : (C) == 'R'                                                          \
+ ? ((TARGET_ADDR32 && GET_CODE (VALUE) == LABEL_REF)                   \
+    || addr32_operand (VALUE, VOIDmode))                               \
+ : (C) == 'S'                                                          \
+ ? 0                                                                   \
+ : (C) == 'T'                                                          \
+ ?  (GET_CODE (VALUE) == MEM                                           \
+     && memreg_operand (VALUE, GET_MODE (VALUE)))                      \
+ : (C) == 'U'                                                          \
+ ?  (GET_CODE (VALUE) == MEM                                           \
+     && PUSH_POP_P (GET_MODE (VALUE), XEXP (VALUE, 0)))                        \
  : 0)
 \f
 /* Stack layout and stack pointer usage.  */
@@ -1069,7 +1076,7 @@ m32r_output_function_epilogue (FILE, SIZE)
 
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  */
-#define FUNCTION_PROFILER(FILE, LABELNO)
+#define FUNCTION_PROFILER(FILE, LABELNO) abort ()
 \f
 /* Trampolines.  */
 
@@ -1184,24 +1191,37 @@ do { \
 (GET_CODE (X) == CONST_INT && INT16_P (INTVAL (X)))
 
 /* local to this file */
-#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \
-(GET_CODE (X) == PLUS                          \
- && RTX_OK_FOR_BASE_P (XEXP (X, 0))            \
+#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X)                           \
+(GET_CODE (X) == PLUS                                                  \
+ && RTX_OK_FOR_BASE_P (XEXP (X, 0))                                    \
  && RTX_OK_FOR_OFFSET_P (XEXP (X, 1)))
 
 /* local to this file */
-#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X) \
-(GET_CODE (X) == LO_SUM                                \
- && RTX_OK_FOR_BASE_P (XEXP (X, 0))            \
+/* For LO_SUM addresses, do not allow them if the MODE is > 1 word,
+   since more than one instruction will be required.  */
+#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X)                           \
+(GET_CODE (X) == LO_SUM                                                        \
+ && (MODE != BLKmode && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD)                \
+ && RTX_OK_FOR_BASE_P (XEXP (X, 0))                                    \
  && CONSTANT_P (XEXP (X, 1)))
 
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ if (RTX_OK_FOR_BASE_P (X))                           \
-    goto ADDR;                                         \
-  if (LEGITIMATE_OFFSET_ADDRESS_P ((MODE), (X)))       \
-    goto ADDR;                                         \
-  if (LEGITIMATE_LO_SUM_ADDRESS_P ((MODE), (X)))       \
-    goto ADDR;                                         \
+/* local to this file */
+/* Memory address that is a push/pop of the stack pointer.  */
+#define PUSH_POP_P(MODE, X)                                            \
+((MODE) == SImode                                                      \
+ && (GET_CODE (X) == POST_INC                                          \
+     || GET_CODE (X) == PRE_INC                                                \
+     || GET_CODE (X) == PRE_DEC))
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)                                \
+{ if (RTX_OK_FOR_BASE_P (X))                                           \
+    goto ADDR;                                                         \
+  if (LEGITIMATE_OFFSET_ADDRESS_P ((MODE), (X)))                       \
+    goto ADDR;                                                         \
+  if (LEGITIMATE_LO_SUM_ADDRESS_P ((MODE), (X)))                       \
+    goto ADDR;                                                         \
+  if (PUSH_POP_P ((MODE), (X)))                                                \
+    goto ADDR;                                                         \
 }
 
 /* Try machine-dependent ways of modifying an illegitimate address
@@ -1223,14 +1243,13 @@ do { \
 
 /* Go to LABEL if ADDR (a legitimate address expression)
    has an effect that depends on the machine mode it is used for.  */
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
-do {                                   \
-  if (GET_CODE (ADDR) == PRE_DEC)      \
-    goto LABEL;                                \
-  if (GET_CODE (ADDR) == PRE_INC)      \
-    goto LABEL;                                \
-  if (GET_CODE (ADDR) == POST_INC)     \
-    goto LABEL;                                \
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)                      \
+do {                                                                   \
+  if (GET_CODE (ADDR) == PRE_DEC                                       \
+      || GET_CODE (ADDR) == PRE_INC                                    \
+      || GET_CODE (ADDR) == POST_INC                                   \
+      || GET_CODE (ADDR) == LO_SUM)                                    \
+    goto LABEL;                                                                \
 } while (0)
 \f
 /* Condition code usage.  */
@@ -1286,7 +1305,7 @@ do {                                      \
 /* Compute the cost of moving data between registers and memory.  */
 /* Memory is 3 times as expensive as registers.
    ??? Is that the right way to look at it?  */
-#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
+#define MEMORY_MOVE_COST(MODE,CLASS,IN_P) \
 (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD ? 6 : 12)
 
 /* The cost of a branch insn.  */
@@ -1355,7 +1374,10 @@ do {                                     \
 #define HAIFA_P 0
 #endif
 
-/* Indicate how many instructions can be issued at the same time.  */
+/* Indicate how many instructions can be issued at the same time.
+   This is 1/2 of a lie.  The m32r can issue only 1 long insn at
+   once, but 2.  However doing so allows the scheduler to group
+   the two short insns together.  */
 #define ISSUE_RATE 2
 
 /* When the `length' insn attribute is used, this macro specifies the
@@ -1635,6 +1657,27 @@ do {                                                     \
   fprintf (FILE, "%s%s", USER_LABEL_PREFIX, real_name);        \
 } while (0)           
 
+/* CYGNUS LOCAL -- m32rx/meissner */
+/* For the m32r if -Os, don't force line number label to begin
+   at the beginning of the word.  */
+
+#undef ASM_OUTPUT_SOURCE_LINE
+#define ASM_OUTPUT_SOURCE_LINE(file, line)                             \
+do                                                                     \
+  {                                                                    \
+    static int sym_lineno = 1;                                         \
+    fprintf (file, ".stabn 68,0,%d,.LM%d-",                            \
+            line, sym_lineno);                                         \
+    assemble_name (file,                                               \
+                  XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));\
+    fprintf (file,                                                     \
+            (optimize_size) ? "\n\t.debugsym .LM%d\n" : "\n.LM%d:\n",  \
+            sym_lineno);                                               \
+    sym_lineno += 1;                                                   \
+  }                                                                    \
+while (0)
+/* END CYGNUS LOCAL -- m32rx/meissner */
+
 /* Store in OUTPUT a string (made with alloca) containing
    an assembler-name for a local static variable named NAME.
    LABELNO is an integer which is different for each call.  */
@@ -1998,6 +2041,7 @@ extern int  small_insn_p                  PROTO((Rtx, int));
 extern int  large_insn_p                       PROTO((Rtx, int));
 extern int  m32r_select_cc_mode                        PROTO((int, Rtx, Rtx));
 extern Rtx  gen_compare                                PROTO((int, Rtx, Rtx, int));
+extern Rtx  gen_split_move_double              PROTO((Rtx *));
 extern int  function_arg_partial_nregs         PROTO((CUMULATIVE_ARGS *,
                                                       int, Tree, int));
 extern void m32r_setup_incoming_varargs                PROTO((CUMULATIVE_ARGS *,
@@ -2008,6 +2052,7 @@ extern enum m32r_function_type m32r_compute_function_type
                                                PROTO((Tree));
 extern unsigned m32r_compute_frame_size                PROTO((int));
 extern int  m32r_first_insn_address            PROTO((void));
+extern void m32r_expand_prologue               PROTO((void));
 extern void m32r_output_function_prologue      STDIO_PROTO((FILE *, int));
 extern void m32r_output_function_epilogue      STDIO_PROTO((FILE *, int));
 extern void m32r_finalize_pic                  PROTO((void));
index 49f71d6..3c49e54 100644 (file)
 ;; 0 - blockage
 ;; 1 - flush_icache
 ;; 2 - load_sda_base
+;; 3 - setting carry in addx/subx instructions.
 \f
 ;; Insn type.  Used to default other attribute values.
-;; move4 = 4 byte move
 (define_attr "type"
-  "move,move4,load,store,unary,binary,compare,shift,mul,div,uncond_branch,branch,call,multi,misc"
+  "int2,int4,load2,load4,load8,store2,store4,store8,shift2,shift4,mul2,div4,uncond_branch,branch,call,multi,misc"
   (const_string "misc"))
 
 ;; Length in bytes.
 (define_attr "length" ""
-  (cond [(eq_attr "type" "move,unary,shift,mul,div")
+  (cond [(eq_attr "type" "int2,load2,store2,shift2,mul2")
         (const_int 2)
 
-        (eq_attr "type" "binary")
-        (if_then_else (match_operand 2 "register_operand" "")
-                      (const_int 2) (const_int 4))
-
-        (eq_attr "type" "compare")
-        (if_then_else (match_operand 1 "register_operand" "")
-                      (const_int 2) (const_int 4))
-
-        (eq_attr "type" "load")
-        (if_then_else (match_operand 1 "memreg_operand" "")
-                      (const_int 2) (const_int 4))
-
-        (eq_attr "type" "store")
-        (if_then_else (match_operand 0 "memreg_operand" "")
-                      (const_int 2) (const_int 4))
+        (eq_attr "type" "int4,load4,store4,shift4,div4")
+        (const_int 4)
 
         (eq_attr "type" "multi")
         (const_int 8)
 
 ;; Whether an instruction is 16-bit or 32-bit
 (define_attr "insn_size" "short,long"
-  (if_then_else (eq_attr "length" "2")
+  (if_then_else (eq_attr "type" "int2,load2,store2,shift2,mul2")
                (const_string "short")
                (const_string "long")))
 
+(define_attr "debug" "no,yes"
+  (const (symbol_ref "(TARGET_DEBUG != 0)")))
+
+(define_attr "opt_size" "no,yes"
+  (const (symbol_ref "(optimize_size != 0)")))
+
 (define_attr "m32r" "no,yes"
   (const (symbol_ref "(TARGET_M32R != 0)")))
 
 ;; (define_function_unit {name} {multiplicity} {simulataneity} {test}
 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
 
-;; References to loaded registers should wait a cycle.
-;; Memory with load-delay of 1 (i.e. 2 cycle load).
-(define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0)
-
 ;; Hack to get GCC to better pack the instructions.
 ;; We pretend there is a separate long function unit that conflicts with
 ;; both the left and right 16 bit insn slots.
 
-(define_function_unit "left" 1 1
-  (eq_attr "length" "2")
+(define_function_unit "short" 2 2
+  (and (eq_attr "m32r" "yes")
+       (and (eq_attr "insn_size" "short")
+           (eq_attr "type" "!load2")))
   1 0
-  [(not (eq_attr "length" "2"))])
+  [(eq_attr "insn_size" "long")])
 
-(define_function_unit "right" 1 1
-  (eq_attr "length" "2")
-  1 0
-  [(not (eq_attr "length" "2"))])
+(define_function_unit "short" 2 2      ;; load delay of 1 clock for mem execution + 1 clock for WB
+  (and (eq_attr "m32r" "yes")
+       (eq_attr "type" "load2"))
+  3 0
+  [(eq_attr "insn_size" "long")])
 
 (define_function_unit "long" 1 1
-  (not (eq_attr "length" "2"))
+  (and (eq_attr "m32r" "yes")
+       (and (eq_attr "insn_size" "long")
+           (eq_attr "type" "!load4,load8")))
   1 0
-  [(eq_attr "length" "2")])
+  [(eq_attr "insn_size" "short")])
+
+(define_function_unit "long" 1 1       ;; load delay of 1 clock for mem execution + 1 clock for WB
+  (and (eq_attr "m32r" "yes")
+       (and (eq_attr "insn_size" "long")
+           (eq_attr "type" "load4,load8")))
+  3 0
+  [(eq_attr "insn_size" "short")])
+
+
+\f
+;; Instruction grouping
 
 \f
 ;; Expand prologue as RTL
-;; ??? Unfinished.
-
-;(define_expand "prologue"
-;  [(const_int 1)]
-;  ""
-;  "
-;{
-;}")
+(define_expand "prologue"
+  [(const_int 1)]
+  ""
+  "
+{
+  m32r_expand_prologue ();
+  DONE;
+}")
+
 \f
 ;; Move instructions.
 ;;
 }")
 
 (define_insn "*movqi_insn"
-  [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,r,m")
-       (match_operand:QI 1 "move_src_operand" "r,I,JQR,m,r"))]
+  [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,r,r,T,m")
+       (match_operand:QI 1 "move_src_operand" "r,I,JQR,T,m,r,r"))]
   "register_operand (operands[0], QImode) || register_operand (operands[1], QImode)"
   "@
    mv %0,%1
    ldi %0,%#%1
    ldi %0,%#%1
    ldub %0,%1
+   ldub %0,%1
+   stb %1,%0
    stb %1,%0"
-  [(set_attr "type" "move,move,move4,load,store")])
+  [(set_attr "type" "int2,int2,int4,load2,load4,store2,store4")
+   (set_attr "length" "2,2,4,2,4,2,4")])
 
 (define_expand "movhi"
   [(set (match_operand:HI 0 "general_operand" "")
 }")
 
 (define_insn "*movhi_insn"
-  [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,r,r,m")
-       (match_operand:HI 1 "move_src_operand" "r,I,JQR,K,m,r"))]
+  [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,r,r,r,T,m")
+       (match_operand:HI 1 "move_src_operand" "r,I,JQR,K,T,m,r,r"))]
   "register_operand (operands[0], HImode) || register_operand (operands[1], HImode)"
   "@
    mv %0,%1
    ldi %0,%#%1
    ld24 %0,%#%1
    lduh %0,%1
+   lduh %0,%1
+   sth %1,%0
    sth %1,%0"
-  [(set_attr "type" "move,move,move4,move4,load,store")])
+  [(set_attr "type" "int2,int2,int4,int4,load2,load4,store2,store4")
+   (set_attr "length" "2,2,4,4,2,4,2,4")])
+
+(define_expand "movsi_push"
+  [(set (mem:SI (pre_dec:SI (match_operand:SI 0 "register_operand" "")))
+       (match_operand:SI 1 "register_operand" ""))]
+  ""
+  "")
+
+(define_expand "movsi_pop"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (mem:SI (post_inc:SI (match_operand:SI 1 "register_operand" ""))))]
+  ""
+  "")
 
 (define_expand "movsi"
   [(set (match_operand:SI 0 "general_operand" "")
     }
 }")
 
-(define_insn "*movsi_insn"
-  [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,r,r,r,r,m")
 ;; ??? Do we need a const_double constraint here for large unsigned values?
-       (match_operand:SI 1 "move_src_operand" "r,I,J,MQ,L,N,m,r"))]
+(define_insn "*movsi_insn"
+  [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,r,r,r,r,r,r,T,U,m")
+       (match_operand:SI 1 "move_src_operand" "r,I,J,MQ,L,n,T,U,m,r,r,r"))]
   "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)"
-  "@
-   mv %0,%1
-   ldi %0,%#%1 ; %X1
-   ldi %0,%#%1 ; %X1
-   ld24 %0,%#%1 ; %X1
-   seth %0,%#%T1
-   seth %0,%#%T1\;or3 %0,%0,%#%B1
-   ld %0,%1
-   st %1,%0"
-  [(set_attr "type" "move,move,move4,move4,move4,multi,load,store")])
+  "*
+{
+  if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == SUBREG)
+    {
+      switch (GET_CODE (operands[1]))
+       {
+         HOST_WIDE_INT value;
+
+         default:
+           break;
+
+         case REG:
+         case SUBREG:
+           return \"mv %0,%1\";
+
+         case MEM:
+           return \"ld %0,%1\";
+
+         case CONST_INT:
+           value = INTVAL (operands[1]);
+           if (INT16_P (value))
+             return \"ldi %0,%#%1\\t; %X1\";
+
+           if (UINT24_P (value))
+             return \"ld24 %0,%#%1\\t; %X1\";
+
+           if (UPPER16_P (value))
+             return \"seth %0,%#%T1\\t; %X1\";
+
+           return \"#\";
+
+         case CONST:
+         case SYMBOL_REF:
+         case LABEL_REF:
+           if (TARGET_ADDR24)
+             return \"ld24 %0,%#%1\";
+
+           return \"#\";
+       }
+    }
+
+  else if (GET_CODE (operands[0]) == MEM
+          && (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG))
+    return \"st %1,%0\";
+
+  fatal_insn (\"bad movsi insn\", insn);
+}"
+  [(set_attr "type" "int2,int2,int4,int4,int4,multi,load2,load2,load4,store2,store2,store4")
+   (set_attr "length" "2,2,4,4,4,8,2,2,4,2,2,4")])
 
 ; Try to use a four byte / two byte pair for constants not loadable with
 ; ldi, ld24, seth.
   operands[3] = GEN_INT ((val) & 0xffff);
 }")
 
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (match_operand:SI 1 "seth_add3_operand" "i"))]
+  "TARGET_ADDR32"
+  [(set (match_dup 0)
+       (high:SI (match_dup 1)))
+   (set (match_dup 0)
+       (lo_sum:SI (match_dup 0)
+                  (match_dup 1)))]
+  "")
+
 ;; Small data area support.
 ;; The address of _SDA_BASE_ is loaded into a register and all objects in
 ;; the small data area are indexed off that.  This is done for each reference
        (unspec [(const_int 0)] 2))]
   ""
   "ld24 %0,#_SDA_BASE_"
-  [(set_attr "type" "move4")])
+  [(set_attr "type" "int4")
+   (set_attr "length" "4")])
 
 ;; 32 bit address support.
 
        (high:SI (match_operand 1 "symbolic_operand" "")))]
   ""
   "seth %0,%#shigh(%1)"
-  [(set_attr "type" "move4")])
+  [(set_attr "type" "int4")
+   (set_attr "length" "4")])
 
 (define_insn "lo_sum_si"
   [(set (match_operand:SI 0 "register_operand" "=r")
                   (match_operand:SI 2 "immediate_operand" "in")))]
   ""
   "add3 %0,%1,%#%B2"
-  [(set_attr "length" "4")])
+  [(set_attr "type" "int4")
+   (set_attr "length" "4")])
 
 (define_expand "movdi"
   [(set (match_operand:DI 0 "general_operand" "")
 
   if (GET_CODE (operands[0]) == MEM)
     operands[1] = force_reg (DImode, operands[1]);
-
-  if (CONSTANT_P (operands[1])
-      && ! easy_di_const (operands[1]))
-    {
-      rtx mem = force_const_mem (DImode, operands[1]);
-      rtx reg = ((reload_in_progress || reload_completed)
-                ? copy_to_suggested_reg (XEXP (mem, 0),
-                                         gen_rtx (REG, Pmode, REGNO (operands[0])),
-                                         Pmode)
-                : force_reg (Pmode, XEXP (mem, 0)));
-      operands[1] = change_address (mem, DImode, reg);
-    }
 }")
 
 (define_insn "*movdi_insn"
-  [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m")
-       (match_operand:DI 1 "move_double_src_operand" "r,nG,m,r"))]
+  [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,r,m")
+       (match_operand:DI 1 "move_double_src_operand" "r,nG,F,m,r"))]
   "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)"
-  "*
-{
-  switch (which_alternative)
-    {
-    case 0 :
-      /* We normally copy the low-numbered register first.  However, if
-        the first register operand 0 is the same as the second register of
-        operand 1, we must copy in the opposite order.  */
-      if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-       return \"mv %R0,%R1\;mv %0,%1\";
-      else
-       return \"mv %0,%1\;mv %R0,%R1\";
-    case 1 :
-      return \"#\";
-    case 2 :
-      /* If the low-address word is used in the address, we must load it
-        last.  Otherwise, load it first.  Note that we cannot have
-        auto-increment in that case since the address register is known to be
-        dead.  */
-      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-                            operands [1], 0))
-       {
-         return \"ld %R0,%R1\;ld %0,%1\";
-       }
-      else
-       {
-         /* Try to use auto-inc addressing if we can.  */
-         if (GET_CODE (XEXP (operands[1], 0)) == REG
-             && dead_or_set_p (insn, XEXP (operands[1], 0)))
-           {
-             operands[1] = XEXP (operands[1], 0);
-             return \"ld %0,@%1+\;ld %R0,@%1\";
-           }
-         return \"ld %0,%1\;ld %R0,%R1\";
-       }
-    case 3 :
-      /* Try to use auto-inc addressing if we can.  */
-      if (GET_CODE (XEXP (operands[0], 0)) == REG
-         && dead_or_set_p (insn, XEXP (operands[0], 0)))
-       {
-         operands[0] = XEXP (operands[0], 0);
-         return \"st %1,@%0\;st %R1,@+%0\";
-       }
-      return \"st %1,%0\;st %R1,%R0\";
-    }
-}"
-  [(set_attr "type" "multi,multi,multi,multi")
-   (set_attr "length" "4,4,6,6")])
+  "#"
+  [(set_attr "type" "multi,multi,multi,load8,store8")
+   (set_attr "length" "4,4,16,6,6")])
 
 (define_split
-  [(set (match_operand:DI 0 "register_operand" "")
-       (match_operand:DI 1 "const_double_operand" ""))]
+  [(set (match_operand:DI 0 "move_dest_operand" "")
+       (match_operand:DI 1 "move_double_src_operand" ""))]
   "reload_completed"
-  [(set (match_dup 2) (match_dup 4))
-   (set (match_dup 3) (match_dup 5))]
-  "
-{
-  operands[2] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0);
-  operands[3] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0);
-  split_double (operands[1], operands + 4, operands + 5);
-}")
+  [(match_dup 2)]
+  "operands[2] = gen_split_move_double (operands);")
 \f
 ;; Floating point move insns.
 
 }")
 
 (define_insn "*movsf_insn"
-  [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m")
-       (match_operand:SF 1 "move_src_operand" "r,F,m,r"))]
+  [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,r,T,m")
+       (match_operand:SF 1 "move_src_operand" "r,F,T,m,r,r"))]
   "register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)"
-  "*
-{
-  switch (which_alternative)
-    {
-    case 0 :
-      return \"mv %0,%1\";
-    case 1 :
-      {
-       REAL_VALUE_TYPE r;
-       long l;
-       REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
-       REAL_VALUE_TO_TARGET_SINGLE (r, l);
-       operands[1] = GEN_INT (l);
-       if (l == 0)
-         return \"ldi %0,%#0\";
-       if ((l & 0xffff) == 0)
-         return \"seth %0,%#%T1\";
-       else
-         return \"seth %0,%#%T1\;or3 %0,%0,%#%B1\";
-      }
-    case 2 :
-      return \"ld %0,%1\";
-    case 3 :
-      return \"st %1,%0\";
-    }
-}"
+  "@
+   mv %0,%1
+   #
+   ld %0,%1
+   ld %0,%1
+   st %1,%0
+   st %1,%0"
   ;; ??? Length of alternative 1 is either 2, 4 or 8.
-  [(set_attr "type" "move,multi,load,store")])
+  [(set_attr "type" "int2,multi,load2,load4,store2,store4")
+   (set_attr "length" "2,8,2,4,2,4")])
+
+(define_split
+  [(set (match_operand:SF 0 "register_operand" "")
+       (match_operand:SF 1 "const_double_operand" ""))]
+  "reload_completed"
+  [(set (match_dup 2) (match_dup 3))]
+  "
+{
+  long l;
+  REAL_VALUE_TYPE rv;
+
+  REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
+  REAL_VALUE_TO_TARGET_SINGLE (rv, l);
+
+  operands[2] = operand_subword (operands[0], 0, 0, SFmode);
+  operands[3] = GEN_INT (l);
+}")
 
 (define_expand "movdf"
   [(set (match_operand:DF 0 "general_operand" "")
 
   if (GET_CODE (operands[0]) == MEM)
     operands[1] = force_reg (DFmode, operands[1]);
-
-  if (GET_CODE (operands[1]) == CONST_DOUBLE
-      && ! easy_df_const (operands[1]))
-    {
-      rtx mem = force_const_mem (DFmode, operands[1]);
-      rtx reg = ((reload_in_progress || reload_completed)
-                ? copy_to_suggested_reg (XEXP (mem, 0),
-                                         gen_rtx (REG, Pmode, REGNO (operands[0])),
-                                         Pmode)
-                : force_reg (Pmode, XEXP (mem, 0)));
-      operands[1] = change_address (mem, DFmode, reg);
-    }
 }")
 
 (define_insn "*movdf_insn"
   [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m")
-       (match_operand:DF 1 "move_double_src_operand" "r,H,m,r"))]
+       (match_operand:DF 1 "move_double_src_operand" "r,F,m,r"))]
   "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)"
-  "*
-{
-  switch (which_alternative)
-    {
-    case 0 :
-      /* We normally copy the low-numbered register first.  However, if
-        the first register operand 0 is the same as the second register of
-        operand 1, we must copy in the opposite order.  */
-      if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-       return \"mv %R0,%R1\;mv %0,%1\";
-      else
-       return \"mv %0,%1\;mv %R0,%R1\";
-    case 1 :
-      {
-       REAL_VALUE_TYPE r;
-       long l[2];
-       REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
-       REAL_VALUE_TO_TARGET_DOUBLE (r, l);
-       operands[1] = GEN_INT (l[0]);
-       if (l[0] == 0 && l[1] == 0)
-         return \"ldi %0,%#0\;ldi %R0,%#0\";
-       else if (l[1] != 0)
-         abort ();
-       else if ((l[0] & 0xffff) == 0)
-         return \"seth %0,%#%T1\;ldi %R0,%#0\";
-       else
-         abort ();
-      }
-    case 2 :
-      /* If the low-address word is used in the address, we must load it
-        last.  Otherwise, load it first.  Note that we cannot have
-        auto-increment in that case since the address register is known to be
-        dead.  */
-      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-                            operands [1], 0))
-       {
-         return \"ld %R0,%R1\;ld %0,%1\";
-       }
-      else
-       {
-         /* Try to use auto-inc addressing if we can.  */
-         if (GET_CODE (XEXP (operands[1], 0)) == REG
-             && dead_or_set_p (insn, XEXP (operands[1], 0)))
-           {
-             operands[1] = XEXP (operands[1], 0);
-             return \"ld %0,@%1+\;ld %R0,@%1\";
-           }
-         return \"ld %0,%1\;ld %R0,%R1\";
-       }
-    case 3 :
-      /* Try to use auto-inc addressing if we can.  */
-      if (GET_CODE (XEXP (operands[0], 0)) == REG
-         && dead_or_set_p (insn, XEXP (operands[0], 0)))
-       {
-         operands[0] = XEXP (operands[0], 0);
-         return \"st %1,@%0\;st %R1,@+%0\";
-       }
-      return \"st %1,%0\;st %R1,%R0\";
-    }
-}"
-  [(set_attr "type" "multi,multi,multi,multi")
-   (set_attr "length" "4,6,6,6")])
+  "#"
+  [(set_attr "type" "multi,multi,load8,store8")
+   (set_attr "length" "4,16,6,6")])
+
+(define_split
+  [(set (match_operand:DF 0 "move_dest_operand" "")
+       (match_operand:DF 1 "move_double_src_operand" ""))]
+  "reload_completed"
+  [(match_dup 2)]
+  "operands[2] = gen_split_move_double (operands);")
 \f
 ;; Zero extension instructions.
 
 (define_insn "zero_extendqihi2"
-  [(set (match_operand:HI 0 "register_operand" "=r,r")
-       (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+  [(set (match_operand:HI 0 "register_operand" "=r,r,r")
+       (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,T,m")))]
   ""
   "@
    and3 %0,%1,%#255
+   ldub %0,%1
    ldub %0,%1"
-  [(set_attr "type" "unary,load")
-   (set_attr "length" "4,*")])
+  [(set_attr "type" "int4,load2,load4")
+   (set_attr "length" "4,2,4")])
 
 (define_insn "zero_extendqisi2"
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,T,m")))]
   ""
   "@
    and3 %0,%1,%#255
+   ldub %0,%1
    ldub %0,%1"
-  [(set_attr "type" "unary,load")
-   (set_attr "length" "4,*")])
+  [(set_attr "type" "int4,load2,load4")
+   (set_attr "length" "4,2,4")])
 
 (define_insn "zero_extendhisi2"
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+       (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,T,m")))]
   ""
   "@
    and3 %0,%1,%#65535
+   lduh %0,%1
    lduh %0,%1"
-  [(set_attr "type" "unary,load")
-   (set_attr "length" "4,*")])
+  [(set_attr "type" "int4,load2,load4")
+   (set_attr "length" "4,2,4")])
 \f
 ;; Sign extension instructions.
 ;; ??? See v850.md.
 }")
 
 (define_insn "*sign_extendqihi2_insn"
-  [(set (match_operand:HI 0 "register_operand" "=r")
-       (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
+  [(set (match_operand:HI 0 "register_operand" "=r,r")
+       (sign_extend:HI (match_operand:QI 1 "memory_operand" "T,m")))]
   ""
   "ldb %0,%1"
-  [(set_attr "type" "load")])
+  [(set_attr "type" "load2,load4")
+   (set_attr "length" "2,4")])
 
 (define_expand "extendqisi2"
   [(set (match_operand:SI 0 "register_operand" "")
 }")
 
 (define_insn "*sign_extendqisi2_insn"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (sign_extend:SI (match_operand:QI 1 "memory_operand" "T,m")))]
   ""
   "ldb %0,%1"
-  [(set_attr "type" "load")])
+  [(set_attr "type" "load2,load4")
+   (set_attr "length" "2,4")])
 
 (define_expand "extendhisi2"
   [(set (match_operand:SI 0 "register_operand" "")
 }")
 
 (define_insn "*sign_extendhisi2_insn"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (sign_extend:SI (match_operand:HI 1 "memory_operand" "T,m")))]
   ""
   "ldh %0,%1"
-  [(set_attr "type" "load")])
+  [(set_attr "type" "load2,load4")
+   (set_attr "length" "2,4")])
 \f
 ;; Arithmetic instructions.
 
    add %0,%2
    addi %0,%#%2
    add3 %0,%1,%#%2"
-  [(set_attr "type" "binary")
+  [(set_attr "type" "int2,int2,int4")
    (set_attr "length" "2,2,4")])
 
 ;(define_split
                 (match_operand:DI 2 "register_operand" "r")))
    (clobber (reg:CC 17))]
   ""
-  "*
-{
-  /* ??? The cmp clears the condition bit.  Can we speed up somehow?  */
-  return \"cmp %L0,%L0\;addx %L0,%L2\;addx %H0,%H2\";
-}"
-  [(set_attr "type" "binary")
+  "#"
+  [(set_attr "type" "multi")
    (set_attr "length" "6")])
 
+;; ??? The cmp clears the condition bit.  Can we speed up somehow?
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "register_operand" "")))
+   (clobber (match_operand 3 "" ""))]
+  "reload_completed"
+  [(parallel [(set (match_dup 3)
+                  (const_int 0))
+             (use (match_dup 4))])
+   (parallel [(set (match_dup 4)
+                  (plus:SI (match_dup 4)
+                           (plus:SI (match_dup 5)
+                                    (match_dup 3))))
+             (set (match_dup 3)
+                  (unspec [(const_int 0)] 3))])
+   (parallel [(set (match_dup 6)
+                  (plus:SI (match_dup 6)
+                           (plus:SI (match_dup 7)
+                                    (match_dup 3))))
+             (set (match_dup 3)
+                  (unspec [(const_int 0)] 3))])]
+  "
+{
+  operands[4] = operand_subword (operands[0], (WORDS_BIG_ENDIAN != 0), 0, DImode);
+  operands[5] = operand_subword (operands[2], (WORDS_BIG_ENDIAN != 0), 0, DImode);
+  operands[6] = operand_subword (operands[0], (WORDS_BIG_ENDIAN == 0), 0, DImode);
+  operands[7] = operand_subword (operands[2], (WORDS_BIG_ENDIAN == 0), 0, DImode);
+}")
+
+(define_insn "*clear_c"
+  [(set (reg:CC 17)
+       (const_int 0))
+   (use (match_operand:SI 0 "register_operand" "r"))]
+  ""
+  "cmp %0,%0"
+  [(set_attr "type" "int2")
+   (set_attr "length" "2")])
+
+(define_insn "*add_carry"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (match_operand:SI 1 "register_operand" "%0")
+                (plus:SI (match_operand:SI 2 "register_operand" "r")
+                         (reg:CC 17))))
+   (set (reg:CC 17)
+       (unspec [(const_int 0)] 3))]
+  ""
+  "addx %0,%2"
+  [(set_attr "type" "int2")
+   (set_attr "length" "2")])
+
 (define_insn "subsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (minus:SI (match_operand:SI 1 "register_operand" "0")
                  (match_operand:SI 2 "register_operand" "r")))]
   ""
   "sub %0,%2"
-  [(set_attr "type" "binary")])
+  [(set_attr "type" "int2")
+   (set_attr "length" "2")])
 
 (define_insn "subdi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
                  (match_operand:DI 2 "register_operand" "r")))
    (clobber (reg:CC 17))]
   ""
-  "*
-{
-  /* ??? The cmp clears the condition bit.  Can we speed up somehow?  */
-  return \"cmp %L0,%L0\;subx %L0,%L2\;subx %H0,%H2\";
-}"
-  [(set_attr "type" "binary")
+  "#"
+  [(set_attr "type" "multi")
    (set_attr "length" "6")])
+
+;; ??? The cmp clears the condition bit.  Can we speed up somehow?
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+       (minus:DI (match_operand:DI 1 "register_operand" "")
+                 (match_operand:DI 2 "register_operand" "")))
+   (clobber (match_operand 3 "" ""))]
+  "reload_completed"
+  [(parallel [(set (match_dup 3)
+                  (const_int 0))
+             (use (match_dup 4))])
+   (parallel [(set (match_dup 4)
+                  (minus:SI (match_dup 4)
+                            (minus:SI (match_dup 5)
+                                      (match_dup 3))))
+             (set (match_dup 3)
+                  (unspec [(const_int 0)] 3))])
+   (parallel [(set (match_dup 6)
+                  (minus:SI (match_dup 6)
+                            (minus:SI (match_dup 7)
+                                      (match_dup 3))))
+             (set (match_dup 3)
+                  (unspec [(const_int 0)] 3))])]
+  "
+{
+  operands[4] = operand_subword (operands[0], (WORDS_BIG_ENDIAN != 0), 0, DImode);
+  operands[5] = operand_subword (operands[2], (WORDS_BIG_ENDIAN != 0), 0, DImode);
+  operands[6] = operand_subword (operands[0], (WORDS_BIG_ENDIAN == 0), 0, DImode);
+  operands[7] = operand_subword (operands[2], (WORDS_BIG_ENDIAN == 0), 0, DImode);
+}")
+
+(define_insn "*sub_carry"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (minus:SI (match_operand:SI 1 "register_operand" "%0")
+                 (minus:SI (match_operand:SI 2 "register_operand" "r")
+                           (reg:CC 17))))
+   (set (reg:CC 17)
+       (unspec [(const_int 0)] 3))]
+  ""
+  "subx %0,%2"
+  [(set_attr "type" "int2")
+   (set_attr "length" "2")])
 \f
 ; Multiply/Divide instructions.
 
                 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
   ""
   "mullo %1,%2\;mvfacmi %0"
-  [(set_attr "type" "mul")
+  [(set_attr "type" "multi")
    (set_attr "length" "4")])
 
 (define_insn "mulsi3"
                 (match_operand:SI 2 "register_operand" "r")))]
   ""
   "mul %0,%2"
-  [(set_attr "type" "mul")])
+  [(set_attr "type" "mul2")
+   (set_attr "length" "2")])
 
 (define_insn "divsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
                (match_operand:SI 2 "register_operand" "r")))]
   ""
   "div %0,%2"
-  [(set_attr "type" "div")])
+  [(set_attr "type" "div4")
+   (set_attr "length" "4")])
 
 (define_insn "udivsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
                 (match_operand:SI 2 "register_operand" "r")))]
   ""
   "divu %0,%2"
-  [(set_attr "type" "div")])
+  [(set_attr "type" "div4")
+   (set_attr "length" "4")])
 
 (define_insn "modsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
                (match_operand:SI 2 "register_operand" "r")))]
   ""
   "rem %0,%2"
-  [(set_attr "type" "div")])
+  [(set_attr "type" "div4")
+   (set_attr "length" "4")])
 
 (define_insn "umodsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
                 (match_operand:SI 2 "register_operand" "r")))]
   ""
   "remu %0,%2"
-  [(set_attr "type" "div")])
+  [(set_attr "type" "div4")
+   (set_attr "length" "4")])
 \f
 ;; Boolean instructions.
 ;;
   ""
   "@
    and %0,%2
-   and3 %0,%1,%#%2 ; %X2"
-  [(set_attr "type" "binary")])
+   and3 %0,%1,%#%2\\t; %X2"
+  [(set_attr "type" "int2,int4")
+   (set_attr "length" "2,4")])
 
 (define_insn "iorsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
   ""
   "@
    or %0,%2
-   or3 %0,%1,%#%2 ; %X2"
-  [(set_attr "type" "binary")])
+   or3 %0,%1,%#%2\\t; %X2"
+  [(set_attr "type" "int2,int4")
+   (set_attr "length" "2,4")])
 
 (define_insn "xorsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
   ""
   "@
    xor %0,%2
-   xor3 %0,%1,%#%2 ; %X2"
-  [(set_attr "type" "binary")])
+   xor3 %0,%1,%#%2\\t; %X2"
+  [(set_attr "type" "int2,int4")
+   (set_attr "length" "2,4")])
 
 (define_insn "negsi2"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (match_operand:SI 1 "register_operand" "r")))]
   ""
   "neg %0,%1"
-  [(set_attr "type" "unary")])
+  [(set_attr "type" "int2")
+   (set_attr "length" "2")])
 
 (define_insn "one_cmplsi2"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (not:SI (match_operand:SI 1 "register_operand" "r")))]
   ""
   "not %0,%1"
-  [(set_attr "type" "unary")])
+  [(set_attr "type" "int2")
+   (set_attr "length" "2")])
 \f
 ;; Shift instructions.
 
    sll %0,%2
    slli %0,%#%2
    sll3 %0,%1,%#%2"
-  [(set_attr "type" "shift")
+  [(set_attr "type" "shift2,shift2,shift4")
    (set_attr "length" "2,2,4")])
 
 (define_insn "ashrsi3"
    sra %0,%2
    srai %0,%#%2
    sra3 %0,%1,%#%2"
-  [(set_attr "type" "shift")
+  [(set_attr "type" "shift2,shift2,shift4")
    (set_attr "length" "2,2,4")])
 
 (define_insn "lshrsi3"
    srl %0,%2
    srli %0,%#%2
    srl3 %0,%1,%#%2"
-  [(set_attr "type" "shift")
+  [(set_attr "type" "shift2,shift2,shift4")
    (set_attr "length" "2,2,4")])
 \f
 ;; Compare instructions.
           return \"add3 %2,%0,%#%N1\;cmpui %2,#1\";
     }
 }"
-  [(set_attr "type" "compare,compare")
+  [(set_attr "type" "multi,multi")
    (set_attr "length" "8,8")])
 
 (define_insn "cmp_ltsi_insn"
   "@
    cmp %0,%1
    cmpi %0,%#%1"
-  [(set_attr "type" "compare,compare")
-   (set_attr "length" "4,6")])
+  [(set_attr "type" "int2,int4")
+   (set_attr "length" "2,4")])
 
 (define_insn "cmp_ltusi_insn"
   [(set (reg:CC 17)
        (ltu:CC (match_operand:SI 0 "register_operand" "r,r")
                (match_operand:SI 1 "reg_or_uint16_operand" "r,K")))]
   ""
-  "*
-{
-  if (which_alternative == 0)
-    return \"cmpu %0,%1\";
-  else
-   return \"cmpui %0,%#%1\";
-}"
-  [(set_attr "type" "compare")
-   (set_attr "length" "4,6")])
+  "@
+   cmpu %0,%1
+   cmpui %0,%#%1"
+  [(set_attr "type" "int2,int4")
+   (set_attr "length" "2,4")])
 
 ;; reg == small constant comparisons are best handled by putting the result
 ;; of the comparison in a tmp reg and then using beqz/bnez.
 (define_insn "cmp_ne_small_const_insn"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (ne:SI (match_operand:SI 1 "register_operand" "0,r")
-              (match_operand:SI 2 "cmp_int16_operand" "S,P")))]
+              (match_operand:SI 2 "cmp_int16_operand" "N,P")))]
   ""
   "@
    addi %0,%#%N2
    add3 %0,%1,%#%N2"
-  [(set_attr "type" "compare")
+  [(set_attr "type" "int2,int4")
    (set_attr "length" "2,4")])
 \f
 ;; These control RTL generation for conditional jump insns.
   [(const_int 0)]
   ""
   "nop"
-  [(set_attr "type" "misc")
+  [(set_attr "type" "int2")
    (set_attr "length" "2")])
 
 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
   [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)]
   ""
   "* return \"nop ; flush-icache\";"
-  [(set_attr "type" "misc")])
+  [(set_attr "type" "int2")
+   (set_attr "length" "2")])
 \f
 ;; Conditional move instructions
 ;; Based on those done for the d10v
    )]
   "zero_and_one (operands [2], operands[3])"
   "* return emit_cond_move (operands, insn);"
-  [(set_attr "type"   "move")
+  [(set_attr "type" "multi")
    (set_attr "length" "8")
   ]
 )
   [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
                         (const_int 4)))
         (match_operand:SI 1 "register_operand" "r"))]
-  "dead_or_set_p (insn, operands[0])"
+  "0 && dead_or_set_p (insn, operands[0])"
   "st %1,@+%0"
-  [(set_attr "type" "store")
+  [(set_attr "type" "store2")
    (set_attr "length" "2")])
 
 ;; This case is triggered by compiling this code:
         (match_dup 0)
    )
   ]
-  "dead_or_set_p (insn, operands [0])"
+  "0 && dead_or_set_p (insn, operands [0])"
   "st %1,@(%3,%2)"
-  [(set_attr "type" "store")
+  [(set_attr "type" "store4")
    (set_attr "length" "4")
   ]
 )