OSDN Git Service

2005-07-02 Zack Weinberg <zack@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / config / mcore / mcore.c
index bdf50cc..8237d45 100644 (file)
@@ -1,5 +1,5 @@
 /* Output routines for Motorola MCore processor
-   Copyright (C) 1993, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright (C) 1993, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
 
    This file is part of GCC.
@@ -16,8 +16,8 @@
 
    You should have received a copy of the GNU General Public License
    along with GCC; see the file COPYING.  If not, write to
-   the Free Software Foundation, 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -49,8 +49,7 @@
 /* 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;
+int mcore_stack_increment = STACK_UNITS_MAXSTEP;
 
 /* For dumping information about frame sizes.  */
 char * mcore_current_function_name = 0;
@@ -119,10 +118,8 @@ cond_type;
 
 static void       output_stack_adjust           (int, int);
 static int        calc_live_regs                (int *);
-static int        const_ok_for_mcore            (int);
 static int        try_constant_tricks           (long, int *, int *);
 static const char *     output_inline_const     (enum machine_mode, rtx *);
-static void       block_move_sequence           (rtx, rtx, rtx, rtx, int, int, int);
 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);
@@ -139,7 +136,7 @@ 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);
+                                                unsigned int, tree);
 #endif
 static void       mcore_unique_section         (tree, int);
 static void mcore_encode_section_info          (tree, rtx, int);
@@ -150,13 +147,16 @@ static int        mcore_ior_cost                  (rtx);
 static bool       mcore_rtx_costs              (rtx, int, int, int *);
 static void       mcore_external_libcall       (rtx);
 static bool       mcore_return_in_memory       (tree, tree);
+static int        mcore_arg_partial_bytes       (CUMULATIVE_ARGS *,
+                                                enum machine_mode,
+                                                tree, bool);
 
 \f
 /* Initialize the GCC target structure.  */
 #undef  TARGET_ASM_EXTERNAL_LIBCALL
 #define TARGET_ASM_EXTERNAL_LIBCALL    mcore_external_libcall
 
-#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
 #undef  TARGET_MERGE_DECL_ATTRIBUTES
 #define TARGET_MERGE_DECL_ATTRIBUTES   merge_dllimport_decl_attributes
 #endif
@@ -172,6 +172,10 @@ static bool       mcore_return_in_memory   (tree, tree);
 #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
@@ -196,6 +200,8 @@ static bool       mcore_return_in_memory    (tree, tree);
 #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_SETUP_INCOMING_VARARGS
 #define TARGET_SETUP_INCOMING_VARARGS  mcore_setup_incoming_varargs
@@ -303,9 +309,7 @@ mcore_print_operand_address (FILE * stream, rtx x)
            break;
 
          default:
-           debug_rtx (x);
-
-           abort ();
+           gcc_unreachable ();
          }
       }
 
@@ -320,7 +324,7 @@ mcore_print_operand_address (FILE * stream, rtx x)
 /* 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
@@ -364,7 +368,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':
@@ -592,18 +596,12 @@ 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;
-       }
+      /* 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.  */
+      gcc_assert (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0);
       code = LEU;
       /* Drop through.  */
       
@@ -648,12 +646,6 @@ mcore_symbolic_address_p (rtx x)
     }
 }
 
-int
-mcore_call_address_operand (rtx x, enum machine_mode mode)
-{
-  return register_operand (x, mode) || CONSTANT_P (x);
-}
-
 /* Functions to output assembly code for a function call.  */
 
 char *
@@ -666,8 +658,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 +670,11 @@ mcore_output_call (rtx operands[], int 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);
@@ -696,7 +685,7 @@ mcore_output_call (rtx operands[], int index)
 
 /* Can we load a constant with a single instruction ?  */
 
-static int
+int
 const_ok_for_mcore (int value)
 {
   if (value >= 0 && value <= 127)
@@ -913,7 +902,7 @@ mcore_is_dead (rtx first, rtx 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;
 }
@@ -1094,9 +1083,10 @@ mcore_output_andn (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
   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);
@@ -1136,15 +1126,13 @@ output_inline_const (enum machine_mode mode, rtx operands[])
   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;
 
@@ -1252,7 +1240,7 @@ 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)
@@ -1283,10 +1271,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 +1317,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)
@@ -1359,7 +1347,7 @@ mcore_output_movedouble (rtx operands[], enum machine_mode mode ATTRIBUTE_UNUSED
              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";
@@ -1377,7 +1365,7 @@ mcore_output_movedouble (rtx operands[], enum machine_mode mode ATTRIBUTE_UNUSED
              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";
@@ -1386,130 +1374,16 @@ 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.  */
 
-/* Nonzero if OP can be source of a simple move operation.  */
-
-int
-mcore_general_movsrc_operand (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);
-}
-
-/* Nonzero if OP can be destination of a simple move operation.  */
-
-int
-mcore_general_movdst_operand (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 (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;
-}
-
-/* Nonzero if OP should be recognized during reload for an ixh/ixw
-   operand.  See the ixh/ixw patterns.  */
-
-int
-mcore_reload_operand (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 (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 (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 (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 (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 (rtx op)
 {
@@ -1519,110 +1393,6 @@ mcore_arith_S_operand (rtx op)
   return 0;
 }
 
-int
-mcore_arith_M_operand (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 (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 (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 (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 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  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 an add/sub insn.  */
-
-int
-mcore_addsub_operand (rtx op, enum machine_mode mode)
-{
-  if (register_operand (op, mode))
-    return 1;
-
-  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;
-      */
-    }
-  
-  return 0;
-}
-
-/* Nonzero if OP is a valid source operand for a compare operation.  */
-
-int
-mcore_compare_operand (rtx op, enum machine_mode mode)
-{
-  if (register_operand (op, mode))
-    return 1;
-
-  if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
-    return 1;
-  
-  return 0;
-}
-
 /* Expand insert bit field.  BRC  */
 
 int
@@ -1722,87 +1492,6 @@ mcore_expand_insv (rtx operands[])
 
   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 (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 (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;
-    }
-
-  return 1;
-}
 \f
 /* ??? Block move stuff stolen from m88k.  This code has not been
    verified for correctness.  */
@@ -1822,127 +1511,117 @@ mcore_store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 static const enum machine_mode mode_from_align[] =
 {
   VOIDmode, QImode, HImode, VOIDmode, SImode,
-  VOIDmode, VOIDmode, VOIDmode, DImode
 };
 
 static void
-block_move_sequence (rtx dest, rtx dst_mem, rtx src, rtx 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_INT (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;
+         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_INT (offset_st)));
-         
-         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 (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 (GET_CODE (operands[2]) == CONST_INT)
+  if (bytes <= 0)
+    return false;
+  if (align > 4)
+    align = 4;
+
+  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
 
@@ -2168,14 +1847,7 @@ layout_mcore_frame (struct mcore_frame * infp)
   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
@@ -2204,9 +1876,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.  */
@@ -2255,13 +1925,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);
@@ -2449,7 +2117,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.
 
@@ -2791,7 +2459,7 @@ conditionalize_block (rtx 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 ++;
@@ -2985,21 +2653,9 @@ mcore_is_same_reg (rtx x, rtx y)
 void
 mcore_override_options (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;
+    target_flags |= MASK_M340;
 }
 \f
 /* Compute the number of word sized registers needed to 
@@ -3026,7 +2682,7 @@ handle_structs_in_regs (enum machine_mode mode, 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.
@@ -3102,7 +2758,7 @@ mcore_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
 {
   int arg_reg;
   
-  if (! named)
+  if (! named || mode == VOIDmode)
     return 0;
 
   if (targetm.calls.must_pass_in_stack (mode, type))
@@ -3116,19 +2772,18 @@ mcore_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
   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
+/* 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 (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;
@@ -3157,7 +2812,7 @@ mcore_function_arg_partial_nregs (CUMULATIVE_ARGS cum, enum machine_mode mode,
   reg = NPARM_REGS - reg;
 
   /* Return partially in registers and partially on the stack.  */
-  return reg;
+  return reg * UNITS_PER_WORD;
 }
 \f
 /* Return nonzero if SYMBOL is marked as being dllexport'd.  */
@@ -3188,13 +2843,10 @@ 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.  */
@@ -3226,17 +2878,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,
@@ -3247,7 +2895,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;
     }
   
@@ -3381,7 +3029,7 @@ mcore_handle_naked_attribute (tree * node, tree name, tree args ATTRIBUTE_UNUSED
     }
   else
     {
-      warning ("`%s' attribute only applies to functions",
+      warning (OPT_Wattributes, "%qs attribute only applies to functions",
               IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
@@ -3433,7 +3081,9 @@ mcore_naked_function_p (void)
 
 #ifdef OBJECT_FORMAT_ELF
 static void
-mcore_asm_named_section (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);
 }