diff options
Diffstat (limited to 'gcc/config/m68hc11/m68hc11.md')
-rw-r--r-- | gcc/config/m68hc11/m68hc11.md | 611 |
1 files changed, 535 insertions, 76 deletions
diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md index a71e4f3f0f5..b986e6503e2 100644 --- a/gcc/config/m68hc11/m68hc11.md +++ b/gcc/config/m68hc11/m68hc11.md @@ -1,5 +1,5 @@ ;;- Machine description file for Motorola 68HC11 and 68HC12. -;;- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +;;- Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. ;;- Contributed by Stephane Carrez (stcarrez@nerim.fr) ;; This file is part of GNU CC. @@ -143,6 +143,7 @@ (A_REGNUM 5) ; A (high part of D) (B_REGNUM 6) ; B (low part of D) (CC_REGNUM 7) ; Condition code register + (SOFT_Z_REGNUM 11) ; Z soft register ]) ;;-------------------------------------------------------------------- @@ -258,7 +259,7 @@ [(set (cc0) (match_operand:QI 0 "tst_operand" "")) (use (match_operand:HI 1 "hard_reg_operand" "")) - (use (reg:HI 11))] + (use (reg:HI SOFT_Z_REGNUM))] "z_replacement_completed == 2" [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1)) (set (match_dup 1) (match_dup 2)) @@ -365,7 +366,7 @@ (compare (match_operand:HI 0 "tst_operand" "dxy,m") (match_operand:HI 1 "cmp_operand" "m,dxy"))) (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy")) - (use (reg:HI 11))] + (use (reg:HI SOFT_Z_REGNUM))] "" "#") @@ -374,7 +375,7 @@ (compare (match_operand:HI 0 "tst_operand" "") (match_operand:HI 1 "cmp_operand" ""))) (use (match_operand:HI 2 "hard_reg_operand" "")) - (use (reg:HI 11))] + (use (reg:HI SOFT_Z_REGNUM))] "z_replacement_completed == 2" [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2)) (set (match_dup 2) (match_dup 3)) @@ -444,7 +445,7 @@ [(set (cc0) (and:QI (match_operand:QI 0 "tst_operand" "") (match_operand:QI 1 "hard_addr_reg_operand" "")))] - "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode" + "z_replacement_completed == 2" [(set (match_dup 3) (match_dup 2)) (set (cc0) (and:QI (match_dup 0) (match_dup 4)))] "operands[2] = gen_rtx (REG, HImode, REGNO (operands[1])); @@ -456,7 +457,7 @@ (and:QI (match_operand:QI 0 "tst_operand" "d,m") (match_operand:QI 1 "cmp_operand" "m,d"))) (use (match_operand:HI 2 "hard_reg_operand" "xy,xy")) - (use (reg:HI 11))] + (use (reg:HI SOFT_Z_REGNUM))] "" "#") @@ -465,12 +466,12 @@ (and:QI (match_operand:QI 0 "tst_operand" "") (match_operand:QI 1 "cmp_operand" ""))) (use (match_operand:HI 2 "hard_reg_operand" "")) - (use (reg:HI 11))] + (use (reg:HI SOFT_Z_REGNUM))] "z_replacement_completed == 2" - [(set (mem:HI (pre_dec:HI (reg:HI 3))) (match_dup 2)) + [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2)) (set (match_dup 2) (match_dup 3)) (set (cc0) (and:QI (match_dup 0) (match_dup 1))) - (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI 3))))] + (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);") (define_insn "bitcmphi" @@ -546,7 +547,7 @@ (compare (match_operand:QI 0 "tst_operand" "dxy,m") (match_operand:QI 1 "cmp_operand" "m,dxy"))) (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy")) - (use (reg:HI 11))] + (use (reg:HI SOFT_Z_REGNUM))] "" "#") @@ -555,7 +556,7 @@ (compare (match_operand:QI 0 "tst_operand" "") (match_operand:QI 1 "cmp_operand" ""))) (use (match_operand:HI 2 "hard_reg_operand" "")) - (use (reg:HI 11))] + (use (reg:HI SOFT_Z_REGNUM))] "z_replacement_completed == 2" [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2)) (set (match_dup 2) (match_dup 3)) @@ -620,7 +621,7 @@ ;; because there is no memory->memory moves. It must be defined with ;; earlyclobber (&) so that it does not appear in the source or destination ;; address. Providing patterns for movdi/movdf allows GCC to generate -;; better code. [Until now, the scratch register is limited to D becuse +;; better code. [Until now, the scratch register is limited to D because ;; otherwise we can run out of registers in the A_REGS class for reload]. ;; ;; For 68HC12, the scratch register is not necessary. To use the same @@ -2089,9 +2090,9 @@ }") (define_insn "*addhi3_68hc12" - [(set (match_operand:HI 0 "register_operand" "=xy,d,xy*z*w,xy*z*w,xy*z") + [(set (match_operand:HI 0 "register_operand" "=xyd,d,xy*z*w,xy*z*w,xy*z") (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*zw,0") - (match_operand:HI 2 "general_operand" "N,im*A*wu,id,id,!mu*A")))] + (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))] "TARGET_M6812" "* { @@ -2278,9 +2279,9 @@ }") (define_insn "*addhi3" - [(set (match_operand:HI 0 "hard_reg_operand" "=A,d,!A,d*A,!d*A") - (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0") - (match_operand:HI 2 "general_operand" "N,i,I,mi*A*d,!u*d*w")))] + [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,!d*A") + (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0") + (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,!u*d*w")))] "TARGET_M6811" "* { @@ -2894,12 +2895,15 @@ }") (define_insn "mulqi3" - [(set (match_operand:QI 0 "register_operand" "=d") - (mult:QI (match_operand:QI 1 "nonimmediate_operand" "dum") - (match_operand:QI 2 "nonimmediate_operand" "dum")))] + [(set (match_operand:QI 0 "register_operand" "=d,*x,*y") + (mult:QI (match_operand:QI 1 "nonimmediate_operand" "%dum,0,0") + (match_operand:QI 2 "general_operand" "dium,*xium,*yium")))] "" "* { + if (A_REG_P (operands[0])) + return \"#\"; + if (D_REG_P (operands[1]) && D_REG_P (operands[2])) { output_asm_insn (\"tba\", operands); @@ -2925,6 +2929,28 @@ return \"mul\"; }") +(define_split + [(set (match_operand:QI 0 "hard_addr_reg_operand" "") + (mult:QI (match_operand:QI 1 "general_operand" "") + (match_operand:QI 2 "general_operand" "")))] + "z_replacement_completed == 2" + [(parallel [(set (reg:HI D_REGNUM) (match_dup 3)) + (set (match_dup 3) (reg:HI D_REGNUM))]) + (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6))) + (parallel [(set (reg:HI D_REGNUM) (match_dup 3)) + (set (match_dup 3) (reg:HI D_REGNUM))])] + " + operands[3] = gen_rtx (REG, HImode, REGNO (operands[0])); + if (A_REG_P (operands[1])) + operands[5] = gen_rtx (REG, QImode, HARD_D_REGNUM); + else + operands[5] = operands[1]; + if (A_REG_P (operands[2])) + operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM); + else + operands[6] = operands[2]; + ") + (define_insn "mulqihi3" [(set (match_operand:HI 0 "register_operand" "=d,d") (mult:HI (sign_extend:HI @@ -4446,15 +4472,21 @@ (set (match_dup 4) (match_dup 2)) (set (match_dup 2) (match_dup 5)) - (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) + (rotate:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 6) (match_dup 2)) (set (match_dup 2) (match_dup 7)) - (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) + (rotate:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 8) (match_dup 2)) (set (match_dup 2) (match_dup 9)) - (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) + (rotate:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 10) (match_dup 2))] "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]); operands[5] = m68hc11_gen_highpart (HImode, operands[3]); @@ -4757,13 +4789,16 @@ (define_insn "*ashlhi3_2" - [(set (match_operand:HI 0 "register_operand" "=d") - (ashift:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "register_operand" "+x"))) + [(set (match_operand:HI 0 "register_operand" "=d,*x") + (ashift:HI (match_operand:HI 1 "register_operand" "0,0") + (match_operand:HI 2 "register_operand" "+x,+d"))) (clobber (match_dup 2))] "" "* { + if (A_REG_P (operands[0])) + return \"#\"; + CC_STATUS_INIT; return \"bsr\\t___lshlhi3\"; }") @@ -5046,21 +5081,17 @@ }") (define_insn "*ashrhi3" - [(set (match_operand:HI 0 "register_operand" "=d,x") + [(set (match_operand:HI 0 "register_operand" "=d,*x") (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0") (match_operand:HI 2 "register_operand" "+x,+d"))) (clobber (match_dup 2))] "" "* { - CC_STATUS_INIT; - if (D_REG_P (operands[2])) - output_asm_insn (\"xgd%0\", operands); + if (A_REG_P (operands[0])) + return \"#\"; output_asm_insn (\"bsr\\t___ashrhi3\", operands); - if (D_REG_P (operands[2])) - output_asm_insn (\"xgd%0\", operands); - return \"\"; }") @@ -5310,15 +5341,18 @@ (set (match_dup 4) (match_dup 2)) (set (match_dup 2) (match_dup 5)) - (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 6) (match_dup 2)) (set (match_dup 2) (match_dup 7)) - (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 8) (match_dup 2)) (set (match_dup 2) (match_dup 9)) - (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 10) (match_dup 2))] "operands[3] = m68hc11_gen_highpart (SImode, operands[1]); operands[5] = m68hc11_gen_lowpart (HImode, operands[3]); @@ -5594,22 +5628,17 @@ }") (define_insn "*lshrhi3" - [(set (match_operand:HI 0 "register_operand" "=d,x") + [(set (match_operand:HI 0 "register_operand" "=d,*x") (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0") (match_operand:HI 2 "register_operand" "+x,+d"))) (clobber (match_dup 2))] "" "* { - CC_STATUS_INIT; - if (D_REG_P (operands[2])) - output_asm_insn (\"xgd%0\", operands); - - output_asm_insn (\"bsr\\t___lshrhi3\", operands); - if (D_REG_P (operands[2])) - output_asm_insn (\"xgd%0\", operands); + if (A_REG_P (operands[0])) + return \"#\"; - return \"\"; + return \"bsr\\t___lshrhi3\"; }") (define_expand "lshrqi3" @@ -5750,7 +5779,8 @@ (define_insn "*rotlhi3_with_carry" [(set (match_operand:HI 0 "register_operand" "=d") (rotate:HI (match_operand:HI 1 "register_operand" "0") - (reg:HI CC_REGNUM)))] + (const_int 1))) + (clobber (reg:HI CC_REGNUM))] "" "* { @@ -5761,7 +5791,8 @@ (define_insn "*rotrhi3_with_carry" [(set (match_operand:HI 0 "register_operand" "=d") (rotatert:HI (match_operand:HI 1 "register_operand" "0") - (reg:HI CC_REGNUM)))] + (const_int 1))) + (clobber (reg:HI CC_REGNUM))] "" "* { @@ -5780,7 +5811,41 @@ return \"\"; }") -(define_insn "rotlhi3" +(define_insn "rotrqi3" + [(set (match_operand:QI 0 "register_operand" "=d,!q") + (rotatert:QI (match_operand:QI 1 "register_operand" "0,0") + (match_operand:QI 2 "const_int_operand" "i,i")))] + "" + "* +{ + m68hc11_gen_rotate (ROTATERT, insn, operands); + return \"\"; +}") + +(define_expand "rotlhi3" + [(set (match_operand:HI 0 "register_operand" "") + (rotate:HI (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + if (GET_CODE (operands[2]) != CONST_INT) + { + rtx scratch = gen_reg_rtx (HImode); + operand1 = force_reg (HImode, operand1); + + emit_move_insn (scratch, operands[2]); + emit_insn (gen_rtx (PARALLEL, VOIDmode, + gen_rtvec (2, gen_rtx (SET, VOIDmode, + operand0, + gen_rtx_ROTATE (HImode, + operand1, scratch)), + gen_rtx (CLOBBER, VOIDmode, scratch)))); + DONE; + } +}") + +(define_insn "rotlhi3_const" [(set (match_operand:HI 0 "register_operand" "=d") (rotate:HI (match_operand:HI 1 "register_operand" "0") (match_operand:HI 2 "const_int_operand" "i")))] @@ -5791,18 +5856,44 @@ return \"\"; }") -(define_insn "rotrqi3" - [(set (match_operand:QI 0 "register_operand" "=d,!q") - (rotatert:QI (match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "const_int_operand" "i,i")))] +(define_insn "*rotlhi3" + [(set (match_operand:HI 0 "register_operand" "=d,*x") + (rotate:HI (match_operand:HI 1 "register_operand" "0,0") + (match_operand:HI 2 "general_operand" "+x,+d"))) + (clobber (match_dup 2))] "" "* { - m68hc11_gen_rotate (ROTATERT, insn, operands); - return \"\"; + if (A_REG_P (operands[0])) + return \"#\"; + + return \"bsr\\t___rotlhi3\"; }") -(define_insn "rotrhi3" +(define_expand "rotrhi3" + [(set (match_operand:HI 0 "register_operand" "") + (rotatert:HI (match_operand:HI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + if (GET_CODE (operands[2]) != CONST_INT) + { + rtx scratch = gen_reg_rtx (HImode); + operand1 = force_reg (HImode, operand1); + + emit_move_insn (scratch, operands[2]); + emit_insn (gen_rtx (PARALLEL, VOIDmode, + gen_rtvec (2, gen_rtx (SET, VOIDmode, + operand0, + gen_rtx_ROTATERT (HImode, + operand1, scratch)), + gen_rtx (CLOBBER, VOIDmode, scratch)))); + DONE; + } +}") + +(define_insn "rotrhi3_const" [(set (match_operand:HI 0 "register_operand" "=d") (rotatert:HI (match_operand:HI 1 "register_operand" "0") (match_operand:HI 2 "const_int_operand" "i")))] @@ -5813,6 +5904,242 @@ return \"\"; }") +(define_insn "*rotrhi3" + [(set (match_operand:HI 0 "register_operand" "=d,*x") + (rotatert:HI (match_operand:HI 1 "register_operand" "0,0") + (match_operand:HI 2 "general_operand" "+x,+d"))) + (clobber (match_dup 2))] + "" + "* +{ + if (A_REG_P (operands[0])) + return \"#\"; + + return \"bsr\\t___rotrhi3\"; +}") + +;; Split a shift operation on an address register in a shift +;; on D_REGNUM. +(define_split /* "*rotrhi3_addr" */ + [(set (match_operand:HI 0 "hard_addr_reg_operand" "") + (match_operator:HI 3 "m68hc11_shift_operator" + [(match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "register_operand" "")])) + (clobber (match_dup 2))] + "z_replacement_completed == 2" + [(parallel [(set (reg:HI D_REGNUM) (match_dup 0)) + (set (match_dup 0) (reg:HI D_REGNUM))]) + (parallel [(set (reg:HI D_REGNUM) + (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)])) + (clobber (match_dup 0))]) + (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) + (set (match_dup 0) (reg:HI D_REGNUM))])] + "") + +;;-------------------------------------------------------------------- +;;- 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 ;;-------------------------------------------------------------------- @@ -6279,14 +6606,27 @@ "" "* { - int far_call = current_function_far; - if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) { - if (SYMBOL_REF_FLAG (XEXP (operands[0], 0)) == 1) + if (m68hc11_is_far_symbol (operands[0])) + { + if (TARGET_M6812) + { + output_asm_insn (\"call\\t%0\", operands); + return \"\"; + } + else + { + output_asm_insn (\"pshb\", operands); + output_asm_insn (\"ldab\\t#%%page(%0)\", operands); + output_asm_insn (\"ldy\\t#%%addr(%0)\", operands); + return \"jsr\\t__call_a32\"; + } + } + if (m68hc11_is_trap_symbol (operands[0])) return \"swi\"; else - return far_call ? \"call\\t%0\" : \"bsr\\t%0\"; + return \"bsr\\t%0\"; } else { @@ -6301,14 +6641,27 @@ "" "* { - int far_call = current_function_far; - if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) { - if (SYMBOL_REF_FLAG (XEXP (operands[1], 0)) == 1) + if (m68hc11_is_far_symbol (operands[1])) + { + if (TARGET_M6812) + { + output_asm_insn (\"call\\t%1\", operands); + return \"\"; + } + else + { + output_asm_insn (\"pshb\", operands); + output_asm_insn (\"ldab\\t#%%page(%1)\", operands); + output_asm_insn (\"ldy\\t#%%addr(%1)\", operands); + return \"jsr\\t__call_a32\"; + } + } + if (m68hc11_is_trap_symbol (operands[1])) return \"swi\"; else - return far_call ? \"call\\t%1\" : \"bsr\\t%1\"; + return \"bsr\\t%1\"; } else { @@ -6393,18 +6746,18 @@ if (ret_size && ret_size <= 2) { - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, gen_rtx_RETURN (VOIDmode), - gen_rtx_USE (VOIDmode, - gen_rtx_REG (HImode, 1))))); + emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, + gen_rtvec (2, gen_rtx_RETURN (VOIDmode), + gen_rtx_USE (VOIDmode, + gen_rtx_REG (HImode, 1))))); DONE; } if (ret_size) { - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, gen_rtx_RETURN (VOIDmode), - gen_rtx_USE (VOIDmode, - gen_rtx_REG (SImode, 0))))); + emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, + gen_rtvec (2, gen_rtx_RETURN (VOIDmode), + gen_rtx_USE (VOIDmode, + gen_rtx_REG (SImode, 0))))); DONE; } }") @@ -6422,7 +6775,25 @@ return \"\"; if (current_function_interrupt || current_function_trap) return \"rti\"; - return current_function_far ? \"rtc\" : \"rts\"; + else if (!current_function_far) + return \"rts\"; + else if (TARGET_M6812) + return \"rtc\"; + else + { + int ret_size = 0; + + if (current_function_return_rtx) + ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx)); + + if (ret_size == 0) + return \"jmp\\t__return_void\"; + if (ret_size <= 2) + return \"jmp\\t__return_16\"; + if (ret_size <= 4) + return \"jmp\\t__return_32\"; + return \"jmp\\t__return_16\"; + } }") (define_insn "*return_16bit" @@ -6439,7 +6810,12 @@ return \"\"; if (current_function_interrupt || current_function_trap) return \"rti\"; - return current_function_far ? \"rtc\" : \"rts\"; + else if (!current_function_far) + return \"rts\"; + else if (TARGET_M6812) + return \"rtc\"; + else + return \"jmp\\t__return_16\"; }") (define_insn "*return_32bit" @@ -6456,7 +6832,12 @@ return \"\"; if (current_function_interrupt || current_function_trap) return \"rti\"; - return current_function_far ? \"rtc\" : \"rts\"; + else if (!current_function_far) + return \"rts\"; + else if (TARGET_M6812) + return \"rtc\"; + else + return \"jmp\\t__return_32\"; }") (define_insn "indirect_jump" @@ -6488,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. @@ -6547,8 +6984,7 @@ (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 1))] "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2])) - && !reg_mentioned_p (operands[2], operands[0]) - && GET_MODE (operands[2]) == HImode" + && !reg_mentioned_p (operands[2], operands[0])" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (match_dup 2))] "") @@ -6673,6 +7109,29 @@ "") ;; +;; Replace a "ldd <mem>; addd #N; std <mem>" into a +;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register +;; and the constant is small. +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "general_operand" "")) + (set (match_dup 0) (plus:HI (match_dup 0) + (match_operand:HI 2 "const_int_operand" ""))) + (set (match_operand:HI 3 "nonimmediate_operand" "") + (match_dup 0)) + (match_scratch:HI 4 "xy")] + "D_REG_P (operands[0]) + && (TARGET_M6812 + || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2)) + && peep2_reg_dead_p (3, operands[0])" + [(set (match_dup 4) (match_dup 1)) + (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2))) + (set (match_dup 3) (match_dup 4))] + "if (reg_mentioned_p (operands[4], operands[1])) FAIL; + if (reg_mentioned_p (operands[4], operands[3])) FAIL;") + +;; ;; This peephole catches the address computations generated by the reload ;; pass. (define_peephole |