Commit c5defebb by Richard Kenner

*** empty log message ***

From-SVN: r691
parent 5f61baa4
...@@ -516,6 +516,9 @@ scc_comparison_operator (op, mode) ...@@ -516,6 +516,9 @@ scc_comparison_operator (op, mode)
&& (cc_mode != CCUNSmode)) && (cc_mode != CCUNSmode))
return 0; return 0;
if (cc_mode == CCEQmode && code != EQ && code != NE)
return 0;
return 1; return 1;
} }
...@@ -607,6 +610,12 @@ ccr_bit (op, scc_p) ...@@ -607,6 +610,12 @@ ccr_bit (op, scc_p)
cc_regnum = REGNO (XEXP (op, 0)); cc_regnum = REGNO (XEXP (op, 0));
base_bit = 4 * (cc_regnum - 68); 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) switch (code)
{ {
case NE: case NE:
...@@ -817,6 +826,14 @@ print_operand (file, x, code) ...@@ -817,6 +826,14 @@ print_operand (file, x, code)
fprintf (file, "%d", 32 - 4 * (REGNO (x) - 68)); fprintf (file, "%d", 32 - 4 * (REGNO (x) - 68));
return; 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': case 'R':
/* X is a CR register. Print the mask for `mtcrf'. */ /* X is a CR register. Print the mask for `mtcrf'. */
if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
......
...@@ -1245,22 +1245,26 @@ struct rs6000_args {int words, fregno, nargs_prototype; }; ...@@ -1245,22 +1245,26 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
/* Add any extra modes needed to represent the condition code. /* Add any extra modes needed to represent the condition code.
For the RS/6000, we need separate modes when unsigned (logical) comparisons 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 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, /* 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 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 should be used. CCUNSmode should be used for unsigned comparisons.
PLUS, MINUS, or NEG. CCmode should be used when no special processing is CCEQmode should be used when we are doing an inequality comparison on
needed. */ the result of a comparison. CCmode should be used in all other cases. */
#define SELECT_CC_MODE(OP,X) \ #define SELECT_CC_MODE(OP,X) \
(GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode \ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode \
: ((OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU \ : (OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU ? CCUNSmode \
? CCUNSmode : CCmode)) : (((OP) == EQ || (OP) == NE) && GET_RTX_CLASS (GET_CODE (X)) == '<' \
? CCEQmode : CCmode))
/* Define the information needed to generate branch and scc insns. This is /* 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 stored from the compare operation. Note that we can't use "rtx" here
......
...@@ -3294,7 +3294,9 @@ ...@@ -3294,7 +3294,9 @@
;; way the machine works. ;; way the machine works.
;; ;;
;; Note that this is probably faster if we can put an insn between the ;; 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 "" (define_insn ""
[(set (match_operand:SI 0 "gen_reg_operand" "=r") [(set (match_operand:SI 0 "gen_reg_operand" "=r")
(match_operator:SI 1 "scc_comparison_operator" (match_operator:SI 1 "scc_comparison_operator"
...@@ -3369,6 +3371,52 @@ ...@@ -3369,6 +3371,52 @@
}" }"
[(set_attr "type" "delayed_compare")]) [(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. ;; There are some scc insns that can be done directly, without a compare.
;; These are faster because they don't involve the communications between ;; 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 ;; 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