OSDN Git Service

* config/mips/mips.h (MIPS_CMP_MOVT, MIPS_CMP_MOVF): Delete.
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 29 Aug 2004 11:10:05 +0000 (11:10 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 29 Aug 2004 11:10:05 +0000 (11:10 +0000)
* config/mips/mips.c (mips_prepare_builtin_arg): New function.
(mips_prepare_builtin_target): New function.
(mips_expand_builtin): Use them.  Update calls to subroutines.
(mips_expand_ps_cond_move_builtin): Use the new functions.  Replace
cmp_choice with a boolean argument to select between movt and movf.
Take the comparison's icode as an argument, not the function's fcode.
(mips_expand_compare_builtin): New function.  Rename existing function
to mips_expand_scalar_compare_builtin.
(mips_expand_scalar_compare_builtin, mips_expand_4s_compare_builtin)
(mips_expand_ps_compare_builtin): Use the new functions.  Take the
comparison's icode as an argument, not the builtin's fcode.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@86716 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/config/mips/mips.h

index a35febb..38f35be 100644 (file)
@@ -1,5 +1,20 @@
 2004-08-29  Richard Sandiford  <rsandifo@redhat.com>
 
+       * config/mips/mips.h (MIPS_CMP_MOVT, MIPS_CMP_MOVF): Delete.
+       * config/mips/mips.c (mips_prepare_builtin_arg): New function.
+       (mips_prepare_builtin_target): New function.
+       (mips_expand_builtin): Use them.  Update calls to subroutines.
+       (mips_expand_ps_cond_move_builtin): Use the new functions.  Replace
+       cmp_choice with a boolean argument to select between movt and movf.
+       Take the comparison's icode as an argument, not the function's fcode.
+       (mips_expand_compare_builtin): New function.  Rename existing function
+       to mips_expand_scalar_compare_builtin.
+       (mips_expand_scalar_compare_builtin, mips_expand_4s_compare_builtin)
+       (mips_expand_ps_compare_builtin): Use the new functions.  Take the
+       comparison's icode as an argument, not the builtin's fcode.
+
+2004-08-29  Richard Sandiford  <rsandifo@redhat.com>
+
        * config/mips/mips.c (print_operand): Remove '%Y' and '%y'.
        (mips_expand_4s_compare_builtin): Redefine CCV4 to be 0 if all
        registers are false and -1 if all registers are true.
index 4f6ddd5..1ee3743 100644 (file)
@@ -263,15 +263,17 @@ static tree mips_gimplify_va_arg_expr (tree, tree, tree *, tree *);
 static bool mips_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode mode,
                                    tree, bool);
 static bool mips_vector_mode_supported_p (enum machine_mode);
-static void mips_init_builtins (void);
+static rtx mips_prepare_builtin_arg (enum insn_code, unsigned int, tree *);
+static rtx mips_prepare_builtin_target (enum insn_code, unsigned int, rtx);
 static rtx mips_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
-static rtx mips_expand_compare_builtin (rtx, unsigned int, tree);
-static rtx mips_expand_ps_compare_builtin (enum mips_cmp_choice, rtx,
-                                          unsigned int, tree);
-static rtx mips_expand_4s_compare_builtin (enum mips_cmp_choice, rtx,
-                                          unsigned int, tree);
-static rtx mips_expand_ps_cond_move_builtin (enum mips_cmp_choice, rtx,
-                                            unsigned int, tree);
+static void mips_init_builtins (void);
+static rtx mips_expand_ps_cond_move_builtin (bool, enum insn_code, rtx, tree);
+static rtx mips_expand_compare_builtin (bool, rtx, rtx, rtx, int);
+static rtx mips_expand_scalar_compare_builtin (enum insn_code, rtx, tree);
+static rtx mips_expand_4s_compare_builtin (enum mips_cmp_choice,
+                                          enum insn_code, rtx, tree);
+static rtx mips_expand_ps_compare_builtin (enum mips_cmp_choice,
+                                          enum insn_code, rtx, tree);
 
 /* Structure to be filled in by compute_frame_size with register
    save masks, and offsets for the current function.  */
@@ -10011,6 +10013,41 @@ static const struct builtin_description mips_bdesc[] =
 };
 
 
+/* Take the head of argument list *ARGLIST and convert it into a form
+   suitable for input operand OP of instruction ICODE.  Return the value
+   and point *ARGLIST at the next element of the list.  */
+
+static rtx
+mips_prepare_builtin_arg (enum insn_code icode,
+                         unsigned int op, tree *arglist)
+{
+  rtx value;
+  enum machine_mode mode;
+
+  value = expand_expr (TREE_VALUE (*arglist), NULL_RTX, VOIDmode, 0);
+  mode = insn_data[icode].operand[op].mode;
+  if (!insn_data[icode].operand[op].predicate (value, mode))
+    value = copy_to_mode_reg (mode, value);
+
+  *arglist = TREE_CHAIN (*arglist);
+  return value;
+}
+
+/* Return an rtx suitable for output operand OP of instruction ICODE.
+   If TARGET is non-null, try to use it where possible.  */
+
+static rtx
+mips_prepare_builtin_target (enum insn_code icode, unsigned int op, rtx target)
+{
+  enum machine_mode mode;
+
+  mode = insn_data[icode].operand[op].mode;
+  if (target == 0 || !insn_data[icode].operand[op].predicate (target, mode))
+    target = gen_reg_rtx (mode);
+
+  return target;
+}
+
 /* Expand builtin functions.  This is called from TARGET_EXPAND_BUILTIN.  */
 
 rtx
@@ -10018,22 +10055,18 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
                     enum machine_mode mode ATTRIBUTE_UNUSED,
                     int ignore ATTRIBUTE_UNUSED)
 {
-  rtx pat;
+  rtx op0, op1, op2;
   enum insn_code icode;
-  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
-  tree arglist = TREE_OPERAND (exp, 1);
-  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
-  tree arg0;
-  tree arg1;
-  tree arg2;
-  enum machine_mode tmode;
-  enum machine_mode mode0;
-  enum machine_mode mode1;
-  enum machine_mode mode2;
-  rtx op0;
-  rtx op1;
-  rtx op2;
+  tree fndecl, arglist;
+  unsigned int fcode;
 
+  fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+  arglist = TREE_OPERAND (exp, 1);
+  fcode = DECL_FUNCTION_CODE (fndecl);
+  if (fcode >= ARRAY_SIZE (mips_bdesc))
+    return 0;
+
+  icode = mips_bdesc[fcode].icode;
   switch (fcode)
     {
     /* Two Operands.  */
@@ -10050,31 +10083,10 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_RSQRT2_S:
     case MIPS_BUILTIN_RSQRT2_D:
     case MIPS_BUILTIN_RSQRT2_PS:
-
-      icode = mips_bdesc[fcode].icode;
-      arg0 = TREE_VALUE (arglist);
-      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
-      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
-      op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
-      tmode = insn_data[icode].operand[0].mode;
-      mode0 = insn_data[icode].operand[1].mode;
-      mode1 = insn_data[icode].operand[2].mode;
-
-      if (target == 0
-         || GET_MODE (target) != tmode
-         || !(*insn_data[icode].operand[0].predicate) (target, tmode))
-       target = gen_reg_rtx (tmode);
-
-      if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
-       op0 = copy_to_mode_reg (mode0, op0);
-      if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
-       op1 = copy_to_mode_reg (mode1, op1);
-
-      pat = GEN_FCN (icode) (target, op0, op1);
-      if (!pat)
-       return 0;
-      
-      emit_insn (pat);
+      target = mips_prepare_builtin_target (icode, 0, target);
+      op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+      op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+      emit_insn (GEN_FCN (icode) (target, op0, op1));
       return target;
 
     /* One Operand.  */
@@ -10089,62 +10101,18 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_RSQRT1_S:
     case MIPS_BUILTIN_RSQRT1_D:
     case MIPS_BUILTIN_RSQRT1_PS:
-
-      icode = mips_bdesc[fcode].icode;
-      arg0 = TREE_VALUE (arglist);
-      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
-      tmode = insn_data[icode].operand[0].mode;
-      mode0 = insn_data[icode].operand[1].mode;
-
-      if (target == 0
-         || GET_MODE (target) != tmode
-         || !(*insn_data[icode].operand[0].predicate) (target, tmode))
-       target = gen_reg_rtx (tmode);
-
-      if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
-       op0 = copy_to_mode_reg (mode0, op0);
-      
-      pat = GEN_FCN (icode) (target, op0);
-      if (!pat)
-       return 0;
-      
-      emit_insn (pat);
+      target = mips_prepare_builtin_target (icode, 0, target);
+      op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+      emit_insn (GEN_FCN (icode) (target, op0));
       return target;
 
     /* Three Operands.  */
     case MIPS_BUILTIN_ALNV_PS:
-
-      icode = mips_bdesc[fcode].icode;
-      arg0 = TREE_VALUE (arglist);
-      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
-      arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
-      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
-      op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
-      op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
-      tmode = insn_data[icode].operand[0].mode;
-      mode0 = insn_data[icode].operand[1].mode;
-      mode1 = insn_data[icode].operand[2].mode;
-      mode2 = insn_data[icode].operand[3].mode;
-
-      if (target == 0
-         || GET_MODE (target) != tmode
-         || !(*insn_data[icode].operand[0].predicate) (target, tmode))
-       target = gen_reg_rtx (tmode);
-
-      if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
-       op0 = copy_to_mode_reg (mode0, op0);
-
-      if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
-       op1 = copy_to_mode_reg (mode1, op1);
-
-      if (!(*insn_data[icode].operand[3].predicate) (op2, mode2))
-       op2 = copy_to_mode_reg (mode2, op2);
-
-      pat = GEN_FCN (icode) (target, op0, op1, op2);
-      if (!pat)
-       return 0;
-      
-      emit_insn (pat);
+      target = mips_prepare_builtin_target (icode, 0, target);
+      op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+      op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+      op2 = mips_prepare_builtin_arg (icode, 3, &arglist);
+      emit_insn (GEN_FCN (icode) (target, op0, op1, op2));
       return target;
 
     /* Paired Single Comparison.  */
@@ -10180,8 +10148,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_ANY_CABS_NGE_PS:
     case MIPS_BUILTIN_ANY_CABS_LE_PS:
     case MIPS_BUILTIN_ANY_CABS_NGT_PS:
-      return mips_expand_ps_compare_builtin (MIPS_CMP_ANY, target, 
-                                            fcode, arglist);
+      return mips_expand_ps_compare_builtin (MIPS_CMP_ANY, icode,
+                                            target, arglist);
 
     /* Paired Single Comparison.  */
     case MIPS_BUILTIN_UPPER_C_F_PS:
@@ -10216,8 +10184,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_UPPER_CABS_NGE_PS:
     case MIPS_BUILTIN_UPPER_CABS_LE_PS:
     case MIPS_BUILTIN_UPPER_CABS_NGT_PS:
-      return mips_expand_ps_compare_builtin (MIPS_CMP_UPPER, target, 
-                                            fcode, arglist);
+      return mips_expand_ps_compare_builtin (MIPS_CMP_UPPER, icode,
+                                            target, arglist);
 
     /* Paired Single Comparison.  */
     case MIPS_BUILTIN_LOWER_C_F_PS:
@@ -10252,8 +10220,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_LOWER_CABS_NGE_PS:
     case MIPS_BUILTIN_LOWER_CABS_LE_PS:
     case MIPS_BUILTIN_LOWER_CABS_NGT_PS:
-      return mips_expand_ps_compare_builtin (MIPS_CMP_LOWER, target, 
-                                            fcode, arglist);
+      return mips_expand_ps_compare_builtin (MIPS_CMP_LOWER, icode,
+                                            target, arglist);
 
     /* Paired Single Comparison.  */
     case MIPS_BUILTIN_ALL_C_F_PS:
@@ -10288,8 +10256,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_ALL_CABS_NGE_PS:
     case MIPS_BUILTIN_ALL_CABS_LE_PS:
     case MIPS_BUILTIN_ALL_CABS_NGT_PS:
-      return mips_expand_ps_compare_builtin (MIPS_CMP_ALL, target, 
-                                            fcode, arglist);
+      return mips_expand_ps_compare_builtin (MIPS_CMP_ALL, icode,
+                                            target, arglist);
 
     /* Four Single Comparison.  */
     case MIPS_BUILTIN_ANY_C_F_4S:
@@ -10324,8 +10292,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_ANY_CABS_NGE_4S:
     case MIPS_BUILTIN_ANY_CABS_LE_4S:
     case MIPS_BUILTIN_ANY_CABS_NGT_4S:
-      return mips_expand_4s_compare_builtin (MIPS_CMP_ANY, target, 
-                                            fcode, arglist);
+      return mips_expand_4s_compare_builtin (MIPS_CMP_ANY, icode,
+                                            target, arglist);
 
     /* Four Single Comparison.  */
     case MIPS_BUILTIN_ALL_C_F_4S:
@@ -10360,8 +10328,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_ALL_CABS_NGE_4S:
     case MIPS_BUILTIN_ALL_CABS_LE_4S:
     case MIPS_BUILTIN_ALL_CABS_NGT_4S:
-      return mips_expand_4s_compare_builtin (MIPS_CMP_ALL, target, 
-                                            fcode, arglist);
+      return mips_expand_4s_compare_builtin (MIPS_CMP_ALL, icode,
+                                            target, arglist);
 
     /* Single/Double Compare Absolute.  */
     case MIPS_BUILTIN_CABS_F_S:
@@ -10396,7 +10364,7 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_CABS_NGE_D:
     case MIPS_BUILTIN_CABS_LE_D:
     case MIPS_BUILTIN_CABS_NGT_D:
-      return mips_expand_compare_builtin (target, fcode, arglist);
+      return mips_expand_scalar_compare_builtin (icode, target, arglist);
 
     /* Conditional Move on True.  */
     case MIPS_BUILTIN_MOVT_C_F_PS:
@@ -10431,8 +10399,7 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_MOVT_CABS_NGE_PS:
     case MIPS_BUILTIN_MOVT_CABS_LE_PS:
     case MIPS_BUILTIN_MOVT_CABS_NGT_PS:
-      return mips_expand_ps_cond_move_builtin (MIPS_CMP_MOVT, target, 
-                                              fcode, arglist);
+      return mips_expand_ps_cond_move_builtin (true, icode, target, arglist);
 
     /* Conditional Move on False.  */
     case MIPS_BUILTIN_MOVF_C_F_PS:
@@ -10467,8 +10434,7 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_MOVF_CABS_NGE_PS:
     case MIPS_BUILTIN_MOVF_CABS_LE_PS:
     case MIPS_BUILTIN_MOVF_CABS_NGT_PS:
-      return mips_expand_ps_cond_move_builtin (MIPS_CMP_MOVF, target, 
-                                              fcode, arglist);
+      return mips_expand_ps_cond_move_builtin (false, icode, target, arglist);
 
     default:
       break;
@@ -10654,169 +10620,116 @@ mips_init_builtins (void)
     }
 }
 
-/* This performs a paired single compare, and then a conditional move based
-   on the result of that compare.  CMP_CHOICE is the kind of comparison we
-   want.  TARGET is a suggestion of where to put the result.  FCODE is the
-   function code.  ARGLIST is the list of arguments.  The return value is
-   the result of the conditional move.  */
+/* Expand a __builtin_mips_movt_*_ps() or __builtin_mips_movf_*_ps()
+   function (MOVE_ON_TRUE says which).  ARGLIST is the list of arguments
+   to the function and ICODE says which instruction should be used to
+   compare the first two arguments.  TARGET, if nonnull, suggests a
+   good place to put the result.  */
 
 static rtx
-mips_expand_ps_cond_move_builtin (enum mips_cmp_choice cmp_choice,
-                                 rtx target, unsigned int fcode,
-                                 tree arglist)
+mips_expand_ps_cond_move_builtin (bool move_on_true, enum insn_code icode,
+                                 rtx target, tree arglist)
 {
-  rtx pat;
-  enum insn_code icode;
-  tree arg0;
-  tree arg1;
-  tree arg2;
-  tree arg3;
-  rtx op0;
-  rtx op1;
-  rtx op2;
-  rtx op3;
-  enum machine_mode tmode;
-  enum machine_mode mode0;
-  enum machine_mode mode1;
-  rtx temp_target;
-  rtx src1;
-  rtx src2;
-
-  arg0 = TREE_VALUE (arglist);
-  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
-  arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
-  arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
-  op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
-  op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
-  op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
-  op3 = expand_expr (arg3, NULL_RTX, VOIDmode, 0);
-
-  icode = mips_bdesc[fcode].icode;
-  tmode = insn_data[icode].operand[0].mode;
-  mode0 = insn_data[icode].operand[1].mode;
-  mode1 = insn_data[icode].operand[2].mode;
-
-  if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
-    op0 = copy_to_mode_reg (mode0, op0);
-
-  if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
-    op1 = copy_to_mode_reg (mode1, op1);
+  rtx cmp_result, op0, op1;
 
-  /* temp_target is the result of the comparison.  */
-  temp_target = gen_reg_rtx (tmode);
+  cmp_result = mips_prepare_builtin_target (icode, 0, 0);
+  op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+  op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+  emit_insn (GEN_FCN (icode) (cmp_result, op0, op1));
 
-  pat = GEN_FCN (icode) (temp_target, op0, op1);
-  if (!pat)
-    return 0;
+  icode = CODE_FOR_mips_cond_move_tf_ps;
+  target = mips_prepare_builtin_target (icode, 0, target);
+  if (move_on_true)
+    {
+      op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+      op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+    }
+  else
+    {
+      op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+      op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+    }
+  emit_insn (gen_mips_cond_move_tf_ps (target, op0, op1, cmp_result));
+  return target;
+}
 
-  emit_insn (pat);
+/* Use comparison instruction PAT to set condition-code register REG.
+   If NONZERO_IF_EQUAL_P, return an rtx that is 1 if the new value of
+   REG equals CONSTANT and 0 otherwise.  Return the inverse if
+   !NONZERO_IF_EQUAL_P.  TARGET, if nonnull, suggests a good place
+   for the result.  */
 
-  icode = CODE_FOR_mips_cond_move_tf_ps;
-  tmode = insn_data[icode].operand[0].mode;
+static rtx
+mips_expand_compare_builtin (bool nonzero_if_equal_p, rtx target,
+                            rtx pat, rtx reg, int constant)
+{
+  rtx label1, label2, if_then_else;
 
-  if (target == 0
-      || GET_MODE (target) != tmode
-      || !(*insn_data[icode].operand[0].predicate) (target, tmode))
-    target = gen_reg_rtx (tmode);
+  if (target == 0 || GET_MODE (target) != SImode)
+    target = gen_reg_rtx (SImode);
 
-  /* Let op2 be the same as the tmode */
-  if (!(*insn_data[icode].operand[0].predicate) (op2, tmode))
-    op2 = copy_to_mode_reg (tmode, op2);
+  /* First assume that REG == CONSTANT.  */
+  emit_move_insn (target, nonzero_if_equal_p ? const1_rtx : const0_rtx);
 
-  /* Let op3 be the same as the tmode */
-  if (!(*insn_data[icode].operand[0].predicate) (op3, tmode))
-    op3 = copy_to_mode_reg (tmode, op3);
+  /* Branch to LABEL1 if REG != CONSTANT.  */
+  emit_insn (pat);
+  label1 = gen_label_rtx ();
+  label2 = gen_label_rtx ();
+  if_then_else
+    = gen_rtx_IF_THEN_ELSE (VOIDmode,
+                           gen_rtx_fmt_ee (NE, GET_MODE (reg),
+                                           reg, GEN_INT (constant)),
+                           gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx);
+  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else));
+  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
+                              gen_rtx_LABEL_REF (VOIDmode, label2)));
+  emit_barrier ();
+  emit_label (label1);
 
-  /* Copy op2 to target */
-  emit_insn (gen_rtx_SET (tmode, target, op2)); 
+  /* Fix TARGET for REG != CONSTANT.  */
+  emit_move_insn (target, nonzero_if_equal_p ? const0_rtx : const1_rtx);
+  emit_label (label2);
 
-  switch (cmp_choice)
-    {
-    case MIPS_CMP_MOVT:
-      src1 = op3;
-      src2 = target;
-      break;
+  return target;
+}
 
-    case MIPS_CMP_MOVF:
-      src1 = target;
-      src2 = op3;
-      break;
+/* Read two scalar arguments from ARGLIST and use instruction ICODE to
+   compare them.  Return the result as a boolean SImode value.  TARGET,
+   if nonnull, suggests a good place to put the result.  */
 
-    default:
-      return 0;
-    }
+rtx
+mips_expand_scalar_compare_builtin (enum insn_code icode, rtx target,
+                                   tree arglist)
+{
+  rtx pat, cmp_result, op0, op1;
 
-  emit_insn (gen_mips_cond_move_tf_ps (target, src1, src2, temp_target));
+  cmp_result = mips_prepare_builtin_target (icode, 0, 0);
+  op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+  op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+  pat = GEN_FCN (icode) (cmp_result, op0, op1);
 
-  return target;
+  return mips_expand_compare_builtin (false, target, pat, cmp_result, 0);
 }
 
-/* This performs two paired single compares, and returns an boolean value to
-   represent the result of the compare.  CMP_CHOICE is the kind of comparison
-   we want.  TARGET is a suggestion of where to put the result.  FCODE is
-   the builtin function code.  ARGLIST is the list of arguments.  The
-   return value is the result of the compare.  */
+/* Read four V2SF arguments from ARGLIST and use instruction ICODE to
+   compare them.  Use CMP_CHOICE to convert the four condition codes
+   into an SImode value.  TARGET, if nonnull, suggests a good place
+   to put this value.  */
 
 rtx
-mips_expand_4s_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target,
-                               unsigned int fcode, tree arglist)
+mips_expand_4s_compare_builtin (enum mips_cmp_choice cmp_choice,
+                               enum insn_code icode, rtx target,
+                               tree arglist)
 {
-  rtx pat;
-  enum insn_code icode;
-  tree arg0;
-  tree arg1;
-  tree arg2;
-  tree arg3;
-  rtx op0;
-  rtx op1;
-  rtx op2;
-  rtx op3;
-  enum machine_mode tmode;
-  enum machine_mode mode0;
-  enum machine_mode mode1;
-  enum machine_mode mode2;
-  enum machine_mode mode3;
-  rtx temp_target;
-  rtx label1;
-  rtx label2;
-  rtx if_then_else;
+  rtx pat, cmp_result, op0, op1, op2, op3;
   int compare_value;
 
-  if (target == 0 || GET_MODE (target) != SImode)
-    target = gen_reg_rtx (SImode);
-
-  icode = mips_bdesc[fcode].icode;
-  arg0 = TREE_VALUE (arglist);
-  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
-  arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
-  arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
-  op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
-  op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
-  op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
-  op3 = expand_expr (arg3, NULL_RTX, VOIDmode, 0);
-  tmode = insn_data[icode].operand[0].mode;
-  mode0 = insn_data[icode].operand[1].mode;
-  mode1 = insn_data[icode].operand[2].mode;
-  mode2 = insn_data[icode].operand[3].mode;
-  mode3 = insn_data[icode].operand[4].mode;
-
-  temp_target = gen_reg_rtx (tmode);
-
-  if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
-    op0 = copy_to_mode_reg (mode0, op0);
-
-  if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
-    op1 = copy_to_mode_reg (mode1, op1);
-
-  if (!(*insn_data[icode].operand[3].predicate) (op2, mode2))
-    op2 = copy_to_mode_reg (mode2, op2);
-
-  if (!(*insn_data[icode].operand[4].predicate) (op3, mode3))
-    op3 = copy_to_mode_reg (mode3, op3);
-
-  pat = GEN_FCN (icode) (temp_target, op0, op1, op2, op3);
-  if (!pat)
-    return 0;
+  cmp_result = mips_prepare_builtin_target (icode, 0, 0);
+  op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+  op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+  op2 = mips_prepare_builtin_arg (icode, 3, &arglist);
+  op3 = mips_prepare_builtin_arg (icode, 4, &arglist);
+  pat = GEN_FCN (icode) (cmp_result, op0, op1, op2, op3);
 
   /* We fake the value of CCV4 to be:
      0 if all registers are false.
@@ -10841,161 +10754,28 @@ mips_expand_4s_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target,
       break;
 
     default:
-      return 0;
+      abort ();
     }
 
-  if (cmp_choice == MIPS_CMP_ALL)
-    emit_move_insn (target, const1_rtx);
-  else
-    emit_move_insn (target, const0_rtx);
-
-  emit_insn (pat);
-
-  label1 = gen_label_rtx ();
-  label2 = gen_label_rtx ();
-  if_then_else 
-    = gen_rtx_IF_THEN_ELSE (VOIDmode,
-                           gen_rtx_fmt_ee (NE, CCV4mode, temp_target,
-                                           GEN_INT (compare_value)),
-                           gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx);
-
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else)); 
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 
-                              gen_rtx_LABEL_REF (VOIDmode, label2)));
-
-  emit_barrier ();
-  emit_label (label1);
-
-  if (cmp_choice == MIPS_CMP_ALL)
-    emit_move_insn (target, const0_rtx);
-  else
-    emit_move_insn (target, const1_rtx);
-
-  emit_label (label2);
-
-  return target;
+  return mips_expand_compare_builtin (cmp_choice == MIPS_CMP_ALL,
+                                     target, pat, cmp_result, compare_value);
 }
 
-/* This performs a single float or double float comparison.  TARGET is a
-   suggestion of where to put the result.  FCODE is the builtin function code.
-   ARGLIST is the list of arguments.  The return value is the result of the
-   compare.  */
+/* Like mips_expand_4s_compare_builtin, but compares two V2SF vectors rather
+   than four.  The arguments and return type are otherwise the same. */
 
 rtx
-mips_expand_compare_builtin (rtx target, unsigned int fcode, tree arglist)
+mips_expand_ps_compare_builtin (enum mips_cmp_choice cmp_choice,
+                               enum insn_code icode, rtx target,
+                               tree arglist)
 {
-  rtx pat;
-  enum insn_code icode;
-  tree arg0;
-  tree arg1;
-  rtx op0;
-  rtx op1;
-  enum machine_mode tmode;
-  enum machine_mode mode0;
-  enum machine_mode mode1;
-  rtx temp_target;
-  rtx label1;
-  rtx label2;
-  rtx if_then_else;
-  enum rtx_code test_code;
-
-  if (target == 0 || GET_MODE (target) != SImode)
-    target = gen_reg_rtx (SImode);
-
-  icode = mips_bdesc[fcode].icode;
-  arg0 = TREE_VALUE (arglist);
-  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
-  op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
-  op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
-  tmode = insn_data[icode].operand[0].mode;
-  mode0 = insn_data[icode].operand[1].mode;
-  mode1 = insn_data[icode].operand[2].mode;
-
-  temp_target = gen_reg_rtx (tmode);
-
-  if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
-    op0 = copy_to_mode_reg (mode0, op0);
-
-  if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
-    op1 = copy_to_mode_reg (mode1, op1);
-
-  pat = GEN_FCN (icode) (temp_target, op0, op1);
-  if (!pat)
-    return 0;
-
-  emit_move_insn (target, const0_rtx);
-  emit_insn (pat);
-
-  label1 = gen_label_rtx ();
-  label2 = gen_label_rtx ();
-
-  test_code =  NE;
-  if_then_else
-    = gen_rtx_IF_THEN_ELSE (VOIDmode,
-                           gen_rtx_fmt_ee (test_code, CCmode, 
-                                           temp_target, const0_rtx),
-                           gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx);
-
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else)); 
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 
-                              gen_rtx_LABEL_REF (VOIDmode, label2)));
-
-  emit_barrier ();
-  emit_label (label1);
-  emit_move_insn (target, const1_rtx);
-  emit_label (label2);
-
-  return target;
-}
-
-/* This performs a paired single compare, and returns an boolean value to
-   represent the result of the compare.  CMP_CHOICE is the kind of comparison
-   we want.  TARGET is a suggestion of where to put the result.  FCODE is
-   the builtin function code.  ARGLIST is the list of arguments.  The
-   return value is the result of the compare.  */
-
-rtx
-mips_expand_ps_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target,
-                               unsigned int fcode, tree arglist)
-{
-  rtx pat;
-  enum insn_code icode;
-  tree arg0;
-  tree arg1;
-  rtx op0;
-  rtx op1;
-  enum machine_mode tmode;
-  enum machine_mode mode0;
-  enum machine_mode mode1;
-  rtx temp_target;
-  rtx label1;
-  rtx label2;
-  rtx if_then_else;
+  rtx pat, cmp_result, op0, op1;
   int compare_value;
 
-  if (target == 0 || GET_MODE (target) != SImode)
-    target = gen_reg_rtx (SImode);
-
-  icode = mips_bdesc[fcode].icode;
-  arg0 = TREE_VALUE (arglist);
-  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
-  op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
-  op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
-  tmode = insn_data[icode].operand[0].mode;
-  mode0 = insn_data[icode].operand[1].mode;
-  mode1 = insn_data[icode].operand[2].mode;
-
-  temp_target = gen_reg_rtx (tmode);
-
-  if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
-    op0 = copy_to_mode_reg (mode0, op0);
-
-  if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
-    op1 = copy_to_mode_reg (mode1, op1);
-
-  pat = GEN_FCN (icode) (temp_target, op0, op1);
-  if (!pat)
-    return 0;
+  cmp_result = mips_prepare_builtin_target (icode, 0, 0);
+  op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+  op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+  pat = GEN_FCN (icode) (cmp_result, op0, op1);
 
   /* We fake the value of CCV2 to be:
      0 if all registers are false.
@@ -11019,12 +10799,12 @@ mips_expand_ps_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target,
       break;
 
     case MIPS_CMP_UPPER:
-      temp_target = simplify_gen_subreg (CCmode, temp_target, CCV2mode, 4);
+      cmp_result = simplify_gen_subreg (CCmode, cmp_result, CCV2mode, 4);
       compare_value = 0;
       break;
 
     case MIPS_CMP_LOWER:
-      temp_target = simplify_gen_subreg (CCmode, temp_target, CCV2mode, 0);
+      cmp_result = simplify_gen_subreg (CCmode, cmp_result, CCV2mode, 0);
       compare_value = 0;
       break;
 
@@ -11033,41 +10813,11 @@ mips_expand_ps_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target,
       break;
 
     default:
-      return 0;
+      abort ();
     }
 
-  if (cmp_choice == MIPS_CMP_ALL)
-    emit_move_insn (target, const1_rtx);
-  else
-    emit_move_insn (target, const0_rtx);
-
-  emit_insn (pat);
-
-  label1 = gen_label_rtx ();
-  label2 = gen_label_rtx ();
-
-  if_then_else 
-    = gen_rtx_IF_THEN_ELSE (VOIDmode,
-                           gen_rtx_fmt_ee (NE, GET_MODE (temp_target),
-                                           temp_target,
-                                           GEN_INT (compare_value)),
-                           gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx);
-
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else)); 
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 
-                              gen_rtx_LABEL_REF (VOIDmode, label2)));
-
-  emit_barrier ();
-  emit_label (label1);
-
-  if (cmp_choice == MIPS_CMP_ALL)
-    emit_move_insn (target, const0_rtx);
-  else
-    emit_move_insn (target, const1_rtx);
-
-  emit_label (label2);
-
-  return target;
+  return mips_expand_compare_builtin (cmp_choice == MIPS_CMP_ALL,
+                                     target, pat, cmp_result, compare_value);
 }
 \f
 #include "gt-mips.h"
index 991d801..b8a6844 100644 (file)
@@ -3385,8 +3385,5 @@ enum mips_cmp_choice
   MIPS_CMP_LOWER,  /* Check if the lower one of two results is true.  */
   MIPS_CMP_ALL,    /* Check if all results are true.  */
 
-  MIPS_CMP_MOVT,   /* Conditional move if true.  */
-  MIPS_CMP_MOVF,   /* Conditional move if false.  */
-
   MIPS_CMP_MAX
 };