diff gcc/config/mn10300/mn10300.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
line wrap: on
line diff
--- a/gcc/config/mn10300/mn10300.c	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/config/mn10300/mn10300.c	Fri Oct 27 22:46:09 2017 +0900
@@ -1,6 +1,5 @@
 /* Subroutines for insn-output.c for Matsushita MN10300 series
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
    Contributed by Jeff Law (law@cygnus.com).
 
    This file is part of GCC.
@@ -22,28 +21,38 @@
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "target.h"
 #include "rtl.h"
 #include "tree.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "cfghooks.h"
+#include "cfgloop.h"
+#include "df.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "optabs.h"
 #include "regs.h"
-#include "hard-reg-set.h"
-#include "insn-config.h"
-#include "conditions.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "diagnostic-core.h"
+#include "alias.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "calls.h"
 #include "output.h"
 #include "insn-attr.h"
-#include "flags.h"
-#include "recog.h"
 #include "reload.h"
+#include "explow.h"
 #include "expr.h"
-#include "optabs.h"
-#include "function.h"
-#include "obstack.h"
-#include "diagnostic-core.h"
-#include "tm_p.h"
 #include "tm-constrs.h"
-#include "target.h"
+#include "cfgrtl.h"
+#include "dumpfile.h"
+#include "builtins.h"
+
+/* This file should be included last.  */
 #include "target-def.h"
-#include "df.h"
 
 /* This is used in the am33_2.0-linux-gnu port, in which global symbol
    names are not prefixed by underscores, to tell whether to prefix a
@@ -51,76 +60,18 @@
    symbol names from register names.  */
 int mn10300_protect_label;
 
-/* The selected processor.  */
-enum processor_type mn10300_processor = PROCESSOR_DEFAULT;
-
-/* Processor type to select for tuning.  */
-static const char * mn10300_tune_string = NULL;
-
 /* Selected processor type for tuning.  */
 enum processor_type mn10300_tune_cpu = PROCESSOR_DEFAULT;
 
-/* The size of the callee register save area.  Right now we save everything
-   on entry since it costs us nothing in code size.  It does cost us from a
-   speed standpoint, so we want to optimize this sooner or later.  */
-#define REG_SAVE_BYTES (4 * df_regs_ever_live_p (2)		\
-			+ 4 * df_regs_ever_live_p (3)		\
-		        + 4 * df_regs_ever_live_p (6)		\
-			+ 4 * df_regs_ever_live_p (7)		\
-			+ 16 * (df_regs_ever_live_p (14)	\
-				|| df_regs_ever_live_p (15)	\
-				|| df_regs_ever_live_p (16)	\
-				|| df_regs_ever_live_p (17)))
-
-/* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
-static const struct default_options mn10300_option_optimization_table[] =
-  {
-    { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
-    { OPT_LEVELS_NONE, 0, NULL, 0 }
-  };
-
 #define CC_FLAG_Z	1
 #define CC_FLAG_N	2
 #define CC_FLAG_C	4
 #define CC_FLAG_V	8
 
-static int cc_flags_for_mode(enum machine_mode);
+static int cc_flags_for_mode(machine_mode);
 static int cc_flags_for_code(enum rtx_code);
 
-/* Implement TARGET_HANDLE_OPTION.  */
-
-static bool
-mn10300_handle_option (size_t code,
-		       const char *arg ATTRIBUTE_UNUSED,
-		       int value)
-{
-  switch (code)
-    {
-    case OPT_mam33:
-      mn10300_processor = value ? PROCESSOR_AM33 : PROCESSOR_MN10300;
-      return true;
-
-    case OPT_mam33_2:
-      mn10300_processor = (value
-			   ? PROCESSOR_AM33_2
-			   : MIN (PROCESSOR_AM33, PROCESSOR_DEFAULT));
-      return true;
-
-    case OPT_mam34:
-      mn10300_processor = (value ? PROCESSOR_AM34 : PROCESSOR_DEFAULT);
-      return true;
-
-    case OPT_mtune_:
-      mn10300_tune_string = arg;
-      return true;
-
-    default:
-      return true;
-    }
-}
-
 /* Implement TARGET_OPTION_OVERRIDE.  */
-
 static void
 mn10300_option_override (void)
 {
@@ -198,7 +149,7 @@
     case 'B':
       {
 	enum rtx_code cmp = GET_CODE (x);
-	enum machine_mode mode = GET_MODE (XEXP (x, 0));
+	machine_mode mode = GET_MODE (XEXP (x, 0));
 	const char *str;
 	int have_flags;
 
@@ -291,7 +242,7 @@
 	{
 	case MEM:
 	  fputc ('(', file);
-	  output_address (XEXP (x, 0));
+	  output_address (GET_MODE (x), XEXP (x, 0));
 	  fputc (')', file);
 	  break;
 
@@ -310,7 +261,7 @@
 	{
 	case MEM:
 	  fputc ('(', file);
-	  output_address (XEXP (x, 0));
+	  output_address (GET_MODE (x), XEXP (x, 0));
 	  fputc (')', file);
 	  break;
 
@@ -325,22 +276,21 @@
 	case CONST_DOUBLE:
 	  {
 	    long val[2];
-	    REAL_VALUE_TYPE rv;
 
 	    switch (GET_MODE (x))
 	      {
-	      case DFmode:
-		REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
-		REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
+	      case E_DFmode:
+		REAL_VALUE_TO_TARGET_DOUBLE
+		  (*CONST_DOUBLE_REAL_VALUE (x), val);
 		fprintf (file, "0x%lx", val[0]);
 		break;;
-	      case SFmode:
-		REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
-		REAL_VALUE_TO_TARGET_SINGLE (rv, val[0]);
+	      case E_SFmode:
+		REAL_VALUE_TO_TARGET_SINGLE
+		  (*CONST_DOUBLE_REAL_VALUE (x), val[0]);
 		fprintf (file, "0x%lx", val[0]);
 		break;;
-	      case VOIDmode:
-	      case DImode:
+	      case E_VOIDmode:
+	      case E_DImode:
 		mn10300_print_operand_address (file,
 					       GEN_INT (CONST_DOUBLE_LOW (x)));
 		break;
@@ -370,7 +320,7 @@
 	case MEM:
 	  fputc ('(', file);
 	  x = adjust_address (x, SImode, 4);
-	  output_address (XEXP (x, 0));
+	  output_address (GET_MODE (x), XEXP (x, 0));
 	  fputc (')', file);
 	  break;
 
@@ -385,19 +335,18 @@
 	case CONST_DOUBLE:
 	  {
 	    long val[2];
-	    REAL_VALUE_TYPE rv;
 
 	    switch (GET_MODE (x))
 	      {
-	      case DFmode:
-		REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
-		REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
+	      case E_DFmode:
+		REAL_VALUE_TO_TARGET_DOUBLE
+		  (*CONST_DOUBLE_REAL_VALUE (x), val);
 		fprintf (file, "0x%lx", val[1]);
 		break;;
-	      case SFmode:
+	      case E_SFmode:
 		gcc_unreachable ();
-	      case VOIDmode:
-	      case DImode:
+	      case E_VOIDmode:
+	      case E_DImode:
 		mn10300_print_operand_address (file,
 					       GEN_INT (CONST_DOUBLE_HIGH (x)));
 		break;
@@ -423,9 +372,10 @@
     case 'A':
       fputc ('(', file);
       if (REG_P (XEXP (x, 0)))
-	output_address (gen_rtx_PLUS (SImode, XEXP (x, 0), const0_rtx));
+	output_address (VOIDmode, gen_rtx_PLUS (SImode,
+						XEXP (x, 0), const0_rtx));
       else
-	output_address (XEXP (x, 0));
+	output_address (VOIDmode, XEXP (x, 0));
       fputc (')', file);
       break;
 
@@ -456,12 +406,12 @@
 	{
 	case MEM:
 	  fputc ('(', file);
-	  output_address (XEXP (x, 0));
+	  output_address (GET_MODE (x), XEXP (x, 0));
 	  fputc (')', file);
 	  break;
 
 	case PLUS:
-	  output_address (x);
+	  output_address (VOIDmode, x);
 	  break;
 
 	case REG:
@@ -476,10 +426,8 @@
 	case CONST_DOUBLE:
 	  {
 	    unsigned long val;
-	    REAL_VALUE_TYPE rv;
-
-	    REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
-	    REAL_VALUE_TO_TARGET_SINGLE (rv, val);
+
+	    REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
 	    fprintf (file, "0x%lx", val);
 	    break;
 	  }
@@ -677,20 +625,36 @@
 
 /* Returns the set of live, callee-saved registers as a bitmask.  The
    callee-saved extended registers cannot be stored individually, so
-   all of them will be included in the mask if any one of them is used.  */
-
-int
-mn10300_get_live_callee_saved_regs (void)
+   all of them will be included in the mask if any one of them is used.
+   Also returns the number of bytes in the registers in the mask if
+   BYTES_SAVED is not NULL.  */
+
+unsigned int
+mn10300_get_live_callee_saved_regs (unsigned int * bytes_saved)
 {
   int mask;
   int i;
-
-  mask = 0;
+  unsigned int count;
+
+  count = mask = 0;
   for (i = 0; i <= LAST_EXTENDED_REGNUM; i++)
     if (df_regs_ever_live_p (i) && ! call_really_used_regs[i])
-      mask |= (1 << i);
+      {
+	mask |= (1 << i);
+	++ count;
+      }
+
   if ((mask & 0x3c000) != 0)
-    mask |= 0x3c000;
+    {
+      for (i = 0x04000; i < 0x40000; i <<= 1)
+	if ((mask & i) == 0)
+	  ++ count;
+      
+      mask |= 0x3c000;
+    }
+
+  if (bytes_saved)
+    * bytes_saved = count * UNITS_PER_WORD;
 
   return mask;
 }
@@ -754,9 +718,9 @@
 	continue;
 
       ++count;
-      x = plus_constant (stack_pointer_rtx, count * -4);
+      x = plus_constant (Pmode, stack_pointer_rtx, count * -4);
       x = gen_frame_mem (SImode, x);
-      x = gen_rtx_SET (VOIDmode, x, gen_rtx_REG (SImode, regno));
+      x = gen_rtx_SET (x, gen_rtx_REG (SImode, regno));
       elts[count] = F(x);
 
       /* Remove the register from the mask so that... */
@@ -768,8 +732,8 @@
   gcc_assert (mask == 0);
 
   /* Create the instruction that updates the stack pointer.  */
-  x = plus_constant (stack_pointer_rtx, count * -4);
-  x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x);
+  x = plus_constant (Pmode, stack_pointer_rtx, count * -4);
+  x = gen_rtx_SET (stack_pointer_rtx, x);
   elts[0] = F(x);
 
   /* We need one PARALLEL element to update the stack pointer and
@@ -778,13 +742,31 @@
   F (emit_insn (x));
 }
 
+static inline unsigned int
+popcount (unsigned int mask)
+{
+  unsigned int count = 0;
+  
+  while (mask)
+    {
+      ++ count;
+      mask &= ~ (mask & - mask);
+    }
+  return count;
+}
+
 void
 mn10300_expand_prologue (void)
 {
   HOST_WIDE_INT size = mn10300_frame_size ();
-
+  unsigned int mask;
+
+  mask = mn10300_get_live_callee_saved_regs (NULL);
   /* If we use any of the callee-saved registers, save them now.  */
-  mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs ());
+  mn10300_gen_multiple_store (mask);
+
+  if (flag_stack_usage_info)
+    current_function_static_stack_size = size + popcount (mask) * 4;
 
   if (TARGET_AM33_2 && fp_regs_to_save ())
     {
@@ -801,6 +783,9 @@
       unsigned int strategy_size = (unsigned)-1, this_strategy_size;
       rtx reg;
 
+      if (flag_stack_usage_info)
+	current_function_static_stack_size += num_regs_to_save * 4;
+
       /* We have several different strategies to save FP registers.
 	 We can store them using SP offsets, which is beneficial if
 	 there are just a few registers to save, or we can use `a0' in
@@ -1041,8 +1026,10 @@
 mn10300_expand_epilogue (void)
 {
   HOST_WIDE_INT size = mn10300_frame_size ();
-  int reg_save_bytes = REG_SAVE_BYTES;
-  
+  unsigned int reg_save_bytes;
+
+  mn10300_get_live_callee_saved_regs (& reg_save_bytes);
+
   if (TARGET_AM33_2 && fp_regs_to_save ())
     {
       int num_regs_to_save = fp_regs_to_save (), i;
@@ -1112,7 +1099,7 @@
 	      /* Insn: add size + 4 * num_regs_to_save
 				+ reg_save_bytes - 252,sp.  */
 	      this_strategy_size = SIZE_ADD_SP (size + 4 * num_regs_to_save
-						+ reg_save_bytes - 252);
+						+ (int) reg_save_bytes - 252);
 	      /* Insn: fmov (##,sp),fs#, fo each fs# to be restored.  */
 	      this_strategy_size += SIZE_FMOV_SP (252 - reg_save_bytes
 						  - 4 * num_regs_to_save,
@@ -1260,9 +1247,9 @@
 
   /* Adjust the stack and restore callee-saved registers, if any.  */
   if (mn10300_can_use_rets_insn ())
-    emit_jump_insn (gen_rtx_RETURN (VOIDmode));
+    emit_jump_insn (ret_rtx);
   else
-    emit_jump_insn (gen_return_ret (GEN_INT (size + REG_SAVE_BYTES)));
+    emit_jump_insn (gen_return_ret (GEN_INT (size + reg_save_bytes)));
 }
 
 /* Recognize the PARALLEL rtx generated by mn10300_gen_multiple_store().
@@ -1270,9 +1257,8 @@
    parallel.  If OP is a multiple store, return a mask indicating which
    registers it saves.  Return 0 otherwise.  */
 
-int
-mn10300_store_multiple_operation (rtx op,
-				  enum machine_mode mode ATTRIBUTE_UNUSED)
+unsigned int
+mn10300_store_multiple_regs (rtx op)
 {
   int count;
   int mask;
@@ -1369,7 +1355,7 @@
 
 static reg_class_t
 mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
-			  enum machine_mode mode, secondary_reload_info *sri)
+			  machine_mode mode, secondary_reload_info *sri)
 {
   enum reg_class rclass = (enum reg_class) rclass_i;
   enum reg_class xclass = NO_REGS;
@@ -1435,7 +1421,7 @@
 
       if (xregno >= FIRST_PSEUDO_REGISTER && xregno != INVALID_REGNUM)
 	{
-	  addr = reg_equiv_mem [xregno];
+	  addr = reg_equiv_mem (xregno);
 	  if (addr)
 	    addr = XEXP (addr, 0);
 	}
@@ -1445,7 +1431,6 @@
       if (addr && CONSTANT_ADDRESS_P (addr))
 	return GENERAL_REGS;
     }
-
   /* Otherwise assume no secondary reloads are needed.  */
   return NO_REGS;
 }
@@ -1477,7 +1462,10 @@
      is the size of the callee register save area.  */
   if (from == ARG_POINTER_REGNUM)
     {
-      diff += REG_SAVE_BYTES;
+      unsigned int reg_save_bytes;
+
+      mn10300_get_live_callee_saved_regs (& reg_save_bytes);
+      diff += reg_save_bytes;
       diff += 4 * fp_regs_to_save ();
     }
 
@@ -1507,7 +1495,7 @@
   alias_set_type set = get_varargs_alias_set ();
 
   if (argadj)
-    offset = plus_constant (crtl->args.arg_offset_rtx, argadj);
+    offset = plus_constant (Pmode, crtl->args.arg_offset_rtx, argadj);
   else
     offset = crtl->args.arg_offset_rtx;
 
@@ -1516,7 +1504,8 @@
   emit_move_insn (mem, gen_rtx_REG (SImode, 0));
 
   mem = gen_rtx_MEM (SImode,
-		     plus_constant (crtl->args.internal_arg_pointer, 4));
+		     plus_constant (Pmode,
+				    crtl->args.internal_arg_pointer, 4));
   set_mem_alias_set (mem, set);
   emit_move_insn (mem, gen_rtx_REG (SImode, 1));
 
@@ -1535,8 +1524,8 @@
 /* Return true when a parameter should be passed by reference.  */
 
 static bool
-mn10300_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
-			   enum machine_mode mode, const_tree type,
+mn10300_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
+			   machine_mode mode, const_tree type,
 			   bool named ATTRIBUTE_UNUSED)
 {
   unsigned HOST_WIDE_INT size;
@@ -1553,9 +1542,10 @@
    from a function.  If the result is NULL_RTX, the argument is pushed.  */
 
 static rtx
-mn10300_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+mn10300_function_arg (cumulative_args_t cum_v, machine_mode mode,
 		      const_tree type, bool named ATTRIBUTE_UNUSED)
 {
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   rtx result = NULL_RTX;
   int size;
 
@@ -1601,9 +1591,11 @@
    (TYPE is null for libcalls where that information may not be available.)  */
 
 static void
-mn10300_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+mn10300_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
 			      const_tree type, bool named ATTRIBUTE_UNUSED)
 {
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+
   cum->nbytes += (mode != BLKmode
 		  ? (GET_MODE_SIZE (mode) + 3) & ~3
 		  : (int_size_in_bytes (type) + 3) & ~3);
@@ -1613,9 +1605,10 @@
    partially in registers and partially in memory.  */
 
 static int
-mn10300_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+mn10300_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
 			   tree type, bool named ATTRIBUTE_UNUSED)
 {
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int size;
 
   /* We only support using 2 data registers as argument registers.  */
@@ -1658,7 +1651,7 @@
 			bool outgoing)
 {
   rtx rv;
-  enum machine_mode mode = TYPE_MODE (valtype);
+  machine_mode mode = TYPE_MODE (valtype);
 
   if (! POINTER_TYPE_P (valtype))
     return gen_rtx_REG (mode, FIRST_DATA_REGNUM);
@@ -1682,7 +1675,7 @@
 /* Implements TARGET_LIBCALL_VALUE.  */
 
 static rtx
-mn10300_libcall_value (enum machine_mode mode,
+mn10300_libcall_value (machine_mode mode,
 		       const_rtx fun ATTRIBUTE_UNUSED)
 {
   return gen_rtx_REG (mode, FIRST_DATA_REGNUM);
@@ -1794,7 +1787,7 @@
 
 int
 mn10300_symbolic_operand (rtx op,
-			  enum machine_mode mode ATTRIBUTE_UNUSED)
+			  machine_mode mode ATTRIBUTE_UNUSED)
 {
   switch (GET_CODE (op))
     {
@@ -1826,7 +1819,7 @@
 
 static rtx
 mn10300_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
-			    enum machine_mode mode ATTRIBUTE_UNUSED)
+			    machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (flag_pic && ! mn10300_legitimate_pic_operand_p (x))
     x = mn10300_legitimize_pic_address (oldx, NULL_RTX);
@@ -1869,6 +1862,7 @@
 mn10300_legitimize_pic_address (rtx orig, rtx reg)
 {
   rtx x;
+  rtx_insn *insn;
 
   if (GET_CODE (orig) == LABEL_REF
       || (GET_CODE (orig) == SYMBOL_REF
@@ -1882,7 +1876,7 @@
       x = gen_rtx_CONST (SImode, x);
       emit_move_insn (reg, x);
 
-      x = emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
+      insn = emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
     }
   else if (GET_CODE (orig) == SYMBOL_REF)
     {
@@ -1894,12 +1888,12 @@
       x = gen_rtx_PLUS (SImode, pic_offset_table_rtx, x);
       x = gen_const_mem (SImode, x);
 
-      x = emit_move_insn (reg, x);
+      insn = emit_move_insn (reg, x);
     }
   else
     return orig;
 
-  set_unique_reg_note (x, REG_EQUAL, orig);
+  set_unique_reg_note (insn, REG_EQUAL, orig);
   return reg;
 }
 
@@ -1957,7 +1951,7 @@
    function record_unscaled_index_insn_codes.  */
 
 static bool
-mn10300_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+mn10300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
 {
   rtx base, index;
 
@@ -2025,7 +2019,7 @@
 
 rtx
 mn10300_legitimize_reload_address (rtx x,
-				   enum machine_mode mode ATTRIBUTE_UNUSED,
+				   machine_mode mode ATTRIBUTE_UNUSED,
 				   int opnum, int type,
 				   int ind_levels ATTRIBUTE_UNUSED)
 {
@@ -2056,13 +2050,13 @@
   return any_change ? x : NULL_RTX;
 }
 
-/* Used by LEGITIMATE_CONSTANT_P().  Returns TRUE if X is a valid
+/* Implement TARGET_LEGITIMATE_CONSTANT_P.  Returns TRUE if X is a valid
    constant.  Note that some "constants" aren't valid, such as TLS
    symbols and unconverted GOT-based references, so we eliminate
    those here.  */
 
-bool
-mn10300_legitimate_constant_p (rtx x)
+static bool
+mn10300_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 {
   switch (GET_CODE (x))
     {
@@ -2168,7 +2162,8 @@
    with an address register.  */
 
 static int
-mn10300_address_cost (rtx x, bool speed)
+mn10300_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+		      addr_space_t as ATTRIBUTE_UNUSED, bool speed)
 {
   HOST_WIDE_INT i;
   rtx base, index;
@@ -2221,7 +2216,7 @@
       return speed ? 2 : 6;
 
     default:
-      return rtx_cost (x, MEM, speed);
+      return rtx_cost (x, Pmode, MEM, 0, speed);
     }
 }
 
@@ -2232,7 +2227,7 @@
    early exit from reload meaning no work is required.  */
 
 static int
-mn10300_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+mn10300_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
 			    reg_class_t ifrom, reg_class_t ito)
 {
   enum reg_class from = (enum reg_class) ifrom;
@@ -2319,7 +2314,7 @@
    move cost above.  This is not a problem.  */
 
 static int
-mn10300_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, 
+mn10300_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED, 
 			  reg_class_t iclass, bool in ATTRIBUTE_UNUSED)
 {
   enum reg_class rclass = (enum reg_class) iclass;
@@ -2335,12 +2330,14 @@
    to represent cycles.  Size-relative costs are in bytes.  */
 
 static bool
-mn10300_rtx_costs (rtx x, int code, int outer_code, int *ptotal, bool speed)
+mn10300_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		   int opno ATTRIBUTE_UNUSED, int *ptotal, bool speed)
 {
   /* This value is used for SYMBOL_REF etc where we want to pretend
      we have a full 32-bit constant.  */
   HOST_WIDE_INT i = 0x12345678;
   int total;
+  int code = GET_CODE (x);
 
   switch (code)
     {
@@ -2426,7 +2423,7 @@
 	  i = INTVAL (XEXP (x, 1));
 	  if (i == 1 || i == 4)
 	    {
-	      total = 1 + rtx_cost (XEXP (x, 0), PLUS, speed);
+	      total = 1 + rtx_cost (XEXP (x, 0), mode, PLUS, 0, speed);
 	      goto alldone;
 	    }
 	}
@@ -2482,7 +2479,8 @@
       break;
 
     case MEM:
-      total = mn10300_address_cost (XEXP (x, 0), speed);
+      total = mn10300_address_cost (XEXP (x, 0), mode,
+				    MEM_ADDR_SPACE (x), speed);
       if (speed)
 	total = COSTS_N_INSNS (2 + total);
       goto alldone;
@@ -2505,12 +2503,15 @@
    may access it using GOTOFF instead of GOT.  */
 
 static void
-mn10300_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
+mn10300_encode_section_info (tree decl, rtx rtl, int first)
 {
   rtx symbol;
 
+  default_encode_section_info (decl, rtl, first);
+
   if (! MEM_P (rtl))
     return;
+
   symbol = XEXP (rtl, 0);
   if (GET_CODE (symbol) != SYMBOL_REF)
     return;
@@ -2554,7 +2555,7 @@
      clobber the flags but do not affect the contents of D0 or D1.  */
 
   disp = expand_binop (SImode, sub_optab, fnaddr,
-		       plus_constant (XEXP (m_tramp, 0), 11),
+		       plus_constant (Pmode, XEXP (m_tramp, 0), 11),
 		       NULL_RTX, 1, OPTAB_DIRECT);
 
   mem = adjust_address (m_tramp, SImode, 0);
@@ -2625,14 +2626,19 @@
   return true;
 }
 
-bool
-mn10300_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
+/* Implement TARGET_HARD_REGNO_MODE_OK.  */
+
+static bool
+mn10300_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
 {
   if (REGNO_REG_CLASS (regno) == FP_REGS
       || REGNO_REG_CLASS (regno) == FP_ACC_REGS)
     /* Do not store integer values in FP registers.  */
     return GET_MODE_CLASS (mode) == MODE_FLOAT && ((regno & 1) == 0);
-  
+
+  if (! TARGET_AM33 && REGNO_REG_CLASS (regno) == EXTENDED_REGS)
+    return false;
+
   if (((regno) & 1) == 0 || GET_MODE_SIZE (mode) == 4)
     return true;
 
@@ -2644,8 +2650,10 @@
   return false;
 }
 
-bool
-mn10300_modes_tieable (enum machine_mode mode1, enum machine_mode mode2)
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+mn10300_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 {
   if (GET_MODE_CLASS (mode1) == MODE_FLOAT
       && GET_MODE_CLASS (mode2) != MODE_FLOAT)
@@ -2664,17 +2672,17 @@
 }
 
 static int
-cc_flags_for_mode (enum machine_mode mode)
+cc_flags_for_mode (machine_mode mode)
 {
   switch (mode)
     {
-    case CCmode:
+    case E_CCmode:
       return CC_FLAG_Z | CC_FLAG_N | CC_FLAG_C | CC_FLAG_V;
-    case CCZNCmode:
+    case E_CCZNCmode:
       return CC_FLAG_Z | CC_FLAG_N | CC_FLAG_C;
-    case CCZNmode:
+    case E_CCZNmode:
       return CC_FLAG_Z | CC_FLAG_N;
-    case CC_FLOATmode:
+    case E_CC_FLOATmode:
       return -1;
     default:
       gcc_unreachable ();
@@ -2693,7 +2701,6 @@
     case LT:	/* N */
     case GE:	/* ~N */
       return CC_FLAG_N;
-      break;
 
     case GT:    /* ~(Z|(N^V)) */
     case LE:    /* Z|(N^V) */
@@ -2722,7 +2729,7 @@
     }
 }
 
-enum machine_mode
+machine_mode
 mn10300_select_cc_mode (enum rtx_code code, rtx x, rtx y ATTRIBUTE_UNUSED)
 {
   int req;
@@ -2740,21 +2747,15 @@
 }
 
 static inline bool
-is_load_insn (rtx insn)
+set_is_load_p (rtx set)
 {
-  if (GET_CODE (PATTERN (insn)) != SET)
-    return false;
-
-  return MEM_P (SET_SRC (PATTERN (insn)));
+  return MEM_P (SET_SRC (set));
 }
 
 static inline bool
-is_store_insn (rtx insn)
+set_is_store_p (rtx set)
 {
-  if (GET_CODE (PATTERN (insn)) != SET)
-    return false;
-
-  return MEM_P (SET_DEST (PATTERN (insn)));
+  return MEM_P (SET_DEST (set));
 }
 
 /* Update scheduling costs for situations that cannot be
@@ -2764,42 +2765,46 @@
    COST is the current cycle cost for DEP.  */
 
 static int
-mn10300_adjust_sched_cost (rtx insn, rtx link, rtx dep, int cost)
+mn10300_adjust_sched_cost (rtx_insn *insn, int dep_type, rtx_insn *dep,
+			   int cost, unsigned int)
 {
-  int timings = get_attr_timings (insn);
+  rtx insn_set;
+  rtx dep_set;
+  int timings;
 
   if (!TARGET_AM33)
     return 1;
 
-  if (GET_CODE (insn) == PARALLEL)
-    insn = XVECEXP (insn, 0, 0);
-
-  if (GET_CODE (dep) == PARALLEL)
-    dep = XVECEXP (dep, 0, 0);
+  /* We are only interested in pairs of SET. */
+  insn_set = single_set (insn);
+  if (!insn_set)
+    return cost;
+
+  dep_set = single_set (dep);
+  if (!dep_set)
+    return cost;
 
   /* For the AM34 a load instruction that follows a
      store instruction incurs an extra cycle of delay.  */
   if (mn10300_tune_cpu == PROCESSOR_AM34
-      && is_load_insn (dep)
-      && is_store_insn (insn))
+      && set_is_load_p (dep_set)
+      && set_is_store_p (insn_set))
     cost += 1;
 
   /* For the AM34 a non-store, non-branch FPU insn that follows
      another FPU insn incurs a one cycle throughput increase.  */
   else if (mn10300_tune_cpu == PROCESSOR_AM34
-      && ! is_store_insn (insn)
+      && ! set_is_store_p (insn_set)
       && ! JUMP_P (insn)
-      && GET_CODE (PATTERN (dep)) == SET
-      && GET_CODE (PATTERN (insn)) == SET
-      && GET_MODE_CLASS (GET_MODE (SET_SRC (PATTERN (dep)))) == MODE_FLOAT
-      && GET_MODE_CLASS (GET_MODE (SET_SRC (PATTERN (insn)))) == MODE_FLOAT)
+      && GET_MODE_CLASS (GET_MODE (SET_SRC (dep_set))) == MODE_FLOAT
+      && GET_MODE_CLASS (GET_MODE (SET_SRC (insn_set))) == MODE_FLOAT)
     cost += 1;
 
   /*  Resolve the conflict described in section 1-7-4 of
       Chapter 3 of the MN103E Series Instruction Manual
       where it says:
 
-        "When the preceeding instruction is a CPU load or
+        "When the preceding instruction is a CPU load or
 	 store instruction, a following FPU instruction
 	 cannot be executed until the CPU completes the
 	 latency period even though there are no register
@@ -2810,27 +2815,25 @@
     return cost;
 
   /* If a data dependence already exists then the cost is correct.  */
-  if (REG_NOTE_KIND (link) == 0)
+  if (dep_type == 0)
     return cost;
 
   /* Check that the instruction about to scheduled is an FPU instruction.  */
-  if (GET_CODE (PATTERN (dep)) != SET)
-    return cost;
-
-  if (GET_MODE_CLASS (GET_MODE (SET_SRC (PATTERN (dep)))) != MODE_FLOAT)
+  if (GET_MODE_CLASS (GET_MODE (SET_SRC (dep_set))) != MODE_FLOAT)
     return cost;
 
   /* Now check to see if the previous instruction is a load or store.  */
-  if (! is_load_insn (insn) && ! is_store_insn (insn))
+  if (! set_is_load_p (insn_set) && ! set_is_store_p (insn_set))
     return cost;
 
   /* XXX: Verify: The text of 1-7-4 implies that the restriction
-     only applies when an INTEGER load/store preceeds an FPU
+     only applies when an INTEGER load/store precedes an FPU
      instruction, but is this true ?  For now we assume that it is.  */
-  if (GET_MODE_CLASS (GET_MODE (SET_SRC (PATTERN (insn)))) != MODE_INT)
+  if (GET_MODE_CLASS (GET_MODE (SET_SRC (insn_set))) != MODE_INT)
     return cost;
 
   /* Extract the latency value from the timings attribute.  */
+  timings = get_attr_timings (insn);
   return timings < 100 ? (timings % 10) : (timings % 100);
 }
 
@@ -2856,49 +2859,49 @@
     call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
 }
 
-/* Worker function for TARGET_MD_ASM_CLOBBERS.
+/* Worker function for TARGET_MD_ASM_ADJUST.
    We do this in the mn10300 backend to maintain source compatibility
    with the old cc0-based compiler.  */
 
-static tree
-mn10300_md_asm_clobbers (tree outputs ATTRIBUTE_UNUSED,
-                         tree inputs ATTRIBUTE_UNUSED,
-                         tree clobbers)
+static rtx_insn *
+mn10300_md_asm_adjust (vec<rtx> &/*outputs*/, vec<rtx> &/*inputs*/,
+		       vec<const char *> &/*constraints*/,
+		       vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs)
 {
-  clobbers = tree_cons (NULL_TREE, build_string (5, "EPSW"),
-                        clobbers);
-  return clobbers;
+  clobbers.safe_push (gen_rtx_REG (CCmode, CC_REG));
+  SET_HARD_REG_BIT (clobbered_regs, CC_REG);
+  return NULL;
 }
 
 /* A helper function for splitting cbranch patterns after reload.  */
 
 void
-mn10300_split_cbranch (enum machine_mode cmp_mode, rtx cmp_op, rtx label_ref)
+mn10300_split_cbranch (machine_mode cmp_mode, rtx cmp_op, rtx label_ref)
 {
   rtx flags, x;
 
   flags = gen_rtx_REG (cmp_mode, CC_REG);
   x = gen_rtx_COMPARE (cmp_mode, XEXP (cmp_op, 0), XEXP (cmp_op, 1));
-  x = gen_rtx_SET (VOIDmode, flags, x);
+  x = gen_rtx_SET (flags, x);
   emit_insn (x);
 
   x = gen_rtx_fmt_ee (GET_CODE (cmp_op), VOIDmode, flags, const0_rtx);
   x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label_ref, pc_rtx);
-  x = gen_rtx_SET (VOIDmode, pc_rtx, x);
+  x = gen_rtx_SET (pc_rtx, x);
   emit_jump_insn (x);
 }
 
 /* A helper function for matching parallels that set the flags.  */
 
 bool
-mn10300_match_ccmode (rtx insn, enum machine_mode cc_mode)
+mn10300_match_ccmode (rtx insn, machine_mode cc_mode)
 {
   rtx op1, flags;
-  enum machine_mode flags_mode;
+  machine_mode flags_mode;
 
   gcc_checking_assert (XVECLEN (PATTERN (insn), 0) == 2);
 
-  op1 = XVECEXP (PATTERN (insn), 0, 1);
+  op1 = XVECEXP (PATTERN (insn), 0, 0);
   gcc_checking_assert (GET_CODE (SET_SRC (op1)) == COMPARE);
 
   flags = SET_DEST (op1);
@@ -2916,6 +2919,23 @@
   return true;
 }
 
+/* This function is used to help split:
+   
+     (set (reg) (and (reg) (int)))
+     
+   into:
+   
+     (set (reg) (shift (reg) (int))
+     (set (reg) (shift (reg) (int))
+     
+   where the shitfs will be shorter than the "and" insn.
+
+   It returns the number of bits that should be shifted.  A positive
+   values means that the low bits are to be cleared (and hence the
+   shifts should be right followed by left) whereas a negative value
+   means that the high bits are to be cleared (left followed by right).
+   Zero is returned when it would not be economical to split the AND.  */
+
 int
 mn10300_split_and_operand_count (rtx op)
 {
@@ -2932,7 +2952,7 @@
 	 would be replacing 1 6-byte insn with 2 3-byte insns.  */
       if (count > (optimize_insn_for_speed_p () ? 2 : 4))
 	return 0;
-      return -count;
+      return count;
     }
   else
     {
@@ -2960,14 +2980,14 @@
    cannot be bundled.  */
 
 static bool
-extract_bundle (rtx insn, struct liw_data * pdata)
+extract_bundle (rtx_insn *insn, struct liw_data * pdata)
 {
   bool allow_consts = true;
-  rtx p,s;
+  rtx p;
 
   gcc_assert (pdata != NULL);
 
-  if (insn == NULL_RTX)
+  if (insn == NULL)
     return false;
   /* Make sure that we are dealing with a simple SET insn.  */
   p = single_set (insn);
@@ -2981,8 +3001,6 @@
 
   pdata->op = get_attr_liw_op (insn);
 
-  s = SET_SRC (p);
-
   switch (pdata->op)
     {
     case LIW_OP_MOV:
@@ -3088,11 +3106,11 @@
 static void
 mn10300_bundle_liw (void)
 {
-  rtx r;
-
-  for (r = get_insns (); r != NULL_RTX; r = next_nonnote_nondebug_insn (r))
+  rtx_insn *r;
+
+  for (r = get_insns (); r != NULL; r = next_nonnote_nondebug_insn (r))
     {
-      rtx insn1, insn2;
+      rtx_insn *insn1, *insn2;
       struct liw_data liw1, liw2;
 
       insn1 = r;
@@ -3118,27 +3136,194 @@
 
       delete_insn (insn2);
 
+      rtx insn2_pat;
       if (liw1.op == LIW_OP_CMP)
-	insn2 = gen_cmp_liw (liw2.dest, liw2.src, liw1.dest, liw1.src,
-			     GEN_INT (liw2.op));
+	insn2_pat = gen_cmp_liw (liw2.dest, liw2.src, liw1.dest, liw1.src,
+				 GEN_INT (liw2.op));
       else if (liw2.op == LIW_OP_CMP)
-	insn2 = gen_liw_cmp (liw1.dest, liw1.src, liw2.dest, liw2.src,
-			     GEN_INT (liw1.op));
+	insn2_pat = gen_liw_cmp (liw1.dest, liw1.src, liw2.dest, liw2.src,
+				 GEN_INT (liw1.op));
       else
-	insn2 = gen_liw (liw1.dest, liw2.dest, liw1.src, liw2.src,
-			 GEN_INT (liw1.op), GEN_INT (liw2.op));
-
-      insn2 = emit_insn_after (insn2, insn1);
+	insn2_pat = gen_liw (liw1.dest, liw2.dest, liw1.src, liw2.src,
+			     GEN_INT (liw1.op), GEN_INT (liw2.op));
+
+      insn2 = emit_insn_after (insn2_pat, insn1);
       delete_insn (insn1);
       r = insn2;
     }
 }
 
+#define DUMP(reason, insn)			\
+  do						\
+    {						\
+      if (dump_file)				\
+	{					\
+	  fprintf (dump_file, reason "\n");	\
+	  if (insn != NULL_RTX)			\
+	    print_rtl_single (dump_file, insn);	\
+	  fprintf(dump_file, "\n");		\
+	}					\
+    }						\
+  while (0)
+
+/* Replace the BRANCH insn with a Lcc insn that goes to LABEL.
+   Insert a SETLB insn just before LABEL.  */
+
+static void
+mn10300_insert_setlb_lcc (rtx_insn *label, rtx_insn *branch)
+{
+  rtx lcc, comparison, cmp_reg;
+
+  if (LABEL_NUSES (label) > 1)
+    {
+      rtx_insn *insn;
+
+      /* This label is used both as an entry point to the loop
+	 and as a loop-back point for the loop.  We need to separate
+	 these two functions so that the SETLB happens upon entry,
+	 but the loop-back does not go to the SETLB instruction.  */
+      DUMP ("Inserting SETLB insn after:", label);
+      insn = emit_insn_after (gen_setlb (), label);
+      label = gen_label_rtx ();
+      emit_label_after (label, insn);
+      DUMP ("Created new loop-back label:", label);
+    }
+  else
+    {
+      DUMP ("Inserting SETLB insn before:", label);
+      emit_insn_before (gen_setlb (), label);
+    }
+
+  comparison = XEXP (SET_SRC (PATTERN (branch)), 0);
+  cmp_reg = XEXP (comparison, 0);
+  gcc_assert (REG_P (cmp_reg));
+
+  /* If the comparison has not already been split out of the branch
+     then do so now.  */
+  gcc_assert (REGNO (cmp_reg) == CC_REG);
+
+  if (GET_MODE (cmp_reg) == CC_FLOATmode)
+    lcc = gen_FLcc (comparison, label);
+  else
+    lcc = gen_Lcc (comparison, label);    
+
+  rtx_insn *jump = emit_jump_insn_before (lcc, branch);
+  mark_jump_label (XVECEXP (lcc, 0, 0), jump, 0);
+  JUMP_LABEL (jump) = label;
+  DUMP ("Replacing branch insn...", branch);
+  DUMP ("... with Lcc insn:", jump);
+  delete_insn (branch);
+}
+
+static bool
+mn10300_block_contains_call (basic_block block)
+{
+  rtx_insn *insn;
+
+  FOR_BB_INSNS (block, insn)
+    if (CALL_P (insn))
+      return true;
+
+  return false;
+}
+
+static bool
+mn10300_loop_contains_call_insn (loop_p loop)
+{
+  basic_block * bbs;
+  bool result = false;
+  unsigned int i;
+
+  bbs = get_loop_body (loop);
+
+  for (i = 0; i < loop->num_nodes; i++)
+    if (mn10300_block_contains_call (bbs[i]))
+      {
+	result = true;
+	break;
+      }
+
+  free (bbs);
+  return result;
+}
+
+static void
+mn10300_scan_for_setlb_lcc (void)
+{
+  loop_p loop;
+
+  DUMP ("Looking for loops that can use the SETLB insn", NULL_RTX);
+
+  df_analyze ();
+  compute_bb_for_insn ();
+
+  /* Find the loops.  */
+  loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
+
+  /* FIXME: For now we only investigate innermost loops.  In practice however
+     if an inner loop is not suitable for use with the SETLB/Lcc insns, it may
+     be the case that its parent loop is suitable.  Thus we should check all
+     loops, but work from the innermost outwards.  */
+  FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
+    {
+      const char * reason = NULL;
+
+      /* Check to see if we can modify this loop.  If we cannot
+	 then set 'reason' to describe why it could not be done.  */
+      if (loop->latch == NULL)
+	reason = "it contains multiple latches";
+      else if (loop->header != loop->latch)
+	/* FIXME: We could handle loops that span multiple blocks,
+	   but this requires a lot more work tracking down the branches
+	   that need altering, so for now keep things simple.  */
+	reason = "the loop spans multiple blocks";
+      else if (mn10300_loop_contains_call_insn (loop))
+	reason = "it contains CALL insns";
+      else
+	{
+	  rtx_insn *branch = BB_END (loop->latch);
+
+	  gcc_assert (JUMP_P (branch));
+	  if (single_set (branch) == NULL_RTX || ! any_condjump_p (branch))
+	    /* We cannot optimize tablejumps and the like.  */
+	    /* FIXME: We could handle unconditional jumps.  */
+	    reason = "it is not a simple loop";
+	  else
+	    {
+	      rtx_insn *label;
+
+	      if (dump_file)
+		flow_loop_dump (loop, dump_file, NULL, 0);
+
+	      label = BB_HEAD (loop->header);
+	      gcc_assert (LABEL_P (label));
+
+	      mn10300_insert_setlb_lcc (label, branch);
+	    }
+	}
+
+      if (dump_file && reason != NULL)
+	fprintf (dump_file, "Loop starting with insn %d is not suitable because %s\n",
+		 INSN_UID (BB_HEAD (loop->header)),
+		 reason);
+    }
+
+  loop_optimizer_finalize ();
+
+  df_finish_pass (false);  
+
+  DUMP ("SETLB scan complete", NULL_RTX);
+}
+
 static void
 mn10300_reorg (void)
 {
-  if (TARGET_AM33)
+  /* These are optimizations, so only run them if optimizing.  */
+  if (TARGET_AM33 && (optimize > 0 || optimize_size))
     {
+      if (TARGET_ALLOW_SETLB)
+	mn10300_scan_for_setlb_lcc ();
+
       if (TARGET_ALLOW_LIW)
 	mn10300_bundle_liw ();
     }
@@ -3149,9 +3334,6 @@
 #undef  TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG mn10300_reorg
 
-#undef  TARGET_EXCEPT_UNWIND_INFO
-#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info
-
 #undef  TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
 
@@ -3175,14 +3357,8 @@
 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA mn10300_asm_output_addr_const_extra
 
-#undef  TARGET_DEFAULT_TARGET_FLAGS
-#define TARGET_DEFAULT_TARGET_FLAGS MASK_MULT_BUG | MASK_PTR_A0D0 | MASK_ALLOW_LIW
-#undef  TARGET_HANDLE_OPTION
-#define TARGET_HANDLE_OPTION mn10300_handle_option
 #undef  TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE mn10300_option_override
-#undef  TARGET_OPTION_OPTIMIZATION_TABLE
-#define TARGET_OPTION_OPTIMIZATION_TABLE mn10300_option_optimization_table
 
 #undef  TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO mn10300_encode_section_info
@@ -3210,10 +3386,15 @@
 #undef  TARGET_CASE_VALUES_THRESHOLD
 #define TARGET_CASE_VALUES_THRESHOLD mn10300_case_values_threshold
 
+#undef TARGET_LRA_P
+#define TARGET_LRA_P hook_bool_void_false
+
 #undef  TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P	mn10300_legitimate_address_p
 #undef  TARGET_DELEGITIMIZE_ADDRESS
 #define TARGET_DELEGITIMIZE_ADDRESS	mn10300_delegitimize_address
+#undef  TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P	mn10300_legitimate_constant_p
 
 #undef  TARGET_PREFERRED_RELOAD_CLASS
 #define TARGET_PREFERRED_RELOAD_CLASS mn10300_preferred_reload_class
@@ -3242,10 +3423,16 @@
 #undef  TARGET_CONDITIONAL_REGISTER_USAGE
 #define TARGET_CONDITIONAL_REGISTER_USAGE mn10300_conditional_register_usage
 
-#undef TARGET_MD_ASM_CLOBBERS
-#define TARGET_MD_ASM_CLOBBERS  mn10300_md_asm_clobbers
+#undef TARGET_MD_ASM_ADJUST
+#define TARGET_MD_ASM_ADJUST mn10300_md_asm_adjust
 
 #undef  TARGET_FLAGS_REGNUM
 #define TARGET_FLAGS_REGNUM  CC_REG
 
+#undef  TARGET_HARD_REGNO_MODE_OK
+#define TARGET_HARD_REGNO_MODE_OK mn10300_hard_regno_mode_ok
+
+#undef  TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P mn10300_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;