mn10300: Cleanup all arithmetic.
authorRichard Henderson <rth@redhat.com>
Wed, 19 Jan 2011 18:38:56 +0000 (10:38 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 19 Jan 2011 18:38:56 +0000 (10:38 -0800)
For addition and logicals, define an operation-plus-flags update pattern
in preparation for compare elimination.  In addition, clean up the way
we compare and validate CC_MODEs.  Define NEG in terms of NOT; this is
smaller and allows a non-clobbering destination alternative.

From-SVN: r169010

gcc/ChangeLog
gcc/config/mn10300/mn10300-modes.def
gcc/config/mn10300/mn10300-protos.h
gcc/config/mn10300/mn10300.c
gcc/config/mn10300/mn10300.h
gcc/config/mn10300/mn10300.md
gcc/config/mn10300/predicates.md

index e2bda22f2e4168eae983539d905b87b8d9589463..5a85c704db42d24000a9e64634b563213d0d6490 100644 (file)
@@ -1,5 +1,71 @@
 2011-01-19  Richard Henderson  <rth@redhat.com>
 
+       * config/mn10300/mn10300-modes.def (CCZN, CCZNC): New modes.
+       * config/mn10300/mn10300.c (CC_FLAG_Z): New.
+       (CC_FLAG_N, CC_FLAG_C, CC_FLAG_V): New.
+       (cc_flags_for_mode, cc_flags_for_code): New.
+       (mn10300_print_operand) ['B']: Use nc/ns for GE/LT when the
+       overflow flag is not valid.  Validate that the flags we need
+       for the comparison are valid.
+       (mn10300_output_cmp): Remove.
+       (mn10300_output_add): New.
+       (mn10300_select_cc_mode): Use cc_flags_for_code.
+       (mn10300_split_cbranch): New.
+       (mn10300_match_ccmode): New.
+       (mn10300_split_and_operand_count): New.
+       * config/mn10300/mn10300.h (SELECT_CC_MODE): Pass all of the arguments
+       to the function.
+       * config/mn10300/mn10300.md (*am33_addsi3, *mn10300_addsi3): Merge...
+       (addsi3): ... here.  Use mn10300_output_add.
+       (*addsi3_flags): New.
+       (*am33_subsi3, *mn10300_subsi3): Merge...
+       (subsi3): ... here.  Use attribute isa.
+       (*subsi3_flags): New.
+       (negsi2): Rewrite from expander to insn_and_split.  Use NOT+INC
+       when possible.
+       (*am33_andsi3, *mn10300_andsi3): Merge...
+       (andsi3): ... here.
+       (*andsi3_flags): New.
+       (andsi3 splitters): New.
+       (*am33_iorsi3, *mn10300_iorsi3): Merge...
+       (iorsi3): ... here.
+       (*iorsi3_flags): New.
+       (*am33_xorsi3, *mn10300_xorsi3): Merge...
+       (xorsi3): ... here.
+       (*xorsi3_flags): New.
+       (*am33_cmpsi2, *mn10300_cmplsi2): Merge...
+       (one_cmplsi2): ... here.
+       (*one_cmplsi2_flags): New.
+       (*cbranchsi4_cmp): Rename from cbranchsi4_post_reload.  Use "r"
+       instead of "dax" in constraints.  Use mn10300_split_cbranch.
+       (*cmpsi): Rename from cmpsi.  Do not use mn10300_output_cmp.  Do not
+       use matching constraints to eliminate a self-comparison.
+       (*integer_conditional_branch): Rename from integer_conditional_branch.
+       Use int_mode_flags to match CC_REG.
+       (*cbranchsi4_btst, *btstsi): New.
+       (*cbranchsf4_cmp): Rename from *cbranchsf4_post_reload.  Use
+       mn10300_split_cbranch.
+       (*am33_cmpsf): Rename from am33_cmpsf.
+       (*float_conditional_branch): Rename from float_conditional_branch.
+       (*zero_extendqisi2_am33, *zero_extendqisi2_mn10300): Merge...
+       (zero_extendqisi2): ... here.
+       (*zero_extendhisi2_am33, *zero_extendhisi2_mn10300): Merge...
+       (zero_extendhisi2): ... here.
+       (*extendqisi2_am33, *extendqisi2_mn10300): Merge...
+       (extendqisi2): ... here.
+       (*extendhisi2_am33, *extendhisi2_mn10300): Merge...
+       (extendhisi2): ... here.
+       (*am33_ashlsi3, *mn10300_ashlsi3): Merge...
+       (ashlsi3): ... here.
+       (*am33_lshrsi3, *mn10300_lshrsi3): Merge...
+       (lshrsi3): ... here.
+       (*am33_ashrisi3, *mn10300_ashrsi3): Merge...
+       (ashrsi3): ... here.
+       (consecutive add peephole): Remove.
+       * config/mn10300/predicates.md (label_ref_operand): New.
+       (int_mode_flags): New.
+       (CCZN_comparison_operator): New.
+
        * config/mn10300/mn10300.md (UNSPEC_EXT): New.
        (throughput_42_latency_43): New reservation.
        (mulsidi3, umulsidi3): New expanders.
index 8bcffcd41a4d5eab396f6551965eedff45284e58..832663edb2af9ed7a8dcd5eaf829dd4944dfc860 100644 (file)
@@ -19,4 +19,6 @@
    the Free Software Foundation, , Inc., 51 Franklin Street - Fifth
    Floor, Boston, MA 02110-1301, USA.  */
 
+CC_MODE (CCZN);
+CC_MODE (CCZNC);
 CC_MODE (CC_FLOAT);
index d0ce1b3f7b648aa2427ddb015e133530e030c3dd..28a94126fffb44f23792c87bf9faf3eaac9fdd65 100644 (file)
@@ -32,13 +32,16 @@ extern int   mn10300_get_live_callee_saved_regs (void);
 extern bool  mn10300_hard_regno_mode_ok (unsigned int, Mmode);
 extern bool  mn10300_legitimate_constant_p (rtx);
 extern bool  mn10300_modes_tieable (Mmode, Mmode);
-extern Cstar mn10300_output_cmp (rtx, rtx);
+extern Cstar mn10300_output_add (rtx[3], bool);
 extern void  mn10300_print_operand (FILE *, rtx, int);
 extern void  mn10300_print_operand_address (FILE *, rtx);
 extern void  mn10300_print_reg_list (FILE *, int);
-extern Mmode mn10300_select_cc_mode (rtx);
+extern Mmode mn10300_select_cc_mode (enum rtx_code, rtx, rtx);
 extern int   mn10300_store_multiple_operation (rtx, Mmode);
 extern int   mn10300_symbolic_operand (rtx, Mmode);
+extern void  mn10300_split_cbranch (Mmode, rtx, rtx);
+extern int   mn10300_split_and_operand_count (rtx);
+extern bool  mn10300_match_ccmode (rtx, Mmode);
 #endif /* RTX_CODE */
 
 extern bool  mn10300_regno_in_class_p (unsigned, int, bool);
index 023c69c1557be30baa70e78e97d0fb7cb72463e6..7535253e0f0e8f745124c472f31c57889d45dbf2 100644 (file)
@@ -81,6 +81,14 @@ static const struct default_options mn10300_option_optimization_table[] =
     { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
     { OPT_LEVELS_NONE, 0, NULL, 0 }
   };
+
+#define CC_FLAG_Z      1
+#define CC_FLAG_N      2
+#define CC_FLAG_C      4
+#define CC_FLAG_V      8
+
+static int cc_flags_for_mode(enum machine_mode);
+static int cc_flags_for_code(enum rtx_code);
 \f
 /* Implement TARGET_HANDLE_OPTION.  */
 
@@ -134,7 +142,7 @@ mn10300_option_override (void)
         when this flag is not enabled by default.  */
       flag_split_wide_types = 1;
     }
-  
+
   if (mn10300_tune_string)
     {
       if (strcasecmp (mn10300_tune_string, "mn10300") == 0)
@@ -171,95 +179,82 @@ mn10300_print_operand (FILE *file, rtx x, int code)
     {
       case 'b':
       case 'B':
-       if (GET_MODE (XEXP (x, 0)) == CC_FLOATmode)
-         {
-           switch (code == 'b' ? GET_CODE (x)
-                   : reverse_condition_maybe_unordered (GET_CODE (x)))
-             {
-             case NE:
-               fprintf (file, "ne");
-               break;
-             case EQ:
-               fprintf (file, "eq");
-               break;
-             case GE:
-               fprintf (file, "ge");
-               break;
-             case GT:
-               fprintf (file, "gt");
-               break;
-             case LE:
-               fprintf (file, "le");
-               break;
-             case LT:
-               fprintf (file, "lt");
-               break;
-             case ORDERED:
-               fprintf (file, "lge");
-               break;
-             case UNORDERED:
-               fprintf (file, "uo");
-               break;
-             case LTGT:
-               fprintf (file, "lg");
-               break;
-             case UNEQ:
-               fprintf (file, "ue");
-               break;
-             case UNGE:
-               fprintf (file, "uge");
-               break;
-             case UNGT:
-               fprintf (file, "ug");
-               break;
-             case UNLE:
-               fprintf (file, "ule");
-               break;
-             case UNLT:
-               fprintf (file, "ul");
-               break;
-             default:
-               gcc_unreachable ();
-             }
-           break;
-         }
-       /* These are normal and reversed branches.  */
-       switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
-         {
-         case NE:
-           fprintf (file, "ne");
-           break;
-         case EQ:
-           fprintf (file, "eq");
-           break;
-         case GE:
-           fprintf (file, "ge");
-           break;
-         case GT:
-           fprintf (file, "gt");
-           break;
-         case LE:
-           fprintf (file, "le");
-           break;
-         case LT:
-           fprintf (file, "lt");
-           break;
-         case GEU:
-           fprintf (file, "cc");
-           break;
-         case GTU:
-           fprintf (file, "hi");
-           break;
-         case LEU:
-           fprintf (file, "ls");
-           break;
-         case LTU:
-           fprintf (file, "cs");
-           break;
-         default:
-           gcc_unreachable ();
-         }
+       {
+         enum rtx_code cmp = GET_CODE (x);
+         enum machine_mode mode = GET_MODE (XEXP (x, 0));
+         const char *str;
+         int have_flags;
+
+         if (code == 'B')
+           cmp = reverse_condition (cmp);
+         have_flags = cc_flags_for_mode (mode);
+
+         switch (cmp)
+           {
+           case NE:
+             str = "ne";
+             break;
+           case EQ:
+             str = "eq";
+             break;
+           case GE:
+             /* bge is smaller than bnc.  */
+             str = (have_flags & CC_FLAG_V ? "ge" : "nc");
+             break;
+           case LT:
+             str = (have_flags & CC_FLAG_V ? "lt" : "ns");
+             break;
+           case GT:
+             str = "gt";
+             break;
+           case LE:
+             str = "le";
+             break;
+           case GEU:
+             str = "cc";
+             break;
+           case GTU:
+             str = "hi";
+             break;
+           case LEU:
+             str = "ls";
+             break;
+           case LTU:
+             str = "cs";
+             break;
+           case ORDERED:
+             str = "lge";
+             break;
+           case UNORDERED:
+             str = "uo";
+             break;
+           case LTGT:
+             str = "lg";
+             break;
+           case UNEQ:
+             str = "ue";
+             break;
+           case UNGE:
+             str = "uge";
+             break;
+           case UNGT:
+             str = "ug";
+             break;
+           case UNLE:
+             str = "ule";
+             break;
+           case UNLT:
+             str = "ul";
+             break;
+           default:
+             gcc_unreachable ();
+           }
+
+         gcc_checking_assert ((cc_flags_for_code (cmp) & ~have_flags) == 0);
+         fputs (str, file);
+       }
        break;
+
       case 'C':
        /* This is used for the operand to a call instruction;
           if it's a REG, enclose it in parens, else output
@@ -1709,95 +1704,96 @@ mn10300_function_value_regno_p (const unsigned int regno)
  return (regno == FIRST_DATA_REGNUM || regno == FIRST_ADDRESS_REGNUM);
 }
 
-/* Output a compare insn.  */
+/* Output an addition operation.  */
 
 const char *
-mn10300_output_cmp (rtx operand, rtx insn)
+mn10300_output_add (rtx operands[3], bool need_flags)
 {
-  rtx temp;
-  int past_call = 0;
+  rtx dest, src1, src2;
+  unsigned int dest_regnum, src1_regnum, src2_regnum;
+  enum reg_class src1_class, src2_class, dest_class;
 
-  /* We can save a byte if we can find a register which has the value
-     zero in it.  */
-  temp = PREV_INSN (insn);
-  while (optimize && temp)
-    {
-      rtx set;
-
-      /* We allow the search to go through call insns.  We record
-        the fact that we've past a CALL_INSN and reject matches which
-        use call clobbered registers.  */
-      if (LABEL_P (temp)
-         || JUMP_P (temp)
-         || GET_CODE (temp) == BARRIER)
-       break;
+  dest = operands[0];
+  src1 = operands[1];
+  src2 = operands[2];
 
-      if (CALL_P (temp))
-       past_call = 1;
+  dest_regnum = true_regnum (dest);
+  src1_regnum = true_regnum (src1);
 
-      if (GET_CODE (temp) == NOTE)
-       {
-         temp = PREV_INSN (temp);
-         continue;
-       }
+  dest_class = REGNO_REG_CLASS (dest_regnum);
+  src1_class = REGNO_REG_CLASS (src1_regnum);
 
-      /* It must be an insn, see if it is a simple set.  */
-      set = single_set (temp);
-      if (!set)
-       {
-         temp = PREV_INSN (temp);
-         continue;
-       }
+  if (GET_CODE (src2) == CONST_INT)
+    {
+      gcc_assert (dest_regnum == src1_regnum);
 
-      /* Are we setting a data register to zero (this does not win for
-        address registers)?
-
-        If it's a call clobbered register, have we past a call?
-
-        Make sure the register we find isn't the same as ourself;
-        the mn10300 can't encode that.
-
-        ??? reg_set_between_p return nonzero anytime we pass a CALL_INSN
-        so the code to detect calls here isn't doing anything useful.  */
-      if (REG_P (SET_DEST (set))
-         && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
-         && !reg_set_between_p (SET_DEST (set), temp, insn)
-         && (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
-             == REGNO_REG_CLASS (REGNO (operand)))
-         && REGNO_REG_CLASS (REGNO (SET_DEST (set))) != EXTENDED_REGS
-         && REGNO (SET_DEST (set)) != REGNO (operand)
-         && (!past_call
-             || ! call_really_used_regs [REGNO (SET_DEST (set))]))
-       {
-         rtx xoperands[2];
-         xoperands[0] = operand;
-         xoperands[1] = SET_DEST (set);
+      if (src2 == const1_rtx && !need_flags)
+       return "inc %0";
+      if (INTVAL (src2) == 4 && !need_flags && dest_class != DATA_REGS)
+        return "inc4 %0";
 
-         output_asm_insn ("cmp %1,%0", xoperands);
-         return "";
-       }
+      gcc_assert (!need_flags || dest_class != SP_REGS);
+      return "add %2,%0";
+    }
+  else if (CONSTANT_P (src2))
+    return "add %2,%0";
+
+  src2_regnum = true_regnum (src2);
+  src2_class = REGNO_REG_CLASS (src2_regnum);
+      
+  if (dest_regnum == src1_regnum)
+    return "add %2,%0";
+  if (dest_regnum == src2_regnum)
+    return "add %1,%0";
+
+  /* The rest of the cases are reg = reg+reg.  For AM33, we can implement
+     this directly, as below, but when optimizing for space we can sometimes
+     do better by using a mov+add.  For MN103, we claimed that we could
+     implement a three-operand add because the various move and add insns
+     change sizes across register classes, and we can often do better than
+     reload in choosing which operand to move.  */
+  if (TARGET_AM33 && optimize_insn_for_speed_p ())
+    return "add %2,%1,%0";
+
+  /* Catch cases where no extended register was used.  */
+  if (src1_class != EXTENDED_REGS
+      && src2_class != EXTENDED_REGS
+      && dest_class != EXTENDED_REGS)
+    {
+      /* We have to copy one of the sources into the destination, then
+         add the other source to the destination.
+
+         Carefully select which source to copy to the destination; a
+         naive implementation will waste a byte when the source classes
+         are different and the destination is an address register.
+         Selecting the lowest cost register copy will optimize this
+         sequence.  */
+      if (src1_class == dest_class)
+        return "mov %1,%0\n\tadd %2,%0";
+      else
+       return "mov %2,%0\n\tadd %1,%0";
+    }
 
-      if (REGNO_REG_CLASS (REGNO (operand)) == EXTENDED_REGS
-         && REG_P (SET_DEST (set))
-         && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
-         && !reg_set_between_p (SET_DEST (set), temp, insn)
-         && (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
-             != REGNO_REG_CLASS (REGNO (operand)))
-         && REGNO_REG_CLASS (REGNO (SET_DEST (set))) == EXTENDED_REGS
-         && REGNO (SET_DEST (set)) != REGNO (operand)
-         && (!past_call
-             || ! call_really_used_regs [REGNO (SET_DEST (set))]))
-       {
-         rtx xoperands[2];
-         xoperands[0] = operand;
-         xoperands[1] = SET_DEST (set);
+  /* At least one register is an extended register.  */
 
-         output_asm_insn ("cmp %1,%0", xoperands);
-         return "";
-       }
-      temp = PREV_INSN (temp);
-    }
-  return "cmp 0,%0";
+  /* The three operand add instruction on the am33 is a win iff the
+     output register is an extended register, or if both source
+     registers are extended registers.  */
+  if (dest_class == EXTENDED_REGS || src1_class == src2_class)
+    return "add %2,%1,%0";
+
+  /* It is better to copy one of the sources to the destination, then
+     perform a 2 address add.  The destination in this case must be
+     an address or data register and one of the sources must be an
+     extended register and the remaining source must not be an extended
+     register.
+
+     The best code for this case is to copy the extended reg to the
+     destination, then emit a two address add.  */
+  if (src1_class == EXTENDED_REGS)
+    return "mov %1,%0\n\tadd %2,%0";
+  else
+    return "mov %2,%0\n\tadd %1,%0";
 }
 
 /* Return 1 if X contains a symbolic expression.  We know these
@@ -2674,10 +2670,80 @@ mn10300_modes_tieable (enum machine_mode mode1, enum machine_mode mode2)
   return false;
 }
 
+static int
+cc_flags_for_mode (enum machine_mode mode)
+{
+  switch (mode)
+    {
+    case CCmode:
+      return CC_FLAG_Z | CC_FLAG_N | CC_FLAG_C | CC_FLAG_V;
+    case CCZNCmode:
+      return CC_FLAG_Z | CC_FLAG_N | CC_FLAG_C;
+    case CCZNmode:
+      return CC_FLAG_Z | CC_FLAG_N;
+    case CC_FLOATmode:
+      return -1;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+static int
+cc_flags_for_code (enum rtx_code code)
+{
+  switch (code)
+    {
+    case EQ:   /* Z */
+    case NE:   /* ~Z */
+      return CC_FLAG_Z;
+
+    case LT:   /* N */
+    case GE:   /* ~N */
+      return CC_FLAG_N;
+      break;
+
+    case GT:    /* ~(Z|(N^V)) */
+    case LE:    /* Z|(N^V) */
+      return CC_FLAG_Z | CC_FLAG_N | CC_FLAG_V;
+
+    case GEU:  /* ~C */
+    case LTU:  /* C */
+      return CC_FLAG_C;
+
+    case GTU:  /* ~(C | Z) */
+    case LEU:  /* C | Z */
+      return CC_FLAG_Z | CC_FLAG_C;
+
+    case ORDERED:
+    case UNORDERED:
+    case LTGT:
+    case UNEQ:
+    case UNGE:
+    case UNGT:
+    case UNLE:
+    case UNLT:
+      return -1;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
 enum machine_mode
-mn10300_select_cc_mode (rtx x)
+mn10300_select_cc_mode (enum rtx_code code, rtx x, rtx y ATTRIBUTE_UNUSED)
 {
-  return (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) ? CC_FLOATmode : CCmode;
+  int req;
+
+  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+    return CC_FLOATmode;
+
+  req = cc_flags_for_code (code);
+
+  if (req & CC_FLAG_V)
+    return CCmode;
+  if (req & CC_FLAG_C)
+    return CCZNCmode;
+  return CCZNmode;
 }
 
 static inline bool
@@ -2811,6 +2877,82 @@ mn10300_md_asm_clobbers (tree outputs ATTRIBUTE_UNUSED,
   return clobbers;
 }
 \f
+/* A helper function for splitting cbranch patterns after reload.  */
+
+void
+mn10300_split_cbranch (enum machine_mode cmp_mode, rtx cmp_op, rtx label_ref)
+{
+  rtx flags, x;
+
+  flags = gen_rtx_REG (cmp_mode, CC_REG);
+  x = gen_rtx_COMPARE (cmp_mode, XEXP (cmp_op, 0), XEXP (cmp_op, 1));
+  x = gen_rtx_SET (VOIDmode, flags, x);
+  emit_insn (x);
+
+  x = gen_rtx_fmt_ee (GET_CODE (cmp_op), VOIDmode, flags, const0_rtx);
+  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label_ref, pc_rtx);
+  x = gen_rtx_SET (VOIDmode, pc_rtx, x);
+  emit_jump_insn (x);
+}
+
+/* A helper function for matching parallels that set the flags.  */
+
+bool
+mn10300_match_ccmode (rtx insn, enum machine_mode cc_mode)
+{
+  rtx op1, flags;
+  enum machine_mode flags_mode;
+
+  gcc_checking_assert (XVECLEN (PATTERN (insn), 0) == 2);
+
+  op1 = XVECEXP (PATTERN (insn), 0, 1);
+  gcc_checking_assert (GET_CODE (SET_SRC (op1)) == COMPARE);
+
+  flags = SET_DEST (op1);
+  flags_mode = GET_MODE (flags);
+
+  if (GET_MODE (SET_SRC (op1)) != flags_mode)
+    return false;
+  if (GET_MODE_CLASS (flags_mode) != MODE_CC)
+    return false;
+
+  /* Ensure that the mode of FLAGS is compatible with CC_MODE.  */
+  if (cc_flags_for_mode (flags_mode) & ~cc_flags_for_mode (cc_mode))
+    return false;
+
+  return true;
+}
+
+int
+mn10300_split_and_operand_count (rtx op)
+{
+  HOST_WIDE_INT val = INTVAL (op);
+  int count;
+
+  if (val < 0)
+    {
+      /* High bit is set, look for bits clear at the bottom.  */
+      count = exact_log2 (-val);
+      if (count < 0)
+       return 0;
+      /* This is only size win if we can use the asl2 insn.  Otherwise we
+        would be replacing 1 6-byte insn with 2 3-byte insns.  */
+      if (count > (optimize_insn_for_speed_p () ? 2 : 4))
+       return 0;
+      return -count;
+    }
+  else
+    {
+      /* High bit is clear, look for bits set at the bottom.  */
+      count = exact_log2 (val + 1);
+      count = 32 - count;
+      /* Again, this is only a size win with asl2.  */
+      if (count > (optimize_insn_for_speed_p () ? 2 : 4))
+       return 0;
+      return -count;
+    }
+}
+\f
 /* Initialize the GCC target structure.  */
 
 #undef  TARGET_EXCEPT_UNWIND_INFO
index 05c78266a67eb16bc3e3054202840efd7ab22ed6..21d36338306398808990d25da6c29eee21a34dcb 100644 (file)
@@ -600,7 +600,7 @@ do {                                                                             \
 /* Non-global SYMBOL_REFs have SYMBOL_REF_FLAG enabled.  */
 #define MN10300_GLOBAL_P(X) (! SYMBOL_REF_FLAG (X))
 \f
-#define SELECT_CC_MODE(OP, X, Y)  mn10300_select_cc_mode (X)
+#define SELECT_CC_MODE(OP, X, Y)  mn10300_select_cc_mode (OP, X, Y)
 #define REVERSIBLE_CC_MODE(MODE)  0
 \f
 /* Nonzero if access to memory by bytes or half words is no faster
index bc68ca5d8fdcd7af6f3650eab741cad716037e9e..152477c874cd2c8869e10059b4c7ba7a609f92fc 100644 (file)
                 ])]
 )
 
-\f
-;; ----------------------------------------------------------------------
-;; ADD INSTRUCTIONS
-;; ----------------------------------------------------------------------
-
-(define_expand "addsi3"
-  [(parallel [(set (match_operand:SI          0 "register_operand")
-                  (plus:SI (match_operand:SI 1 "register_operand")
-                           (match_operand:SI 2 "nonmemory_operand")))
-             (clobber (reg:CC CC_REG))
-            ])
-  ]
-  ""
-  "")
-
-(define_insn "*am33_addsi3"
-  [(set (match_operand:SI          0 "register_operand" "=dx,a,x,a,dax,!*y,!dax")
-       (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,dax")
-                (match_operand:SI 2 "nonmemory_operand" "J,J,L,L,daxi,i,dax")))
-   (clobber (reg:CC CC_REG))
-  ]
-  "TARGET_AM33"
-  "*
-{
-  switch (which_alternative)
-    {
-    case 0:
-    case 1:
-      return \"inc %0\";
-    case 2:
-    case 3:
-      return \"inc4 %0\";
-    case 4:
-    case 5:
-      return \"add %2,%0\";
-    case 6:
-      {
-       enum reg_class src1_class, src2_class, dst_class;
-
-       src1_class = REGNO_REG_CLASS (true_regnum (operands[1]));
-       src2_class = REGNO_REG_CLASS (true_regnum (operands[2]));
-       dst_class = REGNO_REG_CLASS (true_regnum (operands[0]));
-
-       /* I'm not sure if this can happen or not.  Might as well be prepared
-         and generate the best possible code if it does happen.  */
-       if (true_regnum (operands[0]) == true_regnum (operands[1]))
-         return \"add %2,%0\";
-       if (true_regnum (operands[0]) == true_regnum (operands[2]))
-         return \"add %1,%0\";
-
-       /* Catch cases where no extended register was used.  These should be
-          handled just like the mn10300.  */
-       if (src1_class != EXTENDED_REGS
-           && src2_class != EXTENDED_REGS
-           && dst_class != EXTENDED_REGS)
-         {
-           /* We have to copy one of the sources into the destination, then
-              add the other source to the destination.
-
-              Carefully select which source to copy to the destination; a
-              naive implementation will waste a byte when the source classes
-              are different and the destination is an address register.
-              Selecting the lowest cost register copy will optimize this
-              sequence.  */
-           if (REGNO_REG_CLASS (true_regnum (operands[1]))
-               == REGNO_REG_CLASS (true_regnum (operands[0])))
-             return \"mov %1,%0\;add %2,%0\";
-           return \"mov %2,%0\;add %1,%0\";
-         }
-
-       /* At least one register is an extended register.  */
-
-       /* The three operand add instruction on the am33 is a win iff the
-          output register is an extended register, or if both source
-          registers are extended registers.  */
-       if (dst_class == EXTENDED_REGS
-           || src1_class == src2_class)
-         return \"add %2,%1,%0\";
-
-      /* It is better to copy one of the sources to the destination, then
-        perform a 2 address add.  The destination in this case must be
-        an address or data register and one of the sources must be an
-        extended register and the remaining source must not be an extended
-        register.
-
-        The best code for this case is to copy the extended reg to the
-        destination, then emit a two address add.  */
-      if (src1_class == EXTENDED_REGS)
-       return \"mov %1,%0\;add %2,%0\";
-      return \"mov %2,%0\;add %1,%0\";
-      }
-    default:
-      gcc_unreachable ();
-    }
-  }"
-  [(set_attr "timings" "11,11,11,11,11,11,22")]
-)
-
 ;; If the flags register is not live, generate CLR instead of MOV 0.
 ;; For MN103, this is only legal for DATA_REGS; for AM33 this is legal
 ;; but not a win for ADDRESS_REGS.
 ;; ADD INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_insn "*mn10300_addsi3"
-  [(set (match_operand:SI          0 "register_operand" "=dx,a,a,dax,!*y,!dax")
-       (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,dax")
-                (match_operand:SI 2 "nonmemory_operand" "J,J,L,daxi,i,dax")))
-   (clobber (reg:CC CC_REG))
-  ]
+(define_insn "addsi3"
+  [(set (match_operand:SI          0 "register_operand"  "=r,!*y,!r")
+       (plus:SI (match_operand:SI 1 "register_operand"  "%0,  0, r")
+                (match_operand:SI 2 "nonmemory_operand" "ri,  i, r")))
+   (clobber (reg:CC CC_REG))]
   ""
-  "*
-{
-  switch (which_alternative)
-    {
-    case 0:
-    case 1:
-      return \"inc %0\";
-    case 2:
-      return \"inc4 %0\";
-    case 3:
-    case 4:
-      return \"add %2,%0\";
-    case 5:
-      /* I'm not sure if this can happen or not.  Might as well be prepared
-        and generate the best possible code if it does happen.  */
-      if (true_regnum (operands[0]) == true_regnum (operands[1]))
-       return \"add %2,%0\";
-      if (true_regnum (operands[0]) == true_regnum (operands[2]))
-       return \"add %1,%0\";
-
-      /* We have to copy one of the sources into the destination, then add
-        the other source to the destination.
-
-        Carefully select which source to copy to the destination; a naive
-        implementation will waste a byte when the source classes are different
-        and the destination is an address register.  Selecting the lowest
-        cost register copy will optimize this sequence.  */
-      if (REGNO_REG_CLASS (true_regnum (operands[1]))
-         == REGNO_REG_CLASS (true_regnum (operands[0])))
-       return \"mov %1,%0\;add %2,%0\";
-      return \"mov %2,%0\;add %1,%0\";
-    default:
-      gcc_unreachable ();
-    }
-}"
-  [(set_attr "timings" "11,11,11,11,11,22")]
+  { return mn10300_output_add (operands, false); }
+  [(set_attr "timings" "11,11,22")]
+)
+
+;; Note that ADD IMM,SP does not set the flags, so omit that here.
+(define_insn "*addsi3_flags"
+  [(set (match_operand:SI          0 "register_operand"  "=r,!r")
+       (plus:SI (match_operand:SI 1 "register_operand"  "%0, r")
+                (match_operand:SI 2 "nonmemory_operand" "ri, r")))
+   (set (reg CC_REG)
+       (compare (plus:SI (match_dup 1) (match_dup 2))
+                (const_int 0)))]
+  "reload_completed && mn10300_match_ccmode (insn, CCZNCmode)"
+  { return mn10300_output_add (operands, true); }
+  [(set_attr "timings" "11,22")]
 )
 
 ;; ----------------------------------------------------------------------
 ;; SUBTRACT INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_expand "subsi3"
-  [(parallel [(set (match_operand:SI           0 "register_operand")
-                  (minus:SI (match_operand:SI 1 "register_operand")
-                            (match_operand:SI 2 "nonmemory_operand")))
-             (clobber (reg:CC CC_REG))
-            ])
-  ]
+(define_insn "subsi3"
+  [(set (match_operand:SI           0 "register_operand"  "=r,r")
+       (minus:SI (match_operand:SI 1 "register_operand"  " 0,r")
+                 (match_operand:SI 2 "nonmemory_operand" "ri,r")))
+   (clobber (reg:CC CC_REG))]
   ""
-  "")
-
-(define_insn "*am33_subsi3"
-  [(set (match_operand:SI           0 "register_operand" "=dax,!dax")
-       (minus:SI (match_operand:SI 1 "register_operand" "0,dax")
-                 (match_operand:SI 2 "nonmemory_operand" "daxi,dax")))
-   (clobber (reg:CC CC_REG))
-  ]
-  "TARGET_AM33"
-  "*
-  {
-    if (true_regnum (operands[0]) == true_regnum (operands[1]))
-      return \"sub %2,%0\";
-    else
-      {
-        enum reg_class src1_class, src2_class, dst_class;
-
-        src1_class = REGNO_REG_CLASS (true_regnum (operands[1]));
-        src2_class = REGNO_REG_CLASS (true_regnum (operands[2]));
-        dst_class = REGNO_REG_CLASS (true_regnum (operands[0]));
-
-        /* If no extended registers are used, then the best way to handle
-          this is to copy the first source operand into the destination
-          and emit a two address subtraction.  */
-        if (src1_class != EXTENDED_REGS
-           && src2_class != EXTENDED_REGS
-           && dst_class != EXTENDED_REGS
-           && true_regnum (operands[0]) != true_regnum (operands[2]))
-         return \"mov %1,%0\;sub %2,%0\";
-        return \"sub %2,%1,%0\";
-      }
-  }"
-  [(set_attr "timings" "11,22")]
+  "@
+   sub %2,%0
+   sub %2,%1,%0"
+  [(set_attr "isa" "*,am33")
+   (set_attr "timings" "11,22")]
 )
 
-(define_insn "*mn10300_subsi3"
-  [(set (match_operand:SI           0 "register_operand" "=dax")
-       (minus:SI (match_operand:SI 1 "register_operand" "0")
-                 (match_operand:SI 2 "nonmemory_operand" "daxi")))
-   (clobber (reg:CC CC_REG))
-  ]
-  ""
-  "sub %2,%0"
-  [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
-                                      (const_int 11) (const_int 22)))]
+(define_insn "*subsi3_flags"
+  [(set (match_operand:SI           0 "register_operand"  "=r,r")
+       (minus:SI (match_operand:SI 1 "register_operand"  " 0,r")
+                 (match_operand:SI 2 "nonmemory_operand" "ri,r")))
+   (set (reg CC_REG)
+       (compare (minus:SI (match_dup 1) (match_dup 2))
+                (const_int 0)))]
+  "reload_completed && mn10300_match_ccmode (insn, CCZNCmode)"
+  "@
+   sub %2,%0
+   sub %2,%1,%0"
+  [(set_attr "isa" "*,am33")
+   (set_attr "timings" "11,22")]
 )
 
-(define_expand "negsi2"
-  [(set (match_operand:SI         0 "register_operand")
-        (neg:SI (match_operand:SI 1 "register_operand")))]
+(define_insn_and_split "negsi2"
+  [(set (match_operand:SI         0 "register_operand"  "=D,&r")
+       (neg:SI (match_operand:SI 1 "register_operand"  " 0, r")))
+   (clobber (reg:CC CC_REG))]
   ""
-  "
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
 {
-  rtx target = gen_reg_rtx (SImode);
-
-  emit_move_insn (target, const0_rtx);
-  emit_insn (gen_subsi3 (target, target, operands[1]));
-  emit_move_insn (operands[0], target);
+  /* Recall that twos-compliment is ones-compliment plus one.  When
+     allocated in DATA_REGS this is 2+1 bytes; otherwise (for am33)
+     this is 3+3 bytes.
+
+     For AM33, it would have been possible to load zero and use the
+     three-address subtract to have a total size of 3+4*N bytes for
+     multiple negations, plus increased throughput.  Not attempted here.  */
+     
+  if (true_regnum (operands[0]) == true_regnum (operands[1]))
+    {
+      emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
+      emit_insn (gen_addsi3 (operands[0], operands[0], const1_rtx));
+    }
+  else
+    {
+      emit_move_insn (operands[0], const0_rtx);
+      emit_insn (gen_subsi3 (operands[0], operands[0], operands[1]));
+    }
   DONE;
-}")
+})
 
 ;; ----------------------------------------------------------------------
 ;; MULTIPLY INSTRUCTIONS
 ;; AND INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_expand "andsi3"
-  [(parallel [(set (match_operand:SI         0 "register_operand")
-                  (and:SI (match_operand:SI 1 "register_operand")
-                          (match_operand:SI 2 "nonmemory_operand")))
-             (clobber (reg:CC CC_REG))
-            ])
-  ]
+(define_insn "andsi3"
+  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (and:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
+   (clobber (reg:CC CC_REG))]
   ""
-  "")
-
-(define_insn "*am33_andsi3"
-  [(set (match_operand:SI         0 "register_operand" "=dx,dx,!dax")
-       (and:SI (match_operand:SI 1 "register_operand" "%0,0,dax")
-               (match_operand:SI 2 "nonmemory_operand" "N,dxi,dax")))
-   (clobber (reg:CC CC_REG))
-  ]
-  "TARGET_AM33"
-  {
-    if (CONST_INT_P (operands[2]))
-      switch (INTVAL (operands[2]))
-        {
-        case 0xff:       return "extbu %0";
-        case 0xffff:     return "exthu %0";
-        case 0x7fffffff: return "add  %0, %0; lsr 1, %0";
-        case 0x3fffffff: return "asl2 %0; lsr 2, %0";
-        case 0x1fffffff: return "add  %0, %0; asl2 %0; lsr 3, %0";
-        case 0x0fffffff: return "asl2 %0; asl2 %0; lsr 4, %0";
-        case 0xfffffffe: return "lsr 1, %0; add  %0, %0";
-        case 0xfffffffc: return "lsr 2, %0; asl2 %0";
-        case 0xfffffff8: return "lsr 3, %0; add  %0, %0; asl2 %0";
-        case 0xfffffff0: return "lsr 4, %0; asl2 %0; asl2 %0";
-        }
-      
-    if (REG_P (operands[2]) && REG_P (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[2])
-        && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
-        && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
-        && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
-      return "mov %1, %0; and %2, %0";
-    if (REG_P (operands[2]) && REG_P (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[2]))
-      return "and %1, %2, %0";
-    if (REG_P (operands[2]) && REG_P (operands[0])
-        && true_regnum (operands[2]) == true_regnum (operands[0]))
-      return "and %1, %0";
-
-    return "and %2, %0";
-  }
-  [(set_attr "timings" "33")]
+  "@
+   and %2,%0
+   and %2,%0
+   and %2,%1,%0"
+  [(set_attr "isa" "*,*,am33")
+   (set_attr "timings" "22,11,11")]
+)
+
+(define_insn "*andsi3_flags"
+  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (and:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
+   (set (reg CC_REG)
+       (compare (and:SI (match_dup 1) (match_dup 2))
+                (const_int 0)))]
+  "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
+  "@
+   and %2,%0
+   and %2,%0
+   and %2,%1,%0"
+  [(set_attr "isa" "*,*,am33")
+   (set_attr "timings" "22,11,11")]
 )
 
-(define_insn "*mn10300_andsi3"
-  [(set (match_operand:SI         0 "register_operand" "=dx,dx")
-       (and:SI (match_operand:SI 1 "register_operand" "%0,0")
-               (match_operand:SI 2 "nonmemory_operand" "N,dxi")))
-   (clobber (reg:CC CC_REG))
-  ]
+;; Make sure we generate extensions instead of ANDs.
+
+(define_split
+  [(parallel [(set (match_operand:SI 0 "register_operand" "")
+                  (and:SI (match_operand:SI 1 "register_operand" "")
+                          (const_int 255)))
+             (clobber (reg:CC CC_REG))])]
   ""
-  {
-    if (CONST_INT_P (operands[2]))
-      switch (INTVAL (operands[2]))
-        {
-        case 0xff:       return "extbu %0";
-        case 0xffff:     return "exthu %0";
-        case 0x7fffffff: return "add  %0, %0; lsr 1, %0";
-        case 0x3fffffff: return "asl2 %0; lsr 2, %0";
-        case 0x1fffffff: return "add  %0, %0; asl2 %0; lsr 3, %0";
-        case 0x0fffffff: return "asl2 %0; asl2 %0; lsr 4, %0";
-        case 0xfffffffe: return "lsr 1, %0; add  %0, %0";
-        case 0xfffffffc: return "lsr 2, %0; asl2 %0";
-        case 0xfffffff8: return "lsr 3, %0; add  %0, %0; asl2 %0";
-        case 0xfffffff0: return "lsr 4, %0; asl2 %0; asl2 %0";
-       }
+  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
+  { operands[1] = gen_lowpart (QImode, operands[1]); }
+)
 
-    return "and %2, %0";
-  }
-  [(set_attr "timings" "33")]
+(define_split
+  [(parallel [(set (match_operand:SI 0 "register_operand" "")
+                  (and:SI (match_operand:SI 1 "register_operand" "")
+                          (const_int 65535)))
+             (clobber (reg:CC CC_REG))])]
+  ""
+  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
+  { operands[1] = gen_lowpart (HImode, operands[1]); }
 )
 
+;; Split AND by an appropriate constant into two shifts.  Recall that 
+;; operations with a full 32-bit immediate require an extra cycle, so
+;; this is a size optimization with no speed penalty.  This only applies
+;; do DATA_REGS; the shift insns that AM33 adds are too large for a win.
+
+(define_split
+  [(parallel [(set (match_operand:SI 0 "register_operand" "")
+                  (and:SI (match_dup 0)
+                          (match_operand:SI 1 "const_int_operand" "")))
+             (clobber (reg:CC CC_REG))])]
+  "reload_completed
+   && REGNO_DATA_P (true_regnum (operands[0]), 1)
+   && mn10300_split_and_operand_count (operands[1]) != 0"
+  [(const_int 0)]
+{
+  int count = mn10300_split_and_operand_count (operands[1]);
+  if (count > 0)
+    {
+      emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (count)));
+      emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (count)));
+    }
+  else
+    {
+      emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (-count)));
+      emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (-count)));
+    }
+  DONE;
+})
+
 ;; ----------------------------------------------------------------------
 ;; OR INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_expand "iorsi3"
-  [(parallel [(set (match_operand:SI         0 "register_operand")
-                  (ior:SI (match_operand:SI 1 "register_operand")
-                          (match_operand:SI 2 "nonmemory_operand")))
-             (clobber (reg:CC CC_REG))
-            ])
-  ]
-  ""
-  "")
-
-(define_insn "*am33_iorsi3"
-  [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
-       (ior:SI (match_operand:SI 1 "register_operand" "%0,dax")
-               (match_operand:SI 2 "nonmemory_operand" "dxi,dax")))
-   (clobber (reg:CC CC_REG))
-  ]
-  "TARGET_AM33"
-  "*
-  {
-    if (REG_P (operands[2]) && REG_P (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[2])
-        && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
-        && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
-        && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
-      return \"mov %1,%0\;or %2,%0\";
-    if (REG_P (operands[2]) && REG_P (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[2]))
-      return \"or %1,%2,%0\";
-    if (REG_P (operands[2]) && REG_P (operands[0])
-        && true_regnum (operands[2]) == true_regnum (operands[0]))
-      return \"or %1,%0\";
-    return \"or %2,%0\";
-  }"
-  [(set_attr "timings" "22")]
-)
-
-(define_insn "*mn10300_iorsi3"
-  [(set (match_operand:SI         0 "register_operand" "=dx")
-       (ior:SI (match_operand:SI 1 "register_operand" "%0")
-               (match_operand:SI 2 "nonmemory_operand" "dxi")))
-   (clobber (reg:CC CC_REG))
-  ]
+(define_insn "iorsi3"
+  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (ior:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
+   (clobber (reg:CC CC_REG))]
   ""
-  "or %2,%0"
-  [(set_attr "timings" "33")]
+  "@
+   or %2,%0
+   or %2,%0
+   or %2,%1,%0"
+  [(set_attr "isa" "*,*,am33")
+   (set_attr "timings" "22,11,11")]
+)
+
+(define_insn "*iorsi3_flags"
+  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (ior:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
+   (set (reg CC_REG)
+       (compare (ior:SI (match_dup 1) (match_dup 2))
+                (const_int 0)))]
+  "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
+  "@
+   or %2,%0
+   or %2,%0
+   or %2,%1,%0"
+  [(set_attr "isa" "*,*,am33")
+   (set_attr "timings" "22,11,11")]
 )
 
 ;; ----------------------------------------------------------------------
 ;; XOR INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_expand "xorsi3"
-  [(parallel [(set (match_operand:SI         0 "register_operand")
-                  (xor:SI (match_operand:SI 1 "register_operand")
-                          (match_operand:SI 2 "nonmemory_operand")))
-             (clobber (reg:CC CC_REG))
-            ])
-  ]
-  ""
-  "")
-
-(define_insn "*am33_xorsi3"
-  [(set (match_operand:SI         0 "register_operand" "=dx,!dax")
-       (xor:SI (match_operand:SI 1 "register_operand" "%0,dax")
-               (match_operand:SI 2 "nonmemory_operand" "dxi,dax")))
-   (clobber (reg:CC CC_REG))
-  ]
-  "TARGET_AM33"
-  "*
-  {
-    if (REG_P (operands[2]) && REG_P (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[2])
-        && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
-        && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
-        && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
-      return \"mov %1,%0\;xor %2,%0\";
-    if (REG_P (operands[2]) && REG_P (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[1])
-        && true_regnum (operands[0]) != true_regnum (operands[2]))
-      return \"xor %1,%2,%0\";
-    if (REG_P (operands[2]) && REG_P (operands[0])
-        && true_regnum (operands[2]) == true_regnum (operands[0]))
-      return \"xor %1,%0\";
-    return \"xor %2,%0\";
-  }"
-  [(set_attr "timings" "22")]
-)
-
-(define_insn "*mn10300_xorsi3"
-  [(set (match_operand:SI         0 "register_operand" "=dx")
-       (xor:SI (match_operand:SI 1 "register_operand" "%0")
-               (match_operand:SI 2 "nonmemory_operand" "dxi")))
-   (clobber (reg:CC CC_REG))
-  ]
+(define_insn "xorsi3"
+  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (xor:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
+   (clobber (reg:CC CC_REG))]
   ""
-  "xor %2,%0"
-  [(set_attr "timings" "11")]
+  "@
+   xor %2,%0
+   xor %2,%0
+   xor %2,%1,%0"
+  [(set_attr "isa" "*,*,am33")
+   (set_attr "timings" "22,11,11")]
+)
+
+(define_insn "*xorsi3_flags"
+  [(set (match_operand:SI         0 "register_operand"  "=D,D,r")
+       (xor:SI (match_operand:SI 1 "register_operand"  "%0,0,r")
+               (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
+   (set (reg CC_REG)
+       (compare (xor:SI (match_dup 1) (match_dup 2))
+                (const_int 0)))]
+  "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
+  "@
+   xor %2,%0
+   xor %2,%0
+   xor %2,%1,%0"
+  [(set_attr "isa" "*,*,am33")
+   (set_attr "timings" "22,11,11")]
 )
 
 ;; ----------------------------------------------------------------------
 ;; NOT INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_expand "one_cmplsi2"
-  [(parallel [(set (match_operand:SI         0 "register_operand")
-                  (not:SI (match_operand:SI 1 "register_operand")))
-             (clobber (reg:CC CC_REG))
-            ])
-  ]
+(define_insn "one_cmplsi2"
+  [(set (match_operand:SI         0 "register_operand" "=D")
+       (not:SI (match_operand:SI 1 "register_operand" " 0")))
+   (clobber (reg:CC CC_REG))]
   ""
-  "")
-
-(define_insn "*am33_cmplsi2"
-  [(set (match_operand:SI         0 "register_operand" "=dx,!dax")
-       (not:SI (match_operand:SI 1 "register_operand" "0,0")))
-   (clobber (reg:CC CC_REG))
-  ]
-  "TARGET_AM33"
   "not %0"
 )
 
-(define_insn "*mn10300_cmplsi2"
-  [(set (match_operand:SI         0 "register_operand" "=dx")
-       (not:SI (match_operand:SI 1 "register_operand" "0")))
-   (clobber (reg:CC CC_REG))
-  ]
-  ""
+(define_insn "*one_cmplsi2_flags"
+  [(set (match_operand:SI         0 "register_operand" "=D")
+       (not:SI (match_operand:SI 1 "register_operand" " 0")))
+   (set (reg CC_REG)
+       (compare (not:SI (match_dup 1))
+                (const_int 0)))]
+  "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
   "not %0"
 )
 \f
              (match_operator                    0 "ordered_comparison_operator"
                              [(match_operand:SI 1 "register_operand")
                               (match_operand:SI 2 "nonmemory_operand")])
-              (label_ref (match_operand          3 ""))
+              (label_ref (match_operand 3 ""))
               (pc)))]
   ""
   ""
 )
 
-(define_insn_and_split "*cbranchsi4_post_reload"
+(define_insn_and_split "*cbranchsi4_cmp"
   [(set (pc)
        (if_then_else (match_operator           3 "ordered_comparison_operator"
-                       [(match_operand:SI       0 "register_operand"  "dax")
-                       (match_operand:SI       1 "nonmemory_operand" "daxi")])
-                     (label_ref (match_operand 2 "" ""))
-                     (pc)))
-   ]
+                       [(match_operand:SI       0 "register_operand"  "r")
+                       (match_operand:SI       1 "nonmemory_operand" "ri")])
+                     (match_operand            2 "label_ref_operand" "")
+                     (pc)))]
   ""
   "#"
   "reload_completed"
   [(const_int 0)]
-  "
-  /* We construct the split by hand as otherwise the JUMP_LABEL
-     attribute is not set correctly on the jump insn.  */
-  emit_insn (gen_cmpsi (operands[0], operands[1]));
-  
-  emit_jump_insn (gen_integer_conditional_branch
-                      (gen_rtx_fmt_ee (GET_CODE (operands[3]),
-                                      CCmode,
-                                      gen_rtx_REG (CCmode, CC_REG),
-                                                   const0_rtx),
-                                      operands[2]));
-  "
-)
+{
+  mn10300_split_cbranch (CCmode, operands[3], operands[2]);
+  DONE;
+})
 
-;; Ordinarily, the cmp instruction will set the Z bit of cc0 to 1 if
-;; its operands hold equal values, but the operands of a cmp
-;; instruction must be distinct registers.  In the case where we'd
-;; like to compare a register to itself, we can achieve this effect
-;; with a btst 0,d0 instead.  (This will not alter the contents of d0
-;; but will have the proper effect on cc0.  Using d0 is arbitrary; any
-;; data register would work.)
-
-;; Even though the first alternative would be preferable if it can
-;; possibly match, reload must not be given the opportunity to attempt
-;; to use it.  It assumes that such matches can only occur when one of
-;; the operands is used for input and the other for output.  Since
-;; this is not the case, it abort()s.  Indeed, such a reload cannot be
-;; possibly satisfied, so just mark the alternative with a `!', so
-;; that it is not considered by reload.
-
-(define_insn "cmpsi"
-  [(set (reg:CC CC_REG)
-       (compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax,dax")
-                (match_operand:SI 1 "nonmemory_operand" "*0,I,daxi")))]
-  ""
-  {
-    if (which_alternative == 0)
-      return \"btst 0,d0\";
-    if (which_alternative == 1)
-      return mn10300_output_cmp (operands[0], insn);
-    return \"cmp %1,%0\";
-  }
+(define_insn "*cmpsi"
+  [(set (reg CC_REG)
+       (compare (match_operand:SI 0 "register_operand"  "r")
+                (match_operand:SI 1 "nonmemory_operand" "ri")))]
+  "reload_completed"
+{
+  /* The operands of CMP must be distinct registers.  In the case where
+     we've failed to optimize the comparison of a register to itself, we
+     must use another method to set the Z flag.  We can achieve this 
+     effect with a BTST 0,D0.  This will not alter the contents of D0;
+     the use of d0 is arbitrary; any data register would work.  */
+  if (rtx_equal_p (operands[0], operands[1]))
+    return "btst 0,d0";
+  else
+    return "cmp %1,%0";
+}
   [(set_attr_alternative "timings"
-                        [(const_int 11)
-                         (if_then_else (eq_attr "cpu" "am34")
-                                       (const_int 11) (const_int 22))
-                         (const_int 22)
-                        ])
-  ]
+     [(if_then_else (eq_attr "cpu" "am34") (const_int 11) (const_int 22))])]
 )
 
-(define_insn "integer_conditional_branch"
+(define_insn "*integer_conditional_branch"
   [(set (pc)
        (if_then_else (match_operator 0 "comparison_operator"
-                                     [(reg:CC CC_REG) (const_int 0)])
+                       [(match_operand 2 "int_mode_flags" "")
+                        (const_int 0)])
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
-  ""
+  "reload_completed"
   "b%b0 %1"
 )
 
+(define_insn_and_split "*cbranchsi4_btst"
+  [(set (pc)
+       (if_then_else
+         (match_operator 3 "CCZN_comparison_operator"
+           [(and:SI (match_operand:SI 0 "register_operand" "D")
+                    (match_operand:SI 1 "immediate_operand" "i"))
+            (const_int 0)])
+         (match_operand 2 "label_ref_operand" "")
+         (pc)))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  mn10300_split_cbranch (CCZNmode, operands[3], operands[2]);
+  DONE;
+})
+
+(define_insn "*btstsi"
+  [(set (reg:CCZN CC_REG)
+       (compare:CCZN
+         (and:SI (match_operand:SI 0 "register_operand" "D")
+                 (match_operand:SI 1 "immediate_operand" "i"))
+         (const_int 0)))]
+  "reload_completed"
+  "btst %1,%0"
+)
+
 (define_expand "cbranchsf4"
   [(set (pc)
       (if_then_else
             (match_operator                    0 "ordered_comparison_operator"
                            [(match_operand:SF 1 "register_operand")
                             (match_operand:SF 2 "nonmemory_operand")])
-           (label_ref (match_operand          3 ""))
+           (label_ref (match_operand 3 ""))
            (pc)))]
   "TARGET_AM33_2"
   ""
 )
 
-(define_insn_and_split "*cbranchsf4_post_reload"
+(define_insn_and_split "*cbranchsf4_cmp"
   [(set (pc)
        (if_then_else (match_operator            3 "ordered_comparison_operator"
                        [(match_operand:SF       0 "register_operand"  "f")
                         (match_operand:SF       1 "nonmemory_operand" "fF")])
-                     (label_ref (match_operand  2 "" ""))
+                     (match_operand             2 "label_ref_operand" "")
                      (pc)))
    ]
   "TARGET_AM33_2"
   "#"
   "&& reload_completed"
   [(const_int 0)]
-  "
-  /* We construct the split by hand as otherwise the JUMP_LABEL
-     attribute is not set correctly on the jump insn.  */
-  emit_insn (gen_am33_cmpsf (operands[0], operands[1]));
-  
-  emit_jump_insn (gen_float_conditional_branch
-                     (gen_rtx_fmt_ee (GET_CODE (operands[3]),
-                                     CC_FLOATmode,
-                                     gen_rtx_REG (CC_FLOATmode, CC_REG),
-                                     const0_rtx),
-                                     operands[2]));
-  "
-)
+{
+  mn10300_split_cbranch (CC_FLOATmode, operands[3], operands[2]);
+  DONE;
+})
 
-(define_insn "am33_cmpsf"
+(define_insn "*am33_cmpsf"
   [(set (reg:CC_FLOAT CC_REG)
        (compare:CC_FLOAT (match_operand:SF 0 "register_operand"  "f")
                          (match_operand:SF 1 "nonmemory_operand" "fF")))]
-  "TARGET_AM33_2"
+  "TARGET_AM33_2 && reload_completed"
   "fcmp %1, %0"
   [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
                                       (const_int 17) (const_int 25)))]
 )
 
-(define_insn "float_conditional_branch"
+(define_insn "*float_conditional_branch"
   [(set (pc)
        (if_then_else (match_operator 0 "comparison_operator"
                                      [(reg:CC_FLOAT CC_REG) (const_int 0)])
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
-  "TARGET_AM33_2"
+  "TARGET_AM33_2 && reload_completed"
   "fb%b0 %1"
   [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
                                       (const_int 44) (const_int 33)))]
    (match_operand:SI 2 "immediate_operand")
    (match_operand 3 "" "") (match_operand 4 "")]
   ""
-  "
 {
   rtx table = gen_reg_rtx (SImode);
   rtx index = gen_reg_rtx (SImode);
 
   emit_jump_insn (gen_tablejump (addr, operands[3]));
   DONE;
-}")
+})
 
 (define_insn "tablejump"
   [(set (pc) (match_operand:SI 0 "register_operand" "a"))
               (match_operand 1 "")
               (match_operand 2 "")])]
   ""
-  "
 {
   int i;
 
       emit_move_insn (SET_DEST (set), SET_SRC (set));
     }
   DONE;
-}")
+})
 
 (define_insn "nop"
   [(const_int 0)]
 ;; EXTEND INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_expand "zero_extendqisi2"
-  [(set (match_operand:SI 0 "register_operand")
+(define_insn "zero_extendqisi2"
+  [(set (match_operand:SI 0 "register_operand"      "=D,D,r")
        (zero_extend:SI
-        (match_operand:QI 1 "nonimmediate_operand")))]
+        (match_operand:QI 1 "nonimmediate_operand" " 0,m,r")))]
   ""
-  "")
-
-(define_insn "*zero_extendqisi2_am33"
-  [(set (match_operand:SI 0 "register_operand" "=dx,dx,dx,!dax,!dax,!dax")
-       (zero_extend:SI
-        (match_operand:QI 1 "nonimmediate_operand" "0,dax,m,0,dax,m")))]
-  "TARGET_AM33"
   "@
-  extbu %0
-  mov %1,%0\;extbu %0
-  movbu %1,%0
-  extbu %0
-  mov %1,%0\;extbu %0
-  movbu %1,%0"
-  [(set_attr_alternative "timings"
-                        [(const_int 11)
-                         (const_int 22)
-                         (if_then_else (eq_attr "cpu" "am34")
-                                       (const_int 13) (const_int 24))
-                         (const_int 11)
-                         (const_int 22)
-                         (if_then_else (eq_attr "cpu" "am34")
-                                       (const_int 13) (const_int 24))
-                        ])
-  ]
-)
-
-(define_insn "*zero_extendqisi2_mn10300"
-  [(set (match_operand:SI 0 "register_operand" "=dx,dx,dx")
-       (zero_extend:SI
-        (match_operand:QI 1 "nonimmediate_operand" "0,d,m")))]
-  ""
-  "@
-  extbu %0
-  mov %1,%0\;extbu %0
-  movbu %1,%0"
-  [(set_attr_alternative "timings"
-                        [(const_int 11)
-                         (const_int 22)
-                         (if_then_else (eq_attr "cpu" "am34")
-                                       (const_int 13) (const_int 24))
-                        ])
-  ]
-)
-
-(define_expand "zero_extendhisi2"
-  [(set (match_operand:SI 0 "register_operand")
-       (zero_extend:SI
-        (match_operand:HI 1 "nonimmediate_operand")))]
-  ""
-  "")
-
-(define_insn "*zero_extendhisi2_am33"
-  [(set (match_operand:SI 0 "register_operand" "=dx,dx,dx,!dax,!dax,!dax")
-       (zero_extend:SI
-        (match_operand:HI 1 "nonimmediate_operand" "0,dax,m,0,dax,m")))]
-  "TARGET_AM33"
-  "@
-  exthu %0
-  mov %1,%0\;exthu %0
-  movhu %1,%0
-  exthu %0
-  mov %1,%0\;exthu %0
-  movhu %1,%0"
-  [(set_attr_alternative "timings"
-                        [(const_int 11)
-                         (const_int 22)
-                         (if_then_else (eq_attr "cpu" "am34")
-                                       (const_int 13) (const_int 24))
-                         (const_int 11)
-                         (const_int 22)
-                         (if_then_else (eq_attr "cpu" "am34")
-                                       (const_int 13) (const_int 24))
-                        ])
-  ]
+   extbu %0
+   movbu %1,%0
+   extbu %1,%0"
+  [(set_attr "isa" "*,*,am33")
+   (set_attr_alternative "timings"
+                [(const_int 11)
+                 (if_then_else (eq_attr "cpu" "am34")
+                               (const_int 13) (const_int 24))
+                 (const_int 11)
+                ])]
 )
 
-(define_insn "*zero_extendhisi2_mn10300"
-  [(set (match_operand:SI 0 "register_operand" "=dx,dx,dx")
+(define_insn "zero_extendhisi2"
+  [(set (match_operand:SI 0 "register_operand"      "=D,D,r")
        (zero_extend:SI
-        (match_operand:HI 1 "nonimmediate_operand" "0,dx,m")))]
-  ""
-  "@
-  exthu %0
-  mov %1,%0\;exthu %0
-  movhu %1,%0"
-  [(set_attr_alternative "timings"
-                        [(const_int 11)
-                         (const_int 22)
-                         (if_then_else (eq_attr "cpu" "am34")
-                                       (const_int 13) (const_int 24))
-                        ])
-  ]
-)
-
-;;- sign extension instructions
-
-(define_expand "extendqisi2"
-  [(set (match_operand:SI 0 "register_operand")
-       (sign_extend:SI
-        (match_operand:QI 1 "register_operand")))]
+        (match_operand:HI 1 "nonimmediate_operand" " 0,m,r")))]
   ""
-  "")
-
-(define_insn "*extendqisi2_am33"
-  [(set (match_operand:SI 0 "register_operand" "=dx,dx,!dax,!dax")
-       (sign_extend:SI
-        (match_operand:QI 1 "register_operand" "0,dx,0,dax")))]
-  "TARGET_AM33"
   "@
-  extb %0
-  mov %1,%0\;extb %0
-  extb %0
-  mov %1,%0\;extb %0"
-  [(set_attr "timings" "11,22,11,22")]
-)
-
-(define_insn "*extendqisi2_mn10300"
-  [(set (match_operand:SI 0 "register_operand" "=dx,dx")
-       (sign_extend:SI
-        (match_operand:QI 1 "register_operand" "0,dx")))]
-  ""
-  "@
-  extb %0
-  mov %1,%0\;extb %0"
-  [(set_attr "timings" "11,22")]
+   exthu %0
+   movhu %1,%0
+   exthu %1,%0"
+  [(set_attr "isa" "*,*,am33")
+   (set_attr_alternative "timings"
+                [(const_int 11)
+                 (if_then_else (eq_attr "cpu" "am34")
+                               (const_int 13) (const_int 24))
+                 (const_int 11)])]
 )
 
-(define_expand "extendhisi2"
-  [(set (match_operand:SI 0 "register_operand")
+(define_insn "extendqisi2"
+  [(set (match_operand:SI 0 "register_operand" "=D,r")
        (sign_extend:SI
-        (match_operand:HI 1 "register_operand")))]
+        (match_operand:QI 1 "register_operand" "0,r")))]
   ""
-  "")
-
-(define_insn "*extendhisi2_am33"
-  [(set (match_operand:SI 0 "register_operand" "=dx,dx,!dax,!dax")
-       (sign_extend:SI
-        (match_operand:HI 1 "register_operand" "0,dax,0,dax")))]
-  "TARGET_AM33"
   "@
-  exth %0
-  mov %1,%0\;exth %0
-  exth %0
-  mov %1,%0\;exth %0"
-  [(set_attr "timings" "11,22,11,22")]
+   extb %0
+   extb %1,%0"
+  [(set_attr "isa" "*,am33")]
 )
 
-(define_insn "*extendhisi2_mn10300"
-  [(set (match_operand:SI 0 "register_operand" "=dx,dx")
+(define_insn "extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=D,r")
        (sign_extend:SI
-        (match_operand:HI 1 "register_operand" "0,dx")))]
+        (match_operand:HI 1 "register_operand" "0,r")))]
   ""
   "@
-  exth %0
-  mov %1,%0\;exth %0"
-  [(set_attr "timings" "11,22")]
+   exth %0
+   exth %1,%0"
+  [(set_attr "isa" "*,am33")]
 )
 \f
 ;; ----------------------------------------------------------------------
 ;; SHIFTS
 ;; ----------------------------------------------------------------------
 
-(define_expand "ashlsi3"
-  [(parallel [(set (match_operand:SI 0 "register_operand")
-                  (ashift:SI
-                   (match_operand:SI 1 "register_operand")
-                   (match_operand:QI 2 "nonmemory_operand")))
-             (clobber (reg:CC CC_REG))
-            ])
-  ]
-  ""
-  "")
-
-(define_insn "*am33_ashlsi3"
-  [(set (match_operand:SI 0 "register_operand" "=dax,dx,!dax")
+(define_insn "ashlsi3"
+  [(set (match_operand:SI  0 "register_operand"  "=r,D,d,d, D,r")
        (ashift:SI
-        (match_operand:SI 1 "register_operand" "0,0,dax")
-        (match_operand:QI 2 "nonmemory_operand" "J,dxi,dax")))
-   (clobber (reg:CC CC_REG))
-  ]
-  "TARGET_AM33"
-  "*
-  {
-    if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
-      return \"add %0,%0\";
-
-    if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 2)
-      return \"asl2 %0\";
-
-    if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 3
-        && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
-      return \"asl2 %0\;add %0,%0\";
-
-    if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 4
-        && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
-      return \"asl2 %0\;asl2 %0\";
-
-    if (true_regnum (operands[1]) == true_regnum (operands[0]))
-      return \"asl %S2,%0\";
-
-    if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
-        && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
-        && true_regnum (operands[0]) != true_regnum (operands[2]))
-      return \"mov %1,%0\;asl %S2,%0\";
-    return \"asl %2,%1,%0\";
-  }"
-  [(set_attr "timings" "22")]
-)
-
-(define_insn "*mn10300_ashlsi3"
-  [(set (match_operand:SI 0 "register_operand" "=dax,dx,dx,dx,dx")
-       (ashift:SI
-        (match_operand:SI 1 "register_operand" "0,0,0,0,0")
-        (match_operand:QI 2 "nonmemory_operand" "J,K,M,L,dxi")))
-   (clobber (reg:CC CC_REG))
-  ]
+         (match_operand:SI 1 "register_operand"  " 0,0,0,0, 0,r")
+         (match_operand:QI 2 "nonmemory_operand" " J,K,M,L,Di,r")))
+   (clobber (reg:CC CC_REG))]
   ""
   "@
-  add %0,%0
-  asl2 %0
-  asl2 %0\;add %0,%0
-  asl2 %0\;asl2 %0
-  asl %S2,%0"
-  [(set_attr "timings" "11,11,22,22,11")]
-)
-
-(define_expand "lshrsi3"
-  [(parallel [(set (match_operand:SI 0 "register_operand")
-                  (lshiftrt:SI
-                   (match_operand:SI 1 "register_operand")
-                   (match_operand:QI 2 "nonmemory_operand")))
-             (clobber (reg:CC CC_REG))
-            ])
-  ]
-  ""
-  "")
-
-(define_insn "*am33_lshrsi3"
-  [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+   add %0,%0
+   asl2 %0
+   asl2 %0\;add %0,%0
+   asl2 %0\;asl2 %0
+   asl %S2,%0
+   asl %2,%1,%0"
+  [(set_attr "isa" "*,*,*,*,*,am33")
+   (set_attr "timings" "11,11,22,22,11,11")]
+)
+
+(define_insn "lshrsi3"
+  [(set (match_operand:SI  0 "register_operand"  "=D,r")
        (lshiftrt:SI
-        (match_operand:SI 1 "register_operand" "0,dax")
-        (match_operand:QI 2 "nonmemory_operand" "dxi,dax")))
-   (clobber (reg:CC CC_REG))
-  ]
-  "TARGET_AM33"
-  "*
-  {
-    if (true_regnum (operands[1]) == true_regnum (operands[0]))
-      return \"lsr %S2,%0\";
-
-    if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
-        && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
-        && true_regnum (operands[0]) != true_regnum (operands[2]))
-      return \"mov %1,%0\;lsr %S2,%0\";
-    return \"lsr %2,%1,%0\";
-  }"
-  [(set_attr "timings" "22")]
-)
-
-(define_insn "*mn10300_lshrsi3"
-  [(set (match_operand:SI 0 "register_operand" "=dx")
-       (lshiftrt:SI
-        (match_operand:SI 1 "register_operand" "0")
-        (match_operand:QI 2 "nonmemory_operand" "dxi")))
-   (clobber (reg:CC CC_REG))
-  ]
-  ""
-  "lsr %S2,%0"
-  [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
-                                      (const_int 11) (const_int 22)))]
-)
-
-(define_expand "ashrsi3"
-  [(parallel [(set (match_operand:SI 0 "register_operand")
-                  (ashiftrt:SI
-                   (match_operand:SI 1 "register_operand")
-                   (match_operand:QI 2 "nonmemory_operand")))
-             (clobber (reg:CC CC_REG))
-            ])
-  ]
+         (match_operand:SI 1 "register_operand"  " 0,r")
+         (match_operand:QI 2 "nonmemory_operand" "Di,r")))
+   (clobber (reg:CC CC_REG))]
   ""
-  "")
-
-(define_insn "*am33_ashrisi3"
-  [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
-       (ashiftrt:SI
-        (match_operand:SI 1 "register_operand" "0,dax")
-        (match_operand:QI 2 "nonmemory_operand" "dxi,dax")))
-   (clobber (reg:CC CC_REG))
-  ]
-  "TARGET_AM33"
-  "*
-  {
-    if (true_regnum (operands[1]) == true_regnum (operands[0]))
-      return \"asr %S2,%0\";
-
-    if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
-        && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
-        && true_regnum (operands[0]) != true_regnum (operands[2]))
-      return \"mov %1,%0\;asr %S2,%0\";
-    return \"asr %2,%1,%0\";
-  }"
-  [(set_attr "timings" "22")]
+  "@
+   lsr %S2,%0
+   lsr %2,%1,%0"
+  [(set_attr "isa" "*,am33")]
 )
 
-(define_insn "*mn10300_ashrsi3"
-  [(set (match_operand:SI 0 "register_operand" "=dx")
+(define_insn "ashrsi3"
+  [(set (match_operand:SI  0 "register_operand"  "=D,r")
        (ashiftrt:SI
-        (match_operand:SI 1 "register_operand" "0")
-        (match_operand:QI 2 "nonmemory_operand" "dxi")))
-   (clobber (reg:CC CC_REG))
-  ]
+         (match_operand:SI 1 "register_operand"  " 0,r")
+         (match_operand:QI 2 "nonmemory_operand" "Di,r")))
+   (clobber (reg:CC CC_REG))]
   ""
-  "asr %S2,%0"
-  [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
-                                      (const_int 11) (const_int 22)))]
+  "@
+   asr %S2,%0
+   asr %2,%1,%0"
+  [(set_attr "isa" "*,am33")]
 )
 
 ;; ----------------------------------------------------------------------
   [(set_attr "timings" "66")]
 )
 
-;; Try to combine consecutive updates of the stack pointer (or any
-;; other register for that matter).
-(define_peephole
-  [(parallel [(set (match_operand:SI 0 "register_operand" "=dxay")
-                  (plus:SI (match_dup 0)
-                           (match_operand 1 "const_int_operand" "")))
-             (clobber (reg:CC CC_REG))
-            ])
-   (parallel [(set (match_dup 0)
-                  (plus:SI (match_dup 0)
-                           (match_operand 2 "const_int_operand" "")))
-             (clobber (reg:CC CC_REG))
-            ])
-  ]
-  ""
-  "*
-{
-  operands[1] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[1]));
-  return \"add %1,%0\";
-}"
-)
-
 (define_expand "int_label"
   [(unspec [(match_operand:SI 0 "" "")] UNSPEC_INT_LABEL)]
   "" "")
index df1b1f479663a2ebdccf9b9514a5eba1e8ac0af1..4badebba69905a28f469694d5ccb594cb33839ab 100644 (file)
   return XEXP (op, 0) == stack_pointer_rtx
       || XEXP (op, 1) == stack_pointer_rtx;
 })
+
+(define_predicate "label_ref_operand"
+  (match_code "label_ref"))
+
+(define_special_predicate "int_mode_flags"
+  (match_code "reg")
+{
+  if (REGNO (op) != CC_REG)
+    return false;
+  if (GET_MODE (op) == CC_FLOATmode)
+    return false;
+  return GET_MODE_CLASS (GET_MODE (op)) == MODE_CC;
+})
+
+(define_predicate "CCZN_comparison_operator"
+  (match_code "eq,ne,lt,ge"))