OSDN Git Service

* config/m68hc11/m68hc11.md ("tstqi_z_used"): Use define_insn_and_split.
[pf3gnuchains/gcc-fork.git] / gcc / config / m68hc11 / m68hc11.md
index 306053f..02782a6 100644 (file)
@@ -1,21 +1,22 @@
 ;;- Machine description file for Motorola 68HC11 and 68HC12.
-;;- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
-;;- Contributed by Stephane Carrez (stcarrez@worldnet.fr)
+;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+;;- Free Software Foundation, Inc.
+;;- Contributed by Stephane Carrez (stcarrez@nerim.fr)
 
-;; This file is part of GNU CC.
+;; This file is part of GCC.
 
-;; GNU CC is free software; you can redistribute it and/or modify
+;; GCC is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 2, or (at your option)
 ;; any later version.
 
-;; GNU CC is distributed in the hope that it will be useful,
+;; GCC is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING.  If not, write to
+;; along with GCC; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
 ;; Boston, MA 02111-1307, USA.
 
@@ -93,7 +94,7 @@
 ;; Operands modifiers:
 ;;
 ;;     %b      Get the low part of the operand (to obtain a QImode)
-;;             This modified must always be used for QImode operations
+;;             This modifier must always be used for QImode operations
 ;;             because a correction must be applied when the operand
 ;;             is a soft register (ex: *ZD1). Otherwise, we generate
 ;;             *ZD1 and this is the high part of the register. For other
    (A_REGNUM        5)         ; A (high part of D)
    (B_REGNUM        6)         ; B (low part of D)
    (CC_REGNUM       7)         ; Condition code register
+   (SOFT_TMP_REGNUM 10)         ; TMP soft register
+   (SOFT_Z_REGNUM   11)         ; Z soft register
+   (SOFT_XY_REGNUM  12)         ; XY soft register
 ])
 
 ;;--------------------------------------------------------------------
 
 ;;
 ;; Split pattern for (tst:QI) on an address register.
-;; The value is saved in memory and we test the low part only.
 ;;
 (define_split
   [(set (cc0)
-       (match_operand:QI 0 "hard_addr_reg_operand" "xy"))]
+       (match_operand:QI 0 "hard_addr_reg_operand" ""))]
   "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
-  [(set (match_dup 3) (match_dup 2))
-   (set (cc0) (match_dup 4))]
-  "operands[2] = gen_rtx (REG, HImode, REGNO (operands[0]));
-   operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
-   operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);")
+  [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
+             (set (match_dup 1) (reg:HI D_REGNUM))])
+   (set (cc0) (reg:QI D_REGNUM))
+   (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
+             (set (match_dup 1) (reg:HI D_REGNUM))])]
+  "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
 
 (define_insn "tstqi_1"
   [(set (cc0)
        (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
   ""
-  "@
-   tst\\t%0
-   tstb
-   #
-   tst\\t%b0")
+  "*
+{
+  if (A_REG_P (operands[0]))
+    return \"#\";
+
+  else if (D_REG_P (operands[0]))
+    return \"tstb\";
+
+  else if (dead_register_here (insn, d_reg))
+    return \"ldab\\t%b0\";
+
+  else
+    return \"tst\\t%b0\";
+}")
 
 ;;
 ;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated 
 ;; avoid problems with the flow+cse register pass which are made
 ;; after Z register replacement.
 ;;
-(define_insn "tstqi_z_used"
+(define_insn_and_split "tstqi_z_used"
   [(set (cc0)
        (match_operand:QI 0 "tst_operand" "m"))
    (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
-   (use (reg:HI 11))]
+   (use (reg:HI SOFT_Z_REGNUM))]
   ""
-  "#")
-
-(define_split /* "tstqi_z_used" */
-  [(set (cc0)
-       (match_operand:QI 0 "tst_operand" "m"))
-   (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
-   (use (reg:HI 11))]
+  "#"
   "z_replacement_completed == 2"
   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
    (set (match_dup 1) (match_dup 2))
    (set (cc0) (match_dup 0))
    (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
-  "operands[2] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
+  "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
 
 
 ;;--------------------------------------------------------------------
 ;;
 (define_split
   [(set (cc0)
-       (compare (match_operand:HI 0 "hard_reg_operand" "dxy")
-                (match_operand:HI 1 "hard_reg_operand" "Aw")))]
-  "reload_completed"
+       (compare (match_operand:HI 0 "hard_reg_operand" "")
+                (match_operand:HI 1 "hard_reg_operand" "")))]
+  "TARGET_M6811
+   && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
   [(set (match_dup 2) (match_dup 1))
    (set (cc0)
         (compare (match_dup 0) (match_dup 2)))]
-  "operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);")
+  "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
+
+(define_split
+  [(set (cc0)
+       (compare (match_operand:HI 0 "hard_reg_operand" "")
+                (match_operand:HI 1 "hard_reg_operand" "")))]
+  "TARGET_M6812
+   && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
+  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
+   (set (cc0)
+        (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
+  "")
 
 (define_expand "cmphi"
   [(set (cc0)
   DONE;
 }")
 
-(define_insn "cmphi_1"
+(define_insn "cmphi_1_hc12"
   [(set (cc0)
        (compare (match_operand:HI 0 "tst_operand" 
-                               "x,dy,xyd,?xy,d,m,!u,dxy,dxy")
-                (match_operand:HI 1 "cmp_operand"
+                               "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
+                (match_operand:HI 1 "general_operand"
                                "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
-  ""
+  "TARGET_M6812"
   "*
 {
   if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
     return \"cp%0\\t%1\";
 }")
 
-(define_insn "cmphi_z_used"
+(define_insn "cmphi_1_hc11"
   [(set (cc0)
-       (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))]
-  ""
-  "#")
-  
-(define_split /* "cmphi_z_used" */
+       (compare (match_operand:HI 0 "tst_operand" 
+                               "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
+                (match_operand:HI 1 "cmp_operand"
+                               "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
+  "TARGET_M6811"
+  "*
+{
+  if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
+    {
+      cc_status.flags |= CC_REVERSED;
+      return \"cp%1\\t%0\";
+    }
+  else if (H_REG_P (operands[1]))
+    return \"#\";
+  else
+    return \"cp%0\\t%1\";
+}")
+
+(define_insn_and_split "cmphi_z_used"
   [(set (cc0)
        (compare (match_operand:HI 0 "tst_operand" "dxy,m")
-                (match_operand:HI 1 "cmp_operand" "m,dxy")))
+                (match_operand:HI 1 "cmp_operand" "mi,dxy")))
    (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
-   (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))
    (set (cc0) (compare (match_dup 0) (match_dup 1)))
    (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
-  "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
+  "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
 
 ;;
 ;; 8-bit comparison with address register.
 ;;
 (define_split
   [(set (cc0)
-       (compare (match_operand:QI 0 "hard_addr_reg_operand" "xy")
-                (match_operand:QI 1 "cmp_operand" "uimA")))]
+       (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
+                (match_operand:QI 1 "cmp_operand" "")))]
   "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
   [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
               (set (match_dup 3) (reg:HI D_REGNUM))])
         (compare (reg:QI D_REGNUM) (match_dup 1)))
    (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]));")
+  "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
 
 (define_split
   [(set (cc0)
-       (compare (match_operand:QI 0 "hard_reg_operand" "dxy")
-                (match_operand:QI 1 "hard_reg_operand" "dxy")))]
+       (compare (match_operand:QI 0 "hard_reg_operand" "")
+                (match_operand:QI 1 "hard_reg_operand" "")))]
   "reload_completed"
   [(set (match_dup 3) (match_dup 4))
    (set (cc0)
         (compare (match_dup 0) (match_dup 2)))]
-  "operands[2] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
-   operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
-   operands[4] = gen_rtx (REG, HImode, REGNO (operands[1]));")
+  "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
+   operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
+   operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
 
 (define_expand "cmpqi"
   [(set (cc0)
 
 (define_split /* "bitcmpqi" */
   [(set (cc0)
-       (and:QI (match_operand:QI 0 "tst_operand" "d")
-               (match_operand:QI 1 "hard_addr_reg_operand" "xy")))]
-  "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
+       (and:QI (match_operand:QI 0 "tst_operand" "")
+               (match_operand:QI 1 "hard_addr_reg_operand" "")))]
+  "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]));
-   operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
-   operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);")
+  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
+   operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
+   operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
 
-(define_insn "bitcmpqi_z_used"
+(define_insn_and_split "bitcmpqi_z_used"
   [(set (cc0)
        (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))]
   ""
-  "#")
-  
-(define_split /* "bitcmpqi_z_used" */
-  [(set (cc0)
-       (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))]
+  "#"
   "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))))]
-  "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
+   (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"
   [(set (cc0)
    return \"cmpb\\t%b0\";
 }")
 
-(define_insn "cmpqi_z_used"
+(define_insn_and_split "cmpqi_z_used"
   [(set (cc0)
        (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))]
   ""
-  "#")
-  
-(define_split /* cmpqi_z_used */
-  [(set (cc0)
-       (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))]
+  "#"
   "z_replacement_completed == 2"
   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
    (set (match_dup 2) (match_dup 3))
    (set (cc0) (compare (match_dup 0) (match_dup 1)))
    (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
-  "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
-
-(define_expand "cmpdf"
-  [(set (cc0)
-       (compare (match_operand:DF 0 "general_operand" "")
-                (match_operand:DF 1 "general_operand" "")))]
-  "0"
-  "
-{
-  m68hc11_compare_op0 = operands[0];
-  m68hc11_compare_op1 = operands[1];
-  DONE;
-}")
-
-(define_expand "cmpsf"
-  [(set (cc0)
-       (compare (match_operand:SF 0 "general_operand" "")
-                (match_operand:SF 1 "general_operand" "")))]
-  "0"
-  "
-{
-  m68hc11_compare_op0 = operands[0];
-  m68hc11_compare_op1 = operands[1];
-  DONE;
-}")
+  "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
 
 ;;--------------------------------------------------------------------
 ;;-  Move strict_low_part
 ;; (strict_low_part ...) information.  This is correct for our machine
 ;; description but not for GCC optimization passes.
 ;;
-(define_insn "movstrictsi"
+(define_insn_and_split "movstrictsi"
   [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
        (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
   ""
-  "#")
-
-(define_split
-  [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
-       (match_operand:SI 1 "general_operand" "D,Dim,u"))]
+  "#"
   "z_replacement_completed == 2"
   [(set (match_dup 0) (match_dup 1))]
   "")
 
-(define_insn "movstricthi"
+(define_insn_and_split "movstricthi"
   [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
        (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
   ""
-  "#")
-
-(define_split
-  [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
-       (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
+  "#"
   "z_replacement_completed == 2"
   [(set (match_dup 0) (match_dup 1))]
   "")
 
-(define_insn "movstrictqi"
+(define_insn_and_split "movstrictqi"
   [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
        (match_operand:QI 1 "general_operand" "d,imudA"))]
   ""
-  "#")
-
-(define_split
-  [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,dA"))
-       (match_operand:QI 1 "general_operand" "d,imudA"))]
+  "#"
   "z_replacement_completed == 2"
   [(set (match_dup 0) (match_dup 1))]
   "")
 ;; 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
 ")
 
 (define_insn "movdi_internal"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=U,!u,U,m,m,!u")
-       (match_operand:DI 1 "general_operand" "iU,iU,!u,mi,!u,!mu"))
-   (clobber (match_scratch:HI 2 "=&d,&d,&d,&d,&d,&d"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=ou,U,!u,U,m,m,!u")
+       (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
+   (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
   ""
   "#")
 
 (define_split
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=uUm")
-       (match_operand:DI 1 "general_operand" "iuUm"))
-   (clobber (match_scratch:HI 2 "=&d"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (match_operand:DI 1 "general_operand" ""))
+   (clobber (match_scratch:HI 2 ""))]
   "reload_completed"
   [(const_int 0)]
   "m68hc11_split_move (operands[0], operands[1], operands[2]);
 ")
 
 (define_insn "movdf_internal"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=U,!u,U,m,m,!u")
-       (match_operand:DF 1 "general_operand" "iU,iU,!u,mi,!u,!mu"))
-   (clobber (match_scratch:HI 2 "=&d,&d,&d,&d,&d,&d"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=ou,U,!u,U,m,m,!u")
+       (match_operand:DF 1 "general_operand" "G,iU,iU,!u,mi,!u,!mu"))
+   (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
   ""
   "#")
 
 (define_split
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=uUm")
-       (match_operand:DF 1 "general_operand" "iuUm"))
-   (clobber (match_scratch:HI 2 "=&d"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "")
+       (match_operand:DF 1 "general_operand" ""))
+   (clobber (match_scratch:HI 2 ""))]
   "reload_completed"
   [(const_int 0)]
   "m68hc11_split_move (operands[0], operands[1], operands[2]);
 ")
 
 (define_insn "movsi_internal"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,?D,m,?D,?u,?u,!u,D")
-       (match_operand:SI 1 "general_operand"      "imu,im,?D,!u,?D,mi,!u,!D"))
-   (clobber (match_scratch:HI 2                    "=&d,X,X,X,X,&d,&d,X"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=ou,mu,?D,m,?D,?u,?u,!u,D")
+       (match_operand:SI 1 "general_operand"      "K,imu,im,?D,!u,?D,mi,!u,!D"))
+   (clobber (match_scratch:HI 2                    "=X,&d,X,X,X,X,&d,&d,X"))]
   ""
   "#")
 
 (define_split
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D")
-       (match_operand:SI 1 "general_operand" "im,im,D,!u,D,mi,!u,!D"))
-   (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+       (match_operand:SI 1 "general_operand" ""))
+   (clobber (match_scratch:HI 2 ""))]
   "reload_completed"
   [(const_int 0)]
   "m68hc11_split_move (operands[0], operands[1], operands[2]);
 ")
 
 (define_insn "movsf_internal"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D")
-       (match_operand:SF 1 "general_operand" "im,im,D,!u,D,mi,!u,!D"))
-   (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=o!u,m,D,m,D,!u,!u,!u,D")
+       (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
+   (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
   ""
   "#")
 
 (define_split
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D")
-       (match_operand:SF 1 "general_operand" "im,im,D,!u,D,mi,!u,!D"))
-   (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "")
+       (match_operand:SF 1 "general_operand" ""))
+   (clobber (match_scratch:HI 2 ""))]
   "reload_completed"
   [(const_int 0)]
   "m68hc11_split_move (operands[0], operands[1], operands[2]);
 ;;--------------------------------------------------------------------
 
 (define_insn "*movhi2_push"
-  [(set (match_operand:HI 0 "push_operand" "=<,<")
-       (match_operand:HI 1 "general_operand" "xy,?d"))]
+  [(set (match_operand:HI 0 "push_operand" "=<,<,<")
+       (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
   "TARGET_M6811 && !TARGET_M6812"
   "*
 {
     {
       rtx insn;
 
-      insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
+      insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
                                          stack_pointer_rtx,
                                          REG_NOTES (insn));
 ;; appear in the source operand.
 ;;
 (define_split
-  [(set (match_operand:QI 0 "hard_addr_reg_operand" "=A")
+  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
         (match_operand:QI 1 "general_operand" ""))]
-  "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode
+  "z_replacement_completed == 2
    && !reg_mentioned_p (operands[0], operands[1])
-   && !D_REG_P (operands[1])"
+   && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
   [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
               (set (match_dup 2) (reg:HI D_REGNUM))])
    (set (reg:QI D_REGNUM) (match_dup 1))
    (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
               (set (match_dup 2) (reg:HI D_REGNUM))])]
-  "operands[2] = gen_rtx (REG, HImode, REGNO (operands[0]));")
+  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
 
 ;;
 ;; 8-bit operations on address registers.
 ;;
 (define_split
   [(set (match_operand:QI 0 "nonimmediate_operand" "")
-        (match_operand:QI 1 "hard_addr_reg_operand" "=A"))]
-  "z_replacement_completed == 2 && GET_MODE (operands[1]) == QImode
+        (match_operand:QI 1 "hard_addr_reg_operand" ""))]
+  "z_replacement_completed == 2
    && !reg_mentioned_p (operands[1], operands[0])
-   && !D_REG_P (operands[0])"
+   && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
   [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
               (set (match_dup 2) (reg:HI D_REGNUM))])
    (set (match_dup 0) (reg:QI D_REGNUM))
    (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
               (set (match_dup 2) (reg:HI D_REGNUM))])]
-  "operands[2] = gen_rtx (REG, HImode, REGNO (operands[1]));")
+  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
 
 (define_insn "*movqi2_push"
   [(set (match_operand:QI 0 "push_operand" "=<,<")
     {
       rtx insn;
 
-      insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
+      insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
                                          stack_pointer_rtx,
                                          REG_NOTES (insn));
 
 (define_insn "*movqi_68hc12"
   [(set (match_operand:QI 0 "nonimmediate_operand" 
-                               "=d*AU*q,d*A*q,*u,d*A*q,m,m")
+                               "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
        (match_operand:QI 1 "general_operand" 
-                               "*ri*q,U,*ri*qU,m,d*q,!A"))]
+                               "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
   "TARGET_M6812"
   "*
 {
 }")
 
 (define_insn "*movqi_m68hc11"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=dA*q,m,m,dA*q,*u")
-       (match_operand:QI 1 "general_operand" "dAim*q,d*q,!A,*u,dA*q"))]
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
+       (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
   "TARGET_M6811"
   "*
 {
   "#")
 
 (define_split
-  [(set (match_operand:DI 0 "push_operand" "=<")
-       (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "dmu*B")))
+  [(set (match_operand:DI 0 "push_operand" "")
+       (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
    (clobber (match_scratch:HI 2 "=&dB"))]
   "z_replacement_completed == 2"
   [(const_int 0)]
    /* Source operand must be in a hard register.  */
    if (!H_REG_P (src))
      {
-       src = gen_rtx (REG, QImode, REGNO (operands[2]));
+       src = gen_rtx_REG (QImode, REGNO (operands[2]));
        emit_move_insn (src, operands[1]);
      }
 
        else
         {
            emit_move_insn (push, operands[2]);
-           emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
-                                 gen_rtx (REG, HImode, HARD_SP_REGNUM),
+           emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
+                                 gen_rtx_REG (HImode, HARD_SP_REGNUM),
                                  const1_rtx));
         }
      }
      {
        /* Source is in X or Y.  It's better to push the 16-bit register
           and then to some stack adjustment.  */
-       src = gen_rtx (REG, HImode, REGNO (src));
+       src = gen_rtx_REG (HImode, REGNO (src));
        emit_move_insn (push, src);
        emit_move_insn (operands[2], const0_rtx);
-       emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
-                             gen_rtx (REG, HImode, HARD_SP_REGNUM),
+       emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
+                             gen_rtx_REG (HImode, HARD_SP_REGNUM),
                              const1_rtx));
        emit_move_insn (push, operands[2]);
-       emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
-                             gen_rtx (REG, HImode, HARD_SP_REGNUM),
+       emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
+                             gen_rtx_REG (HImode, HARD_SP_REGNUM),
                              const1_rtx));
      }      
    emit_move_insn (push, operands[2]);
 }")
 
 (define_split
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=mu")
-       (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "dmu*B")))
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
    (clobber (match_scratch:HI 2 "=&dB"))]
   "z_replacement_completed == 2"
   [(const_int 0)]
    /* Source operand must be in a hard register.  */
    if (!H_REG_P (src))
      {
-       src = gen_rtx (REG, QImode, REGNO (operands[2]));
+       src = gen_rtx_REG (QImode, REGNO (operands[2]));
        emit_move_insn (src, operands[1]);
      }
 
    emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
    emit_move_insn (operands[2], const0_rtx);
-   src = gen_rtx (REG, QImode, REGNO (operands[2]));
+   src = gen_rtx_REG (QImode, REGNO (operands[2]));
    emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
 
    emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
   "#")
 
 (define_split
-  [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,!u,!u")
+  [(set (match_operand:DI 0 "non_push_operand" "")
        (zero_extend:DI 
-           (match_operand:HI 1 "nonimmediate_operand" "m,dA,!u,dmA,!u")))
-   (clobber (match_scratch:HI 2 "=&d,&dB,&dB,&dB,&dB"))]
+           (match_operand:HI 1 "nonimmediate_operand" "")))
+   (clobber (match_scratch:HI 2 ""))]
   "z_replacement_completed == 2"
   [(const_int 0)]
   "
   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
        (zero_extend:DI 
            (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
-   (clobber (match_scratch:HI 2 "=d,d,&dB,d"))]
+   (clobber (match_scratch:HI 2 "=d,d,d,d"))]
   ""
   "#")
 
 (define_split 
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
        (zero_extend:DI 
-           (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
-   (clobber (match_scratch:HI 2 "=d,d,&dB,d"))]
+           (match_operand:SI 1 "nonimmediate_operand" "")))
+   (clobber (match_scratch:HI 2 ""))]
   "z_replacement_completed == 2"
   [(const_int 0)]
   "
   "#")
 
 (define_split
-  [(set (match_operand:SI 0 "non_push_operand" "=D,mu,m,m,!u,!u")
+  [(set (match_operand:SI 0 "non_push_operand" "")
        (zero_extend:SI 
-           (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,m,!u,m,!u")))
-   (clobber (match_scratch:HI 2 "=X,X,&d,&dB,&dB,&dB"))]
+           (match_operand:HI 1 "nonimmediate_operand" "")))
+   (clobber (match_scratch:HI 2 ""))]
   "reload_completed"
   [(const_int 0)]
   "
   "#")
 
 (define_split 
-  [(set (match_operand:SI 0 "non_push_operand" "=mu")
-       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dxy")))]
+  [(set (match_operand:SI 0 "non_push_operand" "")
+       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
   "reload_completed && !X_REG_P (operands[0])"
   [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
    (set (match_dup 3) (const_int 0))]
    operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
 
 (define_split 
-  [(set (match_operand:SI 0 "hard_reg_operand" "=D")
-       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dxymu")))]
+  [(set (match_operand:SI 0 "hard_reg_operand" "")
+       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
   "z_replacement_completed == 2 && X_REG_P (operands[0])"
   [(set (match_dup 2) (match_dup 3))
    (set (match_dup 4) (const_int 0))
   "
    if (X_REG_P (operands[1]))
      {
-       emit_insn (gen_swap_areg (gen_rtx (REG, HImode, HARD_D_REGNUM),
-                                 gen_rtx (REG, HImode, HARD_X_REGNUM)));
-       emit_insn (gen_zero_extendqihi2 (gen_rtx (REG, HImode, HARD_D_REGNUM),
-                                        gen_rtx (REG, QImode, HARD_D_REGNUM)));
-       emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM),
+       emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
+                                 gen_rtx_REG (HImode, HARD_X_REGNUM)));
+       emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
+                                        gen_rtx_REG (QImode, HARD_D_REGNUM)));
+       emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
                        const0_rtx);
        DONE;
      }
 
-   if (reg_mentioned_p (gen_rtx (REG, HImode, HARD_X_REGNUM), operands[1]))
+   if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
      {
        emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
                                                              operands[0]),
                                         operands[1]));
-       emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM), const0_rtx);
+       emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
        DONE;
      }
    operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
    operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
    if (A_REG_P (operands[1]))
      {
-       operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
-       operands[3] = gen_rtx (REG, HImode, REGNO (operands[1]));
-       operands[6] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
+       operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
+       operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
+       operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
      }
    else
      {
        operands[5] = operands[2] =
-       operands[3] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+       operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
        operands[6] = operands[1];
      }
 ")
 
 (define_insn "zero_extendqihi2"
-  [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!u,d,m,!u")
+  [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
        (zero_extend:HI 
            (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
   ""
   ""
   "*
 {
-  extern rtx ix_reg;
   rtx ops[3];
   int need_tst = 0;
 
     {
       if (!D_REG_P (operands[1]))
         {
-         ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
+         ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
          ops[1] = operands[1];
          m68hc11_gen_movqi (insn, ops);
        }
   if (X_REG_P (operands[0]))
     output_asm_insn (\"dex\", operands);
 
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
+  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
 
   if (!X_REG_P (operands[0]))
     {
        {
          if (!D_REG_P (operands[1]))
            {
-             ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
+             ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
              ops[1] = operands[1];
              m68hc11_gen_movqi (insn, ops);
            }
       output_asm_insn (\"bpl\\t%l0\", ops);
       output_asm_insn (\"deca\", operands);
 
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", 
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\", 
                                 CODE_LABEL_NUMBER (ops[0]));
     }
    else
          output_asm_insn (\"bpl\\t%l0\", ops);
         }
       output_asm_insn (\"dec\\t%h0\", operands);
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[0]));
     }
 
 ;; a temporary scratch memory location.
 ;;
 (define_split
-  [(set (match_operand:SI 0 "register_operand" "=D")
-       (sign_extend:SI (match_operand:HI 1 "register_operand" "A")))]
+  [(set (match_operand:SI 0 "register_operand" "")
+       (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
   "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
   [(set (reg:HI D_REGNUM) (match_dup 1))
    (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
   ""
   "*
 {
-  extern rtx ix_reg;
   rtx ops[2];
   int x_reg_used;
 
       x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
       if (x_reg_used)
         {
-         ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+         ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
          ops[1] = operands[1];
          m68hc11_gen_movhi (insn, ops);
         }
          Don't use it; keep it for documentation.  */
       if (!D_REG_P (operands[1]) && !x_reg_used)
         {
-          ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+          ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
           ops[1] = operands[1];
           m68hc11_gen_movhi (insn, ops);
         }
     }
   else
     {
-      ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
       ops[1] = operands[1];
       m68hc11_gen_movhi (insn, ops);
     }
   ops[0] = gen_label_rtx ();
   output_asm_insn (\"bpl\\t%l0\", ops);
   output_asm_insn (\"dex\", operands);
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
+  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
 
   return \"\";
 }")
   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
        (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
                 (match_operand:QI 2 "general_operand" "m,d")))]
-  "TARGET_M6812"
+  "TARGET_M6812 && TARGET_MIN_MAX"
   "*
 {
   /* Flags are set according to (sub:QI (operand 1) (operand2)).
   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
        (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
                 (match_operand:QI 2 "general_operand" "m,d")))]
-  "TARGET_M6812"
+  "TARGET_M6812 && TARGET_MIN_MAX"
   "*
 {
   /* Flags are set according to (sub:QI (operand 1) (operand2)).
   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
        (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
                 (match_operand:HI 2 "general_operand" "m,d")))]
-  "TARGET_M6812"
+  "TARGET_M6812 && TARGET_MIN_MAX"
   "*
 {
   /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
        (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
                 (match_operand:HI 2 "general_operand" "m,d")))]
-  "TARGET_M6812"
+  "TARGET_M6812 && TARGET_MIN_MAX"
   "*
 {
   /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
 ;;
 (define_expand "addsi3"
   [(parallel [(set (match_operand:SI 0 "register_operand" "")
-                    (plus:SI (match_operand:SI 1 "register_operand" "")
+                    (plus:SI (match_operand:SI 1 "general_operand" "")
                              (match_operand:SI 2 "general_operand" "")))
               (clobber (match_scratch:HI 3 ""))])]
   ""
   "")
 
-;;
-;; Translate D = D + D into D = D << 1
-;; We have to do this because adding a register to itself is not possible.
-;;
-;; Manipulation of A and B registers directly confuses the cse-regs pass
-;; so the split must be made after z-replacement register.
-;;
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "=D")
-       (plus:SI (match_dup 0)
-                (match_dup 0)))
-   (clobber (match_scratch:HI 1 "=X"))]
-  "reload_completed && z_replacement_completed == 2"
-  [(set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
-   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
-              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
-   (set (reg:QI B_REGNUM) (rotate:QI (reg:QI B_REGNUM) (reg:QI CC_REGNUM)))
-   (set (reg:QI A_REGNUM) (rotate:QI (reg:QI A_REGNUM) (reg:QI CC_REGNUM)))
-   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
-              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
-  "")
-
-
 (define_insn "*addsi3_zero_extendhi"
   [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
        (plus:SI (zero_extend:SI 
         }
       else if (!D_REG_P (operands[1]))
         {
-          ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+          ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
           ops[1] = operands[1];
           m68hc11_gen_movhi (insn, ops);
         }
   output_asm_insn (\"inx\", ops);
 
   CC_STATUS_INIT;
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
+  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
   return \"\";  
 }")
 
 
 (define_split /* "*addsi3_zero_extendqi" */
-  [(set (match_operand:SI 0 "register_operand" "=D,D")
+  [(set (match_operand:SI 0 "register_operand" "")
        (plus:SI (zero_extend:SI 
-                  (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
-                (match_operand:SI 2 "memory_operand" "m,m")))
+                  (match_operand:QI 1 "general_operand" ""))
+                (match_operand:SI 2 "memory_operand" "")))
    (clobber (match_scratch:HI 3 "=X,X"))]
   "reload_completed"
   [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
     {
       if (H_REG_P (operands[1]))
        {
-         ops[0] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
-         ops[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
+         ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
+         ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
          m68hc11_gen_movhi (insn, ops);
        }
       else
        {
          ops[0] = operands[1];
        }
-      ops[1] = gen_rtx (CONST_INT, VOIDmode, 0);
+      ops[1] = const0_rtx;
     }
   else
     {
         }
       else if (!D_REG_P (operands[1]))
         {
-          ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
+          ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
           ops[1] = operands[1];
           m68hc11_gen_movqi (insn, ops);
         }
       output_asm_insn (\"bcc\\t%l3\", ops);
       output_asm_insn (\"inx\", ops);
 
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[3]));
     }
   CC_STATUS_INIT;
 }")
 
 (define_insn "*addsi3"
-  [(set (match_operand:SI 0 "non_push_operand" "=m,D,!u,?D,D")
+  [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
        (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
-                (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?miu")))
+                (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
    (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
   ""
   "*
     }
   else
     {
-      ops[1] = gen_rtx (CONST_INT, VOIDmode, - val);
+      ops[1] = GEN_INT (- val);
       add_insn = \"subd\\t%1\";
       inc_insn = \"dex\";
       incb_mem  = \"dec\\t%b1\";
           output_asm_insn (inch_mem, ops);
        }
     }
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
+  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
 
   CC_STATUS_INIT;
   return \"\";
 }")
 
 (define_split
-  [(set (match_operand:SI 0 "register_operand" "=D,u")
-       (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_operand:SI 1 "register_operand" "")
                 (match_operand:SI 2 "const_int_operand" "")))
-   (clobber (match_scratch:HI 3 "=X,d"))]
+   (clobber (match_scratch:HI 3 ""))]
   "reload_completed && z_replacement_completed == 2
    && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
   [(set (match_dup 5) (match_dup 6))
   "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
    if (X_REG_P (operands[0]))
      {
-       operands[5] = operands[6] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+       operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
      }
    else
      {
    ")
 
 (define_split
-  [(set (match_operand:SI 0 "register_operand" "=D")
-       (plus:SI (match_operand:SI 1 "register_operand" "%0")
-                (match_operand:SI 2 "general_operand" "mui")))
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_operand:SI 1 "register_operand" "")
+                (match_operand:SI 2 "general_operand" "")))
    (clobber (match_scratch:HI 3 "=X"))]
   "reload_completed && z_replacement_completed == 2
    && (GET_CODE (operands[2]) != CONST_INT || 
   ops[0] = gen_label_rtx ();
   output_asm_insn (\"bcc\\t%l0\", ops);
   output_asm_insn (\"in%0\", operands);
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
+  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
   CC_STATUS_INIT;
   return \"\";
 }")
 {
   if (TARGET_M6811 && SP_REG_P (operands[0]))
     {
-      emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
-                        gen_rtx (SET, VOIDmode,
+      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
+                        gen_rtx_SET (VOIDmode,
                                  operand0,
-                                 gen_rtx (PLUS, HImode,
+                                 gen_rtx_PLUS (HImode,
                                           operand1, operand2)),
-                       gen_rtx (CLOBBER, VOIDmode,
-                               gen_rtx (SCRATCH, HImode)))));
+                       gen_rtx_CLOBBER (VOIDmode,
+                               gen_rtx_SCRATCH (HImode)))));
       DONE;
     }
 }")
 
-(define_split /* "*addhi3_strict_low_part" */
-  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+dxy"))
-        (plus:QI (match_operand:QI 1 "register_operand" "")
-                 (match_operand:QI 2 "general_operand" "")))]
-  "0 && z_replacement_completed == 2"
-  [(set (match_dup 0)
-       (plus:QI (match_dup 1) (match_dup 2)))]
-  "")
-
-(define_split /* "*addhi3_strict_low_part" */
-  [(set (match_operand:HI 0 "register_operand" "=dA")
-        (plus:HI (match_operand:HI 1 "register_operand" "%0")
-                 (match_operand:HI 2 "general_operand" "")))
-   (clobber (match_scratch:HI 3 ""))]
-  "0 && z_replacement_completed == 2 && !SP_REG_P (operands[0])"
-  [(set (match_dup 0)
-       (plus:HI (match_dup 1) (match_dup 2)))]
-  "")
-
 (define_insn "*addhi3_68hc12"
-  [(set (match_operand:HI 0 "register_operand" "=*d,A*w,A*w,A")
-        (plus:HI (match_operand:HI 1 "register_operand" "%0,0,Aw,0")
-                 (match_operand:HI 2 "general_operand" "imA*wu,id,id,!muA")))]
+  [(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" "i,m*A*wu,id,id,!mu*A")))]
   "TARGET_M6812"
   "*
 {
   int val;
   const char* insn_code;
 
-  if (which_alternative >= 3)
+  if (which_alternative >= 4)
     {
       if (A_REG_P (operands[2]))
         {
   else
     val = 1000;
 
-  if (val != -1 || val != 1 || !rtx_equal_p (operands[0], operands[1]))
+  if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
     {
       m68hc11_notice_keep_cc (operands[0]);
       switch (REGNO (operands[0]))
 {
   HOST_WIDE_INT val;
 
+  if (optimize && Y_REG_P (operands[3])
+      && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
+    operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
+
   if (GET_CODE (operands[2]) == CONST_INT
       && (val = INTVAL (operands[2])) != 0
       && (CONST_OK_FOR_LETTER_P (val, 'P')
          || (val > 0 && val <= 8)))
     {
-      if (optimize && Y_REG_P (operands[3])
-          && dead_register_here (insn, gen_rtx (REG, HImode, HARD_X_REGNUM)))
-       operands[3] = gen_rtx (REG, HImode, HARD_X_REGNUM);
       while (val > 1 || val < -1)
        {
          if (val > 0)
       return \"\";
     }
 
-  /* Need to transfer to SP to IY and then to D register.
-     Register IY is lost, this is specified by the (clobber) statement.  */
+  /* Need to transfer to SP to X/Y and then to D register.
+     Register X/Y is lost, this is specified by the (clobber) statement.  */
   output_asm_insn (\"ts%3\", operands);
-  output_asm_insn (\"xgd%3\", operands);
-  output_asm_insn (\"addd\\t%2\", operands);
-  output_asm_insn (\"xgd%3\", operands);
+  if (GET_CODE (operands[2]) == CONST_INT
+      && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
+      && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
+    {
+      output_asm_insn (\"ldab\\t%2\", operands);
+      output_asm_insn (\"ab%3\", operands);
+      CC_STATUS_INIT;
+    }
+  else
+    {
+      output_asm_insn (\"xgd%3\", operands);
+      output_asm_insn (\"addd\\t%2\", operands);
+      output_asm_insn (\"xgd%3\", operands);
+    }
 
    /* The status flags correspond to the addd.  xgdy and tys do not
       modify the flags.  */
   return \"t%3s\";
 }")
 
-;;
-;; Translate d = d + d into d = d << 1
-;; We have to do this because adding a register to itself is not possible.
-;; ??? It's not clear whether this is really necessary.
-;;
-(define_split
-  [(set (match_operand:HI 0 "hard_reg_operand" "=dA")
-       (plus:HI (match_dup 0)
-                (match_dup 0)))]
-  "reload_completed"
-  [(set (match_dup 0) (ashift:HI (match_dup 0) (const_int 1)))]
-  "")
-
 (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"
   "*
 {
   const char* insn_code;
   int val;
-  extern rtx ix_reg;
 
   if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
     {
 ;; ??? It's not clear whether this is really necessary.
 ;;
 (define_split
-  [(set (match_operand:QI 0 "hard_reg_operand" "=dA")
+  [(set (match_operand:QI 0 "hard_reg_operand" "")
        (plus:QI (match_dup 0)
                 (match_dup 0)))]
   "0 && reload_completed"
   "")
 
 (define_insn "*subsi3"
-  [(set (match_operand:SI 0 "register_operand" "=D,D")
-       (minus:SI (match_operand:SI 1 "general_operand" "0,!mui")
-                 (match_operand:SI 2 "general_operand" "!mui,!D")))
-   (clobber (match_scratch:HI 3 "=X,X"))]
+  [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
+       (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
+                 (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
+   (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
   ""
   "#")
 
 (define_insn "*subsi3_zero_extendhi"
   [(set (match_operand:SI 0 "register_operand" "=D")
        (minus:SI (match_operand:SI 1 "register_operand" "0")
-           (zero_extend:SI (match_operand:HI 2 "general_operand" "d!mui"))))
+           (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
    (clobber (match_scratch:HI 3 "=X"))]
   ""
   "*
 {
   rtx ops[2];
 
+  if (A_REG_P (operands[2]))
+    {
+      if (TARGET_M6812)
+        ops[0] = gen_rtx_MEM (HImode,
+                         gen_rtx_PRE_DEC (HImode,
+                                  gen_rtx_REG (HImode, HARD_SP_REGNUM)));
+      else
+        ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
+
+      ops[1] = operands[2];
+      m68hc11_gen_movhi (insn, ops);
+      if (TARGET_M6812)
+        operands[2] = gen_rtx_MEM (HImode,
+                              gen_rtx_POST_INC (HImode,
+                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
+      else
+        operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
+    }
   ops[0] = gen_label_rtx (); 
   output_asm_insn (\"subd\\t%2\", operands);
   output_asm_insn (\"bcc\\t%l0\", ops);
   output_asm_insn (\"dex\", ops);
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
+  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
   CC_STATUS_INIT;
   return \"\";
 }")
 (define_insn "*subsi3_zero_extendqi"
   [(set (match_operand:SI 0 "register_operand" "=D")
        (minus:SI (match_operand:SI 1 "register_operand" "0")
-           (zero_extend:SI (match_operand:QI 2 "general_operand" "!dmui"))))
+           (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
    (clobber (match_scratch:HI 3 "=X"))]
   ""
   "*
 {
   rtx ops[2];
 
+  if (A_REG_P (operands[2]))
+    {
+      ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
+      ops[1] = operands[2];
+      m68hc11_gen_movhi (insn, ops);
+      operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
+    }
   ops[0] = gen_label_rtx (); 
   output_asm_insn (\"subb\\t%b2\", operands);
   output_asm_insn (\"sbca\\t#0\", operands);
   output_asm_insn (\"bcc\\t%l0\", ops);
   output_asm_insn (\"dex\", ops);
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
+  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
   CC_STATUS_INIT;
   return \"\";
 }")
 ;; reg:QI 7 -> ccr      reg:QI 5 -> A
 ;;
 (define_split /* "*subsi3" */
-  [(set (match_operand:SI 0 "register_operand" "=D")
-       (minus:SI (match_operand:SI 1 "register_operand" "0")
-                 (match_operand:SI 2 "general_operand" "mui")))
+  [(set (match_operand:SI 0 "register_operand" "")
+       (minus:SI (match_operand:SI 1 "register_operand" "")
+                 (match_operand:SI 2 "general_operand" "")))
    (clobber (match_scratch:HI 3 "=X"))]
   "reload_completed && z_replacement_completed == 2
    && X_REG_P (operands[1])"
    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
 
 (define_split /* "*subsi3" */
-  [(set (match_operand:SI 0 "register_operand" "=D")
-       (minus:SI (match_operand:SI 1 "general_operand" "mui")
-                 (match_operand:SI 2 "register_operand" "D")))
+  [(set (match_operand:SI 0 "register_operand" "")
+       (minus:SI (match_operand:SI 1 "general_operand" "")
+                 (match_operand:SI 2 "register_operand" "")))
    (clobber (match_scratch:HI 3 "=X"))]
   "reload_completed && z_replacement_completed == 2
    && X_REG_P (operands[2])"
    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
 
+(define_split /* "*subsi3" */
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+       (minus:SI (match_operand:SI 1 "general_operand" "")
+                 (match_operand:SI 2 "general_operand" "")))
+   (clobber (match_scratch:HI 3 "=d"))]
+  "reload_completed && z_replacement_completed == 2
+   && !X_REG_P (operands[0])"
+  [(set (match_dup 3) (match_dup 4))
+   (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
+   (set (match_dup 4) (match_dup 3))
+   (set (match_dup 3) (match_dup 6))
+   (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
+   (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
+   (set (match_dup 6) (match_dup 3))]
+  "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
+   operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
+   operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
+   operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
+   operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
+   operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
+
 ;;
 ;; - 16-bit Subtract.
 ;;
        (minus:HI (match_operand:HI 1 "register_operand" "0")
                  (match_operand:HI 2 "general_operand" "g")))]
   ""
-  "
-{
-  if (TARGET_M6811 && SP_REG_P (operands[0]))
-    {
-     emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
-                        gen_rtx (SET, VOIDmode,
-                                 operand0,
-                                 gen_rtx (MINUS, HImode,
-                                          operand1, operand2)),
-                       gen_rtx (CLOBBER, VOIDmode,
-                               gen_rtx (SCRATCH, HImode, 0)))));
-     DONE;
-  }
-}")
+  "")
 
 ;;
 ;; Subtract from stack. This is better if we provide a pattern.
 
   if (D_REG_P (operands[3]))
     {
-      output_asm_insn (\"xgdx\", operands);
+      int save_x;
+
+      save_x = !dead_register_here (insn, ix_reg);
+      if (save_x)
+       output_asm_insn (\"xgdx\", operands);
       output_asm_insn (\"tsx\", operands);
       output_asm_insn (\"xgdx\", operands);
       output_asm_insn (\"subd\\t%2\", operands);
       /* The status flags correspond to the addd. xgdx/y and tx/ys do not
          modify the flags.  */
       output_asm_insn (\"txs\", operands);
-      return \"xgdx\";
+      if (save_x)
+        return \"xgdx\";
+      else
+        return \"\";
     }
 
   /* Need to transfer to SP to X,Y and then to D register.
     {
       rtx ops[2];
 
-      ops[0] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
+      ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
       ops[1] = operands[2];
       m68hc11_gen_movqi (insn, ops);
       return \"subb\\t%T0\\n\\tsbca\\t#0\";
          operands[1] = temp;
        }
 
-      ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
+      ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
       ops[1] = operands[2];
       m68hc11_gen_movqi (insn, ops);
 
 }")
 
 (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);
   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
     {
       rtx ops[2];
 
-      ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
+      ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
       ops[1] = operands[2];
       m68hc11_gen_movqi (insn, ops);
     }
 ;;- and instructions.
 ;;--------------------------------------------------------------------
 
-(define_insn "anddi3"
+(define_insn_and_split "anddi3"
   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
        (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
                (match_operand:DI 2 "general_operand" "imu,imu")))
    (clobber (match_scratch:HI 3 "=d,d"))]
   ""
-  "#")
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "m68hc11_split_logical (SImode, AND, operands);
+   DONE;")
 
-(define_insn "andsi3"
+(define_insn_and_split "andsi3"
   [(set (match_operand:SI 0 "register_operand" "=D,!u")
        (and:SI (match_operand:SI 1 "register_operand" "%0,0")
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
    (clobber (match_scratch:HI 3 "=X,d"))]
   ""
-  "#")
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "m68hc11_split_logical (HImode, AND, operands);
+   DONE;")
 
 (define_expand "andhi3"
   [(set (match_operand:HI 0 "register_operand" "")
   CC_STATUS_INIT;
 
   /* The bclr instruction uses an inverted mask.  */
-  operands[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FFFF);
+  operands[1] = GEN_INT ((~val) & 0x0FFFF);
 
   /* When destination is a global variable, generate a .relax instruction
      and load the address in the clobber register.  That load can be
       if ((val & 0x0FF00) != 0x0FF00)
         output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
 
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[2]));
       return \"\";
     }
       rtx ops[2];
 
       ops[0] = operands[0];
-      ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
+      ops[1] = GEN_INT ((~val) & 0x0FF);
       output_asm_insn (\"bclr\\t%b0, %1\", ops);
     }
   else if ((val & 0x0FF) != 0)
       rtx ops[2];
 
       ops[0] = operands[0];
-      ops[1] = gen_rtx (CONST_INT, VOIDmode, ((~val) & 0x0FF00) >> 8);
+      ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
       output_asm_insn (\"bclr\\t%h0, %1\", ops);
     }
   else if ((val & 0x0FF00) != 0)
     return \"#\";
 
   CC_STATUS_INIT;
-  return \"andb\\t%b2\\n\\tanda\\t%h2\";
+  return \"anda\\t%h2\\n\\tandb\\t%b2\";
 }")
 
 (define_expand "andqi3"
     }
 
   /* The bclr instruction uses an inverted mask.  */
-  operands[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
+  operands[1] = GEN_INT ((~val) & 0x0FF);
 
   /* When destination is a global variable, generate a .relax instruction
      and load the address in the clobber register.  That load can be
       output_asm_insn (\".relax\\t%l2\", ops);
       m68hc11_gen_movhi (insn, ops);
       output_asm_insn (\"bclr\\t0,%2, %1\", operands);
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[2]));
       return \"\";
     }
       rtx ops[2];
 
       ops[0] = operands[0];
-      ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
+      ops[1] = GEN_INT ((~val) & 0x0FF);
       output_asm_insn (\"bclr\\t%b0, %b1\", ops);
       return \"\";
     }
 ;;- Bit set or instructions.
 ;;--------------------------------------------------------------------
 
-(define_insn "iordi3"
+(define_insn_and_split "iordi3"
   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
        (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
                (match_operand:DI 2 "general_operand" "imu,imu")))
    (clobber (match_scratch:HI 3 "=d,d"))]
   ""
-  "#")
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "m68hc11_split_logical (SImode, IOR, operands);
+   DONE;")
 
-(define_insn "iorsi3"
+(define_insn_and_split "iorsi3"
   [(set (match_operand:SI 0 "register_operand" "=D,!u")
        (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
    (clobber (match_scratch:HI 3 "=X,d"))]
   ""
-  "#")
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "m68hc11_split_logical (HImode, IOR, operands);
+   DONE;")
 
 (define_expand "iorhi3"
   [(set (match_operand:HI 0 "register_operand" "")
 
       if ((val & 0x0FF00) != 0)
         output_asm_insn (\"bset\\t0,%2, %h1\", operands);
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[2]));
       return \"\";
     }
     return \"#\";
 
   CC_STATUS_INIT;
-  return \"orab\\t%b2\\n\\toraa\\t%h2\";
+  return \"oraa\\t%h2\\n\\torab\\t%b2\";
 }")
 
 (define_expand "iorqi3"
       output_asm_insn (\".relax\\t%l2\", ops);
       m68hc11_gen_movhi (insn, ops);
       output_asm_insn (\"bset\\t0,%2, %1\", operands);
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[2]));
       return \"\";
     }
 ;;- xor instructions.
 ;;--------------------------------------------------------------------
 
-(define_insn "xordi3"
+(define_insn_and_split "xordi3"
   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
        (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
                (match_operand:DI 2 "general_operand" "imu,imu")))
    (clobber (match_scratch:HI 3 "=d,d"))]
   ""
-  "#")
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "m68hc11_split_logical (SImode, XOR, operands);
+   DONE;")
 
-(define_insn "xorsi3"
+(define_insn_and_split "xorsi3"
   [(set (match_operand:SI 0 "register_operand" "=D,!u")
        (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
    (clobber (match_scratch:HI 3 "=X,d"))]
   ""
-  "#")
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "m68hc11_split_logical (HImode, XOR, operands);
+   DONE;")
 
 (define_insn "xorhi3"
   [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
     }
 
   CC_STATUS_INIT;
-  return \"eorb\\t%b2\\n\\teora\\t%h2\";
+  return \"eora\\t%h2\\n\\teorb\\t%b2\";
 }")
 
 (define_insn "xorqi3"
 ;;- Bit set or instructions.
 ;;--------------------------------------------------------------------
 
-(define_insn "*logicalsi3_zexthi"
+(define_insn_and_split "*logicalsi3_zexthi"
   [(set (match_operand:SI 0 "register_operand" "=D")
        (match_operator:SI 3 "m68hc11_logical_operator"
                [(zero_extend:SI
                     (match_operand:HI 1 "general_operand" "imudA"))
                 (match_operand:SI 2 "general_operand" "Dimu")]))]
   ""
-  "#")
-
-(define_insn "*logicalsi3_zextqi"
-  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
-       (match_operator:SI 3 "m68hc11_logical_operator"
-               [(zero_extend:SI
-                    (match_operand:QI 1 "general_operand" "d,*A,imu"))
-                (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
-  ""
-  "#")
-
-(define_split /* logicalsi3_zextqi */
-  [(set (match_operand:SI 0 "register_operand" "")
-       (match_operator:SI 3 "m68hc11_logical_operator"
-                [(zero_extend:SI
-                    (match_operand:QI 1 "general_operand" ""))
-                 (match_operand:SI 2 "general_operand" "")]))]
-  "z_replacement_completed == 2"
-  [(set (reg:QI A_REGNUM) (match_dup 4))
-   (set (reg:QI D_REGNUM) (match_dup 7))
-   (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
+  "#"
+  "reload_completed"
+  [(set (reg:HI D_REGNUM) (match_dup 4))
+   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
    (set (reg:HI X_REGNUM) (match_dup 6))]
-  "PUT_MODE (operands[3], QImode);
+  "PUT_MODE (operands[3], HImode);
    if (X_REG_P (operands[2]))
      {
        operands[5] = operands[1];
        /* Make all the (set (REG:x) (REG:y)) a nop set.  */
-       operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM);
-       operands[7] = gen_rtx (REG, QImode, HARD_D_REGNUM);
+       operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
        operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
      }
    else
      {
-       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
-       operands[7] = operands[1];
-       operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
-       operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
+       operands[4] = operands[1];
+       operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
        operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
      }
-   /* For an AND, make sure the high 24-bit part is cleared.  */
+   /* For an AND, make sure the high 16-bit part is cleared.  */
    if (GET_CODE (operands[3]) == AND)
      {
-       operands[4] = const0_rtx;
        operands[6] = const0_rtx;
      }
    ")
 
-(define_split /* logicalsi3_zexthi */
-  [(set (match_operand:SI 0 "register_operand" "")
+(define_insn_and_split "*logicalsi3_zextqi"
+  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
        (match_operator:SI 3 "m68hc11_logical_operator"
-                [(zero_extend:SI
-                    (match_operand:HI 1 "general_operand" ""))
-                 (match_operand:SI 2 "general_operand" "")]))]
-  "reload_completed"
-  [(set (reg:HI D_REGNUM) (match_dup 4))
-   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
+               [(zero_extend:SI
+                    (match_operand:QI 1 "general_operand" "d,*A,imu"))
+                (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
+  ""
+  "#"
+  "z_replacement_completed == 2"
+  [(set (reg:QI A_REGNUM) (match_dup 4))
+   (set (reg:QI D_REGNUM) (match_dup 7))
+   (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
    (set (reg:HI X_REGNUM) (match_dup 6))]
-  "PUT_MODE (operands[3], HImode);
+  "PUT_MODE (operands[3], QImode);
    if (X_REG_P (operands[2]))
      {
        operands[5] = operands[1];
        /* Make all the (set (REG:x) (REG:y)) a nop set.  */
-       operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
-       operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
+       operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
+       operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
+       operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
      }
    else
      {
-       operands[4] = operands[1];
-       operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
+       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
+       operands[7] = operands[1];
+       operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
+       operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
        operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
      }
-   /* For an AND, make sure the high 16-bit part is cleared.  */
+   /* For an AND, make sure the high 24-bit part is cleared.  */
    if (GET_CODE (operands[3]) == AND)
      {
+       operands[4] = const0_rtx;
        operands[6] = const0_rtx;
      }
    ")
 
-(define_insn "*logicalhi3_zexthi_ashift8"
+(define_insn_and_split "*logicalhi3_zexthi_ashift8"
   [(set (match_operand:HI 0 "register_operand" "=d")
        (match_operator:HI 3 "m68hc11_logical_operator"
                [(zero_extend:HI
-                    (match_operand:QI 1 "general_operand" "imud"))
+                    (match_operand:QI 1 "general_operand" "imud*A"))
                 (ashift:HI
-                    (match_operand:HI 2 "general_operand" "dimu")
+                    (match_operand:HI 2 "general_operand" "imud*A")
                     (const_int 8))]))]
   ""
-  "#")
+  "#"
+  "z_replacement_completed == 2"
+  [(set (reg:QI A_REGNUM) (match_dup 4))
+   (set (reg:QI B_REGNUM) (match_dup 5))]
+  "
+   if (GET_CODE (operands[3]) == AND)
+     {
+       emit_insn (gen_movhi (operands[0], const0_rtx));
+       DONE;
+     }
+   else
+     {
+       operands[5] = operands[1];
+       if (D_REG_P (operands[2]))
+         {
+           operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
+         }
+       else
+         {
+           operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
+         }
+     }
+  ")
 
-(define_insn "*logicalhi3_zexthi"
+(define_insn_and_split "*logicalhi3_zexthi"
   [(set (match_operand:HI 0 "register_operand" "=d,d")
        (match_operator:HI 3 "m68hc11_logical_operator"
                [(zero_extend:HI
                     (match_operand:QI 1 "general_operand" "imd*A,?u"))
                 (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
   ""
-  "#")
-
-(define_split /* logicalhi3_zexthi */
-  [(set (match_operand:HI 0 "register_operand" "")
-       (match_operator:HI 3 "m68hc11_logical_operator"
-               [(zero_extend:HI
-                    (match_operand:QI 1 "general_operand" ""))
-                (match_operand:HI 2 "general_operand" "")]))]
+  "#"
   "z_replacement_completed == 2"
   [(set (reg:QI B_REGNUM) (match_dup 6))
    (set (reg:QI A_REGNUM) (match_dup 4))
    PUT_MODE (operands[3], QImode);
    if (D_REG_P (operands[2]))
      {
-       operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM);
+       operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
        operands[5] = operands[1];
-       operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM);
+       operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
      }
    else
      {
        operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
        operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
        if (D_REG_P (operands[1]))
-        operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM);
+        operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
        else
          operands[6] = operands[1];
      }
      }
   ")
 
-(define_split /* logicalhi3_zexthi_ashift8 */
-  [(set (match_operand:HI 0 "register_operand" "")
-       (match_operator:HI 3 "m68hc11_logical_operator"
-               [(zero_extend:HI
-                    (match_operand:QI 1 "general_operand" ""))
-                (ashift:HI
-                    (match_operand:HI 2 "general_operand" "")
-                    (const_int 8))]))]
-  "z_replacement_completed == 2"
-  [(set (reg:QI A_REGNUM) (match_dup 4))
-   (set (reg:QI B_REGNUM) (match_dup 5))]
-  "
-   if (GET_CODE (operands[3]) == AND)
-     {
-       emit_insn (gen_movhi (operands[0], const0_rtx));
-       DONE;
-     }
-   else
-     {
-       operands[5] = operands[1];
-       if (D_REG_P (operands[2]))
-         {
-           operands[4] = gen_rtx (REG, QImode, HARD_B_REGNUM);
-         }
-       else
-         {
-           operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
-         }
-     }
-  ")
 
-(define_insn "*logicalsi3_silshr16"
-  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
+(define_insn_and_split "*logicalsi3_silshr16"
+  [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
           (match_operator:SI 3 "m68hc11_logical_operator"
              [(lshiftrt:SI 
-                  (match_operand:SI 1 "general_operand" "uim,uim,?D")
+                  (match_operand:SI 1 "general_operand" "uim,uim,0,0")
                   (const_int 16))
-               (match_operand:SI 2 "general_operand" "uim,0,0")]))]
+               (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
   ""
-  "#")
-
-(define_split /* logicalsi3_silshr16 */
-  [(set (match_operand:SI 0 "register_operand" "")
-          (match_operator:SI 3 "m68hc11_logical_operator"
-               [(lshiftrt:SI 
-                       (match_operand:SI 1 "general_operand" "")
-                       (const_int 16))
-                (match_operand:SI 2 "general_operand" "")]))]
+  "#"
   "reload_completed"
   [(set (reg:HI D_REGNUM) (match_dup 4))
    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
   "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
    if (X_REG_P (operands[2]))
      {
-       operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
-       operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
+       operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
+       operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
      }
    else
      {
      }
 ")
 
-(define_insn "*logicalsi3_silshl16"
+(define_insn_and_split "*logicalsi3_silshl16"
   [(set (match_operand:SI 0 "register_operand" "=D,D")
           (match_operator:SI 3 "m68hc11_logical_operator"
              [(ashift:SI 
                   (const_int 16))
                (match_operand:SI 2 "general_operand" "0,0")]))]
   ""
-  "#")
-
-(define_split /* logicalsi3_silshl16 */
-  [(set (match_operand:SI 0 "register_operand" "")
-          (match_operator:SI 3 "m68hc11_logical_operator"
-               [(ashift:SI 
-                       (match_operand:SI 1 "general_operand" "")
-                       (const_int 16))
-                (match_operand:SI 2 "general_operand" "")]))]
+  "#"
   "z_replacement_completed == 2"
   [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
    (set (reg:HI D_REGNUM) (match_dup 5))]
    if (GET_CODE (operands[3]) == AND)
      operands[5] = const0_rtx;
    else
-     operands[5] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+     operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
    ")
 
-
-;;--------------------------------------------------------------------
-;;- 64/32-bit Logical Operations.  Patterns are defined so that GCC
-;; can optimize correctly.  These insns are split by the `final'
-;; pass (# pattern).  They are split to fall in the corresponding
-;; 16-bit logical patterns.
-;;--------------------------------------------------------------------
-
-;; Split 64-bit logical operations: anddi3, iordi3, xordi3
-(define_split
-  [(set (match_operand:DI 0 "reg_or_some_mem_operand" "")
-       (match_operator:DI 4 "m68hc11_logical_operator"
-            [(match_operand:DI 1 "reg_or_some_mem_operand" "")
-             (match_operand:DI 2 "general_operand" "")]))
-   (clobber (match_scratch:HI 3 ""))]
+(define_insn_and_split "*logicalsi3_silshl16_zext"
+  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
+          (match_operator:SI 3 "m68hc11_logical_operator"
+             [(ashift:SI
+                 (zero_extend:SI
+                    (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
+                 (const_int 16))
+           (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
+  ""
+  "#"
+  ;; Must split before z register replacement
   "reload_completed"
-  [(const_int 0)]
-  "m68hc11_split_logical (SImode, GET_CODE (operands[4]), operands);
-   DONE;")
-
-;; Split 32-bit logical operations: andsi3, iorsi3, xorsi3
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (match_operator:SI 3 "m68hc11_logical_operator"
-            [(match_operand:SI 1 "register_operand" "")
-             (match_operand:SI 2 "general_operand" "")]))]
-  "0 && reload_completed"
-  [(const_int 0)]
-  "m68hc11_split_logical (HImode, GET_CODE (operands[3]), operands);
-   DONE;")
+  [(set (match_dup 4) (match_dup 5))
+   (set (match_dup 6) (match_dup 7))]
+  "
+    /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
+   if (GET_CODE (operands[1]) == HARD_D_REGNUM
+       && GET_CODE (operands[3]) != AND)
+     {
+       /* This particular case is too early to be split before
+          Z register replacement because the cse-reg pass we do
+         does not recognize the 'swap_areg'.  It is ok to handle
+         this case after.  */
+       if (z_replacement_completed != 2)
+         {
+          FAIL;
+        }
+       emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM), operands[2]);
+       emit_insn (gen_swap_areg (gen_rtx (REG, HImode, HARD_D_REGNUM),
+                                gen_rtx (REG, HImode, HARD_X_REGNUM)));
+     }
+   operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+   operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
+   operands[5] = operands[2];
+   operands[7] = operands[1];
 
-;; Split 32-bit logical operations: andsi3, iorsi3, xorsi3
-(define_split
-  [(set (match_operand:SI 0 "reg_or_some_mem_operand" "")
-       (match_operator:SI 4 "m68hc11_logical_operator"
-            [(match_operand:SI 1 "reg_or_some_mem_operand" "")
-             (match_operand:SI 2 "general_operand" "")]))
-   (clobber (match_scratch:HI 3 ""))]
-  "reload_completed"
-  [(const_int 0)]
-  "m68hc11_split_logical (HImode, GET_CODE (operands[4]), operands);
-   DONE;")
+   if (GET_CODE (operands[3]) == AND)
+     operands[5] = operands[7] = const0_rtx;
+   ")
 
 ;;--------------------------------------------------------------------
 ;; 16-bit Arithmetic and logical operations on X and Y:
 ;;
 ;;
 (define_split
-  [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A")
+  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
        (match_operator:HI 3 "m68hc11_arith_operator"
-            [(match_operand:HI 1 "hard_addr_reg_operand" "0")
-            (match_operand:HI 2 "general_operand" "dAuim")]))]
+            [(match_operand:HI 1 "hard_addr_reg_operand" "")
+            (match_operand:HI 2 "general_operand" "")]))]
   "z_replacement_completed == 2
    /* If we are adding a small constant to X or Y, it's
      better to use one or several inx/iny instructions.  */
             || (GET_CODE (operands[2]) == CONST_INT
                && INTVAL (operands[2]) >= -4
                && INTVAL (operands[2]) <= 4)))"
-  [(set (match_dup 4) (match_dup 5))
+  [(set (match_dup 9) (match_dup 0))
+   (set (match_dup 4) (match_dup 5))
    (set (match_dup 8) (match_dup 7))
+   (set (match_dup 0) (match_dup 1))
    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
               (set (match_dup 0) (reg:HI D_REGNUM))])
    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
               (set (match_dup 0) (reg:HI D_REGNUM))])]
   "
+   operands[9] = operands[0];
+   /* For 68HC12, push the value on the stack and do the operation
+      with a pop.  */
+   if (TARGET_M6812
+       && m68hc11_non_shift_operator (operands[3], HImode)
+       && (H_REG_P (operands[2])
+          || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
+              && reg_mentioned_p (operands[0], operands[2]))))
+     {
+       operands[4] = gen_rtx_MEM (HImode,
+                             gen_rtx_PRE_DEC (HImode,
+                                      gen_rtx_REG (HImode, HARD_SP_REGNUM)));
+       operands[6] = gen_rtx_MEM (HImode,
+                             gen_rtx_POST_INC (HImode,
+                                      gen_rtx_REG (HImode, HARD_SP_REGNUM)));
+       operands[5] = operands[2];
+       operands[8] = operands[7] = operands[0];
+     }
    /* Save the operand2 in a temporary location and use it.  */
-   if ((H_REG_P (operands[2])
-        || reg_mentioned_p  (operands[0], operands[2]))
-       && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
+   else if ((H_REG_P (operands[2])
+             || reg_mentioned_p  (operands[0], operands[2]))
+            && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
      {
-       operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
+       if (GET_CODE (operands[3]) == MINUS
+          && reg_mentioned_p (operands[0], operands[2]))
+        {
+          operands[9] = gen_rtx_MEM (HImode,
+                             gen_rtx_PRE_DEC (HImode,
+                                      gen_rtx_REG (HImode, HARD_SP_REGNUM)));
+          operands[1] = gen_rtx_MEM (HImode,
+                             gen_rtx_POST_INC (HImode,
+                                      gen_rtx_REG (HImode, HARD_SP_REGNUM)));
+          operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
+          operands[4] = operands[7] = operands[0];
+          operands[6] = operands[8];
+          operands[5] = operands[2];
+        }
+       else 
+        {
+       operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
        operands[6] = operands[4];
        if (!H_REG_P (operands[2]))
         {
            operands[5] = operands[2];
           operands[8] = operands[7] = operands[0];
         }
+        }
      }
    else
      {
    ")
 
 (define_split
-  [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A")
+  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
        (match_operator:HI 3 "m68hc11_arith_operator"
-            [(match_operand:HI 1 "general_operand" "mu")
-            (match_operand:HI 2 "general_operand" "dAuim")]))]
+            [(match_operand:HI 1 "general_operand" "")
+            (match_operand:HI 2 "general_operand" "")]))]
   "z_replacement_completed == 2
    /* If we are adding a small constant to X or Y, it's
      better to use one or several inx/iny instructions.  */
 ;; The shift operators are special and must not appear here.
 ;;
 (define_split
-  [(set (match_operand:HI 0 "d_register_operand" "=d")
+  [(set (match_operand:HI 0 "d_register_operand" "")
        (match_operator:HI 3 "m68hc11_non_shift_operator"
-            [(match_operand:HI 1 "d_register_operand" "%0")
-            (match_operand:HI 2 "hard_reg_operand" "*d*A")]))]
-  "z_replacement_completed == 2 && !SP_REG_P (operands[2])"
+            [(match_operand:HI 1 "d_register_operand" "")
+            (match_operand:HI 2 "hard_reg_operand" "")]))]
+  "TARGET_M6811
+   && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
   [(set (match_dup 4) (match_dup 2))
    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
-  "operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);")
+  "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
+
+;;
+;; For 68HC12, push the operand[2] value on the stack and do the
+;; logical/arithmetic operation with a pop.
+;;
+(define_split
+  [(set (match_operand:HI 0 "d_register_operand" "")
+       (match_operator:HI 3 "m68hc11_non_shift_operator"
+            [(match_operand:HI 1 "d_register_operand" "")
+            (match_operand:HI 2 "hard_reg_operand" "")]))]
+  "TARGET_M6812
+   && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
+  [(set (match_dup 4) (match_dup 2))
+   (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
+  "operands[4] = gen_rtx_MEM (HImode,
+                         gen_rtx_PRE_DEC (HImode,
+                                  gen_rtx_REG (HImode, HARD_SP_REGNUM)));
+   operands[5] = gen_rtx_MEM (HImode,
+                         gen_rtx_POST_INC (HImode,
+                                  gen_rtx_REG (HImode, HARD_SP_REGNUM)));
+   ")
 
 ;;--------------------------------------------------------------------
 ;; 16-bit Unary operations on X and Y:
 ;;
 ;;             NOT NEG
 ;;
-;; Operations on X or Y registers are split here. Instructions are
+;; Operations on X or Y registers are split here.  Instructions are
 ;; changed into:
 ;;   - xgdx/xgdy instruction pattern,
 ;;   - The same operation on register D,
 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
 ;;
 (define_split
-  [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A")
+  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
        (match_operator:HI 2 "m68hc11_unary_operator"
-            [(match_operand 1 "general_operand" "uim*d*A")]))]
+            [(match_operand 1 "general_operand" "")]))]
   "z_replacement_completed == 2"
   [(set (match_dup 4) (match_dup 5))
    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
       || reg_mentioned_p (operands[0], operands[1]))
     {
       /* Move to the destination register, before the xgdx.  */
-      operands[4] = gen_rtx (REG, GET_MODE (operands[1]), 
+      operands[4] = gen_rtx_REG (GET_MODE (operands[1]), 
                             REGNO (operands[0]));
       operands[5] = operands[1];
 
       /* Apply the operation on D.  */
-      operands[3] = gen_rtx (REG, GET_MODE (operands[1]), HARD_D_REGNUM);
+      operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
     }
   else
     {
 ;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
 ;;
 (define_split
-  [(set (match_operand:QI 0 "hard_addr_reg_operand" "=xy")
+  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
        (match_operator:QI 3 "m68hc11_arith_operator"
-            [(match_operand:QI 1 "hard_addr_reg_operand" "%0")
-            (match_operand:QI 2 "general_operand" "dxyuim")]))]
+            [(match_operand:QI 1 "hard_addr_reg_operand" "")
+            (match_operand:QI 2 "general_operand" "")]))]
   "z_replacement_completed == 2
    /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
       incqi pattern generates a better code.  */
    (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
    (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
               (set (match_dup 4) (reg:HI D_REGNUM))])]
-  "operands[4] = gen_rtx (REG, HImode, REGNO (operands[0]));
+  "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
 
    /* For the second operand is a hard register or if the address
       register appears in the source, we have to save the operand[2]
       will result in a nop.  */
    if (H_REG_P (operands[2]))
      {
-       operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
-       operands[6] = gen_rtx (REG, HImode, REGNO (operands[2]));
-       operands[7] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
+       operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
+       operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
+       operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
      }
    else if (reg_mentioned_p (operands[0], operands[2]))
      {
-       operands[5] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
+       operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
        operands[6] = operands[2];
        operands[7] = operands[5];
      }
    else
      {
-       operands[5] = operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM);
+       operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
        operands[7] = operands[2];
      }
   ")
 ;; The shift operators are special and must not appear here.
 ;;
 (define_split
-  [(set (match_operand:QI 0 "d_register_operand" "=d")
+  [(set (match_operand:QI 0 "d_register_operand" "")
        (match_operator:QI 3 "m68hc11_non_shift_operator"
-            [(match_operand:QI 1 "d_register_operand" "%0")
-            (match_operand:QI 2 "hard_reg_operand" "*d*x*y")]))]
+            [(match_operand:QI 1 "d_register_operand" "")
+            (match_operand:QI 2 "hard_reg_operand" "")]))]
   "reload_completed"
   [(set (match_dup 5) (match_dup 6))
    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
-  "operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
-   operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
-   operands[6] = gen_rtx (REG, HImode, REGNO (operands[2]));")
+  "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
+   operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
+   operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
 
 ;;--------------------------------------------------------------------
 ;; 8-bit Unary operations on X and Y:
 ;;
 ;;             NOT NEG
 ;;
-;; Operations on X or Y registers are split here. Instructions are
+;; Operations on X or Y registers are split here.  Instructions are
 ;; changed into:
 ;;   - xgdx/xgdy instruction pattern,
 ;;   - The same operation on register D,
 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
 ;;
 (define_split
-  [(set (match_operand:QI 0 "hard_addr_reg_operand" "=xy")
+  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
        (match_operator:QI 2 "m68hc11_unary_operator"
-            [(match_operand:QI 1 "general_operand" "uim*d*x*y")]))]
+            [(match_operand:QI 1 "general_operand" "")]))]
   "z_replacement_completed == 2"
   [(set (match_dup 4) (match_dup 5))
    (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]));
+  operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
   if ((H_REG_P (operands[1])
        && !rtx_equal_p (operands[0], operands[1]))
       || reg_mentioned_p (operands[0], operands[1]))
       operands[5] = operands[1];
 
       /* Apply the operation on D.  */
-      operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM);
+      operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
     }
   else
     {
 
 (define_insn "negsi2"
   [(set (match_operand:SI 0 "register_operand" "=D")
-       (neg:SI (match_operand:SI 1 "register_operand" "0")))]
+       (neg:SI (match_operand:SI 1 "general_operand" "0")))]
   ""
   "*
 {
+  rtx ops[1];
+
   CC_STATUS_INIT;
 
   /* With -Os or without -O, use a special library call.  */
   if (optimize_size || optimize == 0)
     return \"bsr\\t___negsi2\";
 
-  /* 32-bit complement and add 1.  The comb/coma set the carry and they
-     are smaller (use it for low-part).  The eorb/eora leave the carry
-     unchanged but are bigger (use it for high-part).  */
-  output_asm_insn (\"comb\\n\\tcoma\\n\\taddd\\t#1\\n\\txgdx\", operands);
-  output_asm_insn (\"eorb\\t#0xFF\\n\\teora\\t#0xFF\", operands);
-  return \"adcb\\t#0\\n\\tadca\\t#0\\n\\txgdx\";
+  ops[0] = gen_label_rtx ();
+
+  /* 32-bit complement and add 1.  */
+  output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
+  output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
+  output_asm_insn (\"bne\\t%l0\", ops);
+  output_asm_insn (\"inx\", operands);
+  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
+  return \"\";
 }")
 
 (define_insn "neghi2"
-  [(set (match_operand:HI 0 "register_operand" "=d,d,*A")
+  [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
        (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
   ""
   "@
    DONE;")
 
 (define_insn "one_cmplsi2"
-  [(set (match_operand:SI 0 "non_push_operand" "=D")
-       (not:SI (match_operand:SI 1 "general_operand" "0")))]
+  [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
+       (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
+   (clobber (match_scratch:HI 2 "=X,d,X"))]
   ""
-  "bsr\\t___one_cmplsi2")
+  "@
+   bsr\\t___one_cmplsi2
+   #
+   #")
 
 (define_insn "one_cmplhi2"
-  [(set (match_operand:HI 0 "non_push_operand" "=d,m,!u,*A")
+  [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
        (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
   ""
   "@
    comb\\n\\tcoma
    com\\t%b0\\n\\tcom\\t%h0
-   com\\t%b0\\n\\tcom\\t%h0
-   #")
+   #
+   com\\t%b0\\n\\tcom\\t%h0")
 
 (define_insn "one_cmplqi2"
-  [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,!*A")
+  [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
        (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
   ""
   "@
    comb
    com\\t%b0
-   com\\t%b0
-   #")
+   #
+   com\\t%b0")
 
 (define_split /* "*one_cmplsi2" */
-  [(set (match_operand:SI 0 "non_push_operand" "=Dum")
-       (not:SI (match_operand:SI 1 "non_push_operand" "0")))]
+  [(set (match_operand:SI 0 "non_push_operand" "")
+       (not:SI (match_dup 0)))
+   (clobber (match_scratch:HI 1 ""))]
   "z_replacement_completed == 2
-   && (!D_REG_P (operands[0]) || (optimize && optimize_size == 0))"
-  [(set (reg:HI D_REGNUM) (not:HI (reg:HI D_REGNUM)))
-   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
-              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
-   (set (reg:HI D_REGNUM) (not:HI (reg:HI D_REGNUM)))
-   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
-              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
-  "
-{
-  /* The result pattern only works for D register.
-     Generate 2 one_cmplhi2 instructions.  */
-  if (!D_REG_P (operands[0]))
-    {
-      rtx ops[2];
+   && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
+  [(set (match_dup 2) (not:HI (match_dup 2)))
+   (set (match_dup 3) (not:HI (match_dup 3)))]
+  "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
+   operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
 
-      ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
-      ops[1] = m68hc11_gen_highpart (HImode, operands[0]);
-      emit_insn (gen_one_cmplhi2 (ops[0], ops[0]));
-      emit_insn (gen_one_cmplhi2 (ops[1], ops[1]));
-      DONE;
-    }
-}")
+(define_split /* "*one_cmplsi2" */
+  [(set (match_operand:SI 0 "non_push_operand" "")
+       (not:SI (match_operand:SI 1 "non_push_operand" "")))
+   (clobber (match_operand:HI 2 "d_register_operand" ""))]
+  "z_replacement_completed == 2
+   && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
+  [(set (match_dup 2) (match_dup 3))
+   (set (match_dup 2) (not:HI (match_dup 2)))
+   (set (match_dup 4) (match_dup 2))
+   (set (match_dup 2) (match_dup 5))
+   (set (match_dup 2) (not:HI (match_dup 2)))
+   (set (match_dup 6) (match_dup 2))]
+  "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
+   operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
+   operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
+   operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
 
 ;;--------------------------------------------------------------------
 ;;- arithmetic shifts
     }
 }")
 
-(define_insn "*ashldi3_const32"
+(define_insn_and_split "*ashldi3_const32"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
        (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
                   (const_int 32)))
    (clobber (match_scratch:HI 2 "=&A,d,d"))]
    ""
-   "#")
-
-(define_split
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=<,um")
-       (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi")
-                  (const_int 32)))
-   (clobber (match_scratch:HI 2 "=&A,d"))]
+   "#"
    "reload_completed"
    [(const_int 0)]
    "/* Move the lowpart in the highpart first in case the shift
       {
          m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
                             const0_rtx, operands[2]);
+
+         /* Adjust first operand if it uses SP so that we take into
+            account the above push.  Can occur only for 68HC12.  */
+         if (reg_mentioned_p (gen_rtx (REG, HImode, HARD_SP_REGNUM),
+                             operands[1]))
+           operands[1] = adjust_address (operands[1],
+                                        GET_MODE (operands[0]), 4);
       }
     m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
                        m68hc11_gen_lowpart (SImode, operands[1]),
       }
     DONE;")
 
-(define_insn "*ashldi3_const1"
+(define_insn_and_split "*ashldi3_const1"
   [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
        (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
                   (const_int 1)))
    (clobber (match_scratch:HI 2 "=d,d,d"))]
    ""
-   "#")
-
-(define_split
-  [(set (match_operand:DI 0 "non_push_operand" "=um")
-       (ashift:DI (match_operand:DI 1 "general_operand" "umi")
-                  (const_int 1)))
-   (clobber (match_scratch:HI 2 "=d"))]
+   "#"
    "z_replacement_completed == 2"
    [(set (match_dup 2) (match_dup 3))
     (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
     (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]);
     operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
 
 (define_insn "addsi_silshr16"
-  [(set (match_operand:SI 0 "register_operand" "=D")
-          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim")
+  [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
+          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
                                (const_int 16))
-                  (match_operand:SI 2 "general_operand" "0")))]
+                  (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
   ""
   "#")
 
 (define_split
-  [(set (match_operand:SI 0 "register_operand" "=D")
-          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim")
+  [(set (match_operand:SI 0 "register_operand" "")
+          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
                                (const_int 16))
-                  (match_operand:SI 2 "general_operand" "0")))]
-  "z_replacement_completed == 2"
+                  (match_operand:SI 2 "general_operand" "")))]
+  "z_replacement_completed == 2 && !X_REG_P (operands[1])"
   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
-   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
+   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
+                                           (const_int 0))
+                                  (reg:HI CC_REGNUM)))]
   "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
 
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
+                               (const_int 16))
+                  (match_operand:SI 2 "general_operand" "")))]
+  "z_replacement_completed == 2 && X_REG_P (operands[1])"
+  [(set (reg:HI D_REGNUM) (match_dup 5))
+   (set (reg:HI X_REGNUM) (match_dup 3))
+   (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
+   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
+                                           (const_int 0))
+                                  (reg:HI CC_REGNUM)))]
+  "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
+   if (X_REG_P (operands[2]))
+     {
+       operands[4] = gen_rtx (REG, HImode, HARD_X_REGNUM);
+       operands[5] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+     }
+   else
+     {
+       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
+       operands[5] = gen_rtx (REG, HImode, HARD_X_REGNUM);
+     }
+")
+
 (define_insn "addsi_ashift16"
   [(set (match_operand:SI 0 "register_operand" "=D")
           (plus:SI 
   "#")
 
 (define_split
-  [(set (match_operand:SI 0 "register_operand" "=D")
+  [(set (match_operand:SI 0 "register_operand" "")
           (plus:SI 
-                  (mult:SI (match_operand:SI 2 "general_operand" "uim")
+                  (mult:SI (match_operand:SI 2 "general_operand" "")
                            (const_int 65536))
-                  (match_operand:SI 1 "general_operand" "0")))
+                  (match_operand:SI 1 "general_operand" "")))
    (clobber (match_scratch:HI 3 "=X"))]
   "0 && reload_completed && z_replacement_completed == 2"
   [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
   operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
 }")
 
-(define_insn "addsi_andshr16"
+(define_insn_and_split "addsi_andshr16"
   [(set (match_operand:SI 0 "register_operand" "=D")
           (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
                           (const_int 65535))
                   (match_operand:SI 2 "general_operand" "0")))]
   ""
-  "#")
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "=D")
-          (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
-                          (const_int 65535))
-                  (match_operand:SI 2 "general_operand" "0")))]
+  "#"
   "z_replacement_completed == 2"
   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
    (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
    "")
 
 (define_split
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=D,um")
-       (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D")
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+       (ashift:SI (match_operand:SI 1 "general_operand" "")
                   (const_int 16)))
-   (clobber (match_scratch:HI 3 "=X,X"))]
+   (clobber (match_scratch:HI 3 ""))]
    ""
   [(set (match_dup 2) (match_dup 3))
    (set (match_dup 4) (const_int 0))]
    ""
    "#")
 
-(define_insn "*ashlsi3_const16_zexthi"
+(define_insn_and_split "*ashlsi3_const16_zexthi"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
        (ashift:SI (zero_extend:HI 
                        (match_operand:HI 1 "general_operand" "duim*A"))
                   (const_int 16)))
    (clobber (match_scratch:HI 2 "=X"))]
    ""
-   "#")
-
-(define_split /* "*ashlsi3_const16_zexthi"*/
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
-       (ashift:SI (zero_extend:HI 
-                       (match_operand:HI 1 "general_operand" "duim*a"))
-                  (const_int 16)))
-   (clobber (match_scratch:HI 2 "=X"))]
+   "#"
    "reload_completed"
    [(set (reg:HI X_REGNUM) (match_dup 1))
     (set (reg:HI D_REGNUM) (const_int 0))]
       rtx ops[2];
 
       ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
-      ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
       m68hc11_gen_movhi (insn, ops);
       output_asm_insn (\"lsld\", ops);
       if (!X_REG_P (operands[0]))
        {
          /* Load the high part in X in case the source operand
             uses X as a memory pointer.  */
-         ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM);
+         ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
           ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
           m68hc11_gen_movhi (insn, ops);
           output_asm_insn (\"xgdx\", ops);
   if (!Y_REG_P (operands[2]))
     {
       rtx ops[1];
+      int y_dead = dead_register_here (insn, iy_reg);
 
       ops[0] = operands[1];
-      output_asm_insn (\"pshy\", operands);
-      if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
+      if (y_dead == 0)
        {
-         ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
+          output_asm_insn (\"pshy\", operands);
+          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
+           ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
        }
       output_asm_insn (\"ldy\\t%0\", ops);
       output_asm_insn (\"bsr\\t___ashlsi3\", operands);
-      return \"puly\";
+      return y_dead == 0 ? \"puly\" : \"\";
     }
   return \"bsr\\t___ashlsi3\";
 }")
     {
       rtx scratch = gen_reg_rtx (HImode);
       emit_move_insn (scratch, operands[2]);
-      emit_insn (gen_rtx (PARALLEL, VOIDmode,
-                gen_rtvec (2, gen_rtx (SET, VOIDmode,
+      emit_insn (gen_rtx_PARALLEL (VOIDmode,
+                gen_rtvec (2, gen_rtx_SET (VOIDmode,
                            operand0,
                            gen_rtx_ASHIFT (HImode,
                                        operand1, scratch)),
-                             gen_rtx (CLOBBER, VOIDmode, scratch))));
+                             gen_rtx_CLOBBER (VOIDmode, scratch))));
       DONE;
     }
 }")
 
 
 (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\";
 }")
   if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
     return \"#\";
 
-  ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
+  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
   ops[1] = operands[2];
   m68hc11_gen_movqi (insn, ops);
 
       rtx scratch = gen_reg_rtx (HImode);
 
       emit_move_insn (scratch, operands[2]);
-      emit_insn (gen_rtx (PARALLEL, VOIDmode,
-                gen_rtvec (2, gen_rtx (SET, VOIDmode,
+      emit_insn (gen_rtx_PARALLEL (VOIDmode,
+                gen_rtvec (2, gen_rtx_SET (VOIDmode,
                                operand0,
                                gen_rtx_ASHIFTRT (HImode,
                                        operand1, scratch)),
-                             gen_rtx (CLOBBER, VOIDmode, scratch))));
+                             gen_rtx_CLOBBER (VOIDmode, scratch))));
        DONE;
     }
 }")
       output_asm_insn (\"comb\", operands);
 
       CC_STATUS_INIT;
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[0]));
       return \"\";
     }
       output_asm_insn (\"bge\\t%l0\", ops);
       output_asm_insn (\"deca\", operands);
 
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[0]));
 
       val -= 8;
       output_asm_insn (\"bcc\\t%l0\", ops);
       output_asm_insn (\"coma\", ops);
 
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[0]));
       return \"\";
     }
 }")
 
 (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 \"\"; 
 }")
 
   if (!Y_REG_P (operands[2]))
     {
       rtx ops[1];
+      int y_dead = dead_register_here (insn, iy_reg);
 
       ops[0] = operands[1];
-      output_asm_insn (\"pshy\", operands);
-      if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
+      if (y_dead == 0)
        {
-         ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
+          output_asm_insn (\"pshy\", operands);
+          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
+           ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
        }
       output_asm_insn (\"ldy\\t%0\", ops);
       output_asm_insn (\"bsr\\t___ashrsi3\", operands);
-      return \"puly\";
+      return y_dead == 0 ? \"puly\" : \"\";
     }
   return \"bsr\\t___ashrsi3\";
 }")
   if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
     return \"#\";
 
-  ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
+  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
   ops[1] = operands[2];
   m68hc11_gen_movqi (insn, ops);
 
     }
 }")
 
-(define_insn "*lshrdi3_const32"
+(define_insn_and_split "*lshrdi3_const32"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
                     (const_int 32)))
    (clobber (match_scratch:HI 2 "=&A,d,d"))]
    ""
-   "#")
-
-(define_split
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=<,um")
-       (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
-                    (const_int 32)))
-   (clobber (match_scratch:HI 2 "=&A,d"))]
+   "#"
    "reload_completed"
    [(const_int 0)]
    "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
    "#")
 
 (define_split
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=um")
-       (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi")
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
                     (match_operand:DI 2 "const_int_operand" "")))
    (clobber (match_scratch:HI 3 "=d"))]
    "z_replacement_completed && INTVAL (operands[2]) >= 56"
     (set (match_dup 5) (reg:HI D_REGNUM))
     (set (match_dup 6) (reg:HI D_REGNUM))
     (set (match_dup 7) (reg:HI D_REGNUM))]
-   "operands[8] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 56);
+   "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
     operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
     operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
     operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
     operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
 
 (define_split
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=um")
-       (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi")
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
                     (match_operand:DI 2 "const_int_operand" "")))
    (clobber (match_scratch:HI 3 "=d"))]
    "z_replacement_completed && INTVAL (operands[2]) >= 48 
     (set (match_dup 5) (reg:HI D_REGNUM))
     (set (match_dup 6) (reg:HI D_REGNUM))
     (set (match_dup 7) (reg:HI D_REGNUM))]
-   "operands[8] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 48);
+   "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
     operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
     operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
     operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
     operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
     operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
 
-(define_insn "*lshrdi_const1"
+(define_insn_and_split "*lshrdi_const1"
   [(set (match_operand:DI 0 "non_push_operand" "=m,u")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
                     (const_int 1)))
    (clobber (match_scratch:HI 2 "=d,d"))]
    ""
-   "#")
-
-(define_split
-  [(set (match_operand:DI 0 "non_push_operand" "=um")
-       (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi")
-                    (const_int 1)))
-   (clobber (match_scratch:HI 2 "=d"))]
+   "#"
    "z_replacement_completed == 2"
    [(set (match_dup 2) (match_dup 3))
     (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
     (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]);
    "")
 
 (define_split
-  [(set (match_operand:SI 0 "non_push_operand" "=D,um")
-       (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,D")
+  [(set (match_operand:SI 0 "non_push_operand" "")
+       (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
                     (const_int 16)))
-   (clobber (match_scratch:HI 3 "=X,X"))]
+   (clobber (match_scratch:HI 3 ""))]
    "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
   [(set (match_dup 2) (match_dup 3))
    (set (match_dup 4) (const_int 0))]
       rtx ops[2];
 
       ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
-      ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
       m68hc11_gen_movhi (insn, ops);
       output_asm_insn (\"lsrd\", ops);
       if (!X_REG_P (operands[0]))
       else
        {
          /* Load the lowpart in X in case the operands is some N,x.  */
-         ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM);
+         ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
           ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
           m68hc11_gen_movhi (insn, ops);
           output_asm_insn (\"xgdx\", ops);
   if (!Y_REG_P (operands[2]))
     {
       rtx ops[1];
+      int y_dead = dead_register_here (insn, iy_reg);
 
       ops[0] = operands[1];
-      output_asm_insn (\"pshy\", operands);
-      if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
+      if (y_dead == 0)
        {
-         ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
+          output_asm_insn (\"pshy\", operands);
+          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
+           ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
        }
       output_asm_insn (\"ldy\\t%0\", ops);
       output_asm_insn (\"bsr\\t___lshrsi3\", operands);
-      return \"puly\";
+      return y_dead == 0 ? \"puly\" : \"\";
     }
   return \"bsr\\t___lshrsi3\";
 }")
       operand1 = force_reg (HImode, operand1);
 
       emit_move_insn (scratch, operands[2]);
-      emit_insn (gen_rtx (PARALLEL, VOIDmode,
-                gen_rtvec (2, gen_rtx (SET, VOIDmode,
+      emit_insn (gen_rtx_PARALLEL (VOIDmode,
+                gen_rtvec (2, gen_rtx_SET (VOIDmode,
                                        operand0,
                                        gen_rtx_LSHIFTRT (HImode,
                                                operand1, scratch)),
-                             gen_rtx (CLOBBER, VOIDmode, scratch))));
+                             gen_rtx_CLOBBER (VOIDmode, scratch))));
      DONE;
   }
 }")
 }")
 
 (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"
     return \"#\";
 
   CC_STATUS_INIT;
-  ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
+  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
   ops[1] = operands[2];
   m68hc11_gen_movqi (insn, ops);
 
   ops[1] = gen_label_rtx ();
   output_asm_insn (\"ble\\t%l1\", ops);
 
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                             CODE_LABEL_NUMBER (ops[0]));
 
   output_asm_insn (\"lsrb\", operands);
   output_asm_insn (\"deca\", operands);
   output_asm_insn (\"bne\\t%l0\", ops);
 
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                             CODE_LABEL_NUMBER (ops[1]));
   return \"\";
 }")
 (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))]
   ""
   "*
 {
 (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))]
   ""
   "*
 {
   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")))]
   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_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"
+(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")))]
   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;
+    }
+
+  /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
+     the operator and its operands are not relevant.  */
+  if (GET_MODE (operands[0]) == HImode)
+    {
+      emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
+                                              gen_rtx_NE (HImode,
+                                                          operands[0],
+                                                          const1_rtx),
+                                              operands[4]));
+      DONE;
+    }
+  if (GET_MODE (operands[0]) == QImode)
+    {
+      emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
+                                              gen_rtx_NE (QImode,
+                                                          operands[0],
+                                                          const1_rtx),
+                                              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
 ;;--------------------------------------------------------------------
       smaller and a little bit faster.  This happens quite often due
       to reloading of operands[0].  In that case, flags are set correctly
       due to the load instruction.  */
-  if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+  if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+      || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
     return \"beq\\t%l1\";
   else
     return \"tbeq\\t%0,%l1\";
   "TARGET_M6812"
   "*
 {
-   if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
      return \"bne\\t%l1\";
    else
      return \"tbne\\t%0,%l1\";
   "TARGET_M6812"
   "*
 {
-   if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
      return \"beq\\t%l1\";
    else
      return \"tbeq\\tb,%l1\";
   "TARGET_M6812"
   "*
 {
-   if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
      return \"bne\\t%l1\";
    else
      return \"tbne\\tb,%l1\";
 {
   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 \"bsr\\t%0\";
 {
   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 \"bsr\\t%1\";
 
   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;
     }
 }")
     return \"\";
   if (current_function_interrupt || current_function_trap)
     return \"rti\";
-  return \"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"
     return \"\";
   if (current_function_interrupt || current_function_trap)
     return \"rti\";
-  return \"rts\";
+  else if (!current_function_far)
+    return \"rts\";
+  else if (TARGET_M6812)
+    return \"rtc\";
+  else
+    return \"jmp\\t__return_16\";
 }")
 
 (define_insn "*return_32bit"
     return \"\";
   if (current_function_interrupt || current_function_trap)
     return \"rti\";
-  return \"rts\";
+  else if (!current_function_far)
+    return \"rts\";
+  else if (TARGET_M6812)
+    return \"rtc\";
+  else
+    return \"jmp\\t__return_32\";
 }")
 
 (define_insn "indirect_jump"
 ;;- 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.
+;; pr target/6899: This peephole is not valid because a register CSE
+;; pass removes the pulx/puly.
+;;
+(define_peephole2
+  [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
+   (match_scratch:HI 0 "xy")]
+  "0 && TARGET_M6812 && optimize_size"
+  [(set (match_dup 0) (match_dup 1))]
+  "operands[1] = gen_rtx_MEM (HImode,
+                         gen_rtx_POST_INC (HImode,
+                                  gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
+
+;;
+;; Optimize memory<->memory moves when the value is also loaded in
+;; a register.
+;;
+(define_peephole2
+  [(set (match_operand:QI 0 "memory_operand" "")
+       (match_operand:QI 1 "memory_operand" ""))
+   (set (reg:QI D_REGNUM)
+       (match_operand:QI 2 "memory_operand" ""))]
+  "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
+   || (GET_CODE (XEXP (operands[0], 0)) == REG
+       && GET_CODE (XEXP (operands[2], 0)) == POST_INC
+       && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
+  [(set (reg:QI D_REGNUM) (match_dup 1))
+   (set (match_dup 2) (reg:QI D_REGNUM))]
+  "")
+
+;;
+;; Remove a possible move before a compare instruction when that
+;; move will go in a dead register.  Compare with the source then.
+;;
+(define_peephole2
+  [(set (match_operand:HI 0 "hard_reg_operand" "")
+       (match_operand:HI 1 "hard_reg_operand" ""))
+   (set (cc0)
+       (compare (match_dup 0)
+                (match_operand:HI 2 "cmp_operand" "")))]
+  "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
+   && peep2_reg_dead_p (2, operands[0])
+   && !reg_mentioned_p (operands[0], operands[2])"
+  [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
+  "")
+
+;;
+;; Optimize loading a constant to memory when that same constant
+;; is loaded to a hard register.  Switch the two to use the register
+;; for memory initialization.  In most cases, the constant is 0.
+;;
+(define_peephole2
+  [(set (match_operand:HI 0 "memory_operand" "")
+       (match_operand:HI 1 "immediate_operand" ""))
+   (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])"
+  [(set (match_dup 2) (match_dup 1))
+   (set (match_dup 0) (match_dup 2))]
+  "")
+
 ;;
 ;; Reorganize to optimize address computations.
 ;;
   "")
 
 ;;
-;; Reorganize address computation based on stack pointer.
+;; Optimize an address register increment and a compare to use
+;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
+;; before reload, but can be enabled after).
+;;
+(define_peephole2
+  [(set (match_operand:HI 0 "hard_reg_operand" "")
+       (plus:HI (match_dup 0)
+                (match_operand:HI 1 "const_int_operand" "")))
+   (set (cc0)
+       (match_operand:QI 2 "memory_operand" ""))]
+  "TARGET_AUTO_INC_DEC
+   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
+   && reg_mentioned_p (operands[0], operands[2])"
+  [(set (cc0) (match_dup 3))]
+  "if (INTVAL (operands[1]) == 1)
+     operands[3] = gen_rtx_MEM (QImode,
+                           gen_rtx_PRE_INC (HImode, operands[0]));
+   else
+     operands[3] = gen_rtx_MEM (QImode,
+                           gen_rtx_PRE_DEC (HImode, operands[0]));
+  ")
+
+;;
+;; Likewise for compare.
+;;
+(define_peephole2
+  [(set (match_operand:HI 0 "hard_reg_operand" "")
+       (plus:HI (match_dup 0)
+                (match_operand:HI 1 "const_int_operand" "")))
+   (set (cc0)
+       (compare (match_operand:QI 2 "hard_reg_operand" "")
+                (match_operand:QI 3 "memory_operand" "")))]
+  "TARGET_AUTO_INC_DEC
+   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
+   && reg_mentioned_p (operands[0], operands[3])"
+  [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
+  "if (INTVAL (operands[1]) == 1)
+     operands[4] = gen_rtx_MEM (QImode,
+                           gen_rtx_PRE_INC (HImode, operands[0]));
+   else
+     operands[4] = gen_rtx_MEM (QImode,
+                           gen_rtx_PRE_DEC (HImode, operands[0]));
+  ")
+
+(define_peephole2
+  [(set (match_operand:HI 0 "hard_reg_operand" "")
+       (plus:HI (match_dup 0)
+                (match_operand:HI 1 "const_int_operand" "")))
+   (set (cc0)
+       (compare (match_operand:QI 2 "memory_operand" "")
+                (match_operand:QI 3 "hard_reg_operand" "")))]
+  "TARGET_AUTO_INC_DEC
+   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
+   && reg_mentioned_p (operands[0], operands[2])"
+  [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
+  "if (INTVAL (operands[1]) == 1)
+     operands[4] = gen_rtx_MEM (QImode,
+                           gen_rtx_PRE_INC (HImode, operands[0]));
+   else
+     operands[4] = gen_rtx_MEM (QImode,
+                           gen_rtx_PRE_DEC (HImode, operands[0]));
+  ")
+
+;;
+;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n"
+;; (avoids many temporary moves because we can't add sp to another reg easily)
 ;;
 (define_peephole2
   [(set (match_operand:HI 0 "hard_reg_operand" "")
   "")
 
 ;;
+;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
+;;
+(define_peephole2
+  [(set (match_operand:HI 0 "hard_reg_operand" "")
+       (match_operand:HI 1 "const_int_operand" ""))
+   (set (match_dup 0)
+       (plus:HI (match_dup 0)
+                (match_operand:HI 2 "general_operand" "")))]
+  "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
+  [(set (match_dup 0) (match_dup 2))
+   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
+  "")
+
+;;
+;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
+;;
+(define_peephole2
+  [(set (match_operand:HI 0 "hard_reg_operand" "")
+        (match_operand:HI 1 "memory_operand" ""))
+   (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
+        (match_dup 0))
+   (match_scratch:HI 2 "x")]
+  "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 2) (match_dup 1))
+   (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
+  "")
+
+;;
+;; 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
   rtx ops[2];
 
   ops[0] = operands[0];
-  ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
   m68hc11_gen_movhi (insn, ops);
   return \"\";
 }
 
 ;;;
 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
-;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
+;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
 ;;;
 (define_peephole
   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
 
 ;;;
 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
-;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
+;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
 ;;;
 (define_peephole
   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
   rtx ops[2];
 
   ops[0] = operands[0];
-  ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
   m68hc11_gen_movhi (insn, ops);
   return \"\";
 }
   rtx ops[2];
 
   ops[0] = operands[0];
-  ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
+  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
   m68hc11_gen_movhi (insn, ops);
   return \"\";
 }
   rtx ops[2];
 
   ops[0] = operands[2];
-  ops[1] = gen_rtx (MEM, HImode,
-                   gen_rtx (POST_INC, HImode, stack_pointer_rtx));
+  ops[1] = gen_rtx_MEM (HImode,
+                   gen_rtx_POST_INC (HImode, stack_pointer_rtx));
   m68hc11_gen_movhi (insn, ops);
   return \"\";
 }