OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / m68k.c
index 53b0926..25b8f0c 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines for insn-output.c for Motorola 68000 family.
    Copyright (C) 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2003, 2004
+   2001, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -17,8 +17,8 @@ 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.  */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -44,6 +44,18 @@ Boston, MA 02111-1307, USA.  */
 #include "debug.h"
 #include "flags.h"
 
+enum reg_class regno_reg_class[] =
+{
+  DATA_REGS, DATA_REGS, DATA_REGS, DATA_REGS,
+  DATA_REGS, DATA_REGS, DATA_REGS, DATA_REGS,
+  ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
+  ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  ADDR_REGS
+};
+
+
 /* The ASM_DOT macro allows easy string pasting to handle the differences
    between MOTOROLA and MIT syntaxes in asm_fprintf(), which doesn't
    support the %. option.  */
@@ -58,7 +70,7 @@ Boston, MA 02111-1307, USA.  */
 #endif
 
 
-/* Structure describing stack frame layout. */
+/* Structure describing stack frame layout.  */
 struct m68k_frame
 {
   /* Stack pointer to frame pointer offset.  */
@@ -91,21 +103,14 @@ struct m68k_frame
 /* Current frame information calculated by m68k_compute_frame_layout().  */
 static struct m68k_frame current_frame;
 
-/* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
-   if SGS_SWITCH_TABLE.  */
-int switch_table_difference_label_flag;
-
+static bool m68k_handle_option (size_t, const char *, int);
 static rtx find_addr_reg (rtx);
 static const char *singlemove_string (rtx *);
 static void m68k_output_function_prologue (FILE *, HOST_WIDE_INT);
 static void m68k_output_function_epilogue (FILE *, HOST_WIDE_INT);
 #ifdef M68K_TARGET_COFF
-static void m68k_coff_asm_named_section (const char *, unsigned int);
+static void m68k_coff_asm_named_section (const char *, unsigned int, tree);
 #endif /* M68K_TARGET_COFF */
-#ifdef HPUX_ASM
-static void m68k_hp320_internal_label (FILE *, const char *, unsigned long);
-static void m68k_hp320_file_start (void);
-#endif
 static void m68k_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
                                          HOST_WIDE_INT, tree);
 static rtx m68k_struct_value_rtx (tree, int);
@@ -119,22 +124,8 @@ static int const_int_cost (rtx);
 static bool m68k_rtx_costs (rtx, int, int, int *);
 \f
 
-/* Alignment to use for loops and jumps */
-/* Specify power of two alignment used for loops.  */
-const char *m68k_align_loops_string;
-/* Specify power of two alignment used for non-loop jumps.  */
-const char *m68k_align_jumps_string;
-/* Specify power of two alignment used for functions.  */
-const char *m68k_align_funcs_string;
 /* Specify the identification number of the library being built */
-const char *m68k_library_id_string;
-
-/* Specify power of two alignment used for loops.  */
-int m68k_align_loops;
-/* Specify power of two alignment used for non-loop jumps.  */
-int m68k_align_jumps;
-/* Specify power of two alignment used for functions.  */
-int m68k_align_funcs;
+const char *m68k_library_id_string = "_current_shared_library_a5_offset_";
 
 /* Nonzero if the last compare/test insn had FP operands.  The
    sCC expanders peek at this to determine what to do for the
@@ -175,10 +166,6 @@ int m68k_last_compare_had_fp_operands;
 #define TARGET_ASM_FUNCTION_PROLOGUE m68k_output_function_prologue
 #undef TARGET_ASM_FUNCTION_EPILOGUE
 #define TARGET_ASM_FUNCTION_EPILOGUE m68k_output_function_epilogue
-#ifdef HPUX_ASM
-#undef TARGET_ASM_INTERNAL_LABEL
-#define  TARGET_ASM_INTERNAL_LABEL m68k_hp320_internal_label
-#endif
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK m68k_output_mi_thunk
@@ -188,6 +175,11 @@ int m68k_last_compare_had_fp_operands;
 #undef TARGET_ASM_FILE_START_APP_OFF
 #define TARGET_ASM_FILE_START_APP_OFF true
 
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS MASK_STRICT_ALIGNMENT
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION m68k_handle_option
+
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS m68k_rtx_costs
 
@@ -209,6 +201,237 @@ static const struct attribute_spec m68k_attribute_table[] =
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
+/* Base flags for 68k ISAs.  */
+#define FL_FOR_isa_00    FL_ISA_68000
+#define FL_FOR_isa_10    (FL_FOR_isa_00 | FL_ISA_68010)
+/* FL_68881 controls the default setting of -m68881.  gcc has traditionally
+   generated 68881 code for 68020 and 68030 targets unless explicitly told
+   not to.  */
+#define FL_FOR_isa_20    (FL_FOR_isa_10 | FL_ISA_68020 \
+                         | FL_BITFIELD | FL_68881)
+#define FL_FOR_isa_40    (FL_FOR_isa_20 | FL_ISA_68040)
+#define FL_FOR_isa_cpu32 (FL_FOR_isa_10 | FL_ISA_68020)
+
+/* Base flags for ColdFire ISAs.  */
+#define FL_FOR_isa_a     (FL_COLDFIRE | FL_ISA_A)
+#define FL_FOR_isa_aplus (FL_FOR_isa_a | FL_ISA_APLUS | FL_CF_USP)
+/* Note ISA_B doesn't necessarily include USP (user stack pointer) support.  */
+#define FL_FOR_isa_b     (FL_FOR_isa_a | FL_ISA_B | FL_CF_HWDIV)
+#define FL_FOR_isa_c     (FL_FOR_isa_b | FL_ISA_C | FL_CF_USP)
+
+enum m68k_isa
+{
+  /* Traditional 68000 instruction sets.  */
+  isa_00,
+  isa_10,
+  isa_20,
+  isa_40,
+  isa_cpu32,
+  /* ColdFire instruction set variants.  */
+  isa_a,
+  isa_aplus,
+  isa_b,
+  isa_c,
+  isa_max
+};
+
+/* Information about one of the -march, -mcpu or -mtune arguments.  */
+struct m68k_target_selection
+{
+  /* The argument being described.  */
+  const char *name;
+
+  /* For -mcpu, this is the device selected by the option.
+     For -mtune and -march, it is a representative device
+     for the microarchitecture or ISA respectively.  */
+  enum target_device device;
+
+  /* The M68K_DEVICE fields associated with DEVICE.  See the comment
+     in m68k-devices.def for details.  FAMILY is only valid for -mcpu.  */
+  const char *family;
+  enum uarch_type microarch;
+  enum m68k_isa isa;
+  unsigned long flags;
+};
+
+/* A list of all devices in m68k-devices.def.  Used for -mcpu selection.  */
+static const struct m68k_target_selection all_devices[] =
+{
+#define M68K_DEVICE(NAME,ENUM_VALUE,FAMILY,MULTILIB,MICROARCH,ISA,FLAGS) \
+  { NAME, ENUM_VALUE, FAMILY, u##MICROARCH, ISA, FLAGS | FL_FOR_##ISA },
+#include "m68k-devices.def"
+#undef M68K_DEVICE
+  { NULL, unk_device, NULL, unk_arch, isa_max, 0 }
+};
+
+/* A list of all ISAs, mapping each one to a representative device.
+   Used for -march selection.  */
+static const struct m68k_target_selection all_isas[] =
+{
+  { "68000",    m68000,     NULL,  u68000,   isa_00,    FL_FOR_isa_00 },
+  { "68010",    m68010,     NULL,  u68010,   isa_10,    FL_FOR_isa_10 },
+  { "68020",    m68020,     NULL,  u68020,   isa_20,    FL_FOR_isa_20 },
+  { "68030",    m68030,     NULL,  u68030,   isa_20,    FL_FOR_isa_20 },
+  { "68040",    m68040,     NULL,  u68040,   isa_40,    FL_FOR_isa_40 },
+  { "68060",    m68060,     NULL,  u68060,   isa_40,    FL_FOR_isa_40 },
+  { "cpu32",    cpu32,      NULL,  ucpu32,   isa_20,    FL_FOR_isa_cpu32 },
+  { "isaa",     mcf5206e,   NULL,  ucfv2,    isa_a,     (FL_FOR_isa_a
+                                                        | FL_CF_HWDIV) },
+  { "isaaplus", mcf5271,    NULL,  ucfv2,    isa_aplus, (FL_FOR_isa_aplus
+                                                        | FL_CF_HWDIV) },
+  { "isab",     mcf5407,    NULL,  ucfv4,    isa_b,     FL_FOR_isa_b },
+  { "isac",     unk_device, NULL,  ucfv4,    isa_c,     (FL_FOR_isa_c
+                                                        | FL_CF_FPU
+                                                        | FL_CF_EMAC) },
+  { NULL,       unk_device, NULL,  unk_arch, isa_max,   0 }
+};
+
+/* A list of all microarchitectures, mapping each one to a representative
+   device.  Used for -mtune selection.  */
+static const struct m68k_target_selection all_microarchs[] =
+{
+  { "68000",    m68000,     NULL,  u68000,    isa_00,  FL_FOR_isa_00 },
+  { "68010",    m68010,     NULL,  u68010,    isa_10,  FL_FOR_isa_10 },
+  { "68020",    m68020,     NULL,  u68020,    isa_20,  FL_FOR_isa_20 },
+  { "68020-40", m68020,     NULL,  u68020_40, isa_20,  FL_FOR_isa_20 },
+  { "68020-60", m68020,     NULL,  u68020_60, isa_20,  FL_FOR_isa_20 },
+  { "68030",    m68030,     NULL,  u68030,    isa_20,  FL_FOR_isa_20 },
+  { "68040",    m68040,     NULL,  u68040,    isa_40,  FL_FOR_isa_40 },
+  { "68060",    m68060,     NULL,  u68060,    isa_40,  FL_FOR_isa_40 },
+  { "cpu32",    cpu32,      NULL,  ucpu32,    isa_20,  FL_FOR_isa_cpu32 },
+  { "cfv2",     mcf5206,    NULL,  ucfv2,     isa_a,   FL_FOR_isa_a },
+  { "cfv3",     mcf5307,    NULL,  ucfv3,     isa_a,   (FL_FOR_isa_a
+                                                       | FL_CF_HWDIV) },
+  { "cfv4",     mcf5407,    NULL,  ucfv4,     isa_b,   FL_FOR_isa_b },
+  { "cfv4e",    mcf547x,    NULL,  ucfv4e,    isa_b,   (FL_FOR_isa_b
+                                                       | FL_CF_USP
+                                                       | FL_CF_EMAC
+                                                       | FL_CF_FPU) },
+  { NULL,       unk_device, NULL,  unk_arch,  isa_max, 0 }
+};
+\f
+/* The entries associated with the -mcpu, -march and -mtune settings,
+   or null for options that have not been used.  */
+const struct m68k_target_selection *m68k_cpu_entry;
+const struct m68k_target_selection *m68k_arch_entry;
+const struct m68k_target_selection *m68k_tune_entry;
+
+/* Which CPU we are generating code for.  */
+enum target_device m68k_cpu;
+
+/* Which microarchitecture to tune for.  */
+enum uarch_type m68k_tune;
+
+/* Which FPU to use.  */
+enum fpu_type m68k_fpu;
+
+/* The set of FL_* flags that apply to the target processor.  */
+unsigned int m68k_cpu_flags;
+\f
+/* See whether TABLE has an entry with name NAME.  Return true and
+   store the entry in *ENTRY if so, otherwise return false and
+   leave *ENTRY alone.  */
+
+static bool
+m68k_find_selection (const struct m68k_target_selection **entry,
+                    const struct m68k_target_selection *table,
+                    const char *name)
+{
+  size_t i;
+
+  for (i = 0; table[i].name; i++)
+    if (strcmp (table[i].name, name) == 0)
+      {
+       *entry = table + i;
+       return true;
+      }
+  return false;
+}
+
+/* Implement TARGET_HANDLE_OPTION.  */
+
+static bool
+m68k_handle_option (size_t code, const char *arg, int value)
+{
+  switch (code)
+    {
+    case OPT_march_:
+      return m68k_find_selection (&m68k_arch_entry, all_isas, arg);
+
+    case OPT_mcpu_:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, arg);
+
+    case OPT_mtune_:
+      return m68k_find_selection (&m68k_tune_entry, all_microarchs, arg);
+
+    case OPT_m5200:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "5206");
+
+    case OPT_m5206e:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "5206e");
+
+    case OPT_m528x:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "528x");
+
+    case OPT_m5307:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "5307");
+
+    case OPT_m5407:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "5407");
+
+    case OPT_mcfv4e:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "547x");
+
+    case OPT_m68000:
+    case OPT_mc68000:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "68000");
+
+    case OPT_m68010:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "68010");
+
+    case OPT_m68020:
+    case OPT_mc68020:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "68020");
+
+    case OPT_m68020_40:
+      return (m68k_find_selection (&m68k_tune_entry, all_microarchs,
+                                  "68020-40")
+             && m68k_find_selection (&m68k_cpu_entry, all_devices, "68020"));
+
+    case OPT_m68020_60:
+      return (m68k_find_selection (&m68k_tune_entry, all_microarchs,
+                                  "68020-60")
+             && m68k_find_selection (&m68k_cpu_entry, all_devices, "68020"));
+
+    case OPT_m68030:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "68030");
+
+    case OPT_m68040:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "68040");
+
+    case OPT_m68060:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "68060");
+
+    case OPT_m68302:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "68302");
+
+    case OPT_m68332:
+    case OPT_mcpu32:
+      return m68k_find_selection (&m68k_cpu_entry, all_devices, "68332");
+
+    case OPT_mshared_library_id_:
+      if (value > MAX_LIBRARY_ID)
+       error ("-mshared-library-id=%s is not between 0 and %d",
+              arg, MAX_LIBRARY_ID);
+      else
+       asprintf ((char **) &m68k_library_id_string, "%d", (value * -4) - 4);
+      return true;
+
+    default:
+      return true;
+    }
+}
+
 /* Sometimes certain combinations of command options do not make
    sense on a particular target machine.  You can define a macro
    `OVERRIDE_OPTIONS' to take account of this.  This macro, if
@@ -221,40 +444,67 @@ struct gcc_target targetm = TARGET_INITIALIZER;
 void
 override_options (void)
 {
-  int def_align;
-  int i;
+  const struct m68k_target_selection *entry;
+  unsigned long target_mask;
 
-  def_align = 1;
+  /* User can choose:
 
-  /* Validate -malign-loops= value, or provide default */
-  m68k_align_loops = def_align;
-  if (m68k_align_loops_string)
-    {
-      i = atoi (m68k_align_loops_string);
-      if (i < 1 || i > MAX_CODE_ALIGN)
-       error ("-malign-loops=%d is not between 1 and %d", i, MAX_CODE_ALIGN);
-      else
-       m68k_align_loops = i;
-    }
+     -mcpu=
+     -march=
+     -mtune=
 
-  /* Library identification */
-  if (m68k_library_id_string)
+     -march=ARCH should generate code that runs any processor
+     implementing architecture ARCH.  -mcpu=CPU should override -march
+     and should generate code that runs on processor CPU, making free
+     use of any instructions that CPU understands.  -mtune=UARCH applies
+     on top of -mcpu or -march and optimises the code for UARCH.  It does
+     not change the target architecture.  */
+  if (m68k_cpu_entry)
     {
-      int id;
+      /* Complain if the -march setting is for a different microarchitecture,
+        or includes flags that the -mcpu setting doesn't.  */
+      if (m68k_arch_entry
+         && (m68k_arch_entry->microarch != m68k_cpu_entry->microarch
+             || (m68k_arch_entry->flags & ~m68k_cpu_entry->flags) != 0))
+       warning (0, "-mcpu=%s conflicts with -march=%s",
+                m68k_cpu_entry->name, m68k_arch_entry->name);
 
-      if (! TARGET_ID_SHARED_LIBRARY)
-       error ("-mshared-library-id= specified without -mid-shared-library");
-      id = atoi (m68k_library_id_string);
-      if (id < 0 || id > MAX_LIBRARY_ID)
-       error ("-mshared-library-id=%d is not between 0 and %d", id, MAX_LIBRARY_ID);
-
-      /* From now on, m68k_library_id_string will contain the library offset.  */
-      asprintf ((char **)&m68k_library_id_string, "%d", (id * -4) - 4);
+      entry = m68k_cpu_entry;
     }
   else
-    /* If TARGET_ID_SHARED_LIBRARY is enabled, this will point to the
-       current library.  */
-    m68k_library_id_string = "_current_shared_library_a5_offset_";
+    entry = m68k_arch_entry;
+
+  if (!entry)
+    entry = all_devices + TARGET_CPU_DEFAULT;
+
+  m68k_cpu_flags = entry->flags;
+
+  /* Use the architecture setting to derive default values for
+     certain flags.  */
+  target_mask = 0;
+  if ((m68k_cpu_flags & FL_BITFIELD) != 0)
+    target_mask |= MASK_BITFIELD;
+  if ((m68k_cpu_flags & FL_CF_HWDIV) != 0)
+    target_mask |= MASK_CF_HWDIV;
+  if ((m68k_cpu_flags & (FL_68881 | FL_CF_FPU)) != 0)
+    target_mask |= MASK_HARD_FLOAT;
+  target_flags |= target_mask & ~target_flags_explicit;
+
+  /* Set the directly-usable versions of the -mcpu and -mtune settings.  */
+  m68k_cpu = entry->device;
+  if (m68k_tune_entry)
+    m68k_tune = m68k_tune_entry->microarch;
+#ifdef M68K_DEFAULT_TUNE
+  else if (!m68k_cpu_entry && !m68k_arch_entry)
+    m68k_tune = M68K_DEFAULT_TUNE;
+#endif
+  else
+    m68k_tune = entry->microarch;
+
+  /* Set the type of FPU.  */
+  m68k_fpu = (!TARGET_HARD_FLOAT ? FPUTYPE_NONE
+             : (m68k_cpu_flags & FL_COLDFIRE) != 0 ? FPUTYPE_COLDFIRE
+             : FPUTYPE_68881);
 
   /* Sanity check to ensure that msep-data and mid-sahred-library are not
    * both specified together.  Doing so simply doesn't make sense.
@@ -269,33 +519,10 @@ override_options (void)
   if (TARGET_SEP_DATA || TARGET_ID_SHARED_LIBRARY)
     flag_pic = 2;
 
-  /* Validate -malign-jumps= value, or provide default */
-  m68k_align_jumps = def_align;
-  if (m68k_align_jumps_string)
-    {
-      i = atoi (m68k_align_jumps_string);
-      if (i < 1 || i > MAX_CODE_ALIGN)
-       error ("-malign-jumps=%d is not between 1 and %d", i, MAX_CODE_ALIGN);
-      else
-       m68k_align_jumps = i;
-    }
-
-  /* Validate -malign-functions= value, or provide default */
-  m68k_align_funcs = def_align;
-  if (m68k_align_funcs_string)
-    {
-      i = atoi (m68k_align_funcs_string);
-      if (i < 1 || i > MAX_CODE_ALIGN)
-       error ("-malign-functions=%d is not between 1 and %d",
-              i, MAX_CODE_ALIGN);
-      else
-       m68k_align_funcs = i;
-    }
-
-  /* -fPIC uses 32-bit pc-relative displacements, which don't exist
-     until the 68020.  */
-  if (!TARGET_68020 && !TARGET_COLDFIRE && (flag_pic == 2))
-    error("-fPIC is not currently supported on the 68000 or 68010\n");
+  /* -mpcrel -fPIC uses 32-bit pc-relative displacements.  Raise an
+     error if the target does not support them.  */
+  if (TARGET_PCREL && !TARGET_68020 && flag_pic == 2)
+    error ("-mpcrel -fPIC is not currently supported on selected cpu");
 
   /* ??? A historic way of turning on pic, or is this intended to
      be an embedded thing that doesn't have the same name binding
@@ -313,6 +540,30 @@ override_options (void)
 
   SUBTARGET_OVERRIDE_OPTIONS;
 }
+
+/* Generate a macro of the form __mPREFIX_cpu_NAME, where PREFIX is the
+   given argument and NAME is the argument passed to -mcpu.  Return NULL
+   if -mcpu was not passed.  */
+
+const char *
+m68k_cpp_cpu_ident (const char *prefix)
+{
+  if (!m68k_cpu_entry)
+    return NULL;
+  return concat ("__m", prefix, "_cpu_", m68k_cpu_entry->name, NULL);
+}
+
+/* Generate a macro of the form __mPREFIX_family_NAME, where PREFIX is the
+   given argument and NAME is the name of the representative device for
+   the -mcpu argument's family.  Return NULL if -mcpu was not passed.  */
+
+const char *
+m68k_cpp_cpu_family (const char *prefix)
+{
+  if (!m68k_cpu_entry)
+    return NULL;
+  return concat ("__m", prefix, "_family_", m68k_cpu_entry->family, NULL);
+}
 \f
 /* Return nonzero if FUNC is an interrupt function as specified by the
    "interrupt_handler" attribute.  */
@@ -338,7 +589,7 @@ m68k_handle_fndecl_attribute (tree *node, tree name,
 {
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
-      warning ("`%s' attribute only applies to functions",
+      warning (OPT_Wattributes, "%qs attribute only applies to functions",
               IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
@@ -376,7 +627,7 @@ m68k_compute_frame_layout (void)
 
   current_frame.foffset = 0;
   mask = rmask = saved = 0;
-  if (TARGET_68881 /* || TARGET_CFV4E */)
+  if (TARGET_HARD_FLOAT)
     {
       for (regno = 16; regno < 24; regno++)
        if (m68k_save_reg (regno, interrupt_handler))
@@ -385,7 +636,7 @@ m68k_compute_frame_layout (void)
            rmask |= 1 << (23 - regno);
            saved++;
          }
-      current_frame.foffset = saved * 12 /* (TARGET_CFV4E ? 8 : 12) */;
+      current_frame.foffset = saved * TARGET_FP_REG_SIZE;
       current_frame.offset += current_frame.foffset;
     }
   current_frame.fpu_no = saved;
@@ -399,20 +650,26 @@ m68k_compute_frame_layout (void)
 HOST_WIDE_INT
 m68k_initial_elimination_offset (int from, int to)
 {
-  /* FIXME: The correct offset to compute here would appear to be
-       (frame_pointer_needed ? -UNITS_PER_WORD * 2 : -UNITS_PER_WORD);
-     but for some obscure reason, this must be 0 to get correct code.  */
+  int argptr_offset;
+  /* The arg pointer points 8 bytes before the start of the arguments,
+     as defined by FIRST_PARM_OFFSET.  This makes it coincident with the
+     frame pointer in most frames.  */
+  argptr_offset = frame_pointer_needed ? 0 : UNITS_PER_WORD;
   if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
-    return 0;
+    return argptr_offset;
 
   m68k_compute_frame_layout ();
 
-  if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
-    return current_frame.offset + current_frame.size + (frame_pointer_needed ? -UNITS_PER_WORD * 2 : -UNITS_PER_WORD);
-  else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
-    return current_frame.offset + current_frame.size;
-
-  abort();
+  gcc_assert (to == STACK_POINTER_REGNUM);
+  switch (from)
+    {
+    case ARG_POINTER_REGNUM:
+      return current_frame.offset + current_frame.size - argptr_offset;
+    case FRAME_POINTER_REGNUM:
+      return current_frame.offset + current_frame.size;
+    default:
+      gcc_unreachable ();
+    }
 }
 
 /* Refer to the array `regs_ever_live' to determine which registers
@@ -424,9 +681,13 @@ m68k_initial_elimination_offset (int from, int to)
 static bool
 m68k_save_reg (unsigned int regno, bool interrupt_handler)
 {
-  if (flag_pic && current_function_uses_pic_offset_table
-      && regno == PIC_OFFSET_TABLE_REGNUM)
-    return true;
+  if (flag_pic && regno == PIC_OFFSET_TABLE_REGNUM)
+    {
+      if (current_function_uses_pic_offset_table)
+       return true;
+      if (!current_function_is_leaf && TARGET_ID_SHARED_LIBRARY)
+       return true;
+    }
 
   if (current_function_calls_eh_return)
     {
@@ -452,13 +713,13 @@ m68k_save_reg (unsigned int regno, bool interrupt_handler)
   /* Interrupt handlers must also save call_used_regs
      if they are live or when calling nested functions.  */
   if (interrupt_handler)
-  {
-     if (regs_ever_live[regno])
-       return true;
+    {
+      if (regs_ever_live[regno])
+       return true;
 
-     if (!current_function_is_leaf && call_used_regs[regno])
-       return true;
-  }
+      if (!current_function_is_leaf && call_used_regs[regno])
+       return true;
+    }
 
   /* Never need to save registers that aren't touched.  */
   if (!regs_ever_live[regno])
@@ -473,7 +734,8 @@ m68k_save_reg (unsigned int regno, bool interrupt_handler)
    SIZE is an int: how many units of temporary storage to allocate.  */
 
 static void
-m68k_output_function_prologue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+m68k_output_function_prologue (FILE *stream,
+                              HOST_WIDE_INT size ATTRIBUTE_UNUSED)
 {
   HOST_WIDE_INT fsize_with_regs;
   HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;
@@ -489,40 +751,36 @@ m68k_output_function_prologue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
 
   /* On ColdFire add register save into initial stack frame setup, if possible.  */
   fsize_with_regs = current_frame.size;
-  if (TARGET_COLDFIRE && current_frame.reg_no > 2)
-    fsize_with_regs += current_frame.reg_no * 4;
+  if (TARGET_COLDFIRE)
+    {
+      if (current_frame.reg_no > 2)
+       fsize_with_regs += current_frame.reg_no * 4;
+      if (current_frame.fpu_no)
+       fsize_with_regs += current_frame.fpu_no * 8;
+    }
 
   if (frame_pointer_needed)
     {
-      if (current_frame.size == 0 && TARGET_68040)
+      if (current_frame.size == 0 && TUNE_68040)
        /* on the 68040, pea + move is faster than link.w 0 */
-       fprintf (stream, MOTOROLA ?
-                          "\tpea (%s)\n\tmove.l %s,%s\n" :
-                          "\tpea %s@\n\tmovel %s,%s\n",
-                reg_names[FRAME_POINTER_REGNUM],
-                reg_names[STACK_POINTER_REGNUM],
-                reg_names[FRAME_POINTER_REGNUM]);
+       fprintf (stream, (MOTOROLA
+                         ? "\tpea (%s)\n\tmove.l %s,%s\n"
+                         : "\tpea %s@\n\tmovel %s,%s\n"),
+                M68K_REGNAME (FRAME_POINTER_REGNUM),
+                M68K_REGNAME (STACK_POINTER_REGNUM),
+                M68K_REGNAME (FRAME_POINTER_REGNUM));
       else if (fsize_with_regs < 0x8000)
        asm_fprintf (stream, "\tlink" ASM_DOTW " %s,%I%wd\n",
-                    reg_names[FRAME_POINTER_REGNUM], -fsize_with_regs);
+                    M68K_REGNAME (FRAME_POINTER_REGNUM), -fsize_with_regs);
       else if (TARGET_68020)
        asm_fprintf (stream, "\tlink" ASM_DOTL " %s,%I%wd\n",
-                    reg_names[FRAME_POINTER_REGNUM], -fsize_with_regs);
+                    M68K_REGNAME (FRAME_POINTER_REGNUM), -fsize_with_regs);
       else
        /* Adding negative number is faster on the 68040.  */
-       asm_fprintf (stream, "\tlink" ASM_DOTW " %s,%I0\n"
-                            "\tadd" ASM_DOT "l %I%wd,%Rsp\n",
-                    reg_names[FRAME_POINTER_REGNUM], -fsize_with_regs);
-
-      if (dwarf2out_do_frame ())
-       {
-         char *l;
-          l = (char *) dwarf2out_cfi_label ();   
-         cfa_offset += 4;
-         dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_offset);
-         dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, cfa_offset);
-         cfa_offset += current_frame.size;
-       }
+       asm_fprintf (stream,
+                    "\tlink" ASM_DOTW " %s,%I0\n"
+                    "\tadd" ASM_DOT "l %I%wd,%Rsp\n",
+                    M68K_REGNAME (FRAME_POINTER_REGNUM), -fsize_with_regs);
     }
   else if (fsize_with_regs) /* !frame_pointer_needed */
     {
@@ -537,65 +795,102 @@ m68k_output_function_prologue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
                asm_fprintf (stream, "\tsubq" ASM_DOT "l %I%wd,%Rsp\n",
                             fsize_with_regs);
            }
-         else if (fsize_with_regs <= 16 && TARGET_CPU32)
+         else if (fsize_with_regs <= 16 && TUNE_CPU32)
            /* On the CPU32 it is faster to use two subqw instructions to
               subtract a small integer (8 < N <= 16) to a register.  */
            asm_fprintf (stream,
                         "\tsubq" ASM_DOT "w %I8,%Rsp\n"
                         "\tsubq" ASM_DOT "w %I%wd,%Rsp\n",
                         fsize_with_regs - 8);
-         else if (TARGET_68040)
+         else if (TUNE_68040)
            /* Adding negative number is faster on the 68040.  */
            asm_fprintf (stream, "\tadd" ASM_DOT "w %I%wd,%Rsp\n",
                         -fsize_with_regs);
          else
-           asm_fprintf (stream, MOTOROLA ?
-                                  "\tlea (%wd,%Rsp),%Rsp\n" :
-                                  "\tlea %Rsp@(%wd),%Rsp\n",
+           asm_fprintf (stream, (MOTOROLA
+                                 ? "\tlea (%wd,%Rsp),%Rsp\n"
+                                 : "\tlea %Rsp@(%wd),%Rsp\n"),
                         -fsize_with_regs);
        }
       else /* fsize_with_regs >= 0x8000 */
-       asm_fprintf (stream, "\tadd" ASM_DOT "l %I%wd,%Rsp\n", -fsize_with_regs);
+       asm_fprintf (stream, "\tadd" ASM_DOT "l %I%wd,%Rsp\n",
+                    -fsize_with_regs);
+    } /* !frame_pointer_needed */
 
-      if (dwarf2out_do_frame ())
+  if (dwarf2out_do_frame ())
+    {
+      if (frame_pointer_needed)
        {
-         cfa_offset += current_frame.size + 4;
+         char *l;
+         l = (char *) dwarf2out_cfi_label ();
+         cfa_offset += 4;
+         dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_offset);
+         dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, cfa_offset);
+         cfa_offset += current_frame.size;
+        }
+      else
+        {
+         cfa_offset += current_frame.size;
          dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
-       }
-    } /* !frame_pointer_needed */
+        }
+    }
 
   if (current_frame.fpu_mask)
     {
-      asm_fprintf (stream, MOTOROLA ?
-                            "\tfmovm %I0x%x,-(%Rsp)\n" :
-                            "\tfmovem %I0x%x,%Rsp@-\n",
-                  current_frame.fpu_mask);
+      if (TARGET_68881)
+       {
+         asm_fprintf (stream, (MOTOROLA
+                               ? "\tfmovm %I0x%x,-(%Rsp)\n"
+                               : "\tfmovem %I0x%x,%Rsp@-\n"),
+                      current_frame.fpu_mask);
+       }
+      else
+       {
+         int offset;
+
+         /* stack already has registers in it.  Find the offset from
+            the bottom of stack to where the FP registers go */
+         if (current_frame.reg_no <= 2)
+           offset = 0;
+         else
+           offset = current_frame.reg_no * 4;
+         if (offset)
+           asm_fprintf (stream,
+                        "\tfmovem %I0x%x,%d(%Rsp)\n",
+                        current_frame.fpu_rev_mask,
+                        offset);
+         else
+           asm_fprintf (stream,
+                        "\tfmovem %I0x%x,(%Rsp)\n",
+                        current_frame.fpu_rev_mask);
+       }
 
       if (dwarf2out_do_frame ())
        {
          char *l = (char *) dwarf2out_cfi_label ();
          int n_regs, regno;
 
-         cfa_offset += current_frame.fpu_no * 12;
+         cfa_offset += current_frame.fpu_no * TARGET_FP_REG_SIZE;
          if (! frame_pointer_needed)
            dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
          for (regno = 16, n_regs = 0; regno < 24; regno++)
            if (current_frame.fpu_mask & (1 << (regno - 16)))
-             dwarf2out_reg_save (l, regno, -cfa_offset + n_regs++ * 12);
+             dwarf2out_reg_save (l, regno, -cfa_offset
+                                 + n_regs++ * TARGET_FP_REG_SIZE);
        }
     }
 
-  /* If the stack limit is not a symbol, check it here.  
+  /* If the stack limit is not a symbol, check it here.
      This has the disadvantage that it may be too late...  */
   if (current_function_limit_stack)
     {
       if (REG_P (stack_limit_rtx))
        asm_fprintf (stream, "\tcmp" ASM_DOT "l %s,%Rsp\n\ttrapcs\n",
-                    reg_names[REGNO (stack_limit_rtx)]);
+                    M68K_REGNAME (REGNO (stack_limit_rtx)));
       else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF)
-       warning ("stack limit expression is not supported");
+       warning (0, "stack limit expression is not supported");
     }
-  
+
   if (current_frame.reg_no <= 2)
     {
       /* Store each separately in the same order moveml uses.
@@ -608,38 +903,38 @@ m68k_output_function_prologue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
       for (i = 0; i < 16; i++)
         if (current_frame.reg_rev_mask & (1 << i))
          {
-           asm_fprintf (stream, MOTOROLA ?
-                                  "\t%Omove.l %s,-(%Rsp)\n" :
-                                  "\tmovel %s,%Rsp@-\n",
-                        reg_names[15 - i]);
+           asm_fprintf (stream, (MOTOROLA
+                                 ? "\t%Omove.l %s,-(%Rsp)\n"
+                                 : "\tmovel %s,%Rsp@-\n"),
+                        M68K_REGNAME (15 - i));
            if (dwarf2out_do_frame ())
              {
                char *l = (char *) dwarf2out_cfi_label ();
 
                cfa_offset += 4;
-               if (! frame_pointer_needed)
-                 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
-               dwarf2out_reg_save (l, 15 - i, -cfa_offset);
+               if (! frame_pointer_needed)
+                 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
+               dwarf2out_reg_save (l, 15 - i, -cfa_offset);
              }
          }
     }
   else if (current_frame.reg_rev_mask)
     {
       if (TARGET_COLDFIRE)
-       /* The ColdFire does not support the predecrement form of the 
+       /* The ColdFire does not support the predecrement form of the
           MOVEM instruction, so we must adjust the stack pointer and
           then use the plain address register indirect mode.
           The required register save space was combined earlier with
           the fsize_with_regs amount.  */
 
-       asm_fprintf (stream, MOTOROLA ?
-                              "\tmovm.l %I0x%x,(%Rsp)\n" :
-                              "\tmoveml %I0x%x,%Rsp@\n",
+       asm_fprintf (stream, (MOTOROLA
+                             ? "\tmovm.l %I0x%x,(%Rsp)\n"
+                             : "\tmoveml %I0x%x,%Rsp@\n"),
                     current_frame.reg_mask);
       else
-       asm_fprintf (stream, MOTOROLA ?
-                              "\tmovm.l %I0x%x,-(%Rsp)\n" :
-                              "\tmoveml %I0x%x,%Rsp@-\n",
+       asm_fprintf (stream, (MOTOROLA
+                             ? "\tmovm.l %I0x%x,-(%Rsp)\n"
+                             : "\tmoveml %I0x%x,%Rsp@-\n"),
                     current_frame.reg_rev_mask);
       if (dwarf2out_do_frame ())
        {
@@ -654,29 +949,30 @@ m68k_output_function_prologue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
              dwarf2out_reg_save (l, regno, -cfa_offset + n_regs++ * 4);
        }
     }
-  if (!TARGET_SEP_DATA && flag_pic &&
-      (current_function_uses_pic_offset_table ||
-        (!current_function_is_leaf && TARGET_ID_SHARED_LIBRARY)))
+  if (!TARGET_SEP_DATA && flag_pic
+      && (current_function_uses_pic_offset_table
+         || (!current_function_is_leaf && TARGET_ID_SHARED_LIBRARY)))
     {
       if (TARGET_ID_SHARED_LIBRARY)
        {
          asm_fprintf (stream, "\tmovel %s@(%s), %s\n",
-                      reg_names[PIC_OFFSET_TABLE_REGNUM],
+                      M68K_REGNAME (PIC_OFFSET_TABLE_REGNUM),
                       m68k_library_id_string,
-                      reg_names[PIC_OFFSET_TABLE_REGNUM]);
+                      M68K_REGNAME (PIC_OFFSET_TABLE_REGNUM));
        }
       else
        {
          if (MOTOROLA)
-           asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
-                        reg_names[PIC_OFFSET_TABLE_REGNUM]);
+           asm_fprintf (stream,
+                        "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
+                        M68K_REGNAME (PIC_OFFSET_TABLE_REGNUM));
          else
            {
              asm_fprintf (stream, "\tmovel %I%U_GLOBAL_OFFSET_TABLE_, %s\n",
-                          reg_names[PIC_OFFSET_TABLE_REGNUM]);
+                          M68K_REGNAME (PIC_OFFSET_TABLE_REGNUM));
              asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
-                          reg_names[PIC_OFFSET_TABLE_REGNUM],
-                          reg_names[PIC_OFFSET_TABLE_REGNUM]);
+                          M68K_REGNAME (PIC_OFFSET_TABLE_REGNUM),
+                          M68K_REGNAME (PIC_OFFSET_TABLE_REGNUM));
            }
        }
     }
@@ -692,7 +988,7 @@ use_return_insn (void)
 
   /* We can output the epilogue as RTL only if no registers need to be
      restored.  */
-  m68k_compute_frame_layout();
+  m68k_compute_frame_layout ();
   return current_frame.reg_no ? false : true;
 }
 
@@ -705,14 +1001,15 @@ use_return_insn (void)
    omit stack adjustments before returning.  */
 
 static void
-m68k_output_function_epilogue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+m68k_output_function_epilogue (FILE *stream,
+                              HOST_WIDE_INT size ATTRIBUTE_UNUSED)
 {
   HOST_WIDE_INT fsize, fsize_with_regs;
   bool big = false;
   bool restore_from_sp = false;
   rtx insn = get_last_insn ();
 
-  m68k_compute_frame_layout();
+  m68k_compute_frame_layout ();
 
   /* If the last insn was a BARRIER, we don't have to write any code.  */
   if (GET_CODE (insn) == NOTE)
@@ -731,11 +1028,12 @@ m68k_output_function_epilogue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
 
   fsize = current_frame.size;
 
-  /* FIXME : leaf_function_p below is too strong.
+  /* FIXME: leaf_function_p below is too strong.
      What we really need to know there is if there could be pending
      stack adjustment needed at that point.  */
-  restore_from_sp = ! frame_pointer_needed
-            || (! current_function_calls_alloca && leaf_function_p ());
+  restore_from_sp
+    = (! frame_pointer_needed
+       || (! current_function_calls_alloca && leaf_function_p ()));
 
   /* fsize_with_regs is the size we need to adjust the sp when
      popping the frame.  */
@@ -746,8 +1044,13 @@ m68k_output_function_epilogue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
      after restoring registers. When the frame pointer isn't used,
      we can merge movem adjustment into frame unlinking
      made immediately after it.  */
-  if (TARGET_COLDFIRE && restore_from_sp && (current_frame.reg_no > 2))
-    fsize_with_regs += current_frame.reg_no * 4;
+  if (TARGET_COLDFIRE && restore_from_sp)
+    {
+      if (current_frame.reg_no > 2)
+       fsize_with_regs += current_frame.reg_no * 4;
+      if (current_frame.fpu_no)
+       fsize_with_regs += current_frame.fpu_no * 8;
+    }
 
   if (current_frame.offset + fsize >= 0x8000
       && ! restore_from_sp
@@ -779,64 +1082,65 @@ m68k_output_function_epilogue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
                if (MOTOROLA)
                  asm_fprintf (stream, "\t%Omove.l -%wd(%s,%Ra1.l),%s\n",
                               offset,
-                              reg_names[FRAME_POINTER_REGNUM],
-                              reg_names[i]);
+                              M68K_REGNAME (FRAME_POINTER_REGNUM),
+                              M68K_REGNAME (i));
                else
                  asm_fprintf (stream, "\tmovel %s@(-%wd,%Ra1:l),%s\n",
-                              reg_names[FRAME_POINTER_REGNUM],
+                              M68K_REGNAME (FRAME_POINTER_REGNUM),
                               offset,
-                              reg_names[i]);
+                              M68K_REGNAME (i));
              }
             else if (restore_from_sp)
-             asm_fprintf (stream, MOTOROLA ?
-                                    "\t%Omove.l (%Rsp)+,%s\n" :
-                                    "\tmovel %Rsp@+,%s\n",
-                          reg_names[i]);
+             asm_fprintf (stream, (MOTOROLA
+                                   ? "\t%Omove.l (%Rsp)+,%s\n"
+                                   : "\tmovel %Rsp@+,%s\n"),
+                          M68K_REGNAME (i));
             else
              {
                if (MOTOROLA)
                  asm_fprintf (stream, "\t%Omove.l -%wd(%s),%s\n",
                               offset,
-                              reg_names[FRAME_POINTER_REGNUM],
-                              reg_names[i]);
+                              M68K_REGNAME (FRAME_POINTER_REGNUM),
+                              M68K_REGNAME (i));
                else
                  asm_fprintf (stream, "\tmovel %s@(-%wd),%s\n",
-                              reg_names[FRAME_POINTER_REGNUM],
+                              M68K_REGNAME (FRAME_POINTER_REGNUM),
                               offset,
-                              reg_names[i]);
+                              M68K_REGNAME (i));
              }
             offset -= 4;
           }
     }
   else if (current_frame.reg_mask)
     {
-      /* The ColdFire requires special handling due to its limited moveml insn.  */
+      /* The ColdFire requires special handling due to its limited moveml
+        insn.  */
       if (TARGET_COLDFIRE)
         {
           if (big)
             {
               asm_fprintf (stream, "\tadd" ASM_DOT "l %s,%Ra1\n",
-                          reg_names[FRAME_POINTER_REGNUM]);
-              asm_fprintf (stream, MOTOROLA ?
-                                    "\tmovm.l (%Ra1),%I0x%x\n" :
-                                    "\tmoveml %Ra1@,%I0x%x\n",
+                          M68K_REGNAME (FRAME_POINTER_REGNUM));
+              asm_fprintf (stream, (MOTOROLA
+                                   ? "\tmovm.l (%Ra1),%I0x%x\n"
+                                   : "\tmoveml %Ra1@,%I0x%x\n"),
                           current_frame.reg_mask);
             }
           else if (restore_from_sp)
-            asm_fprintf (stream, MOTOROLA ?
-                                   "\tmovm.l (%Rsp),%I0x%x\n" :
-                                   "\tmoveml %Rsp@,%I0x%x\n",
+            asm_fprintf (stream, (MOTOROLA
+                                  ? "\tmovm.l (%Rsp),%I0x%x\n"
+                                  : "\tmoveml %Rsp@,%I0x%x\n"),
                          current_frame.reg_mask);
           else
             {
              if (MOTOROLA)
                asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n",
                             current_frame.offset + fsize,
-                            reg_names[FRAME_POINTER_REGNUM],
+                            M68K_REGNAME (FRAME_POINTER_REGNUM),
                             current_frame.reg_mask);
              else
                asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n",
-                            reg_names[FRAME_POINTER_REGNUM],
+                            M68K_REGNAME (FRAME_POINTER_REGNUM),
                             current_frame.offset + fsize,
                             current_frame.reg_mask);
            }
@@ -848,19 +1152,19 @@ m68k_output_function_epilogue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
              if (MOTOROLA)
                asm_fprintf (stream, "\tmovm.l -%wd(%s,%Ra1.l),%I0x%x\n",
                             current_frame.offset + fsize,
-                            reg_names[FRAME_POINTER_REGNUM],
+                            M68K_REGNAME (FRAME_POINTER_REGNUM),
                             current_frame.reg_mask);
              else
                asm_fprintf (stream, "\tmoveml %s@(-%wd,%Ra1:l),%I0x%x\n",
-                            reg_names[FRAME_POINTER_REGNUM],
+                            M68K_REGNAME (FRAME_POINTER_REGNUM),
                             current_frame.offset + fsize,
                             current_frame.reg_mask);
            }
          else if (restore_from_sp)
            {
-             asm_fprintf (stream, MOTOROLA ?
-                                    "\tmovm.l (%Rsp)+,%I0x%x\n" :
-                                    "\tmoveml %Rsp@+,%I0x%x\n",
+             asm_fprintf (stream, (MOTOROLA
+                                   ? "\tmovm.l (%Rsp)+,%I0x%x\n"
+                                   : "\tmoveml %Rsp@+,%I0x%x\n"),
                           current_frame.reg_mask);
            }
          else
@@ -868,11 +1172,11 @@ m68k_output_function_epilogue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
              if (MOTOROLA)
                asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n",
                             current_frame.offset + fsize,
-                            reg_names[FRAME_POINTER_REGNUM],
+                            M68K_REGNAME (FRAME_POINTER_REGNUM),
                             current_frame.reg_mask);
              else
                asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n",
-                            reg_names[FRAME_POINTER_REGNUM],
+                            M68K_REGNAME (FRAME_POINTER_REGNUM),
                             current_frame.offset + fsize,
                             current_frame.reg_mask);
            }
@@ -882,43 +1186,74 @@ m68k_output_function_epilogue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
     {
       if (big)
        {
-         if (MOTOROLA)
+         if (TARGET_COLDFIRE)
+           {
+             if (current_frame.reg_no)
+               asm_fprintf (stream, MOTOROLA ?
+                            "\tfmovem.d %d(%Ra1),%I0x%x\n" :
+                            "\tfmovmd (%d,%Ra1),%I0x%x\n",
+                            current_frame.reg_no * 4,
+                            current_frame.fpu_rev_mask);
+             else
+               asm_fprintf (stream, MOTOROLA ?
+                            "\tfmovem.d (%Ra1),%I0x%x\n" :
+                            "\tfmovmd (%Ra1),%I0x%x\n",
+                            current_frame.fpu_rev_mask);
+           }
+         else if (MOTOROLA)
            asm_fprintf (stream, "\tfmovm -%wd(%s,%Ra1.l),%I0x%x\n",
                         current_frame.foffset + fsize,
-                        reg_names[FRAME_POINTER_REGNUM],
+                        M68K_REGNAME (FRAME_POINTER_REGNUM),
                         current_frame.fpu_rev_mask);
          else
            asm_fprintf (stream, "\tfmovem %s@(-%wd,%Ra1:l),%I0x%x\n",
-                        reg_names[FRAME_POINTER_REGNUM],
+                        M68K_REGNAME (FRAME_POINTER_REGNUM),
                         current_frame.foffset + fsize,
                         current_frame.fpu_rev_mask);
        }
       else if (restore_from_sp)
        {
-         if (MOTOROLA)
-           asm_fprintf (stream, "\tfmovm (%Rsp)+,%I0x%x\n",
-                        current_frame.fpu_rev_mask);
+         if (TARGET_COLDFIRE)
+           {
+             int offset;
+
+             /* Stack already has registers in it.  Find the offset from
+                the bottom of stack to where the FP registers go.  */
+             if (current_frame.reg_no <= 2)
+               offset = 0;
+             else
+               offset = current_frame.reg_no * 4;
+             if (offset)
+               asm_fprintf (stream,
+                            "\tfmovem %Rsp@(%d), %I0x%x\n",
+                            offset, current_frame.fpu_rev_mask);
+             else
+               asm_fprintf (stream,
+                            "\tfmovem %Rsp@, %I0x%x\n",
+                            current_frame.fpu_rev_mask);
+           }
          else
-           asm_fprintf (stream, "\tfmovem %Rsp@+,%I0x%x\n",
+           asm_fprintf (stream, MOTOROLA ?
+                        "\tfmovm (%Rsp)+,%I0x%x\n" :
+                        "\tfmovem %Rsp@+,%I0x%x\n",
                         current_frame.fpu_rev_mask);
        }
       else
        {
-         if (MOTOROLA)
+         if (MOTOROLA && !TARGET_COLDFIRE)
            asm_fprintf (stream, "\tfmovm -%wd(%s),%I0x%x\n",
                         current_frame.foffset + fsize,
-                        reg_names[FRAME_POINTER_REGNUM],
+                        M68K_REGNAME (FRAME_POINTER_REGNUM),
                         current_frame.fpu_rev_mask);
          else
            asm_fprintf (stream, "\tfmovem %s@(-%wd),%I0x%x\n",
-                        reg_names[FRAME_POINTER_REGNUM],
+                        M68K_REGNAME (FRAME_POINTER_REGNUM),
                         current_frame.foffset + fsize,
                         current_frame.fpu_rev_mask);
        }
     }
   if (frame_pointer_needed)
-    fprintf (stream, "\tunlk %s\n",
-            reg_names[FRAME_POINTER_REGNUM]);
+    fprintf (stream, "\tunlk %s\n", M68K_REGNAME (FRAME_POINTER_REGNUM));
   else if (fsize_with_regs)
     {
       if (fsize_with_regs <= 8)
@@ -930,30 +1265,31 @@ m68k_output_function_epilogue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
            asm_fprintf (stream, "\taddq" ASM_DOT "l %I%wd,%Rsp\n",
                         fsize_with_regs);
        }
-      else if (fsize_with_regs <= 16 && TARGET_CPU32)
+      else if (fsize_with_regs <= 16 && TUNE_CPU32)
        {
          /* On the CPU32 it is faster to use two addqw instructions to
             add a small integer (8 < N <= 16) to a register.  */
-         asm_fprintf (stream, "\taddq" ASM_DOT "w %I8,%Rsp\n"
-                              "\taddq" ASM_DOT "w %I%wd,%Rsp\n",
+         asm_fprintf (stream,
+                      "\taddq" ASM_DOT "w %I8,%Rsp\n"
+                      "\taddq" ASM_DOT "w %I%wd,%Rsp\n",
                       fsize_with_regs - 8);
        }
       else if (fsize_with_regs < 0x8000)
        {
-         if (TARGET_68040)
+         if (TUNE_68040)
            asm_fprintf (stream, "\tadd" ASM_DOT "w %I%wd,%Rsp\n",
                         fsize_with_regs);
          else
-           asm_fprintf (stream, MOTOROLA ?
-                                  "\tlea (%wd,%Rsp),%Rsp\n" :
-                                  "\tlea %Rsp@(%wd),%Rsp\n",
+           asm_fprintf (stream, (MOTOROLA
+                                 ? "\tlea (%wd,%Rsp),%Rsp\n"
+                                 : "\tlea %Rsp@(%wd),%Rsp\n"),
                         fsize_with_regs);
        }
       else
        asm_fprintf (stream, "\tadd" ASM_DOT "l %I%wd,%Rsp\n", fsize_with_regs);
     }
   if (current_function_calls_eh_return)
-    asm_fprintf (stream, "\tadd" ASM_DOT"l %Ra0,%Rsp\n");
+    asm_fprintf (stream, "\tadd" ASM_DOT "l %Ra0,%Rsp\n");
   if (m68k_interrupt_function_p (current_function_decl))
     fprintf (stream, "\trte\n");
   else if (current_function_pops_args)
@@ -962,14 +1298,6 @@ m68k_output_function_epilogue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED
     fprintf (stream, "\trts\n");
 }
 \f
-/* Similar to general_operand, but exclude stack_pointer_rtx.  */
-
-int
-not_sp_operand (rtx op, enum machine_mode mode)
-{
-  return op != stack_pointer_rtx && nonimmediate_operand (op, mode);
-}
-
 /* Return true if X is a valid comparison operator for the dbcc 
    instruction.  
 
@@ -979,7 +1307,7 @@ not_sp_operand (rtx op, enum machine_mode mode)
    It also rejects some comparisons when CC_NO_OVERFLOW is set.  */
    
 int
-valid_dbcc_comparison_p (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
+valid_dbcc_comparison_p_2 (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   switch (GET_CODE (x))
     {
@@ -1006,25 +1334,21 @@ flags_in_68881 (void)
 
 /* Output a BSR instruction suitable for PIC code.  */
 void
-m68k_output_pic_call(rtx dest)
+m68k_output_pic_call (rtx dest)
 {
   const char *out;
 
   if (!(GET_CODE (dest) == MEM && GET_CODE (XEXP (dest, 0)) == SYMBOL_REF))
     out = "jsr %0";
-      /* We output a BSR instruction if we're using -fpic or we're building for
-       * a target that supports long branches.  If we're building -fPIC on the
-       * 68000, 68010 or ColdFire we generate one of two sequences:
-       * a shorter one that uses a GOT entry or a longer one that doesn't.
-       * We'll use the -Os command-line flag to decide which to generate.
-       * Both sequences take the same time to execute on the ColdFire.
-       */
+      /* We output a BSR instruction if we're building for a target that
+        supports long branches.  Otherwise we generate one of two sequences:
+        a shorter one that uses a GOT entry or a longer one that doesn't.
+        We'll use the -Os command-line flag to decide which to generate.
+        Both sequences take the same time to execute on the ColdFire.  */
   else if (TARGET_PCREL)
     out = "bsr.l %o0";
-  else if ((flag_pic == 1) || TARGET_68020)
-#ifdef HPUX_ASM
-    out = "bsr.l %0";
-#elif defined(USE_GAS)
+  else if (TARGET_68020)
+#if defined(USE_GAS)
     out = "bsr.l %0@PLTPC";
 #else
     out = "bsr %0@PLTPC";
@@ -1034,7 +1358,7 @@ m68k_output_pic_call(rtx dest)
   else
     out = "lea %0-.-8,%%a1\n\tjsr 0(%%pc,%%a1)";
 
-  output_asm_insn(out, &dest);
+  output_asm_insn (out, &dest);
 }
 
 /* Output a dbCC; jCC sequence.  Note we do not handle the 
@@ -1049,77 +1373,77 @@ output_dbcc_and_branch (rtx *operands)
   switch (GET_CODE (operands[3]))
     {
       case EQ:
-       output_asm_insn (MOTOROLA ?
-                          "dbeq %0,%l1\n\tjbeq %l2" :
-                          "dbeq %0,%l1\n\tjeq %l2",
+       output_asm_insn (MOTOROLA
+                        ? "dbeq %0,%l1\n\tjbeq %l2"
+                        : "dbeq %0,%l1\n\tjeq %l2",
                         operands);
        break;
 
       case NE:
-       output_asm_insn (MOTOROLA ?
-                          "dbne %0,%l1\n\tjbne %l2" :
-                          "dbne %0,%l1\n\tjne %l2",
+       output_asm_insn (MOTOROLA
+                        ? "dbne %0,%l1\n\tjbne %l2"
+                        : "dbne %0,%l1\n\tjne %l2",
                         operands);
        break;
 
       case GT:
-       output_asm_insn (MOTOROLA ?
-                          "dbgt %0,%l1\n\tjbgt %l2" :
-                          "dbgt %0,%l1\n\tjgt %l2",
+       output_asm_insn (MOTOROLA
+                        ? "dbgt %0,%l1\n\tjbgt %l2"
+                        : "dbgt %0,%l1\n\tjgt %l2",
                         operands);
        break;
 
       case GTU:
-       output_asm_insn (MOTOROLA ?
-                          "dbhi %0,%l1\n\tjbhi %l2" :
-                          "dbhi %0,%l1\n\tjhi %l2",
+       output_asm_insn (MOTOROLA
+                        ? "dbhi %0,%l1\n\tjbhi %l2"
+                        : "dbhi %0,%l1\n\tjhi %l2",
                         operands);
        break;
 
       case LT:
-       output_asm_insn (MOTOROLA ?
-                          "dblt %0,%l1\n\tjblt %l2" :
-                          "dblt %0,%l1\n\tjlt %l2",
+       output_asm_insn (MOTOROLA
+                        ? "dblt %0,%l1\n\tjblt %l2"
+                        : "dblt %0,%l1\n\tjlt %l2",
                         operands);
        break;
 
       case LTU:
-       output_asm_insn (MOTOROLA ?
-                          "dbcs %0,%l1\n\tjbcs %l2" :
-                          "dbcs %0,%l1\n\tjcs %l2",
+       output_asm_insn (MOTOROLA
+                        ? "dbcs %0,%l1\n\tjbcs %l2"
+                        : "dbcs %0,%l1\n\tjcs %l2",
                         operands);
        break;
 
       case GE:
-       output_asm_insn (MOTOROLA ?
-                          "dbge %0,%l1\n\tjbge %l2" :
-                          "dbge %0,%l1\n\tjge %l2",
+       output_asm_insn (MOTOROLA
+                        ? "dbge %0,%l1\n\tjbge %l2"
+                        : "dbge %0,%l1\n\tjge %l2",
                         operands);
        break;
 
       case GEU:
-       output_asm_insn (MOTOROLA ?
-                          "dbcc %0,%l1\n\tjbcc %l2" :
-                          "dbcc %0,%l1\n\tjcc %l2",
+       output_asm_insn (MOTOROLA
+                        ? "dbcc %0,%l1\n\tjbcc %l2"
+                        : "dbcc %0,%l1\n\tjcc %l2",
                         operands);
        break;
 
       case LE:
-       output_asm_insn (MOTOROLA ?
-                          "dble %0,%l1\n\tjble %l2" :
-                          "dble %0,%l1\n\tjle %l2",
+       output_asm_insn (MOTOROLA
+                        ? "dble %0,%l1\n\tjble %l2"
+                        : "dble %0,%l1\n\tjle %l2",
                         operands);
        break;
 
       case LEU:
-       output_asm_insn (MOTOROLA ?
-                          "dbls %0,%l1\n\tjbls %l2" : 
-                          "dbls %0,%l1\n\tjls %l2",
+       output_asm_insn (MOTOROLA
+                        ? "dbls %0,%l1\n\tjbls %l2"
+                        : "dbls %0,%l1\n\tjls %l2",
                         operands);
        break;
 
       default:
-       abort ();
+       gcc_unreachable ();
     }
 
   /* If the decrement is to be done in SImode, then we have
@@ -1127,9 +1451,9 @@ output_dbcc_and_branch (rtx *operands)
   switch (GET_MODE (operands[0]))
     {
       case SImode:
-        output_asm_insn (MOTOROLA ?
-                          "clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1" :
-                          "clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1",
+        output_asm_insn (MOTOROLA
+                        ? "clr%.w %0\n\tsubq%.l #1,%0\n\tjbpl %l1"
+                        : "clr%.w %0\n\tsubq%.l #1,%0\n\tjpl %l1",
                         operands);
         break;
 
@@ -1137,12 +1461,12 @@ output_dbcc_and_branch (rtx *operands)
         break;
 
       default:
-        abort ();
+        gcc_unreachable ();
     }
 }
 
 const char *
-output_scc_di(rtx op, rtx operand1, rtx operand2, rtx dest)
+output_scc_di (rtx op, rtx operand1, rtx operand2, rtx dest)
 {
   rtx loperands[7];
   enum rtx_code op_code = GET_CODE (op);
@@ -1174,143 +1498,115 @@ output_scc_di(rtx op, rtx operand1, rtx operand2, rtx dest)
       else
        loperands[3] = adjust_address (operand2, SImode, 4);
     }
-  loperands[4] = gen_label_rtx();
+  loperands[4] = gen_label_rtx ();
   if (operand2 != const0_rtx)
     {
-      if (MOTOROLA)
-#ifdef SGS_CMP_ORDER
-        output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands);
-#else
-        output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands);
-#endif
-      else
-#ifdef SGS_CMP_ORDER
-        output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands);
-#else
-        output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands);
-#endif
+      output_asm_insn (MOTOROLA
+                      ? "cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1"
+                      : "cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1",
+                      loperands);
     }
   else
     {
       if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (loperands[0]))
        output_asm_insn ("tst%.l %0", loperands);
       else
-       {
-#ifdef SGS_CMP_ORDER
-         output_asm_insn ("cmp%.w %0,%#0", loperands);
-#else
-         output_asm_insn ("cmp%.w %#0,%0", loperands);
-#endif
-       }
+       output_asm_insn ("cmp%.w #0,%0", loperands);
 
       output_asm_insn (MOTOROLA ? "jbne %l4" : "jne %l4", loperands);
 
       if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (loperands[1]))
        output_asm_insn ("tst%.l %1", loperands);
       else
-       {
-#ifdef SGS_CMP_ORDER
-         output_asm_insn ("cmp%.w %1,%#0", loperands);
-#else
-         output_asm_insn ("cmp%.w %#0,%1", loperands);
-#endif
-       }
+       output_asm_insn ("cmp%.w #0,%1", loperands);
     }
 
   loperands[5] = dest;
-  
+
   switch (op_code)
     {
       case EQ:
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[4]));
+                                          CODE_LABEL_NUMBER (loperands[4]));
         output_asm_insn ("seq %5", loperands);
         break;
 
       case NE:
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[4]));
+                                          CODE_LABEL_NUMBER (loperands[4]));
         output_asm_insn ("sne %5", loperands);
         break;
 
       case GT:
-        loperands[6] = gen_label_rtx();
-        output_asm_insn (MOTOROLA ?
-                          "shi %5\n\tjbra %l6" :
-                          "shi %5\n\tjra %l6",
+        loperands[6] = gen_label_rtx ();
+        output_asm_insn (MOTOROLA ? "shi %5\n\tjbra %l6" : "shi %5\n\tjra %l6",
                         loperands);
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[4]));
+                                          CODE_LABEL_NUMBER (loperands[4]));
         output_asm_insn ("sgt %5", loperands);
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[6]));
+                                          CODE_LABEL_NUMBER (loperands[6]));
         break;
 
       case GTU:
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[4]));
+                                          CODE_LABEL_NUMBER (loperands[4]));
         output_asm_insn ("shi %5", loperands);
         break;
 
       case LT:
-        loperands[6] = gen_label_rtx();
-        output_asm_insn (MOTOROLA ?
-                          "scs %5\n\tjbra %l6" :
-                          "scs %5\n\tjra %l6",
+        loperands[6] = gen_label_rtx ();
+        output_asm_insn (MOTOROLA ? "scs %5\n\tjbra %l6" : "scs %5\n\tjra %l6",
                         loperands);
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[4]));
+                                          CODE_LABEL_NUMBER (loperands[4]));
         output_asm_insn ("slt %5", loperands);
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[6]));
+                                          CODE_LABEL_NUMBER (loperands[6]));
         break;
 
       case LTU:
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[4]));
+                                          CODE_LABEL_NUMBER (loperands[4]));
         output_asm_insn ("scs %5", loperands);
         break;
 
       case GE:
-        loperands[6] = gen_label_rtx();
-        output_asm_insn (MOTOROLA ?
-                          "scc %5\n\tjbra %l6" :
-                          "scc %5\n\tjra %l6",
-                          loperands);
+        loperands[6] = gen_label_rtx ();
+        output_asm_insn (MOTOROLA ? "scc %5\n\tjbra %l6" : "scc %5\n\tjra %l6",
+                        loperands);
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[4]));
+                                          CODE_LABEL_NUMBER (loperands[4]));
         output_asm_insn ("sge %5", loperands);
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[6]));
+                                          CODE_LABEL_NUMBER (loperands[6]));
         break;
 
       case GEU:
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[4]));
+                                          CODE_LABEL_NUMBER (loperands[4]));
         output_asm_insn ("scc %5", loperands);
         break;
 
       case LE:
-        loperands[6] = gen_label_rtx();
-        output_asm_insn (MOTOROLA ?
-                          "sls %5\n\tjbra %l6" :
-                          "sls %5\n\tjra %l6",
+        loperands[6] = gen_label_rtx ();
+        output_asm_insn (MOTOROLA ? "sls %5\n\tjbra %l6" : "sls %5\n\tjra %l6",
                         loperands);
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[4]));
+                                          CODE_LABEL_NUMBER (loperands[4]));
         output_asm_insn ("sle %5", loperands);
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[6]));
+                                          CODE_LABEL_NUMBER (loperands[6]));
         break;
 
       case LEU:
         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (loperands[4]));
+                                          CODE_LABEL_NUMBER (loperands[4]));
         output_asm_insn ("sls %5", loperands);
         break;
 
       default:
-       abort ();
+       gcc_unreachable ();
     }
   return "";
 }
@@ -1354,53 +1650,6 @@ output_btst (rtx *operands, rtx countop, rtx dataop, rtx insn, int signpos)
   return "btst %0,%1";
 }
 \f
-/* Returns true if OP is either a symbol reference or a sum of a symbol
-   reference and a constant.  */
-
-bool
-symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  switch (GET_CODE (op))
-    {
-    case SYMBOL_REF:
-    case LABEL_REF:
-      return true;
-
-    case CONST:
-      op = XEXP (op, 0);
-      return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
-              || GET_CODE (XEXP (op, 0)) == LABEL_REF)
-             && GET_CODE (XEXP (op, 1)) == CONST_INT);
-
-#if 0 /* Deleted, with corresponding change in m68k.h,
-        so as to fit the specs.  No CONST_DOUBLE is ever symbolic.  */
-    case CONST_DOUBLE:
-      return GET_MODE (op) == mode;
-#endif
-
-    default:
-      return false;
-    }
-}
-\f
-/* Check for sign_extend or zero_extend.  Used for bit-count operands.  */
-
-int
-extend_operator(rtx x, enum machine_mode mode)
-{
-    if (mode != VOIDmode && GET_MODE(x) != mode)
-       return 0;
-    switch (GET_CODE(x))
-       {
-       case SIGN_EXTEND :
-       case ZERO_EXTEND :
-           return 1;
-       default :
-           return 0;
-       }
-}
-
-\f
 /* Legitimize PIC addresses.  If the address is already
    position-independent, we return ORIG.  Newly generated
    position-independent addresses go to REG.  If we need more
@@ -1450,14 +1699,13 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
   /* First handle a simple SYMBOL_REF or LABEL_REF */
   if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
     {
-      if (reg == 0)
-       abort ();
+      gcc_assert (reg);
 
       pic_ref = gen_rtx_MEM (Pmode,
                             gen_rtx_PLUS (Pmode,
                                           pic_offset_table_rtx, orig));
       current_function_uses_pic_offset_table = 1;
-      RTX_UNCHANGING_P (pic_ref) = 1;
+      MEM_READONLY_P (pic_ref) = 1;
       emit_move_insn (reg, pic_ref);
       return reg;
     }
@@ -1470,17 +1718,14 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
          && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
        return orig;
 
-      if (reg == 0)
-       abort ();
+      gcc_assert (reg);
 
       /* legitimize both operands of the PLUS */
-      if (GET_CODE (XEXP (orig, 0)) == PLUS)
-       {
-         base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
-         orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
-                                        base == reg ? 0 : reg);
-       }
-      else abort ();
+      gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+      
+      base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+      orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+                                    base == reg ? 0 : reg);
 
       if (GET_CODE (orig) == CONST_INT)
        return plus_constant (base, INTVAL (orig));
@@ -1491,11 +1736,11 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
 }
 
 \f
-typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
+typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ, MVS, MVZ } CONST_METHOD;
 
 static CONST_METHOD const_method (rtx);
 
-#define USE_MOVQ(i)    ((unsigned)((i) + 128) <= 255)
+#define USE_MOVQ(i)    ((unsigned) ((i) + 128) <= 255)
 
 static CONST_METHOD
 const_method (rtx constant)
@@ -1509,7 +1754,7 @@ const_method (rtx constant)
 
   /* The ColdFire doesn't have byte or word operations.  */
   /* FIXME: This may not be useful for the m68060 either.  */
-  if (!TARGET_COLDFIRE) 
+  if (!TARGET_COLDFIRE)
     {
       /* if -256 < N < 256 but N is not in range for a moveq
         N^ff will be, so use moveq #N^ff, dreg; not.b dreg.  */
@@ -1521,11 +1766,22 @@ const_method (rtx constant)
       /* This is the only value where neg.w is useful */
       if (i == -65408)
        return NEGW;
-      /* Try also with swap */
-      u = i;
-      if (USE_MOVQ ((u >> 16) | (u << 16)))
-       return SWAP;
     }
+
+  /* Try also with swap.  */
+  u = i;
+  if (USE_MOVQ ((u >> 16) | (u << 16)))
+    return SWAP;
+
+  if (TARGET_ISAB)
+    {
+      /* Try using MVZ/MVS with an immediate value to load constants.  */
+      if (i >= 0 && i <= 65535)
+       return MVZ;
+      if (i >= -32768 && i <= 32767)
+       return MVS;
+    }
+
   /* Otherwise, use move.l */
   return MOVL;
 }
@@ -1535,19 +1791,21 @@ const_int_cost (rtx constant)
 {
   switch (const_method (constant))
     {
-      case MOVQ :
-      /* Constants between -128 and 127 are cheap due to moveq */
-       return 0;
-      case NOTB :
-      case NOTW :
-      case NEGW :
-      case SWAP :
-      /* Constants easily generated by moveq + not.b/not.w/neg.w/swap  */
-        return 1;
-      case MOVL :
-       return 2;
-      default :
-        abort ();
+    case MOVQ:
+      /* Constants between -128 and 127 are cheap due to moveq.  */
+      return 0;
+    case MVZ:
+    case MVS:
+    case NOTB:
+    case NOTW:
+    case NEGW:
+    case SWAP:
+      /* Constants easily generated by moveq + not.b/not.w/neg.w/swap.  */
+      return 1;
+    case MOVL:
+      return 2;
+    default:
+      gcc_unreachable ();
     }
 }
 
@@ -1585,11 +1843,23 @@ m68k_rtx_costs (rtx x, int code, int outer_code, int *total)
        in synth_mult on the 68020, relative to an average of the time
        for add and the time for shift, taking away a little more because
        sometimes move insns are needed.  */
-    /* div?.w is relatively cheaper on 68000 counted in COSTS_N_INSNS terms.  */
-#define MULL_COST (TARGET_68060 ? 2 : TARGET_68040 ? 5 : TARGET_CFV3 ? 3 : TARGET_COLDFIRE ? 10 : 13)
-#define MULW_COST (TARGET_68060 ? 2 : TARGET_68040 ? 3 : TARGET_68020 ? 8 : \
-                       TARGET_CFV3 ? 2 : 5)
-#define DIVW_COST (TARGET_68020 ? 27 : TARGET_CF_HWDIV ? 11 : 12)
+    /* div?.w is relatively cheaper on 68000 counted in COSTS_N_INSNS
+       terms.  */
+#define MULL_COST                              \
+  (TUNE_68060 ? 2                              \
+   : TUNE_68040 ? 5                            \
+   : TUNE_CFV2 ? 10                            \
+   : TARGET_COLDFIRE ? 3 : 13)
+
+#define MULW_COST                              \
+  (TUNE_68060 ? 2                              \
+   : TUNE_68040 ? 3                            \
+   : TUNE_68000_10 || TUNE_CFV2 ? 5            \
+   : TARGET_COLDFIRE ? 2 : 8)
+
+#define DIVW_COST                              \
+  (TARGET_CF_HWDIV ? 11                                \
+   : TUNE_68000_10 || TARGET_COLDFIRE ? 12 : 27)
 
     case PLUS:
       /* An lea costs about three times as much as a simple add.  */
@@ -1611,12 +1881,12 @@ m68k_rtx_costs (rtx x, int code, int outer_code, int *total)
     case ASHIFT:
     case ASHIFTRT:
     case LSHIFTRT:
-      if (TARGET_68060)
+      if (TUNE_68060)
        {
           *total = COSTS_N_INSNS(1);
          return true;
        }
-      if (! TARGET_68020 && ! TARGET_COLDFIRE)
+      if (TUNE_68000_10)
         {
          if (GET_CODE (XEXP (x, 1)) == CONST_INT)
            {
@@ -1627,7 +1897,7 @@ m68k_rtx_costs (rtx x, int code, int outer_code, int *total)
                *total = COSTS_N_INSNS (4) + (INTVAL (XEXP (x, 1)) - 16) / 2;
            }
          else
-           *total = COSTS_N_INSNS (10); /* worst case */
+           *total = COSTS_N_INSNS (10); /* Worst case.  */
          return true;
         }
       /* A shift by a big integer takes an extra instruction.  */
@@ -1682,45 +1952,68 @@ output_move_const_into_data_reg (rtx *operands)
   i = INTVAL (operands[1]);
   switch (const_method (operands[1]))
     {
-    case MOVQ :
+    case MVZ:
+      return "mvzw %1,%0";
+    case MVS:
+      return "mvsw %1,%0";
+    case MOVQ:
       return "moveq %1,%0";
-    case NOTB :
+    case NOTB:
       CC_STATUS_INIT;
       operands[1] = GEN_INT (i ^ 0xff);
       return "moveq %1,%0\n\tnot%.b %0";
-    case NOTW :
+    case NOTW:
       CC_STATUS_INIT;
       operands[1] = GEN_INT (i ^ 0xffff);
       return "moveq %1,%0\n\tnot%.w %0";
-    case NEGW :
+    case NEGW:
       CC_STATUS_INIT;
-      return "moveq %#-128,%0\n\tneg%.w %0";
-    case SWAP :
+      return "moveq #-128,%0\n\tneg%.w %0";
+    case SWAP:
       {
        unsigned u = i;
 
        operands[1] = GEN_INT ((u << 16) | (u >> 16));
        return "moveq %1,%0\n\tswap %0";
       }
-    case MOVL :
+    case MOVL:
        return "move%.l %1,%0";
-    default :
-       abort ();
+    default:
+       gcc_unreachable ();
+    }
+}
+
+/* Return 1 if 'constant' can be represented by
+   mov3q on a ColdFire V4 core.  */
+int
+valid_mov3q_const (rtx constant)
+{
+  int i;
+
+  if (TARGET_ISAB && GET_CODE (constant) == CONST_INT)
+    {
+      i = INTVAL (constant);
+      if (i == -1 || (i >= 1 && i <= 7))
+       return 1;
     }
+  return 0;
 }
 
+
 const char *
 output_move_simode_const (rtx *operands)
 {
   if (operands[1] == const0_rtx
       && (DATA_REG_P (operands[0])
          || GET_CODE (operands[0]) == MEM)
-      /* clr insns on 68000 read before writing.
-        This isn't so on the 68010, but we have no TARGET_68010.  */
-      && ((TARGET_68020 || TARGET_COLDFIRE)
+      /* clr insns on 68000 read before writing.  */
+      && ((TARGET_68010 || TARGET_COLDFIRE)
          || !(GET_CODE (operands[0]) == MEM
               && MEM_VOLATILE_P (operands[0]))))
     return "clr%.l %0";
+  else if ((GET_MODE (operands[0]) == SImode)
+           && valid_mov3q_const (operands[1]))
+    return "mov3q%.l %1,%0";
   else if (operands[1] == const0_rtx
           && ADDRESS_REG_P (operands[0]))
     return "sub%.l %0,%0";
@@ -1729,13 +2022,21 @@ output_move_simode_const (rtx *operands)
   else if (ADDRESS_REG_P (operands[0])
           && INTVAL (operands[1]) < 0x8000
           && INTVAL (operands[1]) >= -0x8000)
-    return "move%.w %1,%0";
+    {
+      if (valid_mov3q_const (operands[1]))
+        return "mov3q%.l %1,%0";
+      return "move%.w %1,%0";
+    }
   else if (GET_CODE (operands[0]) == MEM
-      && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
-      && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
+          && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
+          && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
           && INTVAL (operands[1]) < 0x8000
           && INTVAL (operands[1]) >= -0x8000)
-    return "pea %a1";
+    {
+      if (valid_mov3q_const (operands[1]))
+        return "mov3q%.l %1,%-";
+      return "pea %a1";
+    }
   return "move%.l %1,%0";
 }
 
@@ -1763,9 +2064,8 @@ output_move_himode (rtx *operands)
       if (operands[1] == const0_rtx
          && (DATA_REG_P (operands[0])
              || GET_CODE (operands[0]) == MEM)
-         /* clr insns on 68000 read before writing.
-            This isn't so on the 68010, but we have no TARGET_68010.  */
-         && ((TARGET_68020 || TARGET_COLDFIRE)
+         /* clr insns on 68000 read before writing.  */
+         && ((TARGET_68010 || TARGET_COLDFIRE)
              || !(GET_CODE (operands[0]) == MEM
                   && MEM_VOLATILE_P (operands[0]))))
        return "clr%.w %0";
@@ -1775,9 +2075,7 @@ output_move_himode (rtx *operands)
       else if (DATA_REG_P (operands[0])
               && INTVAL (operands[1]) < 128
               && INTVAL (operands[1]) >= -128)
-       {
-         return "moveq %1,%0";
-       }
+       return "moveq %1,%0";
       else if (INTVAL (operands[1]) < 0x8000
               && INTVAL (operands[1]) >= -0x8000)
        return "move%.w %1,%0";
@@ -1796,23 +2094,12 @@ output_move_himode (rtx *operands)
       && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS)
     {
       rtx labelref = XEXP (XEXP (operands[1], 0), 1);
-#if MOTOROLA && !defined (SGS_SWITCH_TABLES)
-#ifdef SGS
-      asm_fprintf (asm_out_file, "\tset %LLI%d,.+2\n",
-                  CODE_LABEL_NUMBER (XEXP (labelref, 0)));
-#else /* not SGS */
-      asm_fprintf (asm_out_file, "\t.set %LLI%d,.+2\n",
-                  CODE_LABEL_NUMBER (XEXP (labelref, 0)));
-#endif /* not SGS */
-#else /* SGS_SWITCH_TABLES or not MOTOROLA */
-      (*targetm.asm_out.internal_label) (asm_out_file, "LI",
-                                CODE_LABEL_NUMBER (XEXP (labelref, 0)));
-#ifdef SGS_SWITCH_TABLES
-      /* Set flag saying we need to define the symbol
-        LD%n (with value L%n-LI%n) at the end of the switch table.  */
-      switch_table_difference_label_flag = 1;
-#endif /* SGS_SWITCH_TABLES */
-#endif /* SGS_SWITCH_TABLES or not MOTOROLA */
+      if (MOTOROLA)
+       asm_fprintf (asm_out_file, "\t.set %LLI%d,.+2\n",
+                    CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+      else
+       (*targetm.asm_out.internal_label) (asm_out_file, "LI",
+                                          CODE_LABEL_NUMBER (XEXP (labelref, 0)));
     }
   return "move%.w %1,%0";
 }
@@ -1820,38 +2107,19 @@ output_move_himode (rtx *operands)
 const char *
 output_move_qimode (rtx *operands)
 {
-  rtx xoperands[4];
-
-  /* This is probably useless, since it loses for pushing a struct
-     of several bytes a byte at a time.         */
   /* 68k family always modifies the stack pointer by at least 2, even for
      byte pushes.  The 5200 (ColdFire) does not do this.  */
-  if (GET_CODE (operands[0]) == MEM
-      && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
-      && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
-      && ! ADDRESS_REG_P (operands[1])
-      && ! TARGET_COLDFIRE)
-    {
-      xoperands[1] = operands[1];
-      xoperands[2]
-       = gen_rtx_MEM (QImode,
-                      gen_rtx_PLUS (VOIDmode, stack_pointer_rtx, const1_rtx));
-      /* Just pushing a byte puts it in the high byte of the halfword. */
-      /* We must put it in the low-order, high-numbered byte.  */
-      if (!reg_mentioned_p (stack_pointer_rtx, operands[1]))
-       {
-         xoperands[3] = stack_pointer_rtx;
-         output_asm_insn ("subq%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
-       }
-      else
-       output_asm_insn ("move%.b %1,%-\n\tmove%.b %@,%2", xoperands);
-      return "";
-    }
-
-  /* clr and st insns on 68000 read before writing.
-     This isn't so on the 68010, but we have no TARGET_68010.  */
+  
+  /* This case is generated by pushqi1 pattern now.  */
+  gcc_assert (!(GET_CODE (operands[0]) == MEM
+               && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
+               && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
+               && ! ADDRESS_REG_P (operands[1])
+               && ! TARGET_COLDFIRE));
+
+  /* clr and st insns on 68000 read before writing.  */
   if (!ADDRESS_REG_P (operands[0])
-      && ((TARGET_68020 || TARGET_COLDFIRE)
+      && ((TARGET_68010 || TARGET_COLDFIRE)
          || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
     {
       if (operands[1] == const0_rtx)
@@ -1868,9 +2136,7 @@ output_move_qimode (rtx *operands)
       && DATA_REG_P (operands[0])
       && INTVAL (operands[1]) < 128
       && INTVAL (operands[1]) >= -128)
-    {
-      return "moveq %1,%0";
-    }
+    return "moveq %1,%0";
   if (operands[1] == const0_rtx && ADDRESS_REG_P (operands[0]))
     return "sub%.l %0,%0";
   if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
@@ -1886,9 +2152,8 @@ const char *
 output_move_stricthi (rtx *operands)
 {
   if (operands[1] == const0_rtx
-      /* clr insns on 68000 read before writing.
-        This isn't so on the 68010, but we have no TARGET_68010.  */
-      && ((TARGET_68020 || TARGET_COLDFIRE)
+      /* clr insns on 68000 read before writing.  */
+      && ((TARGET_68010 || TARGET_COLDFIRE)
          || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
     return "clr%.w %0";
   return "move%.w %1,%0";
@@ -1898,9 +2163,8 @@ const char *
 output_move_strictqi (rtx *operands)
 {
   if (operands[1] == const0_rtx
-      /* clr insns on 68000 read before writing.
-         This isn't so on the 68010, but we have no TARGET_68010.  */
-      && ((TARGET_68020 || TARGET_COLDFIRE)
+      /* clr insns on 68000 read before writing.  */
+      && ((TARGET_68010 || TARGET_COLDFIRE)
           || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
     return "clr%.b %0";
   return "move%.b %1,%0";
@@ -1968,12 +2232,10 @@ output_move_double (rtx *operands)
   else
     optype1 = RNDOP;
 
-  /* Check for the cases that the operand constraints are not
-     supposed to allow to happen.  Abort if we get one,
-     because generating code for these cases is painful.  */
-
-  if (optype0 == RNDOP || optype1 == RNDOP)
-    abort ();
+  /* Check for the cases that the operand constraints are not supposed
+     to allow to happen.  Generating code for these cases is
+     painful.  */
+  gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
 
   /* If one operand is decrementing and one is incrementing
      decrement the former register explicitly
@@ -1983,9 +2245,9 @@ output_move_double (rtx *operands)
     {
       operands[0] = XEXP (XEXP (operands[0], 0), 0);
       if (size == 12)
-        output_asm_insn ("sub%.l %#12,%0", operands);
+        output_asm_insn ("sub%.l #12,%0", operands);
       else
-        output_asm_insn ("subq%.l %#8,%0", operands);
+        output_asm_insn ("subq%.l #8,%0", operands);
       if (GET_MODE (operands[1]) == XFmode)
        operands[0] = gen_rtx_MEM (XFmode, operands[0]);
       else if (GET_MODE (operands[0]) == DFmode)
@@ -1998,9 +2260,9 @@ output_move_double (rtx *operands)
     {
       operands[1] = XEXP (XEXP (operands[1], 0), 0);
       if (size == 12)
-        output_asm_insn ("sub%.l %#12,%1", operands);
+        output_asm_insn ("sub%.l #12,%1", operands);
       else
-        output_asm_insn ("subq%.l %#8,%1", operands);
+        output_asm_insn ("subq%.l #8,%1", operands);
       if (GET_MODE (operands[1]) == XFmode)
        operands[1] = gen_rtx_MEM (XFmode, operands[1]);
       else if (GET_MODE (operands[1]) == DFmode)
@@ -2069,15 +2331,11 @@ output_move_double (rtx *operands)
              middlehalf[1] = GEN_INT (l[1]);
              latehalf[1] = GEN_INT (l[2]);
            }
-         else if (CONSTANT_P (operands[1]))
+         else
            {
-             /* actually, no non-CONST_DOUBLE constant should ever
-                appear here.  */
-             abort ();
-             if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
-               latehalf[1] = constm1_rtx;
-             else
-               latehalf[1] = const0_rtx;
+             /* No non-CONST_DOUBLE constant should ever appear
+                here.  */
+             gcc_assert (!CONSTANT_P (operands[1]));
            }
        }
       else
@@ -2130,7 +2388,7 @@ output_move_double (rtx *operands)
          /* If both halves of dest are used in the src memory address,
             compute the address into latehalf of dest.
             Note that this can't happen if the dest is two data regs.  */
-compadr:
+       compadr:
          xops[0] = latehalf[0];
          xops[1] = XEXP (operands[1], 0);
          output_asm_insn ("lea %a1,%0", xops);
@@ -2161,8 +2419,7 @@ compadr:
            goto compadr;
 
          /* JRV says this can't happen: */
-         if (addreg0 || addreg1)
-           abort ();
+         gcc_assert (!addreg0 && !addreg1);
 
          /* Only the middle reg conflicts; simply put it last.  */
          output_asm_insn (singlemove_string (operands), operands);
@@ -2194,16 +2451,16 @@ compadr:
       if (addreg0)
        {
          if (size == 12)
-           output_asm_insn ("addq%.l %#8,%0", &addreg0);
+           output_asm_insn ("addq%.l #8,%0", &addreg0);
          else
-           output_asm_insn ("addq%.l %#4,%0", &addreg0);
+           output_asm_insn ("addq%.l #4,%0", &addreg0);
        }
       if (addreg1)
        {
          if (size == 12)
-           output_asm_insn ("addq%.l %#8,%0", &addreg1);
+           output_asm_insn ("addq%.l #8,%0", &addreg1);
          else
-           output_asm_insn ("addq%.l %#4,%0", &addreg1);
+           output_asm_insn ("addq%.l #4,%0", &addreg1);
        }
 
       /* Do that word.  */
@@ -2211,17 +2468,17 @@ compadr:
 
       /* Undo the adds we just did.  */
       if (addreg0)
-       output_asm_insn ("subq%.l %#4,%0", &addreg0);
+       output_asm_insn ("subq%.l #4,%0", &addreg0);
       if (addreg1)
-       output_asm_insn ("subq%.l %#4,%0", &addreg1);
+       output_asm_insn ("subq%.l #4,%0", &addreg1);
 
       if (size == 12)
        {
          output_asm_insn (singlemove_string (middlehalf), middlehalf);
          if (addreg0)
-           output_asm_insn ("subq%.l %#4,%0", &addreg0);
+           output_asm_insn ("subq%.l #4,%0", &addreg0);
          if (addreg1)
-           output_asm_insn ("subq%.l %#4,%0", &addreg1);
+           output_asm_insn ("subq%.l #4,%0", &addreg1);
        }
 
       /* Do low-numbered word.  */
@@ -2236,18 +2493,18 @@ compadr:
   if (size == 12)
     {
       if (addreg0)
-       output_asm_insn ("addq%.l %#4,%0", &addreg0);
+       output_asm_insn ("addq%.l #4,%0", &addreg0);
       if (addreg1)
-       output_asm_insn ("addq%.l %#4,%0", &addreg1);
+       output_asm_insn ("addq%.l #4,%0", &addreg1);
 
       output_asm_insn (singlemove_string (middlehalf), middlehalf);
     }
 
   /* Make any unoffsettable addresses point at high-numbered word.  */
   if (addreg0)
-    output_asm_insn ("addq%.l %#4,%0", &addreg0);
+    output_asm_insn ("addq%.l #4,%0", &addreg0);
   if (addreg1)
-    output_asm_insn ("addq%.l %#4,%0", &addreg1);
+    output_asm_insn ("addq%.l #4,%0", &addreg1);
 
   /* Do that word.  */
   output_asm_insn (singlemove_string (latehalf), latehalf);
@@ -2256,21 +2513,207 @@ compadr:
   if (addreg0)
     {
       if (size == 12)
-        output_asm_insn ("subq%.l %#8,%0", &addreg0);
+        output_asm_insn ("subq%.l #8,%0", &addreg0);
       else
-        output_asm_insn ("subq%.l %#4,%0", &addreg0);
+        output_asm_insn ("subq%.l #4,%0", &addreg0);
     }
   if (addreg1)
     {
       if (size == 12)
-        output_asm_insn ("subq%.l %#8,%0", &addreg1);
+        output_asm_insn ("subq%.l #8,%0", &addreg1);
       else
-        output_asm_insn ("subq%.l %#4,%0", &addreg1);
+        output_asm_insn ("subq%.l #4,%0", &addreg1);
     }
 
   return "";
 }
 
+
+/* Ensure mode of ORIG, a REG rtx, is MODE.  Returns either ORIG or a
+   new rtx with the correct mode.  */
+
+static rtx
+force_mode (enum machine_mode mode, rtx orig)
+{
+  if (mode == GET_MODE (orig))
+    return orig;
+
+  if (REGNO (orig) >= FIRST_PSEUDO_REGISTER)
+    abort ();
+
+  return gen_rtx_REG (mode, REGNO (orig));
+}
+
+static int
+fp_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return reg_renumber && FP_REG_P (op);
+}
+
+/* Emit insns to move operands[1] into operands[0].
+
+   Return 1 if we have written out everything that needs to be done to
+   do the move.  Otherwise, return 0 and the caller will emit the move
+   normally.
+
+   Note SCRATCH_REG may not be in the proper mode depending on how it
+   will be used.  This routine is responsible for creating a new copy
+   of SCRATCH_REG in the proper mode.  */
+
+int
+emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
+{
+  register rtx operand0 = operands[0];
+  register rtx operand1 = operands[1];
+  register rtx tem;
+
+  if (scratch_reg
+      && reload_in_progress && GET_CODE (operand0) == REG
+      && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
+    operand0 = reg_equiv_mem[REGNO (operand0)];
+  else if (scratch_reg
+          && reload_in_progress && GET_CODE (operand0) == SUBREG
+          && GET_CODE (SUBREG_REG (operand0)) == REG
+          && REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER)
+    {
+     /* We must not alter SUBREG_BYTE (operand0) since that would confuse
+       the code which tracks sets/uses for delete_output_reload.  */
+      rtx temp = gen_rtx_SUBREG (GET_MODE (operand0),
+                                reg_equiv_mem [REGNO (SUBREG_REG (operand0))],
+                                SUBREG_BYTE (operand0));
+      operand0 = alter_subreg (&temp);
+    }
+
+  if (scratch_reg
+      && reload_in_progress && GET_CODE (operand1) == REG
+      && REGNO (operand1) >= FIRST_PSEUDO_REGISTER)
+    operand1 = reg_equiv_mem[REGNO (operand1)];
+  else if (scratch_reg
+          && reload_in_progress && GET_CODE (operand1) == SUBREG
+          && GET_CODE (SUBREG_REG (operand1)) == REG
+          && REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER)
+    {
+     /* We must not alter SUBREG_BYTE (operand0) since that would confuse
+       the code which tracks sets/uses for delete_output_reload.  */
+      rtx temp = gen_rtx_SUBREG (GET_MODE (operand1),
+                                reg_equiv_mem [REGNO (SUBREG_REG (operand1))],
+                                SUBREG_BYTE (operand1));
+      operand1 = alter_subreg (&temp);
+    }
+
+  if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM
+      && ((tem = find_replacement (&XEXP (operand0, 0)))
+         != XEXP (operand0, 0)))
+    operand0 = gen_rtx_MEM (GET_MODE (operand0), tem);
+  if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM
+      && ((tem = find_replacement (&XEXP (operand1, 0)))
+         != XEXP (operand1, 0)))
+    operand1 = gen_rtx_MEM (GET_MODE (operand1), tem);
+
+  /* Handle secondary reloads for loads/stores of FP registers where
+     the address is symbolic by using the scratch register */
+  if (fp_reg_operand (operand0, mode)
+      && ((GET_CODE (operand1) == MEM
+          && ! memory_address_p (DFmode, XEXP (operand1, 0)))
+         || ((GET_CODE (operand1) == SUBREG
+              && GET_CODE (XEXP (operand1, 0)) == MEM
+              && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0)))))
+      && scratch_reg)
+    {
+      if (GET_CODE (operand1) == SUBREG)
+       operand1 = XEXP (operand1, 0);
+
+      /* SCRATCH_REG will hold an address.  We want
+        it in SImode regardless of what mode it was originally given
+        to us.  */
+      scratch_reg = force_mode (SImode, scratch_reg);
+
+      /* D might not fit in 14 bits either; for such cases load D into
+        scratch reg.  */
+      if (!memory_address_p (Pmode, XEXP (operand1, 0)))
+       {
+         emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));
+         emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, 0)),
+                                                      Pmode,
+                                                      XEXP (XEXP (operand1, 0), 0),
+                                                      scratch_reg));
+       }
+      else
+       emit_move_insn (scratch_reg, XEXP (operand1, 0));
+      emit_insn (gen_rtx_SET (VOIDmode, operand0,
+                             gen_rtx_MEM (mode, scratch_reg)));
+      return 1;
+    }
+  else if (fp_reg_operand (operand1, mode)
+          && ((GET_CODE (operand0) == MEM
+               && ! memory_address_p (DFmode, XEXP (operand0, 0)))
+              || ((GET_CODE (operand0) == SUBREG)
+                  && GET_CODE (XEXP (operand0, 0)) == MEM
+                  && !memory_address_p (DFmode, XEXP (XEXP (operand0, 0), 0))))
+          && scratch_reg)
+    {
+      if (GET_CODE (operand0) == SUBREG)
+       operand0 = XEXP (operand0, 0);
+
+      /* SCRATCH_REG will hold an address and maybe the actual data.  We want
+        it in SIMODE regardless of what mode it was originally given
+        to us.  */
+      scratch_reg = force_mode (SImode, scratch_reg);
+
+      /* D might not fit in 14 bits either; for such cases load D into
+        scratch reg.  */
+      if (!memory_address_p (Pmode, XEXP (operand0, 0)))
+       {
+         emit_move_insn (scratch_reg, XEXP (XEXP (operand0, 0), 1));
+         emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand0,
+                                                                       0)),
+                                                      Pmode,
+                                                      XEXP (XEXP (operand0, 0),
+                                                                  0),
+                                                      scratch_reg));
+       }
+      else
+       emit_move_insn (scratch_reg, XEXP (operand0, 0));
+      emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (mode, scratch_reg),
+                             operand1));
+      return 1;
+    }
+  /* Handle secondary reloads for loads of FP registers from constant
+     expressions by forcing the constant into memory.
+
+     use scratch_reg to hold the address of the memory location.
+
+     The proper fix is to change PREFERRED_RELOAD_CLASS to return
+     NO_REGS when presented with a const_int and an register class
+     containing only FP registers.  Doing so unfortunately creates
+     more problems than it solves.   Fix this for 2.5.  */
+  else if (fp_reg_operand (operand0, mode)
+          && CONSTANT_P (operand1)
+          && scratch_reg)
+    {
+      rtx xoperands[2];
+
+      /* SCRATCH_REG will hold an address and maybe the actual data.  We want
+        it in SIMODE regardless of what mode it was originally given
+        to us.  */
+      scratch_reg = force_mode (SImode, scratch_reg);
+
+      /* Force the constant into memory and put the address of the
+        memory location into scratch_reg.  */
+      xoperands[0] = scratch_reg;
+      xoperands[1] = XEXP (force_const_mem (mode, operand1), 0);
+      emit_insn (gen_rtx_SET (mode, scratch_reg, xoperands[1]));
+
+      /* Now load the destination register.  */
+      emit_insn (gen_rtx_SET (mode, operand0,
+                             gen_rtx_MEM (mode, scratch_reg)));
+      return 1;
+    }
+
+  /* Now have insn-emit do whatever it normally does.  */
+  return 0;
+}
+
 /* Return a REG that occurs in ADDR with coefficient 1.
    ADDR can be effectively incremented by incrementing REG.  */
 
@@ -2288,11 +2731,10 @@ find_addr_reg (rtx addr)
       else if (CONSTANT_P (XEXP (addr, 1)))
        addr = XEXP (addr, 0);
       else
-       abort ();
+       gcc_unreachable ();
     }
-  if (GET_CODE (addr) == REG)
-    return addr;
-  abort ();
+  gcc_assert (GET_CODE (addr) == REG);
+  return addr;
 }
 
 /* Output assembler code to perform a 32-bit 3-operand add.  */
@@ -2315,27 +2757,9 @@ output_addsi3 (rtx *operands)
       if (GET_CODE (operands[2]) == CONST_INT
          && (INTVAL (operands[2]) < -32768 || INTVAL (operands[2]) > 32767))
         return "move%.l %2,%0\n\tadd%.l %1,%0";
-#ifdef SGS
       if (GET_CODE (operands[2]) == REG)
-       return "lea 0(%1,%2.l),%0";
-      else
-       return "lea %c2(%1),%0";
-#else /* !SGS */
-      if (MOTOROLA)
-       {
-         if (GET_CODE (operands[2]) == REG)
-          return "lea (%1,%2.l),%0";
-         else
-          return "lea (%c2,%1),%0";
-       }
-      else /* !MOTOROLA (MIT syntax) */
-       {
-         if (GET_CODE (operands[2]) == REG)
-           return "lea %1@(0,%2:l),%0";
-         else
-           return "lea %1@(%c2),%0";
-       }
-#endif /* !SGS */
+       return MOTOROLA ? "lea (%1,%2.l),%0" : "lea %1@(0,%2:l),%0";
+      return MOTOROLA ? "lea (%c2,%1),%0" : "lea %1@(%c2),%0";
     }
   if (GET_CODE (operands[2]) == CONST_INT)
     {
@@ -2351,26 +2775,26 @@ output_addsi3 (rtx *operands)
       /* On the CPU32 it is faster to use two addql instructions to
         add a small integer (8 < N <= 16) to a register.
         Likewise for subql.  */
-      if (TARGET_CPU32 && REG_P (operands[0]))
+      if (TUNE_CPU32 && REG_P (operands[0]))
        {
          if (INTVAL (operands[2]) > 8
              && INTVAL (operands[2]) <= 16)
            {
              operands[2] = GEN_INT (INTVAL (operands[2]) - 8);
-             return "addq%.l %#8,%0\n\taddq%.l %2,%0";
+             return "addq%.l #8,%0\n\taddq%.l %2,%0";
            }
          if (INTVAL (operands[2]) < -8
              && INTVAL (operands[2]) >= -16)
            {
              operands[2] = GEN_INT (- INTVAL (operands[2]) - 8);
-             return "subq%.l %#8,%0\n\tsubq%.l %2,%0";
+             return "subq%.l #8,%0\n\tsubq%.l %2,%0";
            }
        }
       if (ADDRESS_REG_P (operands[0])
          && INTVAL (operands[2]) >= -0x8000
          && INTVAL (operands[2]) < 0x8000)
        {
-         if (TARGET_68040)
+         if (TUNE_68040)
            return "add%.w %2,%0";
          else
            return MOTOROLA ? "lea (%c2,%0),%0" : "lea %0@(%c2),%0";
@@ -2394,9 +2818,7 @@ notice_update_cc (rtx exp, rtx insn)
   if (GET_CODE (exp) == SET)
     {
       if (GET_CODE (SET_SRC (exp)) == CALL)
-       {
-         CC_STATUS_INIT; 
-       }
+       CC_STATUS_INIT; 
       else if (ADDRESS_REG_P (SET_DEST (exp)))
        {
          if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
@@ -2410,9 +2832,7 @@ notice_update_cc (rtx exp, rtx insn)
                   || GET_CODE (SET_SRC (exp)) == FIX
                   || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
                   || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
-       {
-         CC_STATUS_INIT; 
-       }
+       CC_STATUS_INIT; 
       /* A pair of move insns doesn't produce a useful overall cc.  */
       else if (!FP_REG_P (SET_DEST (exp))
               && !FP_REG_P (SET_SRC (exp))
@@ -2420,30 +2840,27 @@ notice_update_cc (rtx exp, rtx insn)
               && (GET_CODE (SET_SRC (exp)) == REG
                   || GET_CODE (SET_SRC (exp)) == MEM
                   || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
-       {
-         CC_STATUS_INIT; 
-       }
-      else if (GET_CODE (SET_SRC (exp)) == CALL)
-       {
-         CC_STATUS_INIT; 
-       }
-      else if (XEXP (exp, 0) != pc_rtx)
+       CC_STATUS_INIT; 
+      else if (SET_DEST (exp) != pc_rtx)
        {
          cc_status.flags = 0;
-         cc_status.value1 = XEXP (exp, 0);
-         cc_status.value2 = XEXP (exp, 1);
+         cc_status.value1 = SET_DEST (exp);
+         cc_status.value2 = SET_SRC (exp);
        }
     }
   else if (GET_CODE (exp) == PARALLEL
           && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
     {
-      if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
+      rtx dest = SET_DEST (XVECEXP (exp, 0, 0));
+      rtx src  = SET_SRC  (XVECEXP (exp, 0, 0));
+
+      if (ADDRESS_REG_P (dest))
        CC_STATUS_INIT;
-      else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
+      else if (dest != pc_rtx)
        {
          cc_status.flags = 0;
-         cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
-         cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
+         cc_status.value1 = dest;
+         cc_status.value2 = src;
        }
     }
   else
@@ -2497,7 +2914,7 @@ output_move_const_double (rtx *operands)
     {
       static char buf[40];
 
-      sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
+      sprintf (buf, "fmovecr #0x%x,%%0", code & 0xff);
       return buf;
     }
   return "fmove%.d %1,%0";
@@ -2512,7 +2929,7 @@ output_move_const_single (rtx *operands)
     {
       static char buf[40];
 
-      sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
+      sprintf (buf, "fmovecr #0x%x,%%0", code & 0xff);
       return buf;
     }
   return "fmove%.s %f1,%0";
@@ -2535,7 +2952,7 @@ static const char *const strings_68881[7] = {
   "10000.0",
   "1e8",
   "1e16"
-  };
+};
 
 static const int codes_68881[7] = {
   0x0f,
@@ -2545,7 +2962,7 @@ static const int codes_68881[7] = {
   0x35,
   0x36,
   0x37
-  };
+};
 
 REAL_VALUE_TYPE values_68881[7];
 
@@ -2578,7 +2995,7 @@ standard_68881_constant_p (rtx x)
 
   /* fmovecr must be emulated on the 68040 and 68060, so it shouldn't be
      used at all on those chips.  */
-  if (TARGET_68040 || TARGET_68060)
+  if (TUNE_68040_60)
     return 0;
 
   if (! inited_68881_table)
@@ -2693,12 +3110,12 @@ print_operand (FILE *file, rtx op, int letter)
     asm_fprintf (file, "%Rfpcr");
   else if (letter == '$')
     {
-      if (TARGET_68040_ONLY)
+      if (TARGET_68040)
        fprintf (file, "s");
     }
   else if (letter == '&')
     {
-      if (TARGET_68040_ONLY)
+      if (TARGET_68040)
        fprintf (file, "d");
     }
   else if (letter == '/')
@@ -2706,9 +3123,9 @@ print_operand (FILE *file, rtx op, int letter)
   else if (letter == 'o')
     {
       /* This is only for direct addresses with TARGET_PCREL */
-      if (GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
-          || !TARGET_PCREL) 
-       abort ();
+      gcc_assert (GET_CODE (op) == MEM
+                 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+                 && TARGET_PCREL);
       output_addr_const (file, XEXP (op, 0));
     }
   else if (GET_CODE (op) == REG)
@@ -2716,9 +3133,9 @@ print_operand (FILE *file, rtx op, int letter)
       if (letter == 'R')
        /* Print out the second register name of a register pair.
           I.e., R (6) => 7.  */
-       fputs (reg_names[REGNO (op) + 1], file);
+       fputs (M68K_REGNAME(REGNO (op) + 1), file);
       else
-       fputs (reg_names[REGNO (op)], file);
+       fputs (M68K_REGNAME(REGNO (op)), file);
     }
   else if (GET_CODE (op) == MEM)
     {
@@ -2789,23 +3206,16 @@ print_operand (FILE *file, rtx op, int letter)
 
    This routine is responsible for distinguishing between -fpic and -fPIC 
    style relocations in an address.  When generating -fpic code the
-   offset is output in word mode (eg movel a5@(_foo:w), a0).  When generating
-   -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
-
-#ifndef ASM_OUTPUT_CASE_FETCH
-# if MOTOROLA
-#  ifdef SGS
-#   define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
-       asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
-#  else /* !SGS */
-#   define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
-       asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
-#  endif /* !SGS */
-# else /* !MOTOROLA */
-#  define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
-       asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
-# endif /* !MOTOROLA */
-#endif /* ASM_OUTPUT_CASE_FETCH */
+   offset is output in word mode (e.g. movel a5@(_foo:w), a0).  When generating
+   -fPIC code the offset is output in long mode (e.g. movel a5@(_foo:l), a0) */
+
+#if MOTOROLA
+#  define ASM_OUTPUT_CASE_FETCH(file, labelno, regname) \
+  asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
+#else /* !MOTOROLA */
+# define ASM_OUTPUT_CASE_FETCH(file, labelno, regname) \
+  asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
+#endif /* !MOTOROLA */
 
 void
 print_operand_address (FILE *file, rtx addr)
@@ -2815,266 +3225,249 @@ print_operand_address (FILE *file, rtx addr)
 
   switch (GET_CODE (addr))
     {
-      case REG:
-       fprintf (file, MOTOROLA ? "(%s)" : "%s@", reg_names[REGNO (addr)]);
-       break;
-      case PRE_DEC:
-       fprintf (file, MOTOROLA ? "-(%s)" : "%s@-",
-                reg_names[REGNO (XEXP (addr, 0))]);
-       break;
-      case POST_INC:
-       fprintf (file, MOTOROLA ? "(%s)+" : "%s@+",
-                reg_names[REGNO (XEXP (addr, 0))]);
-       break;
-      case PLUS:
-       reg1 = reg2 = ireg = breg = offset = 0;
-       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
-         {
-           offset = XEXP (addr, 0);
-           addr = XEXP (addr, 1);
-         }
-       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
-         {
-           offset = XEXP (addr, 1);
-           addr = XEXP (addr, 0);
-         }
-       if (GET_CODE (addr) != PLUS)
-         {
-           ;
-         }
-       else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
-         {
-           reg1 = XEXP (addr, 0);
-           addr = XEXP (addr, 1);
-         }
-       else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
-         {
-           reg1 = XEXP (addr, 1);
-           addr = XEXP (addr, 0);
-         }
-       else if (GET_CODE (XEXP (addr, 0)) == MULT)
-         {
-           reg1 = XEXP (addr, 0);
-           addr = XEXP (addr, 1);
-         }
-       else if (GET_CODE (XEXP (addr, 1)) == MULT)
-         {
-           reg1 = XEXP (addr, 1);
-           addr = XEXP (addr, 0);
-         }
-       else if (GET_CODE (XEXP (addr, 0)) == REG)
-         {
-           reg1 = XEXP (addr, 0);
-           addr = XEXP (addr, 1);
-         }
-       else if (GET_CODE (XEXP (addr, 1)) == REG)
-         {
-           reg1 = XEXP (addr, 1);
-           addr = XEXP (addr, 0);
-         }
-       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
-           || GET_CODE (addr) == SIGN_EXTEND)
-         {
-           if (reg1 == 0)
-             {
-               reg1 = addr;
-             }
-           else
-             {
-               reg2 = addr;
-             }
-           addr = 0;
-         }
+    case REG:
+      fprintf (file, MOTOROLA ? "(%s)" : "%s@", M68K_REGNAME (REGNO (addr)));
+      break;
+    case PRE_DEC:
+      fprintf (file, MOTOROLA ? "-(%s)" : "%s@-",
+              M68K_REGNAME (REGNO (XEXP (addr, 0))));
+      break;
+    case POST_INC:
+      fprintf (file, MOTOROLA ? "(%s)+" : "%s@+",
+              M68K_REGNAME (REGNO (XEXP (addr, 0))));
+      break;
+    case PLUS:
+      reg1 = reg2 = ireg = breg = offset = 0;
+      if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
+       {
+         offset = XEXP (addr, 0);
+         addr = XEXP (addr, 1);
+       }
+      else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
+       {
+         offset = XEXP (addr, 1);
+         addr = XEXP (addr, 0);
+       }
+      if (GET_CODE (addr) != PLUS)
+       {
+         ;
+       }
+      else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
+       {
+         reg1 = XEXP (addr, 0);
+         addr = XEXP (addr, 1);
+       }
+      else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
+       {
+         reg1 = XEXP (addr, 1);
+         addr = XEXP (addr, 0);
+       }
+      else if (GET_CODE (XEXP (addr, 0)) == MULT)
+       {
+         reg1 = XEXP (addr, 0);
+         addr = XEXP (addr, 1);
+       }
+      else if (GET_CODE (XEXP (addr, 1)) == MULT)
+       {
+         reg1 = XEXP (addr, 1);
+         addr = XEXP (addr, 0);
+       }
+      else if (GET_CODE (XEXP (addr, 0)) == REG)
+       {
+         reg1 = XEXP (addr, 0);
+         addr = XEXP (addr, 1);
+       }
+      else if (GET_CODE (XEXP (addr, 1)) == REG)
+       {
+         reg1 = XEXP (addr, 1);
+         addr = XEXP (addr, 0);
+       }
+      if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
+         || GET_CODE (addr) == SIGN_EXTEND)
+       {
+         if (reg1 == 0)
+           reg1 = addr;
+         else
+           reg2 = addr;
+         addr = 0;
+       }
 #if 0  /* for OLD_INDEXING */
-       else if (GET_CODE (addr) == PLUS)
-         {
-           if (GET_CODE (XEXP (addr, 0)) == REG)
-             {
-               reg2 = XEXP (addr, 0);
-               addr = XEXP (addr, 1);
-             }
-           else if (GET_CODE (XEXP (addr, 1)) == REG)
-             {
-               reg2 = XEXP (addr, 1);
-               addr = XEXP (addr, 0);
-             }
-         }
+      else if (GET_CODE (addr) == PLUS)
+       {
+         if (GET_CODE (XEXP (addr, 0)) == REG)
+           {
+             reg2 = XEXP (addr, 0);
+             addr = XEXP (addr, 1);
+           }
+         else if (GET_CODE (XEXP (addr, 1)) == REG)
+           {
+             reg2 = XEXP (addr, 1);
+             addr = XEXP (addr, 0);
+           }
+       }
 #endif
-       if (offset != 0)
-         {
-           if (addr != 0)
-             {
-               abort ();
-             }
-           addr = offset;
-         }
-       if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
-                     || GET_CODE (reg1) == MULT))
-           || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
-         {
-           breg = reg2;
-           ireg = reg1;
-         }
-       else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
-         {
-           breg = reg1;
-           ireg = reg2;
-         }
-       if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
-           && ! (flag_pic && ireg == pic_offset_table_rtx))
-         {
-           int scale = 1;
-           if (GET_CODE (ireg) == MULT)
-             {
-               scale = INTVAL (XEXP (ireg, 1));
-               ireg = XEXP (ireg, 0);
-             }
-           if (GET_CODE (ireg) == SIGN_EXTEND)
-             {
-               ASM_OUTPUT_CASE_FETCH (file,
-                            CODE_LABEL_NUMBER (XEXP (addr, 0)),
-                            reg_names[REGNO (XEXP (ireg, 0))]);
-               fprintf (file, "w");
-             }
-           else
-             {
-               ASM_OUTPUT_CASE_FETCH (file,
-                            CODE_LABEL_NUMBER (XEXP (addr, 0)),
-                            reg_names[REGNO (ireg)]);
-               fprintf (file, "l");
-             }
-           if (scale != 1)
-             fprintf (file, MOTOROLA ? "*%d" : ":%d", scale);
-           putc (')', file);
-           break;
-         }
-       if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
-           && ! (flag_pic && breg == pic_offset_table_rtx))
-         {
-           ASM_OUTPUT_CASE_FETCH (file,
-                        CODE_LABEL_NUMBER (XEXP (addr, 0)),
-                        reg_names[REGNO (breg)]);
-           fprintf (file, "l)");
-           break;
-         }
-       if (ireg != 0 || breg != 0)
-         {
-           int scale = 1;
-           if (breg == 0)
-             {
-               abort ();
-             }
-           if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
-             {
-               abort ();
-             }
-           if (MOTOROLA)
-             {
-               if (addr != 0)
-                 {
-                   output_addr_const (file, addr);
-                   if (flag_pic && (breg == pic_offset_table_rtx))
+      if (offset != 0)
+       {
+         gcc_assert (!addr);
+         addr = offset;
+       }
+      if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
+                   || GET_CODE (reg1) == MULT))
+         || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
+       {
+         breg = reg2;
+         ireg = reg1;
+       }
+      else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
+       {
+         breg = reg1;
+         ireg = reg2;
+       }
+      if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
+         && ! (flag_pic && ireg == pic_offset_table_rtx))
+       {
+         int scale = 1;
+         if (GET_CODE (ireg) == MULT)
+           {
+             scale = INTVAL (XEXP (ireg, 1));
+             ireg = XEXP (ireg, 0);
+           }
+         if (GET_CODE (ireg) == SIGN_EXTEND)
+           {
+             ASM_OUTPUT_CASE_FETCH (file,
+                                    CODE_LABEL_NUMBER (XEXP (addr, 0)),
+                                    M68K_REGNAME (REGNO (XEXP (ireg, 0))));
+             fprintf (file, "w");
+           }
+         else
+           {
+             ASM_OUTPUT_CASE_FETCH (file,
+                                    CODE_LABEL_NUMBER (XEXP (addr, 0)),
+                                    M68K_REGNAME (REGNO (ireg)));
+             fprintf (file, "l");
+           }
+         if (scale != 1)
+           fprintf (file, MOTOROLA ? "*%d" : ":%d", scale);
+         putc (')', file);
+         break;
+       }
+      if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
+         && ! (flag_pic && breg == pic_offset_table_rtx))
+       {
+         ASM_OUTPUT_CASE_FETCH (file,
+                                CODE_LABEL_NUMBER (XEXP (addr, 0)),
+                                M68K_REGNAME (REGNO (breg)));
+         fprintf (file, "l)");
+         break;
+       }
+      if (ireg != 0 || breg != 0)
+       {
+         int scale = 1;
+           
+         gcc_assert (breg);
+         gcc_assert (flag_pic || !addr || GET_CODE (addr) != LABEL_REF);
+           
+         if (MOTOROLA)
+           {
+             if (addr != 0)
+               {
+                 output_addr_const (file, addr);
+                 if (flag_pic && (breg == pic_offset_table_rtx))
+                   {
+                     fprintf (file, "@GOT");
+                     if (flag_pic == 1)
+                       fprintf (file, ".w");
+                   }
+               }
+             fprintf (file, "(%s", M68K_REGNAME (REGNO (breg)));
+             if (ireg != 0)
+               putc (',', file);
+           }
+         else /* !MOTOROLA */
+           {
+             fprintf (file, "%s@(", M68K_REGNAME (REGNO (breg)));
+             if (addr != 0)
+               {
+                 output_addr_const (file, addr);
+                 if (breg == pic_offset_table_rtx)
+                   switch (flag_pic)
                      {
-                       fprintf (file, "@GOT");
-                       if (flag_pic == 1)
-                         fprintf (file, ".w");
+                     case 1:
+                       fprintf (file, ":w");
+                       break;
+                     case 2:
+                       fprintf (file, ":l");
+                       break;
+                     default:
+                       break;
                      }
-                 }
-               fprintf (file, "(%s", reg_names[REGNO (breg)]);
-               if (ireg != 0)
-                 putc (',', file);
-             }
-           else /* !MOTOROLA */
-             {
-               fprintf (file, "%s@(", reg_names[REGNO (breg)]);
-               if (addr != 0)
-                 {
-                   output_addr_const (file, addr);
-                   if (breg == pic_offset_table_rtx)
-                     switch (flag_pic)
-                       {
-                       case 1:
-                         fprintf (file, ":w"); break;
-                       case 2:
-                         fprintf (file, ":l"); break;
-                       default:
-                         break;
-                       }
-                   if (ireg != 0)
-                     putc (',', file);
-                 }
-             } /* !MOTOROLA */
-           if (ireg != 0 && GET_CODE (ireg) == MULT)
-             {
-               scale = INTVAL (XEXP (ireg, 1));
-               ireg = XEXP (ireg, 0);
-             }
-           if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
-             fprintf (file, MOTOROLA ? "%s.w" : "%s:w",
-                      reg_names[REGNO (XEXP (ireg, 0))]);
-           else if (ireg != 0)
-             fprintf (file, MOTOROLA ? "%s.l" : "%s:l",
-                      reg_names[REGNO (ireg)]);
-           if (scale != 1)
-             fprintf (file, MOTOROLA ? "*%d" : ":%d", scale);
-           putc (')', file);
-           break;
-         }
-       else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
-                && ! (flag_pic && reg1 == pic_offset_table_rtx))       
-         {
-           ASM_OUTPUT_CASE_FETCH (file,
-                        CODE_LABEL_NUMBER (XEXP (addr, 0)),
-                        reg_names[REGNO (reg1)]);
-           fprintf (file, "l)");
-           break;
-         }
-       /* FALL-THROUGH (is this really what we want?)  */
-      default:
-        if (GET_CODE (addr) == CONST_INT
-           && INTVAL (addr) < 0x8000
-           && INTVAL (addr) >= -0x8000)
-         {
-           if (MOTOROLA)
-#ifdef SGS
-             /* Many SGS assemblers croak on size specifiers for constants.  */
-             fprintf (file, "%d", (int) INTVAL (addr));
-#else
-             fprintf (file, "%d.w", (int) INTVAL (addr));
-#endif
-           else /* !MOTOROLA */
-             fprintf (file, "%d:w", (int) INTVAL (addr));
-         }
-       else if (GET_CODE (addr) == CONST_INT)
-         {
-           fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
-         }
-       else if (TARGET_PCREL)
-         {
-           fputc ('(', file);
-           output_addr_const (file, addr);
-           if (flag_pic == 1)
-             asm_fprintf (file, ":w,%Rpc)");
-           else
-             asm_fprintf (file, ":l,%Rpc)");
-         }
-       else
-         {
-           /* Special case for SYMBOL_REF if the symbol name ends in
-              `.<letter>', this can be mistaken as a size suffix.  Put
-              the name in parentheses.  */
-           if (GET_CODE (addr) == SYMBOL_REF
-               && strlen (XSTR (addr, 0)) > 2
-               && XSTR (addr, 0)[strlen (XSTR (addr, 0)) - 2] == '.')
-             {
-               putc ('(', file);
-               output_addr_const (file, addr);
-               putc (')', file);
-             }
-           else
+                 if (ireg != 0)
+                   putc (',', file);
+               }
+           } /* !MOTOROLA */
+         if (ireg != 0 && GET_CODE (ireg) == MULT)
+           {
+             scale = INTVAL (XEXP (ireg, 1));
+             ireg = XEXP (ireg, 0);
+           }
+         if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
+           fprintf (file, MOTOROLA ? "%s.w" : "%s:w",
+                    M68K_REGNAME (REGNO (XEXP (ireg, 0))));
+         else if (ireg != 0)
+           fprintf (file, MOTOROLA ? "%s.l" : "%s:l",
+                    M68K_REGNAME (REGNO (ireg)));
+         if (scale != 1)
+           fprintf (file, MOTOROLA ? "*%d" : ":%d", scale);
+         putc (')', file);
+         break;
+       }
+      else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
+              && ! (flag_pic && reg1 == pic_offset_table_rtx))
+       {
+         ASM_OUTPUT_CASE_FETCH (file,
+                                CODE_LABEL_NUMBER (XEXP (addr, 0)),
+                                M68K_REGNAME (REGNO (reg1)));
+         fprintf (file, "l)");
+         break;
+       }
+      /* FALL-THROUGH (is this really what we want?)  */
+    default:
+      if (GET_CODE (addr) == CONST_INT
+         && INTVAL (addr) < 0x8000
+         && INTVAL (addr) >= -0x8000)
+       {
+         fprintf (file, MOTOROLA ? "%d.w" : "%d:w", (int) INTVAL (addr));
+       }
+      else if (GET_CODE (addr) == CONST_INT)
+       {
+         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
+       }
+      else if (TARGET_PCREL)
+       {
+         fputc ('(', file);
+         output_addr_const (file, addr);
+         if (flag_pic == 1)
+           asm_fprintf (file, ":w,%Rpc)");
+         else
+           asm_fprintf (file, ":l,%Rpc)");
+       }
+      else
+       {
+         /* Special case for SYMBOL_REF if the symbol name ends in
+            `.<letter>', this can be mistaken as a size suffix.  Put
+            the name in parentheses.  */
+         if (GET_CODE (addr) == SYMBOL_REF
+             && strlen (XSTR (addr, 0)) > 2
+             && XSTR (addr, 0)[strlen (XSTR (addr, 0)) - 2] == '.')
+           {
+             putc ('(', file);
              output_addr_const (file, addr);
-         }
-       break;
+             putc (')', file);
+           }
+         else
+           output_addr_const (file, addr);
+       }
+      break;
     }
 }
 \f
@@ -3134,45 +3527,6 @@ strict_low_part_peephole_ok (enum machine_mode mode, rtx first_insn,
   return false;
 }
 
-/* Accept integer operands in the range 0..0xffffffff.  We have to check the
-   range carefully since this predicate is used in DImode contexts.  Also, we
-   need some extra crud to make it work when hosted on 64-bit machines.  */
-
-int
-const_uint32_operand (rtx op, enum machine_mode mode)
-{
-  /* It doesn't make sense to ask this question with a mode that is
-     not larger than 32 bits.  */
-  if (GET_MODE_BITSIZE (mode) <= 32)
-    abort ();
-
-#if HOST_BITS_PER_WIDE_INT > 32
-  /* All allowed constants will fit a CONST_INT.  */
-  return (GET_CODE (op) == CONST_INT
-         && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
-#else
-  return (GET_CODE (op) == CONST_INT
-         || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
-#endif
-}
-
-/* Accept integer operands in the range -0x80000000..0x7fffffff.  We have
-   to check the range carefully since this predicate is used in DImode
-   contexts.  */
-
-int
-const_sint32_operand (rtx op, enum machine_mode mode)
-{
-  /* It doesn't make sense to ask this question with a mode that is
-     not larger than 32 bits.  */
-  if (GET_MODE_BITSIZE (mode) <= 32)
-    abort ();
-
-  /* All allowed constants will fit a CONST_INT.  */
-  return (GET_CODE (op) == CONST_INT
-         && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
-}
-
 /* Operand predicates for implementing asymmetric pc-relative addressing
    on m68k.  The m68k supports pc-relative addressing (mode 7, register 2)
    when used as a source operand, but not as a destination operand.
@@ -3230,69 +3584,12 @@ const_sint32_operand (rtx op, enum machine_mode mode)
    ***************************************************************************/
 
 
-/* Special case of a general operand that's used as a source operand.
-   Use this to permit reads from PC-relative memory when -mpcrel
-   is specified.  */
-
-int
-general_src_operand (rtx op, enum machine_mode mode)
-{
-  if (TARGET_PCREL
-      && GET_CODE (op) == MEM
-      && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
-         || GET_CODE (XEXP (op, 0)) == LABEL_REF
-         || GET_CODE (XEXP (op, 0)) == CONST))
-    return 1;
-  return general_operand (op, mode);
-}
-
-/* Special case of a nonimmediate operand that's used as a source.
-   Use this to permit reads from PC-relative memory when -mpcrel
-   is specified.  */
-
-int
-nonimmediate_src_operand (rtx op, enum machine_mode mode)
-{
-  if (TARGET_PCREL && GET_CODE (op) == MEM
-      && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
-         || GET_CODE (XEXP (op, 0)) == LABEL_REF
-         || GET_CODE (XEXP (op, 0)) == CONST))
-    return 1;
-  return nonimmediate_operand (op, mode);
-}
-
-/* Special case of a memory operand that's used as a source.
-   Use this to permit reads from PC-relative memory when -mpcrel
-   is specified.  */
-
-int
-memory_src_operand (rtx op, enum machine_mode mode)
-{
-  if (TARGET_PCREL && GET_CODE (op) == MEM
-      && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
-         || GET_CODE (XEXP (op, 0)) == LABEL_REF
-         || GET_CODE (XEXP (op, 0)) == CONST))
-    return 1;
-  return memory_operand (op, mode);
-}
-
-/* Predicate that accepts only a pc-relative address.  This is needed
-   because pc-relative addresses don't satisfy the predicate
-   "general_src_operand".  */
-
-int
-pcrel_address (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF
-         || GET_CODE (op) == CONST);
-}
-
 const char *
 output_andsi3 (rtx *operands)
 {
   int logval;
   if (GET_CODE (operands[2]) == CONST_INT
-      && (INTVAL (operands[2]) | 0xffff) == (HOST_WIDE_INT)0xffffffff
+      && (INTVAL (operands[2]) | 0xffff) == -1
       && (DATA_REG_P (operands[0])
          || offsettable_memref_p (operands[0]))
       && !TARGET_COLDFIRE)
@@ -3312,9 +3609,7 @@ output_andsi3 (rtx *operands)
           || offsettable_memref_p (operands[0])))
     {
       if (DATA_REG_P (operands[0]))
-        {
-          operands[1] = GEN_INT (logval);
-        }
+       operands[1] = GEN_INT (logval);
       else
         {
          operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
@@ -3403,7 +3698,8 @@ output_xorsi3 (rtx *operands)
 /* Output assembly to switch to section NAME with attribute FLAGS.  */
 
 static void
-m68k_coff_asm_named_section (const char *name, unsigned int flags)
+m68k_coff_asm_named_section (const char *name, unsigned int flags, 
+                            tree decl ATTRIBUTE_UNUSED)
 {
   char flagchar;
 
@@ -3417,28 +3713,6 @@ m68k_coff_asm_named_section (const char *name, unsigned int flags)
 
 #endif /* M68K_TARGET_COFF */
 
-#ifdef HPUX_ASM
-static void
-m68k_hp320_internal_label (FILE *stream, const char *prefix,
-                           unsigned long labelno)
-{
-  if (prefix[0] == 'L' && prefix[1] == 'I')
-    fprintf(stream, "\tset %s%ld,.+2\n", prefix, labelno);
-  else
-    fprintf (stream, "%s%ld:\n", prefix, labelno);
-}
-
-static void
-m68k_hp320_file_start (void)
-{
-  /* version 1: 68010.
-             2: 68020 without FPU.
-            3: 68020 with FPU.  */
-  fprintf (asm_out_file, "\tversion %d\n",
-          TARGET_68020 ? (TARGET_68881 ? 3 : 2) : 1);
-}
-#endif
-
 static void
 m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
                      HOST_WIDE_INT delta,
@@ -3449,19 +3723,38 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
   const char *fmt;
 
   if (delta > 0 && delta <= 8)
-    asm_fprintf (file, MOTOROLA ?
-                        "\taddq.l %I%d,4(%Rsp)\n" :
-                        "\taddql %I%d,%Rsp@(4)\n",
+    asm_fprintf (file, (MOTOROLA
+                       ? "\taddq.l %I%d,4(%Rsp)\n"
+                       : "\taddql %I%d,%Rsp@(4)\n"),
                 (int) delta);
   else if (delta < 0 && delta >= -8)
-    asm_fprintf (file, MOTOROLA ?
-                        "\tsubq.l %I%d,4(%Rsp)\n" :
-                        "\tsubql %I%d,%Rsp@(4)\n",
+    asm_fprintf (file, (MOTOROLA
+                       ? "\tsubq.l %I%d,4(%Rsp)\n"
+                       : "\tsubql %I%d,%Rsp@(4)\n"),
                 (int) -delta);
+  else if (TARGET_COLDFIRE)
+    {
+      /* ColdFire can't add/sub a constant to memory unless it is in
+        the range of addq/subq.  So load the value into %d0 and
+        then add it to 4(%sp). */
+      if (delta >= -128 && delta <= 127)
+       asm_fprintf (file, (MOTOROLA
+                           ? "\tmoveq.l %I%wd,%Rd0\n"
+                           : "\tmoveql %I%wd,%Rd0\n"),
+                    delta);
+      else
+       asm_fprintf (file, (MOTOROLA
+                           ? "\tmove.l %I%wd,%Rd0\n"
+                           : "\tmovel %I%wd,%Rd0\n"),
+                    delta);
+      asm_fprintf (file, (MOTOROLA
+                         ? "\tadd.l %Rd0,4(%Rsp)\n"
+                         : "\taddl %Rd0,%Rsp@(4)\n"));
+    }
   else
-    asm_fprintf (file, MOTOROLA ?
-                        "\tadd.l %I%wd,4(%Rsp)\n" :
-                        "\taddl %I%wd,%Rsp@(4)\n",
+    asm_fprintf (file, (MOTOROLA
+                       ? "\tadd.l %I%wd,4(%Rsp)\n"
+                       : "\taddl %I%wd,%Rsp@(4)\n"),
                 delta);
 
   xops[0] = DECL_RTL (function);
@@ -3471,27 +3764,29 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
     {
       if (TARGET_PCREL)
        fmt = "bra.l %o0";
-      else if ((flag_pic == 1) || TARGET_68020)
+      else if (flag_pic == 1 || TARGET_68020)
        {
          if (MOTOROLA)
-#ifdef HPUX_ASM
-           fmt = "bra.l %0";
-#elif defined(USE_GAS)
-           fmt = "bra.l %0@PLTPC";
+           {
+#if defined (USE_GAS)
+             fmt = "bra.l %0@PLTPC";
 #else
-           fmt = "bra %0@PLTPC";
+             fmt = "bra %0@PLTPC";
 #endif
+           }
          else /* !MOTOROLA */
+           {
 #ifdef USE_GAS
-           fmt = "bra.l %0";
+             fmt = "bra.l %0";
 #else
-           fmt = "jra %0,a1";
+             fmt = "jra %0,a1";
 #endif
+           }
        }
       else if (optimize_size || TARGET_ID_SHARED_LIBRARY)
         fmt = "move.l %0@GOT(%%a5), %%a1\n\tjmp (%%a1)";
       else
-        fmt = "lea %0-.-8,%%a1\n\tjsr 0(%%pc,%%a1)";
+        fmt = "lea %0-.-8,%%a1\n\tjmp 0(%%pc,%%a1)";
     }
   else
     {
@@ -3513,3 +3808,99 @@ m68k_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
 {
   return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM);
 }
+
+/* Return nonzero if register old_reg can be renamed to register new_reg.  */
+int
+m68k_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
+                          unsigned int new_reg)
+{
+
+  /* Interrupt functions can only use registers that have already been
+     saved by the prologue, even if they would normally be
+     call-clobbered.  */
+
+  if (m68k_interrupt_function_p (current_function_decl)
+      && !regs_ever_live[new_reg])
+    return 0;
+
+  return 1;
+}
+
+/* Value is true if hard register REGNO can hold a value of machine-mode MODE.
+   On the 68000, the cpu registers can hold any mode except bytes in address
+   registers, but the 68881 registers can hold only SFmode or DFmode.  */
+bool
+m68k_regno_mode_ok (int regno, enum machine_mode mode)
+{
+  if (DATA_REGNO_P (regno))
+    {
+      /* Data Registers, can hold aggregate if fits in.  */
+      if (regno + GET_MODE_SIZE (mode) / 4 <= 8)
+       return true;
+    }
+  else if (ADDRESS_REGNO_P (regno))
+    {
+      /* Address Registers, can't hold bytes, can hold aggregate if
+        fits in.  */
+      if (GET_MODE_SIZE (mode) == 1)
+       return false;
+      if (regno + GET_MODE_SIZE (mode) / 4 <= 16)
+       return true;
+    }
+  else if (FP_REGNO_P (regno))
+    {
+      /* FPU registers, hold float or complex float of long double or
+        smaller.  */
+      if ((GET_MODE_CLASS (mode) == MODE_FLOAT
+          || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
+         && GET_MODE_UNIT_SIZE (mode) <= TARGET_FP_REG_SIZE)
+       return true;
+    }
+  return false;
+}
+
+/* Return floating point values in a 68881 register.  This makes 68881 code
+   a little bit faster.  It also makes -msoft-float code incompatible with
+   hard-float code, so people have to be careful not to mix the two.
+   For ColdFire it was decided the ABI incompatibility is undesirable.
+   If there is need for a hard-float ABI it is probably worth doing it
+   properly and also passing function arguments in FP registers.  */
+rtx
+m68k_libcall_value (enum machine_mode mode)
+{
+  switch (mode) {
+  case SFmode:
+  case DFmode:
+  case XFmode:
+    if (TARGET_68881)
+      return gen_rtx_REG (mode, 16);
+    break;
+  default:
+    break;
+  }
+  return gen_rtx_REG (mode, 0);
+}
+
+rtx
+m68k_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
+{
+  enum machine_mode mode;
+
+  mode = TYPE_MODE (valtype);
+  switch (mode) {
+  case SFmode:
+  case DFmode:
+  case XFmode:
+    if (TARGET_68881)
+      return gen_rtx_REG (mode, 16);
+    break;
+  default:
+    break;
+  }
+
+  /* If the function returns a pointer, push that into %a0 */
+  if (POINTER_TYPE_P (valtype))
+    return gen_rtx_REG (mode, 8);
+  else
+    return gen_rtx_REG (mode, 0);
+}