summaryrefslogtreecommitdiff
path: root/gcc/config/rx/rx.md
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-17 17:59:20 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-17 17:59:20 +0000
commit2e978fdc922a6c428d73147b8b43bdbceabdf0f1 (patch)
treeb105448070f929fc3c39d6d0c02008834fb45ba5 /gcc/config/rx/rx.md
parent6f04f6f0ef2d76ec8666763a66791f74ce0fd7b4 (diff)
downloadgcc-2e978fdc922a6c428d73147b8b43bdbceabdf0f1.tar.gz
rx: Implement cstoresf4.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@168923 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/rx/rx.md')
-rw-r--r--gcc/config/rx/rx.md92
1 files changed, 92 insertions, 0 deletions
diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md
index 4ffbfec94ed..cdae1cd75ff 100644
--- a/gcc/config/rx/rx.md
+++ b/gcc/config/rx/rx.md
@@ -739,6 +739,98 @@
[(set_attr "length" "3")]
)
+(define_expand "cstoresf4"
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (match_operator:SI 1 "comparison_operator"
+ [(match_operand:SF 2 "register_operand" "")
+ (match_operand:SF 3 "register_operand" "")]))
+ (clobber (match_scratch:SI 4))])]
+ "ALLOW_RX_FPU_INSNS"
+{
+ enum rtx_code cmp1, cmp2;
+
+ /* If the comparison needs swapping of operands, do that now.
+ Do not split the comparison in two yet. */
+ if (rx_split_fp_compare (GET_CODE (operands[0]), &cmp1, &cmp2))
+ {
+ rtx op2, op3;
+
+ if (cmp2 != UNKNOWN)
+ {
+ gcc_assert (cmp1 == UNORDERED);
+ if (cmp2 == GT)
+ cmp1 = UNGT;
+ else if (cmp2 == LE)
+ cmp1 = UNLE;
+ else
+ gcc_unreachable ();
+ }
+
+ op2 = operands[3];
+ op3 = operands[2];
+ operands[0] = gen_rtx_fmt_ee (cmp1, VOIDmode, op2, op3);
+ operands[2] = op2;
+ operands[3] = op3;
+ }
+})
+
+(define_insn_and_split "*cstoresf4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator:SI 4 "rx_fp_comparison_operator"
+ [(match_operand:SF 2 "register_operand" "r")
+ (match_operand:SF 3 "rx_source_operand" "rFiQ")]))
+ (clobber (match_scratch:SI 1 "=r"))]
+ "ALLOW_RX_FPU_INSNS"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ enum rtx_code cmp0, cmp1, cmp2;
+ rtx flags, x;
+ bool swap;
+
+ cmp0 = GET_CODE (operands[4]);
+ swap = rx_split_fp_compare (cmp0, &cmp1, &cmp2);
+ gcc_assert (!swap);
+
+ flags = gen_rtx_REG (CC_Fmode, CC_REG);
+ x = gen_rtx_COMPARE (CC_Fmode, operands[2], operands[3]);
+ x = gen_rtx_SET (VOIDmode, flags, x);
+ emit_insn (x);
+
+ x = gen_rtx_fmt_ee (cmp1, SImode, flags, const0_rtx);
+ x = gen_rtx_SET (VOIDmode, operands[0], x);
+ emit_insn (x);
+
+ if (cmp0 == LTGT)
+ {
+ /* The one case of LTGT needs to be split into ORDERED && NE. */
+ x = gen_rtx_fmt_ee (EQ, VOIDmode, flags, const0_rtx);
+ x = gen_rtx_IF_THEN_ELSE (SImode, x, const0_rtx, operands[0]);
+ x = gen_rtx_SET (VOIDmode, operands[0], x);
+ emit_insn (x);
+ }
+ else if (cmp2 == EQ || cmp2 == NE)
+ {
+ /* Oring the two flags can be performed with a movcc operation. */
+ x = gen_rtx_fmt_ee (cmp2, VOIDmode, flags, const0_rtx);
+ x = gen_rtx_IF_THEN_ELSE (SImode, x, const1_rtx, operands[0]);
+ x = gen_rtx_SET (VOIDmode, operands[0], x);
+ emit_insn (x);
+ }
+ else if (cmp2 != UNKNOWN)
+ {
+ /* We can't use movcc, but need to or in another compare.
+ Do this by storing the second operation into the scratch. */
+ x = gen_rtx_fmt_ee (cmp2, SImode, flags, const0_rtx);
+ x = gen_rtx_SET (VOIDmode, operands[1], x);
+ emit_insn (x);
+
+ emit_insn (gen_iorsi3 (operands[0], operands[0], operands[1]));
+ }
+ DONE;
+})
+
(define_expand "movsicc"
[(parallel
[(set (match_operand:SI 0 "register_operand")