diff options
author | ciceron <ciceron@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-04-12 21:22:49 +0000 |
---|---|---|
committer | ciceron <ciceron@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-04-12 21:22:49 +0000 |
commit | 171bfe897473d8b6d5786c9ac35d5a74962ad59d (patch) | |
tree | 2b567101eee78ff1ed4ed3568ac4f0bc050a8a8b /gcc/config/m68hc11/m68hc11.md | |
parent | f40d58b18b0cdcf909b246a498adbaa1519746c2 (diff) | |
download | gcc-171bfe897473d8b6d5786c9ac35d5a74962ad59d.tar.gz |
* config/m68hc11/m68hc11.md ("decrement_and_branch_until_zero"): New
pattern for dbcc/ibcc generation for 68HC12.
("doloop_end"): New pattern.
("m68hc12_dbcc_dec_hi"): New pattern for dbeq/dbne.
("m68hc12_dbcc_inc_hi"): New pattern for ibeq/ibne.
("m68hc12_dbcc_dec_qi"): New pattern.
("m68hc12_dbcc_inc_qi"): New pattern.
(split): Add split for the above when we can't use dbcc/ibcc due to
reloading.
(peephole2): Add peephole2 to generate the above when possible.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@65527 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/m68hc11/m68hc11.md')
-rw-r--r-- | gcc/config/m68hc11/m68hc11.md | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md index 6fd9d0e3ac9..1fb5a5e8ad8 100644 --- a/gcc/config/m68hc11/m68hc11.md +++ b/gcc/config/m68hc11/m68hc11.md @@ -5937,6 +5937,210 @@ "") ;;-------------------------------------------------------------------- +;;- 68HC12 Decrement/Increment and branch +;;-------------------------------------------------------------------- +;; These patterns are used by loop optimization as well as peephole2 +;; They must handle reloading themselves and the scratch register +;; is used for that. Even if we accept memory operand, we must not +;; accept them on the predicate because it might create too many reloads. +;; (specially on HC12 due to its auto-incdec addressing modes). +;; +(define_expand "decrement_and_branch_until_zero" + [(parallel [(set (pc) + (if_then_else + (ne (plus:HI (match_operand:HI 0 "register_operand" "") + (const_int 0)) + (const_int 1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) + (const_int -1))) + (clobber (match_scratch:HI 2 ""))])] + "TARGET_M6812" + "") + +(define_expand "doloop_end" + [(use (match_operand 0 "" "")) ; loop pseudo + (use (match_operand 1 "" "")) ; iterations; zero if unknown + (use (match_operand 2 "" "")) ; max iterations + (use (match_operand 3 "" "")) ; loop level + (use (match_operand 4 "" ""))] ; label + "TARGET_M6812" + " +{ + /* Reject non-constant loops as it generates bigger code due to + the handling of the loop register. We can do better by using + the peephole2 dbcc/ibcc patterns. */ + if (INTVAL (operands[1]) == 0) + { + FAIL; + } + if (GET_MODE (operands[0]) == HImode) + { + emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0], + gen_rtx (NE, HImode), + operands[4])); + DONE; + } + if (GET_MODE (operands[0]) == QImode) + { + emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0], + gen_rtx (NE, QImode), + operands[4])); + DONE; + } + + FAIL; +}") + +;; Decrement-and-branch insns. +(define_insn "m68hc12_dbcc_dec_hi" + [(set (pc) + (if_then_else + (match_operator 1 "m68hc11_eq_compare_operator" + [(match_operand:HI 0 "register_operand" "+dxy,m*u*z") + (const_int 1)]) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) (const_int -1))) + (clobber (match_scratch:HI 3 "=X,dxy"))] + "TARGET_M6812" + "* +{ + if (!H_REG_P (operands[0])) + return \"#\"; + + CC_STATUS_INIT; + if (GET_CODE (operands[1]) == EQ) + return \"dbeq\\t%0,%l2\"; + else + return \"dbne\\t%0,%l2\"; +}") + +;; Decrement-and-branch insns. +(define_insn "m68hc12_dbcc_inc_hi" + [(set (pc) + (if_then_else + (match_operator 1 "m68hc11_eq_compare_operator" + [(match_operand:HI 0 "register_operand" "+dxy,m*u*z") + (const_int -1)]) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) (const_int 1))) + (clobber (match_scratch:HI 3 "=X,dxy"))] + "TARGET_M6812" + "* +{ + if (!H_REG_P (operands[0])) + return \"#\"; + + CC_STATUS_INIT; + if (GET_CODE (operands[1]) == EQ) + return \"ibeq\\t%0,%l2\"; + else + return \"ibeq\\t%0,%l2\"; +}") + +;; Decrement-and-branch (QImode). +(define_insn "m68hc12_dbcc_dec_qi" + [(set (pc) + (if_then_else + (match_operator 1 "m68hc11_eq_compare_operator" + [(match_operand:QI 0 "register_operand" "+d,m*u*A") + (const_int 1)]) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:QI (match_dup 0) (const_int -1))) + (clobber (match_scratch:QI 3 "=X,d"))] + "TARGET_M6812" + "* +{ + if (!D_REG_P (operands[0])) + return \"#\"; + + CC_STATUS_INIT; + if (GET_CODE (operands[1]) == EQ) + return \"dbeq\\tb,%l2\"; + else + return \"dbne\\tb,%l2\"; +}") + +;; Increment-and-branch (QImode). +(define_insn "m68hc12_dbcc_inc_qi" + [(set (pc) + (if_then_else + (match_operator 1 "m68hc11_eq_compare_operator" + [(match_operand:QI 0 "register_operand" "+d,m*u*A") + (const_int -1)]) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:QI (match_dup 0) (const_int 1))) + (clobber (match_scratch:QI 3 "=X,d"))] + "TARGET_M6812" + "* +{ + if (!D_REG_P (operands[0])) + return \"#\"; + + CC_STATUS_INIT; + if (GET_CODE (operands[1]) == EQ) + return \"ibeq\\tb,%l2\"; + else + return \"ibeq\\tb,%l2\"; +}") + +;; Split the above to handle the case where operand 0 is in memory +;; (a register that couldn't get a hard register) +(define_split + [(set (pc) + (if_then_else + (match_operator 3 "m68hc11_eq_compare_operator" + [(match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "const_int_operand" "")]) + (label_ref (match_operand 4 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" ""))) + (clobber (match_operand:HI 5 "hard_reg_operand" ""))] + "TARGET_M6812 && reload_completed" + [(set (match_dup 5) (match_dup 0)) + (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2))) + (set (match_dup 0) (match_dup 5)) + (set (pc) + (if_then_else (match_op_dup 3 + [(match_dup 5) (const_int 0)]) + (label_ref (match_dup 4)) (pc)))] + "") + +;; Split the above to handle the case where operand 0 is in memory +;; (a register that couldn't get a hard register) +(define_split + [(set (pc) + (if_then_else + (match_operator 3 "m68hc11_eq_compare_operator" + [(match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "const_int_operand" "")]) + (label_ref (match_operand 4 "" "")) + (pc))) + (set (match_dup 0) + (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" ""))) + (clobber (match_operand:QI 5 "hard_reg_operand" ""))] + "TARGET_M6812 && reload_completed" + [(set (match_dup 5) (match_dup 0)) + (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2))) + (set (match_dup 0) (match_dup 5)) + (set (pc) + (if_then_else (match_op_dup 3 + [(match_dup 5) (const_int 0)]) + (label_ref (match_dup 4)) (pc)))] + "") + +;;-------------------------------------------------------------------- ;;- Jumps and transfers ;;-------------------------------------------------------------------- (define_insn "jump" @@ -6665,6 +6869,62 @@ ;;- Peepholes ;;-------------------------------------------------------------------- +;;-------------------------------------------------------------------- +;;- 68HC12 dbcc/ibcc peepholes +;;-------------------------------------------------------------------- +;; +;; Replace: "addd #-1; bne L1" into "dbne d,L1" +;; "addd #-1; beq L1" into "dbeq d,L1" +;; "addd #1; bne L1" into "ibne d,L1" +;; "addd #1; beq L1" into "ibeq d,L1" +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (plus:HI (match_dup 0) + (match_operand:HI 1 "const_int_operand" ""))) + (set (pc) + (if_then_else (match_operator 2 "m68hc11_eq_compare_operator" + [(match_dup 0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] + "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)" + [(parallel [ + (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)]) + (label_ref (match_dup 3)) (pc))) + (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1))) + (clobber (match_dup 4))])] + "operands[4] = gen_rtx_SCRATCH(HImode); + operands[5] = GEN_INT (-INTVAL (operands[1]));") + + +;; +;; Replace: "addb #-1; bne L1" into "dbne b,L1" +;; "addb #-1; beq L1" into "dbeq b,L1" +;; +(define_peephole2 + [(set (match_operand:QI 0 "hard_reg_operand" "") + (plus:QI (match_dup 0) + (match_operand:QI 1 "const_int_operand" ""))) + (set (pc) + (if_then_else (match_operator 2 "m68hc11_eq_compare_operator" + [(match_dup 0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] + "TARGET_M6812 && D_REG_P (operands[0]) + && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)" + [(parallel [ + (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)]) + (label_ref (match_dup 3)) (pc))) + (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1))) + (clobber (match_dup 4))])] + "operands[4] = gen_rtx_SCRATCH(QImode); + operands[5] = GEN_INT (-INTVAL (operands[1]));") + + +;;-------------------------------------------------------------------- +;;- Move peephole2 +;;-------------------------------------------------------------------- + ;; ;; Replace "leas 2,sp" with a "pulx" or a "puly". ;; On 68HC12, this is one cycle slower but one byte smaller. |