Commit c5defebb by Richard Kenner

*** empty log message ***

From-SVN: r691
parent 5f61baa4
......@@ -516,6 +516,9 @@ scc_comparison_operator (op, mode)
&& (cc_mode != CCUNSmode))
return 0;
if (cc_mode == CCEQmode && code != EQ && code != NE)
return 0;
return 1;
}
......@@ -607,6 +610,12 @@ ccr_bit (op, scc_p)
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:
......@@ -817,6 +826,14 @@ print_operand (file, x, code)
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)))
......
......@@ -1245,22 +1245,26 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
/* 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
......
......@@ -3294,7 +3294,9 @@
;; 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"
......@@ -3369,6 +3371,52 @@
}"
[(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
......
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