OSDN Git Service

* config/mcore/mcore.c Don't include assert.h.
[pf3gnuchains/gcc-fork.git] / gcc / config / mcore / mcore.c
index 61fc5bd..6227b17 100644 (file)
@@ -1,33 +1,33 @@
 /* Output routines for Motorola MCore processor
-   Copyright (C) 1993, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
+   2009, 2010 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+   This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
 
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tree.h"
 #include "tm_p.h"
-#include "assert.h"
 #include "mcore.h"
 #include "regs.h"
 #include "hard-reg-set.h"
-#include "real.h"
 #include "insn-config.h"
 #include "conditions.h"
 #include "output.h"
@@ -39,15 +39,10 @@ Boston, MA 02111-1307, USA.  */
 #include "recog.h"
 #include "function.h"
 #include "ggc.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "target.h"
 #include "target-def.h"
-
-/* Maximum size we are allowed to grow the stack in a single operation.
-   If we want more, we must do it in increments of at most this size.
-   If this value is 0, we don't check at all.  */
-const char * mcore_stack_increment_string = 0;
-int          mcore_stack_increment = STACK_UNITS_MAXSTEP;
+#include "df.h"
 
 /* For dumping information about frame sizes.  */
 char * mcore_current_function_name = 0;
@@ -55,14 +50,9 @@ long   mcore_current_compilation_timestamp = 0;
 
 /* Global variables for machine-dependent things.  */
 
-/* Saved operands from the last compare to use when we generate an scc
-  or bcc insn.  */
-rtx arch_compare_op0;
-rtx arch_compare_op1;
-
 /* Provides the class number of the smallest class containing
    reg number.  */
-const int regno_reg_class[FIRST_PSEUDO_REGISTER] =
+const enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER] =
 {
   GENERAL_REGS,        ONLYR1_REGS,  LRW_REGS,     LRW_REGS,
   LRW_REGS,    LRW_REGS,     LRW_REGS,     LRW_REGS,
@@ -86,16 +76,16 @@ const enum reg_class reg_class_from_letter[] =
 
 struct mcore_frame
 {
-  int arg_size;                        /* stdarg spills (bytes) */
-  int reg_size;                        /* non-volatile reg saves (bytes) */
-  int reg_mask;                        /* non-volatile reg saves */
-  int local_size;              /* locals */
-  int outbound_size;           /* arg overflow on calls out */
+  int arg_size;                        /* Stdarg spills (bytes).  */
+  int reg_size;                        /* Non-volatile reg saves (bytes).  */
+  int reg_mask;                        /* Non-volatile reg saves.  */
+  int local_size;              /* Locals.  */
+  int outbound_size;           /* Arg overflow on calls out.  */
   int pad_outbound;
   int pad_local;
   int pad_reg;
   /* Describe the steps we'll use to grow it.  */
-#define        MAX_STACK_GROWS 4       /* gives us some spare space */
+#define        MAX_STACK_GROWS 4       /* Gives us some spare space.  */
   int growth[MAX_STACK_GROWS];
   int arg_offset;
   int reg_offset;
@@ -114,70 +104,177 @@ typedef enum
 }
 cond_type;
 
-static void       output_stack_adjust          PARAMS ((int, int));
-static int        calc_live_regs               PARAMS ((int *));
-static int        const_ok_for_mcore           PARAMS ((int));
-static int        try_constant_tricks          PARAMS ((long, int *, int *));
-static const char *     output_inline_const          PARAMS ((enum machine_mode, rtx *));
-static void       block_move_sequence          PARAMS ((rtx, rtx, rtx, rtx, int, int, int));
-static void       layout_mcore_frame           PARAMS ((struct mcore_frame *));
-static cond_type  is_cond_candidate            PARAMS ((rtx));
-static rtx        emit_new_cond_insn           PARAMS ((rtx, int));
-static rtx        conditionalize_block         PARAMS ((rtx));
-static void       conditionalize_optimization  PARAMS ((rtx));
-static void       mcore_add_gc_roots           PARAMS ((void));
-static rtx        handle_structs_in_regs       PARAMS ((enum machine_mode, tree, int));
-static void       mcore_mark_dllexport         PARAMS ((tree));
-static void       mcore_mark_dllimport         PARAMS ((tree));
-static int        mcore_dllexport_p            PARAMS ((tree));
-static int        mcore_dllimport_p            PARAMS ((tree));
-const struct attribute_spec mcore_attribute_table[];
-static tree       mcore_handle_naked_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static void       output_stack_adjust           (int, int);
+static int        calc_live_regs                (int *);
+static int        try_constant_tricks           (long, HOST_WIDE_INT *, HOST_WIDE_INT *);
+static const char *     output_inline_const     (enum machine_mode, rtx *);
+static void       layout_mcore_frame            (struct mcore_frame *);
+static void       mcore_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int);
+static cond_type  is_cond_candidate             (rtx);
+static rtx        emit_new_cond_insn            (rtx, int);
+static rtx        conditionalize_block          (rtx);
+static void       conditionalize_optimization   (void);
+static void       mcore_reorg                   (void);
+static rtx        handle_structs_in_regs        (enum machine_mode, const_tree, int);
+static void       mcore_mark_dllexport          (tree);
+static void       mcore_mark_dllimport          (tree);
+static int        mcore_dllexport_p             (tree);
+static int        mcore_dllimport_p             (tree);
+static tree       mcore_handle_naked_attribute  (tree *, tree, tree, int, bool *);
 #ifdef OBJECT_FORMAT_ELF
-static void      mcore_asm_named_section      PARAMS ((const char *,
-                                                       unsigned int));
+static void      mcore_asm_named_section       (const char *,
+                                                unsigned int, tree);
 #endif
-static void       mcore_unique_section        PARAMS ((tree, int));
-static void mcore_encode_section_info          PARAMS ((tree, int));
+static void       mcore_print_operand           (FILE *, rtx, int);
+static void       mcore_print_operand_address   (FILE *, rtx);
+static bool       mcore_print_operand_punct_valid_p (unsigned char code);
+static void       mcore_unique_section         (tree, int);
+static void mcore_encode_section_info          (tree, rtx, int);
+static const char *mcore_strip_name_encoding   (const char *);
+static int        mcore_const_costs                    (rtx, RTX_CODE);
+static int        mcore_and_cost                       (rtx);
+static int        mcore_ior_cost                       (rtx);
+static bool       mcore_rtx_costs              (rtx, int, int, int *, bool);
+static void       mcore_external_libcall       (rtx);
+static bool       mcore_return_in_memory       (const_tree, const_tree);
+static int        mcore_arg_partial_bytes       (CUMULATIVE_ARGS *,
+                                                enum machine_mode,
+                                                tree, bool);
+static rtx        mcore_function_arg            (CUMULATIVE_ARGS *,
+                                                enum machine_mode,
+                                                const_tree, bool);
+static void       mcore_function_arg_advance    (CUMULATIVE_ARGS *,
+                                                enum machine_mode,
+                                                const_tree, bool);
+static unsigned int mcore_function_arg_boundary (enum machine_mode,
+                                                const_tree);
+static void       mcore_asm_trampoline_template (FILE *);
+static void       mcore_trampoline_init                (rtx, tree, rtx);
+static void       mcore_option_override                (void);
+\f
+/* MCore specific attributes.  */
+
+static const struct attribute_spec mcore_attribute_table[] =
+{
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+  { "dllexport", 0, 0, true,  false, false, NULL },
+  { "dllimport", 0, 0, true,  false, false, NULL },
+  { "naked",     0, 0, true,  false, false, mcore_handle_naked_attribute },
+  { NULL,        0, 0, false, false, false, NULL }
+};
+
+/* What options are we going to default to specific settings when
+   -O* happens; the user can subsequently override these settings.
+  
+   Omitting the frame pointer is a very good idea on the MCore.
+   Scheduling isn't worth anything on the current MCore implementation.  */
+
+static const struct default_options mcore_option_optimization_table[] =
+  {
+    { OPT_LEVELS_1_PLUS, OPT_ffunction_cse, NULL, 0 },
+    { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
+    { OPT_LEVELS_ALL, OPT_fcaller_saves, NULL, 0 },
+    { OPT_LEVELS_ALL, OPT_fschedule_insns, NULL, 0 },
+    { OPT_LEVELS_ALL, OPT_fschedule_insns2, NULL, 0 },
+    { OPT_LEVELS_SIZE, OPT_mhardlit, NULL, 0 },
+    { OPT_LEVELS_NONE, 0, NULL, 0 }
+  };
 \f
 /* Initialize the GCC target structure.  */
-#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
-#undef TARGET_MERGE_DECL_ATTRIBUTES
-#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
+#undef  TARGET_ASM_EXTERNAL_LIBCALL
+#define TARGET_ASM_EXTERNAL_LIBCALL    mcore_external_libcall
+
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
+#undef  TARGET_MERGE_DECL_ATTRIBUTES
+#define TARGET_MERGE_DECL_ATTRIBUTES   merge_dllimport_decl_attributes
 #endif
 
 #ifdef OBJECT_FORMAT_ELF
-#undef TARGET_ASM_UNALIGNED_HI_OP
+#undef  TARGET_ASM_UNALIGNED_HI_OP
 #define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t"
-#undef TARGET_ASM_UNALIGNED_SI_OP
+#undef  TARGET_ASM_UNALIGNED_SI_OP
 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
 #endif
 
-#undef TARGET_ATTRIBUTE_TABLE
-#define TARGET_ATTRIBUTE_TABLE mcore_attribute_table
-#undef TARGET_ASM_UNIQUE_SECTION
-#define TARGET_ASM_UNIQUE_SECTION mcore_unique_section
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO mcore_encode_section_info
+#undef  TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND           mcore_print_operand
+#undef  TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS   mcore_print_operand_address
+#undef  TARGET_PRINT_OPERAND_PUNCT_VALID_P
+#define TARGET_PRINT_OPERAND_PUNCT_VALID_P mcore_print_operand_punct_valid_p
+
+#undef  TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE                 mcore_attribute_table
+#undef  TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION      mcore_unique_section
+#undef  TARGET_ASM_FUNCTION_RODATA_SECTION
+#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
+#undef  TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS    TARGET_DEFAULT
+#undef  TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO     mcore_encode_section_info
+#undef  TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING     mcore_strip_name_encoding
+#undef  TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS               mcore_rtx_costs
+#undef  TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST            hook_int_rtx_bool_0
+#undef  TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG mcore_reorg
+
+#undef  TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE   default_promote_function_mode_always_promote
+#undef  TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES      hook_bool_const_tree_true
+
+#undef  TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY                mcore_return_in_memory
+#undef  TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK      must_pass_in_stack_var_size
+#undef  TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE  hook_pass_by_reference_must_pass_in_stack
+#undef  TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES       mcore_arg_partial_bytes
+#undef  TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG            mcore_function_arg
+#undef  TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE    mcore_function_arg_advance
+#undef  TARGET_FUNCTION_ARG_BOUNDARY
+#define TARGET_FUNCTION_ARG_BOUNDARY   mcore_function_arg_boundary
+
+#undef  TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS  mcore_setup_incoming_varargs
+
+#undef  TARGET_ASM_TRAMPOLINE_TEMPLATE
+#define TARGET_ASM_TRAMPOLINE_TEMPLATE mcore_asm_trampoline_template
+#undef  TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT         mcore_trampoline_init
+
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE mcore_option_override
+#undef TARGET_OPTION_OPTIMIZATION_TABLE
+#define TARGET_OPTION_OPTIMIZATION_TABLE mcore_option_optimization_table
+
+#undef TARGET_EXCEPT_UNWIND_INFO
+#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Adjust the stack and return the number of bytes taken to do it.  */
 static void
-output_stack_adjust (direction, size)
-     int direction;
-     int size;
+output_stack_adjust (int direction, int size)
 {
   /* If extending stack a lot, we do it incrementally.  */
   if (direction < 0 && size > mcore_stack_increment && mcore_stack_increment > 0)
     {
-      rtx tmp = gen_rtx (REG, SImode, 1);
+      rtx tmp = gen_rtx_REG (SImode, 1);
       rtx memref;
+
       emit_insn (gen_movsi (tmp, GEN_INT (mcore_stack_increment)));
       do
        {
          emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
-         memref = gen_rtx (MEM, SImode, stack_pointer_rtx);
+         memref = gen_rtx_MEM (SImode, stack_pointer_rtx);
          MEM_VOLATILE_P (memref) = 1;
          emit_insn (gen_movsi (memref, stack_pointer_rtx));
          size -= mcore_stack_increment;
@@ -195,7 +292,7 @@ output_stack_adjust (direction, size)
 
       if (size > 32)
        {
-         rtx nval = gen_rtx (REG, SImode, 1);
+         rtx nval = gen_rtx_REG (SImode, 1);
          emit_insn (gen_movsi (nval, val));
          val = nval;
        }
@@ -213,8 +310,7 @@ output_stack_adjust (direction, size)
    both as a mask and a count.  */
 
 static int
-calc_live_regs (count)
-     int * count;
+calc_live_regs (int * count)
 {
   int reg;
   int live_regs_mask = 0;
@@ -223,7 +319,7 @@ calc_live_regs (count)
 
   for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
     {
-      if (regs_ever_live[reg] && !call_used_regs[reg])
+      if (df_regs_ever_live_p (reg) && !call_used_regs[reg])
        {
          (*count)++;
          live_regs_mask |= (1 << reg);
@@ -235,10 +331,8 @@ calc_live_regs (count)
 
 /* Print the operand address in x to the stream.  */
 
-void
-mcore_print_operand_address (stream, x)
-     FILE * stream;
-     rtx x;
+static void
+mcore_print_operand_address (FILE * stream, rtx x)
 {
   switch (GET_CODE (x))
     {
@@ -262,14 +356,12 @@ mcore_print_operand_address (stream, x)
        switch (GET_CODE (index))
          {
          case CONST_INT:
-           fprintf (stream, "(%s,%d)", reg_names[REGNO(base)],
-                    INTVAL (index));
+           fprintf (stream, "(%s," HOST_WIDE_INT_PRINT_DEC ")",
+                    reg_names[REGNO(base)], INTVAL (index));
            break;
 
          default:
-           debug_rtx (x);
-
-           abort ();
+           gcc_unreachable ();
          }
       }
 
@@ -281,10 +373,17 @@ mcore_print_operand_address (stream, x)
     }
 }
 
+static bool
+mcore_print_operand_punct_valid_p (unsigned char code)
+{
+  return (code == '.' || code == '#' || code == '*' || code == '^'
+         || code == '!');
+}
+
 /* Print operand x (an rtx) in assembler syntax to file stream
    according to modifier code.
 
-   'R'  print the next register or memory location along, ie the lsw in
+   'R'  print the next register or memory location along, i.e. the lsw in
         a double word value
    'O'  print a constant without the #
    'M'  print a constant as its negative
@@ -293,11 +392,8 @@ mcore_print_operand_address (stream, x)
    'U'  print register for ldm/stm instruction
    'X'  print byte number for xtrbN instruction.  */
 
-void
-mcore_print_operand (stream, x, code)
-     FILE * stream;
-     rtx x;
-     int code;
+static void
+mcore_print_operand (FILE * stream, rtx x, int code)
 {
   switch (code)
     {
@@ -308,16 +404,16 @@ mcore_print_operand (stream, x, code)
        fprintf (asm_out_file, "%d", exact_log2 (INTVAL (x) + 1));
       break;
     case 'P':
-      fprintf (asm_out_file, "%d", exact_log2 (INTVAL (x)));
+      fprintf (asm_out_file, "%d", exact_log2 (INTVAL (x) & 0xffffffff));
       break;
     case 'Q':
       fprintf (asm_out_file, "%d", exact_log2 (~INTVAL (x)));
       break;
     case 'O':
-      fprintf (asm_out_file, "%d", INTVAL (x));
+      fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
       break;
     case 'M':
-      fprintf (asm_out_file, "%d", - INTVAL (x));
+      fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, - INTVAL (x));
       break;
     case 'R':
       /* Next location along in memory or register.  */
@@ -331,7 +427,7 @@ mcore_print_operand (stream, x, code)
            (stream, XEXP (adjust_address (x, SImode, 4), 0));
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
       break;
     case 'U':
@@ -339,10 +435,10 @@ mcore_print_operand (stream, x, code)
               reg_names[REGNO (x) + 3]);
       break;
     case 'x':
-      fprintf (asm_out_file, "0x%x", INTVAL (x));
+      fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
       break;
     case 'X':
-      fprintf (asm_out_file, "%d", 3 - INTVAL (x) / 8);
+      fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, 3 - INTVAL (x) / 8);
       break;
 
     default:
@@ -364,13 +460,10 @@ mcore_print_operand (stream, x, code)
 
 /* What does a constant cost ?  */
 
-int
-mcore_const_costs (exp, code)
-     rtx exp;
-     enum rtx_code code;
+static int
+mcore_const_costs (rtx exp, enum rtx_code code)
 {
-
-  int val = INTVAL (exp);
+  HOST_WIDE_INT val = INTVAL (exp);
 
   /* Easy constants.  */
   if (   CONST_OK_FOR_I (val)  
@@ -395,11 +488,10 @@ mcore_const_costs (exp, code)
    have been relaxed.   We want to ensure that cse will cse relaxed immeds
    out.  Otherwise we'll get bad code (multiple reloads of the same const).  */
 
-int
-mcore_and_cost (x)
-     rtx x;
+static int
+mcore_and_cost (rtx x)
 {
-  int val;
+  HOST_WIDE_INT val;
 
   if (GET_CODE (XEXP (x, 1)) != CONST_INT)
     return 2;
@@ -422,11 +514,10 @@ mcore_and_cost (x)
 
 /* What does an or cost - see and_cost().  */
 
-int
-mcore_ior_cost (x)
-     rtx x;
+static int
+mcore_ior_cost (rtx x)
 {
-  int val;
+  HOST_WIDE_INT val;
 
   if (GET_CODE (XEXP (x, 1)) != CONST_INT)
     return 2;
@@ -447,27 +538,76 @@ mcore_ior_cost (x)
   return 5;
 }
 
-/* Check to see if a comparison against a constant can be made more efficient
-   by incrementing/decrementing the constant to get one that is more efficient
-   to load.  */
-
-int
-mcore_modify_comparison (code)
-     enum rtx_code code;
+static bool
+mcore_rtx_costs (rtx x, int code, int outer_code, int * total,
+                bool speed ATTRIBUTE_UNUSED)
 {
-  rtx op1   = arch_compare_op1;
+  switch (code)
+    {
+    case CONST_INT:
+      *total = mcore_const_costs (x, (enum rtx_code) outer_code);
+      return true;
+    case CONST:
+    case LABEL_REF:
+    case SYMBOL_REF:
+      *total = 5;
+      return true;
+    case CONST_DOUBLE:
+      *total = 10;
+      return true;
+
+    case AND:
+      *total = COSTS_N_INSNS (mcore_and_cost (x));
+      return true;
+
+    case IOR:
+      *total = COSTS_N_INSNS (mcore_ior_cost (x));
+      return true;
+
+    case DIV:
+    case UDIV:
+    case MOD:
+    case UMOD:
+    case FLOAT:
+    case FIX:
+      *total = COSTS_N_INSNS (100);
+      return true;
   
+    default:
+      return false;
+    }
+}
+
+/* Prepare the operands for a comparison.  Return whether the branch/setcc
+   should reverse the operands.  */
+
+bool
+mcore_gen_compare (enum rtx_code code, rtx op0, rtx op1)
+{
+  rtx cc_reg = gen_rtx_REG (CCmode, CC_REG);
+  bool invert;
+
   if (GET_CODE (op1) == CONST_INT)
     {
-      int val = INTVAL (op1);
+      HOST_WIDE_INT val = INTVAL (op1);
       
       switch (code)
        {
+       case GTU:
+         /* Unsigned > 0 is the same as != 0; everything else is converted
+            below to LEU (reversed cmphs).  */
+         if (val == 0)
+           code = NE;
+         break;
+
+        /* Check whether (LE A imm) can become (LT A imm + 1),
+          or (GT A imm) can become (GE A imm + 1).  */
+       case GT:
        case LE:
          if (CONST_OK_FOR_J (val + 1))
            {
-             arch_compare_op1 = GEN_INT (val + 1);
-             return 1;
+             op1 = GEN_INT (val + 1);
+             code = code == LE ? LT : GE;
            }
          break;
          
@@ -475,30 +615,19 @@ mcore_modify_comparison (code)
          break;
        }
     }
-  
-  return 0;
-}
-
-/* Prepare the operands for a comparison.  */
-
-rtx
-mcore_gen_compare_reg (code)
-     enum rtx_code code;
-{
-  rtx op0 = arch_compare_op0;
-  rtx op1 = arch_compare_op1;
-  rtx cc_reg = gen_rtx (REG, CCmode, CC_REG);
-
   if (CONSTANT_P (op1) && GET_CODE (op1) != CONST_INT)
     op1 = force_reg (SImode, op1);
 
   /* cmpnei: 0-31 (K immediate)
      cmplti: 1-32 (J immediate, 0 using btsti x,31).  */
+  invert = false;
   switch (code)
     {
     case EQ:   /* Use inverted condition, cmpne.  */
       code = NE;
-      /* drop through */
+      invert = true;
+      /* Drop through.  */
       
     case NE:   /* Use normal condition, cmpne.  */
       if (GET_CODE (op1) == CONST_INT && ! CONST_OK_FOR_K (INTVAL (op1)))
@@ -507,7 +636,8 @@ mcore_gen_compare_reg (code)
 
     case LE:   /* Use inverted condition, reversed cmplt.  */
       code = GT;
-      /* drop through */
+      invert = true;
+      /* Drop through.  */
       
     case GT:   /* Use normal condition, reversed cmplt.  */
       if (GET_CODE (op1) == CONST_INT)
@@ -516,40 +646,33 @@ mcore_gen_compare_reg (code)
 
     case GE:   /* Use inverted condition, cmplt.  */
       code = LT;
-      /* drop through */
+      invert = true;
+      /* Drop through.  */
       
     case LT:   /* Use normal condition, cmplt.  */
       if (GET_CODE (op1) == CONST_INT && 
-         /* covered by btsti x,31 */
+         /* covered by btsti x,31 */
          INTVAL (op1) != 0 &&
          ! CONST_OK_FOR_J (INTVAL (op1)))
        op1 = force_reg (SImode, op1);
       break;
 
     case GTU:  /* Use inverted condition, cmple.  */
-      if (GET_CODE (op1) == CONST_INT && INTVAL (op1) == 0)
-       {
-         /* Unsigned > 0 is the same as != 0, but we need
-            to invert the condition, so we want to set
-            code = EQ.  This cannot be done however, as the
-            mcore does not support such a test.  Instead we
-            cope with this case in the "bgtu" pattern itself
-            so we should never reach this point.  */
-         /* code = EQ; */
-         abort ();
-         break;
-       }
+      /* We coped with unsigned > 0 above.  */
+      gcc_assert (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0);
       code = LEU;
-      /* drop through */
+      invert = true;
+      /* Drop through.  */
       
-    case LEU:  /* Use normal condition, reversed cmphs. */
+    case LEU:  /* Use normal condition, reversed cmphs.  */
       if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0)
        op1 = force_reg (SImode, op1);
       break;
 
     case LTU:  /* Use inverted condition, cmphs.  */
       code = GEU;
-      /* drop through */
+      invert = true;
+      /* Drop through.  */
       
     case GEU:  /* Use normal condition, cmphs.  */
       if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0)
@@ -560,15 +683,14 @@ mcore_gen_compare_reg (code)
       break;
     }
 
-  emit_insn (gen_rtx (SET, VOIDmode, cc_reg, gen_rtx (code, CCmode, op0, op1)));
-  
-  return cc_reg;
+  emit_insn (gen_rtx_SET (VOIDmode,
+                         cc_reg,
+                         gen_rtx_fmt_ee (code, CCmode, op0, op1)));
+  return invert;
 }
 
-
 int
-mcore_symbolic_address_p (x)
-     rtx x;
+mcore_symbolic_address_p (rtx x)
 {
   switch (GET_CODE (x))
     {
@@ -585,20 +707,10 @@ mcore_symbolic_address_p (x)
     }
 }
 
-int
-mcore_call_address_operand (x, mode)
-     rtx x;
-     enum machine_mode mode;
-{
-  return register_operand (x, mode) || CONSTANT_P (x);
-}
-
 /* Functions to output assembly code for a function call.  */
 
 char *
-mcore_output_call (operands, index)
-     rtx operands[];
-     int index;
+mcore_output_call (rtx operands[], int index)
 {
   static char buffer[20];
   rtx addr = operands [index];
@@ -607,8 +719,7 @@ mcore_output_call (operands, index)
     {
       if (TARGET_CG_DATA)
        {
-         if (mcore_current_function_name == 0)
-           abort ();
+         gcc_assert (mcore_current_function_name);
          
          ASM_OUTPUT_CG_EDGE (asm_out_file, mcore_current_function_name,
                              "unknown", 1);
@@ -620,13 +731,11 @@ mcore_output_call (operands, index)
     {
       if (TARGET_CG_DATA)
        {
-         if (mcore_current_function_name == 0)
-           abort ();
+         gcc_assert (mcore_current_function_name);
+         gcc_assert (GET_CODE (addr) == SYMBOL_REF);
          
-         if (GET_CODE (addr) != SYMBOL_REF)
-           abort ();
-         
-         ASM_OUTPUT_CG_EDGE (asm_out_file, mcore_current_function_name, XSTR (addr, 0), 0);
+         ASM_OUTPUT_CG_EDGE (asm_out_file, mcore_current_function_name,
+                             XSTR (addr, 0), 0);
        }
       
       sprintf (buffer, "jbsr\t%%%d", index);
@@ -637,19 +746,18 @@ mcore_output_call (operands, index)
 
 /* Can we load a constant with a single instruction ?  */
 
-static int
-const_ok_for_mcore (value)
-     int value;
+int
+const_ok_for_mcore (HOST_WIDE_INT value)
 {
   if (value >= 0 && value <= 127)
     return 1;
   
   /* Try exact power of two.  */
-  if ((value & (value - 1)) == 0)
+  if (CONST_OK_FOR_M (value))
     return 1;
   
-  /* Try exact power of two - 1. */
-  if ((value & (value + 1)) == 0)
+  /* Try exact power of two - 1.  */
+  if (CONST_OK_FOR_N (value) && value != -1)
     return 1;
   
   return 0;
@@ -658,10 +766,9 @@ const_ok_for_mcore (value)
 /* Can we load a constant inline with up to 2 instructions ?  */
 
 int
-mcore_const_ok_for_inline (value)
-     long value;
+mcore_const_ok_for_inline (HOST_WIDE_INT value)
 {
-  int x, y;
+  HOST_WIDE_INT x, y;
    
   return try_constant_tricks (value, & x, & y) > 0;
 }
@@ -669,10 +776,9 @@ mcore_const_ok_for_inline (value)
 /* Are we loading the constant using a not ?  */
 
 int
-mcore_const_trick_uses_not (value)
-     long value;
+mcore_const_trick_uses_not (HOST_WIDE_INT value)
 {
-  int x, y;
+  HOST_WIDE_INT x, y;
 
   return try_constant_tricks (value, & x, & y) == 2; 
 }       
@@ -694,129 +800,124 @@ mcore_const_trick_uses_not (value)
    11: single insn followed by ixw.  */
 
 static int
-try_constant_tricks (value, x, y)
-     long value;
-     int * x;
-     int * y;
+try_constant_tricks (HOST_WIDE_INT value, HOST_WIDE_INT * x, HOST_WIDE_INT * y)
 {
-  int i;
-  unsigned bit, shf, rot;
+  HOST_WIDE_INT i;
+  unsigned HOST_WIDE_INT bit, shf, rot;
 
   if (const_ok_for_mcore (value))
     return 1;  /* Do the usual thing.  */
   
-  if (TARGET_HARDLIT) 
+  if (! TARGET_HARDLIT) 
+    return 0;
+
+  if (const_ok_for_mcore (~value))
+    {
+      *x = ~value;
+      return 2;
+    }
+
+  for (i = 1; i <= 32; i++)
     {
-      if (const_ok_for_mcore (~value))
+      if (const_ok_for_mcore (value - i))
        {
-         *x = ~value;
-         return 2;
+         *x = value - i;
+         *y = i;
+
+         return 3;
        }
-      
-      for (i = 1; i <= 32; i++)
+
+      if (const_ok_for_mcore (value + i))
        {
-         if (const_ok_for_mcore (value - i))
-           {
-             *x = value - i;
-             *y = i;
-             
-             return 3;
-           }
-         
-         if (const_ok_for_mcore (value + i))
-           {
-             *x = value + i;
-             *y = i;
-             
-             return 4;
-           }
+         *x = value + i;
+         *y = i;
+
+         return 4;
        }
-      
-      bit = 0x80000000L;
-      
-      for (i = 0; i <= 31; i++)
+    }
+
+  bit = 0x80000000ULL;
+
+  for (i = 0; i <= 31; i++)
+    {
+      if (const_ok_for_mcore (i - value))
        {
-         if (const_ok_for_mcore (i - value))
-           {
-             *x = i - value;
-             *y = i;
-             
-             return 5;
-           }
-         
-         if (const_ok_for_mcore (value & ~bit))
-           {
-             *y = bit;
-             *x = value & ~bit;
-             
-             return 6;
-           }
-         
-         if (const_ok_for_mcore (value | bit))
-           {
-             *y = ~bit;
-             *x = value | bit;
-             
-             return 7;
-           }
-         
-         bit >>= 1;
+         *x = i - value;
+         *y = i;
+
+         return 5;
        }
-      
-      shf = value;
-      rot = value;
-      
-      for (i = 1; i < 31; i++)
+
+      if (const_ok_for_mcore (value & ~bit))
        {
-         int c;
-         
-         /* MCore has rotate left.  */
-         c = rot << 31;
-         rot >>= 1;
-         rot &= 0x7FFFFFFF;
-         rot |= c;   /* Simulate rotate.  */
-         
-         if (const_ok_for_mcore (rot))
-           {
-             *y = i;
-             *x = rot;
-             
-             return 8;
-           }
-         
-         if (shf & 1)
-           shf = 0;    /* Can't use logical shift, low order bit is one.  */
-         
-         shf >>= 1;
-         
-         if (shf != 0 && const_ok_for_mcore (shf))
-           {
-             *y = i;
-             *x = shf;
-             
-             return 9;
-           }
+         *y = bit;
+         *x = value & ~bit;
+         return 6;
        }
-      
-      if ((value % 3) == 0 && const_ok_for_mcore (value / 3))
+
+      if (const_ok_for_mcore (value | bit))
        {
-         *x = value / 3;
-         
-         return 10;
+         *y = ~bit;
+         *x = value | bit;
+
+         return 7;
        }
-      
-      if ((value % 5) == 0 && const_ok_for_mcore (value / 5))
+
+      bit >>= 1;
+    }
+
+  shf = value;
+  rot = value;
+
+  for (i = 1; i < 31; i++)
+    {
+      int c;
+
+      /* MCore has rotate left.  */
+      c = rot << 31;
+      rot >>= 1;
+      rot &= 0x7FFFFFFF;
+      rot |= c;   /* Simulate rotate.  */
+
+      if (const_ok_for_mcore (rot))
        {
-         *x = value / 5;
-         
-         return 11;
+         *y = i;
+         *x = rot;
+
+         return 8;
        }
+
+      if (shf & 1)
+       shf = 0;        /* Can't use logical shift, low order bit is one.  */
+
+      shf >>= 1;
+
+      if (shf != 0 && const_ok_for_mcore (shf))
+       {
+         *y = i;
+         *x = shf;
+
+         return 9;
+       }
+    }
+
+  if ((value % 3) == 0 && const_ok_for_mcore (value / 3))
+    {
+      *x = value / 3;
+
+      return 10;
+    }
+
+  if ((value % 5) == 0 && const_ok_for_mcore (value / 5))
+    {
+      *x = value / 5;
+
+      return 11;
     }
   
   return 0;
 }
 
-
 /* Check whether reg is dead at first.  This is done by searching ahead
    for either the next use (i.e., reg is live), a death note, or a set of
    reg.  Don't just use dead_or_set_p() since reload does not always mark 
@@ -824,9 +925,7 @@ try_constant_tricks (value, x, y)
    can ignore subregs by extracting the actual register.  BRC  */
 
 int
-mcore_is_dead (first, reg)
-     rtx first;
-     rtx reg;
+mcore_is_dead (rtx first, rtx reg)
 {
   rtx insn;
 
@@ -863,17 +962,15 @@ mcore_is_dead (first, reg)
        }
     }
 
-  /* No conclusive evidence either way, we can not take the chance
+  /* No conclusive evidence either way, we cannot take the chance
      that control flow hid the use from us -- "I'm not dead yet".  */
   return 0;
 }
 
-
 /* Count the number of ones in mask.  */
 
 int
-mcore_num_ones (mask)
-     int mask;
+mcore_num_ones (HOST_WIDE_INT mask)
 {
   /* A trick to count set bits recently posted on comp.compilers.  */
   mask =  (mask >> 1  & 0x55555555) + (mask & 0x55555555);
@@ -887,8 +984,7 @@ mcore_num_ones (mask)
 /* Count the number of zeros in mask.  */
 
 int
-mcore_num_zeros (mask)
-     int mask;
+mcore_num_zeros (HOST_WIDE_INT mask)
 {
   return 32 - mcore_num_ones (mask);
 }
@@ -896,8 +992,7 @@ mcore_num_zeros (mask)
 /* Determine byte being masked.  */
 
 int
-mcore_byte_offset (mask)
-     unsigned int mask;
+mcore_byte_offset (unsigned int mask)
 {
   if (mask == 0x00ffffffL)
     return 0;
@@ -914,8 +1009,7 @@ mcore_byte_offset (mask)
 /* Determine halfword being masked.  */
 
 int
-mcore_halfword_offset (mask)
-     unsigned int mask;
+mcore_halfword_offset (unsigned int mask)
 {
   if (mask == 0x0000ffffL)
     return 0;
@@ -928,9 +1022,7 @@ mcore_halfword_offset (mask)
 /* Output a series of bseti's corresponding to mask.  */
 
 const char *
-mcore_output_bseti (dst, mask)
-     rtx dst;
-     int mask;
+mcore_output_bseti (rtx dst, int mask)
 {
   rtx out_operands[2];
   int bit;
@@ -954,9 +1046,7 @@ mcore_output_bseti (dst, mask)
 /* Output a series of bclri's corresponding to mask.  */
 
 const char *
-mcore_output_bclri (dst, mask)
-     rtx dst;
-     int mask;
+mcore_output_bclri (rtx dst, int mask)
 {
   rtx out_operands[2];
   int bit;
@@ -983,13 +1073,10 @@ mcore_output_bclri (dst, mask)
    really worth the effort.  */
 
 const char *
-mcore_output_cmov (operands, cmp_t, test)
-     rtx operands[];
-     int cmp_t;
-     const char * test;
+mcore_output_cmov (rtx operands[], int cmp_t, const char * test)
 {
-  int load_value;
-  int adjust_value;
+  HOST_WIDE_INT load_value;
+  HOST_WIDE_INT adjust_value;
   rtx out_operands[4];
 
   out_operands[0] = operands[0];
@@ -1022,9 +1109,9 @@ mcore_output_cmov (operands, cmp_t, test)
      instruction sequence has a different length attribute).  */
   if (load_value >= 0 && load_value <= 127)
     output_asm_insn ("movi\t%0,%1", out_operands);
-  else if ((load_value & (load_value - 1)) == 0)
+  else if (CONST_OK_FOR_M (load_value))
     output_asm_insn ("bgeni\t%0,%P1", out_operands);
-  else if ((load_value & (load_value + 1)) == 0)
+  else if (CONST_OK_FOR_N (load_value))
     output_asm_insn ("bmaski\t%0,%N1", out_operands);
    
   /* Output the constant adjustment.  */
@@ -1050,35 +1137,37 @@ mcore_output_cmov (operands, cmp_t, test)
    by an and (i.e. combine the not and the and into andn). BRC  */
 
 const char *
-mcore_output_andn (insn, operands)
-     rtx insn ATTRIBUTE_UNUSED;
-     rtx operands[];
+mcore_output_andn (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
 {
-  int x, y;
+  HOST_WIDE_INT x, y;
   rtx out_operands[3];
   const char * load_op;
   char buf[256];
+  int trick_no;
 
-  if (try_constant_tricks (INTVAL (operands[1]), &x, &y) != 2)
-    abort ();
+  trick_no = try_constant_tricks (INTVAL (operands[1]), &x, &y);
+  gcc_assert (trick_no == 2);
 
   out_operands[0] = operands[0];
-  out_operands[1] = GEN_INT(x);
+  out_operands[1] = GEN_INT (x);
   out_operands[2] = operands[2];
 
   if (x >= 0 && x <= 127)
     load_op = "movi\t%0,%1";
   
   /* Try exact power of two.  */
-  else if ((x & (x - 1)) == 0)
+  else if (CONST_OK_FOR_M (x))
     load_op = "bgeni\t%0,%P1";
   
   /* Try exact power of two - 1.  */
-  else if ((x & (x + 1)) == 0)
+  else if (CONST_OK_FOR_N (x))
     load_op = "bmaski\t%0,%N1";
   
-  else 
-    load_op = "BADMOVI\t%0,%1";
+  else
+    {
+      load_op = "BADMOVI-andn\t%0, %1";
+      gcc_unreachable ();
+    }
 
   sprintf (buf, "%s\n\tandn\t%%2,%%0", load_op);
   output_asm_insn (buf, out_operands);
@@ -1089,28 +1178,24 @@ mcore_output_andn (insn, operands)
 /* Output an inline constant.  */
 
 static const char *
-output_inline_const (mode, operands)
-     enum machine_mode mode;
-     rtx operands[];
+output_inline_const (enum machine_mode mode, rtx operands[])
 {
-  int x = 0, y = 0;
+  HOST_WIDE_INT x = 0, y = 0;
   int trick_no;
   rtx out_operands[3];
   char buf[256];
   char load_op[256];
   const char *dst_fmt;
-  int value;
+  HOST_WIDE_INT value;
 
   value = INTVAL (operands[1]);
-   
-  if ((trick_no = try_constant_tricks (value, &x, &y)) == 0)
-    {
-      /* lrw's are handled separately:  Large inlinable constants
-        never get turned into lrw's.  Our caller uses try_constant_tricks
-         to back off to an lrw rather than calling this routine.  */
-      abort ();
-    }
 
+  trick_no = try_constant_tricks (value, &x, &y);
+  /* lrw's are handled separately: Large inlinable constants never get
+     turned into lrw's.  Our caller uses try_constant_tricks to back
+     off to an lrw rather than calling this routine.  */
+  gcc_assert (trick_no != 0);
+  
   if (trick_no == 1)
     x = value;
 
@@ -1131,15 +1216,18 @@ output_inline_const (mode, operands)
     sprintf (load_op, "movi\t%s,%%1", dst_fmt);
   
   /* Try exact power of two.  */
-  else if ((x & (x - 1)) == 0)
+  else if (CONST_OK_FOR_M (x))
     sprintf (load_op, "bgeni\t%s,%%P1", dst_fmt);
   
   /* Try exact power of two - 1.  */
-  else if ((x & (x + 1)) == 0)
+  else if (CONST_OK_FOR_N (x))
     sprintf (load_op, "bmaski\t%s,%%N1", dst_fmt);
   
-  else 
-    sprintf (load_op, "BADMOVI\t%s,%%1", dst_fmt);
+  else
+    {
+      sprintf (load_op, "BADMOVI-inline_const %s, %%1", dst_fmt);
+      gcc_unreachable ();
+    }      
 
   switch (trick_no)
     {
@@ -1147,35 +1235,35 @@ output_inline_const (mode, operands)
       strcpy (buf, load_op);
       break;
     case 2:   /* not */
-      sprintf (buf, "%s\n\tnot\t%s\t// %d 0x%x", load_op, dst_fmt, value, value);
+      sprintf (buf, "%s\n\tnot\t%s\t// %ld 0x%lx", load_op, dst_fmt, value, value);
       break;
     case 3:   /* add */
-      sprintf (buf, "%s\n\taddi\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);
+      sprintf (buf, "%s\n\taddi\t%s,%%2\t// %ld 0x%lx", load_op, dst_fmt, value, value);
       break;
     case 4:   /* sub */
-      sprintf (buf, "%s\n\tsubi\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);
+      sprintf (buf, "%s\n\tsubi\t%s,%%2\t// %ld 0x%lx", load_op, dst_fmt, value, value);
       break;
     case 5:   /* rsub */
       /* Never happens unless -mrsubi, see try_constant_tricks().  */
-      sprintf (buf, "%s\n\trsubi\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);
+      sprintf (buf, "%s\n\trsubi\t%s,%%2\t// %ld 0x%lx", load_op, dst_fmt, value, value);
       break;
-    case 6:   /* bset */
-      sprintf (buf, "%s\n\tbseti\t%s,%%P2\t// %d 0x%x", load_op, dst_fmt, value, value);
+    case 6:   /* bseti */
+      sprintf (buf, "%s\n\tbseti\t%s,%%P2\t// %ld 0x%lx", load_op, dst_fmt, value, value);
       break;
     case 7:   /* bclr */
-      sprintf (buf, "%s\n\tbclri\t%s,%%Q2\t// %d 0x%x", load_op, dst_fmt, value, value);
+      sprintf (buf, "%s\n\tbclri\t%s,%%Q2\t// %ld 0x%lx", load_op, dst_fmt, value, value);
       break;
     case 8:   /* rotl */
-      sprintf (buf, "%s\n\trotli\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);
+      sprintf (buf, "%s\n\trotli\t%s,%%2\t// %ld 0x%lx", load_op, dst_fmt, value, value);
       break;
     case 9:   /* lsl */
-      sprintf (buf, "%s\n\tlsli\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);
+      sprintf (buf, "%s\n\tlsli\t%s,%%2\t// %ld 0x%lx", load_op, dst_fmt, value, value);
       break;
     case 10:  /* ixh */
-      sprintf (buf, "%s\n\tixh\t%s,%s\t// %d 0x%x", load_op, dst_fmt, dst_fmt, value, value);
+      sprintf (buf, "%s\n\tixh\t%s,%s\t// %ld 0x%lx", load_op, dst_fmt, dst_fmt, value, value);
       break;
     case 11:  /* ixw */
-      sprintf (buf, "%s\n\tixw\t%s,%s\t// %d 0x%x", load_op, dst_fmt, dst_fmt, value, value);
+      sprintf (buf, "%s\n\tixw\t%s,%s\t// %ld 0x%lx", load_op, dst_fmt, dst_fmt, value, value);
       break;
     default:
       return "";
@@ -1189,10 +1277,8 @@ output_inline_const (mode, operands)
 /* Output a move of a word or less value.  */
 
 const char *
-mcore_output_move (insn, operands, mode)
-     rtx insn ATTRIBUTE_UNUSED;
-     rtx operands[];
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+mcore_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[],
+                  enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   rtx dst = operands[0];
   rtx src = operands[1];
@@ -1211,11 +1297,21 @@ mcore_output_move (insn, operands, mode)
          if (GET_CODE (XEXP (src, 0)) == LABEL_REF) 
             return "lrw\t%0,[%1]";              /* a-R */
          else
-            return "ldw\t%0,%1";                 /* r-m */
+           switch (GET_MODE (src))             /* r-m */
+             {
+             case SImode:
+               return "ldw\t%0,%1";
+             case HImode:
+               return "ld.h\t%0,%1";
+             case QImode:
+               return "ld.b\t%0,%1";
+             default:
+               gcc_unreachable ();
+             }
        }
       else if (GET_CODE (src) == CONST_INT)
        {
-         int x, y;
+         HOST_WIDE_INT x, y;
          
          if (CONST_OK_FOR_I (INTVAL (src)))       /* r-I */
             return "movi\t%0,%1";
@@ -1232,98 +1328,19 @@ mcore_output_move (insn, operands, mode)
        return "lrw\t%0, %1";                /* Into the literal pool.  */
     }
   else if (GET_CODE (dst) == MEM)               /* m-r */
-    return "stw\t%1,%0";
-
-  abort ();
-}
-
-/* Outputs a constant inline -- regardless of the cost.
-   Useful for things where we've gotten into trouble and think we'd
-   be doing an lrw into r15 (forbidden). This lets us get out of
-   that pickle even after register allocation.  */
-
-const char *
-mcore_output_inline_const_forced (insn, operands, mode)
-     rtx insn ATTRIBUTE_UNUSED;
-     rtx operands[];
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  unsigned long value = INTVAL (operands[1]);
-  unsigned long ovalue = value;
-  struct piece
-  {
-    int low;
-    int shift;
-  }
-  part[6];
-  int i;
-
-  if (mcore_const_ok_for_inline (value))
-    return output_inline_const (SImode, operands);
+    switch (GET_MODE (dst))
+      {
+      case SImode:
+       return "stw\t%1,%0";
+      case HImode:
+       return "st.h\t%1,%0";
+      case QImode:
+       return "st.b\t%1,%0";
+      default:
+       gcc_unreachable ();
+      }
 
-  for (i = 0; (unsigned) i < ARRAY_SIZE (part); i++)
-    {
-      part[i].shift = 0;
-      part[i].low = (value & 0x1F);
-      value -= part[i].low;
-      
-      if (mcore_const_ok_for_inline (value))
-       break;
-      else
-       {
-         value >>= 5;
-         part[i].shift = 5;
-         
-         while ((value & 1) == 0)
-           {
-             part[i].shift++;
-             value >>= 1;
-           }
-         
-         if (mcore_const_ok_for_inline (value))
-           break;
-       }
-    }
-  
-  /* 5 bits per iteration, a maximum of 5 times == 25 bits and leaves
-     7 bits left in the constant -- which we know we can cover with
-     a movi.  The final value can't be zero otherwise we'd have stopped
-     in the previous iteration.   */
-  if (value == 0 || ! mcore_const_ok_for_inline (value))
-    abort ();
-
-  /* Now, work our way backwards emitting the constant.  */
-
-  /* Emit the value that remains -- it will be non-zero.  */
-  operands[1] = GEN_INT (value);
-  output_asm_insn (output_inline_const (SImode, operands), operands);
-  while (i >= 0)
-    {
-      /* Shift anything we've already loaded.  */
-      if (part[i].shift)
-        {
-         operands[2] = GEN_INT (part[i].shift);
-         output_asm_insn ("lsli       %0,%2", operands);
-         value <<= part[i].shift;
-        }
-      
-      /* Add anything we need into the low 5 bits.  */
-      if (part[i].low != 0)
-        {
-         operands[2] = GEN_INT (part[i].low);
-         output_asm_insn ("addi      %0,%2", operands);
-         value += part[i].low;
-        }
-      
-      i--;
-    }
-  
-  if (value != ovalue)          /* sanity */
-    abort ();
-  /* We've output all the instructions.  */
-  return "";
+  gcc_unreachable ();
 }
 
 /* Return a sequence of instructions to perform DI or DF move.
@@ -1331,9 +1348,7 @@ mcore_output_inline_const_forced (insn, operands, mode)
    to take care when we see overlapping source and dest registers.  */
 
 const char *
-mcore_output_movedouble (operands, mode)
-     rtx operands[];
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+mcore_output_movedouble (rtx operands[], enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   rtx dst = operands[0];
   rtx src = operands[1];
@@ -1349,345 +1364,92 @@ mcore_output_movedouble (operands, mode)
          if (srcreg + 1 == dstreg)
            return "mov %R0,%R1\n\tmov  %0,%1";
          else
-           return "mov %0,%1\n\tmov    %R0,%R1";
-       }
-      else if (GET_CODE (src) == MEM)
-       {
-         rtx memexp = memexp = XEXP (src, 0);
-         int dstreg = REGNO (dst);
-         int basereg = -1;
-         
-         if (GET_CODE (memexp) == LABEL_REF)
-           return "lrw\t%0,[%1]\n\tlrw\t%R0,[%R1]";
-         else if (GET_CODE (memexp) == REG) 
-           basereg = REGNO (memexp);
-         else if (GET_CODE (memexp) == PLUS)
-           {
-             if (GET_CODE (XEXP (memexp, 0)) == REG)
-               basereg = REGNO (XEXP (memexp, 0));
-             else if (GET_CODE (XEXP (memexp, 1)) == REG)
-               basereg = REGNO (XEXP (memexp, 1));
-             else
-               abort ();
-           }
-         else
-           abort ();
-
-          /* ??? length attribute is wrong here.  */
-         if (dstreg == basereg)
-           {
-             /* Just load them in reverse order.  */
-             return "ldw\t%R0,%R1\n\tldw\t%0,%1";
-             
-             /* XXX: alternative: move basereg to basereg+1
-                and then fall through.  */
-           }
-         else
-           return "ldw\t%0,%1\n\tldw\t%R0,%R1";
-       }
-      else if (GET_CODE (src) == CONST_INT)
-       {
-         if (TARGET_LITTLE_END)
-           {
-             if (CONST_OK_FOR_I (INTVAL (src)))
-               output_asm_insn ("movi  %0,%1", operands);
-             else if (CONST_OK_FOR_M (INTVAL (src)))
-               output_asm_insn ("bgeni %0,%P1", operands);
-             else if (INTVAL (src) == -1)
-               output_asm_insn ("bmaski        %0,32", operands);
-             else if (CONST_OK_FOR_N (INTVAL (src)))
-               output_asm_insn ("bmaski        %0,%N1", operands);
-             else
-               abort ();
-
-             if (INTVAL (src) < 0)
-               return "bmaski  %R0,32";
-             else
-               return "movi    %R0,0";
-           }
-         else
-           {
-             if (CONST_OK_FOR_I (INTVAL (src)))
-               output_asm_insn ("movi  %R0,%1", operands);
-             else if (CONST_OK_FOR_M (INTVAL (src)))
-               output_asm_insn ("bgeni %R0,%P1", operands);
-             else if (INTVAL (src) == -1)
-               output_asm_insn ("bmaski        %R0,32", operands);
-             else if (CONST_OK_FOR_N (INTVAL (src)))
-               output_asm_insn ("bmaski        %R0,%N1", operands);
-             else
-               abort ();
-             
-             if (INTVAL (src) < 0)
-               return "bmaski  %0,32";
-             else
-               return "movi    %0,0";
-           }
-       }
-      else
-       abort ();
-    }
-  else if (GET_CODE (dst) == MEM && GET_CODE (src) == REG)
-    return "stw\t%1,%0\n\tstw\t%R1,%R0";
-  else
-    abort ();
-}
-
-/* Predicates used by the templates.  */
-
-/* Non zero if OP can be source of a simple move operation.  */
-
-int
-mcore_general_movsrc_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  /* Any (MEM LABEL_REF) is OK.  That is a pc-relative load.  */
-  if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == LABEL_REF)
-    return 1;
-
-  return general_operand (op, mode);
-}
-
-/* Non zero if OP can be destination of a simple move operation. */
-
-int
-mcore_general_movdst_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (GET_CODE (op) == REG && REGNO (op) == CC_REG)
-    return 0;
-  
-  return general_operand (op, mode);
-}
-
-/* Nonzero if OP is a normal arithmetic register.  */
-
-int
-mcore_arith_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! register_operand (op, mode))
-    return 0;
-
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-
-  if (GET_CODE (op) == REG)
-    return REGNO (op) != CC_REG;
-
-  return 1;
-}
-
-/* Non zero if OP should be recognized during reload for an ixh/ixw
-   operand.  See the ixh/ixw patterns.  */
-
-int
-mcore_reload_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (mcore_arith_reg_operand (op, mode))
-    return 1;
-
-  if (! reload_in_progress)
-    return 0;
-
-  return GET_CODE (op) == MEM;
-}
-
-/* Nonzero if OP is a valid source operand for an arithmetic insn.  */
-
-int
-mcore_arith_J_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (register_operand (op, mode))
-    return 1;
-
-  if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op)))
-    return 1;
-  
-  return 0;
-}
-
-/* Nonzero if OP is a valid source operand for an arithmetic insn.  */
-
-int
-mcore_arith_K_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (register_operand (op, mode))
-    return 1;
-
-  if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
-    return 1;
-
-  return 0;
-}
-
-/* Nonzero if OP is a valid source operand for a shift or rotate insn.  */
-
-int
-mcore_arith_K_operand_not_0 (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (register_operand (op, mode))
-    return 1;
-
-  if (   GET_CODE (op) == CONST_INT
-      && CONST_OK_FOR_K (INTVAL (op))
-      && INTVAL (op) != 0)
-    return 1;
-
-  return 0;
-}
-
-int
-mcore_arith_K_S_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (register_operand (op, mode))
-    return 1;
-
-  if (GET_CODE (op) == CONST_INT)
-    {
-      if (CONST_OK_FOR_K (INTVAL (op)) || CONST_OK_FOR_M (~INTVAL (op)))
-       return 1;
-    }
-  
-  return 0;
-}
-
-int
-mcore_arith_S_operand (op)
-     rtx op;
-{
-  if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (~INTVAL (op)))
-    return 1;
-  
-  return 0;
-}
-
-int
-mcore_arith_M_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (register_operand (op, mode))
-    return 1;
-
-  if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
-    return 1;
-
-  return 0;
-}
-
-/* Nonzero if OP is a valid source operand for loading.  */
-
-int
-mcore_arith_imm_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (register_operand (op, mode))
-    return 1;
-
-  if (GET_CODE (op) == CONST_INT && const_ok_for_mcore (INTVAL (op)))
-    return 1;
-
-  return 0;
-}
-
-int
-mcore_arith_any_imm_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (register_operand (op, mode))
-    return 1;
-
-  if (GET_CODE (op) == CONST_INT)
-    return 1;
-
-  return 0;
-}
-
-/* Nonzero if OP is a valid source operand for a cmov with two consts +/- 1.  */
-
-int
-mcore_arith_O_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (register_operand (op, mode))
-    return 1;
-
-  if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_O (INTVAL (op)))
-    return 1;
-  
-  return 0;
-}
-
-/* Nonzero if OP is a valid source operand for a btsti.  */
-
-int
-mcore_literal_K_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
-    return 1;
-
-  return 0;
-}
+           return "mov %0,%1\n\tmov    %R0,%R1";
+       }
+      else if (GET_CODE (src) == MEM)
+       {
+         rtx memexp = memexp = XEXP (src, 0);
+         int dstreg = REGNO (dst);
+         int basereg = -1;
+         
+         if (GET_CODE (memexp) == LABEL_REF)
+           return "lrw\t%0,[%1]\n\tlrw\t%R0,[%R1]";
+         else if (GET_CODE (memexp) == REG) 
+           basereg = REGNO (memexp);
+         else if (GET_CODE (memexp) == PLUS)
+           {
+             if (GET_CODE (XEXP (memexp, 0)) == REG)
+               basereg = REGNO (XEXP (memexp, 0));
+             else if (GET_CODE (XEXP (memexp, 1)) == REG)
+               basereg = REGNO (XEXP (memexp, 1));
+             else
+               gcc_unreachable ();
+           }
+         else
+           gcc_unreachable ();
 
-/* Nonzero if OP is a valid source operand for an add/sub insn.  */
+          /* ??? length attribute is wrong here.  */
+         if (dstreg == basereg)
+           {
+             /* Just load them in reverse order.  */
+             return "ldw\t%R0,%R1\n\tldw\t%0,%1";
+             
+             /* XXX: alternative: move basereg to basereg+1
+                and then fall through.  */
+           }
+         else
+           return "ldw\t%0,%1\n\tldw\t%R0,%R1";
+       }
+      else if (GET_CODE (src) == CONST_INT)
+       {
+         if (TARGET_LITTLE_END)
+           {
+             if (CONST_OK_FOR_I (INTVAL (src)))
+               output_asm_insn ("movi  %0,%1", operands);
+             else if (CONST_OK_FOR_M (INTVAL (src)))
+               output_asm_insn ("bgeni %0,%P1", operands);
+             else if (CONST_OK_FOR_N (INTVAL (src)))
+               output_asm_insn ("bmaski        %0,%N1", operands);
+             else
+               gcc_unreachable ();
 
-int
-mcore_addsub_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (register_operand (op, mode))
-    return 1;
+             if (INTVAL (src) < 0)
+               return "bmaski  %R0,32";
+             else
+               return "movi    %R0,0";
+           }
+         else
+           {
+             if (CONST_OK_FOR_I (INTVAL (src)))
+               output_asm_insn ("movi  %R0,%1", operands);
+             else if (CONST_OK_FOR_M (INTVAL (src)))
+               output_asm_insn ("bgeni %R0,%P1", operands);
+             else if (CONST_OK_FOR_N (INTVAL (src)))
+               output_asm_insn ("bmaski        %R0,%N1", operands);
+             else
+               gcc_unreachable ();
 
-  if (GET_CODE (op) == CONST_INT)
-    {
-      return 1;
-      
-      /* The following is removed because it precludes large constants from being
-        returned as valid source operands for and add/sub insn.  While large 
-        constants may not directly be used in an add/sub, they may if first loaded
-        into a register.  Thus, this predicate should indicate that they are valid,
-        and the constraint in mcore.md should control whether an additional load to
-        register is needed. (see mcore.md, addsi). -- DAC 4/2/1998  */
-      /*
-       if (CONST_OK_FOR_J(INTVAL(op)) || CONST_OK_FOR_L(INTVAL(op)))
-          return 1;
-      */
+             if (INTVAL (src) < 0)
+               return "bmaski  %0,32";
+             else
+               return "movi    %0,0";
+           }
+       }
+      else
+       gcc_unreachable ();
     }
-  
-  return 0;
+  else if (GET_CODE (dst) == MEM && GET_CODE (src) == REG)
+    return "stw\t%1,%0\n\tstw\t%R1,%R0";
+  else
+    gcc_unreachable ();
 }
 
-/* Nonzero if OP is a valid source operand for a compare operation.  */
+/* Predicates used by the templates.  */
 
 int
-mcore_compare_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+mcore_arith_S_operand (rtx op)
 {
-  if (register_operand (op, mode))
-    return 1;
-
-  if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
+  if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (~INTVAL (op)))
     return 1;
   
   return 0;
@@ -1696,8 +1458,7 @@ mcore_compare_operand (op, mode)
 /* Expand insert bit field.  BRC  */
 
 int
-mcore_expand_insv (operands)
-     rtx operands[];
+mcore_expand_insv (rtx operands[])
 {
   int width = INTVAL (operands[1]);
   int posn = INTVAL (operands[2]);
@@ -1711,23 +1472,23 @@ mcore_expand_insv (operands)
     {
       /* Do directly with bseti or bclri.  */
       /* RBE: 2/97 consider only low bit of constant.  */
-      if ((INTVAL(operands[3])&1) == 0)
+      if ((INTVAL (operands[3]) & 1) == 0)
        {
          mask = ~(1 << posn);
-         emit_insn (gen_rtx (SET, SImode, operands[0],
-                             gen_rtx (AND, SImode, operands[0], GEN_INT (mask))));
+         emit_insn (gen_rtx_SET (SImode, operands[0],
+                             gen_rtx_AND (SImode, operands[0], GEN_INT (mask))));
        }
       else
        {
          mask = 1 << posn;
-         emit_insn (gen_rtx (SET, SImode, operands[0],
-                           gen_rtx (IOR, SImode, operands[0], GEN_INT (mask))));
+         emit_insn (gen_rtx_SET (SImode, operands[0],
+                           gen_rtx_IOR (SImode, operands[0], GEN_INT (mask))));
        }
       
       return 1;
     }
 
-  /* Look at some bitfield placements that we aren't interested
+  /* Look at some bit-field placements that we aren't interested
      in handling ourselves, unless specifically directed to do so.  */
   if (! TARGET_W_FIELD)
     return 0;          /* Generally, give up about now.  */
@@ -1746,12 +1507,12 @@ mcore_expand_insv (operands)
      immediates.  */
 
   /* If setting the entire field, do it directly.  */
-  if (GET_CODE (operands[3]) == CONST_INT && 
-      INTVAL (operands[3]) == ((1 << width) - 1))
+  if (GET_CODE (operands[3]) == CONST_INT
+      && INTVAL (operands[3]) == ((1 << width) - 1))
     {
       mreg = force_reg (SImode, GEN_INT (INTVAL (operands[3]) << posn));
-      emit_insn (gen_rtx (SET, SImode, operands[0],
-                         gen_rtx (IOR, SImode, operands[0], mreg)));
+      emit_insn (gen_rtx_SET (SImode, operands[0],
+                         gen_rtx_IOR (SImode, operands[0], mreg)));
       return 1;
     }
 
@@ -1759,8 +1520,8 @@ mcore_expand_insv (operands)
   mreg = force_reg (SImode, GEN_INT (~(((1 << width) - 1) << posn)));
 
   /* Clear the field, to overlay it later with the source.  */
-  emit_insn (gen_rtx (SET, SImode, operands[0], 
-                     gen_rtx (AND, SImode, operands[0], mreg)));
+  emit_insn (gen_rtx_SET (SImode, operands[0], 
+                     gen_rtx_AND (SImode, operands[0], mreg)));
 
   /* If the source is constant 0, we've nothing to add back.  */
   if (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) == 0)
@@ -1779,101 +1540,17 @@ mcore_expand_insv (operands)
   if (width + posn != (int) GET_MODE_SIZE (SImode))
     {
       ereg = force_reg (SImode, GEN_INT ((1 << width) - 1));      
-      emit_insn (gen_rtx (SET, SImode, sreg,
-                          gen_rtx (AND, SImode, sreg, ereg)));
+      emit_insn (gen_rtx_SET (SImode, sreg,
+                          gen_rtx_AND (SImode, sreg, ereg)));
     }
 
   /* Insert source value in dest.  */
   if (posn != 0)
-    emit_insn (gen_rtx (SET, SImode, sreg,
-                       gen_rtx (ASHIFT, SImode, sreg, GEN_INT (posn))));
+    emit_insn (gen_rtx_SET (SImode, sreg,
+                       gen_rtx_ASHIFT (SImode, sreg, GEN_INT (posn))));
   
-  emit_insn (gen_rtx (SET, SImode, operands[0],
-                     gen_rtx (IOR, SImode, operands[0], sreg)));
-
-  return 1;
-}
-
-/* Return 1 if OP is a load multiple operation.  It is known to be a
-   PARALLEL and the first section will be tested.  */
-int
-mcore_load_multiple_operation (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  int count = XVECLEN (op, 0);
-  int dest_regno;
-  rtx src_addr;
-  int i;
-
-  /* Perform a quick check so we don't blow up below.  */
-  if (count <= 1
-      || GET_CODE (XVECEXP (op, 0, 0)) != SET
-      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
-      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
-    return 0;
-
-  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
-  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
-
-  for (i = 1; i < count; i++)
-    {
-      rtx elt = XVECEXP (op, 0, i);
-
-      if (GET_CODE (elt) != SET
-         || GET_CODE (SET_DEST (elt)) != REG
-         || GET_MODE (SET_DEST (elt)) != SImode
-         || REGNO (SET_DEST (elt))    != (unsigned) (dest_regno + i)
-         || GET_CODE (SET_SRC (elt))  != MEM
-         || GET_MODE (SET_SRC (elt))  != SImode
-         || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
-         || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
-         || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
-         || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
-       return 0;
-    }
-
-  return 1;
-}
-
-/* Similar, but tests for store multiple.  */
-
-int
-mcore_store_multiple_operation (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  int count = XVECLEN (op, 0);
-  int src_regno;
-  rtx dest_addr;
-  int i;
-
-  /* Perform a quick check so we don't blow up below.  */
-  if (count <= 1
-      || GET_CODE (XVECEXP (op, 0, 0)) != SET
-      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
-      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
-    return 0;
-
-  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
-  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
-
-  for (i = 1; i < count; i++)
-    {
-      rtx elt = XVECEXP (op, 0, i);
-
-      if (GET_CODE (elt) != SET
-         || GET_CODE (SET_SRC (elt)) != REG
-         || GET_MODE (SET_SRC (elt)) != SImode
-         || REGNO (SET_SRC (elt)) != (unsigned) (src_regno + i)
-         || GET_CODE (SET_DEST (elt)) != MEM
-         || GET_MODE (SET_DEST (elt)) != SImode
-         || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
-         || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
-         || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
-         || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
-       return 0;
-    }
+  emit_insn (gen_rtx_SET (SImode, operands[0],
+                     gen_rtx_IOR (SImode, operands[0], sreg)));
 
   return 1;
 }
@@ -1896,143 +1573,124 @@ mcore_store_multiple_operation (op, mode)
 static const enum machine_mode mode_from_align[] =
 {
   VOIDmode, QImode, HImode, VOIDmode, SImode,
-  VOIDmode, VOIDmode, VOIDmode, DImode
 };
 
 static void
-block_move_sequence (dest, dst_mem, src, src_mem, size, align, offset)
-     rtx dest, dst_mem;
-     rtx src, src_mem;
-     int size;
-     int align;
-     int offset;
+block_move_sequence (rtx dst_mem, rtx src_mem, int size, int align)
 {
   rtx temp[2];
   enum machine_mode mode[2];
   int amount[2];
-  int active[2];
+  bool active[2];
   int phase = 0;
   int next;
-  int offset_ld = offset;
-  int offset_st = offset;
-
-  active[0] = active[1] = FALSE;
+  int offset_ld = 0;
+  int offset_st = 0;
+  rtx x;
 
-  /* Establish parameters for the first load and for the second load if
-     it is known to be the same mode as the first.  */
-  amount[0] = amount[1] = align;
-
-  mode[0] = mode_from_align[align];
+  x = XEXP (dst_mem, 0);
+  if (!REG_P (x))
+    {
+      x = force_reg (Pmode, x);
+      dst_mem = replace_equiv_address (dst_mem, x);
+    }
 
-  temp[0] = gen_reg_rtx (mode[0]);
-  
-  if (size >= 2 * align)
+  x = XEXP (src_mem, 0);
+  if (!REG_P (x))
     {
-      mode[1] = mode[0];
-      temp[1] = gen_reg_rtx (mode[1]);
+      x = force_reg (Pmode, x);
+      src_mem = replace_equiv_address (src_mem, x);
     }
 
+  active[0] = active[1] = false;
+
   do
     {
-      rtx srcp, dstp;
-      
       next = phase;
-      phase = !phase;
+      phase ^= 1;
 
       if (size > 0)
        {
-         /* Change modes as the sequence tails off.  */
-         if (size < amount[next])
-           {
-             amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
-             mode[next] = mode_from_align[amount[next]];
-             temp[next] = gen_reg_rtx (mode[next]);
-           }
-         
-         size -= amount[next];
-         srcp = gen_rtx (MEM,
-#if 0
-                         MEM_IN_STRUCT_P (src_mem) ? mode[next] : BLKmode,
-#else
-                         mode[next],
-#endif
-                         gen_rtx (PLUS, Pmode, src,
-                                  gen_rtx (CONST_INT, SImode, offset_ld)));
-         
-         RTX_UNCHANGING_P (srcp) = RTX_UNCHANGING_P (src_mem);
-         MEM_VOLATILE_P (srcp) = MEM_VOLATILE_P (src_mem);
-         MEM_IN_STRUCT_P (srcp) = 1;
-         emit_insn (gen_rtx (SET, VOIDmode, temp[next], srcp));
-         offset_ld += amount[next];
-         active[next] = TRUE;
+         int next_amount;
+
+         next_amount = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
+         next_amount = MIN (next_amount, align);
+
+         amount[next] = next_amount;
+         mode[next] = mode_from_align[next_amount];
+         temp[next] = gen_reg_rtx (mode[next]);
+
+         x = adjust_address (src_mem, mode[next], offset_ld);
+         emit_insn (gen_rtx_SET (VOIDmode, temp[next], x));
+
+         offset_ld += next_amount;
+         size -= next_amount;
+         active[next] = true;
        }
 
       if (active[phase])
        {
-         active[phase] = FALSE;
-         
-         dstp = gen_rtx (MEM,
-#if 0
-                         MEM_IN_STRUCT_P (dst_mem) ? mode[phase] : BLKmode,
-#else
-                         mode[phase],
-#endif
-                         gen_rtx (PLUS, Pmode, dest,
-                                  gen_rtx (CONST_INT, SImode, offset_st)));
+         active[phase] = false;
          
-         RTX_UNCHANGING_P (dstp) = RTX_UNCHANGING_P (dst_mem);
-         MEM_VOLATILE_P (dstp) = MEM_VOLATILE_P (dst_mem);
-         MEM_IN_STRUCT_P (dstp) = 1;
-         emit_insn (gen_rtx (SET, VOIDmode, dstp, temp[phase]));
+         x = adjust_address (dst_mem, mode[phase], offset_st);
+         emit_insn (gen_rtx_SET (VOIDmode, x, temp[phase]));
+
          offset_st += amount[phase];
        }
     }
   while (active[next]);
 }
 
-void
-mcore_expand_block_move (dst_mem, src_mem, operands)
-     rtx dst_mem;
-     rtx src_mem;
-     rtx * operands;
+bool
+mcore_expand_block_move (rtx *operands)
 {
-  int align = INTVAL (operands[3]);
-  int bytes;
+  HOST_WIDE_INT align, bytes, max;
+
+  if (GET_CODE (operands[2]) != CONST_INT)
+    return false;
+
+  bytes = INTVAL (operands[2]);
+  align = INTVAL (operands[3]);
+
+  if (bytes <= 0)
+    return false;
+  if (align > 4)
+    align = 4;
 
-  if (GET_CODE (operands[2]) == CONST_INT)
+  switch (align)
     {
-      bytes = INTVAL (operands[2]);
-      
-      if (bytes <= 0)
-       return;
-      if (align > 4)
-       align = 4;
-      
-      /* RBE: bumped 1 and 2 byte align from 1 and 2 to 4 and 8 bytes before
-         we give up and go to memcpy.  */
-      if ((align == 4 && (bytes <= 4*4
-                         || ((bytes & 01) == 0 && bytes <= 8*4)
-                         || ((bytes & 03) == 0 && bytes <= 16*4)))
-         || (align == 2 && bytes <= 4*2)
-         || (align == 1 && bytes <= 4*1))
-       {
-         block_move_sequence (operands[0], dst_mem, operands[1], src_mem,
-                              bytes, align, 0);
-         return;
-       }
+    case 4:
+      if (bytes & 1)
+       max = 4*4;
+      else if (bytes & 3)
+       max = 8*4;
+      else
+       max = 16*4;
+      break;
+    case 2:
+      max = 4*2;
+      break;
+    case 1:
+      max = 4*1;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  if (bytes <= max)
+    {
+      block_move_sequence (operands[0], operands[1], bytes, align);
+      return true;
     }
 
-  /* If we get here, just use the library routine.  */
-  emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), 0, VOIDmode, 3,
-                    operands[0], Pmode, operands[1], Pmode, operands[2],
-                    SImode);
+  return false;
 }
 \f
 
 /* Code to generate prologue and epilogue sequences.  */
 static int number_of_regs_before_varargs;
 
-/* Set by SETUP_INCOMING_VARARGS to indicate to prolog that this is
+/* Set by TARGET_SETUP_INCOMING_VARARGS to indicate to prolog that this is
    for a varargs function.  */
 static int current_function_anonymous_args;
 
@@ -2041,22 +1699,20 @@ static int current_function_anonymous_args;
 #define        ADDI_REACH (32)         /* Maximum addi operand.  */
 
 static void
-layout_mcore_frame (infp)
-     struct mcore_frame * infp;
+layout_mcore_frame (struct mcore_frame * infp)
 {
   int n;
   unsigned int i;
   int nbytes;
   int regarg;
   int localregarg;
-  int localreg;
   int outbounds;
   unsigned int growths;
   int step;
 
   /* Might have to spill bytes to re-assemble a big argument that
      was passed partially in registers and partially on the stack.  */
-  nbytes = current_function_pretend_args_size;
+  nbytes = crtl->args.pretend_args_size;
   
   /* Determine how much space for spilled anonymous args (e.g., stdarg).  */
   if (current_function_anonymous_args)
@@ -2068,9 +1724,9 @@ layout_mcore_frame (infp)
   infp->reg_mask = calc_live_regs (& n);
   infp->reg_size = n * 4;
 
-  /* And the rest of it... locals and space for overflowed outbounds. */
+  /* And the rest of it... locals and space for overflowed outbounds.  */
   infp->local_size = get_frame_size ();
-  infp->outbound_size = current_function_outgoing_args_size;
+  infp->outbound_size = crtl->outgoing_args_size;
 
   /* Make sure we have a whole number of words for the locals.  */
   if (infp->local_size % STACK_BYTES)
@@ -2094,7 +1750,6 @@ layout_mcore_frame (infp)
 
   regarg      = infp->reg_size + infp->arg_size;
   localregarg = infp->local_size + regarg;
-  localreg    = infp->local_size + infp->reg_size;
   outbounds   = infp->outbound_size + infp->pad_outbound;
   growths     = 0;
 
@@ -2170,7 +1825,7 @@ layout_mcore_frame (infp)
       infp->local_growth = growths;
       all -= step;
 
-      assert (all == 0);
+      gcc_assert (all == 0);
 
       /* Finish off if we need to do so.  */
       if (outbounds)
@@ -2248,27 +1903,18 @@ layout_mcore_frame (infp)
 
   /* Anything else that we've forgotten?, plus a few consistency checks.  */
  finish:
-  assert (infp->reg_offset >= 0);
-  assert (growths <= MAX_STACK_GROWS);
+  gcc_assert (infp->reg_offset >= 0);
+  gcc_assert (growths <= MAX_STACK_GROWS);
   
   for (i = 0; i < growths; i++)
-    {
-      if (infp->growth[i] % STACK_BYTES)
-       {
-         fprintf (stderr,"stack growth of %d is not %d aligned\n",
-                  infp->growth[i], STACK_BYTES);
-         abort ();
-       }
-    }
+    gcc_assert (!(infp->growth[i] % STACK_BYTES));
 }
 
 /* Define the offset between two registers, one to be eliminated, and
    the other its replacement, at the start of a routine.  */
 
 int
-mcore_initial_elimination_offset (from, to)
-     int from;
-     int to;
+mcore_initial_elimination_offset (int from, int to)
 {
   int above_frame;
   int below_frame;
@@ -2290,31 +1936,28 @@ mcore_initial_elimination_offset (from, to)
   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
     return below_frame;
 
-  abort ();
-
-  return 0;
+  gcc_unreachable ();
 }
 
 /* Keep track of some information about varargs for the prolog.  */
 
-void
-mcore_setup_incoming_varargs (args_so_far, mode, type, ptr_pretend_size)
-     CUMULATIVE_ARGS args_so_far;
-     enum machine_mode mode;
-     tree type;
-     int * ptr_pretend_size ATTRIBUTE_UNUSED;
+static void
+mcore_setup_incoming_varargs (CUMULATIVE_ARGS *args_so_far,
+                             enum machine_mode mode, tree type,
+                             int * ptr_pretend_size ATTRIBUTE_UNUSED,
+                             int second_time ATTRIBUTE_UNUSED)
 {
   current_function_anonymous_args = 1;
 
   /* We need to know how many argument registers are used before
      the varargs start, so that we can push the remaining argument
      registers during the prologue.  */
-  number_of_regs_before_varargs = args_so_far + mcore_num_arg_regs (mode, type);
+  number_of_regs_before_varargs = *args_so_far + mcore_num_arg_regs (mode, type);
   
-  /* There is a bug somwehere in the arg handling code.
+  /* There is a bug somewhere in the arg handling code.
      Until I can find it this workaround always pushes the
      last named argument onto the stack.  */
-  number_of_regs_before_varargs = args_so_far;
+  number_of_regs_before_varargs = *args_so_far;
   
   /* The last named argument may be split between argument registers
      and the stack.  Allow for this here.  */
@@ -2323,7 +1966,7 @@ mcore_setup_incoming_varargs (args_so_far, mode, type, ptr_pretend_size)
 }
 
 void
-mcore_expand_prolog ()
+mcore_expand_prolog (void)
 {
   struct mcore_frame fi;
   int space_allocated = 0;
@@ -2339,29 +1982,23 @@ mcore_expand_prolog ()
     {
       /* Emit a symbol for this routine's frame size.  */
       rtx x;
-      int len;
 
       x = DECL_RTL (current_function_decl);
       
-      if (GET_CODE (x) != MEM)
-       abort ();
+      gcc_assert (GET_CODE (x) == MEM);
       
       x = XEXP (x, 0);
       
-      if (GET_CODE (x) != SYMBOL_REF)
-       abort ();
+      gcc_assert (GET_CODE (x) == SYMBOL_REF);
       
       if (mcore_current_function_name)
        free (mcore_current_function_name);
       
-      len = strlen (XSTR (x, 0)) + 1;
-      mcore_current_function_name = (char *) xmalloc (len);
-      
-      memcpy (mcore_current_function_name, XSTR (x, 0), len);
+      mcore_current_function_name = xstrdup (XSTR (x, 0));
       
       ASM_OUTPUT_CG_NODE (asm_out_file, mcore_current_function_name, space_allocated);
 
-      if (current_function_calls_alloca)
+      if (cfun->calls_alloca)
        ASM_OUTPUT_CG_EDGE (asm_out_file, mcore_current_function_name, "alloca", 1);
 
       /* 970425: RBE:
@@ -2380,12 +2017,12 @@ mcore_expand_prolog ()
     return;
   
   /* Handle stdarg+regsaves in one shot: can't be more than 64 bytes.  */
-  output_stack_adjust (-1, fi.growth[growth++]);       /* grows it */
+  output_stack_adjust (-1, fi.growth[growth++]);       /* Grows it.  */
 
   /* If we have a parameter passed partially in regs and partially in memory,
      the registers will have been stored to memory already in function.c.  So
      we only need to do something here for varargs functions.  */
-  if (fi.arg_size != 0 && current_function_pretend_args_size == 0)
+  if (fi.arg_size != 0 && crtl->args.pretend_args_size == 0)
     {
       int offset;
       int rn = FIRST_PARM_REG + NPARM_REGS - 1;
@@ -2394,15 +2031,15 @@ mcore_expand_prolog ()
       for (offset = fi.arg_offset; remaining >= 4; offset -= 4, rn--, remaining -= 4)
         {
           emit_insn (gen_movsi
-                     (gen_rtx (MEM, SImode,
+                     (gen_rtx_MEM (SImode,
                                plus_constant (stack_pointer_rtx, offset)),
-                      gen_rtx (REG, SImode, rn)));
+                      gen_rtx_REG (SImode, rn)));
         }
     }
 
   /* Do we need another stack adjustment before we do the register saves?  */
   if (growth < fi.reg_growth)
-    output_stack_adjust (-1, fi.growth[growth++]);             /* grows it */
+    output_stack_adjust (-1, fi.growth[growth++]);             /* Grows it.  */
 
   if (fi.reg_size != 0)
     {
@@ -2419,8 +2056,8 @@ mcore_expand_prolog ()
                first_reg--;
              first_reg++;
 
-             emit_insn (gen_store_multiple (gen_rtx (MEM, SImode, stack_pointer_rtx),
-                                            gen_rtx (REG, SImode, first_reg),
+             emit_insn (gen_store_multiple (gen_rtx_MEM (SImode, stack_pointer_rtx),
+                                            gen_rtx_REG (SImode, first_reg),
                                             GEN_INT (16 - first_reg)));
 
              i -= (15 - first_reg);
@@ -2429,9 +2066,9 @@ mcore_expand_prolog ()
           else if (fi.reg_mask & (1 << i))
            {
              emit_insn (gen_movsi
-                        (gen_rtx (MEM, SImode,
+                        (gen_rtx_MEM (SImode,
                                   plus_constant (stack_pointer_rtx, offs)),
-                         gen_rtx (REG, SImode, i)));
+                         gen_rtx_REG (SImode, i)));
              offs += 4;
            }
         }
@@ -2442,7 +2079,7 @@ mcore_expand_prolog ()
     {
       /* If we haven't already purchased to 'fp'.  */
       if (growth < fi.local_growth)
-        output_stack_adjust (-1, fi.growth[growth++]);         /* grows it */
+        output_stack_adjust (-1, fi.growth[growth++]);         /* Grows it.  */
       
       emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
 
@@ -2453,14 +2090,14 @@ mcore_expand_prolog ()
   else
     {
       if (growth < fi.local_growth)
-        output_stack_adjust (-1, fi.growth[growth++]);         /* grows it */
+        output_stack_adjust (-1, fi.growth[growth++]);         /* Grows it.  */
       if (fi.growth[growth])
         output_stack_adjust (-1, fi.growth[growth++]);
     }
 }
 
 void
-mcore_expand_epilog ()
+mcore_expand_epilog (void)
 {
   struct mcore_frame fi;
   int i;
@@ -2513,8 +2150,8 @@ mcore_expand_epilog ()
          
          first_reg++;
 
-         emit_insn (gen_load_multiple (gen_rtx (REG, SImode, first_reg),
-                                       gen_rtx (MEM, SImode, stack_pointer_rtx),
+         emit_insn (gen_load_multiple (gen_rtx_REG (SImode, first_reg),
+                                       gen_rtx_MEM (SImode, stack_pointer_rtx),
                                        GEN_INT (16 - first_reg)));
 
          i -= (15 - first_reg);
@@ -2523,15 +2160,15 @@ mcore_expand_epilog ()
       else if (fi.reg_mask & (1 << i))
        {
          emit_insn (gen_movsi
-                    (gen_rtx (REG, SImode, i),
-                     gen_rtx (MEM, SImode,
+                    (gen_rtx_REG (SImode, i),
+                     gen_rtx_MEM (SImode,
                               plus_constant (stack_pointer_rtx, offs))));
          offs += 4;
        }
     }
 
   /* Give back anything else.  */
-  /* XXX: Should accumuate total and then give it back.  */
+  /* XXX: Should accumulate total and then give it back.  */
   while (growth >= 0)
     output_stack_adjust ( 1, fi.growth[growth--]);
 }
@@ -2540,7 +2177,7 @@ mcore_expand_epilog ()
 
 /* The MCORE cannot load a large constant into a register, constants have to
    come from a pc relative load.  The reference of a pc relative load
-   instruction must be less than 1k infront of the instruction.  This
+   instruction must be less than 1k in front of the instruction.  This
    means that we often have to dump a constant inside a function, and
    generate code to branch around it.
 
@@ -2596,7 +2233,7 @@ typedef struct
 
 /* The maximum number of constants that can fit into one pool, since
    the pc relative range is 0...1020 bytes and constants are at least 4
-   bytes long.  We subtact 4 from the range to allow for the case where
+   bytes long.  We subtract 4 from the range to allow for the case where
    we need to add a branch/align before the constant pool.  */
 
 #define MAX_COUNT 1016
@@ -2608,7 +2245,7 @@ static int pool_size;
    will only be labels.  */
 
 const char *
-mcore_output_jump_label_table ()
+mcore_output_jump_label_table (void)
 {
   int i;
 
@@ -2620,7 +2257,7 @@ mcore_output_jump_label_table ()
        {
          pool_node * p = pool_vector + i;
 
-         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (p->label));
+         (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (p->label));
          
          output_asm_insn (".long       %0", &p->value);
        }
@@ -2634,8 +2271,7 @@ mcore_output_jump_label_table ()
 /* Check whether insn is a candidate for a conditional.  */
 
 static cond_type
-is_cond_candidate (insn)
-     rtx insn;
+is_cond_candidate (rtx insn)
 {
   /* The only things we conditionalize are those that can be directly
      changed into a conditional.  Only bother with SImode items.  If 
@@ -2686,7 +2322,7 @@ is_cond_candidate (insn)
                GET_MODE (XEXP (src, 0)) == SImode)
        return COND_DEC_INSN;
 
-      /* some insns that we don't bother with:
+      /* Some insns that we don't bother with:
         (set (rx:DI) (ry:DI))
         (set (rx:DI) (const_int 0))
       */            
@@ -2704,9 +2340,7 @@ is_cond_candidate (insn)
    new one.  Return the new insn if emitted.  */
 
 static rtx
-emit_new_cond_insn (insn, cond)
-     rtx insn;
-     int cond;
+emit_new_cond_insn (rtx insn, int cond)
 {
   rtx c_insn = 0;
   rtx pat, dst, src;
@@ -2823,8 +2457,7 @@ emit_new_cond_insn (insn, cond)
    starting at the last instruction of block 2.  This may allow an entire
    if-then-else statement to be conditionalized.  BRC  */
 static rtx
-conditionalize_block (first)
-     rtx first;
+conditionalize_block (rtx first)
 {
   rtx insn;
   rtx br_pat;
@@ -2876,7 +2509,7 @@ conditionalize_block (first)
       
       code = GET_CODE (insn);
 
-      /* Look for the label at the start of block 3. */
+      /* Look for the label at the start of block 3.  */
       if (code == CODE_LABEL && CODE_LABEL_NUMBER (insn) == br_lab_num)
        break;
 
@@ -2886,7 +2519,7 @@ conditionalize_block (first)
       if (code != BARRIER && code != NOTE && !is_cond_candidate (insn))
        return NEXT_INSN (insn);
      
-      /* Remember the last real insn before the label (ie end of block 2).  */
+      /* Remember the last real insn before the label (i.e. end of block 2).  */
       if (code == JUMP_INSN || code == INSN)
        {
          blk_size ++;
@@ -2924,7 +2557,7 @@ conditionalize_block (first)
       if (INSN_DELETED_P (insn))
        continue;
       
-      /* Try to form a conditional variant of the instruction and emit it. */
+      /* Try to form a conditional variant of the instruction and emit it.  */
       if ((newinsn = emit_new_cond_insn (insn, cond)))
        {
          if (end_blk_2_insn == insn)
@@ -2965,23 +2598,21 @@ conditionalize_block (first)
    in before cse 2).  */
 
 static void
-conditionalize_optimization (first)
-     rtx first;
+conditionalize_optimization (void)
 {
   rtx insn;
 
-  for (insn = first; insn; insn = conditionalize_block (insn))
+  for (insn = get_insns (); insn; insn = conditionalize_block (insn))
     continue;
 }
 
 static int saved_warn_return_type = -1;
 static int saved_warn_return_type_count = 0;
 
-/* This function is called from toplev.c before reorg.  */
+/* This is to handle loads from the constant pool.  */
 
-void
-mcore_dependent_reorg (first)
-     rtx first;
+static void
+mcore_reorg (void)
 {
   /* Reset this variable.  */
   current_function_anonymous_args = 0;
@@ -3005,42 +2636,56 @@ mcore_dependent_reorg (first)
     return;
   
   /* Conditionalize blocks where we can.  */
-  conditionalize_optimization (first);
+  conditionalize_optimization ();
 
   /* Literal pool generation is now pushed off until the assembler.  */
 }
 
 \f
-/* Return the reg_class to use when reloading the rtx X into the class
-   CLASS.  */
+/* Return true if X is something that can be moved directly into r15.  */
+
+bool
+mcore_r15_operand_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case CONST_INT:
+      return mcore_const_ok_for_inline (INTVAL (x));
+
+    case REG:
+    case SUBREG:
+    case MEM:
+      return 1;
+
+    default:
+      return 0;
+    }
+}
+
+/* Implement SECONDARY_RELOAD_CLASS.  If RCLASS contains r15, and we can't
+   directly move X into it, use r1-r14 as a temporary.  */
 
-/* If the input is (PLUS REG CONSTANT) representing a stack slot address,
-   then we want to restrict the class to LRW_REGS since that ensures that
-   will be able to safely load the constant.
+enum reg_class
+mcore_secondary_reload_class (enum reg_class rclass,
+                             enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  if (TEST_HARD_REG_BIT (reg_class_contents[rclass], 15)
+      && !mcore_r15_operand_p (x))
+    return LRW_REGS;
+  return NO_REGS;
+}
 
-   If the input is a constant that should be loaded with mvir1, then use
-   ONLYR1_REGS.
+/* Return the reg_class to use when reloading the rtx X into the class
+   RCLASS.  If X is too complex to move directly into r15, prefer to
+   use LRW_REGS instead.  */
 
-   ??? We don't handle the case where we have (PLUS REG CONSTANT) and
-   the constant should be loaded with mvir1, because that can lead to cases
-   where an instruction needs two ONLYR1_REGS reloads.  */
 enum reg_class
-mcore_reload_class (x, class)
-     rtx x;
-     enum reg_class class;
-{
-  enum reg_class new_class;
-
-  if (class == GENERAL_REGS && CONSTANT_P (x)
-      && (GET_CODE (x) != CONST_INT
-         || (   ! CONST_OK_FOR_I (INTVAL (x))
-             && ! CONST_OK_FOR_M (INTVAL (x))
-             && ! CONST_OK_FOR_N (INTVAL (x)))))
-    new_class = LRW_REGS;
-  else
-    new_class = class;
+mcore_reload_class (rtx x, enum reg_class rclass)
+{
+  if (reg_class_subset_p (LRW_REGS, rclass) && !mcore_r15_operand_p (x))
+    return LRW_REGS;
 
-  return new_class;
+  return rclass;
 }
 
 /* Tell me if a pair of reg/subreg rtx's actually refer to the same
@@ -3048,12 +2693,11 @@ mcore_reload_class (x, class)
    they are the same mode or note (e.g., a QImode in r2 matches an HImode
    in r2 matches an SImode in r2. Might think in the future about whether
    we want to be able to say something about modes.  */
+
 int
-mcore_is_same_reg (x, y)
-     rtx x;
-     rtx y;
+mcore_is_same_reg (rtx x, rtx y)
 {
-  /* Strip any and all of the subreg wrappers. */
+  /* Strip any and all of the subreg wrappers.  */
   while (GET_CODE (x) == SUBREG)
     x = SUBREG_REG (x);
   
@@ -3066,63 +2710,24 @@ mcore_is_same_reg (x, y)
   return 0;
 }
 
-/* Called to register all of our global variables with the garbage
-   collector.  */
 static void
-mcore_add_gc_roots ()
-{
-  ggc_add_rtx_root (&arch_compare_op0, 1);
-  ggc_add_rtx_root (&arch_compare_op1, 1);
-}
-
-void
-mcore_override_options ()
+mcore_option_override (void)
 {
-  if (mcore_stack_increment_string)
-    {
-      mcore_stack_increment = atoi (mcore_stack_increment_string);
-      
-      if (mcore_stack_increment < 0
-         || (mcore_stack_increment == 0
-             && (mcore_stack_increment_string[0] != '0'
-                 || mcore_stack_increment_string[1] != 0)))
-       error ("invalid option `-mstack-increment=%s'",
-              mcore_stack_increment_string);   
-    }
-  
   /* Only the m340 supports little endian code.  */
   if (TARGET_LITTLE_END && ! TARGET_M340)
-    target_flags |= M340_BIT;
-
-  mcore_add_gc_roots ();
-}
-\f
-int
-mcore_must_pass_on_stack (mode, type)
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-     tree type;
-{
-  if (type == NULL)
-    return 0;
-
-  /* If the argugment can have its address taken, it must
-     be placed on the stack.  */
-  if (TREE_ADDRESSABLE (type))
-    return 1;
-
-  return 0;
+    target_flags |= MASK_M340;
 }
 
+\f
 /* Compute the number of word sized registers needed to 
    hold a function argument of mode MODE and type TYPE.  */
+
 int
-mcore_num_arg_regs (mode, type)
-     enum machine_mode mode;
-     tree type;
+mcore_num_arg_regs (enum machine_mode mode, const_tree type)
 {
   int size;
 
-  if (MUST_PASS_IN_STACK (mode, type))
+  if (targetm.calls.must_pass_in_stack (mode, type))
     return 0;
 
   if (type && mode == BLKmode)
@@ -3134,14 +2739,11 @@ mcore_num_arg_regs (mode, type)
 }
 
 static rtx
-handle_structs_in_regs (mode, type, reg)
-     enum machine_mode mode;
-     tree type;
-     int  reg;
+handle_structs_in_regs (enum machine_mode mode, const_tree type, int reg)
 {
   int size;
 
-  /* The MCore ABI defines that a structure whoes size is not a whole multiple
+  /* The MCore ABI defines that a structure whose size is not a whole multiple
      of bytes is passed packed into registers (or spilled onto the stack if
      not enough registers are available) with the last few bytes of the
      structure being packed, left-justified, into the last register/stack slot.
@@ -3169,7 +2771,7 @@ handle_structs_in_regs (mode, type, reg)
         }
 
       /* We assume here that NPARM_REGS == 6.  The assert checks this.  */
-      assert (ARRAY_SIZE (arg_regs) == 6);
+      gcc_assert (ARRAY_SIZE (arg_regs) == 6);
       rtvec = gen_rtvec (nregs, arg_regs[0], arg_regs[1], arg_regs[2],
                          arg_regs[3], arg_regs[4], arg_regs[5]);
       
@@ -3181,16 +2783,15 @@ handle_structs_in_regs (mode, type, reg)
 }
 
 rtx
-mcore_function_value (valtype, func)
-     tree valtype;
-     tree func ATTRIBUTE_UNUSED;
+mcore_function_value (const_tree valtype, const_tree func)
 {
   enum machine_mode mode;
   int unsigned_p;
   
   mode = TYPE_MODE (valtype);
 
-  PROMOTE_MODE (mode, unsigned_p, NULL);
+  /* Since we promote return types, we must promote the mode here too.  */
+  mode = promote_function_mode (valtype, mode, &unsigned_p, func, 1);
   
   return handle_structs_in_regs (mode, valtype, FIRST_RET_REG);
 }
@@ -3212,22 +2813,20 @@ mcore_function_value (valtype, func)
    and the rest are pushed.  Any arg that starts within the first
    NPARM_REGS words is at least partially passed in a register unless
    its data type forbids.  */
-rtx
-mcore_function_arg (cum, mode, type, named)
-     CUMULATIVE_ARGS   cum;
-     enum machine_mode mode;
-     tree              type;
-     int               named;
+
+static rtx
+mcore_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                   const_tree type, bool named)
 {
   int arg_reg;
   
-  if (! named)
+  if (! named || mode == VOIDmode)
     return 0;
 
-  if (MUST_PASS_IN_STACK (mode, type))
+  if (targetm.calls.must_pass_in_stack (mode, type))
     return 0;
 
-  arg_reg = ROUND_REG (cum, mode);
+  arg_reg = ROUND_REG (*cum, mode);
   
   if (arg_reg < NPARM_REGS)
     return handle_structs_in_regs (mode, type, FIRST_PARM_REG + arg_reg);
@@ -3235,26 +2834,41 @@ mcore_function_arg (cum, mode, type, named)
   return 0;
 }
 
-/* Implements the FUNCTION_ARG_PARTIAL_NREGS macro.
-   Returns the number of argument registers required to hold *part* of
-   a parameter of machine mode MODE and type TYPE (which may be NULL if
-   the type is not known).  If the argument fits entirly in the argument
+static void
+mcore_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                           const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  *cum = (ROUND_REG (*cum, mode)
+         + (int)named * mcore_num_arg_regs (mode, type));
+}
+
+static unsigned int
+mcore_function_arg_boundary (enum machine_mode mode,
+                            const_tree type ATTRIBUTE_UNUSED)
+{
+  /* Doubles must be aligned to an 8 byte boundary.  */
+  return (mode != BLKmode && GET_MODE_SIZE (mode) == 8
+         ? BIGGEST_ALIGNMENT
+         : PARM_BOUNDARY);
+}
+
+/* Returns the number of bytes of argument registers required to hold *part*
+   of a parameter of machine mode MODE and type TYPE (which may be NULL if
+   the type is not known).  If the argument fits entirely in the argument
    registers, or entirely on the stack, then 0 is returned.  CUM is the
    number of argument registers already used by earlier parameters to
    the function.  */
-int
-mcore_function_arg_partial_nregs (cum, mode, type, named)
-     CUMULATIVE_ARGS   cum;
-     enum machine_mode mode;
-     tree              type;
-     int               named;
+
+static int
+mcore_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                        tree type, bool named)
 {
-  int reg = ROUND_REG (cum, mode);
+  int reg = ROUND_REG (*cum, mode);
 
   if (named == 0)
     return 0;
 
-  if (MUST_PASS_IN_STACK (mode, type))
+  if (targetm.calls.must_pass_in_stack (mode, type))
     return 0;
       
   /* REG is not the *hardware* register number of the register that holds
@@ -3278,29 +2892,29 @@ mcore_function_arg_partial_nregs (cum, mode, type, named)
   reg = NPARM_REGS - reg;
 
   /* Return partially in registers and partially on the stack.  */
-  return reg;
+  return reg * UNITS_PER_WORD;
 }
 \f
-/* Return non-zero if SYMBOL is marked as being dllexport'd.  */
+/* Return nonzero if SYMBOL is marked as being dllexport'd.  */
+
 int
-mcore_dllexport_name_p (symbol)
-     const char * symbol;
+mcore_dllexport_name_p (const char * symbol)
 {
   return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.';
 }
 
-/* Return non-zero if SYMBOL is marked as being dllimport'd.  */
+/* Return nonzero if SYMBOL is marked as being dllimport'd.  */
+
 int
-mcore_dllimport_name_p (symbol)
-     const char * symbol;
+mcore_dllimport_name_p (const char * symbol)
 {
   return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.';
 }
 
 /* Mark a DECL as being dllexport'd.  */
+
 static void
-mcore_mark_dllexport (decl)
-     tree decl;
+mcore_mark_dllexport (tree decl)
 {
   const char * oldname;
   char * newname;
@@ -3309,18 +2923,15 @@ mcore_mark_dllexport (decl)
 
   rtlname = XEXP (DECL_RTL (decl), 0);
   
-  if (GET_CODE (rtlname) == SYMBOL_REF)
-    oldname = XSTR (rtlname, 0);
-  else if (   GET_CODE (rtlname) == MEM
-          && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
-    oldname = XSTR (XEXP (rtlname, 0), 0);
-  else
-    abort ();
+  if (GET_CODE (rtlname) == MEM)
+    rtlname = XEXP (rtlname, 0);
+  gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
+  oldname = XSTR (rtlname, 0);
   
   if (mcore_dllexport_name_p (oldname))
     return;  /* Already done.  */
 
-  newname = alloca (strlen (oldname) + 4);
+  newname = XALLOCAVEC (char, strlen (oldname) + 4);
   sprintf (newname, "@e.%s", oldname);
 
   /* We pass newname through get_identifier to ensure it has a unique
@@ -3331,13 +2942,13 @@ mcore_mark_dllexport (decl)
   idp = get_identifier (newname);
 
   XEXP (DECL_RTL (decl), 0) =
-    gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
+    gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
 }
 
 /* Mark a DECL as being dllimport'd.  */
+
 static void
-mcore_mark_dllimport (decl)
-     tree decl;
+mcore_mark_dllimport (tree decl)
 {
   const char * oldname;
   char * newname;
@@ -3347,17 +2958,13 @@ mcore_mark_dllimport (decl)
 
   rtlname = XEXP (DECL_RTL (decl), 0);
   
-  if (GET_CODE (rtlname) == SYMBOL_REF)
-    oldname = XSTR (rtlname, 0);
-  else if (   GET_CODE (rtlname) == MEM
-          && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
-    oldname = XSTR (XEXP (rtlname, 0), 0);
-  else
-    abort ();
+  if (GET_CODE (rtlname) == MEM)
+    rtlname = XEXP (rtlname, 0);
+  gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
+  oldname = XSTR (rtlname, 0);
   
-  if (mcore_dllexport_name_p (oldname))
-    abort (); /* This shouldn't happen.  */
-  else if (mcore_dllimport_name_p (oldname))
+  gcc_assert (!mcore_dllexport_name_p (oldname));
+  if (mcore_dllimport_name_p (oldname))
     return; /* Already done.  */
 
   /* ??? One can well ask why we're making these checks here,
@@ -3368,7 +2975,7 @@ mcore_mark_dllimport (decl)
       && !DECL_VIRTUAL_P (decl)
       && DECL_INITIAL (decl))
     {
-      error_with_decl (decl, "initialized variable `%s' is marked dllimport");
+      error ("initialized variable %q+D is marked dllimport", decl);
       return;
     }
   
@@ -3382,7 +2989,7 @@ mcore_mark_dllimport (decl)
       TREE_PUBLIC (decl) = 1;
     }
 
-  newname = alloca (strlen (oldname) + 11);
+  newname = XALLOCAVEC (char, strlen (oldname) + 11);
   sprintf (newname, "@i.__imp_%s", oldname);
 
   /* We pass newname through get_identifier to ensure it has a unique
@@ -3392,15 +2999,14 @@ mcore_mark_dllimport (decl)
   /* ??? At least I think that's why we do this.  */
   idp = get_identifier (newname);
 
-  newrtl = gen_rtx (MEM, Pmode,
-                   gen_rtx (SYMBOL_REF, Pmode,
+  newrtl = gen_rtx_MEM (Pmode,
+                   gen_rtx_SYMBOL_REF (Pmode,
                             IDENTIFIER_POINTER (idp)));
   XEXP (DECL_RTL (decl), 0) = newrtl;
 }
 
 static int
-mcore_dllexport_p (decl)
-     tree decl;
+mcore_dllexport_p (tree decl)
 {
   if (   TREE_CODE (decl) != VAR_DECL
       && TREE_CODE (decl) != FUNCTION_DECL)
@@ -3410,8 +3016,7 @@ mcore_dllexport_p (decl)
 }
 
 static int
-mcore_dllimport_p (decl)
-     tree decl;
+mcore_dllimport_p (tree decl)
 {
   if (   TREE_CODE (decl) != VAR_DECL
       && TREE_CODE (decl) != FUNCTION_DECL)
@@ -3421,23 +3026,11 @@ mcore_dllimport_p (decl)
 }
 
 /* We must mark dll symbols specially.  Definitions of dllexport'd objects
-   install some info in the .drective (PE) or .exports (ELF) sections.   */
+   install some info in the .drective (PE) or .exports (ELF) sections.  */
 
 static void
-mcore_encode_section_info (decl, first)
-     tree decl;
-     int first ATTRIBUTE_UNUSED;
+mcore_encode_section_info (tree decl, rtx rtl ATTRIBUTE_UNUSED, int first ATTRIBUTE_UNUSED)
 {
-  /* This bit is copied from arm.h.  */
-  if (optimize > 0
-      && TREE_CONSTANT (decl)
-      && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
-    {
-      rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
-                 ? TREE_CST_RTL (decl) : DECL_RTL (decl));
-      SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
-    }
-
   /* Mark the decl so we can tell from the rtl whether the object is
      dllexport'd or dllimport'd.  */
   if (mcore_dllexport_p (decl))
@@ -3458,7 +3051,7 @@ mcore_encode_section_info (decl, first)
     {
       const char * oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
       tree idp = get_identifier (oldname + 9);
-      rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
+      rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
 
       XEXP (DECL_RTL (decl), 0) = newrtl;
 
@@ -3467,29 +3060,25 @@ mcore_encode_section_info (decl, first)
     }
 }
 
+/* Undo the effects of the above.  */
+
+static const char *
+mcore_strip_name_encoding (const char * str)
+{
+  return str + (str[0] == '@' ? 3 : 0);
+}
+
 /* MCore specific attribute support.
    dllexport - for exporting a function/variable that will live in a dll
    dllimport - for importing a function/variable from a dll
    naked     - do not create a function prologue/epilogue.  */
 
-const struct attribute_spec mcore_attribute_table[] =
-{
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-  { "dllexport", 0, 0, true,  false, false, NULL },
-  { "dllimport", 0, 0, true,  false, false, NULL },
-  { "naked",     0, 0, true,  false, false, mcore_handle_naked_attribute },
-  { NULL,        0, 0, false, false, false, NULL }
-};
-
 /* Handle a "naked" attribute; arguments as in
    struct attribute_spec.handler.  */
+
 static tree
-mcore_handle_naked_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
+mcore_handle_naked_attribute (tree * node, tree name, tree args ATTRIBUTE_UNUSED,
+                             int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
     {
@@ -3511,8 +3100,8 @@ mcore_handle_naked_attribute (node, name, args, flags, no_add_attrs)
     }
   else
     {
-      warning ("`%s' attribute only applies to functions",
-              IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute only applies to functions",
+              name);
       *no_add_attrs = true;
     }
 
@@ -3523,9 +3112,7 @@ mcore_handle_naked_attribute (node, name, args, flags, no_add_attrs)
    old code did as well.  */
 
 static void
-mcore_unique_section (decl, reloc)
-     tree decl;
-     int reloc ATTRIBUTE_UNUSED;
+mcore_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
 {
   int len;
   const char * name;
@@ -3535,7 +3122,7 @@ mcore_unique_section (decl, reloc)
   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
   
   /* Strip off any encoding in name.  */
-  STRIP_NAME_ENCODING (name, name);
+  name = (* targetm.strip_name_encoding) (name);
 
   /* The object is put in, for example, section .text$foo.
      The linker will then ultimately place them in .text
@@ -3544,13 +3131,13 @@ mcore_unique_section (decl, reloc)
     prefix = ".text$";
   /* For compatibility with EPOC, we ignore the fact that the
      section might have relocs against it.  */
-  else if (DECL_READONLY_SECTION (decl, 0))
+  else if (decl_readonly_section (decl, 0))
     prefix = ".rdata$";
   else
     prefix = ".data$";
   
   len = strlen (name) + strlen (prefix);
-  string = alloca (len + 1);
+  string = XALLOCAVEC (char, len + 1);
   
   sprintf (string, "%s%s", prefix, name);
 
@@ -3558,17 +3145,75 @@ mcore_unique_section (decl, reloc)
 }
 
 int
-mcore_naked_function_p ()
+mcore_naked_function_p (void)
 {
   return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
 }
 
 #ifdef OBJECT_FORMAT_ELF
 static void
-mcore_asm_named_section (name, flags)
-     const char *name;
-     unsigned int flags ATTRIBUTE_UNUSED;
+mcore_asm_named_section (const char *name, 
+                        unsigned int flags ATTRIBUTE_UNUSED,
+                        tree decl ATTRIBUTE_UNUSED)
 {
   fprintf (asm_out_file, "\t.section %s\n", name);
 }
 #endif /* OBJECT_FORMAT_ELF */
+
+/* Worker function for TARGET_ASM_EXTERNAL_LIBCALL.  */
+
+static void
+mcore_external_libcall (rtx fun)
+{
+  fprintf (asm_out_file, "\t.import\t");
+  assemble_name (asm_out_file, XSTR (fun, 0));
+  fprintf (asm_out_file, "\n");
+}
+
+/* Worker function for TARGET_RETURN_IN_MEMORY.  */
+
+static bool
+mcore_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+{
+  const HOST_WIDE_INT size = int_size_in_bytes (type);
+  return (size == -1 || size > 2 * UNITS_PER_WORD);
+}
+
+/* Worker function for TARGET_ASM_TRAMPOLINE_TEMPLATE.
+   Output assembler code for a block containing the constant parts
+   of a trampoline, leaving space for the variable parts.
+
+   On the MCore, the trampoline looks like:
+       lrw     r1,  function
+       lrw     r13, area
+       jmp     r13
+       or      r0, r0
+    .literals                                                */
+
+static void
+mcore_asm_trampoline_template (FILE *f)
+{
+  fprintf (f, "\t.short        0x7102\n");
+  fprintf (f, "\t.short        0x7d02\n");
+  fprintf (f, "\t.short        0x00cd\n");
+  fprintf (f, "\t.short        0x1e00\n");
+  fprintf (f, "\t.long 0\n");
+  fprintf (f, "\t.long 0\n");
+}
+
+/* Worker function for TARGET_TRAMPOLINE_INIT.  */
+
+static void
+mcore_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
+{
+  rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
+  rtx mem;
+
+  emit_block_move (m_tramp, assemble_trampoline_template (),
+                  GEN_INT (2*UNITS_PER_WORD), BLOCK_OP_NORMAL);
+
+  mem = adjust_address (m_tramp, SImode, 8);
+  emit_move_insn (mem, chain_value);
+  mem = adjust_address (m_tramp, SImode, 12);
+  emit_move_insn (mem, fnaddr);
+}