OSDN Git Service

2010-04-06 Kai Tietz <kai.tietz@onevision.com>
[pf3gnuchains/gcc-fork.git] / gcc / config / v850 / v850.c
index f3a165d..b7dd092 100644 (file)
@@ -1,13 +1,13 @@
 /* Subroutines for insn-output.c for NEC V850 series
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
-   Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2006, 2007, 2008, 2009 Free Software Foundation, Inc.
    Contributed by Jeff Law (law@cygnus.com).
 
    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 option)
+   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
@@ -16,9 +16,8 @@
    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 "tm_p.h"
 #include "target.h"
 #include "target-def.h"
+#include "df.h"
 
 #ifndef streq
 #define streq(a,b) (strcmp (a, b) == 0)
 #endif
 
 /* Function prototypes for stupid compilers:  */
+static bool v850_handle_option       (size_t, const char *, int);
 static void const_double_split       (rtx, HOST_WIDE_INT *, HOST_WIDE_INT *);
 static int  const_costs_int          (HOST_WIDE_INT, int);
 static int  const_costs                     (rtx, enum rtx_code);
-static bool v850_rtx_costs          (rtx, int, int, int *);
+static bool v850_rtx_costs          (rtx, int, int, int *, bool);
 static void substitute_ep_register   (rtx, rtx, int, int, rtx *, rtx *);
 static void v850_reorg              (void);
 static int  ep_memory_offset         (enum machine_mode, int);
 static void v850_set_data_area       (tree, v850_data_area);
-const struct attribute_spec v850_attribute_table[];
 static tree v850_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
 static tree v850_handle_data_area_attribute (tree *, tree, tree, int, bool *);
 static void v850_insert_attributes   (tree, tree *);
-static void v850_select_section (tree, int, unsigned HOST_WIDE_INT);
+static void v850_asm_init_sections   (void);
+static section *v850_select_section (tree, int, unsigned HOST_WIDE_INT);
 static void v850_encode_data_area    (tree, rtx);
 static void v850_encode_section_info (tree, rtx, int);
-static bool v850_return_in_memory    (tree, tree);
+static bool v850_return_in_memory    (const_tree, const_tree);
+static rtx v850_function_value (const_tree, const_tree, bool);
 static void v850_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
                                         tree, int *, int);
 static bool v850_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
-                                   tree, bool);
+                                   const_tree, bool);
 static int v850_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
                                   tree, bool);
+static bool v850_can_eliminate       (const int, const int);
+static void v850_asm_trampoline_template (FILE *);
+static void v850_trampoline_init (rtx, tree, rtx);
 
 /* Information about the various small memory areas.  */
 struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] =
 {
-  /* name      value           max             physical max */
-  { "tda",     (char *)0,      0,              256 },
-  { "sda",     (char *)0,      0,              65536 },
-  { "zda",     (char *)0,      0,              32768 },
+  /* name      max     physical max */
+  { "tda",     0,              256 },
+  { "sda",     0,              65536 },
+  { "zda",     0,              32768 },
 };
 
 /* Names of the various data areas used on the v850.  */
@@ -95,6 +100,26 @@ static int v850_interrupt_cache_p = FALSE;
 
 /* Whether current function is an interrupt handler.  */
 static int v850_interrupt_p = FALSE;
+
+static GTY(()) section *rosdata_section;
+static GTY(()) section *rozdata_section;
+static GTY(()) section *tdata_section;
+static GTY(()) section *zdata_section;
+static GTY(()) section *zbss_section;
+\f
+/* V850 specific attributes.  */
+
+static const struct attribute_spec v850_attribute_table[] =
+{
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+  { "interrupt_handler", 0, 0, true,  false, false, v850_handle_interrupt_attribute },
+  { "interrupt",         0, 0, true,  false, false, v850_handle_interrupt_attribute },
+  { "sda",               0, 0, true,  false, false, v850_handle_data_area_attribute },
+  { "tda",               0, 0, true,  false, false, v850_handle_data_area_attribute },
+  { "zda",               0, 0, true,  false, false, v850_handle_data_area_attribute },
+  { NULL,                0, 0, false, false, false, NULL }
+};
+
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
@@ -109,27 +134,40 @@ static int v850_interrupt_p = FALSE;
 #undef  TARGET_ASM_SELECT_SECTION
 #define TARGET_ASM_SELECT_SECTION  v850_select_section
 
+/* The assembler supports switchable .bss sections, but
+   v850_select_section doesn't yet make use of them.  */
+#undef  TARGET_HAVE_SWITCHABLE_BSS_SECTIONS
+#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false
+
 #undef TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO v850_encode_section_info
 
 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
 
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS (MASK_DEFAULT | MASK_APP_REGS)
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION v850_handle_option
+
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS v850_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 v850_reorg
 
 #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 v850_return_in_memory
 
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE v850_function_value
+
 #undef TARGET_PASS_BY_REFERENCE
 #define TARGET_PASS_BY_REFERENCE v850_pass_by_reference
 
@@ -142,55 +180,78 @@ static int v850_interrupt_p = FALSE;
 #undef TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE v850_can_eliminate
+
+#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
+#define TARGET_ASM_TRAMPOLINE_TEMPLATE v850_asm_trampoline_template
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT v850_trampoline_init
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
-/* Sometimes certain combinations of command options do not make
-   sense on a particular target machine.  You can define a macro
-   `OVERRIDE_OPTIONS' to take account of this.  This macro, if
-   defined, is executed once just after all the command options have
-   been parsed.
+/* Set the maximum size of small memory area TYPE to the value given
+   by VALUE.  Return true if VALUE was syntactically correct.  VALUE
+   starts with the argument separator: either "-" or "=".  */
 
-   Don't use this macro to turn on various extra optimizations for
-   `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */
-
-void
-override_options (void)
+static bool
+v850_handle_memory_option (enum small_memory_type type, const char *value)
 {
-  int i;
-  extern int atoi (const char *);
+  int i, size;
 
-  /* Parse -m{s,t,z}da=nnn switches */
-  for (i = 0; i < (int)SMALL_MEMORY_max; i++)
-    {
-      if (small_memory[i].value)
-       {
-         if (!ISDIGIT (*small_memory[i].value))
-           error ("%s=%s is not numeric",
-                  small_memory[i].name,
-                  small_memory[i].value);
-         else
-           {
-             small_memory[i].max = atoi (small_memory[i].value);
-             if (small_memory[i].max > small_memory[i].physical_max)
-               error ("%s=%s is too large",
-                  small_memory[i].name,
-                  small_memory[i].value);
-           }
-       }
-    }
+  if (*value != '-' && *value != '=')
+    return false;
+
+  value++;
+  for (i = 0; value[i]; i++)
+    if (!ISDIGIT (value[i]))
+      return false;
+
+  size = atoi (value);
+  if (size > small_memory[type].physical_max)
+    error ("value passed to %<-m%s%> is too large", small_memory[type].name);
+  else
+    small_memory[type].max = size;
+  return true;
+}
 
-  /* Make sure that the US_BIT_SET mask has been correctly initialized.  */
-  if ((target_flags & MASK_US_MASK_SET) == 0)
+/* Implement TARGET_HANDLE_OPTION.  */
+
+static bool
+v850_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
+{
+  switch (code)
     {
-      target_flags |= MASK_US_MASK_SET;
-      target_flags &= ~MASK_US_BIT_SET;
+    case OPT_mspace:
+      target_flags |= MASK_EP | MASK_PROLOG_FUNCTION;
+      return true;
+
+    case OPT_mv850:
+      target_flags &= ~(MASK_CPU ^ MASK_V850);
+      return true;
+
+    case OPT_mv850e:
+    case OPT_mv850e1:
+      target_flags &= ~(MASK_CPU ^ MASK_V850E);
+      return true;
+
+    case OPT_mtda:
+      return v850_handle_memory_option (SMALL_MEMORY_TDA, arg);
+
+    case OPT_msda:
+      return v850_handle_memory_option (SMALL_MEMORY_SDA, arg);
+
+    case OPT_mzda:
+      return v850_handle_memory_option (SMALL_MEMORY_ZDA, arg);
+
+    default:
+      return true;
     }
 }
-
 \f
 static bool
 v850_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
-                       enum machine_mode mode, tree type,
+                       enum machine_mode mode, const_tree type,
                        bool named ATTRIBUTE_UNUSED)
 {
   unsigned HOST_WIDE_INT size;
@@ -203,8 +264,9 @@ v850_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
   return size > 8;
 }
 
-/* Return an RTX to represent where a value with mode MODE will be returned
-   from a function.  If the result is 0, the argument is pushed.  */
+/* Return an RTX to represent where an argument with mode MODE
+   and type TYPE will be passed to a function.  If the result
+   is NULL_RTX, the argument will be pushed.  */
 
 rtx
 function_arg (CUMULATIVE_ARGS * cum,
@@ -212,7 +274,7 @@ function_arg (CUMULATIVE_ARGS * cum,
               tree type,
               int named)
 {
-  rtx result = 0;
+  rtx result = NULL_RTX;
   int size, align;
 
   if (TARGET_GHS && !named)
@@ -224,7 +286,11 @@ function_arg (CUMULATIVE_ARGS * cum,
     size = GET_MODE_SIZE (mode);
 
   if (size < 1)
-    return 0;
+    {
+      /* Once we have stopped using argument registers, do not start up again.  */
+      cum->nbytes = 4 * UNITS_PER_WORD;
+      return NULL_RTX;
+    }
 
   if (type)
     align = TYPE_ALIGN (type) / BITS_PER_UNIT;
@@ -234,11 +300,11 @@ function_arg (CUMULATIVE_ARGS * cum,
   cum->nbytes = (cum->nbytes + align - 1) &~(align - 1);
 
   if (cum->nbytes > 4 * UNITS_PER_WORD)
-    return 0;
+    return NULL_RTX;
 
   if (type == NULL_TREE
       && cum->nbytes + size > 4 * UNITS_PER_WORD)
-    return 0;
+    return NULL_RTX;
 
   switch (cum->nbytes / UNITS_PER_WORD)
     {
@@ -255,7 +321,7 @@ function_arg (CUMULATIVE_ARGS * cum,
       result = gen_rtx_REG (mode, 9);
       break;
     default:
-      result = 0;
+      result = NULL_RTX;
     }
 
   return result;
@@ -279,12 +345,15 @@ v850_arg_partial_bytes (CUMULATIVE_ARGS * cum, enum machine_mode mode,
   else
     size = GET_MODE_SIZE (mode);
 
+  if (size < 1)
+    size = 1;
+  
   if (type)
     align = TYPE_ALIGN (type) / BITS_PER_UNIT;
   else
     align = size;
 
-  cum->nbytes = (cum->nbytes + align - 1) &~(align - 1);
+  cum->nbytes = (cum->nbytes + align - 1) & ~ (align - 1);
 
   if (cum->nbytes > 4 * UNITS_PER_WORD)
     return 0;
@@ -387,10 +456,12 @@ const_costs (rtx r, enum rtx_code c)
 
 static bool
 v850_rtx_costs (rtx x,
-                int code,
+                int codearg,
                 int outer_code ATTRIBUTE_UNUSED,
-                int * total)
+                int * total, bool speed)
 {
+  enum rtx_code code = (enum rtx_code) codearg;
+
   switch (code)
     {
     case CONST_INT:
@@ -405,7 +476,7 @@ v850_rtx_costs (rtx x,
     case DIV:
     case UMOD:
     case UDIV:
-      if (TARGET_V850E && optimize_size)
+      if (TARGET_V850E && !speed)
         *total = 6;
       else
        *total = 60;
@@ -431,6 +502,11 @@ v850_rtx_costs (rtx x,
        *total = 20;
       return true;
 
+    case ZERO_EXTRACT:
+      if (outer_code == COMPARE)
+       *total = 0;
+      return false;
+
     default:
       return false;
     }
@@ -497,30 +573,40 @@ print_operand (FILE * file, rtx x, int code)
            fprintf (file, "l");
            break;
          default:
-           abort ();
+           gcc_unreachable ();
        }
       break;
     case 'F':                  /* high word of CONST_DOUBLE */
-      if (GET_CODE (x) == CONST_INT)
-       fprintf (file, "%d", (INTVAL (x) >= 0) ? 0 : -1);
-      else if (GET_CODE (x) == CONST_DOUBLE)
+      switch (GET_CODE (x))
        {
+       case CONST_INT:
+         fprintf (file, "%d", (INTVAL (x) >= 0) ? 0 : -1);
+         break;
+         
+       case CONST_DOUBLE:
          const_double_split (x, &high, &low);
          fprintf (file, "%ld", (long) high);
+         break;
+
+       default:
+         gcc_unreachable ();
        }
-      else
-       abort ();
       break;
     case 'G':                  /* low word of CONST_DOUBLE */
-      if (GET_CODE (x) == CONST_INT)
-       fprintf (file, "%ld", (long) INTVAL (x));
-      else if (GET_CODE (x) == CONST_DOUBLE)
+      switch (GET_CODE (x))
        {
+       case CONST_INT:
+         fprintf (file, "%ld", (long) INTVAL (x));
+         break;
+         
+       case CONST_DOUBLE:
          const_double_split (x, &high, &low);
          fprintf (file, "%ld", (long) low);
+         break;
+
+       default:
+         gcc_unreachable ();
        }
-      else
-       abort ();
       break;
     case 'L':
       fprintf (file, "%d\n", (int)(INTVAL (x) & 0xffff));
@@ -529,54 +615,42 @@ print_operand (FILE * file, rtx x, int code)
       fprintf (file, "%d", exact_log2 (INTVAL (x)));
       break;
     case 'O':
-      if (special_symbolref_operand (x, VOIDmode))
-        {
-         if (GET_CODE (x) == SYMBOL_REF)
-           ;
-         else if (GET_CODE (x) == CONST)
-           x = XEXP (XEXP (x, 0), 0);
-         else
-           abort ();
-
-          if (SYMBOL_REF_ZDA_P (x))
-            fprintf (file, "zdaoff");
-          else if (SYMBOL_REF_SDA_P (x))
-            fprintf (file, "sdaoff");
-          else if (SYMBOL_REF_TDA_P (x))
-            fprintf (file, "tdaoff");
-          else
-            abort ();
-        }
+      gcc_assert (special_symbolref_operand (x, VOIDmode));
+      
+      if (GET_CODE (x) == CONST)
+       x = XEXP (XEXP (x, 0), 0);
       else
-        abort ();
+       gcc_assert (GET_CODE (x) == SYMBOL_REF);
+      
+      if (SYMBOL_REF_ZDA_P (x))
+       fprintf (file, "zdaoff");
+      else if (SYMBOL_REF_SDA_P (x))
+       fprintf (file, "sdaoff");
+      else if (SYMBOL_REF_TDA_P (x))
+       fprintf (file, "tdaoff");
+      else
+       gcc_unreachable ();
       break;
     case 'P':
-      if (special_symbolref_operand (x, VOIDmode))
-        output_addr_const (file, x);
-      else
-        abort ();
+      gcc_assert (special_symbolref_operand (x, VOIDmode));
+      output_addr_const (file, x);
       break;
     case 'Q':
-      if (special_symbolref_operand (x, VOIDmode))
-        {
-         if (GET_CODE (x) == SYMBOL_REF)
-           ;
-         else if (GET_CODE (x) == CONST)
-           x = XEXP (XEXP (x, 0), 0);
-         else
-           abort ();
-
-          if (SYMBOL_REF_ZDA_P (x))
-            fprintf (file, "r0");
-          else if (SYMBOL_REF_SDA_P (x))
-            fprintf (file, "gp");
-          else if (SYMBOL_REF_TDA_P (x))
-            fprintf (file, "ep");
-          else
-            abort ();
-        }
+      gcc_assert (special_symbolref_operand (x, VOIDmode));
+      
+      if (GET_CODE (x) == CONST)
+       x = XEXP (XEXP (x, 0), 0);
+      else
+       gcc_assert (GET_CODE (x) == SYMBOL_REF);
+      
+      if (SYMBOL_REF_ZDA_P (x))
+       fprintf (file, "r0");
+      else if (SYMBOL_REF_SDA_P (x))
+       fprintf (file, "gp");
+      else if (SYMBOL_REF_TDA_P (x))
+       fprintf (file, "ep");
       else
-        abort ();
+       gcc_unreachable ();
       break;
     case 'R':          /* 2nd word of a double.  */
       switch (GET_CODE (x))
@@ -597,7 +671,7 @@ print_operand (FILE * file, rtx x, int code)
       break;
     case 'S':
       {
-        /* if it's a reference to a TDA variable, use sst/sld vs. st/ld */
+        /* If it's a reference to a TDA variable, use sst/sld vs. st/ld.  */
         if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), FALSE))
           fputs ("s", file);
 
@@ -615,7 +689,7 @@ print_operand (FILE * file, rtx x, int code)
       switch (GET_MODE (x))
        {
        default:
-         abort ();
+         gcc_unreachable ();
 
        case QImode: fputs (".b", file); break;
        case HImode: fputs (".h", file); break;
@@ -627,12 +701,13 @@ print_operand (FILE * file, rtx x, int code)
       fputs (reg_names[0], file);
       break;
     case 'z':                  /* reg or zero */
-      if (x == const0_rtx)
-       fputs (reg_names[0], file);
-      else if (GET_CODE (x) == REG)
+      if (GET_CODE (x) == REG)
        fputs (reg_names[REGNO (x)], file);
       else
-       abort ();
+       {
+         gcc_assert (x == const0_rtx);
+         fputs (reg_names[0], file);
+       }
       break;
     default:
       switch (GET_CODE (x))
@@ -659,7 +734,7 @@ print_operand (FILE * file, rtx x, int code)
          print_operand_address (file, x);
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
       break;
 
@@ -758,7 +833,7 @@ print_operand_address (FILE * file, rtx addr)
               reg_name = "ep";
             }
           else
-            abort ();
+            gcc_unreachable ();
 
           fprintf (file, "%s(", off_name);
           output_addr_const (file, addr);
@@ -822,10 +897,10 @@ output_move_single (rtx * operands)
        {
          HOST_WIDE_INT value = INTVAL (src);
 
-         if (CONST_OK_FOR_J (value))           /* Signed 5 bit immediate.  */
+         if (CONST_OK_FOR_J (value))           /* Signed 5-bit immediate.  */
            return "mov %1,%0";
 
-         else if (CONST_OK_FOR_K (value))      /* Signed 16 bit immediate.  */
+         else if (CONST_OK_FOR_K (value))      /* Signed 16-bit immediate.  */
            return "movea lo(%1),%.,%0";
 
          else if (CONST_OK_FOR_L (value))      /* Upper 16 bits were set.  */
@@ -844,10 +919,10 @@ output_move_single (rtx * operands)
 
          const_double_split (src, &high, &low);
 
-         if (CONST_OK_FOR_J (high))            /* Signed 5 bit immediate.  */
+         if (CONST_OK_FOR_J (high))            /* Signed 5-bit immediate.  */
            return "mov %F1,%0";
 
-         else if (CONST_OK_FOR_K (high))       /* Signed 16 bit immediate.  */
+         else if (CONST_OK_FOR_K (high))       /* Signed 16-bit immediate.  */
            return "movea lo(%F1),%.,%0";
 
          else if (CONST_OK_FOR_L (high))       /* Upper 16 bits were set.  */
@@ -906,84 +981,6 @@ output_move_single (rtx * operands)
 }
 
 \f
-/* Return appropriate code to load up an 8 byte integer or
-   floating point value */
-
-const char *
-output_move_double (rtx * operands)
-{
-  enum machine_mode mode = GET_MODE (operands[0]);
-  rtx dst = operands[0];
-  rtx src = operands[1];
-
-  if (register_operand (dst, mode)
-      && register_operand (src, mode))
-    {
-      if (REGNO (src) + 1 == REGNO (dst))
-       return "mov %R1,%R0\n\tmov %1,%0";
-      else
-       return "mov %1,%0\n\tmov %R1,%R0";
-    }
-
-  /* Storing 0 */
-  if (GET_CODE (dst) == MEM
-      && ((GET_CODE (src) == CONST_INT && INTVAL (src) == 0)
-         || (GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src))))
-    return "st.w %.,%0\n\tst.w %.,%R0";
-
-  if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
-    {
-      HOST_WIDE_INT high_low[2];
-      int i;
-      rtx xop[10];
-
-      if (GET_CODE (src) == CONST_DOUBLE)
-       const_double_split (src, &high_low[1], &high_low[0]);
-      else
-       {
-         high_low[0] = INTVAL (src);
-         high_low[1] = (INTVAL (src) >= 0) ? 0 : -1;
-       }
-
-      for (i = 0; i < 2; i++)
-       {
-         xop[0] = gen_rtx_REG (SImode, REGNO (dst)+i);
-         xop[1] = GEN_INT (high_low[i]);
-         output_asm_insn (output_move_single (xop), xop);
-       }
-
-      return "";
-    }
-
-  if (GET_CODE (src) == MEM)
-    {
-      int ptrreg = -1;
-      int dreg = REGNO (dst);
-      rtx inside = XEXP (src, 0);
-
-      if (GET_CODE (inside) == REG)
-       ptrreg = REGNO (inside);
-      else if (GET_CODE (inside) == SUBREG)
-       ptrreg = subreg_regno (inside);
-      else if (GET_CODE (inside) == PLUS)
-       ptrreg = REGNO (XEXP (inside, 0));
-      else if (GET_CODE (inside) == LO_SUM)
-       ptrreg = REGNO (XEXP (inside, 0));
-
-      if (dreg == ptrreg)
-       return "ld.w %R1,%R0\n\tld.w %1,%0";
-    }
-
-  if (GET_CODE (src) == MEM)
-    return "ld.w %1,%0\n\tld.w %R1,%R0";
-  
-  if (GET_CODE (dst) == MEM)
-    return "st.w %1,%0\n\tst.w %R1,%R0";
-
-  return "mov %1,%0\n\tmov %R1,%R0";
-}
-
-\f
 /* Return maximum offset supported for a short EP memory reference of mode
    MODE and signedness UNSIGNEDP.  */
 
@@ -1037,6 +1034,13 @@ ep_memory_operand (rtx op, enum machine_mode mode, int unsigned_load)
   int max_offset;
   int mask;
 
+  /* If we are not using the EP register on a per-function basis
+     then do not allow this optimization at all.  This is to
+     prevent the use of the SLD/SST instructions which cannot be
+     guaranteed to work properly due to a hardware bug.  */
+  if (!TARGET_EP)
+    return FALSE;
+
   if (GET_CODE (op) != MEM)
     return FALSE;
 
@@ -1078,132 +1082,6 @@ ep_memory_operand (rtx op, enum machine_mode mode, int unsigned_load)
 
   return FALSE;
 }
-
-/* Return true if OP is either a register or 0 */
-
-int
-reg_or_0_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_INT)
-    return INTVAL (op) == 0;
-
-  else if (GET_CODE (op) == CONST_DOUBLE)
-    return CONST_DOUBLE_OK_FOR_G (op);
-
-  else
-    return register_operand (op, mode);
-}
-
-/* Return true if OP is either a register or a signed five bit integer */
-
-int
-reg_or_int5_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_INT)
-    return CONST_OK_FOR_J (INTVAL (op));
-
-  else
-    return register_operand (op, mode);
-}
-
-/* Return true if OP is either a register or a signed nine bit integer.  */
-
-int
-reg_or_int9_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_INT)
-    return CONST_OK_FOR_O (INTVAL (op));
-
-  return register_operand (op, mode);
-}
-
-/* Return true if OP is either a register or a const integer.  */
-
-int
-reg_or_const_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_INT)
-    return TRUE;
-
-  return register_operand (op, mode);
-}
-
-/* Return true if OP is a valid call operand.  */
-
-int
-call_address_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  /* Only registers are valid call operands if TARGET_LONG_CALLS.  */
-  if (TARGET_LONG_CALLS)
-    return GET_CODE (op) == REG;
-  return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);
-}
-
-int
-special_symbolref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  if (GET_CODE (op) == CONST
-      && GET_CODE (XEXP (op, 0)) == PLUS
-      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
-      && CONST_OK_FOR_K (INTVAL (XEXP (XEXP (op, 0), 1))))
-    op = XEXP (XEXP (op, 0), 0);
-
-  if (GET_CODE (op) == SYMBOL_REF)
-    return (SYMBOL_REF_FLAGS (op)
-           & (SYMBOL_FLAG_ZDA | SYMBOL_FLAG_TDA | SYMBOL_FLAG_SDA)) != 0;
-
-  return FALSE;
-}
-
-int
-movsi_source_operand (rtx op, enum machine_mode mode)
-{
-  /* Some constants, as well as symbolic operands
-     must be done with HIGH & LO_SUM patterns.  */
-  if (CONSTANT_P (op)
-      && GET_CODE (op) != HIGH
-      && !(GET_CODE (op) == CONST_INT
-           && (CONST_OK_FOR_J (INTVAL (op))
-               || CONST_OK_FOR_K (INTVAL (op))
-               || CONST_OK_FOR_L (INTVAL (op)))))
-    return special_symbolref_operand (op, mode);
-  else
-    return general_operand (op, mode);
-}
-
-int
-power_of_two_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  if (GET_CODE (op) != CONST_INT)
-    return 0;
-
-  if (exact_log2 (INTVAL (op)) == -1)
-    return 0;
-  return 1;
-}
-
-int
-not_power_of_two_operand (rtx op, enum machine_mode mode)
-{
-  unsigned int mask;
-
-  if (mode == QImode)
-    mask = 0xff;
-  else if (mode == HImode)
-    mask = 0xffff;
-  else if (mode == SImode)
-    mask = 0xffffffff;
-  else
-    return 0;
-
-  if (GET_CODE (op) != CONST_INT)
-    return 0;
-
-  if (exact_log2 (~INTVAL (op) & mask) == -1)
-    return 0;
-  return 1;
-}
-
 \f
 /* Substitute memory references involving a pointer, to use the ep pointer,
    taking care to save and preserve the ep.  */
@@ -1221,7 +1099,7 @@ substitute_ep_register (rtx first_insn,
 
   if (!*p_r1)
     {
-      regs_ever_live[1] = 1;
+      df_set_regs_ever_live (1, true);
       *p_r1 = gen_rtx_REG (Pmode, 1);
       *p_ep = gen_rtx_REG (Pmode, 30);
     }
@@ -1547,12 +1425,15 @@ compute_register_save_size (long * p_reg_saved)
   int size = 0;
   int i;
   int interrupt_handler = v850_interrupt_function_p (current_function_decl);
-  int call_p = regs_ever_live [LINK_POINTER_REGNUM];
+  int call_p = df_regs_ever_live_p (LINK_POINTER_REGNUM);
   long reg_saved = 0;
 
   /* Count the return pointer if we need to save it.  */
-  if (current_function_profile && !call_p)
-    regs_ever_live [LINK_POINTER_REGNUM] = call_p = 1;
+  if (crtl->profile && !call_p)
+    {
+      df_set_regs_ever_live (LINK_POINTER_REGNUM, true);
+      call_p = 1;
+    }
  
   /* Count space for the register saves.  */
   if (interrupt_handler)
@@ -1561,7 +1442,7 @@ compute_register_save_size (long * p_reg_saved)
        switch (i)
          {
          default:
-           if (regs_ever_live[i] || call_p)
+           if (df_regs_ever_live_p (i) || call_p)
              {
                size += 4;
                reg_saved |= 1L << i;
@@ -1589,7 +1470,7 @@ compute_register_save_size (long * p_reg_saved)
     {
       /* Find the first register that needs to be saved.  */
       for (i = 0; i <= 31; i++)
-       if (regs_ever_live[i] && ((! call_used_regs[i])
+       if (df_regs_ever_live_p (i) && ((! call_used_regs[i])
                                  || i == LINK_POINTER_REGNUM))
          break;
 
@@ -1621,7 +1502,7 @@ compute_register_save_size (long * p_reg_saved)
              reg_saved |= 1L << i;
            }
 
-         if (regs_ever_live [LINK_POINTER_REGNUM])
+         if (df_regs_ever_live_p (LINK_POINTER_REGNUM))
            {
              size += 4;
              reg_saved |= 1L << LINK_POINTER_REGNUM;
@@ -1630,7 +1511,7 @@ compute_register_save_size (long * p_reg_saved)
       else
        {
          for (; i <= 31; i++)
-           if (regs_ever_live[i] && ((! call_used_regs[i])
+           if (df_regs_ever_live_p (i) && ((! call_used_regs[i])
                                      || i == LINK_POINTER_REGNUM))
              {
                size += 4;
@@ -1650,7 +1531,7 @@ compute_frame_size (int size, long * p_reg_saved)
 {
   return (size
          + compute_register_save_size (p_reg_saved)
-         + current_function_outgoing_args_size);
+         + crtl->outgoing_args_size);
 }
 
 \f
@@ -1687,7 +1568,7 @@ expand_prologue (void)
     }
 
   /* Save arg registers to the stack if necessary.  */
-  else if (current_function_args_info.anonymous_args)
+  else if (crtl->args.info.anonymous_args)
     {
       if (TARGET_PROLOG_FUNCTION && TARGET_V850E && !TARGET_DISABLE_CALLT)
        emit_insn (gen_save_r6_r9_v850e ());
@@ -1829,7 +1710,7 @@ Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
          if (init_stack_alloc)
            emit_insn (gen_addsi3 (stack_pointer_rtx,
                                   stack_pointer_rtx,
-                                  GEN_INT (-init_stack_alloc)));
+                                  GEN_INT (- (signed) init_stack_alloc)));
          
          /* Save the return pointer first.  */
          if (num_save > 0 && REGNO (save_regs[num_save-1]) == LINK_POINTER_REGNUM)
@@ -1883,7 +1764,7 @@ expand_epilogue (void)
   int offset;
   unsigned int size = get_frame_size ();
   long reg_saved = 0;
-  unsigned int actual_fsize = compute_frame_size (size, &reg_saved);
+  int actual_fsize = compute_frame_size (size, &reg_saved);
   unsigned int init_stack_free = 0;
   rtx restore_regs[32];
   rtx restore_all;
@@ -1927,7 +1808,7 @@ expand_epilogue (void)
   
   if (TARGET_PROLOG_FUNCTION
       && num_restore > 0
-      && actual_fsize >= default_stack
+      && actual_fsize >= (signed) default_stack
       && !interrupt_handler)
     {
       int alloc_stack = (4 * num_restore) + default_stack;
@@ -2008,7 +1889,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
        }
     }
 
-  /* If no epilog save function is available, restore the registers the
+  /* If no epilogue save function is available, restore the registers the
      old fashioned way (one by one).  */
   if (!restore_all)
     {
@@ -2016,10 +1897,10 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
       if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize))
        init_stack_free = 4 * num_restore;
       else
-       init_stack_free = actual_fsize;
+       init_stack_free = (signed) actual_fsize;
 
       /* Deallocate the rest of the stack if it is > 32K.  */
-      if (actual_fsize > init_stack_free)
+      if ((unsigned int) actual_fsize > init_stack_free)
        {
          int diff;
 
@@ -2071,7 +1952,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
                                           plus_constant (stack_pointer_rtx,
                                                          offset)));
 
-             emit_insn (gen_rtx_USE (VOIDmode, restore_regs[i]));
+             emit_use (restore_regs[i]);
              offset -= 4;
            }
 
@@ -2093,7 +1974,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
       else if (actual_fsize)
        emit_jump_insn (gen_return_internal ());
       else
-       emit_jump_insn (gen_return ());
+       emit_jump_insn (gen_return_simple ());
     }
 
   v850_interrupt_cache_p = FALSE;
@@ -2185,17 +2066,6 @@ v850_set_data_area (tree decl, v850_data_area data_area)
     (name, NULL, DECL_ATTRIBUTES (decl));
 }
 \f
-const struct attribute_spec v850_attribute_table[] =
-{
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-  { "interrupt_handler", 0, 0, true,  false, false, v850_handle_interrupt_attribute },
-  { "interrupt",         0, 0, true,  false, false, v850_handle_interrupt_attribute },
-  { "sda",               0, 0, true,  false, false, v850_handle_data_area_attribute },
-  { "tda",               0, 0, true,  false, false, v850_handle_data_area_attribute },
-  { "zda",               0, 0, true,  false, false, v850_handle_data_area_attribute },
-  { NULL,                0, 0, false, false, false, NULL }
-};
-
 /* Handle an "interrupt" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
@@ -2207,8 +2077,8 @@ v850_handle_interrupt_attribute (tree * node,
 {
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
-      warning ("%qs attribute only applies to functions",
-              IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute only applies to functions",
+              name);
       *no_add_attrs = true;
     }
 
@@ -2236,15 +2106,16 @@ v850_handle_data_area_attribute (tree* node,
   else if (is_attribute_p ("zda", name))
     data_area = DATA_AREA_ZDA;
   else
-    abort ();
+    gcc_unreachable ();
   
   switch (TREE_CODE (decl))
     {
     case VAR_DECL:
       if (current_function_decl != NULL_TREE)
        {
-          error ("%Jdata area attributes cannot be specified for "
-                 "local variables", decl, decl);
+          error_at (DECL_SOURCE_LOCATION (decl),
+                   "data area attributes cannot be specified for "
+                   "local variables");
          *no_add_attrs = true;
        }
 
@@ -2254,8 +2125,8 @@ v850_handle_data_area_attribute (tree* node,
       area = v850_get_data_area (decl);
       if (area != DATA_AREA_NORMAL && data_area != area)
        {
-         error ("%Jdata area of '%D' conflicts with previous declaration",
-                 decl, decl);
+         error ("data area of %q+D conflicts with previous declaration",
+                 decl);
          *no_add_attrs = true;
        }
       break;
@@ -2351,7 +2222,7 @@ v850_encode_data_area (tree decl, rtx symbol)
     case DATA_AREA_ZDA: flags |= SYMBOL_FLAG_ZDA; break;
     case DATA_AREA_TDA: flags |= SYMBOL_FLAG_TDA; break;
     case DATA_AREA_SDA: flags |= SYMBOL_FLAG_SDA; break;
-    default: abort ();
+    default: gcc_unreachable ();
     }
   SYMBOL_REF_FLAGS (symbol) = flags;
 }
@@ -2366,75 +2237,6 @@ v850_encode_section_info (tree decl, rtx rtl, int first)
     v850_encode_data_area (decl, XEXP (rtl, 0));
 }
 
-/* Return true if the given RTX is a register which can be restored
-   by a function epilogue.  */
-int
-register_is_ok_for_epilogue (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  /* The save/restore routines can only cope with registers 20 - 31.  */
-  return ((GET_CODE (op) == REG)
-          && (((REGNO (op) >= 20) && REGNO (op) <= 31)));
-}
-
-/* Return nonzero if the given RTX is suitable for collapsing into
-   jump to a function epilogue.  */
-int
-pattern_is_ok_for_epilogue (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  int count = XVECLEN (op, 0);
-  int i;
-  
-  /* If there are no registers to restore then the function epilogue
-     is not suitable.  */
-  if (count <= 2)
-    return 0;
-
-  /* The pattern matching has already established that we are performing a
-     function epilogue and that we are popping at least one register.  We must
-     now check the remaining entries in the vector to make sure that they are
-     also register pops.  There is no good reason why there should ever be
-     anything else in this vector, but being paranoid always helps...
-
-     The test below performs the C equivalent of this machine description
-     pattern match:
-
-        (set (match_operand:SI n "register_is_ok_for_epilogue" "r")
-         (mem:SI (plus:SI (reg:SI 3) (match_operand:SI n "immediate_operand" "i"))))
-     */
-
-  for (i = 3; i < count; i++)
-    {
-      rtx vector_element = XVECEXP (op, 0, i);
-      rtx dest;
-      rtx src;
-      rtx plus;
-      
-      if (GET_CODE (vector_element) != SET)
-       return 0;
-      
-      dest = SET_DEST (vector_element);
-      src = SET_SRC (vector_element);
-
-      if (GET_CODE (dest) != REG
-         || GET_MODE (dest) != SImode
-         || ! register_is_ok_for_epilogue (dest, SImode)
-         || GET_CODE (src) != MEM
-         || GET_MODE (src) != SImode)
-       return 0;
-
-      plus = XEXP (src, 0);
-
-      if (GET_CODE (plus) != PLUS
-         || GET_CODE (XEXP (plus, 0)) != REG
-         || GET_MODE (XEXP (plus, 0)) != SImode
-         || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM
-         || GET_CODE (XEXP (plus, 1)) != CONST_INT)
-       return 0;
-    }
-
-  return 1;
-}
-
 /* Construct a JR instruction to a routine that will perform the equivalent of
    the RTL passed in as an argument.  This RTL is a function epilogue that
    pops registers off the stack and possibly releases some extra stack space
@@ -2453,18 +2255,15 @@ construct_restore_jr (rtx op)
   
   if (count <= 2)
     {
-      error ("bogus JR construction: %d\n", count);
+      error ("bogus JR construction: %d", count);
       return NULL;
     }
 
   /* Work out how many bytes to pop off the stack before retrieving
      registers.  */
-  if (GET_CODE (XVECEXP (op, 0, 1)) != SET)
-    abort ();
-  if (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) != PLUS)
-    abort ();
-  if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) != CONST_INT)
-    abort ();
+  gcc_assert (GET_CODE (XVECEXP (op, 0, 1)) == SET);
+  gcc_assert (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) == PLUS);
+  gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) == CONST_INT);
     
   stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1));
 
@@ -2484,12 +2283,10 @@ construct_restore_jr (rtx op)
     {
       rtx vector_element = XVECEXP (op, 0, i);
       
-      if (GET_CODE (vector_element) != SET)
-       abort ();
-      if (GET_CODE (SET_DEST (vector_element)) != REG)
-       abort ();
-      if (! register_is_ok_for_epilogue (SET_DEST (vector_element), SImode))
-       abort ();
+      gcc_assert (GET_CODE (vector_element) == SET);
+      gcc_assert (GET_CODE (SET_DEST (vector_element)) == REG);
+      gcc_assert (register_is_ok_for_epilogue (SET_DEST (vector_element),
+                                              SImode));
       
       mask |= 1 << REGNO (SET_DEST (vector_element));
     }
@@ -2501,24 +2298,19 @@ construct_restore_jr (rtx op)
        break;
     }
 
-  if (first >= 32)
-    abort ();
+  gcc_assert (first < 32);
 
   /* Discover the last register to pop.  */
   if (mask & (1 << LINK_POINTER_REGNUM))
     {
-      if (stack_bytes != 16)
-       abort ();
+      gcc_assert (stack_bytes == 16);
       
       last = LINK_POINTER_REGNUM;
     }
   else
     {
-      if (stack_bytes != 0)
-       abort ();
-      
-      if ((mask & (1 << 29)) == 0)
-       abort ();
+      gcc_assert (!stack_bytes);
+      gcc_assert (mask & (1 << 29));
       
       last = 29;
     }
@@ -2552,89 +2344,6 @@ construct_restore_jr (rtx op)
 }
 
 
-/* Return nonzero if the given RTX is suitable for collapsing into
-   a jump to a function prologue.  */
-int
-pattern_is_ok_for_prologue (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  int count = XVECLEN (op, 0);
-  int i; 
-  rtx vector_element;
-  /* If there are no registers to save then the function prologue
-     is not suitable.  */
-  if (count <= 2)
-    return 0;
-
-  /* The pattern matching has already established that we are adjusting the
-     stack and pushing at least one register.  We must now check that the
-     remaining entries in the vector to make sure that they are also register
-     pushes, except for the last entry which should be a CLOBBER of r10.
-
-     The test below performs the C equivalent of this machine description
-     pattern match:
-
-     (set (mem:SI (plus:SI (reg:SI 3)
-      (match_operand:SI 2 "immediate_operand" "i")))
-      (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))
-
-     */
-
-  for (i = 2; i < count - (TARGET_LONG_CALLS ? 2: 1); i++)
-    {
-      rtx dest;
-      rtx src;
-      rtx plus;
-      
-      vector_element = XVECEXP (op, 0, i);
-      
-      if (GET_CODE (vector_element) != SET)
-       return 0;
-      
-      dest = SET_DEST (vector_element);
-      src = SET_SRC (vector_element);
-
-      if (GET_CODE (dest) != MEM
-         || GET_MODE (dest) != SImode
-         || GET_CODE (src) != REG
-         || GET_MODE (src) != SImode
-         || ! register_is_ok_for_epilogue (src, SImode))
-       return 0;
-
-      plus = XEXP (dest, 0);
-
-      if ( GET_CODE (plus) != PLUS
-         || GET_CODE (XEXP (plus, 0)) != REG
-         || GET_MODE (XEXP (plus, 0)) != SImode
-         || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM
-         || GET_CODE (XEXP (plus, 1)) != CONST_INT)
-       return 0;
-
-      /* If the register is being pushed somewhere other than the stack
-        space just acquired by the first operand then abandon this quest.
-        Note: the test is <= because both values are negative.  */
-      if (INTVAL (XEXP (plus, 1))
-         <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)))
-       {
-         return 0;
-       }
-    }
-
-  /* Make sure that the last entries in the vector are clobbers.  */
-  for (; i < count; i++)
-    {
-      vector_element = XVECEXP (op, 0, i);
-
-      if (GET_CODE (vector_element) != CLOBBER
-         || GET_CODE (XEXP (vector_element, 0)) != REG
-         || !(REGNO (XEXP (vector_element, 0)) == 10
-              || (TARGET_LONG_CALLS ? (REGNO (XEXP (vector_element, 0)) == 11) : 0 )))
-       return 0;
-    }
-
-  return 1;
-}
-
 /* Construct a JARL instruction to a routine that will perform the equivalent
    of the RTL passed as a parameter.  This RTL is a function prologue that
    saves some of the registers r20 - r31 onto the stack, and possibly acquires
@@ -2658,14 +2367,10 @@ construct_save_jarl (rtx op)
     }
 
   /* Paranoia.  */
-  if (GET_CODE (XVECEXP (op, 0, 0)) != SET)
-    abort ();
-  if (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != PLUS)
-    abort ();
-  if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) != REG)
-    abort ();
-  if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) != CONST_INT)
-    abort ();
+  gcc_assert (GET_CODE (XVECEXP (op, 0, 0)) == SET);
+  gcc_assert (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) == PLUS);
+  gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) == REG);
+  gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) == CONST_INT);
     
   /* Work out how many bytes to push onto the stack after storing the
      registers.  */
@@ -2687,12 +2392,10 @@ construct_save_jarl (rtx op)
     {
       rtx vector_element = XVECEXP (op, 0, i);
       
-      if (GET_CODE (vector_element) != SET)
-       abort ();
-      if (GET_CODE (SET_SRC (vector_element)) != REG)
-       abort ();
-      if (! register_is_ok_for_epilogue (SET_SRC (vector_element), SImode))
-       abort ();
+      gcc_assert (GET_CODE (vector_element) == SET);
+      gcc_assert (GET_CODE (SET_SRC (vector_element)) == REG);
+      gcc_assert (register_is_ok_for_epilogue (SET_SRC (vector_element),
+                                              SImode));
       
       mask |= 1 << REGNO (SET_SRC (vector_element));
     }
@@ -2704,23 +2407,19 @@ construct_save_jarl (rtx op)
        break;
     }
 
-  if (first >= 32)
-    abort ();
+  gcc_assert (first < 32);
 
   /* Discover the last register to push.  */
   if (mask & (1 << LINK_POINTER_REGNUM))
     {
-      if (stack_bytes != -16)
-       abort ();
+      gcc_assert (stack_bytes == -16);
       
       last = LINK_POINTER_REGNUM;
     }
   else
     {
-      if (stack_bytes != 0)
-       abort ();
-      if ((mask & (1 << 29)) == 0)
-       abort ();
+      gcc_assert (!stack_bytes);
+      gcc_assert (mask & (1 << 29));
       
       last = 29;
     }
@@ -2763,24 +2462,24 @@ void
 v850_output_aligned_bss (FILE * file,
                          tree decl,
                          const char * name,
-                         int size,
+                         unsigned HOST_WIDE_INT size,
                          int align)
 {
   switch (v850_get_data_area (decl))
     {
     case DATA_AREA_ZDA:
-      zbss_section ();
+      switch_to_section (zbss_section);
       break;
 
     case DATA_AREA_SDA:
-      sbss_section ();
+      switch_to_section (sbss_section);
       break;
 
     case DATA_AREA_TDA:
-      tdata_section ();
+      switch_to_section (tdata_section);
       
     default:
-      bss_section ();
+      switch_to_section (bss_section);
       break;
     }
   
@@ -2899,7 +2598,7 @@ v850_insert_attributes (tree decl, tree * attr_ptr ATTRIBUTE_UNUSED )
          switch (v850_get_data_area (decl))
            {
            default:
-             abort ();
+             gcc_unreachable ();
              
            case DATA_AREA_SDA:
              kind = ((TREE_READONLY (decl))
@@ -2946,67 +2645,6 @@ v850_insert_attributes (tree decl, tree * attr_ptr ATTRIBUTE_UNUSED )
     }
 }
 
-/* Return nonzero if the given RTX is suitable
-   for collapsing into a DISPOSE instruction.  */
-
-int
-pattern_is_ok_for_dispose (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  int count = XVECLEN (op, 0);
-  int i;
-  
-  /* If there are no registers to restore then
-     the dispose instruction is not suitable.  */
-  if (count <= 2)
-    return 0;
-
-  /* The pattern matching has already established that we are performing a
-     function epilogue and that we are popping at least one register.  We must
-     now check the remaining entries in the vector to make sure that they are
-     also register pops.  There is no good reason why there should ever be
-     anything else in this vector, but being paranoid always helps...
-
-     The test below performs the C equivalent of this machine description
-     pattern match:
-
-        (set (match_operand:SI n "register_is_ok_for_epilogue" "r")
-         (mem:SI (plus:SI (reg:SI 3)
-           (match_operand:SI n "immediate_operand" "i"))))
-     */
-
-  for (i = 3; i < count; i++)
-    {
-      rtx vector_element = XVECEXP (op, 0, i);
-      rtx dest;
-      rtx src;
-      rtx plus;
-      
-      if (GET_CODE (vector_element) != SET)
-       return 0;
-      
-      dest = SET_DEST (vector_element);
-      src  = SET_SRC (vector_element);
-
-      if (   GET_CODE (dest) != REG
-         || GET_MODE (dest) != SImode
-         || ! register_is_ok_for_epilogue (dest, SImode)
-         || GET_CODE (src) != MEM
-         || GET_MODE (src) != SImode)
-       return 0;
-
-      plus = XEXP (src, 0);
-
-      if (   GET_CODE (plus) != PLUS
-         || GET_CODE (XEXP (plus, 0)) != REG
-         || GET_MODE (XEXP (plus, 0)) != SImode
-         || REGNO    (XEXP (plus, 0)) != STACK_POINTER_REGNUM
-         || GET_CODE (XEXP (plus, 1)) != CONST_INT)
-       return 0;
-    }
-
-  return 1;
-}
-
 /* Construct a DISPOSE instruction that is the equivalent of
    the given RTX.  We have already verified that this should
    be possible.  */
@@ -3023,18 +2661,15 @@ construct_dispose_instruction (rtx op)
   
   if (count <= 2)
     {
-      error ("Bogus DISPOSE construction: %d\n", count);
+      error ("bogus DISPOSE construction: %d", count);
       return NULL;
     }
 
   /* Work out how many bytes to pop off the
      stack before retrieving registers.  */
-  if (GET_CODE (XVECEXP (op, 0, 1)) != SET)
-    abort ();
-  if (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) != PLUS)
-    abort ();
-  if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) != CONST_INT)
-    abort ();
+  gcc_assert (GET_CODE (XVECEXP (op, 0, 1)) == SET);
+  gcc_assert (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) == PLUS);
+  gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) == CONST_INT);
     
   stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1));
 
@@ -3045,7 +2680,7 @@ construct_dispose_instruction (rtx op)
      will fit into the DISPOSE instruction.  */
   if (stack_bytes > 128)
     {
-      error ("Too much stack space to dispose of: %d", stack_bytes);
+      error ("too much stack space to dispose of: %d", stack_bytes);
       return NULL;
     }
 
@@ -3056,12 +2691,10 @@ construct_dispose_instruction (rtx op)
     {
       rtx vector_element = XVECEXP (op, 0, i);
       
-      if (GET_CODE (vector_element) != SET)
-       abort ();
-      if (GET_CODE (SET_DEST (vector_element)) != REG)
-       abort ();
-      if (! register_is_ok_for_epilogue (SET_DEST (vector_element), SImode))
-       abort ();
+      gcc_assert (GET_CODE (vector_element) == SET);
+      gcc_assert (GET_CODE (SET_DEST (vector_element)) == REG);
+      gcc_assert (register_is_ok_for_epilogue (SET_DEST (vector_element),
+                                              SImode));
 
       if (REGNO (SET_DEST (vector_element)) == 2)
        use_callt = 1;
@@ -3133,75 +2766,6 @@ construct_dispose_instruction (rtx op)
   return buff;
 }
 
-/* Return nonzero if the given RTX is suitable
-   for collapsing into a PREPARE instruction.  */
-
-int
-pattern_is_ok_for_prepare (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  int count = XVECLEN (op, 0);
-  int i;
-  
-  /* If there are no registers to restore then the prepare instruction
-     is not suitable.  */
-  if (count <= 1)
-    return 0;
-
-  /* The pattern matching has already established that we are adjusting the
-     stack and pushing at least one register.  We must now check that the
-     remaining entries in the vector to make sure that they are also register
-     pushes.
-
-     The test below performs the C equivalent of this machine description
-     pattern match:
-
-     (set (mem:SI (plus:SI (reg:SI 3)
-       (match_operand:SI 2 "immediate_operand" "i")))
-         (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))
-
-     */
-
-  for (i = 2; i < count; i++)
-    {
-      rtx vector_element = XVECEXP (op, 0, i);
-      rtx dest;
-      rtx src;
-      rtx plus;
-      
-      if (GET_CODE (vector_element) != SET)
-       return 0;
-      
-      dest = SET_DEST (vector_element);
-      src  = SET_SRC (vector_element);
-
-      if (   GET_CODE (dest) != MEM
-         || GET_MODE (dest) != SImode
-         || GET_CODE (src) != REG
-         || GET_MODE (src) != SImode
-         || ! register_is_ok_for_epilogue (src, SImode)
-            )
-       return 0;
-
-      plus = XEXP (dest, 0);
-
-      if (   GET_CODE (plus) != PLUS
-         || GET_CODE (XEXP (plus, 0)) != REG
-         || GET_MODE (XEXP (plus, 0)) != SImode
-         || REGNO    (XEXP (plus, 0)) != STACK_POINTER_REGNUM
-         || GET_CODE (XEXP (plus, 1)) != CONST_INT)
-       return 0;
-
-      /* If the register is being pushed somewhere other than the stack
-        space just acquired by the first operand then abandon this quest.
-        Note: the test is <= because both values are negative.  */
-      if (INTVAL (XEXP (plus, 1))
-         <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)))
-       return 0;
-    }
-
-  return 1;
-}
-
 /* Construct a PREPARE instruction that is the equivalent of
    the given RTL.  We have already verified that this should
    be possible.  */
@@ -3218,18 +2782,15 @@ construct_prepare_instruction (rtx op)
   
   if (count <= 1)
     {
-      error ("Bogus PREPEARE construction: %d\n", count);
+      error ("bogus PREPEARE construction: %d", count);
       return NULL;
     }
 
   /* Work out how many bytes to push onto
      the stack after storing the registers.  */
-  if (GET_CODE (XVECEXP (op, 0, 0)) != SET)
-    abort ();
-  if (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != PLUS)
-    abort ();
-  if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) != CONST_INT)
-    abort ();
+  gcc_assert (GET_CODE (XVECEXP (op, 0, 0)) == SET);
+  gcc_assert (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) == PLUS);
+  gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) == CONST_INT);
     
   stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1));
 
@@ -3240,7 +2801,7 @@ construct_prepare_instruction (rtx op)
      will fit into the DISPOSE instruction.  */
   if (stack_bytes < -128)
     {
-      error ("Too much stack space to prepare: %d", stack_bytes);
+      error ("too much stack space to prepare: %d", stack_bytes);
       return NULL;
     }
 
@@ -3250,12 +2811,10 @@ construct_prepare_instruction (rtx op)
     {
       rtx vector_element = XVECEXP (op, 0, i);
       
-      if (GET_CODE (vector_element) != SET)
-       abort ();
-      if (GET_CODE (SET_SRC (vector_element)) != REG)
-       abort ();
-      if (! register_is_ok_for_epilogue (SET_SRC (vector_element), SImode))
-       abort ();
+      gcc_assert (GET_CODE (vector_element) == SET);
+      gcc_assert (GET_CODE (SET_SRC (vector_element)) == REG);
+      gcc_assert (register_is_ok_for_epilogue (SET_SRC (vector_element),
+                                              SImode));
 
       if (REGNO (SET_SRC (vector_element)) == 2)
        use_callt = 1;
@@ -3338,7 +2897,34 @@ v850_return_addr (int count)
   return get_hard_reg_initial_val (Pmode, LINK_POINTER_REGNUM);
 }
 \f
+/* Implement TARGET_ASM_INIT_SECTIONS.  */
+
 static void
+v850_asm_init_sections (void)
+{
+  rosdata_section
+    = get_unnamed_section (0, output_section_asm_op,
+                          "\t.section .rosdata,\"a\"");
+
+  rozdata_section
+    = get_unnamed_section (0, output_section_asm_op,
+                          "\t.section .rozdata,\"a\"");
+
+  tdata_section
+    = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
+                          "\t.section .tdata,\"aw\"");
+
+  zdata_section
+    = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
+                          "\t.section .zdata,\"aw\"");
+
+  zbss_section
+    = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
+                          output_section_asm_op,
+                          "\t.section .zbss,\"aw\"");
+}
+
+static section *
 v850_select_section (tree exp,
                      int reloc ATTRIBUTE_UNUSED,
                      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
@@ -3358,43 +2944,40 @@ v850_select_section (tree exp,
       switch (v850_get_data_area (exp))
         {
         case DATA_AREA_ZDA:
-         if (is_const)
-           rozdata_section ();
-         else
-           zdata_section ();
-         break;
+         return is_const ? rozdata_section : zdata_section;
 
         case DATA_AREA_TDA:
-         tdata_section ();
-         break;
+         return tdata_section;
 
         case DATA_AREA_SDA:
-         if (is_const)
-           rosdata_section ();
-         else
-           sdata_section ();
-         break;
+         return is_const ? rosdata_section : sdata_section;
 
         default:
-          if (is_const)
-           readonly_data_section ();
-         else
-           data_section ();
-         break;
+         return is_const ? readonly_data_section : data_section;
         }
     }
-  else
-    readonly_data_section ();
+  return readonly_data_section;
 }
 \f
 /* Worker function for TARGET_RETURN_IN_MEMORY.  */
 
 static bool
-v850_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+v850_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
 {
   /* Return values > 8 bytes in length in memory.  */
   return int_size_in_bytes (type) > 8 || TYPE_MODE (type) == BLKmode;
 }
+
+/* Worker function for TARGET_FUNCTION_VALUE.  */
+
+rtx
+v850_function_value (const_tree valtype, 
+                    const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
+                    bool outgoing ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (TYPE_MODE (valtype), 10);
+}
+
 \f
 /* Worker function for TARGET_SETUP_INCOMING_VARARGS.  */
 
@@ -3407,3 +2990,44 @@ v850_setup_incoming_varargs (CUMULATIVE_ARGS *ca,
 {
   ca->anonymous_args = (!TARGET_GHS ? 1 : 0);
 }
+
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+static bool
+v850_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
+}
+
+\f
+/* Worker function for TARGET_ASM_TRAMPOLINE_TEMPLATE.  */
+
+static void
+v850_asm_trampoline_template (FILE *f)
+{
+  fprintf (f, "\tjarl .+4,r12\n");
+  fprintf (f, "\tld.w 12[r12],r20\n");
+  fprintf (f, "\tld.w 16[r12],r12\n");
+  fprintf (f, "\tjmp [r12]\n");
+  fprintf (f, "\tnop\n");
+  fprintf (f, "\t.long 0\n");
+  fprintf (f, "\t.long 0\n");
+}
+
+/* Worker function for TARGET_TRAMPOLINE_INIT.  */
+
+static void
+v850_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
+{
+  rtx mem, fnaddr = XEXP (DECL_RTL (fndecl), 0);
+
+  emit_block_move (m_tramp, assemble_trampoline_template (),
+                  GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
+
+  mem = adjust_address (m_tramp, SImode, 16);
+  emit_move_insn (mem, chain_value);
+  mem = adjust_address (m_tramp, SImode, 20);
+  emit_move_insn (mem, fnaddr);
+}
+\f
+#include "gt-v850.h"