aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/m68hc11/m68hc11.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/m68hc11/m68hc11.md')
-rw-r--r--gcc/config/m68hc11/m68hc11.md611
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