Commit 423c1189 by Aldy Hernandez Committed by Aldy Hernandez

rs6000.md (UNSPEC_MV_CR_GT): New constant.

        * config/rs6000/rs6000.md (UNSPEC_MV_CR_GT): New constant.
        (move_from_CR_gt_bit): New.
        (cceq_ior_compare): Name previously unnamed pattern.  Disable for
        E500.
        (cceq_rev_compare): Name previously unnamed pattern.  Allow for
        E500.

        * config/rs6000/spe.md (cmpsfeq_gpr): Rewrite as unspec.
        (tstsfeq_gpr): Same.
        (cmpsfgt_gpr): Same.
        (tstsfgt_gpr): Same.
        (cmpsflt_gpr): Same.
        (tstsflt_gpr): Same.
        (e500_cceq_ior_compare): New.
        (e500_flip_gt_bit): New.

        * config/rs6000/rs6000.c (ccr_bit): Remove E500 specific code.
        (print_operand): Add 'c' and 'D'.
        (rs6000_generate_compare): Rewrite to generate correct rtl.
        (rs6000_emit_sCOND): Handle E500.
        (output_cbranch): Adjust for changes in rs6000_generate_compare.
        (output_e500_flip_gt_bit): New.

        * config/rs6000/rs6000-protos.h (output_e500_flip_gt_bit):
        Protoize.

From-SVN: r80876
parent f5310108
2004-04-19 Aldy Hernandez <aldyh@redhat.com>
* config/rs6000/rs6000.md (UNSPEC_MV_CR_GT): New constant.
(move_from_CR_gt_bit): New.
(cceq_ior_compare): Name previously unnamed pattern. Disable for
E500.
(cceq_rev_compare): Name previously unnamed pattern. Allow for
E500.
* config/rs6000/spe.md (cmpsfeq_gpr): Rewrite as unspec.
(tstsfeq_gpr): Same.
(cmpsfgt_gpr): Same.
(tstsfgt_gpr): Same.
(cmpsflt_gpr): Same.
(tstsflt_gpr): Same.
(e500_cceq_ior_compare): New.
(e500_flip_gt_bit): New.
* config/rs6000/rs6000.c (ccr_bit): Remove E500 specific code.
(print_operand): Add 'c' and 'D'.
(rs6000_generate_compare): Rewrite to generate correct rtl.
(rs6000_emit_sCOND): Handle E500.
(output_cbranch): Adjust for changes in rs6000_generate_compare.
(output_e500_flip_gt_bit): New.
* config/rs6000/rs6000-protos.h (output_e500_flip_gt_bit):
Protoize.
2004-04-19 Eric Christopher <echristo@redhat.com>
* config/mips/mips.h (DWARF2_ADDR_SIZE): New.
......
......@@ -116,6 +116,7 @@ extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
extern void rs6000_emit_sCOND (enum rtx_code, rtx);
extern void rs6000_emit_cbranch (enum rtx_code, rtx);
extern char * output_cbranch (rtx, const char *, int, rtx);
extern char * output_e500_flip_gt_bit (rtx, rtx);
extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
......
......@@ -8798,14 +8798,8 @@ ccr_bit (rtx op, int scc_p)
switch (code)
{
case NE:
if (TARGET_E500 && !TARGET_FPRS
&& TARGET_HARD_FLOAT && cc_mode == CCFPmode)
return base_bit + 1;
return scc_p ? base_bit + 3 : base_bit + 2;
case EQ:
if (TARGET_E500 && !TARGET_FPRS
&& TARGET_HARD_FLOAT && cc_mode == CCFPmode)
return base_bit + 1;
return base_bit + 2;
case GT: case GTU: case UNLE:
return base_bit + 1;
......@@ -9025,6 +9019,26 @@ print_operand (FILE *file, rtx x, int code)
/* %c is output_addr_const if a CONSTANT_ADDRESS_P, otherwise
output_operand. */
case 'c':
/* X is a CR register. Print the number of the GT bit of the CR. */
if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
output_operand_lossage ("invalid %%E value");
else
fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO) + 1);
return;
case 'D':
/* Like 'J' but get to the GT bit. */
if (GET_CODE (x) != REG)
abort ();
/* Bit 1 is GT bit. */
i = 4 * (REGNO (x) - CR0_REGNO) + 1;
/* If we want bit 31, write a shift count of zero, not 32. */
fprintf (file, "%d", i == 31 ? 0 : i + 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)))
......@@ -9812,36 +9826,26 @@ rs6000_generate_compare (enum rtx_code code)
{
rtx cmp, or1, or2, or_result, compare_result2;
/* Note: The E500 comparison instructions set the GT bit (x +
1), on success. This explains the mess. */
switch (code)
{
case EQ:
case UNEQ:
case NE:
case LTGT:
case EQ: case UNEQ: case NE: case LTGT:
cmp = flag_finite_math_only
? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1)
: gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1);
break;
case GT:
case GTU:
case UNGT:
case UNGE:
case GE:
case GEU:
case GT: case GTU: case UNGT: case UNGE: case GE: case GEU:
cmp = flag_finite_math_only
? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1)
: gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1);
break;
case LT:
case LTU:
case UNLT:
case UNLE:
case LE:
case LEU:
case LT: case LTU: case UNLT: case UNLE: case LE: case LEU:
cmp = flag_finite_math_only
? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1)
......@@ -9855,8 +9859,6 @@ rs6000_generate_compare (enum rtx_code code)
/* Synthesize LE and GE from LT/GT || EQ. */
if (code == LE || code == GE || code == LEU || code == GEU)
{
/* Synthesize GE/LE frome GT/LT || EQ. */
emit_insn (cmp);
switch (code)
......@@ -9881,23 +9883,8 @@ rs6000_generate_compare (enum rtx_code code)
rs6000_compare_op1);
emit_insn (cmp);
/* The MC8540 FP compare instructions set the CR bits
differently than other PPC compare instructions. For
that matter, there is no generic test instruction, but a
testgt, testlt, and testeq. For a true condition, bit 2
is set (x1xx) in the CR. Following the traditional CR
values:
LT GT EQ OV
bit3 bit2 bit1 bit0
... bit 2 would be a GT CR alias, so later on we
look in the GT bits for the branch instructions.
However, we must be careful to emit correct RTL in
the meantime, so optimizations don't get confused. */
or1 = gen_rtx_NE (SImode, compare_result, const0_rtx);
or2 = gen_rtx_NE (SImode, compare_result2, const0_rtx);
or1 = gen_rtx_GT (SImode, compare_result, const0_rtx);
or2 = gen_rtx_GT (SImode, compare_result2, const0_rtx);
/* OR them together. */
cmp = gen_rtx_SET (VOIDmode, or_result,
......@@ -9909,16 +9896,10 @@ rs6000_generate_compare (enum rtx_code code)
}
else
{
/* We only care about 1 bit (x1xx), so map everything to NE to
maintain rtl sanity. We'll get to the right bit (x1xx) at
code output time. */
if (code == NE || code == LTGT)
/* Do the inverse here because we have no cmpne
instruction. We use the cmpeq instruction and expect
to get a 0 instead. */
code = EQ;
else
code = NE;
else
code = EQ;
}
emit_insn (cmp);
......@@ -9983,6 +9964,24 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result)
condition_rtx = rs6000_generate_compare (code);
cond_code = GET_CODE (condition_rtx);
if (TARGET_E500 && rs6000_compare_fp_p
&& !TARGET_FPRS && TARGET_HARD_FLOAT)
{
rtx t;
PUT_MODE (condition_rtx, SImode);
t = XEXP (condition_rtx, 0);
if (cond_code != NE && cond_code != EQ)
abort ();
if (cond_code == NE)
emit_insn (gen_e500_flip_gt_bit (t, t));
emit_insn (gen_move_from_CR_gt_bit (result, t));
return;
}
if (cond_code == NE
|| cond_code == GE || cond_code == LE
|| cond_code == GEU || cond_code == LEU
......@@ -10079,9 +10078,9 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn)
to the GT bit. */
if (code == EQ)
/* Opposite of GT. */
code = UNLE;
else if (code == NE)
code = GT;
else if (code == NE)
code = UNLE;
else
abort ();
}
......@@ -10160,6 +10159,25 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn)
return string;
}
/* Return the string to flip the GT bit on a CR. */
char *
output_e500_flip_gt_bit (rtx dst, rtx src)
{
static char string[64];
int a, b;
if (GET_CODE (dst) != REG || ! CR_REGNO_P (REGNO (dst))
|| GET_CODE (src) != REG || ! CR_REGNO_P (REGNO (src)))
abort ();
/* GT bit. */
a = 4 * (REGNO (dst) - CR0_REGNO) + 1;
b = 4 * (REGNO (src) - CR0_REGNO) + 1;
sprintf (string, "crnot %d,%d", a, b);
return string;
}
/* Emit a conditional move: move TRUE_COND to DEST if OP of the
operands of the last comparison is nonzero/true, FALSE_COND if it
is zero/false. Return 0 if the hardware has no such operation. */
......
......@@ -50,6 +50,7 @@
(UNSPEC_TLSGOTTPREL 28)
(UNSPEC_TLSTLS 29)
(UNSPEC_FIX_TRUNC_TF 30) ; fadd, rounding towards zero
(UNSPEC_MV_CR_GT 31) ; move_from_CR_gt_bit
])
;;
......@@ -11290,6 +11291,15 @@
(const_string "mfcr")))
(set_attr "length" "12")])
;; Same as above, but get the GT bit.
(define_insn "move_from_CR_gt_bit"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_GT))]
"TARGET_E500"
"mfcr %0\;{rlinm|rlwinm} %0,%0,%D1,1"
[(set_attr "type" "mfcr")
(set_attr "length" "12")])
;; Same as above, but get the OV/ORDERED bit.
(define_insn "move_from_CR_ov_bit"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
......@@ -13620,7 +13630,7 @@
; which are generated by the branch logic.
; Prefer destructive operations where BT = BB (for crXX BT,BA,BB)
(define_insn ""
(define_insn "*cceq_ior_compare"
[(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
(compare:CCEQ (match_operator:SI 1 "boolean_operator"
[(match_operator:SI 2
......@@ -13634,7 +13644,7 @@
"cc_reg_operand" "0,y")
(const_int 0)])])
(const_int 1)))]
""
"!(TARGET_E500 && TARGET_HARD_FLOAT && !TARGET_FPRS)"
"cr%q1 %E0,%j2,%j4"
[(set_attr "type" "cr_logical,delayed_cr")])
......@@ -13658,7 +13668,7 @@
"cr%q1 %E0,%j2,%j4"
[(set_attr "type" "cr_logical,delayed_cr")])
(define_insn ""
(define_insn "*cceq_rev_compare"
[(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
(compare:CCEQ (match_operator:SI 1
"branch_positive_comparison_operator"
......@@ -13666,9 +13676,7 @@
"cc_reg_operand" "0,y")
(const_int 0)])
(const_int 0)))]
;; This pattern is not available to SPE because the CR bits on an FP
;; compare are different than traditional PPC.
"!TARGET_SPE"
""
"{crnor %E0,%j1,%j1|crnot %E0,%j1}"
[(set_attr "type" "cr_logical,delayed_cr")])
......
......@@ -2455,55 +2455,98 @@
"mfspefscr %0"
[(set_attr "type" "vecsimple")])
;; FP comparison stuff.
(define_insn "e500_cceq_ior_compare"
[(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
(compare:CCEQ (match_operator:SI 1 "boolean_operator"
[(match_operator:SI 2
"branch_positive_comparison_operator"
[(match_operand 3
"cc_reg_operand" "y,y")
(const_int 0)])
(match_operator:SI 4
"branch_positive_comparison_operator"
[(match_operand 5
"cc_reg_operand" "0,y")
(const_int 0)])])
(const_int 1)))]
"TARGET_E500 && TARGET_HARD_FLOAT && !TARGET_FPRS"
"cr%q1 %c0,%j2,%j4"
[(set_attr "type" "cr_logical,delayed_cr")])
;; Flip the GT bit.
(define_insn "e500_flip_gt_bit"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(unspec:CCFP
[(match_operand:CCFP 1 "cc_reg_operand" "y")] 999))]
"!TARGET_FPRS && TARGET_HARD_FLOAT"
"*
{
return output_e500_flip_gt_bit (operands[0], operands[1]);
}"
[(set_attr "type" "cr_logical")])
;; MPC8540 single-precision FP instructions on GPRs.
;; We have 2 variants for each. One for IEEE compliant math and one
;; for non IEEE compliant math.
(define_insn "cmpsfeq_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(eq:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r")))]
(unspec:CCFP
[(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r"))]
1000))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
"efscmpeq %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "tstsfeq_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(eq:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r")))]
(unspec:CCFP
[(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r"))]
1001))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
"efststeq %0,%1,%2"
[(set_attr "type" "veccmpsimple")])
(define_insn "cmpsfgt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(gt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r")))]
(unspec:CCFP
[(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r"))]
1002))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
"efscmpgt %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "tstsfgt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(gt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r")))]
(unspec:CCFP
[(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r"))]
1003))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
"efststgt %0,%1,%2"
[(set_attr "type" "veccmpsimple")])
(define_insn "cmpsflt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(lt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r")))]
(unspec:CCFP
[(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r"))]
1004))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
"efscmplt %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "tstsflt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(lt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r")))]
(unspec:CCFP
[(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
(match_operand:SF 2 "gpc_reg_operand" "r"))]
1004))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
"efststlt %0,%1,%2"
[(set_attr "type" "veccmpsimple")])
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