|| code == UNORDERED);
}
-/* Return 1 if OP is a comparison operation that is valid for an scc insn.
- We check the opcode against the mode of the CC value and disallow EQ or
- NE comparisons for integers. */
+/* Return 1 if OP is a comparison operation that is valid for an scc
+ insn: it must be a positive comparison. */
int
scc_comparison_operator (op, mode)
rtx op;
enum machine_mode mode;
{
- enum rtx_code code = GET_CODE (op);
- enum machine_mode cc_mode;
-
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_RTX_CLASS (code) != '<')
- return 0;
-
- cc_mode = GET_MODE (XEXP (op, 0));
- if (GET_MODE_CLASS (cc_mode) != MODE_CC)
- return 0;
-
- validate_condition_mode (code, cc_mode);
-
- if (code == NE && cc_mode != CCFPmode)
- return 0;
-
- return 1;
+ return branch_positive_comparison_operator (op, mode);
}
int
validate_condition_mode (code, cc_mode);
+ /* When generating a sCOND operation, only positive conditions are
+ allowed. */
+ if (scc_p && code != EQ && code != GT && code != LT && code != UNORDERED
+ && code != GTU && code != LTU)
+ abort ();
+
switch (code)
{
case NE:
/* %c is output_addr_const if a CONSTANT_ADDRESS_P, otherwise
output_operand. */
- case 'D':
- /* There used to be a comment for 'C' reading "This is an
- optional cror needed for certain floating-point
- comparisons. Otherwise write nothing." */
-
- /* Similar, except that this is for an scc, so we must be able to
- encode the test in a single bit that is one. We do the above
- for any LE, GE, GEU, or LEU and invert the bit for NE. */
- if (GET_CODE (x) == LE || GET_CODE (x) == GE
- || GET_CODE (x) == LEU || GET_CODE (x) == GEU)
- {
- int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
-
- fprintf (file, "cror %d,%d,%d\n\t", base_bit + 3,
- base_bit + 2,
- base_bit + (GET_CODE (x) == GE || GET_CODE (x) == GEU));
- }
-
- else if (GET_CODE (x) == NE)
- {
- int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
-
- fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 3,
- base_bit + 2, base_bit + 2);
- }
- else if (TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT
- && GET_CODE (x) == EQ
- && GET_MODE (XEXP (x, 0)) == CCFPmode)
- {
- int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
-
- fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 1,
- base_bit + 1, base_bit + 1);
- }
- return;
-
case 'E':
/* X is a CR register. Print the number of the EQ bit of the CR */
if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
{
rtx condition_rtx;
enum machine_mode op_mode;
+ enum rtx_code cond_code;
condition_rtx = rs6000_generate_compare (code);
+ cond_code = GET_CODE (condition_rtx);
+
+ if (cond_code == NE
+ || cond_code == GE || cond_code == LE
+ || cond_code == GEU || cond_code == LEU
+ || cond_code == ORDERED || cond_code == UNGE || cond_code == UNLE)
+ {
+ rtx not_result = gen_reg_rtx (CCEQmode);
+ rtx not_op, rev_cond_rtx;
+ enum machine_mode cc_mode;
+
+ cc_mode = GET_MODE (XEXP (condition_rtx, 0));
+
+ rev_cond_rtx = gen_rtx (rs6000_reverse_condition (cc_mode, cond_code),
+ SImode, XEXP (condition_rtx, 0), const0_rtx);
+ not_op = gen_rtx_COMPARE (CCEQmode, rev_cond_rtx, const0_rtx);
+ emit_insn (gen_rtx_SET (VOIDmode, not_result, not_op));
+ condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx);
+ }
op_mode = GET_MODE (rs6000_compare_op0);
if (op_mode == VOIDmode)
DONE;
}")
-;; A > 0 is best done using the portable sequence, so fail in that case.
-(define_expand "sgt"
+;; A >= 0 is best done the portable way for A an integer.
+(define_expand "sge"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
""
"
&& (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
FAIL;
- rs6000_emit_sCOND (GT, operands[0]);
+ rs6000_emit_sCOND (GE, operands[0]);
DONE;
}")
-;; A < 0 is best done in the portable way for A an integer.
-(define_expand "slt"
+;; A > 0 is best done using the portable sequence, so fail in that case.
+(define_expand "sgt"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
""
"
{
- if (! rs6000_compare_fp_p
+ if (! rs6000_compare_fp_p
&& (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
FAIL;
- rs6000_emit_sCOND (LT, operands[0]);
+ rs6000_emit_sCOND (GT, operands[0]);
DONE;
}")
-;; A >= 0 is best done the portable way for A an integer.
-(define_expand "sge"
+;; A <= 0 is best done the portable way for A an integer.
+(define_expand "sle"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
""
"
&& (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
FAIL;
- rs6000_emit_sCOND (GE, operands[0]);
+ rs6000_emit_sCOND (LE, operands[0]);
DONE;
}")
-;; A <= 0 is best done the portable way for A an integer.
-(define_expand "sle"
+;; A < 0 is best done in the portable way for A an integer.
+(define_expand "slt"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
""
"
{
- if (! rs6000_compare_fp_p
+ if (! rs6000_compare_fp_p
&& (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
FAIL;
- rs6000_emit_sCOND (LE, operands[0]);
+ rs6000_emit_sCOND (LT, operands[0]);
DONE;
}")
+(define_expand "sgeu"
+ [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+ ""
+ "{ rs6000_emit_sCOND (GEU, operands[0]); DONE; }")
+
(define_expand "sgtu"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
""
"{ rs6000_emit_sCOND (GTU, operands[0]); DONE; }")
+(define_expand "sleu"
+ [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+ ""
+ "{ rs6000_emit_sCOND (LEU, operands[0]); DONE; }")
+
(define_expand "sltu"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
""
"{ rs6000_emit_sCOND (LTU, operands[0]); DONE; }")
-(define_expand "sgeu"
+(define_expand "sunordered"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
""
- "{ rs6000_emit_sCOND (GEU, operands[0]); DONE; }")
+ "{ rs6000_emit_sCOND (UNORDERED, operands[0]); DONE; }")
-(define_expand "sleu"
+(define_expand "sordered"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
""
- "{ rs6000_emit_sCOND (LEU, operands[0]); DONE; }")
+ "{ rs6000_emit_sCOND (ORDERED, operands[0]); DONE; }")
+
+(define_expand "suneq"
+ [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+ ""
+ "{ rs6000_emit_sCOND (UNEQ, operands[0]); DONE; }")
+
+(define_expand "sunge"
+ [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+ ""
+ "{ rs6000_emit_sCOND (UNGE, operands[0]); DONE; }")
+
+(define_expand "sungt"
+ [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+ ""
+ "{ rs6000_emit_sCOND (UNGT, operands[0]); DONE; }")
+
+(define_expand "sunle"
+ [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+ ""
+ "{ rs6000_emit_sCOND (UNLE, operands[0]); DONE; }")
+
+(define_expand "sunlt"
+ [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+ ""
+ "{ rs6000_emit_sCOND (UNLT, operands[0]); DONE; }")
+
+(define_expand "sltgt"
+ [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+ ""
+ "{ rs6000_emit_sCOND (LTGT, operands[0]); DONE; }")
+
\f
;; Here are the actual compare insns.
(define_insn "*cmpsi_internal1"
[(match_operand 2 "cc_reg_operand" "y")
(const_int 0)]))]
""
- "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
+ "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
[(set_attr "type" "mfcr")
(set_attr "length" "12")])
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_OV))]
"TARGET_ISEL"
- "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%t1,1"
+ "mfcr %0\;{rlinm|rlwinm} %0,%0,%t1,1"
[(set_attr "type" "mfcr")
(set_attr "length" "12")])
[(match_operand 2 "cc_reg_operand" "y")
(const_int 0)]))]
"TARGET_POWERPC64"
- "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
+ "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
[(set_attr "type" "mfcr")
(set_attr "length" "12")])
(match_op_dup 1 [(match_dup 2) (const_int 0)]))]
"! TARGET_POWERPC64"
"@
- %D1mfcr %3\;{rlinm.|rlwinm.} %3,%3,%J1,1
+ mfcr %3\;{rlinm.|rlwinm.} %3,%3,%J1,1
#"
[(set_attr "type" "delayed_compare")
(set_attr "length" "12,16")])
operands[4] = GEN_INT (count);
operands[5] = GEN_INT (put_bit);
- return \"%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%4,%5,%5\";
+ return \"mfcr %0\;{rlinm|rlwinm} %0,%0,%4,%5,%5\";
}"
[(set_attr "type" "mfcr")
(set_attr "length" "12")])
operands[5] = GEN_INT (count);
operands[6] = GEN_INT (put_bit);
- return \"%D1mfcr %4\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
+ return \"mfcr %4\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
}"
[(set_attr "type" "delayed_compare")
(set_attr "length" "12,16")])
[(match_operand 5 "cc_reg_operand" "y")
(const_int 0)]))]
"REGNO (operands[2]) != REGNO (operands[5])"
- "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
+ "mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
[(set_attr "type" "mfcr")
(set_attr "length" "20")])
[(match_operand 5 "cc_reg_operand" "y")
(const_int 0)]))]
"TARGET_POWERPC64 && REGNO (operands[2]) != REGNO (operands[5])"
- "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
+ "mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
[(set_attr "type" "mfcr")
(set_attr "length" "20")])