Report fixes from 3_0-branch made on 2001-03-04:
authorciceron <ciceron@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 3 May 2001 19:56:46 +0000 (19:56 +0000)
committerciceron <ciceron@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 3 May 2001 19:56:46 +0000 (19:56 +0000)
* config/m68hc11/larith.asm (__mulqi3): Fix multiplication of two
negative numbers.
(___subdi3, ___adddi3): Use x instead of y as index register.
(__init_bss_section, __map_data_section): Optimize for 68HC12.
(__memset, __memcpy): Likewise.
(regs): Put the soft registers in bss for 68HC12.
(abort): Use trap to abort for 68hc12.
(__mulhi3, __mulhi32): Use emul for 68hc12.
(__mulsi3): Avoid to use the tmp soft register for 68hc12.
* config/m68hc11/m68hc11.h (LIMIT_RELOAD_CLASS): Don't define.
* config/m68hc11/m68hc11-protos.h (limit_reload_class): Remove.
* config/m68hc11/m68hc11.c (limit_reload_class): Remove.
(m68hc11_override_options): Remove setting of flag_no_nonansi_builtin.
Set 68HC12 min offset to -65536.
(print_operand): Put parenthesis arround the operand if it refers
to a symbol having the same name as a register.
(m68hc11_z_replacement): When z register is replaced by its
equivalent soft register, force the insn to be re-recognized.
(m68hc11_check_z_replacement): Fix the test when destination is
the index register and z dies in the insn.
(m68hc11_reorg): Remove the REG_DEAD notes beforce recomputing them.
* config/m68hc11/m68hc11.c (m68hc11_override_options): Initialize
costs according to processor variant.
(m68hc11_shift_cost): New function to compute shift costs.
(m68hc11_rtx_costs): Define costs according to processor variant.
(m6811_cost): Costs for 68HC11.
(m6812_cost): Costs for 68HC12.
(COSTS_N_INSNS): Remove.

* config/m68hc11/m68hc11.h (RTX_COSTS): New.
(DEFAULT_RTX_COSTS): Remove.
(CONST_COSTS): Define costs according to OUTER_CODE.
(processor_costs): New struct to define costs.
(m68hc11_cost): Pointer to current costs.

* config/m68hc11/m68hc11.md (*addhi3_68hc12): Fix generation
and use m68hc11_notice_keep_cc when using leax/leay.
(addhi3 split): Reject split if the insn is handled by
leax/leay above.
* config/m68hc11/m68hc11.c (m68hc11_split_move): For 68HC12 the
push must be handled in a special way if the source operand uses
sp as index register.
(m68hc11_notice_keep_cc): New function.
(m68hc11_gen_movhi): Use it when an insn changes a register but
not the flags.
(m68hc11_gen_movqi): Fix move for 68HC12.
* config/m68hc11/m68hc11-protos.h (m68hc11_notice_keep_cc): Declare.

* config/m68hc11/m68hc11.c (m68hc11_emit_libcall): Use LCT_CONST
and don't pass operands[0] to emit_library_call_value.

* config/m68hc11/m68hc11.md (tsthi_1): Use cpd for 68HC12.
(zero_extendsi split): Simplify and use (zero_extendhi).
(*addhi3): Remove 'w' constraint since stack pointer is handled
by (addhi3_sp).
(*ashlhi3_2): Operand 2 is clobbered use '+' for its constraint.
(*ashlhi3, *ashrhi3, *lshrhi3): Likewise.
(*ashrhi3_const): Fix shift by 7.
(*lshrsi3_const16): Fix template.
(call, call_value): Fix constraint and predicate.

* config/m68hc11/m68hc11.md (X_REGNUM, D_REGNUM): New constant.
(Y_REGNUM, SP_REGNUM, PC_REGNUM, A_REGNUM, B_REGNUM): Likewise.
(CC_REGNUM): Likewise.
(*unnamed splits): Use above constants instead of hard coded numbers.
(*adcq, *subcq, *addsi_carry, *rotlqi3_with_carry): Likewise.
(*rotlhi3_with_carry, *rotrhi3_with_carry): Likewise.
(*return_16bit, *unnamed peepholes): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41802 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/m68hc11/larith.asm
gcc/config/m68hc11/m68hc11-protos.h
gcc/config/m68hc11/m68hc11.c
gcc/config/m68hc11/m68hc11.h
gcc/config/m68hc11/m68hc11.md

index f5941b0..8d5c1e7 100644 (file)
@@ -1,3 +1,88 @@
+2001-05-03  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
+
+       * config/m68hc11/larith.asm (__mulqi3): Fix multiplication of two
+       negative numbers.
+       (___subdi3, ___adddi3): Use x instead of y as index register.
+       (__init_bss_section, __map_data_section): Optimize for 68HC12.
+       (__memset, __memcpy): Likewise.
+       (regs): Put the soft registers in bss for 68HC12.
+       (abort): Use trap to abort for 68hc12.
+       (__mulhi3, __mulhi32): Use emul for 68hc12.
+       (__mulsi3): Avoid to use the tmp soft register for 68hc12.
+
+2001-05-03  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
+
+       * config/m68hc11/m68hc11.h (LIMIT_RELOAD_CLASS): Don't define.
+       * config/m68hc11/m68hc11-protos.h (limit_reload_class): Remove.
+       * config/m68hc11/m68hc11.c (limit_reload_class): Remove.
+       (m68hc11_override_options): Remove setting of flag_no_nonansi_builtin.
+       Set 68HC12 min offset to -65536.
+       (print_operand): Put parenthesis arround the operand if it refers 
+       to a symbol having the same name as a register.
+       (m68hc11_z_replacement): When z register is replaced by its 
+       equivalent soft register, force the insn to be re-recognized.
+       (m68hc11_check_z_replacement): Fix the test when destination is
+       the index register and z dies in the insn.
+       (m68hc11_reorg): Remove the REG_DEAD notes beforce recomputing them.
+
+2001-05-03  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
+
+       * config/m68hc11/m68hc11.c (m68hc11_override_options): Initialize
+       costs according to processor variant.
+       (m68hc11_shift_cost): New function to compute shift costs.
+       (m68hc11_rtx_costs): Define costs according to processor variant.
+       (m6811_cost): Costs for 68HC11.
+       (m6812_cost): Costs for 68HC12.
+       (COSTS_N_INSNS): Remove.
+
+       * config/m68hc11/m68hc11.h (RTX_COSTS): New.
+       (DEFAULT_RTX_COSTS): Remove.
+       (CONST_COSTS): Define costs according to OUTER_CODE.
+       (processor_costs): New struct to define costs.
+       (m68hc11_cost): Pointer to current costs.
+
+2001-05-03  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
+
+       * config/m68hc11/m68hc11.md (*addhi3_68hc12): Fix generation
+       and use m68hc11_notice_keep_cc when using leax/leay.
+       (addhi3 split): Reject split if the insn is handled by 
+       leax/leay above.
+       * config/m68hc11/m68hc11.c (m68hc11_split_move): For 68HC12 the
+       push must be handled in a special way if the source operand uses
+       sp as index register.
+       (m68hc11_notice_keep_cc): New function.
+       (m68hc11_gen_movhi): Use it when an insn changes a register but 
+       not the flags.
+       (m68hc11_gen_movqi): Fix move for 68HC12.
+       * config/m68hc11/m68hc11-protos.h (m68hc11_notice_keep_cc): Declare.
+
+2001-05-03  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
+
+       * config/m68hc11/m68hc11.c (m68hc11_emit_libcall): Use LCT_CONST
+       and don't pass operands[0] to emit_library_call_value.
+
+2001-05-03  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
+
+       * config/m68hc11/m68hc11.md (tsthi_1): Use cpd for 68HC12.
+       (zero_extendsi split): Simplify and use (zero_extendhi).
+       (*addhi3): Remove 'w' constraint since stack pointer is handled 
+       by (addhi3_sp).
+       (*ashlhi3_2): Operand 2 is clobbered use '+' for its constraint.
+       (*ashlhi3, *ashrhi3, *lshrhi3): Likewise.
+       (*ashrhi3_const): Fix shift by 7.
+       (*lshrsi3_const16): Fix template.
+       (call, call_value): Fix constraint and predicate.
+
+2001-05-03  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
+
+       * config/m68hc11/m68hc11.md (X_REGNUM, D_REGNUM): New constant.
+       (Y_REGNUM, SP_REGNUM, PC_REGNUM, A_REGNUM, B_REGNUM): Likewise.
+       (CC_REGNUM): Likewise.
+       (*unnamed splits): Use above constants instead of hard coded numbers.
+       (*adcq, *subcq, *addsi_carry, *rotlqi3_with_carry): Likewise.
+       (*rotlhi3_with_carry, *rotrhi3_with_carry): Likewise.
+       (*return_16bit, *unnamed peepholes): Likewise.
+
 2001-05-03  David O'Brien  <obrien@FreeBSD.org>
 
        * config.gcc(rs6000-ibm-aix|powerpc-ibm-aix):  Do not include
index e757729..fe70702 100644 (file)
@@ -1,5 +1,5 @@
-/* libgcc1 routines for M68HC11.
-   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* libgcc1 routines for M68HC11 & M68HC12.
+   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -47,7 +47,11 @@ NAME:        .word 0;                        \
 /* Pseudo hard registers used by gcc.
    They must be located in page0. 
    They will normally appear at the end of .page0 section.  */
+#ifdef mc68hc12
+       .sect .bss
+#else
        .sect .page0
+#endif
        .globl _.tmp,_.frame
        .globl _.z,_.xy
 REG(_.tmp)
@@ -61,7 +65,11 @@ REG(_.frame)
 /* Pseudo hard registers used by gcc.
    They must be located in page0. 
    They will normally appear at the end of .page0 section.  */
+#ifdef mc68hc12
+       .sect .bss
+#else
        .sect .page0
+#endif
        .globl _.d1,_.d2,_.d3,_.d4,_.d5,_.d6
        .globl _.d7,_.d8
 REG(_.d1)
@@ -97,7 +105,11 @@ REG(_.d16)
 /* Pseudo hard registers used by gcc.
    They must be located in page0. 
    They will normally appear at the end of .page0 section.  */
+#ifdef mc68hc12
+       .sect .bss
+#else
        .sect .page0
+#endif
        .globl _.d17,_.d18,_.d19,_.d20,_.d21,_.d22
        .globl _.d23,_.d24,_.d25,_.d26,_.d27,_.d28
        .globl _.d29,_.d30,_.d31,_.d32
@@ -157,8 +169,12 @@ fatal:
        .globl abort
 abort:
        ldd     #255            ; 
+#ifdef mc68hc12
+       trap    #0x30
+#else
        .byte 0xCD              ; Generate an illegal instruction trap
        .byte 0x03              ; The simulator catches this and stops.
+#endif
        jmp _exit
 #endif
        
@@ -189,6 +205,23 @@ _cleanup:
 ;;; 
 __memcpy:
 memcpy:
+#ifdef mc68hc12
+       ldx     2,sp
+       ldy     4,sp
+       pshd
+       xgdy
+       lsrd
+       bcc     Start
+       movb    1,x+,1,y+
+Start:
+       beq     Done
+Loop:
+       movw    2,x+,2,y+
+       dbne    d,Loop
+Done:
+       puld
+       rts
+#else
        xgdy
        tsx
        ldd     4,x
@@ -214,6 +247,7 @@ End:
        xgdy
        rts
 #endif
+#endif
 
 #ifdef L_memset
        .sect .text
@@ -237,6 +271,19 @@ End:
 #endif
 __memset:
 memset:
+#ifdef mc68hc12
+       xgdx
+       ldab    val,sp
+       ldy     size,sp
+       pshx
+       beq     End
+Loop:
+       stab    1,x+
+       dbne    y,Loop
+End:
+       puld
+       rts
+#else
        xgdx
        tsy
        ldab    val,y
@@ -253,6 +300,7 @@ End:
        xgdx
        rts
 #endif
+#endif
                
 #ifdef L_adddi3
        .sect .text
@@ -260,29 +308,28 @@ End:
 
 ___adddi3:
        tsx
-       tsy
        pshb
        psha
        ldd     8,x
-       addd    16,y
+       addd    16,x
        pshb
        psha
 
        ldd     6,x
-       adcb    15,y
-       adca    14,y
+       adcb    15,x
+       adca    14,x
        pshb
        psha
 
        ldd     4,x
-       adcb    13,y
-       adca    12,y
+       adcb    13,x
+       adca    12,x
        pshb
        psha
        
        ldd     2,x
-       adcb    11,y
-       adca    10,y
+       adcb    11,x
+       adca    10,x
        tsx
        ldy     6,x
 
@@ -303,29 +350,28 @@ ___adddi3:
 
 ___subdi3:
        tsx
-       tsy
        pshb
        psha
        ldd     8,x
-       subd    16,y
+       subd    16,x
        pshb
        psha
 
        ldd     6,x
-       sbcb    15,y
-       sbca    14,y
+       sbcb    15,x
+       sbca    14,x
        pshb
        psha
 
        ldd     4,x
-       sbcb    13,y
-       sbca    12,y
+       sbcb    13,x
+       sbca    12,x
        pshb
        psha
        
        ldd     2,x
-       sbcb    11,y
-       sbca    10,y
+       sbcb    11,x
+       sbca    10,x
        
        tsx
        ldy     6,x
@@ -681,7 +727,6 @@ A_or_B_neg:
        addd    #1
        rts
 AB_neg:
-       nega
        negb
        mul
        rts
@@ -699,6 +744,13 @@ AB_neg:
 ;      b = register X
 ;
 ___mulhi3:
+#ifdef mc68hc12
+       pshx                    ; Preserve X
+       exg     x,y
+       emul
+       exg     x,y
+       pulx
+#else
        stx     *_.tmp
        pshb
        ldab    *_.tmp+1
@@ -714,6 +766,7 @@ ___mulhi3:
        pulb
        mul                     ; A.low * B.low
        adda    *_.tmp
+#endif
        rts
 #endif
 
@@ -750,6 +803,11 @@ ___mulhi3:
 ;      <A-high>   0,x
 ;
 __mulhi32:
+#ifdef mc68hc12
+       ldy     2,sp
+       emul
+       exg     x,y
+#else
        pshb
        psha
        tsx
@@ -781,6 +839,7 @@ N:
 Ret:
        pshy
        pulx
+#endif
        rts
        
 #endif
@@ -823,7 +882,11 @@ __mulsi3:
 ;
 ; If A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
 ;
+#ifdef mc68hc12
+       cpx     #0
+#else
        stx     *_.tmp
+#endif
        beq     A_high_zero
        bsr     ___mulhi3               ; A.high * B.low
 ;
@@ -933,6 +996,10 @@ __map_data_section:
        ldx     #__data_image
        ldy     #__data_section_start
 Loop:
+#ifdef mc68hc12
+       movb    1,x+,1,y+
+       dbne    d,Loop
+#else
        psha
        ldaa    0,x
        staa    0,y
@@ -941,6 +1008,7 @@ Loop:
        iny
        subd    #1
        bne     Loop
+#endif
 Done:
 
 #endif
@@ -955,10 +1023,15 @@ __init_bss_section:
        beq     Done
        ldx     #__bss_start
 Loop:
+#ifdef mc68hc12
+       clr     1,x+
+       dbne    d,Loop
+#else
        clr     0,x
        inx
        subd    #1
        bne     Loop
+#endif
 Done:
 
 #endif
index 952e12b..8aaa76c 100644 (file)
@@ -1,5 +1,5 @@
 /* Prototypes for exported functions defined in m68hc11.c
-   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by Stephane Carrez (stcarrez@worldnet.fr)
 
 This file is part of GNU CC.
@@ -70,6 +70,7 @@ extern int m68hc11_go_if_legitimate_address PARAMS((rtx,
 extern int m68hc11_legitimize_address PARAMS((rtx*, rtx, enum machine_mode));
 
 extern void m68hc11_notice_update_cc PARAMS((rtx, rtx));
+extern void m68hc11_notice_keep_cc PARAMS((rtx));
 
 extern void m68hc11_reorg PARAMS((rtx));
 
@@ -137,8 +138,6 @@ extern int hard_reg_operand PARAMS((rtx, enum machine_mode));
 extern int soft_reg_operand PARAMS((rtx, enum machine_mode));
 extern int reg_or_some_mem_operand PARAMS((rtx, enum machine_mode));
 
-extern enum reg_class limit_reload_class PARAMS((enum machine_mode, enum reg_class));
-
 #if defined TREE_CODE
 extern void m68hc11_init_cumulative_args PARAMS((CUMULATIVE_ARGS*,
                                                  tree,
index 0075c39..99baa51 100644 (file)
@@ -62,7 +62,7 @@ static int go_if_legitimate_address_internal PARAMS((rtx, enum machine_mode,
 static int register_indirect_p PARAMS((rtx, enum machine_mode, int));
 static rtx m68hc11_expand_compare PARAMS((enum rtx_code, rtx, rtx));
 static int must_parenthesize PARAMS ((rtx));
-
+static int m68hc11_shift_cost PARAMS ((enum machine_mode, rtx, int));
 static int m68hc11_auto_inc_p PARAMS ((rtx));
 
 void create_regs_rtx PARAMS ((void));
@@ -120,6 +120,78 @@ rtx m68hc11_compare_op0;
 rtx m68hc11_compare_op1;
 \f
 
+struct processor_costs *m68hc11_cost;
+
+/* Costs for a 68HC11.  */
+struct processor_costs m6811_cost = {
+  /* add */
+  COSTS_N_INSNS (2),
+  /* logical */
+  COSTS_N_INSNS (2),
+  /* non-constant shift */
+  COSTS_N_INSNS (20),
+  /* shiftQI const */
+  { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (2),
+    COSTS_N_INSNS (3), COSTS_N_INSNS (4), COSTS_N_INSNS (3),
+    COSTS_N_INSNS (2), COSTS_N_INSNS (1) },
+
+  /* shiftHI const */
+  { COSTS_N_INSNS (0), COSTS_N_INSNS (2), COSTS_N_INSNS (4),
+    COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (6),
+    COSTS_N_INSNS (4), COSTS_N_INSNS (2),
+    COSTS_N_INSNS (2), COSTS_N_INSNS (4),
+    COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (10),
+    COSTS_N_INSNS (8), COSTS_N_INSNS (6), COSTS_N_INSNS (4)
+  },
+  /* mulQI */
+  COSTS_N_INSNS (20),
+  /* mulHI */
+  COSTS_N_INSNS (20 * 4),
+  /* mulSI */
+  COSTS_N_INSNS (20 * 16),
+  /* divQI */
+  COSTS_N_INSNS (20),
+  /* divHI */
+  COSTS_N_INSNS (80),
+  /* divSI */
+  COSTS_N_INSNS (100)
+};
+
+/* Costs for a 68HC12.  */
+struct processor_costs m6812_cost = {
+  /* add */
+  COSTS_N_INSNS (1),
+  /* logical */
+  COSTS_N_INSNS (1),
+  /* non-constant shift */
+  COSTS_N_INSNS (20),
+  /* shiftQI const */
+  { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (2),
+    COSTS_N_INSNS (3), COSTS_N_INSNS (4), COSTS_N_INSNS (3),
+    COSTS_N_INSNS (2), COSTS_N_INSNS (1) },
+
+  /* shiftHI const */
+  { COSTS_N_INSNS (0), COSTS_N_INSNS (2), COSTS_N_INSNS (4),
+    COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (6),
+    COSTS_N_INSNS (4), COSTS_N_INSNS (2),
+    COSTS_N_INSNS (2), COSTS_N_INSNS (4), COSTS_N_INSNS (6),
+    COSTS_N_INSNS (8), COSTS_N_INSNS (10), COSTS_N_INSNS (8),
+    COSTS_N_INSNS (6), COSTS_N_INSNS (4)
+  },
+  /* mulQI */
+  COSTS_N_INSNS (3),
+  /* mulHI */
+  COSTS_N_INSNS (3),
+  /* mulSI */
+  COSTS_N_INSNS (3 * 4),
+  /* divQI */
+  COSTS_N_INSNS (12),
+  /* divHI */
+  COSTS_N_INSNS (12),
+  /* divSI */
+  COSTS_N_INSNS (100)
+};
+
 /* Machine specific options */
 
 const char *m68hc11_regparm_string;
@@ -130,24 +202,11 @@ static void m68hc11_add_gc_roots PARAMS ((void));
 
 static int nb_soft_regs;
 
-/* Flag defined in c-decl.c
-
-   Nonzero means don't recognize the non-ANSI builtin functions.
-   -ansi sets this.
-
-   It is set by 'm68hc11_override_options' to ensure that bcmp() and
-   bzero() are not defined.  Their prototype are wrong and they
-   conflict with newlib definition.  Don't define as external to
-   avoid a link problem for f77.  */
-int flag_no_nonansi_builtin;
-
 int
 m68hc11_override_options ()
 {
   m68hc11_add_gc_roots ();
 
-  flag_no_nonansi_builtin = 1;
-  
   memset (m68hc11_reg_valid_for_index, 0,
          sizeof (m68hc11_reg_valid_for_index));
   memset (m68hc11_reg_valid_for_base, 0, sizeof (m68hc11_reg_valid_for_base));
@@ -159,7 +218,8 @@ m68hc11_override_options ()
          a -m68hc11 option was specified on the command line.  */
       if (TARGET_DEFAULT != MASK_M6811)
         target_flags &= ~TARGET_DEFAULT;
-      
+
+      m68hc11_cost = &m6811_cost;
       m68hc11_min_offset = 0;
       m68hc11_max_offset = 256;
       m68hc11_index_reg_class = NO_REGS;
@@ -176,7 +236,8 @@ m68hc11_override_options ()
   /* Configure for a 68hc12 processor.  */
   if (TARGET_M6812)
     {
-      m68hc11_min_offset = 0;
+      m68hc11_cost = &m6812_cost;
+      m68hc11_min_offset = -65536;
       m68hc11_max_offset = 65536;
       m68hc11_index_reg_class = D_REGS;
       m68hc11_base_reg_class = A_OR_SP_REGS;
@@ -278,29 +339,6 @@ hard_regno_mode_ok (regno, mode)
 }
 
 enum reg_class
-limit_reload_class (mode, class)
-     enum machine_mode mode;
-     enum reg_class class;
-{
-  if (mode == Pmode)
-    {
-      if (class == m68hc11_base_reg_class || class == SP_REGS
-         || class == Y_REGS || class == X_REGS
-         || class == X_OR_SP_REGS || class == Y_OR_S_REGS
-         || class == A_OR_SP_REGS)
-       return class;
-
-      if (debug_m6811)
-       {
-         printf ("Forcing to A_REGS\n");
-         fflush (stdout);
-       }
-      return m68hc11_base_reg_class;
-    }
-  return class;
-}
-
-enum reg_class
 preferred_reload_class (operand, class)
      rtx operand;
      enum reg_class class;
@@ -733,13 +771,14 @@ m68hc11_emit_libcall (name, code, dmode, smode, noperands, operands)
   switch (noperands)
     {
     case 2:
-      ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 1,
-                                     operands[1], smode);
+      ret = emit_library_call_value (libcall, NULL_RTX, LCT_CONST,
+                                     dmode, 1, operands[1], smode);
       equiv = gen_rtx (code, dmode, operands[1]);
       break;
 
     case 3:
-      ret = emit_library_call_value (libcall, operands[0], 1, dmode, 2,
+      ret = emit_library_call_value (libcall, NULL_RTX,
+                                     LCT_CONST, dmode, 2,
                                      operands[1], smode, operands[2],
                                      smode);
       equiv = gen_rtx (code, dmode, operands[1], operands[2]);
@@ -2125,9 +2164,19 @@ print_operand (file, op, letter)
     }
   else
     {
+      int need_parenthesize = 0;
+
       if (letter != 'i')
        asm_fprintf (file, "%0I");
+      else
+        need_parenthesize = must_parenthesize (op);
+
+      if (need_parenthesize)
+        asm_fprintf (file, "(");
+
       output_addr_const (file, op);
+      if (need_parenthesize)
+        asm_fprintf (file, ")");
     }
 }
 
@@ -2508,6 +2557,7 @@ m68hc11_split_move (to, from, scratch)
   rtx low_to, low_from;
   rtx high_to, high_from;
   enum machine_mode mode;
+  int offset = 0;
 
   mode = GET_MODE (to);
   if (GET_MODE_SIZE (mode) == 8)
@@ -2517,6 +2567,22 @@ m68hc11_split_move (to, from, scratch)
   else
     mode = QImode;
 
+  if (TARGET_M6812
+      && IS_STACK_PUSH (to)
+      && reg_mentioned_p (gen_rtx (REG, HImode, HARD_SP_REGNUM), from))
+    {
+      if (mode == SImode)
+        {
+          offset = 4;
+        }
+      else if (mode == HImode)
+        {
+          offset = 2;
+        }
+      else
+        offset = 0;
+    }
+
   low_to = m68hc11_gen_lowpart (mode, to);
   high_to = m68hc11_gen_highpart (mode, to);
 
@@ -2531,6 +2597,11 @@ m68hc11_split_move (to, from, scratch)
   else
     high_from = m68hc11_gen_highpart (mode, from);
 
+  if (offset)
+    {
+      high_from = adj_offsettable_operand (high_from, offset);
+      low_from = high_from;
+    }
   if (mode == SImode)
     {
       m68hc11_split_move (low_to, low_from, scratch);
@@ -2823,6 +2894,7 @@ m68hc11_gen_movhi (insn, operands)
     {
       if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1]))
        {
+          cc_status = cc_prev_status;
          switch (REGNO (operands[1]))
            {
            case HARD_X_REGNUM:
@@ -2837,6 +2909,7 @@ m68hc11_gen_movhi (insn, operands)
        }
       if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0]))
        {
+          cc_status = cc_prev_status;
          switch (REGNO (operands[0]))
            {
            case HARD_X_REGNUM:
@@ -2851,6 +2924,7 @@ m68hc11_gen_movhi (insn, operands)
        }
       if (H_REG_P (operands[0]) && H_REG_P (operands[1]))
        {
+          m68hc11_notice_keep_cc (operands[0]);
          output_asm_insn ("tfr\t%1,%0", operands);
        }
       else if (H_REG_P (operands[0]))
@@ -2892,6 +2966,7 @@ m68hc11_gen_movhi (insn, operands)
              else
                {
                  /* !!!! SCz wrong here.  */
+                  fatal_insn ("Move insn not handled", insn);
                }
            }
          else
@@ -2903,6 +2978,7 @@ m68hc11_gen_movhi (insn, operands)
                }
              else
                {
+                  m68hc11_notice_keep_cc (operands[0]);
                  output_asm_insn ("movw\t%1,%0", operands);
                }
            }
@@ -2912,6 +2988,7 @@ m68hc11_gen_movhi (insn, operands)
 
   if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0]))
     {
+      cc_status = cc_prev_status;
       switch (REGNO (operands[0]))
        {
        case HARD_X_REGNUM:
@@ -2947,7 +3024,7 @@ m68hc11_gen_movhi (insn, operands)
                }
              else
                {
-                 cc_status = cc_prev_status;
+                  m68hc11_notice_keep_cc (operands[0]);
                  output_asm_insn ("pshx\n\tpula\n\tpulb", operands);
                }
            }
@@ -3002,7 +3079,7 @@ m68hc11_gen_movhi (insn, operands)
                }
              else
                {
-                 cc_status = cc_prev_status;
+                 m68hc11_notice_keep_cc (operands[0]);
                  output_asm_insn ("pshb", operands);
                  output_asm_insn ("psha", operands);
                  output_asm_insn ("pulx", operands);
@@ -3058,7 +3135,7 @@ m68hc11_gen_movhi (insn, operands)
        case HARD_SP_REGNUM:
          if (D_REG_P (operands[1]))
            {
-             cc_status = cc_prev_status;
+             m68hc11_notice_keep_cc (operands[0]);
              output_asm_insn ("xgdx", operands);
              output_asm_insn ("txs", operands);
              output_asm_insn ("xgdx", operands);
@@ -3099,6 +3176,7 @@ m68hc11_gen_movhi (insn, operands)
 
   if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1]))
     {
+      cc_status = cc_prev_status;
       switch (REGNO (operands[1]))
        {
        case HARD_X_REGNUM:
@@ -3182,25 +3260,26 @@ m68hc11_gen_movqi (insn, operands)
 
       if (H_REG_P (operands[0]) && H_REG_P (operands[1]))
        {
+          m68hc11_notice_keep_cc (operands[0]);
          output_asm_insn ("tfr\t%1,%0", operands);
        }
       else if (H_REG_P (operands[0]))
        {
          if (Q_REG_P (operands[0]))
-           output_asm_insn ("lda%0\t%1", operands);
+           output_asm_insn ("lda%0\t%b1", operands);
          else if (D_REG_P (operands[0]))
-           output_asm_insn ("ldab\t%1", operands);
+           output_asm_insn ("ldab\t%b1", operands);
          else
-           output_asm_insn ("ld%0\t%1", operands);
+           goto m6811_move;
        }
       else if (H_REG_P (operands[1]))
        {
          if (Q_REG_P (operands[1]))
-           output_asm_insn ("sta%1\t%0", operands);
+           output_asm_insn ("sta%1\t%b0", operands);
          else if (D_REG_P (operands[1]))
-           output_asm_insn ("staa\t%0", operands);
+           output_asm_insn ("stab\t%b0", operands);
          else
-           output_asm_insn ("st%1\t%0", operands);
+           goto m6811_move;
        }
       else
        {
@@ -3227,6 +3306,7 @@ m68hc11_gen_movqi (insn, operands)
              else
                {
                  /* !!!! SCz wrong here.  */
+                  fatal_insn ("Move insn not handled", insn);
                }
            }
          else
@@ -3237,13 +3317,15 @@ m68hc11_gen_movqi (insn, operands)
                }
              else
                {
-                 output_asm_insn ("movb\t%1,%0", operands);
+                  m68hc11_notice_keep_cc (operands[0]);
+                 output_asm_insn ("movb\t%b1,%b0", operands);
                }
            }
        }
       return;
     }
 
+ m6811_move:
   if (H_REG_P (operands[0]))
     {
       switch (REGNO (operands[0]))
@@ -3618,6 +3700,24 @@ m68hc11_notice_update_cc (exp, insn)
       && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
     cc_status.value2 = 0;
 }
+
+/* The current instruction does not affect the flags but changes
+   the register 'reg'.  See if the previous flags can be kept for the
+   next instruction to avoid a comparison.  */
+void
+m68hc11_notice_keep_cc (reg)
+     rtx reg;
+{
+  if (reg == 0
+      || cc_prev_status.value1 == 0
+      || rtx_equal_p (reg, cc_prev_status.value1)
+      || (cc_prev_status.value2
+          && reg_mentioned_p (reg, cc_prev_status.value2)))
+    CC_STATUS_INIT;
+  else
+    cc_status = cc_prev_status;
+}
+
 \f
 
 /* Machine Specific Reorg. */
@@ -3911,7 +4011,7 @@ m68hc11_check_z_replacement (insn, info)
            }
          info->x_used = 1;
          if (z_dies_here && !reg_mentioned_p (src, ix_reg)
-             && GET_CODE (src) == REG && REGNO (src) == HARD_X_REGNUM)
+             && GET_CODE (dst) == REG && REGNO (dst) == HARD_X_REGNUM)
            {
              info->need_save_z = 0;
              info->z_died = 1;
@@ -3982,7 +4082,7 @@ m68hc11_check_z_replacement (insn, info)
            }
          info->y_used = 1;
          if (z_dies_here && !reg_mentioned_p (src, iy_reg)
-             && GET_CODE (src) == REG && REGNO (src) == HARD_Y_REGNUM)
+             && GET_CODE (dst) == REG && REGNO (dst) == HARD_Y_REGNUM)
            {
              info->need_save_z = 0;
              info->z_died = 1;
@@ -4356,6 +4456,8 @@ m68hc11_z_replacement (insn)
               && INTVAL (src) == 0)
        {
          XEXP (body, 0) = gen_rtx (REG, GET_MODE (dst), SOFT_Z_REGNUM);
+          /* Force it to be re-recognized.  */
+          INSN_CODE (insn) = -1;
          return;
        }
     }
@@ -4577,6 +4679,7 @@ m68hc11_reorg (first)
      rtx first;
 {
   int split_done = 0;
+  rtx insn;
 
   z_replacement_completed = 0;
   z_reg = gen_rtx (REG, HImode, HARD_Z_REGNUM);
@@ -4602,6 +4705,28 @@ m68hc11_reorg (first)
      description to use the best assembly directives.  */
   if (optimize)
     {
+      /* Before recomputing the REG_DEAD notes, remove all of them.
+         This is necessary because the reload_cse_regs() pass can
+         have replaced some (MEM) with a register.  In that case,
+         the REG_DEAD that could exist for that register may become
+         wrong.  */
+      for (insn = first; insn; insn = NEXT_INSN (insn))
+        {
+          if (INSN_P (insn))
+            {
+              rtx *pnote;
+
+              pnote = &REG_NOTES (insn);
+              while (*pnote != 0)
+                {
+                  if (REG_NOTE_KIND (*pnote) == REG_DEAD)
+                    *pnote = XEXP (*pnote, 1);
+                  else
+                    pnote = &XEXP (*pnote, 1);
+                }
+            }
+        }
+
       find_basic_blocks (first, max_reg_num (), 0);
       life_analysis (first, 0, PROP_REG_INFO | PROP_DEATH_NOTES);
     }
@@ -4651,8 +4776,6 @@ m68hc11_reorg (first)
 
 /* Cost functions.  */
 
-#define COSTS_N_INSNS(N) ((N) * 4 - 2)
-
 /* Cost of moving memory. */
 int
 m68hc11_memory_move_cost (mode, class, in)
@@ -4783,10 +4906,43 @@ m68hc11_address_cost (addr)
   return cost;
 }
 
+static int
+m68hc11_shift_cost (mode, x, shift)
+     enum machine_mode mode;
+     rtx x;
+     int shift;
+{
+  int total;
+
+  total = rtx_cost (x, SET);
+  if (mode == QImode)
+    total += m68hc11_cost->shiftQI_const[shift % 8];
+  else if (mode == HImode)
+    total += m68hc11_cost->shiftHI_const[shift % 16];
+  else if (shift == 8 || shift == 16 || shift == 32)
+    total += m68hc11_cost->shiftHI_const[8];
+  else if (shift != 0 && shift != 16 && shift != 32)
+    {
+      total += m68hc11_cost->shiftHI_const[1] * shift;
+    }
+
+  /* For SI and others, the cost is higher.  */
+  if (GET_MODE_SIZE (mode) > 2)
+    total *= GET_MODE_SIZE (mode) / 2;
+
+  /* When optimizing for size, make shift more costly so that
+     multiplications are prefered.  */
+  if (optimize_size && (shift % 8) != 0)
+    total *= 2;
+  
+  return total;
+}
+
 int
 m68hc11_rtx_costs (x, code, outer_code)
      rtx x;
-     enum rtx_code code, outer_code;
+     enum rtx_code code;
+     enum rtx_code outer_code ATTRIBUTE_UNUSED;
 {
   enum machine_mode mode = GET_MODE (x);
   int extra_cost = 0;
@@ -4794,9 +4950,6 @@ m68hc11_rtx_costs (x, code, outer_code)
 
   switch (code)
     {
-    case MEM:
-      return m68hc11_address_cost (XEXP (x, 0)) + 4;
-
     case ROTATE:
     case ROTATERT:
     case ASHIFT:
@@ -4804,82 +4957,91 @@ m68hc11_rtx_costs (x, code, outer_code)
     case ASHIFTRT:
       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
        {
-         int val = INTVAL (XEXP (x, 1));
-         int cost;
-
-         /* 8 or 16 shift instructions are fast.
-            Others are proportional to the shift counter.  */
-         if (val == 8 || val == 16 || val == -8 || val == -16)
-           {
-             val = 0;
-           }
-         cost = COSTS_N_INSNS (val + 1);
-         cost += rtx_cost (XEXP (x, 0), outer_code);
-         if (GET_MODE_SIZE (mode) >= 4 && val)
-           {
-             cost *= 4;
-           }
-         return cost;
-       }
-      total = rtx_cost (XEXP (x, 0), outer_code);
-      if (GET_MODE_SIZE (mode) >= 4)
-       {
-         total += COSTS_N_INSNS (16);
-       }
-      else
-       {
-         total += COSTS_N_INSNS (8);
+          return m68hc11_shift_cost (mode, XEXP (x, 0), INTVAL (XEXP (x, 1)));
        }
+
+      total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+      total += m68hc11_cost->shift_var;
       return total;
 
-    case MINUS:
-    case PLUS:
     case AND:
     case XOR:
     case IOR:
-      extra_cost = 0;
+      total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+      total += m68hc11_cost->logical;
 
-      total = rtx_cost (XEXP (x, 0), outer_code)
-       + rtx_cost (XEXP (x, 1), outer_code);
-      if (GET_MODE_SIZE (mode) <= 2)
-       {
-         total += COSTS_N_INSNS (2);
-       }
-      else
+      /* Logical instructions are byte instructions only.  */
+      total *= GET_MODE_SIZE (mode);
+      return total;
+
+    case MINUS:
+    case PLUS:
+      total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+      total += m68hc11_cost->add;
+      if (GET_MODE_SIZE (mode) > 2)
        {
-         total += COSTS_N_INSNS (4);
+         total *= GET_MODE_SIZE (mode) / 2;
        }
       return total;
 
+    case UDIV:
     case DIV:
     case MOD:
-      if (mode == QImode || mode == HImode)
-       {
-         return 30;
-       }
-      else if (mode == SImode)
-       {
-         return 100;
-       }
-      else
-       {
-         return 150;
-       }
-
+      total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+      switch (mode)
+        {
+        case QImode:
+          total += m68hc11_cost->divQI;
+          break;
+
+        case HImode:
+          total += m68hc11_cost->divHI;
+          break;
+
+        case SImode:
+        default:
+          total += m68hc11_cost->divSI;
+          break;
+        }
+      return total;
+      
     case MULT:
-      if (mode == QImode)
-       {
-         return TARGET_OP_TIME ? 10 : 2;
-       }
-      if (mode == HImode)
-       {
-         return TARGET_OP_TIME ? 30 : 4;
-       }
-      if (mode == SImode)
-       {
-         return TARGET_OP_TIME ? 100 : 20;
-       }
-      return 150;
+      /* mul instruction produces 16-bit result.  */
+      if (mode == HImode && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+          && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
+        return m68hc11_cost->multQI
+          + rtx_cost (XEXP (XEXP (x, 0), 0), code)
+          + rtx_cost (XEXP (XEXP (x, 1), 0), code);
+
+      /* emul instruction produces 32-bit result for 68HC12.  */
+      if (TARGET_M6812 && mode == SImode
+          && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+          && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
+        return m68hc11_cost->multHI
+          + rtx_cost (XEXP (XEXP (x, 0), 0), code)
+          + rtx_cost (XEXP (XEXP (x, 1), 0), code);
+
+      total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+      switch (mode)
+        {
+        case QImode:
+          total += m68hc11_cost->multQI;
+          break;
+
+        case HImode:
+          total += m68hc11_cost->multHI;
+          break;
+
+        case SImode:
+          if (GET_CODE (XEXP (x, 1)) == CONST_INT
+              && INTVAL (XEXP (x, 1)) == 65536)
+            break;
+
+        default:
+          total += m68hc11_cost->multSI;
+          break;
+        }
+      return total;
 
     case NEG:
     case SIGN_EXTEND:
@@ -4890,20 +5052,20 @@ m68hc11_rtx_costs (x, code, outer_code)
     case COMPARE:
     case ABS:
     case ZERO_EXTEND:
-      total = rtx_cost (XEXP (x, 0), outer_code);
+      total = extra_cost + rtx_cost (XEXP (x, 0), code);
       if (mode == QImode)
        {
-         return total + extra_cost + COSTS_N_INSNS (1);
+         return total + COSTS_N_INSNS (1);
        }
       if (mode == HImode)
        {
-         return total + extra_cost + COSTS_N_INSNS (2);
+         return total + COSTS_N_INSNS (2);
        }
       if (mode == SImode)
        {
-         return total + extra_cost + COSTS_N_INSNS (4);
+         return total + COSTS_N_INSNS (4);
        }
-      return total + extra_cost + COSTS_N_INSNS (8);
+      return total + COSTS_N_INSNS (8);
 
     case IF_THEN_ELSE:
       if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
index ba4eac7..475bf9c 100644 (file)
@@ -207,6 +207,25 @@ extern const char *m68hc11_soft_reg_count;
    `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */
 
 #define OVERRIDE_OPTIONS       m68hc11_override_options ();
+
+\f
+/* Define cost parameters for a given processor variant.  */
+struct processor_costs {
+  int add;             /* cost of an add instruction */
+  int logical;          /* cost of a logical instruction */
+  int shift_var;
+  int shiftQI_const[8];
+  int shiftHI_const[16];
+  int multQI;
+  int multHI;
+  int multSI;
+  int divQI;
+  int divHI;
+  int divSI;
+};
+
+/* Costs for the current processor.  */
+extern struct processor_costs *m68hc11_cost;
 \f
 
 /* target machine storage layout */
@@ -769,9 +788,6 @@ extern enum reg_class m68hc11_tmp_regs_class;
 
 #define PREFERRED_RELOAD_CLASS(X,CLASS)        preferred_reload_class(X,CLASS)
 
-
-#define LIMIT_RELOAD_CLASS(MODE, CLASS) limit_reload_class(MODE,CLASS)
-
 #define SMALL_REGISTER_CLASSES 1
 
 /* A C expression whose value is nonzero if pseudos that have been
@@ -1456,22 +1472,52 @@ extern unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER];
 
 /* Compute the cost of computing a constant rtl expression RTX whose rtx-code
    is CODE.  The body of this macro is a portion of a switch statement.  If
-   the code is computed here, return it with a return statement. Otherwise,
-   break from the switch.  */
-#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
- case CONST_INT:                        \
-    if (RTX == const0_rtx) return 0;    \
- case CONST:                            \
-    return 0;                            \
- case LABEL_REF:                        \
- case SYMBOL_REF:                       \
-   return 1;                            \
- case CONST_DOUBLE:                     \
+   the code is computed here, return it with a return statement.  Otherwise,
+   break from the switch.
+
+   Constants are cheap.  Moving them in registers must be avoided
+   because most instructions do not handle two register operands.  */
+#define CONST_COSTS(RTX,CODE,OUTER_CODE)                       \
+ case CONST_INT:                                               \
+     /* Logical and arithmetic operations with a constant  */  \
+     /* operand are better because they are not supported  */  \
+     /* with two registers.  */                                        \
+     /* 'clr' is slow */                                       \
+   if ((OUTER_CODE) == SET && (RTX) == const0_rtx)             \
+     return 1;                                                 \
+   else                                                                \
+     return 0;                                                 \
+ case CONST:                                                   \
+ case LABEL_REF:                                               \
+ case SYMBOL_REF:                                              \
+   if ((OUTER_CODE) == SET)                                    \
+      return 1;                                                        \
+   return 0;                                                   \
+ case CONST_DOUBLE:                                            \
    return 0;
 
-#define DEFAULT_RTX_COSTS(X,CODE,OUTER_CODE)           \
-    return m68hc11_rtx_costs (X, CODE, OUTER_CODE);
-
+#define RTX_COSTS(X,CODE,OUTER_CODE)                           \
+ case ROTATE:                                                  \
+ case ROTATERT:                                                        \
+ case ASHIFT:                                                  \
+ case LSHIFTRT:                                                        \
+ case ASHIFTRT:                                                        \
+ case MINUS:                                                   \
+ case PLUS:                                                    \
+ case AND:                                                     \
+ case XOR:                                                     \
+ case IOR:                                                     \
+ case UDIV:                                                    \
+ case DIV:                                                     \
+ case MOD:                                                     \
+ case MULT:                                                    \
+ case NEG:                                                     \
+ case SIGN_EXTEND:                                             \
+ case NOT:                                                     \
+ case COMPARE:                                                 \
+ case ZERO_EXTEND:                                             \
+ case IF_THEN_ELSE:                                            \
+   return m68hc11_rtx_costs (X, CODE, OUTER_CODE);
 
 /* An expression giving the cost of an addressing mode that contains
    ADDRESS.  If not defined, the cost is computed from the ADDRESS
index 4cd495a..ec6956e 100644 (file)
 ;;   Such split pattern must also be valid when z_replacement_completed == 2
 ;;   because flow/cse is not aware that D is composed of {a, b}.
 ;;
+;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
+;;   the high part of a soft register must be expanded after z_replacement
+;;   pass.
+;;
+;;---------------------------------------------------------------------------
+;; Constants
+
+(define_constants [
+   ;; Register numbers
+   (X_REGNUM       0)          ; Index X register
+   (D_REGNUM       1)          ; Data register
+   (Y_REGNUM        2)         ; Index Y register
+   (SP_REGNUM       3)          ; Stack pointer
+   (PC_REGNUM      4)          ; Program counter
+   (A_REGNUM        5)         ; A (high part of D)
+   (B_REGNUM        6)         ; B (low part of D)
+   (CC_REGNUM       7)         ; Condition code register
+])
 
 ;;--------------------------------------------------------------------
 ;;-  Test
   ""
   "*
 {
-   if (D_REG_P (operands[0]))
+   if (D_REG_P (operands[0]) && !TARGET_M6812)
      return \"std\\t%t0\";
    else
      return \"cp%0\\t#0\";
    (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 3))) (match_dup 1))
+  [(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 3))))]
+   (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
   "operands[2] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
 
 
    (use (match_operand:HI 2 "hard_reg_operand" "dxy"))
    (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) (compare (match_dup 0) (match_dup 1)))
-   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI 3))))]
+   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
   "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
 
 ;;
        (compare (match_operand:QI 0 "hard_addr_reg_operand" "xy")
                 (match_operand:QI 1 "cmp_operand" "uimA")))]
   "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
-  [(parallel [(set (reg:HI 1) (match_dup 3))
-              (set (match_dup 3) (reg:HI 1))])
+  [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
+              (set (match_dup 3) (reg:HI D_REGNUM))])
    (set (cc0)
-        (compare (reg:QI 1) (match_dup 1)))
-   (parallel [(set (reg:HI 1) (match_dup 3))
-              (set (match_dup 3) (reg:HI 1))])]
+        (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]));")
 
 (define_split
    (use (match_operand:HI 2 "hard_reg_operand" "dxy"))
    (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) (compare (match_dup 0) (match_dup 1)))
-   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI 3))))]
+   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
   "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
 
 (define_expand "cmpdf"
   "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode
    && !reg_mentioned_p (operands[0], operands[1])
    && !D_REG_P (operands[1])"
-  [(parallel [(set (reg:HI 1) (match_dup 2))
-              (set (match_dup 2) (reg:HI 1))])
-   (set (reg:QI 1) (match_dup 1))
-   (parallel [(set (reg:HI 1) (match_dup 2))
-              (set (match_dup 2) (reg:HI 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]));")
 
 ;;
   "z_replacement_completed == 2 && GET_MODE (operands[1]) == QImode
    && !reg_mentioned_p (operands[1], operands[0])
    && !D_REG_P (operands[0])"
-  [(parallel [(set (reg:HI 1) (match_dup 2))
-              (set (match_dup 2) (reg:HI 1))])
-   (set (match_dup 0) (reg:QI 1))
-   (parallel [(set (reg:HI 1) (match_dup 2))
-              (set (match_dup 2) (reg:HI 1))])]
+  [(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]));")
 
 (define_insn "*movqi2_push"
   [(set (match_operand:SI 0 "non_push_operand" "=mu")
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dxy")))]
   "reload_completed && !X_REG_P (operands[0])"
-  [(set (match_dup 2) (match_dup 3))
-   (set (match_dup 4) (const_int 0))
-   (set (match_dup 5) (const_int 0))]
+  [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
+   (set (match_dup 3) (const_int 0))]
   "
    operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
-   operands[3] = gen_rtx (REG, HImode, REGNO (operands[1]));
-   operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
-   operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
-   operands[5] = m68hc11_gen_highpart (HImode, operands[0]);")
+   operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
 
 (define_split 
   [(set (match_operand:SI 0 "hard_reg_operand" "=D")
   [(set (match_operand:SI 0 "register_operand" "=D")
        (sign_extend:SI (match_operand:HI 1 "register_operand" "A")))]
   "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
-  [(set (reg:HI 1) (match_dup 1))
-   (set (match_dup 0) (sign_extend:SI (reg:HI 1)))]
+  [(set (reg:HI D_REGNUM) (match_dup 1))
+   (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
   "")
 
 (define_insn "extendhisi2"
                 (match_dup 0)))
    (clobber (match_scratch:HI 1 "=X"))]
   "reload_completed && z_replacement_completed == 2"
-  [(set (reg:HI 1) (ashift:HI (reg:HI 1) (const_int 1)))
-   (parallel [(set (reg:HI 1) (reg:HI 0))
-              (set (reg:HI 0) (reg:HI 1))])
-   (set (reg:QI 6) (rotate:QI (reg:QI 6) (reg:QI 7)))
-   (set (reg:QI 5) (rotate:QI (reg:QI 5) (reg:QI 7)))
-   (parallel [(set (reg:HI 1) (reg:HI 0))
-              (set (reg:HI 0) (reg:HI 1))])]
+  [(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))])]
   "")
 
 
                 (match_operand:SI 2 "memory_operand" "m,m")))
    (clobber (match_scratch:HI 3 "=X,X"))]
   "reload_completed"
-  [(set (reg:HI 1) (zero_extend:HI (match_dup 1)))
+  [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
    (parallel [(set (match_dup 0) 
-                  (plus:SI (zero_extend:SI (reg:HI 1)) (match_dup 2)))
+                  (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
              (clobber (match_dup 3))])]
   "")
 
    (clobber (match_scratch:HI 3 "=X"))]
   "reload_completed && z_replacement_completed == 2
    && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
-  [(set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 3)))]
+  [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 3)))]
   "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);")
 
 (define_split
   "reload_completed && z_replacement_completed == 2
    && (GET_CODE (operands[2]) != CONST_INT || 
         (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
-  [(set (reg:HI 1) (plus:HI (reg:HI 1) (match_dup 3)))
-   (parallel [(set (reg:HI 1) (reg:HI 0))
-              (set (reg:HI 0) (reg:HI 1))])
-   (set (reg:QI 6) (plus:QI (plus:QI (reg:QI 7) (reg:QI 6)) (match_dup 4)))
-   (set (reg:QI 5) (plus:QI (plus:QI (reg:QI 7) (reg:QI 5)) (match_dup 5)))
-   (parallel [(set (reg:HI 1) (reg:HI 0))
-              (set (reg:HI 0) (reg:HI 1))])]
+  [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
+   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
+              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
+   (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
+   (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
+   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
+              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
   "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
    operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
   [(set (match_operand:HI 0 "register_operand" "=x")
            (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
                             (const_int 0)) 
-                   (reg:HI 7)))]
+                   (reg:HI CC_REGNUM)))]
   ""
   "*
 {
   "")
 
 (define_insn "*addhi3_68hc12"
-  [(set (match_operand:HI 0 "register_operand" "=d,A*w,A*w")
-        (plus:HI (match_operand:HI 1 "register_operand" "%0,0,Aw")
-                 (match_operand:HI 2 "general_operand" "imA*wu,id,id")))]
+  [(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")))]
   "TARGET_M6812"
   "*
 {
   int val;
   const char* insn_code;
 
+  if (which_alternative >= 3)
+    {
+      if (A_REG_P (operands[2]))
+        {
+         CC_STATUS_INIT;
+         output_asm_insn (\"xgd%2\", operands);
+         output_asm_insn (\"lea%0 d,%0\", operands);
+         return \"xgd%2\";
+       }
+      return \"#\";
+    }
+
   if (D_REG_P (operands[0]))
     {
       if (X_REG_P (operands[2]))
        {
+         m68hc11_notice_keep_cc (operands[0]);
          output_asm_insn (\"xgdx\", operands);
          output_asm_insn (\"leax\\td,%2\", operands);
          return \"xgdx\";
        }
       else if (Y_REG_P (operands[2]))
        {
+         m68hc11_notice_keep_cc (operands[0]);
          output_asm_insn (\"xgdy\", operands);
          output_asm_insn (\"leay\\td,%2\", operands);
          return \"xgdy\";
 
   if (val != -1 || val != 1 || !rtx_equal_p (operands[0], operands[1]))
     {
-      cc_status = cc_prev_status;
+      m68hc11_notice_keep_cc (operands[0]);
       switch (REGNO (operands[0]))
        {
        case HARD_X_REGNUM:
   "")
 
 (define_insn "*addhi3"
-  [(set (match_operand:HI 0 "hard_reg_operand" "=A,d,!A,d*A,!d,!w")
-       (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0")
-                (match_operand:HI 2 "general_operand" "N,i,I,umi*A*d,!*d*w,i")))]
+  [(set (match_operand:HI 0 "hard_reg_operand" "=A,d,!A,d*A,!d")
+       (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0")
+                (match_operand:HI 2 "general_operand" "N,i,I,umi*A*d,!*d*w")))]
   "TARGET_M6811"
   "*
 {
 ;;
 (define_insn "*adcq"
   [(set (match_operand:QI 0 "register_operand" "=q")
-        (plus:QI (plus:QI (reg:QI 7)
+        (plus:QI (plus:QI (reg:QI CC_REGNUM)
                           (match_operand:QI 1 "register_operand" "%0"))
                  (match_operand:QI 2 "general_operand" "ium")))]
   ""
    (clobber (match_scratch:HI 3 "=X"))]
   "reload_completed && z_replacement_completed == 2
    && X_REG_P (operands[1])"
-  [(set (reg:HI 1) (minus:HI (reg:HI 1) (match_dup 3)))
-   (parallel [(set (reg:HI 0) (reg:HI 1))
-              (set (reg:HI 1) (reg:HI 0))])
-   (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 4)))
-   (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 5)))
-   (parallel [(set (reg:HI 0) (reg:HI 1))
-              (set (reg:HI 1) (reg:HI 0))])]
+  [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
+   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
+              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
+   (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
+   (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
+   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
+              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
   "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
    operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
    (clobber (match_scratch:HI 3 "=X"))]
   "reload_completed && z_replacement_completed == 2
    && X_REG_P (operands[2])"
-  [(set (reg:HI 1) (minus:HI (reg:HI 1) (match_dup 3)))
-   (parallel [(set (reg:HI 0) (reg:HI 1))
-              (set (reg:HI 1) (reg:HI 0))])
-   (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 4)))
-   (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 5)))
-   (parallel [(set (reg:HI 0) (reg:HI 1))
-              (set (reg:HI 1) (reg:HI 0))])
+  [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
+   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
+              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
+   (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
+   (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
+   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
+              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
    (set (reg:SI 0) (neg:SI (reg:SI 0)))]
   "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
    operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
 ;;
 (define_insn "*subcq"
   [(set (match_operand:QI 0 "register_operand" "=q")
-        (minus:QI (minus:QI (reg:QI 7)
+        (minus:QI (minus:QI (reg:QI CC_REGNUM)
                             (match_operand:QI 1 "register_operand" "0"))
                   (match_operand:QI 2 "general_operand" "ium")))]
   ""
                     (match_operand:QI 1 "general_operand" "dxy,imu"))
                  (match_operand:SI 2 "general_operand" "imuD,imuD")]))]
   "z_replacement_completed == 2"
-  [(set (reg:QI 5) (match_dup 4))
-   (set (reg:QI 1) (match_dup 7))
-   (set (reg:QI 6) (match_op_dup 3 [(reg:QI 6) (match_dup 5)]))
-   (set (reg:HI 0) (match_dup 6))]
+  [(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], QImode);
    if (X_REG_P (operands[2]))
      {
                     (match_operand:HI 1 "general_operand" "dA,imu"))
                  (match_operand:SI 2 "general_operand" "imuD,imuD")]))]
   "reload_completed"
-  [(set (reg:HI 1) (match_dup 4))
-   (set (reg:HI 1) (match_op_dup 3 [(reg:HI 1) (match_dup 5)]))
-   (set (reg:HI 0) (match_dup 6))]
+  [(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], HImode);
    if (X_REG_P (operands[2]))
      {
                     (match_operand:QI 1 "general_operand" "imud"))
                 (match_operand:HI 2 "general_operand" "dimu")]))]
   "z_replacement_completed == 2"
-  [(set (reg:QI 6) (match_dup 6))
-   (set (reg:QI 5) (match_dup 4))
-   (set (reg:QI 6) (match_op_dup 3 [(reg:QI 6) (match_dup 5)]))]
+  [(set (reg:QI B_REGNUM) (match_dup 6))
+   (set (reg:QI A_REGNUM) (match_dup 4))
+   (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
   "
    PUT_MODE (operands[3], QImode);
    if (D_REG_P (operands[2]))
                     (match_operand:HI 2 "general_operand" "dimu")
                     (const_int 8))]))]
   "z_replacement_completed == 2"
-  [(set (reg:QI 6) (match_dup 5))
-   (set (reg:QI 5) (match_dup 4))]
+  [(set (reg:QI A_REGNUM) (match_dup 4))
+   (set (reg:QI B_REGNUM) (match_dup 5))]
   "
    if (GET_CODE (operands[3]) == AND)
      {
                        (const_int 16))
                 (match_operand:SI 2 "general_operand" "uim,0")]))]
   "reload_completed"
-  [(set (reg:HI 1) (match_dup 4))
-   (set (reg:HI 1) (match_op_dup 3 [(reg:HI 1) (match_dup 5)]))
-   (set (reg:HI 0) (match_dup 6))]
+  [(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))]
   "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
    if (X_REG_P (operands[2]))
      {
                        (const_int 16))
                 (match_operand:SI 2 "general_operand" "0,0")]))]
   "z_replacement_completed == 2"
-  [(parallel [(set (reg:HI 1) (reg:HI 0))
-              (set (reg:HI 0) (reg:HI 1))])
-  (set (reg:HI 1) (match_op_dup 3 [(reg:HI 1) (match_dup 4)]))
-  (parallel [(set (reg:HI 1) (reg:HI 0))
-             (set (reg:HI 0) (reg:HI 1))])]
+  [(parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
+              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
+  (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 4)]))
+  (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
+             (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
   "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
    PUT_MODE (operands[3], HImode);")
 
    /* 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[3]) == PLUS 
-        && (TARGET_M6812
+        && ((TARGET_M6812 
+            && (immediate_operand (operands[2], HImode)
+                || hard_reg_operand (operands[2], HImode)))
             || (GET_CODE (operands[2]) == CONST_INT
                && INTVAL (operands[2]) >= -4
                && INTVAL (operands[2]) <= 4)))"
   [(set (match_dup 4) (match_dup 5))
    (set (match_dup 8) (match_dup 7))
-   (parallel [(set (reg:HI 1) (match_dup 0))
-              (set (match_dup 0) (reg:HI 1))])
-   (set (reg:HI 1) (match_op_dup 3 [(reg:HI 1) (match_dup 6)]))
-   (parallel [(set (reg:HI 1) (match_dup 0))
-              (set (match_dup 0) (reg:HI 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))])]
   "
    /* Save the operand2 in a temporary location and use it. */
    if (H_REG_P (operands[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[3]) == PLUS 
-        && (TARGET_M6812
+        && ((TARGET_M6812 
+           && (immediate_operand (operands[2], HImode)
+               || hard_reg_operand (operands[2], HImode)))
             || (GET_CODE (operands[2]) == CONST_INT
                && INTVAL (operands[2]) >= -4
                && INTVAL (operands[2]) <= 4)))"
   [(set (match_dup 0) (match_dup 1))
-   (parallel [(set (reg:HI 1) (match_dup 0))
-              (set (match_dup 0) (reg:HI 1))])
-   (set (reg:HI 1) (match_op_dup 3 [(reg:HI 1) (match_dup 2)]))
-   (parallel [(set (reg:HI 1) (match_dup 0))
-              (set (match_dup 0) (reg:HI 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 2)]))
+   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
+              (set (match_dup 0) (reg:HI D_REGNUM))])]
   "
    ")
 
             [(match_operand 1 "general_operand" "uim*d*A")]))]
   "z_replacement_completed == 2"
   [(set (match_dup 4) (match_dup 5))
-   (parallel [(set (reg:HI 1) (match_dup 0))
-              (set (match_dup 0) (reg:HI 1))])
-   (set (reg:HI 1) (match_op_dup 2 [(match_dup 3)]))
-   (parallel [(set (reg:HI 1) (match_dup 0))
-              (set (match_dup 0) (reg:HI 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 2 [(match_dup 3)]))
+   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
+              (set (match_dup 0) (reg:HI D_REGNUM))])]
   "
 {
   if ((H_REG_P (operands[1])
         && GET_CODE (operands[2]) == CONST_INT
         && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
   [(set (match_dup 5) (match_dup 6))
-   (parallel [(set (reg:HI 1) (match_dup 4))
-              (set (match_dup 4) (reg:HI 1))])
-   (set (reg:QI 1) (match_op_dup 3 [(reg:QI 1) (match_dup 7)]))
-   (parallel [(set (reg:HI 1) (match_dup 4))
-              (set (match_dup 4) (reg:HI 1))])]
+   (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
+              (set (match_dup 4) (reg:HI D_REGNUM))])
+   (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]));
 
    /* For the second operand is a hard register or if the address
             [(match_operand:QI 1 "general_operand" "uim*d*x*y")]))]
   "z_replacement_completed == 2"
   [(set (match_dup 4) (match_dup 5))
-   (parallel [(set (reg:HI 1) (match_dup 3))
-              (set (match_dup 3) (reg:HI 1))])
-   (set (reg:QI 1) (match_op_dup 2 [(match_dup 6)]))
-   (parallel [(set (reg:HI 1) (match_dup 3))
-              (set (match_dup 3) (reg:HI 1))])]
+   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
+              (set (match_dup 3) (reg:HI D_REGNUM))])
+   (set (reg:QI D_REGNUM) (match_op_dup 2 [(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]));
        (not:SI (match_operand:SI 1 "non_push_operand" "0")))]
   "z_replacement_completed == 2
    && (!D_REG_P (operands[0]) || (optimize && optimize_size == 0))"
-  [(set (reg:HI 1) (not:HI (reg:HI 1)))
-   (parallel [(set (reg:HI 0) (reg:HI 1))
-              (set (reg:HI 1) (reg:HI 0))])
-   (set (reg:HI 1) (not:HI (reg:HI 1)))
-   (parallel [(set (reg:HI 0) (reg:HI 1))
-              (set (reg:HI 1) (reg:HI 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.
     (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 7)))
+    (set (match_dup 2) (rotate:HI (match_dup 2) (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 7)))
+    (set (match_dup 2) (rotate:HI (match_dup 2) (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 7)))
+    (set (match_dup 2) (rotate:HI (match_dup 2) (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]);
                                (const_int 16))
                   (match_operand:SI 2 "general_operand" "0")))]
   "z_replacement_completed == 2"
-  [(set (reg:HI 1) (plus:HI (reg:HI 1) (match_dup 3)))
-   (set (reg:HI 0) (plus:HI (plus:HI (reg:HI 0) (const_int 0)) (reg:HI 7)))]
+  [(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)))]
   "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
 
 (define_insn "addsi_ashift16"
                   (match_operand:SI 1 "general_operand" "0")))
    (clobber (match_scratch:HI 3 "=X"))]
   "0 && reload_completed && z_replacement_completed == 2"
-  [(set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))]
+  [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
   "
 {
   operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
                           (const_int 65535))
                   (match_operand:SI 2 "general_operand" "0")))]
   "z_replacement_completed == 2"
-  [(set (reg:HI 1) (plus:HI (reg:HI 1) (match_dup 3)))
-   (set (reg:HI 0) (plus:HI (plus:HI (reg:HI 0) (const_int 0)) (reg:HI 7)))]
+  [(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)))]
   "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
 
 ;;
                   (const_int 16)))
    (clobber (match_scratch:HI 2 "=X"))]
    "reload_completed"
-   [(set (reg:HI 0) (match_dup 1))
-    (set (reg:HI 1) (const_int 0))]
+   [(set (reg:HI X_REGNUM) (match_dup 1))
+    (set (reg:HI D_REGNUM) (const_int 0))]
    "")
 
 (define_insn "*ashlsi3_const1"
 (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")))
+                   (match_operand:HI 2 "register_operand" "+x")))
    (clobber (match_dup 2))]
   ""
   "*
   return \"bsr\\t___lshlhi3\";
 }")
 
-(define_insn ""
+(define_insn "*ashlhi3"
   [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
        (ashift:HI (match_dup 0)
-                  (match_operand:HI 1 "register_operand" "x")))
+                  (match_operand:HI 1 "register_operand" "+x")))
    (clobber (match_dup 1))]
   ""
   "*
       output_asm_insn (\"rolb\", operands);
       output_asm_insn (\"rola\", operands);
       output_asm_insn (\"tab\", operands);
-      output_asm_insn (\"anda\\t#1\", operands);
+      output_asm_insn (\"anda\\t#0\", operands);
       output_asm_insn (\"bcc\\t%l0\", ops);
-      output_asm_insn (\"oraa\\t#0xFE\", ops);
+      output_asm_insn (\"coma\", ops);
 
       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[0]));
 (define_insn "*ashrhi3"
   [(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")))
+                    (match_operand:HI 2 "register_operand" "+x,+d")))
    (clobber (match_dup 2))]
   ""
   "*
                     (match_operand:DI 2 "const_int_operand" "")))
    (clobber (match_scratch:HI 3 "=d"))]
    "z_replacement_completed && INTVAL (operands[2]) >= 56"
-   [(set (reg:QI 1) (match_dup 9))
-    (set (reg:QI 1) (lshiftrt:QI (reg:QI 1) (match_dup 8)))
-    (set (reg:HI 1) (zero_extend:HI (reg:QI 1)))
-    (set (match_dup 4) (reg:HI 1))
-    (set (reg:QI 1) (const_int 0))
-    (set (match_dup 5) (reg:HI 1))
-    (set (match_dup 6) (reg:HI 1))
-    (set (match_dup 7) (reg:HI 1))]
+   [(set (reg:QI D_REGNUM) (match_dup 9))
+    (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
+    (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
+    (set (match_dup 4) (reg:HI D_REGNUM))
+    (set (reg:QI D_REGNUM) (const_int 0))
+    (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[4] = m68hc11_gen_lowpart (SImode, operands[0]);
     operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
    (clobber (match_scratch:HI 3 "=d"))]
    "z_replacement_completed && INTVAL (operands[2]) >= 48 
     && INTVAL (operands[2]) < 56"
-   [(set (reg:HI 1) (match_dup 9))
-    (set (reg:HI 1) (lshiftrt:HI (reg:HI 1) (match_dup 8)))
-    (set (match_dup 4) (reg:HI 1))
-    (set (reg:HI 1) (const_int 0))
-    (set (match_dup 5) (reg:HI 1))
-    (set (match_dup 6) (reg:HI 1))
-    (set (match_dup 7) (reg:HI 1))]
+   [(set (reg:HI D_REGNUM) (match_dup 9))
+    (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
+    (set (match_dup 4) (reg:HI D_REGNUM))
+    (set (reg:HI D_REGNUM) (const_int 0))
+    (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[4] = m68hc11_gen_lowpart (SImode, operands[0]);
     operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
     (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 7)))
+    (set (match_dup 2) (rotatert:HI (match_dup 2) (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 7)))
+    (set (match_dup 2) (rotatert:HI (match_dup 2) (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 7)))
+    (set (match_dup 2) (rotatert:HI (match_dup 2) (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]);
                     (const_int 16)))
    (clobber (match_scratch:HI 2 "=X,X,X,X"))]
    ""
-   "#
+   "@
+    #
     xgdx\\n\\tldx\\t#0
+    #
     #")
 
 (define_insn "*lshrsi3_const1"
 (define_insn "*lshrhi3"
   [(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")))
+                    (match_operand:HI 2 "register_operand" "+x,+d")))
    (clobber (match_dup 2))]
   ""
   "*
 (define_insn "*rotlqi3_with_carry"
   [(set (match_operand:QI 0 "register_operand" "=d,!q")
        (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
-                  (reg:QI 7)))]
+                  (reg:QI CC_REGNUM)))]
   ""
   "*
 {
 (define_insn "*rotlhi3_with_carry"
   [(set (match_operand:HI 0 "register_operand" "=d")
        (rotate:HI (match_operand:HI 1 "register_operand" "0")
-                  (reg:HI 7)))]
+                  (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 7)))]
+                    (reg:HI CC_REGNUM)))]
   ""
   "*
 {
 ;;
 ;;- Call a function that returns no value.
 (define_insn "call"
-  [(call (match_operand:QI 0 "memory_operand" "mAi")
+  [(call (match_operand:QI 0 "memory_operand" "m")
         (match_operand:SI 1 "general_operand" "g"))]
   ;; Operand 1 not really used on the m68hc11.
   ""
 
 (define_insn "call_value"
   [(set (match_operand 0 "" "=g")
-       (call (match_operand:QI 1 "general_operand" "mAi")
+       (call (match_operand:QI 1 "memory_operand" "m")
              (match_operand:SI 2 "general_operand" "g")))]
   ""
  "*
 
 (define_insn "*return_16bit"
   [(return)
-   (use (reg:HI 1))]
+   (use (reg:HI D_REGNUM))]
   "reload_completed && m68hc11_total_frame_size () == 0"
   "*
 {
 (define_peephole
   [(set (match_operand:HI 0 "hard_reg_operand" "xy")
        (match_operand:HI 1 "const_int_operand" ""))
-   (parallel [(set (reg:HI 1) (match_dup 0))
-             (set (match_dup 0) (reg:HI 1))])
-   (set (reg:HI 1)
-       (plus (reg:HI 1)
+   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
+             (set (match_dup 0) (reg:HI D_REGNUM))])
+   (set (reg:HI D_REGNUM)
+       (plus (reg:HI D_REGNUM)
              (match_operand:HI 2 "general_operand" "")))
-   (parallel [(set (reg:HI 1) (match_dup 0))
-             (set (match_dup 0) (reg:HI 1))])]
+   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
+             (set (match_dup 0) (reg:HI D_REGNUM))])]
   "(INTVAL (operands[1]) & 0x0FF) == 0"
   "*
 {
 ;; (set ...) insn.
 ;;
 (define_peephole
-  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI 1))
-   (parallel [(set (reg:HI 1) (match_dup 0))
-              (set (match_dup 0) (reg:HI 1))])]
+  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
+   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
+              (set (match_dup 0) (reg:HI D_REGNUM))])]
   "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
   "*
 {
 ;; Same as above but due to some split, there may be a noop set
 ;; between the two.
 (define_peephole
-  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI 1))
+  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
    (set (match_dup 0) (match_dup 0))
-   (parallel [(set (reg:HI 1) (match_dup 0))
-              (set (match_dup 0) (reg:HI 1))])]
+   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
+              (set (match_dup 0) (reg:HI D_REGNUM))])]
   "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
   "*
 {
 ;; and we must, at least, setup X/Y with value of D.
 ;;
 (define_peephole
-  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI 1))
-   (parallel [(set (reg:HI 1) (match_dup 0))
-              (set (match_dup 0) (reg:HI 1))])]
+  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
+   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
+              (set (match_dup 0) (reg:HI D_REGNUM))])]
   ""
   "*
 {
 ;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
 ;;;
 (define_peephole
-  [(parallel [(set (reg:HI 1) (match_operand:HI 0 "hard_reg_operand" "A"))
-              (set (match_dup 0) (reg:HI 1))])
-   (set (reg:HI 1) (match_dup 0))]
+  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
+              (set (match_dup 0) (reg:HI D_REGNUM))])
+   (set (reg:HI D_REGNUM) (match_dup 0))]
   "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
   "*
 {
 ;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
 ;;;
 (define_peephole
-  [(parallel [(set (reg:HI 1) (match_operand:HI 0 "hard_reg_operand" "A"))
-              (set (match_dup 0) (reg:HI 1))])
-   (set (reg:QI 1) (match_operand:QI 1 "hard_reg_operand" "A"))]
+  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
+              (set (match_dup 0) (reg:HI D_REGNUM))])
+   (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
   "REGNO (operands[0]) == REGNO (operands[1])
    && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
   "*
 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
 ;;;
 (define_peephole
-  [(parallel [(set (reg:HI 1) (match_operand:HI 0 "hard_reg_operand" "A"))
-              (set (match_dup 0) (reg:HI 1))])
-   (set (reg:HI 1) (match_dup 0))]
+  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
+              (set (match_dup 0) (reg:HI D_REGNUM))])
+   (set (reg:HI D_REGNUM) (match_dup 0))]
   ""
   "*
 {
 ;;; with the xgdx.
 ;;;
 (define_peephole
-  [(parallel [(set (reg:HI 1) (match_operand:HI 0 "hard_reg_operand" "A"))
-              (set (match_dup 0) (reg:HI 1))])
-   (set (reg:QI 1) (match_operand:QI 1 "hard_reg_operand" "A"))]
+  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
+              (set (match_dup 0) (reg:HI D_REGNUM))])
+   (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
   "REGNO (operands[0]) == REGNO (operands[1])"
   "*
 {
 ;;; Catch two consecutive xgdx or xgdy, emit nothing.
 ;;;
 (define_peephole
-  [(parallel [(set (reg:HI 1) (match_operand:HI 0 "hard_reg_operand" "A"))
-              (set (match_dup 0) (reg:HI 1))])
-   (parallel [(set (reg:HI 1) (match_dup 0))
-              (set (match_dup 0) (reg:HI 1))])]
+  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
+              (set (match_dup 0) (reg:HI D_REGNUM))])
+   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
+              (set (match_dup 0) (reg:HI D_REGNUM))])]
   ""
   "*
 {
 ;;
 (define_peephole
   [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
-   (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI 3)))]
+   (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
   "TARGET_M6811"
   "*
 {