*** empty log message ***
authorMichael Meissner <meissner@gcc.gnu.org>
Mon, 27 Apr 1992 19:14:40 +0000 (19:14 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Mon, 27 Apr 1992 19:14:40 +0000 (19:14 +0000)
From-SVN: r844

gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md

index 203ade8b84616fe240ce57e629fb82d90baba113..f47d88f35edb0d36d270a2ecc860ba807c004b77 100644 (file)
@@ -94,6 +94,24 @@ extern char **save_argv;
 extern char  *version_string;
 extern char  *language_string;
 
+/* Enumeration for all of the relational tests, so that we can build
+   arrays indexed by the test type, and not worry about the order
+   of EQ, NE, etc. */
+
+enum internal_test {
+    ITEST_EQ,
+    ITEST_NE,
+    ITEST_GT,
+    ITEST_GE,
+    ITEST_LT,
+    ITEST_LE,
+    ITEST_GTU,
+    ITEST_GEU,
+    ITEST_LTU,
+    ITEST_LEU,
+    ITEST_MAX
+  };
+
 /* Global variables for machine-dependent things.  */
 
 /* Threshold for data being put into the small data/bss area, instead
@@ -462,6 +480,16 @@ md_register_operand (op, mode)
          && MD_REG_P (REGNO (op)));
 }
 
+/* Return truth value of whether OP is the FP status register.  */
+
+int
+fpsw_register_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return (GET_CODE (op) == REG && ST_REG_P (REGNO (op)));
+}
+
 /* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant.  */
 
 int
@@ -658,6 +686,23 @@ fcmp_op (op, mode)
   return (classify_op (op, mode) & CLASS_FCMP_OP) != 0;
 }
 
+
+/* Return true if the operand is either the PC or a label_ref.  */
+
+int
+pc_or_label_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (op == pc_rtx)
+    return TRUE;
+
+  if (GET_CODE (op) == LABEL_REF)
+    return TRUE;
+
+  return FALSE;
+}
+
 \f
 /* Return an operand string if the given instruction's delay slot or
    wrap it in a .set noreorder section.  This is for filling delay
@@ -683,7 +728,7 @@ mips_fill_delay_slot (ret, type, operands, cur_insn)
   register rtx next_insn       = (cur_insn) ? NEXT_INSN (cur_insn) : (rtx)0;
   register int num_nops;
 
-  if (type == DELAY_LOAD)
+  if (type == DELAY_LOAD || type == DELAY_FCMP)
     num_nops = 1;
 
   else if (type == DELAY_HILO)
@@ -1435,6 +1480,210 @@ mips_address_cost (addr)
   return 4;
 }
 
+\f
+/* Make normal rtx_code into something we can index from an array */
+
+static enum internal_test
+map_test_to_internal_test (test_code)
+     enum rtx_code test_code;
+{
+  enum internal_test test = ITEST_MAX;
+
+  switch (test_code)
+    {
+    case EQ:  test = ITEST_EQ;  break;
+    case NE:  test = ITEST_NE;  break;
+    case GT:  test = ITEST_GT;  break;
+    case GE:  test = ITEST_GE;  break;
+    case LT:  test = ITEST_LT;  break;
+    case LE:  test = ITEST_LE;  break;
+    case GTU: test = ITEST_GTU; break;
+    case GEU: test = ITEST_GEU; break;
+    case LTU: test = ITEST_LTU; break;
+    case LEU: test = ITEST_LEU; break;
+    }
+
+  return test;
+}
+
+\f
+/* Generate the code to compare two integer values.  The return value is:
+   (reg:SI xx)         The pseudo register the comparison is in
+   (const_int 0)       The comparison is always false
+   (const_int 1)       The comparison is always true
+   (rtx)0              No register, generate a simple branch.  */
+
+rtx
+gen_int_relational (test_code, result, cmp0, cmp1, p_invert)
+     enum rtx_code test_code;  /* relational test (EQ, etc) */
+     rtx result;               /* result to store comp. or 0 if branch */
+     rtx cmp0;                 /* first operand to compare */
+     rtx cmp1;                 /* second operand to compare */
+     int *p_invert;            /* NULL or ptr to hold whether branch needs */
+                               /* to reserse it's test */
+{
+  struct cmp_info {
+    enum rtx_code test_code;   /* code to use in instruction (LT vs. LTU) */
+    int const_low;             /* low bound of constant we can accept */
+    int const_high;            /* high bound of constant we can accept */
+    int const_add;             /* constant to add (convert LE -> LT) */
+    int reverse_regs;          /* reverse registers in test */
+    int invert_const;          /* != 0 if invert value if cmp1 is constant */
+    int invert_reg;            /* != 0 if invert value if cmp1 is register */
+  };
+
+  static struct cmp_info info[ (int)ITEST_MAX ] = {
+
+    { XOR,      0,  65535,  0,  0,  0,  0 },   /* EQ  */
+    { XOR,      0,  65535,  0,  0,  1,  1 },   /* NE  */
+    { LT,   -32769,  32766,  1,         1,  1,  0 },   /* GT  */
+    { LT,   -32768,  32767,  0,         0,  1,  1 },   /* GE  */
+    { LT,   -32768,  32767,  0,         0,  0,  0 },   /* LT  */
+    { LT,   -32769,  32766,  1,         1,  0,  1 },   /* LE  */
+    { LTU,  -32769,  32766,  1,         1,  1,  0 },   /* GTU */
+    { LTU,  -32768,  32767,  0,         0,  1,  1 },   /* GEU */
+    { LTU,  -32768,  32767,  0,         0,  0,  0 },   /* LTU */
+    { LTU,  -32769,  32766,  1,         1,  0,  1 },   /* LEU */
+  };
+
+  enum internal_test test;
+  struct cmp_info *p_info;
+  int branch_p;
+  int eqne_p;
+  int invert;
+  rtx reg;
+  rtx reg2;
+
+  test = map_test_to_internal_test (test_code);
+  if (test == ITEST_MAX)
+    abort ();
+
+  p_info = &info[ (int)test ];
+  eqne_p = (p_info->test_code == XOR);
+
+  /* See if the test is always true or false.  */
+  if ((GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)
+      && GET_CODE (cmp1) == CONST_INT)
+    {
+      int value = INTVAL (cmp1);
+      rtx truth = (rtx)0;
+
+      if (test == ITEST_GEU && value == 0)
+       truth = const1_rtx;
+
+      else if (test == ITEST_LTU && value == 0)
+       truth = const0_rtx;
+
+      else if (!TARGET_INT64)
+       {
+         if (test == ITEST_LTU && value == -1)
+           truth = const1_rtx;
+
+         else if (test == ITEST_GTU && value == -1)
+           truth = const0_rtx;
+
+         else if (test == ITEST_LEU && value == -1)
+           truth = const1_rtx;
+
+         else if (test == ITEST_GT && value == 0x7fffffff)
+           truth = const0_rtx;
+
+         else if (test == ITEST_LE && value == 0x7fffffff)
+           truth = const1_rtx;
+
+         else if (test == ITEST_LT && value == 0x80000000)
+           truth = const0_rtx;
+
+         else if (test == ITEST_GE && value == 0x80000000)
+           truth = const1_rtx;
+       }
+
+      if (truth != (rtx)0)
+       {
+         if (result != (rtx)0)
+           emit_move_insn (result, truth);
+
+         return truth;
+       }
+    }
+
+  /* Eliminate simple branches */
+  branch_p = (result == (rtx)0);
+  if (branch_p)
+    {
+      if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)
+       {
+         /* Comparisons against zero are simple branches */
+         if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
+           return (rtx)0;
+
+         /* Test for beq/bne.  */
+         if (eqne_p)
+           return (rtx)0;
+       }
+
+      /* allocate a psuedo to calculate the value in.  */
+      result = gen_reg_rtx (SImode);
+    }
+
+  /* Make sure we can handle any constants given to us.  */
+  if (GET_CODE (cmp0) == CONST_INT)
+    cmp0 = force_reg (SImode, cmp0);
+
+  if (GET_CODE (cmp1) == CONST_INT)
+    {
+      int value = INTVAL (cmp1);
+      if (value < p_info->const_low || value > p_info->const_high)
+       cmp1 = force_reg (SImode, cmp1);
+    }
+
+  /* See if we need to invert the result.  */
+  invert = (GET_CODE (cmp1) == CONST_INT)
+               ? p_info->invert_const
+               : p_info->invert_reg;
+
+  if (p_invert != (int *)0)
+    {
+      *p_invert = invert;
+      invert = FALSE;
+    }
+
+  /* Comparison to constants, may involve adding 1 to change a LT into LE.
+     Comparison between two registers, may involve switching operands.  */
+  if (GET_CODE (cmp1) == CONST_INT)
+    {
+      if (p_info->const_add != 0)
+       cmp1 = gen_rtx (CONST_INT, VOIDmode, INTVAL (cmp1) + p_info->const_add);
+    }
+  else if (p_info->reverse_regs)
+    {
+      rtx temp = cmp0;
+      cmp0 = cmp1;
+      cmp1 = temp;
+    }
+
+  reg = (invert || eqne_p) ? gen_reg_rtx (SImode) : result;
+  emit_move_insn (reg, gen_rtx (p_info->test_code, SImode, cmp0, cmp1));
+
+  if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
+    {
+      emit_move_insn (result, gen_rtx (GTU, SImode, reg, const0_rtx));
+      invert = FALSE;
+    }
+
+  else if (eqne_p)
+    {
+      reg2 = (invert) ? gen_reg_rtx (SImode) : result;
+      emit_move_insn (reg2, gen_rtx (LTU, SImode, reg, const1_rtx));
+      reg = reg2;
+    }
+
+  if (invert)
+    emit_move_insn (result, gen_rtx (XOR, SImode, reg, const1_rtx));
+
+  return result;
+}
+
 \f
 /* Emit the common code for doing conditional branches.
    operand[0] is the label to jump to.
@@ -1445,36 +1694,22 @@ gen_conditional_branch (operands, test_code)
      rtx operands[];
      enum rtx_code test_code;
 {
-  enum {
-    I_EQ,
-    I_NE,
-    I_GT,
-    I_GE,
-    I_LT,
-    I_LE,
-    I_GTU,
-    I_GEU,
-    I_LTU,
-    I_LEU,
-    I_MAX
-  } test = I_MAX;
-
-  static enum machine_mode mode_map[(int)CMP_MAX][(int)I_MAX] = {
+  static enum machine_mode mode_map[(int)CMP_MAX][(int)ITEST_MAX] = {
     {                          /* CMP_SI */
-      CC_EQmode,               /* eq  */
-      CC_EQmode,               /* ne  */
-      CCmode,                  /* gt  */
-      CCmode,                  /* ge  */
-      CCmode,                  /* lt  */
-      CCmode,                  /* le  */
-      CCmode,                  /* gtu */
-      CCmode,                  /* geu */
-      CCmode,                  /* ltu */
-      CCmode,                  /* leu */
+      SImode,                  /* eq  */
+      SImode,                  /* ne  */
+      SImode,                  /* gt  */
+      SImode,                  /* ge  */
+      SImode,                  /* lt  */
+      SImode,                  /* le  */
+      SImode,                  /* gtu */
+      SImode,                  /* geu */
+      SImode,                  /* ltu */
+      SImode,                  /* leu */
     },
     {                          /* CMP_SF */
       CC_FPmode,               /* eq  */
-      CC_FPmode,               /* ne  */
+      CC_REV_FPmode,           /* ne  */
       CC_FPmode,               /* gt  */
       CC_FPmode,               /* ge  */
       CC_FPmode,               /* lt  */
@@ -1486,7 +1721,7 @@ gen_conditional_branch (operands, test_code)
     },
     {                          /* CMP_DF */
       CC_FPmode,               /* eq  */
-      CC_FPmode,               /* ne  */
+      CC_REV_FPmode,           /* ne  */
       CC_FPmode,               /* gt  */
       CC_FPmode,               /* ge  */
       CC_FPmode,               /* lt  */
@@ -1499,33 +1734,22 @@ gen_conditional_branch (operands, test_code)
   };
 
   enum machine_mode mode;
-  enum cmp_type type = branch_type;
-  rtx cmp0 = branch_cmp[0];
-  rtx cmp1 = branch_cmp[1];
-  rtx label = gen_rtx (LABEL_REF, VOIDmode, operands[0]);
-
-  /* Make normal rtx_code into something we can index from an array */
-  switch (test_code)
+  enum cmp_type type     = branch_type;
+  rtx cmp0               = branch_cmp[0];
+  rtx cmp1               = branch_cmp[1];
+  rtx label1             = gen_rtx (LABEL_REF, VOIDmode, operands[0]);
+  rtx label2             = pc_rtx;
+  rtx reg                = (rtx)0;
+  int invert             = 0;
+  enum internal_test test = map_test_to_internal_test (test_code);
+
+  if (test == ITEST_MAX)
     {
-    case EQ:  test = I_EQ;  break;
-    case NE:  test = I_NE;  break;
-    case GT:  test = I_GT;  break;
-    case GE:  test = I_GE;  break;
-    case LT:  test = I_LT;  break;
-    case LE:  test = I_LE;  break;
-    case GTU: test = I_GTU; break;
-    case GEU: test = I_GEU; break;
-    case LTU: test = I_LTU; break;
-    case LEU: test = I_LEU; break;
-    }
-
-  if (test == I_MAX)
-    {
-      mode = CCmode;
+      mode = SImode;
       goto fail;
     }
 
-  /* Get the machine mode to use (CCmode, CC_EQmode, or CC_FPmode).  */
+  /* Get the machine mode to use (CCmode, CC_EQmode, CC_FPmode, or CC_REV_FPmode).  */
   mode = mode_map[(int)type][(int)test];
   if (mode == VOIDmode)
     goto fail;
@@ -1536,50 +1760,46 @@ gen_conditional_branch (operands, test_code)
       goto fail;
 
     case CMP_SI:
-      /* Change >, >=, <, <= tests against 0 to use CC_0mode, since we have
-        special instructions to do these tests directly. */
-
-      if (mode == CCmode && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
-       {
-         emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, cmp0));
-         mode = CC_0mode;
-       }
-
-      else if (mode == CCmode && GET_CODE (cmp0) == CONST_INT && INTVAL (cmp0) == 0)
+      reg = gen_int_relational (test_code, (rtx)0, cmp0, cmp1, &invert);
+      if (reg != (rtx)0)
        {
-         emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, cmp1));
-         test_code = reverse_condition (test_code);
-         mode = CC_0mode;
+         cmp0 = reg;
+         cmp1 = const0_rtx;
+         test_code = NE;
        }
 
-      else
-       {
-         /* force args to register for equality comparisons. */
-         if (mode == CC_EQmode && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
-           cmp1 = force_reg (SImode, cmp1);
+      /* Make sure not non-zero constant if ==/!= */
+      else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
+       cmp1 = force_reg (SImode, cmp1);
 
-         emit_insn (gen_rtx (SET, VOIDmode,
-                             cc0_rtx,
-                             gen_rtx (COMPARE, mode, cmp0, cmp1)));
-       }
       break;
 
     case CMP_DF:
-      emit_insn (gen_cmpdf_internal (cmp0, cmp1));
-      break;
-
     case CMP_SF:
-      emit_insn (gen_cmpsf_internal (cmp0, cmp1));
+      {
+       rtx reg = gen_rtx (REG, mode, FPSW_REGNUM);
+       emit_insn (gen_rtx (SET, VOIDmode, reg, gen_rtx (test_code, mode, cmp0, cmp1)));
+       cmp0 = reg;
+       cmp1 = const0_rtx;
+       test_code = NE;
+      }
       break;
     }
   
   /* Generate the jump */
+  if (invert)
+    {
+      label2 = label1;
+      label1 = pc_rtx;
+    }
+
   emit_jump_insn (gen_rtx (SET, VOIDmode,
                           pc_rtx,
                           gen_rtx (IF_THEN_ELSE, VOIDmode,
-                                   gen_rtx (test_code, mode, cc0_rtx, const0_rtx),
-                                   label,
-                                   pc_rtx)));
+                                   gen_rtx (test_code, mode, cmp0, cmp1),
+                                   label1,
+                                   label2)));
+
   return;
 
 fail:
@@ -2728,9 +2948,9 @@ override_options ()
   mips_char_to_class['f'] = ((TARGET_HARD_FLOAT) ? FP_REGS : NO_REGS);
   mips_char_to_class['h'] = HI_REG;
   mips_char_to_class['l'] = LO_REG;
-  mips_char_to_class['s'] = ST_REGS;
   mips_char_to_class['x'] = MD_REGS;
   mips_char_to_class['y'] = GR_REGS;
+  mips_char_to_class['z'] = ST_REGS;
 
   /* Set up array to map GCC register number to debug register number.
      Ignore the special purpose register numbers.  */
@@ -2762,22 +2982,25 @@ override_options ()
 
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
        {
-         register int temp = FALSE;
+         register int temp;
+
+         if (mode == CC_FPmode || mode == CC_REV_FPmode)
+           temp = (regno == FPSW_REGNUM);
 
-         if (GP_REG_P (regno))
+         else if (GP_REG_P (regno))
            temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD));
 
          else if (FP_REG_P (regno))
            temp = ((TARGET_FLOAT64 || ((regno & 1) == 0))
-                   && (TARGET_DEBUG_H_MODE
-                       || class == MODE_FLOAT
-                       || class == MODE_COMPLEX_FLOAT));
+                   && (class == MODE_FLOAT
+                       || class == MODE_COMPLEX_FLOAT
+                       || (TARGET_DEBUG_H_MODE && class == MODE_INT)));
 
          else if (MD_REG_P (regno))
            temp = (mode == SImode || (regno == MD_REG_FIRST && mode == DImode));
 
-         else if (ST_REG_P (regno))
-           temp = ((mode == SImode) || (class == MODE_CC));
+         else
+           temp = FALSE;
 
          mips_hard_regno_mode_ok[(int)mode][regno] = temp;
        }
index 866ce6f5b91f0c3ac3aa1e5a477d0fb23a816704..240d64aeba33ccc28a6c3f9d7f7b04c859668eb9 100644 (file)
@@ -49,7 +49,8 @@ enum cmp_type {
 enum delay_type {
   DELAY_NONE,                          /* no delay slot */
   DELAY_LOAD,                          /* load from memory delay */
-  DELAY_HILO                           /* move from/to hi/lo registers */
+  DELAY_HILO,                          /* move from/to hi/lo registers */
+  DELAY_FCMP                           /* delay after doing c.<xx>.{d,s} */
 };
 
 /* Which processor to schedule for.  Since there is no difference between
@@ -120,12 +121,14 @@ extern unsigned long      compute_frame_size ();
 extern void            expand_block_move ();
 extern int             equality_op ();
 extern int             fcmp_op ();
+extern int             fpsw_register_operand ();
 extern struct rtx_def *        function_arg ();
 extern void            function_arg_advance ();
 extern int             function_arg_partial_nregs ();
 extern void            function_epilogue ();
 extern void            function_prologue ();
 extern void            gen_conditional_branch ();
+extern struct rtx_def * gen_int_relational ();
 extern void            init_cumulative_args ();
 extern int             large_int ();
 extern int             md_register_operand ();
@@ -145,6 +148,7 @@ extern void         mips_output_filename ();
 extern void            mips_output_lineno ();
 extern char           *output_block_move ();
 extern void            override_options ();
+extern int             pc_or_label_operand ();
 extern void            print_operand_address ();
 extern void            print_operand ();
 extern void            print_options ();
@@ -416,7 +420,7 @@ while (0)
 \f
 /* Print subsidiary information on the compiler version in use.  */
 
-#define MIPS_VERSION "[AL 1.1, MM 15]"
+#define MIPS_VERSION "[AL 1.1, MM 16]"
 
 #ifndef MACHINE_TYPE
 #define MACHINE_TYPE "BSD Mips"
@@ -646,7 +650,7 @@ do {                                                        \
 #define MASK_DEBUG     0x40000000      /* Eliminate version # in .s file */
 #define MASK_DEBUG_A   0x20000000      /* don't allow <label>($reg) addrs */
 #define MASK_DEBUG_B   0x10000000      /* GO_IF_LEGITIMATE_ADDRESS debug */
-#define MASK_DEBUG_C   0x08000000      /* suppress normal divmod patterns */
+#define MASK_DEBUG_C   0x08000000      /* allow new seq, sne, etc. patterns */
 #define MASK_DEBUG_D   0x04000000      /* don't do define_split's */
 #define MASK_DEBUG_E   0x02000000      /* function_arg debug */
 #define MASK_DEBUG_F   0x01000000      /* don't try to suppress load nop's */
@@ -1280,8 +1284,8 @@ extern enum reg_class mips_regno_to_class[];
    'f' Floating point registers
    'h' Hi register
    'l' Lo register
-   's' Status registers
-   'x' Multiply/divide registers  */
+   'x' Multiply/divide registers
+   'z' FP Status register */
 
 extern enum reg_class mips_char_to_class[];
 
@@ -2547,47 +2551,34 @@ do                                                                      \
   }                                                                    \
 while (0)
 
-/* A list of names to be used for additional modes for condition
-   code values in registers (*note Jump Patterns::.).  These names
-   are added to `enum machine_mode' and all have class `MODE_CC'. 
-   By convention, they should start with `CC' and end with `mode'.
+/* A list of names to be used for additional modes for condition code
+   values in registers.  These names are added to `enum machine_mode'
+   and all have class `MODE_CC'.  By convention, they should start
+   with `CC' and end with `mode'.
 
    You should only define this macro if your machine does not use
    `cc0' and only if additional modes are required.
 
-   On the MIPS, we use CC_FPmode for all floating point, CC_EQmode for
-   integer equality/inequality comparisons, CC_0mode for comparisons
-   against 0, and CCmode for other integer comparisons.  */
+   On the MIPS, we use CC_FPmode for all floating point except for not
+   equal, CC_REV_FPmode for not equal (to reverse the sense of the
+   jump), CC_EQmode for integer equality/inequality comparisons,
+   CC_0mode for comparisons against 0, and CCmode for other integer
+   comparisons. */
 
-#define EXTRA_CC_MODES CC_EQmode, CC_FPmode, CC_0mode
+#define EXTRA_CC_MODES CC_EQmode, CC_FPmode, CC_0mode, CC_REV_FPmode
 
 /* A list of C strings giving the names for the modes listed in
-   `EXTRA_CC_MODES'.  For example, the Sparc defines this macro and
-   `EXTRA_CC_MODES' as
+   `EXTRA_CC_MODES'.  */
 
-          #define EXTRA_CC_MODES CC_NOOVmode, CCFPmode
-          #define EXTRA_CC_NAMES "CC_NOOV", "CCFP"
-
-   This macro is not required if `EXTRA_CC_MODES' is not defined.  */
-
-#define EXTRA_CC_NAMES "CC_EQ", "CC_FP", "CC_0"
+#define EXTRA_CC_NAMES "CC_EQ", "CC_FP", "CC_0", "CC_REV_FP"
 
 /* Returns a mode from class `MODE_CC' to be used when comparison
-   operation code OP is applied to rtx X.  For example, on the
-   Sparc, `SELECT_CC_MODE' is defined as (see *note Jump
-   Patterns::. for a description of the reason for this definition)
-
-          #define SELECT_CC_MODE(OP,X)                                 \
-            (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode    \
-             : (GET_CODE (X) == PLUS || GET_CODE (X) == MINUS          \
-                || GET_CODE (X) == NEG)                                        \
-             ? CC_NOOVmode : CCmode)
-
-   This macro is not required if `EXTRA_CC_MODES' is not defined.  */
+   operation code OP is applied to rtx X.  */
 
-#define SELECT_CC_MODE (OP, X)                                         \
-  (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CC_FPmode :           \
-   (OP == EQ || OP == NE) ? CC_EQmode : CCmode)
+#define SELECT_CC_MODE(OP, X)                                          \
+  (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT                         \
+       ? SImode                                                        \
+       : ((OP == NE) ? CC_REV_FPmode : CC_FPmode))
 
 \f
 /* Control the assembler format that we output.  */
index 2a188ceb9d6438e071ff7cba851b0c8e5754f15b..f4b7e05beb5f00079863119fe4f63c36adacdcb9 100644 (file)
@@ -58,7 +58,7 @@
   (const_string "unknown"))
 
 ;; Main data type used by the insn
-(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF" (const_string "unknown"))
+(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW" (const_string "unknown"))
 
 ;; # instructions (4 bytes each)
 (define_attr "length" "" (const_int 1))
 
 (define_function_unit "memory"  1 0 (eq_attr "type" "store") 1 0)
 
+(define_function_unit "fp_comp"  1 0 (eq_attr "type" "fcmp")    2 0)
+
 (define_function_unit "transfer" 1 0 (eq_attr "type" "xfer")    2 0)
 (define_function_unit "transfer" 1 0 (eq_attr "type" "hilo")    3 0)
 
                 (subreg:SI (match_dup 2) 0)))
 
    (set (match_dup 3)
-       (ltu:CC (subreg:SI (match_dup 0) 0)
+       (ltu:SI (subreg:SI (match_dup 0) 0)
                (subreg:SI (match_dup 2) 0)))
 
    (set (subreg:SI (match_dup 0) 1)
                 (subreg:SI (match_dup 2) 1)))
 
    (set (match_dup 3)
-       (ltu:CC (subreg:SI (match_dup 0) 1)
+       (ltu:SI (subreg:SI (match_dup 0) 1)
                (subreg:SI (match_dup 2) 1)))
 
    (set (subreg:SI (match_dup 0) 0)
                 (match_dup 2)))
 
    (set (match_dup 3)
-       (ltu:CC (subreg:SI (match_dup 0) 0)
+       (ltu:SI (subreg:SI (match_dup 0) 0)
                (match_dup 2)))
 
    (set (subreg:SI (match_dup 0) 1)
                 (match_dup 2)))
 
    (set (match_dup 3)
-       (ltu:CC (subreg:SI (match_dup 0) 1)
+       (ltu:SI (subreg:SI (match_dup 0) 1)
                (match_dup 2)))
 
    (set (subreg:SI (match_dup 0) 0)
    && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
 
   [(set (match_dup 3)
-       (ltu:CC (subreg:SI (match_dup 1) 0)
+       (ltu:SI (subreg:SI (match_dup 1) 0)
                (subreg:SI (match_dup 2) 0)))
 
    (set (subreg:SI (match_dup 0) 0)
    && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
 
   [(set (match_dup 3)
-       (ltu:CC (subreg:SI (match_dup 1) 1)
+       (ltu:SI (subreg:SI (match_dup 1) 1)
                (subreg:SI (match_dup 2) 1)))
 
    (set (subreg:SI (match_dup 0) 1)
    && INTVAL (operands[2]) > 0"
 
   [(set (match_dup 3)
-       (ltu:CC (subreg:SI (match_dup 1) 0)
+       (ltu:SI (subreg:SI (match_dup 1) 0)
                (match_dup 2)))
 
    (set (subreg:SI (match_dup 0) 0)
    && INTVAL (operands[2]) > 0"
 
   [(set (match_dup 3)
-       (ltu:CC (subreg:SI (match_dup 1) 1)
+       (ltu:SI (subreg:SI (match_dup 1) 1)
                (match_dup 2)))
 
    (set (subreg:SI (match_dup 0) 1)
                (match_dup 2)))
    (clobber (reg:SI 64))
    (clobber (reg:SI 65))]
-  "optimize && !TARGET_DEBUG_C_MODE"
+  "optimize"
   "*
 {
   if (find_reg_note (insn, REG_UNUSED, operands[3]))
                 (match_dup 2)))
    (clobber (reg:SI 64))
    (clobber (reg:SI 65))]
-  "optimize && !TARGET_DEBUG_C_MODE"
+  "optimize"
   "*
 {
   if (find_reg_note (insn, REG_UNUSED, operands[3]))
                (match_operand:SI 2 "register_operand" "d")))
    (clobber (reg:SI 64))
    (clobber (reg:SI 65))]
-  "!optimize || TARGET_DEBUG_C_MODE"
+  "!optimize"
   "div\\t%0,%1,%2"
   [(set_attr "type"    "idiv")
    (set_attr "mode"    "SI")
                (match_operand:SI 2 "register_operand" "d")))
    (clobber (reg:SI 64))
    (clobber (reg:SI 65))]
-  "!optimize || TARGET_DEBUG_C_MODE"
+  "!optimize"
   "rem\\t%0,%1,%2"
   [(set_attr "type"    "idiv")
    (set_attr "mode"    "SI")
                 (match_operand:SI 2 "register_operand" "d")))
    (clobber (reg:SI 64))
    (clobber (reg:SI 65))]
-  "!optimize || TARGET_DEBUG_C_MODE"
+  "!optimize"
   "divu\\t%0,%1,%2"
   [(set_attr "type"    "idiv")
    (set_attr "mode"    "SI")
                 (match_operand:SI 2 "register_operand" "d")))
    (clobber (reg:SI 64))
    (clobber (reg:SI 65))]
-  "!optimize || TARGET_DEBUG_C_MODE"
+  "!optimize"
   "remu\\t%0,%1,%2"
   [(set_attr "type"    "idiv")
    (set_attr "mode"    "SI")
@@ -2629,14 +2631,9 @@ move\\t%0,%z4\\n\\
 ;;     done, so that we can constrain things appropriately.  There
 ;;     are assumptions in the rest of GCC that break if we fold the
 ;;     operands into the branchs for integer operations, and use cc0
-;;     for floating point.
-;;
-;;  3) The compare define_insns then once again set branch_cmp and
-;;     branch_type, and the branch define_insns use them.
-;;
-;;  4) If a set condition code is done instead of a branch, then the
-;;     operands are folded into the RTL, and a separate set of cc0 is
-;;     not done.  This allows slt's to be put into delay slots.
+;;     for floating point, so we use the fp status register instead.
+;;     If needed, an appropriate temporary is created to hold the
+;;     of the integer compare.
 
 (define_expand "cmpsi"
   [(set (cc0)
@@ -2669,53 +2666,6 @@ move\\t%0,%z4\\n\\
     }
 }")
 
-(define_insn "cmpsi_eqne"
-  [(set (cc0)
-       (compare:CC_EQ (match_operand:SI 0 "register_operand" "dJ")
-                      (match_operand:SI 1 "reg_or_0_operand" "dJ")))]
-  ""
-  "*
-{
-  branch_cmp[0] = operands[0];
-  branch_cmp[1] = operands[1];
-  branch_type = CMP_SI;
-  return \"\";
-}"
-  [(set_attr "type"    "icmp")
-   (set_attr "mode"    "none")
-   (set_attr "length"  "0")])
-
-(define_insn "cmpsi_zero"
-  [(set (cc0)
-       (match_operand:SI 0 "reg_or_0_operand" "dJ"))]
-  ""
-  "*
-{
-  branch_cmp[0] = operands[0];
-  branch_cmp[1] = const0_rtx;
-  branch_type = CMP_SI;
-  return \"\";
-}"
-  [(set_attr "type"    "icmp")
-   (set_attr "mode"    "none")
-   (set_attr "length"  "0")])
-
-(define_insn "cmpsi_relational"
-  [(set (cc0)
-       (compare:CC (match_operand:SI 0 "register_operand" "dJ")
-                   (match_operand:SI 1 "arith_operand" "dI")))]
-  ""
-  "*
-{
-  branch_cmp[0] = operands[0];
-  branch_cmp[1] = operands[1];
-  branch_type = CMP_SI;
-  return \"\";
-}"
-  [(set_attr "type"    "icmp")
-   (set_attr "mode"    "none")
-   (set_attr "length"  "0")])
-
 (define_expand "cmpdf"
   [(set (cc0)
        (compare:CC_FP (match_operand:DF 0 "register_operand" "")
@@ -2732,23 +2682,6 @@ move\\t%0,%z4\\n\\
     }
 }")
 
-(define_insn "cmpdf_internal"
-  [(set (cc0)
-       (compare:CC_FP (match_operand:DF 0 "register_operand" "f")
-                      (match_operand:DF 1 "register_operand" "f")))]
-  "TARGET_HARD_FLOAT"
-  "*
-{
-  branch_cmp[0] = operands[0];
-  branch_cmp[1] = operands[1];
-  branch_type = CMP_DF;
-  return \"\";
-}"
-  [(set_attr "type"    "fcmp")
-   (set_attr "mode"    "none")
-   (set_attr "length"  "0")])
-
-
 (define_expand "cmpsf"
   [(set (cc0)
        (compare:CC_FP (match_operand:SF 0 "register_operand" "")
@@ -2765,22 +2698,6 @@ move\\t%0,%z4\\n\\
     }
 }")
 
-(define_insn "cmpsf_internal"
-  [(set (cc0)
-       (compare:CC_FP (match_operand:SF 0 "register_operand" "f")
-                      (match_operand:SF 1 "register_operand" "f")))]
-  "TARGET_HARD_FLOAT"
-  "*
-{
-  branch_cmp[0] = operands[0];
-  branch_cmp[1] = operands[1];
-  branch_type = CMP_SF;
-  return \"\";
-}"
-  [(set_attr "type"    "fcmp")
-   (set_attr "mode"    "none")
-   (set_attr "length"  "0")])
-
 \f
 ;;
 ;;  ....................
@@ -2789,224 +2706,163 @@ move\\t%0,%z4\\n\\
 ;;
 ;;  ....................
 
-;; We really can't note that integer branches clobber $at, and FP
-;; branches clobber $fcr31 because if we use a parallel operation, a
-;; normal insn is used to hold the value instead of jump_insn.  See
-;; above for cmpxx saving the operands in branch_cmp and branch_type.
-
-(define_insn "branch_fp_true"
+(define_insn "branch_fp_ne"
   [(set (pc)
-       (if_then_else (match_operator:CC_FP 0 "fcmp_op" [(cc0) (const_int 0)])
-                     (label_ref (match_operand 1 "" ""))
-                     (pc)))]
+       (if_then_else (ne:CC_FP (reg:CC_FP 66)
+                               (const_int 0))
+                     (match_operand 0 "pc_or_label_operand" "")
+                     (match_operand 1 "pc_or_label_operand" "")))]
   ""
   "*
 {
-  operands[2] = branch_cmp[0];
-  operands[3] = branch_cmp[1];
-
   mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
-  if (branch_type == CMP_DF)
-    {
-      switch (GET_CODE (operands[0]))
-       {
-       case EQ: return \"c.eq.d\\t%2,%3%#\;%*bc1t%?\\t%l1\";
-       case NE: return \"c.eq.d\\t%2,%3%#\;%*bc1f%?\\t%l1\";
-       case LT: return \"c.lt.d\\t%2,%3%#\;%*bc1t%?\\t%l1\";
-       case LE: return \"c.le.d\\t%2,%3%#\;%*bc1t%?\\t%l1\";
-       case GT: return \"c.lt.d\\t%3,%2%#\;%*bc1t%?\\t%l1\";
-       case GE: return \"c.le.d\\t%3,%2%#\;%*bc1t%?\\t%l1\";
-       }
-    }
-
-  else if (branch_type == CMP_SF)
-    {
-      switch (GET_CODE (operands[0]))
-       {
-       case EQ: return \"c.eq.s\\t%2,%3%#\;%*bc1t%?\\t%l1\";
-       case NE: return \"c.eq.s\\t%2,%3%#\;%*bc1f%?\\t%l1\";
-       case LT: return \"c.lt.s\\t%2,%3%#\;%*bc1t%?\\t%l1\";
-       case LE: return \"c.le.s\\t%2,%3%#\;%*bc1t%?\\t%l1\";
-       case GT: return \"c.lt.s\\t%3,%2%#\;%*bc1t%?\\t%l1\";
-       case GE: return \"c.le.s\\t%3,%2%#\;%*bc1t%?\\t%l1\";
-       }
-    }
-
-  abort_with_insn (insn, \"Bad floating compare/branch\");
-  return (char *)0;
+  return (operands[0] != pc_rtx) ? \"%*bc1t%?\\t%0\" : \"%*bc1f%?\\t%1\";
 }"
   [(set_attr "type"    "branch")
    (set_attr "mode"    "none")
-   (set_attr "length"  "3")])
+   (set_attr "length"  "1")])
 
-(define_insn "branch_fp_false"
+(define_insn "branch_fp_ne_rev"
   [(set (pc)
-       (if_then_else (match_operator:CC_FP 0 "fcmp_op" [(cc0) (const_int 0)])
-                     (pc)
-                     (label_ref (match_operand 1 "" ""))))]
+       (if_then_else (ne:CC_REV_FP (reg:CC_REV_FP 66)
+                                   (const_int 0))
+                     (match_operand 0 "pc_or_label_operand" "")
+                     (match_operand 1 "pc_or_label_operand" "")))]
   ""
   "*
 {
-  operands[2] = branch_cmp[0];
-  operands[3] = branch_cmp[1];
-
   mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
-  if (branch_type == CMP_DF)
-    {
-      switch (GET_CODE (operands[0]))
-       {
-       case EQ: return \"c.eq.d\\t%2,%3%#\;%*bc1f%?\\t%l1\";
-       case NE: return \"c.eq.d\\t%2,%3%#\;%*bc1t%?\\t%l1\";
-       case LT: return \"c.lt.d\\t%2,%3%#\;%*bc1f%?\\t%l1\";
-       case LE: return \"c.le.d\\t%2,%3%#\;%*bc1f%?\\t%l1\";
-       case GT: return \"c.lt.d\\t%3,%2%#\;%*bc1f%?\\t%l1\";
-       case GE: return \"c.le.d\\t%3,%2%#\;%*bc1f%?\\t%l1\";
-       }
-    }
-
-  else if (branch_type == CMP_SF)
-    {
-      switch (GET_CODE (operands[0]))
-       {
-       case EQ: return \"c.eq.s\\t%2,%3%#\;%*bc1f%?\\t%l1\";
-       case NE: return \"c.eq.s\\t%2,%3%#\;%*bc1t%?\\t%l1\";
-       case LT: return \"c.lt.s\\t%2,%3%#\;%*bc1f%?\\t%l1\";
-       case LE: return \"c.le.s\\t%2,%3%#\;%*bc1f%?\\t%l1\";
-       case GT: return \"c.lt.s\\t%3,%2%#\;%*bc1f%?\\t%l1\";
-       case GE: return \"c.le.s\\t%3,%2%#\;%*bc1f%?\\t%l1\";
-       }
-    }
-
-  abort_with_insn (insn, \"Bad floating compare/branch\");
-  return (char *)0;
+  return (operands[0] != pc_rtx) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\t%1\";
 }"
   [(set_attr "type"    "branch")
    (set_attr "mode"    "none")
-   (set_attr "length"  "3")])
-
+   (set_attr "length"  "1")])
 
-(define_insn "branch_eqne_true"
+(define_insn "branch_fp_eq"
   [(set (pc)
-       (if_then_else (match_operator:CC_EQ 0 "equality_op" [(cc0) (const_int 0)])
-                     (label_ref (match_operand 1 "" ""))
-                     (pc)))]
+       (if_then_else (eq:CC_FP (reg:CC_FP 66)
+                               (const_int 0))
+                     (match_operand 0 "pc_or_label_operand" "")
+                     (match_operand 1 "pc_or_label_operand" "")))]
   ""
   "*
 {
   mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
-  operands[2] = branch_cmp[0];
-  operands[3] = branch_cmp[1];
-  return \"%*b%C0%?\\t%z2,%z3,%1\";
+  return (operands[0] != pc_rtx) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\t%1\";
 }"
   [(set_attr "type"    "branch")
    (set_attr "mode"    "none")
    (set_attr "length"  "1")])
 
-(define_insn "branch_eqne_false"
+(define_insn "branch_fp_eq_rev"
   [(set (pc)
-       (if_then_else (match_operator:CC_EQ 0 "equality_op" [(cc0) (const_int 0)])
-                     (pc)
-                     (label_ref (match_operand 1 "" ""))))]
+       (if_then_else (eq:CC_REV_FP (reg:CC_REV_FP 66)
+                                   (const_int 0))
+                     (match_operand 0 "pc_or_label_operand" "")
+                     (match_operand 1 "pc_or_label_operand" "")))]
   ""
   "*
 {
   mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
-  operands[2] = branch_cmp[0];
-  operands[3] = branch_cmp[1];
-  return \"%*b%N0%?\\t%z2,%z3,%1\";
+  return (operands[0] != pc_rtx) ? \"%*bc1t%?\\t%0\" : \"%*bc1f%?\\t%1\";
 }"
   [(set_attr "type"    "branch")
    (set_attr "mode"    "none")
    (set_attr "length"  "1")])
 
-(define_insn "branch_zero_true"
+
+(define_insn "branch_zero"
   [(set (pc)
-       (if_then_else (match_operator:CC_0 0 "cmp_op" [(cc0) (const_int 0)])
-                     (label_ref (match_operand 1 "" ""))
-                     (pc)))]
+       (if_then_else (match_operator:SI 0 "cmp_op"
+                                        [(match_operand:SI 1 "arith32_operand" "rn")
+                                         (const_int 0)])
+       (match_operand 2 "pc_or_label_operand" "")
+       (match_operand 3 "pc_or_label_operand" "")))]
   ""
   "*
 {
   mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
-  operands[2] = branch_cmp[0];
 
-  switch (GET_CODE (operands[0]))
+  /* Handle places where CSE has folded a constant into the register operand.  */
+  if (GET_CODE (operands[1]) == CONST_INT)
     {
-    case EQ:  return \"%*beq%?\\t%z2,%.,%1\";
-    case NE:  return \"%*bne%?\\t%z2,%.,%1\";
-    case GTU: return \"%*bne%?\\t%z2,%.,%1\";
-    case LEU: return \"%*beq%?\\t%z2,%.,%1\";
-    case GEU: return \"%*j\\t%1\";
-    case LTU: return \"#%*bltuz\\t%z2,%1\";
+      int value = INTVAL (operands[1]);
+      int truth = 0;
+
+      switch (GET_CODE (operands[0]))
+       {
+       default:  abort ();
+       case EQ:  truth = (value == 0);                 break;
+       case NE:  truth = (value != 0);                 break;
+       case GT:  truth = (value >  0);                 break;
+       case GE:  truth = (value >= 0);                 break;
+       case LT:  truth = (value <  0);                 break;
+       case LE:  truth = (value <= 0);                 break;
+       case GTU: truth = (((unsigned)value) >  0);     break;
+       case GEU: truth = 1;                            break;
+       case LTU: truth = 0;                            break;
+       case LEU: truth = (((unsigned)value) <= 0);     break;
+       }
+
+      if (operands[2] != pc_rtx)
+       return (truth) ? \"%*j\\t%2\" : \"#bne\\t%z1,%.,%2\";
+      else
+       return (truth) ? \"#bne\\t%z1,%.,%3\" : \"%*j\\t%3\";
     }
 
-  return \"%*b%C0z%?\\t%z2,%1\";
-}"
-  [(set_attr "type"    "branch")
-   (set_attr "mode"    "none")
-   (set_attr "length"  "1")])
+  if (operands[2] != pc_rtx)
+    {                          /* normal jump */
+      switch (GET_CODE (operands[0]))
+       {
+       case EQ:  return \"%*beq%?\\t%z1,%.,%2\";
+       case NE:  return \"%*bne%?\\t%z1,%.,%2\";
+       case GTU: return \"%*bne%?\\t%z1,%.,%2\";
+       case LEU: return \"%*beq%?\\t%z1,%.,%2\";
+       case GEU: return \"%*j\\t%2\";
+       case LTU: return \"#%*bltuz\\t%z1,%2\";
+       }
 
-(define_insn "branch_zero_false"
-  [(set (pc)
-       (if_then_else (match_operator:CC_0 0 "cmp_op" [(cc0) (const_int 0)])
-                     (pc)
-                     (label_ref (match_operand 1 "" ""))))]
-  ""
-  "*
-{
-  mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
-  operands[2] = branch_cmp[0];
-  switch (GET_CODE (operands[0]))
-    {
-    case EQ:  return \"%*bne%?\\t%z2,%.,%1\";
-    case NE:  return \"%*beq%?\\t%z2,%.,%1\";
-    case GTU: return \"%*beq%?\\t%z2,%.,%1\";
-    case LEU: return \"%*bne\\t%z2,%.,%1\";
-    case GEU: return \"#%*bgeuz\\t%z2,%1\";
-    case LTU: return \"%*j\\t%1\";
+      return \"%*b%C0z%?\\t%z1,%2\";
     }
+  else
+    {                          /* inverted jump */
+      switch (GET_CODE (operands[0]))
+       {
+       case EQ:  return \"%*bne%?\\t%z1,%.,%3\";
+       case NE:  return \"%*beq%?\\t%z1,%.,%3\";
+       case GTU: return \"%*beq%?\\t%z1,%.,%3\";
+       case LEU: return \"%*bne%?\\t%z1,%.,%3\";
+       case GEU: return \"#%*bgeuz\\t%z1,%3\";
+       case LTU: return \"%*j\\t%3\";
+       }
 
-  return \"%*b%N0z%?\\t%z2,%1\";
+      return \"%*b%N0z%?\\t%z1,%3\";
+    }
 }"
   [(set_attr "type"    "branch")
    (set_attr "mode"    "none")
    (set_attr "length"  "1")])
 
-(define_insn "branch_relop_true"
-  [(set (pc)
-       (if_then_else (match_operator:CC 0 "cmp2_op" [(cc0) (const_int 0)])
-                     (label_ref (match_operand 1 "" ""))
-                     (pc)))]
-  ""
-  "*
-{
-  mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
-  operands[2] = branch_cmp[0];
-  operands[3] = branch_cmp[1];
-
-  return \"%&b%C0%?\\t%z2,%z3,%1%!\";
-}"
-  [(set_attr "type"    "branch")
-   (set_attr "mode"    "none")
-   (set_attr "length"  "2")])
 
-(define_insn "branch_relop_false"
+(define_insn "branch_equality"
   [(set (pc)
-       (if_then_else (match_operator:CC 0 "cmp2_op" [(cc0) (const_int 0)])
-                     (pc)
-                     (label_ref (match_operand 1 "" ""))))]
+       (if_then_else (match_operator:SI 0 "equality_op"
+                                        [(match_operand:SI 1 "register_operand" "d")
+                                         (match_operand:SI 2 "register_operand" "d")])
+       (match_operand 3 "pc_or_label_operand" "")
+       (match_operand 4 "pc_or_label_operand" "")))]
   ""
   "*
 {
   mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
-  operands[2] = branch_cmp[0];
-  operands[3] = branch_cmp[1];
-
-  return \"%&b%N0%?\\t%z2,%z3,%1%!\";
+  return (operands[3] != pc_rtx)
+       ? \"%*b%C0%?\\t%z1,%z2,%3\"
+       : \"%*b%N0%?\\t%z1,%z2,%4\";
 }"
   [(set_attr "type"    "branch")
    (set_attr "mode"    "none")
-   (set_attr "length"  "2")])
+   (set_attr "length"  "1")])
+
 
 (define_expand "beq"
   [(set (pc)
@@ -3179,8 +3035,8 @@ move\\t%0,%z4\\n\\
 
 (define_expand "seq"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (eq:CC_EQ (match_dup 1)
-                 (match_dup 2)))]
+       (eq:SI (match_dup 1)
+              (match_dup 2)))]
   ""
   "
 {
@@ -3193,43 +3049,59 @@ move\\t%0,%z4\\n\\
   operands[1] = branch_cmp[0];
   operands[2] = branch_cmp[1];
 
+  if (TARGET_DEBUG_C_MODE)
+    {
+      gen_int_relational (EQ, operands[0], operands[1], operands[2], (int *)0);
+      DONE;
+    }
+
   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
     operands[2] = force_reg (SImode, operands[2]);
 
   /* fall through and generate default code */
 }")
 
-(define_insn "seq_si"
-  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
-       (eq:CC_EQ (match_operand:SI 1 "register_operand" "%d,d,d")
-                 (match_operand:SI 2 "uns_arith_operand" "J,d,K")))]
+
+(define_insn "seq_si_zero"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (eq:SI (match_operand:SI 1 "register_operand" "d")
+              (const_int 0)))]
   ""
+  "sltu\\t%0,%1,1"
+ [(set_attr "type"     "arith")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "1")])
+
+(define_insn "seq_si"
+  [(set (match_operand:SI 0 "register_operand" "=d,d")
+       (eq:SI (match_operand:SI 1 "register_operand" "%d,d")
+              (match_operand:SI 2 "uns_arith_operand" "d,K")))]
+  "!TARGET_DEBUG_C_MODE"
   "@
-   sltu\\t%0,%1,1
    xor\\t%0,%1,%2\;sltu\\t%0,%0,1
-   xori\\t%0,%1,%x2\;sltu\\t%0,%0,1"
- [(set_attr "type"     "arith,arith,arith")
-   (set_attr "mode"    "SI,SI,SI")
-   (set_attr "length"  "1,2,2")])
+   xori\\t%0,%1,%2\;sltu\\t%0,%0,1"
+ [(set_attr "type"     "arith,arith")
+   (set_attr "mode"    "SI,SI")
+   (set_attr "length"  "2,2")])
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
-       (eq:CC_EQ (match_operand:SI 1 "register_operand" "")
-                 (match_operand:SI 2 "uns_arith_operand" "")))]
-  "!TARGET_DEBUG_D_MODE
+       (eq:SI (match_operand:SI 1 "register_operand" "")
+              (match_operand:SI 2 "uns_arith_operand" "")))]
+  "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE
     && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)"
   [(set (match_dup 0)
        (xor:SI (match_dup 1)
                (match_dup 2)))
    (set (match_dup 0)
-       (ltu:CC (match_dup 0)
+       (ltu:SI (match_dup 0)
                (const_int 1)))]
   "")
 
 (define_expand "sne"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (ne:CC_EQ (match_dup 1)
-                 (match_dup 2)))]
+       (ne:SI (match_dup 1)
+              (match_dup 2)))]
   ""
   "
 {
@@ -3242,48 +3114,57 @@ move\\t%0,%z4\\n\\
   operands[1] = branch_cmp[0];
   operands[2] = branch_cmp[1];
 
+  if (TARGET_DEBUG_C_MODE)
+    {
+      gen_int_relational (NE, operands[0], operands[1], operands[2], (int *)0);
+      DONE;
+    }
+
   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
     operands[2] = force_reg (SImode, operands[2]);
 
   /* fall through and generate default code */
 }")
 
-(define_insn "sne_si"
-  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
-       (ne:CC_EQ (match_operand:SI 1 "register_operand" "%d,d,d")
-                 (match_operand:SI 2 "uns_arith_operand" "J,d,K")))]
+(define_insn "sne_si_zero"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (ne:SI (match_operand:SI 1 "register_operand" "d")
+              (const_int 0)))]
   ""
-  "*
-{
-  if (GET_CODE (operands[2]) != CONST_INT)
-    return \"xor\\t%0,%1,%2\;sltu\\t%0,%.,%0\";
-
-  if (INTVAL (operands[2]) == 0)
-    return \"sltu\\t%0,%.,%1\";
+  "sltu\\t%0,%.,%1"
+ [(set_attr "type"     "arith")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "1")])
 
-  return \"xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0\";
-}"
- [(set_attr "type"     "arith,arith,arith")
-   (set_attr "mode"    "SI,SI,SI")
-   (set_attr "length"  "1,2,2")])
+(define_insn "sne_si"
+  [(set (match_operand:SI 0 "register_operand" "=d,d")
+       (ne:SI (match_operand:SI 1 "register_operand" "%d,d")
+              (match_operand:SI 2 "uns_arith_operand" "d,K")))]
+  "!TARGET_DEBUG_C_MODE"
+  "@
+    xor\\t%0,%1,%2\;sltu\\t%0,%.,%0
+    xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0"
+ [(set_attr "type"     "arith,arith")
+   (set_attr "mode"    "SI,SI")
+   (set_attr "length"  "2,2")])
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
-       (ne:CC_EQ (match_operand:SI 1 "register_operand" "")
-                 (match_operand:SI 2 "uns_arith_operand" "")))]
-  "!TARGET_DEBUG_D_MODE
+       (ne:SI (match_operand:SI 1 "register_operand" "")
+              (match_operand:SI 2 "uns_arith_operand" "")))]
+  "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE
     && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)"
   [(set (match_dup 0)
        (xor:SI (match_dup 1)
                (match_dup 2)))
    (set (match_dup 0)
-       (gtu:CC (match_dup 0)
+       (gtu:SI (match_dup 0)
                (const_int 0)))]
   "")
 
 (define_expand "sgt"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (gt:CC (match_dup 1)
+       (gt:SI (match_dup 1)
               (match_dup 2)))]
   ""
   "
@@ -3297,6 +3178,12 @@ move\\t%0,%z4\\n\\
   operands[1] = branch_cmp[0];
   operands[2] = branch_cmp[1];
 
+  if (TARGET_DEBUG_C_MODE)
+    {
+      gen_int_relational (GT, operands[0], operands[1], operands[2], (int *)0);
+      DONE;
+    }
+
   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
     operands[2] = force_reg (SImode, operands[2]);
 
@@ -3305,7 +3192,7 @@ move\\t%0,%z4\\n\\
 
 (define_insn "sgt_si"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (gt:CC (match_operand:SI 1 "register_operand" "d")
+       (gt:SI (match_operand:SI 1 "register_operand" "d")
               (match_operand:SI 2 "reg_or_0_operand" "dJ")))]
   ""
   "slt\\t%0,%z2,%1"
@@ -3315,7 +3202,7 @@ move\\t%0,%z4\\n\\
 
 (define_expand "sge"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (ge:CC (match_dup 1)
+       (ge:SI (match_dup 1)
               (match_dup 2)))]
   ""
   "
@@ -3327,14 +3214,20 @@ move\\t%0,%z4\\n\\
   operands[1] = branch_cmp[0];
   operands[2] = branch_cmp[1];
 
+  if (TARGET_DEBUG_C_MODE)
+    {
+      gen_int_relational (GE, operands[0], operands[1], operands[2], (int *)0);
+      DONE;
+    }
+
   /* fall through and generate default code */
 }")
 
 (define_insn "sge_si"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (ge:CC (match_operand:SI 1 "register_operand" "d")
+       (ge:SI (match_operand:SI 1 "register_operand" "d")
               (match_operand:SI 2 "arith_operand" "dI")))]
-  ""
+  "!TARGET_DEBUG_C_MODE"
   "slt\\t%0,%1,%2\;xori\\t%0,%0,0x0001"
  [(set_attr "type"     "arith")
    (set_attr "mode"    "SI")
@@ -3342,11 +3235,11 @@ move\\t%0,%z4\\n\\
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
-       (ge:CC (match_operand:SI 1 "register_operand" "")
+       (ge:SI (match_operand:SI 1 "register_operand" "")
               (match_operand:SI 2 "arith_operand" "")))]
-  "!TARGET_DEBUG_D_MODE"
+  "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
   [(set (match_dup 0)
-       (lt:CC (match_dup 1)
+       (lt:SI (match_dup 1)
               (match_dup 2)))
    (set (match_dup 0)
        (xor:SI (match_dup 0)
@@ -3355,7 +3248,7 @@ move\\t%0,%z4\\n\\
 
 (define_expand "slt"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (lt:CC (match_dup 1)
+       (lt:SI (match_dup 1)
               (match_dup 2)))]
   ""
   "
@@ -3367,12 +3260,18 @@ move\\t%0,%z4\\n\\
   operands[1] = branch_cmp[0];
   operands[2] = branch_cmp[1];
 
+  if (TARGET_DEBUG_C_MODE)
+    {
+      gen_int_relational (LT, operands[0], operands[1], operands[2], (int *)0);
+      DONE;
+    }
+
   /* fall through and generate default code */
 }")
 
 (define_insn "slt_si"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (lt:CC (match_operand:SI 1 "register_operand" "d")
+       (lt:SI (match_operand:SI 1 "register_operand" "d")
               (match_operand:SI 2 "arith_operand" "dI")))]
   ""
   "slt\\t%0,%1,%2"
@@ -3382,7 +3281,7 @@ move\\t%0,%z4\\n\\
 
 (define_expand "sle"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (le:CC (match_dup 1)
+       (le:SI (match_dup 1)
               (match_dup 2)))]
   ""
   "
@@ -3396,31 +3295,49 @@ move\\t%0,%z4\\n\\
   operands[1] = branch_cmp[0];
   operands[2] = branch_cmp[1];
 
+  if (TARGET_DEBUG_C_MODE)
+    {
+      gen_int_relational (LE, operands[0], operands[1], operands[2], (int *)0);
+      DONE;
+    }
+
   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767)
     operands[2] = force_reg (SImode, operands[2]);
 
   /* fall through and generate default code */
 }")
 
-(define_insn "sle_si"
-  [(set (match_operand:SI 0 "register_operand" "=d,d")
-       (le:CC (match_operand:SI 1 "register_operand" "d,d")
-              (match_operand:SI 2 "arith_operand" "d,I")))]
-  "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 32767"
-  "@
-   slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001
-   slt\\t%0,%1,(%2+1)"
- [(set_attr "type"     "arith,arith")
-   (set_attr "mode"    "SI,SI")
-   (set_attr "length"  "2,1")])
+(define_insn "sle_si_const"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (le:SI (match_operand:SI 1 "register_operand" "d")
+              (match_operand:SI 2 "small_int" "I")))]
+  "INTVAL (operands[2]) < 32767"
+  "*
+{
+  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2])+1);
+  return \"slt\\t%0,%1,%2\";
+}"
+ [(set_attr "type"     "arith")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "1")])
+
+(define_insn "sle_si_reg"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (le:SI (match_operand:SI 1 "register_operand" "d")
+              (match_operand:SI 2 "register_operand" "d")))]
+  "!TARGET_DEBUG_C_MODE"
+  "slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001"
+ [(set_attr "type"     "arith")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "2")])
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
-       (le:CC (match_operand:SI 1 "register_operand" "")
+       (le:SI (match_operand:SI 1 "register_operand" "")
               (match_operand:SI 2 "register_operand" "")))]
-  "!TARGET_DEBUG_D_MODE"
+  "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
   [(set (match_dup 0)
-       (lt:CC (match_dup 2)
+       (lt:SI (match_dup 2)
               (match_dup 1)))
    (set (match_dup 0)
        (xor:SI (match_dup 0)
@@ -3429,7 +3346,7 @@ move\\t%0,%z4\\n\\
 
 (define_expand "sgtu"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (gtu:CC (match_dup 1)
+       (gtu:SI (match_dup 1)
                (match_dup 2)))]
   ""
   "
@@ -3443,6 +3360,12 @@ move\\t%0,%z4\\n\\
   operands[1] = branch_cmp[0];
   operands[2] = branch_cmp[1];
 
+  if (TARGET_DEBUG_C_MODE)
+    {
+      gen_int_relational (GTU, operands[0], operands[1], operands[2], (int *)0);
+      DONE;
+    }
+
   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
     operands[2] = force_reg (SImode, operands[2]);
 
@@ -3451,7 +3374,7 @@ move\\t%0,%z4\\n\\
 
 (define_insn "sgtu_si"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (gtu:CC (match_operand:SI 1 "register_operand" "d")
+       (gtu:SI (match_operand:SI 1 "register_operand" "d")
                (match_operand:SI 2 "reg_or_0_operand" "dJ")))]
   ""
   "sltu\\t%0,%z2,%1"
@@ -3461,7 +3384,7 @@ move\\t%0,%z4\\n\\
 
 (define_expand "sgeu"
   [(set (match_operand:SI 0 "register_operand" "=d")
-        (geu:CC (match_dup 1)
+        (geu:SI (match_dup 1)
                 (match_dup 2)))]
   ""
   "
@@ -3473,14 +3396,20 @@ move\\t%0,%z4\\n\\
   operands[1] = branch_cmp[0];
   operands[2] = branch_cmp[1];
 
+  if (TARGET_DEBUG_C_MODE)
+    {
+      gen_int_relational (GEU, operands[0], operands[1], operands[2], (int *)0);
+      DONE;
+    }
+
   /* fall through and generate default code */
 }")
 
 (define_insn "sgeu_si"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (geu:CC (match_operand:SI 1 "register_operand" "d")
+       (geu:SI (match_operand:SI 1 "register_operand" "d")
                (match_operand:SI 2 "arith_operand" "dI")))]
-  ""
+  "!TARGET_DEBUG_C_MODE"
   "sltu\\t%0,%1,%2\;xori\\t%0,%0,0x0001"
  [(set_attr "type"     "arith")
    (set_attr "mode"    "SI")
@@ -3488,11 +3417,11 @@ move\\t%0,%z4\\n\\
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
-       (geu:CC (match_operand:SI 1 "register_operand" "")
+       (geu:SI (match_operand:SI 1 "register_operand" "")
                (match_operand:SI 2 "arith_operand" "")))]
-  "!TARGET_DEBUG_D_MODE"
+  "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
   [(set (match_dup 0)
-       (ltu:CC (match_dup 1)
+       (ltu:SI (match_dup 1)
                (match_dup 2)))
    (set (match_dup 0)
        (xor:SI (match_dup 0)
@@ -3501,7 +3430,7 @@ move\\t%0,%z4\\n\\
 
 (define_expand "sltu"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (ltu:CC (match_dup 1)
+       (ltu:SI (match_dup 1)
                (match_dup 2)))]
   ""
   "
@@ -3513,12 +3442,18 @@ move\\t%0,%z4\\n\\
   operands[1] = branch_cmp[0];
   operands[2] = branch_cmp[1];
 
+  if (TARGET_DEBUG_C_MODE)
+    {
+      gen_int_relational (LTU, operands[0], operands[1], operands[2], (int *)0);
+      DONE;
+    }
+
   /* fall through and generate default code */
 }")
 
 (define_insn "sltu_si"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (ltu:CC (match_operand:SI 1 "register_operand" "d")
+       (ltu:SI (match_operand:SI 1 "register_operand" "d")
                (match_operand:SI 2 "arith_operand" "dI")))]
   ""
   "sltu\\t%0,%1,%2"
@@ -3528,7 +3463,7 @@ move\\t%0,%z4\\n\\
 
 (define_expand "sleu"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (leu:CC (match_dup 1)
+       (leu:SI (match_dup 1)
                (match_dup 2)))]
   ""
   "
@@ -3542,37 +3477,279 @@ move\\t%0,%z4\\n\\
   operands[1] = branch_cmp[0];
   operands[2] = branch_cmp[1];
 
+  if (TARGET_DEBUG_C_MODE)
+    {
+      gen_int_relational (LEU, operands[0], operands[1], operands[2], (int *)0);
+      DONE;
+    }
+
   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767)
     operands[2] = force_reg (SImode, operands[2]);
 
   /* fall through and generate default code */
 }")
 
-(define_insn "sleu_si"
-  [(set (match_operand:SI 0 "register_operand" "=d,d")
-       (leu:CC (match_operand:SI 1 "register_operand" "d,d")
-               (match_operand:SI 2 "arith_operand" "d,I")))]
-  "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 32767"
-  "@
-   sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001
-   sltu\\t%0,%1,(%2+1)"
- [(set_attr "type"     "arith,arith")
-   (set_attr "mode"    "SI,SI")
-   (set_attr "length"  "2,1")])
+(define_insn "sleu_si_const"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (leu:SI (match_operand:SI 1 "register_operand" "d")
+               (match_operand:SI 2 "small_int" "I")))]
+  "INTVAL (operands[2]) < 32767"
+  "*
+{
+  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2])+1);
+  return \"sltu\\t%0,%1,%2\";
+}"
+ [(set_attr "type"     "arith")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "1")])
+
+(define_insn "sleu_si_reg"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (leu:SI (match_operand:SI 1 "register_operand" "d")
+               (match_operand:SI 2 "register_operand" "d")))]
+  "!TARGET_DEBUG_C_MODE"
+  "sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001"
+ [(set_attr "type"     "arith")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "2")])
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
-       (leu:CC (match_operand:SI 1 "register_operand" "")
+       (leu:SI (match_operand:SI 1 "register_operand" "")
                (match_operand:SI 2 "register_operand" "")))]
-  "!TARGET_DEBUG_D_MODE"
+  "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
   [(set (match_dup 0)
-       (ltu:CC (match_dup 2)
+       (ltu:SI (match_dup 2)
                (match_dup 1)))
    (set (match_dup 0)
        (xor:SI (match_dup 0)
                (const_int 1)))]
   "")
 
+\f
+;;
+;;  ....................
+;;
+;;     FLOATING POINT COMPARISONS
+;;
+;;  ....................
+
+(define_insn "seq_df"
+  [(set (reg:CC_FP 66)
+       (eq:CC_FP (match_operand:DF 0 "register_operand" "f")
+                 (match_operand:DF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.eq.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
+(define_insn "sne_df"
+  [(set (reg:CC_REV_FP 66)
+       (ne:CC_REV_FP (match_operand:DF 0 "register_operand" "f")
+                     (match_operand:DF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.eq.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
+(define_insn "slt_df"
+  [(set (reg:CC_FP 66)
+       (lt:CC_FP (match_operand:DF 0 "register_operand" "f")
+                 (match_operand:DF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.lt.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
+(define_insn "sle_df"
+  [(set (reg:CC_FP 66)
+       (le:CC_FP (match_operand:DF 0 "register_operand" "f")
+                 (match_operand:DF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.le.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
+(define_insn "sgt_df"
+  [(set (reg:CC_FP 66)
+       (gt:CC_FP (match_operand:DF 0 "register_operand" "f")
+                 (match_operand:DF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.lt.d\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
+(define_insn "sge_df"
+  [(set (reg:CC_FP 66)
+       (ge:CC_FP (match_operand:DF 0 "register_operand" "f")
+                 (match_operand:DF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.le.d\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
+(define_insn "seq_sf"
+  [(set (reg:CC_FP 66)
+       (eq:CC_FP (match_operand:SF 0 "register_operand" "f")
+                 (match_operand:SF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.eq.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
+(define_insn "sne_sf"
+  [(set (reg:CC_REV_FP 66)
+       (ne:CC_REV_FP (match_operand:SF 0 "register_operand" "f")
+                     (match_operand:SF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.eq.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
+(define_insn "slt_sf"
+  [(set (reg:CC_FP 66)
+       (lt:CC_FP (match_operand:SF 0 "register_operand" "f")
+                 (match_operand:SF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.lt.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
+(define_insn "sle_sf"
+  [(set (reg:CC_FP 66)
+       (le:CC_FP (match_operand:SF 0 "register_operand" "f")
+                 (match_operand:SF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.le.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
+(define_insn "sgt_sf"
+  [(set (reg:CC_FP 66)
+       (gt:CC_FP (match_operand:SF 0 "register_operand" "f")
+                 (match_operand:SF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.lt.s\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
+(define_insn "sge_sf"
+  [(set (reg:CC_FP 66)
+       (ge:CC_FP (match_operand:SF 0 "register_operand" "f")
+                 (match_operand:SF 1 "register_operand" "f")))]
+  ""
+  "*
+{
+  rtx xoperands[10];
+  xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+  xoperands[1] = operands[0];
+  xoperands[2] = operands[1];
+
+  return mips_fill_delay_slot (\"c.le.s\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type"     "fcmp")
+  (set_attr "mode"     "FPSW")
+  (set_attr "length"   "1")])
+
 \f
 ;;
 ;;  ....................