OSDN Git Service

* config/mcore/mcore.c Don't include assert.h.
[pf3gnuchains/gcc-fork.git] / gcc / config / mcore / mcore.c
index 826e787..6227b17 100644 (file)
@@ -1,12 +1,12 @@
 /* Output routines for Motorola MCore processor
-   Copyright (C) 1993, 1999, 2000, 2001, 2002, 2003, 2004
-   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 GCC.
 
    GCC is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published
-   by the Free Software Foundation; either version 2, or (at your
+   by the Free Software Foundation; either version 3, or (at your
    option) any later version.
 
    GCC is distributed in the hope that it will be useful, but WITHOUT
@@ -15,9 +15,8 @@
    License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING.  If not, write to
-   the Free Software Foundation, 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.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"
 #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.  */
-int mcore_stack_increment = STACK_UNITS_MAXSTEP;
+#include "df.h"
 
 /* For dumping information about frame sizes.  */
 char * mcore_current_function_name = 0;
@@ -57,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,
@@ -118,7 +106,7 @@ cond_type;
 
 static void       output_stack_adjust           (int, int);
 static int        calc_live_regs                (int *);
-static int        try_constant_tricks           (long, int *, 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);
@@ -127,30 +115,70 @@ 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, tree, int);
+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);
-const struct attribute_spec mcore_attribute_table[];
 static tree       mcore_handle_naked_attribute  (tree *, tree, tree, int, bool *);
 #ifdef OBJECT_FORMAT_ELF
 static void      mcore_asm_named_section       (const char *,
                                                 unsigned int, tree);
 #endif
+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 *);
+static bool       mcore_rtx_costs              (rtx, int, int, int *, bool);
 static void       mcore_external_libcall       (rtx);
-static bool       mcore_return_in_memory       (tree, tree);
+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.  */
 #undef  TARGET_ASM_EXTERNAL_LIBCALL
@@ -168,6 +196,13 @@ static int        mcore_arg_partial_bytes       (CUMULATIVE_ARGS *,
 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
 #endif
 
+#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
@@ -183,16 +218,14 @@ static int        mcore_arg_partial_bytes       (CUMULATIVE_ARGS *,
 #undef  TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS               mcore_rtx_costs
 #undef  TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST            hook_int_rtx_0
+#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_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS   hook_bool_tree_true
-#undef  TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#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_tree_true
+#define TARGET_PROMOTE_PROTOTYPES      hook_bool_const_tree_true
 
 #undef  TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY                mcore_return_in_memory
@@ -202,10 +235,29 @@ static int        mcore_arg_partial_bytes       (CUMULATIVE_ARGS *,
 #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.  */
@@ -267,7 +319,7 @@ calc_live_regs (int * 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);
@@ -279,7 +331,7 @@ calc_live_regs (int * count)
 
 /* Print the operand address in x to the stream.  */
 
-void
+static void
 mcore_print_operand_address (FILE * stream, rtx x)
 {
   switch (GET_CODE (x))
@@ -309,9 +361,7 @@ mcore_print_operand_address (FILE * stream, rtx x)
            break;
 
          default:
-           debug_rtx (x);
-
-           abort ();
+           gcc_unreachable ();
          }
       }
 
@@ -323,6 +373,13 @@ mcore_print_operand_address (FILE * stream, rtx 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.
 
@@ -335,7 +392,7 @@ mcore_print_operand_address (FILE * stream, rtx x)
    'U'  print register for ldm/stm instruction
    'X'  print byte number for xtrbN instruction.  */
 
-void
+static void
 mcore_print_operand (FILE * stream, rtx x, int code)
 {
   switch (code)
@@ -347,7 +404,7 @@ mcore_print_operand (FILE * stream, rtx x, int 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)));
@@ -370,7 +427,7 @@ mcore_print_operand (FILE * stream, rtx x, int code)
            (stream, XEXP (adjust_address (x, SImode, 4), 0));
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
       break;
     case 'U':
@@ -406,7 +463,7 @@ mcore_print_operand (FILE * stream, rtx x, int 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)  
@@ -434,7 +491,7 @@ mcore_const_costs (rtx exp, enum rtx_code code)
 static int
 mcore_and_cost (rtx x)
 {
-  int val;
+  HOST_WIDE_INT val;
 
   if (GET_CODE (XEXP (x, 1)) != CONST_INT)
     return 2;
@@ -460,7 +517,7 @@ mcore_and_cost (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;
@@ -482,12 +539,13 @@ mcore_ior_cost (rtx x)
 }
 
 static bool
-mcore_rtx_costs (rtx x, int code, int outer_code, int * total)
+mcore_rtx_costs (rtx x, int code, int outer_code, int * total,
+                bool speed ATTRIBUTE_UNUSED)
 {
   switch (code)
     {
     case CONST_INT:
-      *total = mcore_const_costs (x, outer_code);
+      *total = mcore_const_costs (x, (enum rtx_code) outer_code);
       return true;
     case CONST:
     case LABEL_REF:
@@ -520,26 +578,36 @@ mcore_rtx_costs (rtx x, int code, int outer_code, int * total)
     }
 }
 
-/* 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.  */
+/* Prepare the operands for a comparison.  Return whether the branch/setcc
+   should reverse the operands.  */
 
-int
-mcore_modify_comparison (enum rtx_code code)
+bool
+mcore_gen_compare (enum rtx_code code, rtx op0, rtx op1)
 {
-  rtx op1 = arch_compare_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;
          
@@ -547,28 +615,18 @@ mcore_modify_comparison (enum rtx_code code)
          break;
        }
     }
-  
-  return 0;
-}
-
-/* Prepare the operands for a comparison.  */
-
-rtx
-mcore_gen_compare_reg (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;
+      invert = true;
       /* Drop through.  */
       
     case NE:   /* Use normal condition, cmpne.  */
@@ -578,6 +636,7 @@ mcore_gen_compare_reg (enum rtx_code code)
 
     case LE:   /* Use inverted condition, reversed cmplt.  */
       code = GT;
+      invert = true;
       /* Drop through.  */
       
     case GT:   /* Use normal condition, reversed cmplt.  */
@@ -587,6 +646,7 @@ mcore_gen_compare_reg (enum rtx_code code)
 
     case GE:   /* Use inverted condition, cmplt.  */
       code = LT;
+      invert = true;
       /* Drop through.  */
       
     case LT:   /* Use normal condition, cmplt.  */
@@ -598,19 +658,10 @@ mcore_gen_compare_reg (enum rtx_code code)
       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;
+      invert = true;
       /* Drop through.  */
       
     case LEU:  /* Use normal condition, reversed cmphs.  */
@@ -620,6 +671,7 @@ mcore_gen_compare_reg (enum rtx_code code)
 
     case LTU:  /* Use inverted condition, cmphs.  */
       code = GEU;
+      invert = true;
       /* Drop through.  */
       
     case GEU:  /* Use normal condition, cmphs.  */
@@ -631,9 +683,10 @@ mcore_gen_compare_reg (enum rtx_code code)
       break;
     }
 
-  emit_insn (gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_fmt_ee (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
@@ -666,8 +719,7 @@ mcore_output_call (rtx operands[], int 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);
@@ -679,13 +731,11 @@ mcore_output_call (rtx operands[], int index)
     {
       if (TARGET_CG_DATA)
        {
-         if (mcore_current_function_name == 0)
-           abort ();
-         
-         if (GET_CODE (addr) != SYMBOL_REF)
-           abort ();
+         gcc_assert (mcore_current_function_name);
+         gcc_assert (GET_CODE (addr) == SYMBOL_REF);
          
-         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);
@@ -697,17 +747,17 @@ mcore_output_call (rtx operands[], int index)
 /* Can we load a constant with a single instruction ?  */
 
 int
-const_ok_for_mcore (int value)
+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)
+  if (CONST_OK_FOR_N (value) && value != -1)
     return 1;
   
   return 0;
@@ -716,9 +766,9 @@ const_ok_for_mcore (int value)
 /* Can we load a constant inline with up to 2 instructions ?  */
 
 int
-mcore_const_ok_for_inline (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;
 }
@@ -726,9 +776,9 @@ mcore_const_ok_for_inline (long value)
 /* Are we loading the constant using a not ?  */
 
 int
-mcore_const_trick_uses_not (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; 
 }       
@@ -750,121 +800,120 @@ mcore_const_trick_uses_not (long value)
    11: single insn followed by ixw.  */
 
 static int
-try_constant_tricks (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;
 }
@@ -921,7 +970,7 @@ mcore_is_dead (rtx first, rtx reg)
 /* Count the number of ones in mask.  */
 
 int
-mcore_num_ones (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);
@@ -935,7 +984,7 @@ mcore_num_ones (int mask)
 /* Count the number of zeros in mask.  */
 
 int
-mcore_num_zeros (int mask)
+mcore_num_zeros (HOST_WIDE_INT mask)
 {
   return 32 - mcore_num_ones (mask);
 }
@@ -1026,8 +1075,8 @@ mcore_output_bclri (rtx dst, int mask)
 const char *
 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];
@@ -1060,9 +1109,9 @@ mcore_output_cmov (rtx operands[], int cmp_t, const char * 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.  */
@@ -1090,31 +1139,35 @@ mcore_output_cmov (rtx operands[], int cmp_t, const char * test)
 const char *
 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);
@@ -1127,24 +1180,22 @@ mcore_output_andn (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
 static const char *
 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;
 
@@ -1165,15 +1216,18 @@ output_inline_const (enum machine_mode mode, rtx 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)
     {
@@ -1181,35 +1235,35 @@ output_inline_const (enum machine_mode mode, rtx 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 "";
@@ -1252,12 +1306,12 @@ mcore_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[],
              case QImode:
                return "ld.b\t%0,%1";
              default:
-               abort ();
+               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";
@@ -1283,10 +1337,10 @@ mcore_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[],
       case QImode:
        return "st.b\t%1,%0";
       default:
-       abort ();
+       gcc_unreachable ();
       }
 
-  abort ();
+  gcc_unreachable ();
 }
 
 /* Return a sequence of instructions to perform DI or DF move.
@@ -1329,10 +1383,10 @@ mcore_output_movedouble (rtx operands[], enum machine_mode mode ATTRIBUTE_UNUSED
              else if (GET_CODE (XEXP (memexp, 1)) == REG)
                basereg = REGNO (XEXP (memexp, 1));
              else
-               abort ();
+               gcc_unreachable ();
            }
          else
-           abort ();
+           gcc_unreachable ();
 
           /* ??? length attribute is wrong here.  */
          if (dstreg == basereg)
@@ -1354,12 +1408,10 @@ mcore_output_movedouble (rtx operands[], enum machine_mode mode ATTRIBUTE_UNUSED
                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 ();
+               gcc_unreachable ();
 
              if (INTVAL (src) < 0)
                return "bmaski  %R0,32";
@@ -1372,13 +1424,11 @@ mcore_output_movedouble (rtx operands[], enum machine_mode mode ATTRIBUTE_UNUSED
                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 ();
-             
+               gcc_unreachable ();
+
              if (INTVAL (src) < 0)
                return "bmaski  %0,32";
              else
@@ -1386,12 +1436,12 @@ mcore_output_movedouble (rtx operands[], enum machine_mode mode ATTRIBUTE_UNUSED
            }
        }
       else
-       abort ();
+       gcc_unreachable ();
     }
   else if (GET_CODE (dst) == MEM && GET_CODE (src) == REG)
     return "stw\t%1,%0\n\tstw\t%R1,%R0";
   else
-    abort ();
+    gcc_unreachable ();
 }
 
 /* Predicates used by the templates.  */
@@ -1422,7 +1472,7 @@ mcore_expand_insv (rtx 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],
@@ -1457,8 +1507,8 @@ mcore_expand_insv (rtx 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],
@@ -1624,7 +1674,7 @@ mcore_expand_block_move (rtx *operands)
       max = 4*1;
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   if (bytes <= max)
@@ -1656,14 +1706,13 @@ layout_mcore_frame (struct mcore_frame * infp)
   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)
@@ -1677,7 +1726,7 @@ layout_mcore_frame (struct mcore_frame * infp)
 
   /* 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)
@@ -1701,7 +1750,6 @@ layout_mcore_frame (struct 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;
 
@@ -1777,7 +1825,7 @@ layout_mcore_frame (struct 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)
@@ -1855,18 +1903,11 @@ layout_mcore_frame (struct 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
@@ -1895,9 +1936,7 @@ mcore_initial_elimination_offset (int from, int 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.  */
@@ -1946,13 +1985,11 @@ mcore_expand_prolog (void)
 
       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);
@@ -1961,7 +1998,7 @@ mcore_expand_prolog (void)
       
       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:
@@ -1985,7 +2022,7 @@ mcore_expand_prolog (void)
   /* 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;
@@ -2140,7 +2177,7 @@ mcore_expand_epilog (void)
 
 /* 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.
 
@@ -2625,30 +2662,30 @@ mcore_r15_operand_p (rtx x)
     }
 }
 
-/* Implement SECONDARY_RELOAD_CLASS.  If CLASS contains r15, and we can't
+/* Implement SECONDARY_RELOAD_CLASS.  If RCLASS contains r15, and we can't
    directly move X into it, use r1-r14 as a temporary.  */
 
 enum reg_class
-mcore_secondary_reload_class (enum reg_class 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[class], 15)
+  if (TEST_HARD_REG_BIT (reg_class_contents[rclass], 15)
       && !mcore_r15_operand_p (x))
     return LRW_REGS;
   return NO_REGS;
 }
 
 /* Return the reg_class to use when reloading the rtx X into the class
-   CLASS.  If X is too complex to move directly into r15, prefer to
+   RCLASS.  If X is too complex to move directly into r15, prefer to
    use LRW_REGS instead.  */
 
 enum reg_class
-mcore_reload_class (rtx x, enum reg_class class)
+mcore_reload_class (rtx x, enum reg_class rclass)
 {
-  if (reg_class_subset_p (LRW_REGS, class) && !mcore_r15_operand_p (x))
+  if (reg_class_subset_p (LRW_REGS, rclass) && !mcore_r15_operand_p (x))
     return LRW_REGS;
 
-  return class;
+  return rclass;
 }
 
 /* Tell me if a pair of reg/subreg rtx's actually refer to the same
@@ -2673,19 +2710,20 @@ mcore_is_same_reg (rtx x, rtx y)
   return 0;
 }
 
-void
-mcore_override_options (void)
+static void
+mcore_option_override (void)
 {
   /* Only the m340 supports little endian code.  */
   if (TARGET_LITTLE_END && ! TARGET_M340)
     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 (enum machine_mode mode, tree type)
+mcore_num_arg_regs (enum machine_mode mode, const_tree type)
 {
   int size;
 
@@ -2701,7 +2739,7 @@ mcore_num_arg_regs (enum machine_mode mode, tree type)
 }
 
 static rtx
-handle_structs_in_regs (enum machine_mode mode, tree type, int reg)
+handle_structs_in_regs (enum machine_mode mode, const_tree type, int reg)
 {
   int size;
 
@@ -2733,7 +2771,7 @@ handle_structs_in_regs (enum machine_mode mode, tree type, int 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]);
       
@@ -2745,14 +2783,15 @@ handle_structs_in_regs (enum machine_mode mode, tree type, int reg)
 }
 
 rtx
-mcore_function_value (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);
 }
@@ -2775,9 +2814,9 @@ mcore_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
    NPARM_REGS words is at least partially passed in a register unless
    its data type forbids.  */
 
-rtx
-mcore_function_arg (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;
   
@@ -2787,7 +2826,7 @@ mcore_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
   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);
@@ -2795,6 +2834,24 @@ mcore_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
   return 0;
 }
 
+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
@@ -2866,18 +2923,15 @@ mcore_mark_dllexport (tree 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
@@ -2904,17 +2958,13 @@ mcore_mark_dllimport (tree 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,
@@ -2925,7 +2975,7 @@ mcore_mark_dllimport (tree decl)
       && !DECL_VIRTUAL_P (decl)
       && DECL_INITIAL (decl))
     {
-      error ("%Jinitialized variable '%D' is marked dllimport", decl, decl);
+      error ("initialized variable %q+D is marked dllimport", decl);
       return;
     }
   
@@ -2939,7 +2989,7 @@ mcore_mark_dllimport (tree 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
@@ -3023,15 +3073,6 @@ mcore_strip_name_encoding (const char * str)
    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.  */
 
@@ -3059,8 +3100,8 @@ mcore_handle_naked_attribute (tree * node, tree name, tree args ATTRIBUTE_UNUSED
     }
   else
     {
-      warning (0, "%qs attribute only applies to functions",
-              IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute only applies to functions",
+              name);
       *no_add_attrs = true;
     }
 
@@ -3096,7 +3137,7 @@ mcore_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
     prefix = ".data$";
   
   len = strlen (name) + strlen (prefix);
-  string = alloca (len + 1);
+  string = XALLOCAVEC (char, len + 1);
   
   sprintf (string, "%s%s", prefix, name);
 
@@ -3132,8 +3173,47 @@ mcore_external_libcall (rtx fun)
 /* Worker function for TARGET_RETURN_IN_MEMORY.  */
 
 static bool
-mcore_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+mcore_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
 {
-  HOST_WIDE_INT size = int_size_in_bytes (type);
+  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);
+}