diff options
Diffstat (limited to 'gcc/config/m32c/cond.md')
| -rw-r--r-- | gcc/config/m32c/cond.md | 165 |
1 files changed, 138 insertions, 27 deletions
diff --git a/gcc/config/m32c/cond.md b/gcc/config/m32c/cond.md index c6b42c7..ad8a5d6 100644 --- a/gcc/config/m32c/cond.md +++ b/gcc/config/m32c/cond.md @@ -32,41 +32,152 @@ ; right flags already. For example, a mov followed by a "cmp *,0" is ; redundant; the move already set the Z flag. -(define_insn "cbranchqi4" +(define_insn_and_split "cbranch<mode>4" [(set (pc) (if_then_else (match_operator 0 "m32c_cmp_operator" - [(match_operand:QI 1 "mrai_operand" "RqiSd,RqiSd,?Rmm,?Rmm") - (match_operand:QI 2 "mrai_operand" "iRqiSd,?Rmm,iRqiSd,?Rmm")]) + [(match_operand:QHPSI 1 "mra_operand" "RraSd") + (match_operand:QHPSI 2 "mrai_operand" "iRraSd")]) (label_ref (match_operand 3 "" "")) (pc)))] "" - "cmp.b\t%2,%1\n\tj%C0\t1f\n\tjmp.a\t%l3\n1:" -; "cmp.b\t%2,%1\n\tj%c0\t%l3" - [(set_attr "flags" "oszc,oszc,oszc,oszc")] + "#" + "" + [(set (reg:CC FLG_REGNO) + (compare (match_dup 1) + (match_dup 2))) + (set (pc) (if_then_else (match_dup 4) + (label_ref (match_dup 3)) + (pc)))] + "operands[4] = m32c_cmp_flg_0 (operands[0]);" ) -(define_insn "cbranchhi4" - [(set (pc) (if_then_else - (match_operator 0 "m32c_cmp_operator" - [(match_operand:HI 1 "mrai_operand" "Rhi,?Sd,Rhi,?Sd,?Rmm,?Rmm") - (match_operand:HI 2 "mrai_operand" "iRhiSd,iRhiSd,?Rmm,?Rmm,iRhiSd,?Rmm")]) - (label_ref (match_operand 3 "" "")) - (pc)))] +(define_insn "stzx_16" + [(set (match_operand:QI 0 "mrai_operand" "=R0w,R0w,R0w") + (if_then_else:QI (eq (reg:CC FLG_REGNO) (const_int 0)) + (match_operand:QI 1 "const_int_operand" "i,i,0") + (match_operand:QI 2 "const_int_operand" "i,0,i")))] + "TARGET_A16" + "@ + stzx\t%1,%2,%0 + stz\t%1,%0 + stnz\t%2,%0") + +(define_insn "stzx_24_<mode>" + [(set (match_operand:QHI 0 "mrai_operand" "=RraSd,RraSd,RraSd") + (if_then_else:QHI (eq (reg:CC FLG_REGNO) (const_int 0)) + (match_operand:QHI 1 "const_int_operand" "i,i,0") + (match_operand:QHI 2 "const_int_operand" "i,0,i")))] + "TARGET_A24" + "@ + stzx.<bwl>\t%1,%2,%0 + stz.<bwl>\t%1,%0 + stnz.<bwl>\t%2,%0") + +(define_insn_and_split "stzx_reversed" + [(set (match_operand 0 "m32c_r0_operand" "") + (if_then_else (ne (reg:CC FLG_REGNO) (const_int 0)) + (match_operand 1 "const_int_operand" "") + (match_operand 2 "const_int_operand" "")))] + "TARGET_A24 || GET_MODE (operands[0]) == QImode" + "#" + "" + [(set (match_dup 0) + (if_then_else (eq (reg:CC FLG_REGNO) (const_int 0)) + (match_dup 2) + (match_dup 1)))] "" - "cmp.w\t%2,%1\n\tj%C0\t1f\n\tjmp.a\t%l3\n1:" -; "cmp.w\t%2,%1\n\tj%c0\t%l3" - [(set_attr "flags" "oszc,oszc,oszc,oszc,oszc,oszc")] ) -(define_insn "cbranchpsi4" - [(set (pc) (if_then_else - (match_operator 0 "m32c_cmp_operator" - [(match_operand:PSI 1 "mrai_operand" "RsiSd,RsiSd,?Rmm,?Rmm") - (match_operand:PSI 2 "mrai_operand" "iRsiSd,?Rmm,iRsiSd,?Rmm")]) - (label_ref (match_operand 3 "" "")) - (pc)))] + +(define_insn "cmp<mode>" + [(set (reg:CC FLG_REGNO) + (compare (match_operand:QHPSI 0 "mra_operand" "RraSd") + (match_operand:QHPSI 1 "mrai_operand" "RraSdi")))] + "" + "cmp.<bwl>\t%1,%0") + +(define_insn "b<code>" + [(set (pc) + (if_then_else (any_cond (reg:CC FLG_REGNO) + (const_int 0)) + (label_ref (match_operand 0 "")) + (pc)))] + "" + "j<code>\t%l0" +) + +;; m32c_conditional_register_usage changes the setcc_gen_code array to +;; point to the _24 variants if needed. + +(define_insn "s<code>" + [(set (match_operand:QI 0 "register_operand" "=Rqi") + (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))] + "TARGET_A16" + "* return m32c_scc_pattern(operands, <CODE>);") + +(define_insn "s<code>_24" + [(set (match_operand:HI 0 "mra_operand" "=RhiSd") + (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))] "TARGET_A24" - "cmp.l\t%2,%1\n\tj%C0\t1f\n\tjmp.a\t%l3\n1:" -; "cmp.l\t%2,%1\n\tj%c0\t%l3" - [(set_attr "flags" "oszc,oszc,oszc,oszc")] - ) + "sc<code>\t%0") + +(define_expand "movqicc" + [(set (match_operand:QI 0 "register_operand" "") + (if_then_else:QI (match_operand 1 "m32c_eqne_operator" "") + (match_operand:QI 2 "const_int_operand" "") + (match_operand:QI 3 "const_int_operand" "")))] + "" + "if (m32c_expand_movcc(operands)) + FAIL; + DONE;" +) + +(define_expand "movhicc" + [(set (match_operand:HI 0 "mra_operand" "") + (if_then_else:HI (match_operand 1 "m32c_eqne_operator" "") + (match_operand:HI 2 "const_int_operand" "") + (match_operand:HI 3 "const_int_operand" "")))] + "TARGET_A24" + "if (m32c_expand_movcc(operands)) + FAIL; + DONE;" +) + + +;; CMP opcodes subtract two values, set the flags, and discard the +;; value. This pattern recovers the sign of the discarded value based +;; on the flags. Operand 0 is set to -1, 0, or 1. This is used for +;; the cmpstr pattern. For optimal code, this should be removed if +;; followed by a suitable CMP insn, as SCMPU sets the flags correctly +;; already (see the peephole following). This pattern is 7 bytes and +;; 5 cycles. If you don't need specific values, a 5/4 pattern can be +;; made with SCGT and BMLT to set the appropriate bits. + +(define_insn "cond_to_int" + [(set (match_operand:HI 0 "mra_qi_operand" "=Rqi") + (if_then_else:HI (lt (reg:CC FLG_REGNO) (const_int 0)) + (const_int -1) + (if_then_else:HI (eq (reg:CC FLG_REGNO) (const_int 0)) + (const_int 0) + (const_int -1))))] + "TARGET_A24" + "sceq\t%0\n\tbmgt\t1,%h0\n\tdec.w\t%0" + [(set_attr "flags" "sz")] + ) + +;; A cond_to_int followed by a compare against zero is essentially a no-op. + +(define_peephole2 + [(set (match_operand:HI 0 "mra_qi_operand" "") + (if_then_else:HI (lt (reg:CC FLG_REGNO) (const_int 0)) + (const_int -1) + (if_then_else:HI (eq (reg:CC FLG_REGNO) (const_int 0)) + (const_int 0) + (const_int -1)))) + (set (reg:CC FLG_REGNO) + (compare (match_operand:HI 1 "mra_qi_operand" "") + (const_int 0))) + ] + "rtx_equal_p(operands[0], operands[1])" + [(const_int 1)] + "") |
