Commit ff55fb9c by Richard Sandiford Committed by Richard Sandiford

mips.h (MIPS_CMP_MOVT, [...]): Delete.

	* 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.

From-SVN: r86716
parent f691c4e3
2004-08-29 Richard Sandiford <rsandifo@redhat.com> 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'. * config/mips/mips.c (print_operand): Remove '%Y' and '%y'.
(mips_expand_4s_compare_builtin): Redefine CCV4 to be 0 if all (mips_expand_4s_compare_builtin): Redefine CCV4 to be 0 if all
registers are false and -1 if all registers are true. registers are false and -1 if all registers are true.
......
...@@ -263,15 +263,17 @@ static tree mips_gimplify_va_arg_expr (tree, tree, tree *, tree *); ...@@ -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, static bool mips_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode mode,
tree, bool); tree, bool);
static bool mips_vector_mode_supported_p (enum machine_mode); 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_builtin (tree, rtx, rtx, enum machine_mode, int);
static rtx mips_expand_compare_builtin (rtx, unsigned int, tree); static void mips_init_builtins (void);
static rtx mips_expand_ps_compare_builtin (enum mips_cmp_choice, rtx, static rtx mips_expand_ps_cond_move_builtin (bool, enum insn_code, rtx, tree);
unsigned int, tree); static rtx mips_expand_compare_builtin (bool, rtx, rtx, rtx, int);
static rtx mips_expand_4s_compare_builtin (enum mips_cmp_choice, rtx, static rtx mips_expand_scalar_compare_builtin (enum insn_code, rtx, tree);
unsigned int, tree); static rtx mips_expand_4s_compare_builtin (enum mips_cmp_choice,
static rtx mips_expand_ps_cond_move_builtin (enum mips_cmp_choice, rtx, enum insn_code, rtx, tree);
unsigned int, 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 /* Structure to be filled in by compute_frame_size with register
save masks, and offsets for the current function. */ save masks, and offsets for the current function. */
...@@ -10011,6 +10013,41 @@ static const struct builtin_description mips_bdesc[] = ...@@ -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. */ /* Expand builtin functions. This is called from TARGET_EXPAND_BUILTIN. */
rtx rtx
...@@ -10018,22 +10055,18 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -10018,22 +10055,18 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED) int ignore ATTRIBUTE_UNUSED)
{ {
rtx pat; rtx op0, op1, op2;
enum insn_code icode; enum insn_code icode;
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); tree fndecl, arglist;
tree arglist = TREE_OPERAND (exp, 1); unsigned int fcode;
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
tree arg0; fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
tree arg1; arglist = TREE_OPERAND (exp, 1);
tree arg2; fcode = DECL_FUNCTION_CODE (fndecl);
enum machine_mode tmode; if (fcode >= ARRAY_SIZE (mips_bdesc))
enum machine_mode mode0; return 0;
enum machine_mode mode1;
enum machine_mode mode2;
rtx op0;
rtx op1;
rtx op2;
icode = mips_bdesc[fcode].icode;
switch (fcode) switch (fcode)
{ {
/* Two Operands. */ /* Two Operands. */
...@@ -10050,31 +10083,10 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -10050,31 +10083,10 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
case MIPS_BUILTIN_RSQRT2_S: case MIPS_BUILTIN_RSQRT2_S:
case MIPS_BUILTIN_RSQRT2_D: case MIPS_BUILTIN_RSQRT2_D:
case MIPS_BUILTIN_RSQRT2_PS: case MIPS_BUILTIN_RSQRT2_PS:
target = mips_prepare_builtin_target (icode, 0, target);
icode = mips_bdesc[fcode].icode; op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
arg0 = TREE_VALUE (arglist); op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist)); emit_insn (GEN_FCN (icode) (target, op0, op1));
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);
return target; return target;
/* One Operand. */ /* One Operand. */
...@@ -10089,62 +10101,18 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -10089,62 +10101,18 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
case MIPS_BUILTIN_RSQRT1_S: case MIPS_BUILTIN_RSQRT1_S:
case MIPS_BUILTIN_RSQRT1_D: case MIPS_BUILTIN_RSQRT1_D:
case MIPS_BUILTIN_RSQRT1_PS: case MIPS_BUILTIN_RSQRT1_PS:
target = mips_prepare_builtin_target (icode, 0, target);
icode = mips_bdesc[fcode].icode; op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
arg0 = TREE_VALUE (arglist); emit_insn (GEN_FCN (icode) (target, op0));
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);
return target; return target;
/* Three Operands. */ /* Three Operands. */
case MIPS_BUILTIN_ALNV_PS: case MIPS_BUILTIN_ALNV_PS:
target = mips_prepare_builtin_target (icode, 0, target);
icode = mips_bdesc[fcode].icode; op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
arg0 = TREE_VALUE (arglist); op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist)); op2 = mips_prepare_builtin_arg (icode, 3, &arglist);
arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); emit_insn (GEN_FCN (icode) (target, op0, op1, op2));
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);
return target; return target;
/* Paired Single Comparison. */ /* Paired Single Comparison. */
...@@ -10180,8 +10148,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -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_NGE_PS:
case MIPS_BUILTIN_ANY_CABS_LE_PS: case MIPS_BUILTIN_ANY_CABS_LE_PS:
case MIPS_BUILTIN_ANY_CABS_NGT_PS: case MIPS_BUILTIN_ANY_CABS_NGT_PS:
return mips_expand_ps_compare_builtin (MIPS_CMP_ANY, target, return mips_expand_ps_compare_builtin (MIPS_CMP_ANY, icode,
fcode, arglist); target, arglist);
/* Paired Single Comparison. */ /* Paired Single Comparison. */
case MIPS_BUILTIN_UPPER_C_F_PS: case MIPS_BUILTIN_UPPER_C_F_PS:
...@@ -10216,8 +10184,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -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_NGE_PS:
case MIPS_BUILTIN_UPPER_CABS_LE_PS: case MIPS_BUILTIN_UPPER_CABS_LE_PS:
case MIPS_BUILTIN_UPPER_CABS_NGT_PS: case MIPS_BUILTIN_UPPER_CABS_NGT_PS:
return mips_expand_ps_compare_builtin (MIPS_CMP_UPPER, target, return mips_expand_ps_compare_builtin (MIPS_CMP_UPPER, icode,
fcode, arglist); target, arglist);
/* Paired Single Comparison. */ /* Paired Single Comparison. */
case MIPS_BUILTIN_LOWER_C_F_PS: case MIPS_BUILTIN_LOWER_C_F_PS:
...@@ -10252,8 +10220,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -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_NGE_PS:
case MIPS_BUILTIN_LOWER_CABS_LE_PS: case MIPS_BUILTIN_LOWER_CABS_LE_PS:
case MIPS_BUILTIN_LOWER_CABS_NGT_PS: case MIPS_BUILTIN_LOWER_CABS_NGT_PS:
return mips_expand_ps_compare_builtin (MIPS_CMP_LOWER, target, return mips_expand_ps_compare_builtin (MIPS_CMP_LOWER, icode,
fcode, arglist); target, arglist);
/* Paired Single Comparison. */ /* Paired Single Comparison. */
case MIPS_BUILTIN_ALL_C_F_PS: case MIPS_BUILTIN_ALL_C_F_PS:
...@@ -10288,8 +10256,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -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_NGE_PS:
case MIPS_BUILTIN_ALL_CABS_LE_PS: case MIPS_BUILTIN_ALL_CABS_LE_PS:
case MIPS_BUILTIN_ALL_CABS_NGT_PS: case MIPS_BUILTIN_ALL_CABS_NGT_PS:
return mips_expand_ps_compare_builtin (MIPS_CMP_ALL, target, return mips_expand_ps_compare_builtin (MIPS_CMP_ALL, icode,
fcode, arglist); target, arglist);
/* Four Single Comparison. */ /* Four Single Comparison. */
case MIPS_BUILTIN_ANY_C_F_4S: case MIPS_BUILTIN_ANY_C_F_4S:
...@@ -10324,8 +10292,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -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_NGE_4S:
case MIPS_BUILTIN_ANY_CABS_LE_4S: case MIPS_BUILTIN_ANY_CABS_LE_4S:
case MIPS_BUILTIN_ANY_CABS_NGT_4S: case MIPS_BUILTIN_ANY_CABS_NGT_4S:
return mips_expand_4s_compare_builtin (MIPS_CMP_ANY, target, return mips_expand_4s_compare_builtin (MIPS_CMP_ANY, icode,
fcode, arglist); target, arglist);
/* Four Single Comparison. */ /* Four Single Comparison. */
case MIPS_BUILTIN_ALL_C_F_4S: case MIPS_BUILTIN_ALL_C_F_4S:
...@@ -10360,8 +10328,8 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -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_NGE_4S:
case MIPS_BUILTIN_ALL_CABS_LE_4S: case MIPS_BUILTIN_ALL_CABS_LE_4S:
case MIPS_BUILTIN_ALL_CABS_NGT_4S: case MIPS_BUILTIN_ALL_CABS_NGT_4S:
return mips_expand_4s_compare_builtin (MIPS_CMP_ALL, target, return mips_expand_4s_compare_builtin (MIPS_CMP_ALL, icode,
fcode, arglist); target, arglist);
/* Single/Double Compare Absolute. */ /* Single/Double Compare Absolute. */
case MIPS_BUILTIN_CABS_F_S: case MIPS_BUILTIN_CABS_F_S:
...@@ -10396,7 +10364,7 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -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_NGE_D:
case MIPS_BUILTIN_CABS_LE_D: case MIPS_BUILTIN_CABS_LE_D:
case MIPS_BUILTIN_CABS_NGT_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. */ /* Conditional Move on True. */
case MIPS_BUILTIN_MOVT_C_F_PS: case MIPS_BUILTIN_MOVT_C_F_PS:
...@@ -10431,8 +10399,7 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -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_NGE_PS:
case MIPS_BUILTIN_MOVT_CABS_LE_PS: case MIPS_BUILTIN_MOVT_CABS_LE_PS:
case MIPS_BUILTIN_MOVT_CABS_NGT_PS: case MIPS_BUILTIN_MOVT_CABS_NGT_PS:
return mips_expand_ps_cond_move_builtin (MIPS_CMP_MOVT, target, return mips_expand_ps_cond_move_builtin (true, icode, target, arglist);
fcode, arglist);
/* Conditional Move on False. */ /* Conditional Move on False. */
case MIPS_BUILTIN_MOVF_C_F_PS: case MIPS_BUILTIN_MOVF_C_F_PS:
...@@ -10467,8 +10434,7 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, ...@@ -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_NGE_PS:
case MIPS_BUILTIN_MOVF_CABS_LE_PS: case MIPS_BUILTIN_MOVF_CABS_LE_PS:
case MIPS_BUILTIN_MOVF_CABS_NGT_PS: case MIPS_BUILTIN_MOVF_CABS_NGT_PS:
return mips_expand_ps_cond_move_builtin (MIPS_CMP_MOVF, target, return mips_expand_ps_cond_move_builtin (false, icode, target, arglist);
fcode, arglist);
default: default:
break; break;
...@@ -10654,348 +10620,162 @@ mips_init_builtins (void) ...@@ -10654,348 +10620,162 @@ mips_init_builtins (void)
} }
} }
/* This performs a paired single compare, and then a conditional move based /* Expand a __builtin_mips_movt_*_ps() or __builtin_mips_movf_*_ps()
on the result of that compare. CMP_CHOICE is the kind of comparison we function (MOVE_ON_TRUE says which). ARGLIST is the list of arguments
want. TARGET is a suggestion of where to put the result. FCODE is the to the function and ICODE says which instruction should be used to
function code. ARGLIST is the list of arguments. The return value is compare the first two arguments. TARGET, if nonnull, suggests a
the result of the conditional move. */ good place to put the result. */
static rtx static rtx
mips_expand_ps_cond_move_builtin (enum mips_cmp_choice cmp_choice, mips_expand_ps_cond_move_builtin (bool move_on_true, enum insn_code icode,
rtx target, unsigned int fcode, rtx target, tree arglist)
tree arglist)
{ {
rtx pat; rtx cmp_result, op0, op1;
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)) cmp_result = mips_prepare_builtin_target (icode, 0, 0);
op0 = copy_to_mode_reg (mode0, op0); op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
if (!(*insn_data[icode].operand[2].predicate) (op1, mode1)) emit_insn (GEN_FCN (icode) (cmp_result, op0, op1));
op1 = copy_to_mode_reg (mode1, op1);
/* temp_target is the result of the comparison. */
temp_target = gen_reg_rtx (tmode);
pat = GEN_FCN (icode) (temp_target, op0, op1);
if (!pat)
return 0;
emit_insn (pat);
icode = CODE_FOR_mips_cond_move_tf_ps; icode = CODE_FOR_mips_cond_move_tf_ps;
tmode = insn_data[icode].operand[0].mode; target = mips_prepare_builtin_target (icode, 0, target);
if (move_on_true)
if (target == 0
|| GET_MODE (target) != tmode
|| !(*insn_data[icode].operand[0].predicate) (target, tmode))
target = gen_reg_rtx (tmode);
/* Let op2 be the same as the tmode */
if (!(*insn_data[icode].operand[0].predicate) (op2, tmode))
op2 = copy_to_mode_reg (tmode, op2);
/* Let op3 be the same as the tmode */
if (!(*insn_data[icode].operand[0].predicate) (op3, tmode))
op3 = copy_to_mode_reg (tmode, op3);
/* Copy op2 to target */
emit_insn (gen_rtx_SET (tmode, target, op2));
switch (cmp_choice)
{ {
case MIPS_CMP_MOVT: op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
src1 = op3; op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
src2 = target;
break;
case MIPS_CMP_MOVF:
src1 = target;
src2 = op3;
break;
default:
return 0;
} }
else
emit_insn (gen_mips_cond_move_tf_ps (target, src1, src2, temp_target)); {
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; return target;
} }
/* This performs two paired single compares, and returns an boolean value to /* Use comparison instruction PAT to set condition-code register REG.
represent the result of the compare. CMP_CHOICE is the kind of comparison If NONZERO_IF_EQUAL_P, return an rtx that is 1 if the new value of
we want. TARGET is a suggestion of where to put the result. FCODE is REG equals CONSTANT and 0 otherwise. Return the inverse if
the builtin function code. ARGLIST is the list of arguments. The !NONZERO_IF_EQUAL_P. TARGET, if nonnull, suggests a good place
return value is the result of the compare. */ for the result. */
rtx static rtx
mips_expand_4s_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target, mips_expand_compare_builtin (bool nonzero_if_equal_p, rtx target,
unsigned int fcode, tree arglist) rtx pat, rtx reg, int constant)
{ {
rtx pat; rtx label1, label2, if_then_else;
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;
int compare_value;
if (target == 0 || GET_MODE (target) != SImode) if (target == 0 || GET_MODE (target) != SImode)
target = gen_reg_rtx (SImode); target = gen_reg_rtx (SImode);
icode = mips_bdesc[fcode].icode; /* First assume that REG == CONSTANT. */
arg0 = TREE_VALUE (arglist); emit_move_insn (target, nonzero_if_equal_p ? const1_rtx : const0_rtx);
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;
/* We fake the value of CCV4 to be:
0 if all registers are false.
-1 if all registers are true.
an indeterminate value otherse.
Thus, we can map "enum mips_cmp_choice" to RTL comparison operators:
MIPS_CMP_ANY -> (NE 0)
MIPS_CMP_ALL -> (EQ -1).
However, because MIPS doesn't have "branch_all" instructions,
for MIPS_CMP_ALL, we will use (NE -1) and reverse the assignment of
the target to 1 first and then 0. */
switch (cmp_choice)
{
case MIPS_CMP_ANY:
compare_value = 0;
break;
case MIPS_CMP_ALL:
compare_value = -1;
break;
default:
return 0;
}
if (cmp_choice == MIPS_CMP_ALL)
emit_move_insn (target, const1_rtx);
else
emit_move_insn (target, const0_rtx);
/* Branch to LABEL1 if REG != CONSTANT. */
emit_insn (pat); emit_insn (pat);
label1 = gen_label_rtx (); label1 = gen_label_rtx ();
label2 = gen_label_rtx (); label2 = gen_label_rtx ();
if_then_else if_then_else
= gen_rtx_IF_THEN_ELSE (VOIDmode, = gen_rtx_IF_THEN_ELSE (VOIDmode,
gen_rtx_fmt_ee (NE, CCV4mode, temp_target, gen_rtx_fmt_ee (NE, GET_MODE (reg),
GEN_INT (compare_value)), reg, GEN_INT (constant)),
gen_rtx_LABEL_REF (VOIDmode, label1), pc_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, if_then_else));
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
gen_rtx_LABEL_REF (VOIDmode, label2))); gen_rtx_LABEL_REF (VOIDmode, label2)));
emit_barrier (); emit_barrier ();
emit_label (label1); emit_label (label1);
if (cmp_choice == MIPS_CMP_ALL) /* Fix TARGET for REG != CONSTANT. */
emit_move_insn (target, const0_rtx); emit_move_insn (target, nonzero_if_equal_p ? const0_rtx : const1_rtx);
else
emit_move_insn (target, const1_rtx);
emit_label (label2); emit_label (label2);
return target; return target;
} }
/* This performs a single float or double float comparison. TARGET is a /* Read two scalar arguments from ARGLIST and use instruction ICODE to
suggestion of where to put the result. FCODE is the builtin function code. compare them. Return the result as a boolean SImode value. TARGET,
ARGLIST is the list of arguments. The return value is the result of the if nonnull, suggests a good place to put the result. */
compare. */
rtx rtx
mips_expand_compare_builtin (rtx target, unsigned int fcode, tree arglist) mips_expand_scalar_compare_builtin (enum insn_code icode, rtx target,
tree arglist)
{ {
rtx pat; rtx pat, cmp_result, op0, op1;
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; cmp_result = mips_prepare_builtin_target (icode, 0, 0);
arg0 = TREE_VALUE (arglist); op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist)); op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); pat = GEN_FCN (icode) (cmp_result, op0, op1);
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); return mips_expand_compare_builtin (false, target, pat, cmp_result, 0);
}
if (!(*insn_data[icode].operand[1].predicate) (op0, mode0)) /* Read four V2SF arguments from ARGLIST and use instruction ICODE to
op0 = copy_to_mode_reg (mode0, op0); 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. */
if (!(*insn_data[icode].operand[2].predicate) (op1, mode1)) rtx
op1 = copy_to_mode_reg (mode1, op1); mips_expand_4s_compare_builtin (enum mips_cmp_choice cmp_choice,
enum insn_code icode, rtx target,
tree arglist)
{
rtx pat, cmp_result, op0, op1, op2, op3;
int compare_value;
pat = GEN_FCN (icode) (temp_target, op0, op1); cmp_result = mips_prepare_builtin_target (icode, 0, 0);
if (!pat) op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
return 0; 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);
emit_move_insn (target, const0_rtx); /* We fake the value of CCV4 to be:
emit_insn (pat); 0 if all registers are false.
-1 if all registers are true.
an indeterminate value otherse.
label1 = gen_label_rtx (); Thus, we can map "enum mips_cmp_choice" to RTL comparison operators:
label2 = gen_label_rtx (); MIPS_CMP_ANY -> (NE 0)
MIPS_CMP_ALL -> (EQ -1).
test_code = NE; However, because MIPS doesn't have "branch_all" instructions,
if_then_else for MIPS_CMP_ALL, we will use (NE -1) and reverse the assignment of
= gen_rtx_IF_THEN_ELSE (VOIDmode, the target to 1 first and then 0. */
gen_rtx_fmt_ee (test_code, CCmode, switch (cmp_choice)
temp_target, const0_rtx), {
gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx); case MIPS_CMP_ANY:
compare_value = 0;
break;
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else)); case MIPS_CMP_ALL:
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, compare_value = -1;
gen_rtx_LABEL_REF (VOIDmode, label2))); break;
emit_barrier (); default:
emit_label (label1); abort ();
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 paired single compare, and returns an boolean value to /* Like mips_expand_4s_compare_builtin, but compares two V2SF vectors rather
represent the result of the compare. CMP_CHOICE is the kind of comparison than four. The arguments and return type are otherwise the same. */
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 rtx
mips_expand_ps_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target, mips_expand_ps_compare_builtin (enum mips_cmp_choice cmp_choice,
unsigned int fcode, tree arglist) enum insn_code icode, rtx target,
tree arglist)
{ {
rtx pat; rtx pat, cmp_result, op0, op1;
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;
int compare_value; int compare_value;
if (target == 0 || GET_MODE (target) != SImode) cmp_result = mips_prepare_builtin_target (icode, 0, 0);
target = gen_reg_rtx (SImode); op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
icode = mips_bdesc[fcode].icode; pat = GEN_FCN (icode) (cmp_result, op0, op1);
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;
/* We fake the value of CCV2 to be: /* We fake the value of CCV2 to be:
0 if all registers are false. 0 if all registers are false.
...@@ -11019,12 +10799,12 @@ mips_expand_ps_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target, ...@@ -11019,12 +10799,12 @@ mips_expand_ps_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target,
break; break;
case MIPS_CMP_UPPER: 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; compare_value = 0;
break; break;
case MIPS_CMP_LOWER: 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; compare_value = 0;
break; break;
...@@ -11033,41 +10813,11 @@ mips_expand_ps_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target, ...@@ -11033,41 +10813,11 @@ mips_expand_ps_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target,
break; break;
default: default:
return 0; abort ();
} }
if (cmp_choice == MIPS_CMP_ALL) return mips_expand_compare_builtin (cmp_choice == MIPS_CMP_ALL,
emit_move_insn (target, const1_rtx); target, pat, cmp_result, compare_value);
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;
} }
#include "gt-mips.h" #include "gt-mips.h"
...@@ -3385,8 +3385,5 @@ enum mips_cmp_choice ...@@ -3385,8 +3385,5 @@ enum mips_cmp_choice
MIPS_CMP_LOWER, /* Check if the lower one of two results is true. */ MIPS_CMP_LOWER, /* Check if the lower one of two results is true. */
MIPS_CMP_ALL, /* Check if all results are 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 MIPS_CMP_MAX
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment