&& (cc_mode != CCUNSmode))
return 0;
+ if (cc_mode == CCEQmode && code != EQ && code != NE)
+ return 0;
+
return 1;
}
\f
cc_regnum = REGNO (XEXP (op, 0));
base_bit = 4 * (cc_regnum - 68);
+ /* In CCEQmode cases we have made sure that the result is always in the
+ third bit of the CR field. */
+
+ if (cc_mode == CCEQmode)
+ return base_bit + 3;
+
switch (code)
{
case NE:
fprintf (file, "%d", 32 - 4 * (REGNO (x) - 68));
return;
+ case 'E':
+ /* X is a CR register. Print the number of the third bit of the CR */
+ if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
+ output_operand_lossage ("invalid %%E value");
+
+ fprintf(file, "%d", 4 * (REGNO (x) - 68) + 3);
+ break;
+
case 'R':
/* X is a CR register. Print the mask for `mtcrf'. */
if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
/* Add any extra modes needed to represent the condition code.
For the RS/6000, we need separate modes when unsigned (logical) comparisons
- are being done and we need a separate mode for floating-point. */
+ are being done and we need a separate mode for floating-point. We also
+ use a mode for the case when we are comparing the results of two
+ comparisons. */
-#define EXTRA_CC_MODES CCUNSmode, CCFPmode
+#define EXTRA_CC_MODES CCUNSmode, CCFPmode, CCEQmode
/* Define the names for the modes specified above. */
-#define EXTRA_CC_NAMES "CCUNS", "CCFP"
+#define EXTRA_CC_NAMES "CCUNS", "CCFP", "CCEQ"
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. For floating-point, CCFPmode
- should be used. CC_NOOVmode should be used when the first operand is a
- PLUS, MINUS, or NEG. CCmode should be used when no special processing is
- needed. */
+ should be used. CCUNSmode should be used for unsigned comparisons.
+ CCEQmode should be used when we are doing an inequality comparison on
+ the result of a comparison. CCmode should be used in all other cases. */
+
#define SELECT_CC_MODE(OP,X) \
(GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode \
- : ((OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU \
- ? CCUNSmode : CCmode))
+ : (OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU ? CCUNSmode \
+ : (((OP) == EQ || (OP) == NE) && GET_RTX_CLASS (GET_CODE (X)) == '<' \
+ ? CCEQmode : CCmode))
/* Define the information needed to generate branch and scc insns. This is
stored from the compare operation. Note that we can't use "rtx" here
;; way the machine works.
;;
;; Note that this is probably faster if we can put an insn between the
-;; mfcr and rlinm, but this is tricky. Let's leave it for now.
+;; mfcr and rlinm, but this is tricky. Let's leave it for now. In most
+;; cases the insns below which don't use an intermediate CR field will
+;; be used instead.
(define_insn ""
[(set (match_operand:SI 0 "gen_reg_operand" "=r")
(match_operator:SI 1 "scc_comparison_operator"
}"
[(set_attr "type" "delayed_compare")])
+;; If we are comparing the result of two comparisons, this can be done
+;; using creqv or crxor.
+
+(define_insn ""
+ [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y")
+ (compare:CCEQ (match_operator 1 "scc_comparison_operator"
+ [(match_operand 2 "cc_reg_operand" "y")
+ (const_int 0)])
+ (match_operator 3 "scc_comparison_operator"
+ [(match_operand 4 "cc_reg_operand" "y")
+ (const_int 0)])))]
+ "REGNO (operands[2]) != REGNO (operands[4])"
+ "*
+{
+ enum rtx_code code1, code2;
+
+ code1 = GET_CODE (operands[1]);
+ code2 = GET_CODE (operands[3]);
+
+ if ((code1 == EQ || code1 == LT || code1 == GT
+ || code1 == LTU || code1 == GTU
+ || (code1 != NE && GET_MODE (operands[2]) == CCFPmode))
+ !=
+ (code2 == EQ || code2 == LT || code2 == GT
+ || code2 == LTU || code2 == GTU
+ || (code2 != NE && GET_MODE (operands[4]) == CCFPmode)))
+ return \"%C1%C3crxor %E0,%j1,%j3\";
+ else
+ return \"%C1%C3creqv %E0,%j1,%j3\";
+}")
+
+;; There is a 3 cycle delay between consecutive mfcr instructions
+;; so it is useful to combine 2 scc instructions to use only one mfcr.
+
+(define_peephole
+ [(set (match_operand:SI 0 "gen_reg_operand" "=r")
+ (match_operator:SI 1 "scc_comparison_operator"
+ [(match_operand 2 "cc_reg_operand" "y")
+ (const_int 0)]))
+ (set (match_operand:SI 3 "gen_reg_operand" "=r")
+ (match_operator:SI 4 "scc_comparison_operator"
+ [(match_operand 5 "cc_reg_operand" "y")
+ (const_int 0)]))]
+ "REGNO (operands[2]) != REGNO (operands[5])"
+ "%D1%D4mfcr %3\;rlinm %0,%3,%J1,31,31\;rlinm %3,%3,%J4,31,31")
+
;; There are some scc insns that can be done directly, without a compare.
;; These are faster because they don't involve the communications between
;; the FXU and branch units. In fact, we will be replacing all of the