m68hc11.c (m68hc11_print_operand): Call m68hc11_print_operand_address.
[gcc.git] / gcc / config / m68hc11 / m68hc11.c
index 93fe2c3d9ad7dcb91dcf82663d22bb2ce92a763a..e45a74892c6471b45be515bad178c279a16e2a6e 100644 (file)
@@ -1,13 +1,13 @@
 /* Subroutines for code generation on Motorola 68HC11 and 68HC12.
 /* Subroutines for code generation on Motorola 68HC11 and 68HC12.
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+   2009, 2010 Free Software Foundation, Inc.
    Contributed by Stephane Carrez (stcarrez@nerim.fr)
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
    Contributed by Stephane Carrez (stcarrez@nerim.fr)
 
 This file is part of GCC.
 
 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)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -16,9 +16,8 @@ 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
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-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.
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.
 
 Note:
    A first 68HC11 port was made by Otto Lind (otto@coactive.com)
 
 Note:
    A first 68HC11 port was made by Otto Lind (otto@coactive.com)
@@ -40,10 +39,10 @@ Note:
 #include "tm.h"
 #include "rtl.h"
 #include "tree.h"
 #include "tm.h"
 #include "rtl.h"
 #include "tree.h"
+#include "expr.h"
 #include "tm_p.h"
 #include "regs.h"
 #include "hard-reg-set.h"
 #include "tm_p.h"
 #include "regs.h"
 #include "hard-reg-set.h"
-#include "real.h"
 #include "insn-config.h"
 #include "conditions.h"
 #include "output.h"
 #include "insn-config.h"
 #include "conditions.h"
 #include "output.h"
@@ -52,6 +51,7 @@ Note:
 #include "recog.h"
 #include "expr.h"
 #include "libfuncs.h"
 #include "recog.h"
 #include "expr.h"
 #include "libfuncs.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "basic-block.h"
 #include "function.h"
 #include "toplev.h"
 #include "basic-block.h"
 #include "function.h"
@@ -59,25 +59,30 @@ Note:
 #include "reload.h"
 #include "target.h"
 #include "target-def.h"
 #include "reload.h"
 #include "target.h"
 #include "target-def.h"
+#include "df.h"
 
 
+static void m68hc11_option_override (void);
 static void emit_move_after_reload (rtx, rtx, rtx);
 static rtx simplify_logical (enum machine_mode, int, rtx, rtx *);
 static void emit_move_after_reload (rtx, rtx, rtx);
 static rtx simplify_logical (enum machine_mode, int, rtx, rtx *);
-static void m68hc11_emit_logical (enum machine_mode, int, rtx *);
+static void m68hc11_emit_logical (enum machine_mode, enum rtx_code, rtx *);
 static void m68hc11_reorg (void);
 static void m68hc11_reorg (void);
-static int go_if_legitimate_address_internal (rtx, enum machine_mode, int);
-static int register_indirect_p (rtx, enum machine_mode, int);
+static bool m68hc11_legitimate_address_p_1 (enum machine_mode, rtx, bool);
+static bool m68hc11_legitimate_address_p (enum machine_mode, rtx, bool);
 static rtx m68hc11_expand_compare (enum rtx_code, rtx, rtx);
 static int must_parenthesize (rtx);
 static rtx m68hc11_expand_compare (enum rtx_code, rtx, rtx);
 static int must_parenthesize (rtx);
-static int m68hc11_address_cost (rtx);
+static int m68hc11_address_cost (rtx, bool);
 static int m68hc11_shift_cost (enum machine_mode, rtx, int);
 static int m68hc11_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code);
 static int m68hc11_shift_cost (enum machine_mode, rtx, int);
 static int m68hc11_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code);
-static bool m68hc11_rtx_costs (rtx, int, int, int *);
+static bool m68hc11_rtx_costs (rtx, int, int, int *, bool);
 static tree m68hc11_handle_fntype_attribute (tree *, tree, tree, int, bool *);
 static tree m68hc11_handle_fntype_attribute (tree *, tree, tree, int, bool *);
-const struct attribute_spec m68hc11_attribute_table[];
+static tree m68hc11_handle_page0_attribute (tree *, tree, tree, int, bool *);
+static bool m68hc11_class_likely_spilled_p (reg_class_t);
 
 void create_regs_rtx (void);
 
 static void asm_print_register (FILE *, int);
 
 void create_regs_rtx (void);
 
 static void asm_print_register (FILE *, int);
+static void m68hc11_print_operand (FILE *, rtx, int);
+static void m68hc11_print_operand_address (FILE *, rtx);
 static void m68hc11_output_function_epilogue (FILE *, HOST_WIDE_INT);
 static void m68hc11_asm_out_constructor (rtx, int);
 static void m68hc11_asm_out_destructor (rtx, int);
 static void m68hc11_output_function_epilogue (FILE *, HOST_WIDE_INT);
 static void m68hc11_asm_out_constructor (rtx, int);
 static void m68hc11_asm_out_destructor (rtx, int);
@@ -89,7 +94,9 @@ static int autoinc_mode (rtx);
 static int m68hc11_make_autoinc_notes (rtx *, void *);
 static void m68hc11_init_libfuncs (void);
 static rtx m68hc11_struct_value_rtx (tree, int);
 static int m68hc11_make_autoinc_notes (rtx *, void *);
 static void m68hc11_init_libfuncs (void);
 static rtx m68hc11_struct_value_rtx (tree, int);
-static bool m68hc11_return_in_memory (tree, tree);
+static bool m68hc11_return_in_memory (const_tree, const_tree);
+static bool m68hc11_can_eliminate (const int, const int);
+static void m68hc11_trampoline_init (rtx, tree, rtx);
 
 /* Must be set to 1 to produce debug messages.  */
 int debug_m6811 = 0;
 
 /* Must be set to 1 to produce debug messages.  */
 int debug_m6811 = 0;
@@ -140,19 +147,8 @@ unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER];
    This is 1 for 68HC11 and 0 for 68HC12.  */
 int m68hc11_sp_correction;
 
    This is 1 for 68HC11 and 0 for 68HC12.  */
 int m68hc11_sp_correction;
 
-#define ADDR_STRICT       0x01  /* Accept only registers in class A_REGS  */
-#define ADDR_INCDEC       0x02  /* Post/Pre inc/dec */
-#define ADDR_INDEXED      0x04  /* D-reg index */
-#define ADDR_OFFSET       0x08
-#define ADDR_INDIRECT     0x10  /* Accept (mem (mem ...)) for [n,X] */
-#define ADDR_CONST        0x20  /* Accept const and symbol_ref  */
-
 int m68hc11_addr_mode;
 int m68hc11_mov_addr_mode;
 int m68hc11_addr_mode;
 int m68hc11_mov_addr_mode;
-
-/* Comparison operands saved by the "tstxx" and "cmpxx" expand patterns.  */
-rtx m68hc11_compare_op0;
-rtx m68hc11_compare_op1;
 \f
 
 const struct processor_costs *m68hc11_cost;
 \f
 
 const struct processor_costs *m68hc11_cost;
@@ -227,6 +223,19 @@ static const struct processor_costs m6812_cost = {
   COSTS_N_INSNS (100)
 };
 \f
   COSTS_N_INSNS (100)
 };
 \f
+/* M68HC11 specific attributes.  */
+
+static const struct attribute_spec m68hc11_attribute_table[] =
+{
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+  { "interrupt", 0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
+  { "trap",      0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
+  { "far",       0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
+  { "near",      0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
+  { "page0",     0, 0, false, false, false, m68hc11_handle_page0_attribute },
+  { NULL,        0, 0, false, false, false, NULL }
+};
+\f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table
 /* Initialize the GCC target structure.  */
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table
@@ -234,6 +243,11 @@ static const struct processor_costs m6812_cost = {
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
 
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
 
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND m68hc11_print_operand
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS m68hc11_print_operand_address
+
 #undef TARGET_ASM_FUNCTION_EPILOGUE
 #define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue
 
 #undef TARGET_ASM_FUNCTION_EPILOGUE
 #define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue
 
@@ -272,10 +286,25 @@ static const struct processor_costs m6812_cost = {
 #undef TARGET_STRIP_NAME_ENCODING
 #define TARGET_STRIP_NAME_ENCODING m68hc11_strip_name_encoding
 
 #undef TARGET_STRIP_NAME_ENCODING
 #define TARGET_STRIP_NAME_ENCODING m68hc11_strip_name_encoding
 
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P    m68hc11_legitimate_address_p
+
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE m68hc11_can_eliminate
+
+#undef TARGET_CLASS_LIKELY_SPILLED_P
+#define TARGET_CLASS_LIKELY_SPILLED_P m68hc11_class_likely_spilled_p
+
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT m68hc11_trampoline_init
+
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE m68hc11_option_override
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
-int
-m68hc11_override_options (void)
+static void
+m68hc11_option_override (void)
 {
   memset (m68hc11_reg_valid_for_index, 0,
          sizeof (m68hc11_reg_valid_for_index));
 {
   memset (m68hc11_reg_valid_for_index, 0,
          sizeof (m68hc11_reg_valid_for_index));
@@ -340,7 +369,6 @@ m68hc11_override_options (void)
       if (TARGET_LONG_CALLS)
         current_function_far = 1;
     }
       if (TARGET_LONG_CALLS)
         current_function_far = 1;
     }
-  return 0;
 }
 
 
 }
 
 
@@ -390,9 +418,9 @@ create_regs_rtx (void)
 }
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
 }
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
-    - 8 bit values are stored anywhere (except the SP register).
-    - 16 bit values can be stored in any register whose mode is 16
-    - 32 bit values can be stored in D, X registers or in a soft register
+    - 8-bit values are stored anywhere (except the SP register).
+    - 16-bit values can be stored in any register whose mode is 16
+    - 32-bit values can be stored in D, X registers or in a soft register
       (except the last one because we need 2 soft registers)
     - Values whose size is > 32 bit are not stored in real hard
       registers.  They may be stored in soft registers if there are
       (except the last one because we need 2 soft registers)
     - Values whose size is > 32 bit are not stored in real hard
       registers.  They may be stored in soft registers if there are
@@ -443,7 +471,7 @@ m68hc11_hard_regno_rename_ok (int reg1, int reg2)
 }
 
 enum reg_class
 }
 
 enum reg_class
-preferred_reload_class (rtx operand, enum reg_class class)
+preferred_reload_class (rtx operand, enum reg_class rclass)
 {
   enum machine_mode mode;
 
 {
   enum machine_mode mode;
 
@@ -451,97 +479,97 @@ preferred_reload_class (rtx operand, enum reg_class class)
 
   if (debug_m6811)
     {
 
   if (debug_m6811)
     {
-      printf ("Preferred reload: (class=%s): ", reg_class_names[class]);
+      printf ("Preferred reload: (class=%s): ", reg_class_names[rclass]);
     }
 
     }
 
-  if (class == D_OR_A_OR_S_REGS && SP_REG_P (operand))
+  if (rclass == D_OR_A_OR_S_REGS && SP_REG_P (operand))
     return m68hc11_base_reg_class;
 
     return m68hc11_base_reg_class;
 
-  if (class >= S_REGS && (GET_CODE (operand) == MEM
+  if (rclass >= S_REGS && (GET_CODE (operand) == MEM
                          || GET_CODE (operand) == CONST_INT))
     {
       /* S_REGS class must not be used.  The movhi template does not
          work to move a memory to a soft register.
          Restrict to a hard reg.  */
                          || GET_CODE (operand) == CONST_INT))
     {
       /* S_REGS class must not be used.  The movhi template does not
          work to move a memory to a soft register.
          Restrict to a hard reg.  */
-      switch (class)
+      switch (rclass)
        {
        default:
        case G_REGS:
        case D_OR_A_OR_S_REGS:
        {
        default:
        case G_REGS:
        case D_OR_A_OR_S_REGS:
-         class = A_OR_D_REGS;
+         rclass = A_OR_D_REGS;
          break;
        case A_OR_S_REGS:
          break;
        case A_OR_S_REGS:
-         class = A_REGS;
+         rclass = A_REGS;
          break;
        case D_OR_SP_OR_S_REGS:
          break;
        case D_OR_SP_OR_S_REGS:
-         class = D_OR_SP_REGS;
+         rclass = D_OR_SP_REGS;
          break;
        case D_OR_Y_OR_S_REGS:
          break;
        case D_OR_Y_OR_S_REGS:
-         class = D_OR_Y_REGS;
+         rclass = D_OR_Y_REGS;
          break;
        case D_OR_X_OR_S_REGS:
          break;
        case D_OR_X_OR_S_REGS:
-         class = D_OR_X_REGS;
+         rclass = D_OR_X_REGS;
          break;
        case SP_OR_S_REGS:
          break;
        case SP_OR_S_REGS:
-         class = SP_REGS;
+         rclass = SP_REGS;
          break;
        case Y_OR_S_REGS:
          break;
        case Y_OR_S_REGS:
-         class = Y_REGS;
+         rclass = Y_REGS;
          break;
        case X_OR_S_REGS:
          break;
        case X_OR_S_REGS:
-         class = X_REGS;
+         rclass = X_REGS;
          break;
        case D_OR_S_REGS:
          break;
        case D_OR_S_REGS:
-         class = D_REGS;
+         rclass = D_REGS;
        }
     }
        }
     }
-  else if (class == Y_REGS && GET_CODE (operand) == MEM)
+  else if (rclass == Y_REGS && GET_CODE (operand) == MEM)
     {
     {
-      class = Y_REGS;
+      rclass = Y_REGS;
     }
     }
-  else if (class == A_OR_D_REGS && GET_MODE_SIZE (mode) == 4)
+  else if (rclass == A_OR_D_REGS && GET_MODE_SIZE (mode) == 4)
     {
     {
-      class = D_OR_X_REGS;
+      rclass = D_OR_X_REGS;
     }
     }
-  else if (class >= S_REGS && S_REG_P (operand))
+  else if (rclass >= S_REGS && S_REG_P (operand))
     {
     {
-      switch (class)
+      switch (rclass)
        {
        default:
        case G_REGS:
        case D_OR_A_OR_S_REGS:
        {
        default:
        case G_REGS:
        case D_OR_A_OR_S_REGS:
-         class = A_OR_D_REGS;
+         rclass = A_OR_D_REGS;
          break;
        case A_OR_S_REGS:
          break;
        case A_OR_S_REGS:
-         class = A_REGS;
+         rclass = A_REGS;
          break;
        case D_OR_SP_OR_S_REGS:
          break;
        case D_OR_SP_OR_S_REGS:
-         class = D_OR_SP_REGS;
+         rclass = D_OR_SP_REGS;
          break;
        case D_OR_Y_OR_S_REGS:
          break;
        case D_OR_Y_OR_S_REGS:
-         class = D_OR_Y_REGS;
+         rclass = D_OR_Y_REGS;
          break;
        case D_OR_X_OR_S_REGS:
          break;
        case D_OR_X_OR_S_REGS:
-         class = D_OR_X_REGS;
+         rclass = D_OR_X_REGS;
          break;
        case SP_OR_S_REGS:
          break;
        case SP_OR_S_REGS:
-         class = SP_REGS;
+         rclass = SP_REGS;
          break;
        case Y_OR_S_REGS:
          break;
        case Y_OR_S_REGS:
-         class = Y_REGS;
+         rclass = Y_REGS;
          break;
        case X_OR_S_REGS:
          break;
        case X_OR_S_REGS:
-         class = X_REGS;
+         rclass = X_REGS;
          break;
        case D_OR_S_REGS:
          break;
        case D_OR_S_REGS:
-         class = D_REGS;
+         rclass = D_REGS;
        }
     }
        }
     }
-  else if (class >= S_REGS)
+  else if (rclass >= S_REGS)
     {
       if (debug_m6811)
        {
     {
       if (debug_m6811)
        {
-         printf ("Class = %s for: ", reg_class_names[class]);
+         printf ("Class = %s for: ", reg_class_names[rclass]);
          fflush (stdout);
          debug_rtx (operand);
        }
          fflush (stdout);
          debug_rtx (operand);
        }
@@ -549,19 +577,45 @@ preferred_reload_class (rtx operand, enum reg_class class)
 
   if (debug_m6811)
     {
 
   if (debug_m6811)
     {
-      printf (" => class=%s\n", reg_class_names[class]);
+      printf (" => class=%s\n", reg_class_names[rclass]);
       fflush (stdout);
       debug_rtx (operand);
     }
 
       fflush (stdout);
       debug_rtx (operand);
     }
 
-  return class;
+  return rclass;
+}
+
+/* Implement TARGET_CLASS_LIKELY_SPILLED_P.  */
+
+static bool
+m68hc11_class_likely_spilled_p (reg_class_t rclass)
+{
+  switch (rclass)
+    {
+    case D_REGS:
+    case X_REGS:
+    case Y_REGS:
+    case A_REGS:
+    case SP_REGS:
+    case D_OR_X_REGS:
+    case D_OR_Y_REGS:
+    case X_OR_SP_REGS:
+    case Y_OR_SP_REGS:
+    case D_OR_SP_REGS:
+      return true;
+
+    default:
+      break;
+    }
+
+  return false;
 }
 
 /* Return 1 if the operand is a valid indexed addressing mode.
    For 68hc11:  n,r    with n in [0..255] and r in A_REGS class
    For 68hc12:  n,r    no constraint on the constant, r in A_REGS class.  */
 }
 
 /* Return 1 if the operand is a valid indexed addressing mode.
    For 68hc11:  n,r    with n in [0..255] and r in A_REGS class
    For 68hc12:  n,r    no constraint on the constant, r in A_REGS class.  */
-static int
-register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode)
+int
+m68hc11_valid_addressing_p (rtx operand, enum machine_mode mode, int addr_mode)
 {
   rtx base, offset;
 
 {
   rtx base, offset;
 
@@ -569,8 +623,8 @@ register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode)
     {
     case MEM:
       if ((addr_mode & ADDR_INDIRECT) && GET_MODE_SIZE (mode) <= 2)
     {
     case MEM:
       if ((addr_mode & ADDR_INDIRECT) && GET_MODE_SIZE (mode) <= 2)
-        return register_indirect_p (XEXP (operand, 0), mode,
-                                    addr_mode & (ADDR_STRICT | ADDR_OFFSET));
+        return m68hc11_valid_addressing_p (XEXP (operand, 0), mode,
+                                   addr_mode & (ADDR_STRICT | ADDR_OFFSET));
       return 0;
 
     case POST_INC:
       return 0;
 
     case POST_INC:
@@ -578,8 +632,8 @@ register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode)
     case POST_DEC:
     case PRE_DEC:
       if (addr_mode & ADDR_INCDEC)
     case POST_DEC:
     case PRE_DEC:
       if (addr_mode & ADDR_INCDEC)
-       return register_indirect_p (XEXP (operand, 0), mode,
-                                    addr_mode & ADDR_STRICT);
+       return m68hc11_valid_addressing_p (XEXP (operand, 0), mode,
+                                   addr_mode & ADDR_STRICT);
       return 0;
 
     case PLUS:
       return 0;
 
     case PLUS:
@@ -661,7 +715,7 @@ m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode)
       && reg_equiv_memory_loc[REGNO (operand)])
     {
       operand = reg_equiv_memory_loc[REGNO (operand)];
       && reg_equiv_memory_loc[REGNO (operand)])
     {
       operand = reg_equiv_memory_loc[REGNO (operand)];
-      operand = eliminate_regs (operand, 0, NULL_RTX);
+      operand = eliminate_regs (operand, VOIDmode, NULL_RTX);
     }
 
   if (GET_CODE (operand) != MEM)
     }
 
   if (GET_CODE (operand) != MEM)
@@ -675,7 +729,7 @@ m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode)
     return 1;
 
   addr_mode = m68hc11_mov_addr_mode | (reload_completed ? ADDR_STRICT : 0);
     return 1;
 
   addr_mode = m68hc11_mov_addr_mode | (reload_completed ? ADDR_STRICT : 0);
-  if (!register_indirect_p (operand, mode, addr_mode))
+  if (!m68hc11_valid_addressing_p (operand, mode, addr_mode))
     return 0;
 
   if (TARGET_M6812 && GET_CODE (operand) == PLUS
     return 0;
 
   if (TARGET_M6812 && GET_CODE (operand) == PLUS
@@ -723,19 +777,19 @@ m68hc11_register_indirect_p (rtx operand, enum machine_mode mode)
       && reg_equiv_memory_loc[REGNO (operand)])
     {
       operand = reg_equiv_memory_loc[REGNO (operand)];
       && reg_equiv_memory_loc[REGNO (operand)])
     {
       operand = reg_equiv_memory_loc[REGNO (operand)];
-      operand = eliminate_regs (operand, 0, NULL_RTX);
+      operand = eliminate_regs (operand, VOIDmode, NULL_RTX);
     }
   if (GET_CODE (operand) != MEM)
     return 0;
 
   operand = XEXP (operand, 0);
   addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
     }
   if (GET_CODE (operand) != MEM)
     return 0;
 
   operand = XEXP (operand, 0);
   addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
-  return register_indirect_p (operand, mode, addr_mode);
+  return m68hc11_valid_addressing_p (operand, mode, addr_mode);
 }
 
 }
 
-static int
-go_if_legitimate_address_internal (rtx operand, enum machine_mode mode,
-                                   int strict)
+static bool
+m68hc11_legitimate_address_p_1  (enum machine_mode mode, rtx operand,
+                                 bool strict)
 {
   int addr_mode;
 
 {
   int addr_mode;
 
@@ -749,7 +803,7 @@ go_if_legitimate_address_internal (rtx operand, enum machine_mode mode,
       return 1;
     }
   addr_mode = m68hc11_addr_mode | (strict ? ADDR_STRICT : 0);
       return 1;
     }
   addr_mode = m68hc11_addr_mode | (strict ? ADDR_STRICT : 0);
-  if (register_indirect_p (operand, mode, addr_mode))
+  if (m68hc11_valid_addressing_p (operand, mode, addr_mode))
     {
       return 1;
     }
     {
       return 1;
     }
@@ -764,9 +818,9 @@ go_if_legitimate_address_internal (rtx operand, enum machine_mode mode,
   return 0;
 }
 
   return 0;
 }
 
-int
-m68hc11_go_if_legitimate_address (rtx operand, enum machine_mode mode,
-                                  int strict)
+bool
+m68hc11_legitimate_address_p (enum machine_mode mode, rtx operand,
+                              bool strict)
 {
   int result;
 
 {
   int result;
 
@@ -777,7 +831,7 @@ m68hc11_go_if_legitimate_address (rtx operand, enum machine_mode mode,
       debug_rtx (operand);
     }
 
       debug_rtx (operand);
     }
 
-  result = go_if_legitimate_address_internal (operand, mode, strict);
+  result = m68hc11_legitimate_address_p_1 (mode, operand, strict);
 
   if (debug_m6811)
     {
 
   if (debug_m6811)
     {
@@ -797,14 +851,6 @@ m68hc11_go_if_legitimate_address (rtx operand, enum machine_mode mode,
   return result;
 }
 
   return result;
 }
 
-int
-m68hc11_legitimize_address (rtx *operand ATTRIBUTE_UNUSED,
-                            rtx old_operand ATTRIBUTE_UNUSED,
-                            enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return 0;
-}
-
 
 int
 m68hc11_reload_operands (rtx operands[])
 
 int
 m68hc11_reload_operands (rtx operands[])
@@ -830,7 +876,7 @@ m68hc11_reload_operands (rtx operands[])
        }
 
       /* If the offset is out of range, we have to compute the address
        }
 
       /* If the offset is out of range, we have to compute the address
-         with a separate add instruction.  We try to do with with an 8-bit
+         with a separate add instruction.  We try to do this with an 8-bit
          add on the A register.  This is possible only if the lowest part
          of the offset (i.e., big_offset % 256) is a valid constant offset
          with respect to the mode.  If it's not, we have to generate a
          add on the A register.  This is possible only if the lowest part
          of the offset (i.e., big_offset % 256) is a valid constant offset
          with respect to the mode.  If it's not, we have to generate a
@@ -930,7 +976,7 @@ m68hc11_emit_libcall (const char *name, enum rtx_code code,
       break;
 
     default:
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   insns = get_insns ();
     }
 
   insns = get_insns ();
@@ -995,7 +1041,7 @@ m68hc11_indirect_p (rtx operand, enum machine_mode mode)
 
       operand = XEXP (operand, 0);
       addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
 
       operand = XEXP (operand, 0);
       addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
-      return register_indirect_p (operand, mode, addr_mode);
+      return m68hc11_valid_addressing_p (operand, mode, addr_mode);
     }
   return 0;
 }
     }
   return 0;
 }
@@ -1070,39 +1116,49 @@ symbolic_memory_operand (rtx op, enum machine_mode mode)
    jmp FNADDR
 
 */
    jmp FNADDR
 
 */
-void
-m68hc11_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
+static void
+m68hc11_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
 {
   const char *static_chain_reg = reg_names[STATIC_CHAIN_REGNUM];
 {
   const char *static_chain_reg = reg_names[STATIC_CHAIN_REGNUM];
+  rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
+  rtx mem;
 
   /* Skip the '*'.  */
   if (*static_chain_reg == '*')
     static_chain_reg++;
   if (TARGET_M6811)
     {
 
   /* Skip the '*'.  */
   if (*static_chain_reg == '*')
     static_chain_reg++;
   if (TARGET_M6811)
     {
-      emit_move_insn (gen_rtx_MEM (HImode, tramp), GEN_INT (0x18ce));
-      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 2)), cxt);
-      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 4)),
-                      GEN_INT (0x18df));
-      emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 6)),
+      mem = adjust_address (m_tramp, HImode, 0);
+      emit_move_insn (mem, GEN_INT (0x18ce));
+      mem = adjust_address (m_tramp, HImode, 2);
+      emit_move_insn (mem, cxt);
+      mem = adjust_address (m_tramp, HImode, 4);
+      emit_move_insn (mem, GEN_INT (0x18df));
+      mem = adjust_address (m_tramp, QImode, 6);
+      emit_move_insn (mem,
                       gen_rtx_CONST (QImode,
                                      gen_rtx_SYMBOL_REF (Pmode,
                                                          static_chain_reg)));
                       gen_rtx_CONST (QImode,
                                      gen_rtx_SYMBOL_REF (Pmode,
                                                          static_chain_reg)));
-      emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 7)),
-                      GEN_INT (0x7e));
-      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 8)), fnaddr);
+      mem = adjust_address (m_tramp, QImode, 7);
+      emit_move_insn (mem, GEN_INT (0x7e));
+      mem = adjust_address (m_tramp, HImode, 8);
+      emit_move_insn (mem, fnaddr);
     }
   else
     {
     }
   else
     {
-      emit_move_insn (gen_rtx_MEM (HImode, tramp), GEN_INT (0x1803));
-      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 2)), cxt);
-      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 4)),
+      mem = adjust_address (m_tramp, HImode, 0);
+      emit_move_insn (mem, GEN_INT (0x1803));
+      mem = adjust_address (m_tramp, HImode, 2);
+      emit_move_insn (mem, cxt);
+      mem = adjust_address (m_tramp, HImode, 4);
+      emit_move_insn (mem,
                       gen_rtx_CONST (HImode,
                                      gen_rtx_SYMBOL_REF (Pmode,
                                                          static_chain_reg)));
                       gen_rtx_CONST (HImode,
                                      gen_rtx_SYMBOL_REF (Pmode,
                                                          static_chain_reg)));
-      emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 6)),
-                      GEN_INT (0x06));
-      emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 7)), fnaddr);
+      mem = adjust_address (m_tramp, QImode, 6);
+      emit_move_insn (mem, GEN_INT (0x06));
+      mem = adjust_address (m_tramp, HImode, 7);
+      emit_move_insn (mem, fnaddr);
     }
 }
 \f
     }
 }
 \f
@@ -1123,24 +1179,14 @@ m68hc11_handle_page0_attribute (tree *node, tree name,
     }
   else
     {
     }
   else
     {
-      warning (0, "%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored",
+              name);
       *no_add_attrs = true;
     }
 
   return NULL_TREE;
 }
 
       *no_add_attrs = true;
     }
 
   return NULL_TREE;
 }
 
-const struct attribute_spec m68hc11_attribute_table[] =
-{
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-  { "interrupt", 0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
-  { "trap",      0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
-  { "far",       0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
-  { "near",      0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
-  { "page0",     0, 0, false, false, false, m68hc11_handle_page0_attribute },
-  { NULL,        0, 0, false, false, false, NULL }
-};
-
 /* Keep track of the symbol which has a `trap' attribute and which uses
    the `swi' calling convention.  Since there is only one trap, we only
    record one such symbol.  If there are several, a warning is reported.  */
 /* Keep track of the symbol which has a `trap' attribute and which uses
    the `swi' calling convention.  Since there is only one trap, we only
    record one such symbol.  If there are several, a warning is reported.  */
@@ -1159,8 +1205,8 @@ m68hc11_handle_fntype_attribute (tree *node, tree name,
       && TREE_CODE (*node) != FIELD_DECL
       && TREE_CODE (*node) != TYPE_DECL)
     {
       && TREE_CODE (*node) != FIELD_DECL
       && TREE_CODE (*node) != TYPE_DECL)
     {
-      warning (0, "%qs attribute only applies to functions",
-              IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute only applies to functions",
+              name);
       *no_add_attrs = true;
     }
 
       *no_add_attrs = true;
     }
 
@@ -1179,7 +1225,7 @@ m68hc11_encode_label (tree decl)
 {
   const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
   int len = strlen (str);
 {
   const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
   int len = strlen (str);
-  char *newstr = alloca (len + 2);
+  char *newstr = XALLOCAVEC (char, len + 2);
 
   newstr[0] = '@';
   strcpy (&newstr[1], str);
 
   newstr[0] = '@';
   strcpy (&newstr[1], str);
@@ -1244,13 +1290,14 @@ m68hc11_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
   trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
   if (trap_handler && is_far)
     {
   trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
   if (trap_handler && is_far)
     {
-      warning (0, "%<trap%> and %<far%> attributes are not compatible, ignoring %<far%>");
+      warning (OPT_Wattributes, "%<trap%> and %<far%> attributes are "
+              "not compatible, ignoring %<far%>");
       trap_handler = 0;
     }
   if (trap_handler)
     {
       if (trap_handler_symbol != 0)
       trap_handler = 0;
     }
   if (trap_handler)
     {
       if (trap_handler_symbol != 0)
-        warning (0, "%<trap%> attribute is already used");
+        warning (OPT_Wattributes, "%<trap%> attribute is already used");
       else
         trap_handler_symbol = XEXP (rtl, 0);
     }
       else
         trap_handler_symbol = XEXP (rtl, 0);
     }
@@ -1291,6 +1338,19 @@ m68hc11_is_trap_symbol (rtx sym)
 
 /* Argument support functions.  */
 
 
 /* Argument support functions.  */
 
+/* Given FROM and TO register numbers, say whether this elimination is
+   allowed. Frame pointer elimination is automatically handled.
+
+   All other eliminations are valid.  */
+
+bool
+m68hc11_can_eliminate (const int from, const int to)
+{
+  return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
+          ? ! frame_pointer_needed
+          : true);
+}
+
 /* Define the offset between two registers, one to be eliminated, and the
    other its replacement, at the start of a routine.  */
 int
 /* Define the offset between two registers, one to be eliminated, and the
    other its replacement, at the start of a routine.  */
 int
@@ -1342,7 +1402,7 @@ m68hc11_initial_elimination_offset (int from, int to)
   /* Push any 2 byte pseudo hard registers that we need to save.  */
   for (regno = SOFT_REG_FIRST; regno < SOFT_REG_LAST; regno++)
     {
   /* Push any 2 byte pseudo hard registers that we need to save.  */
   for (regno = SOFT_REG_FIRST; regno < SOFT_REG_LAST; regno++)
     {
-      if (regs_ever_live[regno] && !call_used_regs[regno])
+      if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
        {
          size += 2;
        }
        {
          size += 2;
        }
@@ -1484,8 +1544,8 @@ m68hc11_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
    `downward' to pad below, or `none' to inhibit padding.
 
    Structures are stored left shifted in their argument slot.  */
    `downward' to pad below, or `none' to inhibit padding.
 
    Structures are stored left shifted in their argument slot.  */
-int
-m68hc11_function_arg_padding (enum machine_mode mode, tree type)
+enum direction
+m68hc11_function_arg_padding (enum machine_mode mode, const_tree type)
 {
   if (type != 0 && AGGREGATE_TYPE_P (type))
     return upward;
 {
   if (type != 0 && AGGREGATE_TYPE_P (type))
     return upward;
@@ -1517,28 +1577,16 @@ emit_move_after_reload (rtx to, rtx from, rtx scratch)
   /* Put a REG_INC note to tell the flow analysis that the instruction
      is necessary.  */
   if (IS_STACK_PUSH (to))
   /* Put a REG_INC note to tell the flow analysis that the instruction
      is necessary.  */
   if (IS_STACK_PUSH (to))
-    {
-      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,
-                                           XEXP (XEXP (to, 0), 0),
-                                           REG_NOTES (insn));
-    }
+    add_reg_note (insn, REG_INC, XEXP (XEXP (to, 0), 0));
   else if (IS_STACK_POP (from))
   else if (IS_STACK_POP (from))
-    {
-      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,
-                                           XEXP (XEXP (from, 0), 0),
-                                           REG_NOTES (insn));
-    }
+    add_reg_note (insn, REG_INC, XEXP (XEXP (from, 0), 0));
 
   /* For 68HC11, put a REG_INC note on `sts _.frame' to prevent the cse-reg
      to think that sp == _.frame and later replace a x = sp with x = _.frame.
      The problem is that we are lying to gcc and use `txs' for x = sp
      (which is not really true because txs is really x = sp + 1).  */
   else if (TARGET_M6811 && SP_REG_P (from))
 
   /* For 68HC11, put a REG_INC note on `sts _.frame' to prevent the cse-reg
      to think that sp == _.frame and later replace a x = sp with x = _.frame.
      The problem is that we are lying to gcc and use `txs' for x = sp
      (which is not really true because txs is really x = sp + 1).  */
   else if (TARGET_M6811 && SP_REG_P (from))
-    {
-      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,
-                                           from,
-                                           REG_NOTES (insn));
-    }
+    add_reg_note (insn, REG_INC, from);
 }
 
 int
 }
 
 int
@@ -1556,7 +1604,7 @@ m68hc11_total_frame_size (void)
     size += HARD_REG_SIZE;
 
   for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)
     size += HARD_REG_SIZE;
 
   for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)
-    if (regs_ever_live[regno] && !call_used_regs[regno])
+    if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
       size += HARD_REG_SIZE;
 
   return size;
       size += HARD_REG_SIZE;
 
   return size;
@@ -1579,8 +1627,7 @@ expand_prologue (void)
   int regno;
   rtx scratch;
 
   int regno;
   rtx scratch;
 
-  if (reload_completed != 1)
-    abort ();
+  gcc_assert (reload_completed == 1);
 
   size = get_frame_size ();
 
 
   size = get_frame_size ();
 
@@ -1604,7 +1651,7 @@ expand_prologue (void)
      If the first argument is a 32-bit quantity, the D+X registers
      are used.  Use Y to compute the frame.  Otherwise, X is cheaper.
      For 68HC12, this scratch register is not used.  */
      If the first argument is a 32-bit quantity, the D+X registers
      are used.  Use Y to compute the frame.  Otherwise, X is cheaper.
      For 68HC12, this scratch register is not used.  */
-  if (current_function_args_info.nregs == 2)
+  if (crtl->args.info.nregs == 2)
     scratch = iy_reg;
   else
     scratch = ix_reg;
     scratch = iy_reg;
   else
     scratch = ix_reg;
@@ -1669,7 +1716,7 @@ expand_prologue (void)
   /* Push any 2 byte pseudo hard registers that we need to save.  */
   for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)
     {
   /* Push any 2 byte pseudo hard registers that we need to save.  */
   for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)
     {
-      if (regs_ever_live[regno] && !call_used_regs[regno])
+      if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
        {
          emit_move_after_reload (stack_push_word,
                                  gen_rtx_REG (HImode, regno), scratch);
        {
          emit_move_after_reload (stack_push_word,
                                  gen_rtx_REG (HImode, regno), scratch);
@@ -1685,20 +1732,19 @@ expand_epilogue (void)
   int return_size;
   rtx scratch;
 
   int return_size;
   rtx scratch;
 
-  if (reload_completed != 1)
-    abort ();
+  gcc_assert (reload_completed == 1);
 
   size = get_frame_size ();
 
   /* If we are returning a value in two registers, we have to preserve the
      X register and use the Y register to restore the stack and the saved
      registers.  Otherwise, use X because it's faster (and smaller).  */
 
   size = get_frame_size ();
 
   /* If we are returning a value in two registers, we have to preserve the
      X register and use the Y register to restore the stack and the saved
      registers.  Otherwise, use X because it's faster (and smaller).  */
-  if (current_function_return_rtx == 0)
+  if (crtl->return_rtx == 0)
     return_size = 0;
     return_size = 0;
-  else if (GET_CODE (current_function_return_rtx) == MEM)
+  else if (GET_CODE (crtl->return_rtx) == MEM)
     return_size = HARD_REG_SIZE;
   else
     return_size = HARD_REG_SIZE;
   else
-    return_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
+    return_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
 
   if (return_size > HARD_REG_SIZE && return_size <= 2 * HARD_REG_SIZE)
     scratch = iy_reg;
 
   if (return_size > HARD_REG_SIZE && return_size <= 2 * HARD_REG_SIZE)
     scratch = iy_reg;
@@ -1708,7 +1754,7 @@ expand_epilogue (void)
   /* Pop any 2 byte pseudo hard registers that we saved.  */
   for (regno = SOFT_REG_LAST; regno >= SOFT_REG_FIRST; regno--)
     {
   /* Pop any 2 byte pseudo hard registers that we saved.  */
   for (regno = SOFT_REG_LAST; regno >= SOFT_REG_FIRST; regno--)
     {
-      if (regs_ever_live[regno] && !call_used_regs[regno])
+      if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
        {
          emit_move_after_reload (gen_rtx_REG (HImode, regno),
                                  stack_pop_word, scratch);
        {
          emit_move_after_reload (gen_rtx_REG (HImode, regno),
                                  stack_pop_word, scratch);
@@ -1834,12 +1880,16 @@ m68hc11_gen_lowpart (enum machine_mode mode, rtx x)
        {
          l[0] = CONST_DOUBLE_LOW (x);
        }
        {
          l[0] = CONST_DOUBLE_LOW (x);
        }
-      if (mode == SImode)
-       return GEN_INT (l[0]);
-      else if (mode == HImode && GET_MODE (x) == SFmode)
-       return gen_int_mode (l[0], HImode);
-      else
-       abort ();
+      switch (mode)
+       {
+       case SImode:
+         return GEN_INT (l[0]);
+       case HImode:
+         gcc_assert (GET_MODE (x) == SFmode);
+         return gen_int_mode (l[0], HImode);
+       default:
+         gcc_unreachable ();
+       }
     }
 
   if (mode == QImode && D_REG_P (x))
     }
 
   if (mode == QImode && D_REG_P (x))
@@ -1848,12 +1898,15 @@ m68hc11_gen_lowpart (enum machine_mode mode, rtx x)
   /* gen_lowpart crashes when it is called with a SUBREG.  */
   if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)
     {
   /* gen_lowpart crashes when it is called with a SUBREG.  */
   if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)
     {
-      if (mode == SImode)
-       return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 4);
-      else if (mode == HImode)
-       return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 2);
-      else
-       abort ();
+      switch (mode)
+       {
+       case SImode:
+         return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 4);
+       case HImode:
+         return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 2);
+       default:
+         gcc_unreachable ();
+       }
     }
   x = gen_lowpart (mode, x);
 
     }
   x = gen_lowpart (mode, x);
 
@@ -1910,12 +1963,16 @@ m68hc11_gen_highpart (enum machine_mode mode, rtx x)
          l[1] = CONST_DOUBLE_HIGH (x);
        }
 
          l[1] = CONST_DOUBLE_HIGH (x);
        }
 
-      if (mode == SImode)
-       return GEN_INT (l[1]);
-      else if (mode == HImode && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
-       return gen_int_mode ((l[0] >> 16), HImode);
-      else
-       abort ();
+      switch (mode)
+       {
+       case SImode:
+         return GEN_INT (l[1]);
+       case HImode:
+         gcc_assert (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT);
+         return gen_int_mode ((l[0] >> 16), HImode);
+       default:
+         gcc_unreachable ();
+       }
     }
   if (GET_CODE (x) == CONST_INT)
     {
     }
   if (GET_CODE (x) == CONST_INT)
     {
@@ -1954,20 +2011,16 @@ m68hc11_gen_highpart (enum machine_mode mode, rtx x)
     }
 
   /* gen_highpart crashes when it is called with a SUBREG.  */
     }
 
   /* gen_highpart crashes when it is called with a SUBREG.  */
-  if (GET_CODE (x) == SUBREG)
-    {
-      return gen_rtx_SUBREG (mode, XEXP (x, 0), XEXP (x, 1));
-    }
-  if (GET_CODE (x) == REG)
+  switch (GET_CODE (x))
     {
     {
+    case SUBREG:
+      return gen_rtx_SUBREG (mode, XEXP (x, 0), XINT (x, 1));
+    case REG:
       if (REGNO (x) < FIRST_PSEUDO_REGISTER)
         return gen_rtx_REG (mode, REGNO (x));
       else
         return gen_rtx_SUBREG (mode, x, 0);
       if (REGNO (x) < FIRST_PSEUDO_REGISTER)
         return gen_rtx_REG (mode, REGNO (x));
       else
         return gen_rtx_SUBREG (mode, x, 0);
-    }
-
-  if (GET_CODE (x) == MEM)
-    {
+    case MEM:
       x = change_address (x, mode, 0);
 
       /* Return a different rtx to avoid to share it in several insns
       x = change_address (x, mode, 0);
 
       /* Return a different rtx to avoid to share it in several insns
@@ -1976,8 +2029,10 @@ m68hc11_gen_highpart (enum machine_mode mode, rtx x)
       if (GET_CODE (x) == MEM)
        x = copy_rtx (x);
       return x;
       if (GET_CODE (x) == MEM)
        x = copy_rtx (x);
       return x;
+
+    default:
+      gcc_unreachable ();
     }
     }
-  abort ();
 }
 \f
 
 }
 \f
 
@@ -2109,8 +2164,8 @@ asm_print_register (FILE *file, int regno)
    'T' generate the low-part temporary scratch register.  The operand is
        ignored.  */
 
    'T' generate the low-part temporary scratch register.  The operand is
        ignored.  */
 
-void
-print_operand (FILE *file, rtx op, int letter)
+static void
+m68hc11_print_operand (FILE *file, rtx op, int letter)
 {
   if (letter == 't')
     {
 {
   if (letter == 't')
     {
@@ -2178,56 +2233,36 @@ print_operand (FILE *file, rtx op, int letter)
       switch (GET_CODE (base))
        {
        case PRE_DEC:
       switch (GET_CODE (base))
        {
        case PRE_DEC:
-         if (TARGET_M6812)
-           {
-             fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (op)));
-             asm_print_register (file, REGNO (XEXP (base, 0)));
-           }
-         else
-           abort ();
+         gcc_assert (TARGET_M6812);
+         fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (op)));
+         asm_print_register (file, REGNO (XEXP (base, 0)));
          break;
 
        case POST_DEC:
          break;
 
        case POST_DEC:
-         if (TARGET_M6812)
-           {
-             fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));
-             asm_print_register (file, REGNO (XEXP (base, 0)));
-             fprintf (file, "-");
-           }
-         else
-           abort ();
+         gcc_assert (TARGET_M6812);
+         fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));
+         asm_print_register (file, REGNO (XEXP (base, 0)));
+         fprintf (file, "-");
          break;
 
        case POST_INC:
          break;
 
        case POST_INC:
-         if (TARGET_M6812)
-           {
-             fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));
-             asm_print_register (file, REGNO (XEXP (base, 0)));
-             fprintf (file, "+");
-           }
-         else
-           abort ();
+         gcc_assert (TARGET_M6812);
+         fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));
+         asm_print_register (file, REGNO (XEXP (base, 0)));
+         fprintf (file, "+");
          break;
 
        case PRE_INC:
          break;
 
        case PRE_INC:
-         if (TARGET_M6812)
-           {
-             fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (op)));
-             asm_print_register (file, REGNO (XEXP (base, 0)));
-           }
-         else
-           abort ();
+         gcc_assert (TARGET_M6812);
+         fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (op)));
+         asm_print_register (file, REGNO (XEXP (base, 0)));
          break;
 
         case MEM:
          break;
 
         case MEM:
-          if (TARGET_M6812)
-            {
-              fprintf (file, "[");
-              print_operand_address (file, XEXP (base, 0));
-              fprintf (file, "]");
-            }
-          else
-            abort ();
+          gcc_assert (TARGET_M6812);
+         fprintf (file, "[");
+         m68hc11_print_operand_address (file, XEXP (base, 0));
+         fprintf (file, "]");
           break;
 
        default:
           break;
 
        default:
@@ -2322,8 +2357,8 @@ must_parenthesize (rtx op)
    assembler syntax for an instruction operand that is a memory
    reference whose address is ADDR.  ADDR is an RTL expression.  */
 
    assembler syntax for an instruction operand that is a memory
    reference whose address is ADDR.  ADDR is an RTL expression.  */
 
-void
-print_operand_address (FILE *file, rtx addr)
+static void
+m68hc11_print_operand_address (FILE *file, rtx addr)
 {
   rtx base;
   rtx offset;
 {
   rtx base;
   rtx offset;
@@ -2332,8 +2367,7 @@ print_operand_address (FILE *file, rtx addr)
   switch (GET_CODE (addr))
     {
     case REG:
   switch (GET_CODE (addr))
     {
     case REG:
-      if (!REG_P (addr) || !REG_OK_FOR_BASE_STRICT_P (addr))
-       abort ();
+      gcc_assert (REG_P (addr) && REG_OK_FOR_BASE_STRICT_P (addr));
 
       fprintf (file, "0,");
       asm_print_register (file, REGNO (addr));
 
       fprintf (file, "0,");
       asm_print_register (file, REGNO (addr));
@@ -2344,45 +2378,29 @@ print_operand_address (FILE *file, rtx addr)
       switch (GET_CODE (base))
        {
        case PRE_DEC:
       switch (GET_CODE (base))
        {
        case PRE_DEC:
-         if (TARGET_M6812)
-           {
-             fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (addr)));
-             asm_print_register (file, REGNO (XEXP (base, 0)));
-           }
-         else
-           abort ();
+         gcc_assert (TARGET_M6812);
+         fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (addr)));
+         asm_print_register (file, REGNO (XEXP (base, 0)));
          break;
 
        case POST_DEC:
          break;
 
        case POST_DEC:
-         if (TARGET_M6812)
-           {
-             fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));
-             asm_print_register (file, REGNO (XEXP (base, 0)));
-             fprintf (file, "-");
-           }
-         else
-           abort ();
+         gcc_assert (TARGET_M6812);
+         fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));
+         asm_print_register (file, REGNO (XEXP (base, 0)));
+         fprintf (file, "-");
          break;
 
        case POST_INC:
          break;
 
        case POST_INC:
-         if (TARGET_M6812)
-           {
-             fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));
-             asm_print_register (file, REGNO (XEXP (base, 0)));
-             fprintf (file, "+");
-           }
-         else
-           abort ();
+         gcc_assert (TARGET_M6812);
+         fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));
+         asm_print_register (file, REGNO (XEXP (base, 0)));
+         fprintf (file, "+");
          break;
 
        case PRE_INC:
          break;
 
        case PRE_INC:
-         if (TARGET_M6812)
-           {
-             fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (addr)));
-             asm_print_register (file, REGNO (XEXP (base, 0)));
-           }
-         else
-           abort ();
+         gcc_assert (TARGET_M6812);
+         fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (addr)));
+         asm_print_register (file, REGNO (XEXP (base, 0)));
          break;
 
        default:
          break;
 
        default:
@@ -2405,10 +2423,11 @@ print_operand_address (FILE *file, rtx addr)
          base = XEXP (addr, 1);
          offset = XEXP (addr, 0);
        }
          base = XEXP (addr, 1);
          offset = XEXP (addr, 0);
        }
-      if ((CONSTANT_ADDRESS_P (base)) && (CONSTANT_ADDRESS_P (offset)))
+      if (CONSTANT_ADDRESS_P (base))
        {
          need_parenthesis = must_parenthesize (addr);
 
        {
          need_parenthesis = must_parenthesize (addr);
 
+         gcc_assert (CONSTANT_ADDRESS_P (offset));
          if (need_parenthesis)
            fprintf (file, "(");
 
          if (need_parenthesis)
            fprintf (file, "(");
 
@@ -2418,18 +2437,15 @@ print_operand_address (FILE *file, rtx addr)
          if (need_parenthesis)
            fprintf (file, ")");
        }
          if (need_parenthesis)
            fprintf (file, ")");
        }
-      else if (REG_P (base) && REG_OK_FOR_BASE_STRICT_P (base))
+      else
        {
        {
+         gcc_assert (REG_P (base) && REG_OK_FOR_BASE_STRICT_P (base));
          if (REG_P (offset))
            {
          if (REG_P (offset))
            {
-             if (TARGET_M6812)
-               {
-                 asm_print_register (file, REGNO (offset));
-                 fprintf (file, ",");
-                 asm_print_register (file, REGNO (base));
-               }
-             else
-               abort ();
+             gcc_assert (TARGET_M6812);
+             asm_print_register (file, REGNO (offset));
+             fprintf (file, ",");
+             asm_print_register (file, REGNO (base));
            }
          else
            {
            }
          else
            {
@@ -2444,10 +2460,6 @@ print_operand_address (FILE *file, rtx addr)
              asm_print_register (file, REGNO (base));
            }
        }
              asm_print_register (file, REGNO (base));
            }
        }
-      else
-       {
-         abort ();
-       }
       break;
 
     default:
       break;
 
     default:
@@ -2478,14 +2490,10 @@ m68hc11_expand_compare (enum rtx_code code, rtx op0, rtx op1)
 {
   rtx ret = 0;
 
 {
   rtx ret = 0;
 
-  if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
-    abort ();
-  else
-    {
-      emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
-                             gen_rtx_COMPARE (VOIDmode, op0, op1)));
-      ret = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
-    }
+  gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) != MODE_FLOAT);
+  emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
+                         gen_rtx_COMPARE (VOIDmode, op0, op1)));
+  ret = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
 
   return ret;
 }
 
   return ret;
 }
@@ -2613,7 +2621,7 @@ m68hc11_expand_compare_and_branch (enum rtx_code code, rtx op0, rtx op1,
            break;
 
          default:
            break;
 
          default:
-           abort ();
+           gcc_unreachable ();
          }
 
        /*
          }
 
        /*
@@ -2636,7 +2644,7 @@ m68hc11_expand_compare_and_branch (enum rtx_code code, rtx op0, rtx op1,
       }
 
     default:
       }
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
   return 0;
 }
     }
   return 0;
 }
@@ -2922,7 +2930,7 @@ simplify_logical (enum machine_mode mode, int code, rtx operand, rtx *result)
 }
 
 static void
 }
 
 static void
-m68hc11_emit_logical (enum machine_mode mode, int code, rtx *operands)
+m68hc11_emit_logical (enum machine_mode mode, enum rtx_code code, rtx *operands)
 {
   rtx result;
   int need_copy;
 {
   rtx result;
   int need_copy;
@@ -2992,7 +3000,8 @@ m68hc11_emit_logical (enum machine_mode mode, int code, rtx *operands)
 }
 
 void
 }
 
 void
-m68hc11_split_logical (enum machine_mode mode, int code, rtx *operands)
+m68hc11_split_logical (enum machine_mode mode, enum rtx_code code,
+                      rtx *operands)
 {
   rtx low[4];
   rtx high[4];
 {
   rtx low[4];
   rtx high[4];
@@ -3110,10 +3119,13 @@ m68hc11_gen_movhi (rtx insn, rtx *operands)
 
   if (TARGET_M6812)
     {
 
   if (TARGET_M6812)
     {
-      if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1]))
+      rtx from = operands[1];
+      rtx to = operands[0];
+
+      if (IS_STACK_PUSH (to) && H_REG_P (from))
        {
           cc_status = cc_prev_status;
        {
           cc_status = cc_prev_status;
-         switch (REGNO (operands[1]))
+         switch (REGNO (from))
            {
            case HARD_X_REGNUM:
            case HARD_Y_REGNUM:
            {
            case HARD_X_REGNUM:
            case HARD_Y_REGNUM:
@@ -3124,14 +3136,14 @@ m68hc11_gen_movhi (rtx insn, rtx *operands)
               output_asm_insn ("sts\t2,-sp", operands);
               break;
            default:
               output_asm_insn ("sts\t2,-sp", operands);
               break;
            default:
-             abort ();
+             gcc_unreachable ();
            }
          return;
        }
            }
          return;
        }
-      if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0]))
+      if (IS_STACK_POP (from) && H_REG_P (to))
        {
           cc_status = cc_prev_status;
        {
           cc_status = cc_prev_status;
-         switch (REGNO (operands[0]))
+         switch (REGNO (to))
            {
            case HARD_X_REGNUM:
            case HARD_Y_REGNUM:
            {
            case HARD_X_REGNUM:
            case HARD_Y_REGNUM:
@@ -3139,7 +3151,7 @@ m68hc11_gen_movhi (rtx insn, rtx *operands)
              output_asm_insn ("pul%0", operands);
              break;
            default:
              output_asm_insn ("pul%0", operands);
              break;
            default:
-             abort ();
+             gcc_unreachable ();
            }
          return;
        }
            }
          return;
        }
@@ -3162,11 +3174,52 @@ m68hc11_gen_movhi (rtx insn, rtx *operands)
          else
            output_asm_insn ("st%1\t%0", operands);
        }
          else
            output_asm_insn ("st%1\t%0", operands);
        }
+
+      /* The 68hc12 does not support (MEM:HI (MEM:HI)) with the movw
+         instruction.  We have to use a scratch register as temporary location.
+         Trying to use a specific pattern or constrain failed.  */
+      else if (GET_CODE (to) == MEM && GET_CODE (XEXP (to, 0)) == MEM)
+        {
+          rtx ops[4];
+
+          ops[0] = to;
+          ops[2] = from;
+          ops[3] = 0;
+          if (dead_register_here (insn, d_reg))
+            ops[1] = d_reg;
+          else if (dead_register_here (insn, ix_reg))
+            ops[1] = ix_reg;
+          else if (dead_register_here (insn, iy_reg))
+            ops[1] = iy_reg;
+          else
+            {
+              ops[1] = d_reg;
+              ops[3] = d_reg;
+              output_asm_insn ("psh%3", ops);
+            }
+
+          ops[0] = to;
+          ops[2] = from;
+          output_asm_insn ("ld%1\t%2", ops);
+          output_asm_insn ("st%1\t%0", ops);
+          if (ops[3])
+            output_asm_insn ("pul%3", ops);
+        }
+
+      /* Use movw for non-null constants or when we are clearing
+         a volatile memory reference.  However, this is possible
+         only if the memory reference has a small offset or is an
+         absolute address.  */
+      else if (GET_CODE (from) == CONST_INT
+               && INTVAL (from) == 0
+               && (MEM_VOLATILE_P (to) == 0
+                   || m68hc11_small_indexed_indirect_p (to, HImode) == 0))
+        {
+          output_asm_insn ("clr\t%h0", operands);
+          output_asm_insn ("clr\t%b0", operands);
+        }
       else
        {
       else
        {
-         rtx from = operands[1];
-         rtx to = operands[0];
-
          if ((m68hc11_register_indirect_p (from, GET_MODE (from))
               && !m68hc11_small_indexed_indirect_p (from, GET_MODE (from)))
              || (m68hc11_register_indirect_p (to, GET_MODE (to))
          if ((m68hc11_register_indirect_p (from, GET_MODE (from))
               && !m68hc11_small_indexed_indirect_p (from, GET_MODE (from)))
              || (m68hc11_register_indirect_p (to, GET_MODE (to))
@@ -3183,6 +3236,7 @@ m68hc11_gen_movhi (rtx insn, rtx *operands)
                  ops[0] = to;
                  ops[1] = operands[2];
                  m68hc11_gen_movhi (insn, ops);
                  ops[0] = to;
                  ops[1] = operands[2];
                  m68hc11_gen_movhi (insn, ops);
+                  return;
                }
              else
                {
                }
              else
                {
@@ -3190,19 +3244,11 @@ m68hc11_gen_movhi (rtx insn, rtx *operands)
                   fatal_insn ("move insn not handled", insn);
                }
            }
                   fatal_insn ("move insn not handled", insn);
                }
            }
-         else
-           {
-             if (GET_CODE (from) == CONST_INT && INTVAL (from) == 0)
-               {
-                 output_asm_insn ("clr\t%h0", operands);
-                 output_asm_insn ("clr\t%b0", operands);
-               }
-             else
-               {
-                  m68hc11_notice_keep_cc (operands[0]);
-                 output_asm_insn ("movw\t%1,%0", operands);
-               }
-           }
+          else
+            {
+              m68hc11_notice_keep_cc (operands[0]);
+              output_asm_insn ("movw\t%1,%0", operands);
+            }
        }
       return;
     }
        }
       return;
     }
@@ -3221,7 +3267,7 @@ m68hc11_gen_movhi (rtx insn, rtx *operands)
          output_asm_insn ("pulb", operands);
          break;
        default:
          output_asm_insn ("pulb", operands);
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
       return;
     }
        }
       return;
     }
@@ -3445,7 +3491,7 @@ m68hc11_gen_movhi (rtx insn, rtx *operands)
          output_asm_insn ("psha", operands);
          break;
        default:
          output_asm_insn ("psha", operands);
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
       return;
     }
        }
       return;
     }
@@ -3530,8 +3576,10 @@ m68hc11_gen_movqi (rtx insn, rtx *operands)
        }
       else if (H_REG_P (operands[0]))
        {
        }
       else if (H_REG_P (operands[0]))
        {
-         if (Q_REG_P (operands[0]))
-           output_asm_insn ("lda%0\t%b1", operands);
+          if (IS_STACK_POP (operands[1]))
+            output_asm_insn ("pul%b0", operands);
+         else if (Q_REG_P (operands[0]))
+            output_asm_insn ("lda%0\t%b1", operands);
          else if (D_REG_P (operands[0]))
            output_asm_insn ("ldab\t%b1", operands);
          else
          else if (D_REG_P (operands[0]))
            output_asm_insn ("ldab\t%b1", operands);
          else
@@ -3892,7 +3940,11 @@ m68hc11_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED)
        {
          cc_status.flags = 0;
          cc_status.value1 = XEXP (exp, 0);
        {
          cc_status.flags = 0;
          cc_status.value1 = XEXP (exp, 0);
-         cc_status.value2 = XEXP (exp, 1);
+         if (GET_CODE (XEXP (exp, 1)) == COMPARE
+             && XEXP (XEXP (exp, 1), 1) == CONST0_RTX (GET_MODE (XEXP (XEXP (exp, 1), 0))))
+           cc_status.value2 = XEXP (XEXP (exp, 1), 0);
+         else
+           cc_status.value2 = XEXP (exp, 1);
        }
       else
        {
        }
       else
        {
@@ -4254,9 +4306,7 @@ m68hc11_check_z_replacement (rtx insn, struct replace_info *info)
                  info->must_restore_reg = 0;
                  info->found_call = 1;
                  info->can_use_d = 0;
                  info->must_restore_reg = 0;
                  info->found_call = 1;
                  info->can_use_d = 0;
-                 PUT_CODE (insn, NOTE);
-                 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-                 NOTE_SOURCE_FILE (insn) = 0;
+                 SET_INSN_DELETED (insn);
                  info->last = NEXT_INSN (insn);
                  return 0;
                }
                  info->last = NEXT_INSN (insn);
                  return 0;
                }
@@ -4337,9 +4387,7 @@ m68hc11_check_z_replacement (rtx insn, struct replace_info *info)
                  info->must_restore_reg = 0;
                  info->found_call = 1;
                  info->can_use_d = 0;
                  info->must_restore_reg = 0;
                  info->found_call = 1;
                  info->can_use_d = 0;
-                 PUT_CODE (insn, NOTE);
-                 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-                 NOTE_SOURCE_FILE (insn) = 0;
+                 SET_INSN_DELETED (insn);
                  info->last = NEXT_INSN (insn);
                  return 0;
                }
                  info->last = NEXT_INSN (insn);
                  return 0;
                }
@@ -5015,7 +5063,7 @@ static void
 m68hc11_reorg (void)
 {
   int split_done = 0;
 m68hc11_reorg (void)
 {
   int split_done = 0;
-  rtx insn, first;
+  rtx first;
 
   z_replacement_completed = 0;
   z_reg = gen_rtx_REG (HImode, HARD_Z_REGNUM);
 
   z_replacement_completed = 0;
   z_reg = gen_rtx_REG (HImode, HARD_Z_REGNUM);
@@ -5025,7 +5073,7 @@ m68hc11_reorg (void)
      replacement, unshare everything.  */
   unshare_all_rtl_again (first);
 
      replacement, unshare everything.  */
   unshare_all_rtl_again (first);
 
-  /* Force a split of all splitable insn.  This is necessary for the
+  /* Force a split of all splittable insn.  This is necessary for the
      Z register replacement mechanism because we end up with basic insns.  */
   split_all_insns_noflow ();
   split_done = 1;
      Z register replacement mechanism because we end up with basic insns.  */
   split_all_insns_noflow ();
   split_done = 1;
@@ -5047,29 +5095,9 @@ m68hc11_reorg (void)
      description to use the best assembly directives.  */
   if (optimize)
     {
      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);
-                }
-            }
-        }
-
-      life_analysis (0, PROP_REG_INFO | PROP_DEATH_NOTES);
+      df_note_add_problem ();
+      df_analyze ();
+      df_remove_problem (df_note);
     }
 
   z_replacement_completed = 2;
     }
 
   z_replacement_completed = 2;
@@ -5105,9 +5133,7 @@ m68hc11_reorg (void)
        if (GET_CODE (body) == SET
            && rtx_equal_p (SET_SRC (body), SET_DEST (body)))
          {
        if (GET_CODE (body) == SET
            && rtx_equal_p (SET_SRC (body), SET_DEST (body)))
          {
-           PUT_CODE (insn, NOTE);
-           NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-           NOTE_SOURCE_FILE (insn) = 0;
+           SET_INSN_DELETED  (insn);
            continue;
          }
       }
            continue;
          }
       }
@@ -5130,10 +5156,10 @@ m68hc11_init_libfuncs (void)
 
 /* Cost of moving memory.  */
 int
 
 /* Cost of moving memory.  */
 int
-m68hc11_memory_move_cost (enum machine_mode mode, enum reg_class class,
+m68hc11_memory_move_cost (enum machine_mode mode, enum reg_class rclass,
                           int in ATTRIBUTE_UNUSED)
 {
                           int in ATTRIBUTE_UNUSED)
 {
-  if (class <= H_REGS && class > NO_REGS)
+  if (rclass <= H_REGS && rclass > NO_REGS)
     {
       if (GET_MODE_SIZE (mode) <= 2)
        return COSTS_N_INSNS (1) + (reload_completed | reload_in_progress);
     {
       if (GET_MODE_SIZE (mode) <= 2)
        return COSTS_N_INSNS (1) + (reload_completed | reload_in_progress);
@@ -5178,7 +5204,7 @@ m68hc11_register_move_cost (enum machine_mode mode, enum reg_class from,
    If ADDR is not a valid address, its cost is irrelevant.  */
 
 static int
    If ADDR is not a valid address, its cost is irrelevant.  */
 
 static int
-m68hc11_address_cost (rtx addr)
+m68hc11_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
 {
   int cost = 4;
 
 {
   int cost = 4;
 
@@ -5263,7 +5289,7 @@ m68hc11_shift_cost (enum machine_mode mode, rtx x, int shift)
 {
   int total;
 
 {
   int total;
 
-  total = rtx_cost (x, SET);
+  total = rtx_cost (x, SET, !optimize_size);
   if (mode == QImode)
     total += m68hc11_cost->shiftQI_const[shift % 8];
   else if (mode == HImode)
   if (mode == QImode)
     total += m68hc11_cost->shiftQI_const[shift % 8];
   else if (mode == HImode)
@@ -5307,14 +5333,14 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code,
           return m68hc11_shift_cost (mode, XEXP (x, 0), INTVAL (XEXP (x, 1)));
        }
 
           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 = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
       total += m68hc11_cost->shift_var;
       return total;
 
     case AND:
     case XOR:
     case IOR:
       total += m68hc11_cost->shift_var;
       return total;
 
     case AND:
     case XOR:
     case IOR:
-      total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+      total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
       total += m68hc11_cost->logical;
 
       /* Logical instructions are byte instructions only.  */
       total += m68hc11_cost->logical;
 
       /* Logical instructions are byte instructions only.  */
@@ -5323,7 +5349,7 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code,
 
     case MINUS:
     case PLUS:
 
     case MINUS:
     case PLUS:
-      total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+      total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
       total += m68hc11_cost->add;
       if (GET_MODE_SIZE (mode) > 2)
        {
       total += m68hc11_cost->add;
       if (GET_MODE_SIZE (mode) > 2)
        {
@@ -5334,7 +5360,7 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code,
     case UDIV:
     case DIV:
     case MOD:
     case UDIV:
     case DIV:
     case MOD:
-      total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+      total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
       switch (mode)
         {
         case QImode:
       switch (mode)
         {
         case QImode:
@@ -5357,18 +5383,19 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code,
       if (mode == HImode && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
           && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
         return m68hc11_cost->multQI
       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);
+          + rtx_cost (XEXP (XEXP (x, 0), 0), code, !optimize_size)
+          + rtx_cost (XEXP (XEXP (x, 1), 0), code, !optimize_size);
 
       /* 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
 
       /* 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);
+          + rtx_cost (XEXP (XEXP (x, 0), 0), code, !optimize_size)
+          + rtx_cost (XEXP (XEXP (x, 1), 0), code, !optimize_size);
 
 
-      total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+      total = rtx_cost (XEXP (x, 0), code, !optimize_size)
+             + rtx_cost (XEXP (x, 1), code, !optimize_size);
       switch (mode)
         {
         case QImode:
       switch (mode)
         {
         case QImode:
@@ -5395,7 +5422,8 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code,
     case COMPARE:
     case ABS:
     case ZERO_EXTEND:
     case COMPARE:
     case ABS:
     case ZERO_EXTEND:
-      total = extra_cost + rtx_cost (XEXP (x, 0), code);
+    case ZERO_EXTRACT:
+      total = extra_cost + rtx_cost (XEXP (x, 0), code, !optimize_size);
       if (mode == QImode)
        {
          return total + COSTS_N_INSNS (1);
       if (mode == QImode)
        {
          return total + COSTS_N_INSNS (1);
@@ -5422,8 +5450,12 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code,
 }
 
 static bool
 }
 
 static bool
-m68hc11_rtx_costs (rtx x, int code, int outer_code, int *total)
+m68hc11_rtx_costs (rtx x, int codearg, int outer_code_arg, int *total,
+                  bool speed ATTRIBUTE_UNUSED)
 {
 {
+  enum rtx_code code = (enum rtx_code) codearg;
+  enum rtx_code outer_code = (enum rtx_code) outer_code_arg;
+
   switch (code)
     {
       /* Constants are cheap.  Moving them in registers must be avoided
   switch (code)
     {
       /* Constants are cheap.  Moving them in registers must be avoided
@@ -5444,6 +5476,10 @@ m68hc11_rtx_costs (rtx x, int code, int outer_code, int *total)
        *total = 0;
       return true;
     
        *total = 0;
       return true;
     
+    case ZERO_EXTRACT:
+      if (outer_code != COMPARE)
+       return false;
+
     case ROTATE:
     case ROTATERT:
     case ASHIFT:
     case ROTATE:
     case ROTATERT:
     case ASHIFT:
@@ -5516,7 +5552,7 @@ m68hc11_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
    in the register (D + X = 4).  */
 
 static bool
    in the register (D + X = 4).  */
 
 static bool
-m68hc11_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+m68hc11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
 {
   if (TYPE_MODE (type) == BLKmode)
     {
 {
   if (TYPE_MODE (type) == BLKmode)
     {