OSDN Git Service

Latest updates from FSF 4.7 branch
[pf3gnuchains/gcc-fork.git] / gcc / config / v850 / v850.c
index 1035347..89c01df 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, 2010, 2011 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"
@@ -28,7 +27,6 @@
 #include "rtl.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 "expr.h"
 #include "function.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "ggc.h"
 #include "integrate.h"
 #include "tm_p.h"
 #include "target.h"
 #include "target-def.h"
+#include "df.h"
+#include "opts.h"
 
 #ifndef streq
 #define streq(a,b) (strcmp (a, b) == 0)
 #endif
 
-/* Function prototypes for stupid compilers:  */
-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 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_encode_data_area    (tree, rtx);
-static void v850_encode_section_info (tree, rtx, int);
-static bool v850_return_in_memory    (tree, tree);
-static void v850_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
-                                        tree, int *, int);
-
-/* 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 },
-};
+static void v850_print_operand_address (FILE *, rtx);
 
 /* Names of the various data areas used on the v850.  */
 tree GHS_default_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
@@ -89,107 +62,82 @@ data_area_stack_element * data_area_stack = NULL;
    function is an interrupt handler.  */
 static int v850_interrupt_cache_p = FALSE;
 
+rtx v850_compare_op0, v850_compare_op1;
+
 /* Whether current function is an interrupt handler.  */
 static int v850_interrupt_p = FALSE;
-\f
-/* Initialize the GCC target structure.  */
-#undef TARGET_ASM_ALIGNED_HI_OP
-#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
-
-#undef TARGET_ATTRIBUTE_TABLE
-#define TARGET_ATTRIBUTE_TABLE v850_attribute_table
-
-#undef TARGET_INSERT_ATTRIBUTES
-#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes
 
-#undef  TARGET_ASM_SELECT_SECTION
-#define TARGET_ASM_SELECT_SECTION  v850_select_section
+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
+/* We use this to wrap all emitted insns in the prologue.  */
+static rtx
+F (rtx x)
+{
+  RTX_FRAME_RELATED_P (x) = 1;
+  return x;
+}
 
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO v850_encode_section_info
+/* Mark all the subexpressions of the PARALLEL rtx PAR as
+   frame-related.  Return PAR.
 
-#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
-#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
+   dwarf2out.c:dwarf2out_frame_debug_expr ignores sub-expressions of a
+   PARALLEL rtx other than the first if they do not have the
+   FRAME_RELATED flag set on them.  */
+static rtx
+v850_all_frame_related (rtx par)
+{
+  int len = XVECLEN (par, 0);
+  int i;
 
-#undef TARGET_RTX_COSTS
-#define TARGET_RTX_COSTS v850_rtx_costs
-#undef TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST hook_int_rtx_0
+  for (i = 0; i < len; i++)
+    F (XVECEXP (par, 0, i));
 
-#undef TARGET_MACHINE_DEPENDENT_REORG
-#define TARGET_MACHINE_DEPENDENT_REORG v850_reorg
+  return par;
+}
 
-#undef TARGET_PROMOTE_PROTOTYPES
-#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+/* Handle the TARGET_PASS_BY_REFERENCE target hook.
+   Specify whether to pass the argument by reference.  */
 
-#undef TARGET_STRUCT_VALUE_RTX
-#define TARGET_STRUCT_VALUE_RTX hook_rtx_tree_int_null
-#undef TARGET_RETURN_IN_MEMORY
-#define TARGET_RETURN_IN_MEMORY v850_return_in_memory
+static bool
+v850_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
+                       enum machine_mode mode, const_tree type,
+                       bool named ATTRIBUTE_UNUSED)
+{
+  unsigned HOST_WIDE_INT size;
 
-#undef TARGET_SETUP_INCOMING_VARARGS
-#define TARGET_SETUP_INCOMING_VARARGS v850_setup_incoming_varargs
+  if (type)
+    size = int_size_in_bytes (type);
+  else
+    size = GET_MODE_SIZE (mode);
 
-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.
+  return size > 8;
+}
 
-   Don't use this macro to turn on various extra optimizations for
-   `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */
+/* Implementing the Varargs Macros.  */
 
-void
-override_options (void)
+static bool
+v850_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED)
 {
-  int i;
-  extern int atoi (const char *);
-
-  /* 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);
-           }
-       }
-    }
-
-  /* Make sure that the US_BIT_SET mask has been correctly initialized.  */
-  if ((target_flags & MASK_US_MASK_SET) == 0)
-    {
-      target_flags |= MASK_US_MASK_SET;
-      target_flags &= ~MASK_US_BIT_SET;
-    }
+  return !TARGET_GHS ? true : false;
 }
 
-\f
-
-/* 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,
-              enum machine_mode mode,
-              tree type,
-              int named)
+static rtx
+v850_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
+                  const_tree type, bool named)
 {
-  rtx result = 0;
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+  rtx result = NULL_RTX;
   int size, align;
 
-  if (TARGET_GHS && !named)
+  if (!named)
     return NULL_RTX;
 
   if (mode == BLKmode)
@@ -197,10 +145,16 @@ function_arg (CUMULATIVE_ARGS * cum,
   else
     size = GET_MODE_SIZE (mode);
 
+  size = (size + UNITS_PER_WORD -1) & ~(UNITS_PER_WORD -1);
+
   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)
+  if (size <= UNITS_PER_WORD && type)
     align = TYPE_ALIGN (type) / BITS_PER_UNIT;
   else
     align = size;
@@ -208,11 +162,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)
     {
@@ -229,22 +183,19 @@ function_arg (CUMULATIVE_ARGS * cum,
       result = gen_rtx_REG (mode, 9);
       break;
     default:
-      result = 0;
+      result = NULL_RTX;
     }
 
   return result;
 }
 
-\f
-/* Return the number of words which must be put into registers
+/* Return the number of bytes which must be put into registers
    for values which are part in registers and part in memory.  */
-
-int
-function_arg_partial_nregs (CUMULATIVE_ARGS * cum,
-                            enum machine_mode mode,
-                            tree type,
-                            int named)
+static int
+v850_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
+                        tree type, bool named)
 {
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int size, align;
 
   if (TARGET_GHS && !named)
@@ -255,12 +206,15 @@ function_arg_partial_nregs (CUMULATIVE_ARGS * cum,
   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;
@@ -272,10 +226,27 @@ function_arg_partial_nregs (CUMULATIVE_ARGS * cum,
       && cum->nbytes + size > 4 * UNITS_PER_WORD)
     return 0;
 
-  return (4 * UNITS_PER_WORD - cum->nbytes) / UNITS_PER_WORD;
+  return 4 * UNITS_PER_WORD - cum->nbytes;
+}
+
+/* Update the data in CUM to advance over an argument
+   of mode MODE and data type TYPE.
+   (TYPE is null for libcalls where that information may not be available.)  */
+
+static void
+v850_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
+                          const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+
+  cum->nbytes += (((type && int_size_in_bytes (type) > 8
+                   ? GET_MODE_SIZE (Pmode)
+                   : (mode != BLKmode
+                      ? GET_MODE_SIZE (mode)
+                      : int_size_in_bytes (type))) + UNITS_PER_WORD - 1)
+                 & -UNITS_PER_WORD);
 }
 
-\f
 /* Return the high and low words of a CONST_DOUBLE */
 
 static void
@@ -363,10 +334,13 @@ 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 opno ATTRIBUTE_UNUSED,
+                int * total, bool speed)
 {
+  enum rtx_code code = (enum rtx_code) codearg;
+
   switch (code)
     {
     case CONST_INT:
@@ -381,7 +355,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;
@@ -407,6 +381,11 @@ v850_rtx_costs (rtx x,
        *total = 20;
       return true;
 
+    case ZERO_EXTRACT:
+      if (outer_code == COMPARE)
+       *total = 0;
+      return false;
+
     default:
       return false;
     }
@@ -415,8 +394,8 @@ v850_rtx_costs (rtx x,
 /* Print operand X using operand code CODE to assembly language output file
    FILE.  */
 
-void
-print_operand (FILE * file, rtx x, int code)
+static void
+v850_print_operand (FILE * file, rtx x, int code)
 {
   HOST_WIDE_INT high, low;
 
@@ -473,30 +452,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));
@@ -505,54 +494,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
+       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
-        abort ();
+       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
-        abort ();
+       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
+       gcc_unreachable ();
       break;
     case 'R':          /* 2nd word of a double.  */
       switch (GET_CODE (x))
@@ -562,7 +539,7 @@ print_operand (FILE * file, rtx x, int code)
          break;
        case MEM:
          x = XEXP (adjust_address (x, SImode, 4), 0);
-         print_operand_address (file, x);
+         v850_print_operand_address (file, x);
          if (GET_CODE (x) == CONST_INT)
            fprintf (file, "[r0]");
          break;
@@ -573,7 +550,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);
 
@@ -591,7 +568,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;
@@ -603,19 +580,25 @@ 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 if ((GET_MODE(x) == SImode
+               || GET_MODE(x) == DFmode
+               || GET_MODE(x) == SFmode)
+               && x == CONST0_RTX(GET_MODE(x)))
+      fputs (reg_names[0], file);
       else
-       abort ();
+       {
+         gcc_assert (x == const0_rtx);
+         fputs (reg_names[0], file);
+       }
       break;
     default:
       switch (GET_CODE (x))
        {
        case MEM:
          if (GET_CODE (XEXP (x, 0)) == CONST_INT)
-           output_address (gen_rtx_PLUS (SImode, gen_rtx (REG, SImode, 0),
+           output_address (gen_rtx_PLUS (SImode, gen_rtx_REG (SImode, 0),
                                          XEXP (x, 0)));
          else
            output_address (XEXP (x, 0));
@@ -632,10 +615,10 @@ print_operand (FILE * file, rtx x, int code)
        case CONST:
        case LABEL_REF:
        case CODE_LABEL:
-         print_operand_address (file, x);
+         v850_print_operand_address (file, x);
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
       break;
 
@@ -645,14 +628,14 @@ print_operand (FILE * file, rtx x, int code)
 \f
 /* Output assembly language output for the address ADDR to FILE.  */
 
-void
-print_operand_address (FILE * file, rtx addr)
+static void
+v850_print_operand_address (FILE * file, rtx addr)
 {
   switch (GET_CODE (addr))
     {
     case REG:
       fprintf (file, "0[");
-      print_operand (file, addr, 0);
+      v850_print_operand (file, addr, 0);
       fprintf (file, "]");
       break;
     case LO_SUM:
@@ -660,9 +643,9 @@ print_operand_address (FILE * file, rtx addr)
        {
          /* reg,foo */
          fprintf (file, "lo(");
-         print_operand (file, XEXP (addr, 1), 0);
+         v850_print_operand (file, XEXP (addr, 1), 0);
          fprintf (file, ")[");
-         print_operand (file, XEXP (addr, 0), 0);
+         v850_print_operand (file, XEXP (addr, 0), 0);
          fprintf (file, "]");
        }
       break;
@@ -671,16 +654,16 @@ print_operand_address (FILE * file, rtx addr)
          || GET_CODE (XEXP (addr, 0)) == SUBREG)
        {
          /* reg,foo */
-         print_operand (file, XEXP (addr, 1), 0);
+         v850_print_operand (file, XEXP (addr, 1), 0);
          fprintf (file, "[");
-         print_operand (file, XEXP (addr, 0), 0);
+         v850_print_operand (file, XEXP (addr, 0), 0);
          fprintf (file, "]");
        }
       else
        {
-         print_operand (file, XEXP (addr, 0), 0);
+         v850_print_operand (file, XEXP (addr, 0), 0);
          fprintf (file, "+");
-         print_operand (file, XEXP (addr, 1), 0);
+         v850_print_operand (file, XEXP (addr, 1), 0);
        }
       break;
     case SYMBOL_REF:
@@ -734,7 +717,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);
@@ -749,19 +732,25 @@ print_operand_address (FILE * file, rtx addr)
     }
 }
 
+static bool
+v850_print_operand_punct_valid_p (unsigned char code)
+{
+  return code == '.';
+}
+
 /* When assemble_integer is used to emit the offsets for a switch
    table it can encounter (TRUNCATE:HI (MINUS:SI (LABEL_REF:SI) (LABEL_REF:SI))).
    output_addr_const will normally barf at this, but it is OK to omit
    the truncate and just emit the difference of the two labels.  The
    .hword directive will automatically handle the truncation for us.
    
-   Returns 1 if rtx was handled, 0 otherwise.  */
+   Returns true if rtx was handled, false otherwise.  */
 
-int
+static bool
 v850_output_addr_const_extra (FILE * file, rtx x)
 {
   if (GET_CODE (x) != TRUNCATE)
-    return 0;
+    return false;
 
   x = XEXP (x, 0);
 
@@ -774,10 +763,10 @@ v850_output_addr_const_extra (FILE * file, rtx x)
       && GET_CODE (XEXP (x, 0)) == LABEL_REF
       && GET_CODE (XEXP (XEXP (x, 0), 0)) == CODE_LABEL
       && INSN_DELETED_P (XEXP (XEXP (x, 0), 0)))
-    return 1;
+    return true;
 
   output_addr_const (file, x);
-  return 1;
+  return true;
 }
 \f
 /* Return appropriate code to load up a 1, 2, or 4 integer/floating
@@ -798,17 +787,17 @@ 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.  */
-           return "movea lo(%1),%.,%0";
+         else if (CONST_OK_FOR_K (value))      /* Signed 16-bit immediate.  */
+           return "movea %1,%.,%0";
 
          else if (CONST_OK_FOR_L (value))      /* Upper 16 bits were set.  */
-           return "movhi hi(%1),%.,%0";
+           return "movhi hi0(%1),%.,%0";
 
          /* A random constant.  */
-         else if (TARGET_V850E)
+         else if (TARGET_V850E || TARGET_V850E2_ALL)
              return "mov %1,%0";
          else
            return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
@@ -820,17 +809,17 @@ 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.  */
-           return "movea lo(%F1),%.,%0";
+         else if (CONST_OK_FOR_K (high))       /* Signed 16-bit immediate.  */
+           return "movea %F1,%.,%0";
 
          else if (CONST_OK_FOR_L (high))       /* Upper 16 bits were set.  */
-           return "movhi hi(%F1),%.,%0";
+           return "movhi hi0(%F1),%.,%0";
 
          /* A random constant.  */
-         else if (TARGET_V850E)
+       else if (TARGET_V850E || TARGET_V850E2_ALL)
              return "mov %F1,%0";
 
          else
@@ -847,7 +836,7 @@ output_move_single (rtx * operands)
               || GET_CODE (src) == SYMBOL_REF
               || GET_CODE (src) == CONST)
        {
-         if (TARGET_V850E)
+         if (TARGET_V850E || TARGET_V850E2_ALL) 
            return "mov hilo(%1),%0";
          else
            return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
@@ -881,85 +870,169 @@ output_move_single (rtx * operands)
   return "";
 }
 
-\f
-/* Return appropriate code to load up an 8 byte integer or
-   floating point value */
+/* Generate comparison code.  */
+int
+v850_float_z_comparison_operator (rtx op, enum machine_mode mode)
+{
+  enum rtx_code code = GET_CODE (op);
 
-const char *
-output_move_double (rtx * operands)
+  if (GET_RTX_CLASS (code) != RTX_COMPARE
+      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
+    return 0;
+
+  if (mode != GET_MODE (op) && mode != VOIDmode)
+    return 0;
+
+  if ((GET_CODE (XEXP (op, 0)) != REG
+       || REGNO (XEXP (op, 0)) != CC_REGNUM)
+      || XEXP (op, 1) != const0_rtx)
+    return 0;
+
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_LTmode)
+    return code == LT;
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_LEmode)
+    return code == LE;
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_EQmode)
+    return code == EQ;
+
+  return 0;
+}
+
+int
+v850_float_nz_comparison_operator (rtx op, enum machine_mode mode)
 {
-  enum machine_mode mode = GET_MODE (operands[0]);
-  rtx dst = operands[0];
-  rtx src = operands[1];
+  enum rtx_code code = GET_CODE (op);
 
-  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";
-    }
+  if (GET_RTX_CLASS (code) != RTX_COMPARE
+      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
+    return 0;
+
+  if (mode != GET_MODE (op) && mode != VOIDmode)
+    return 0;
 
-  /* 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 (XEXP (op, 0)) != REG
+       || REGNO (XEXP (op, 0)) != CC_REGNUM)
+      || XEXP (op, 1) != const0_rtx)
+    return 0;
 
-  if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
-    {
-      HOST_WIDE_INT high_low[2];
-      int i;
-      rtx xop[10];
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_GTmode)
+    return code == GT;
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_GEmode)
+    return code == GE;
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_NEmode)
+    return code == NE;
 
-      if (GET_CODE (src) == CONST_DOUBLE)
-       const_double_split (src, &high_low[1], &high_low[0]);
-      else
+  return 0;
+}
+
+enum machine_mode
+v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED)
+{
+  if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
+    {
+      switch (cond)
        {
-         high_low[0] = INTVAL (src);
-         high_low[1] = (INTVAL (src) >= 0) ? 0 : -1;
+       case LE:
+         return CC_FPU_LEmode;
+       case GE:
+         return CC_FPU_GEmode;
+       case LT:
+         return CC_FPU_LTmode;
+       case GT:
+         return CC_FPU_GTmode;
+       case EQ:
+         return CC_FPU_EQmode;
+       case NE:
+         return CC_FPU_NEmode;
+       default:
+         abort ();
        }
+    }
+  return CCmode;
+}
 
-      for (i = 0; i < 2; i++)
+enum machine_mode
+v850_gen_float_compare (enum rtx_code cond, enum machine_mode mode ATTRIBUTE_UNUSED, rtx op0, rtx op1)
+{
+  if (GET_MODE(op0) == DFmode)
+    {
+      switch (cond)
        {
-         xop[0] = gen_rtx_REG (SImode, REGNO (dst)+i);
-         xop[1] = GEN_INT (high_low[i]);
-         output_asm_insn (output_move_single (xop), xop);
+       case LE:
+         emit_insn (gen_cmpdf_le_insn (op0, op1));
+         break;
+       case GE:
+         emit_insn (gen_cmpdf_ge_insn (op0, op1));
+         break;
+       case LT:
+         emit_insn (gen_cmpdf_lt_insn (op0, op1));
+         break;
+       case GT:
+         emit_insn (gen_cmpdf_gt_insn (op0, op1));
+         break;
+       case EQ:
+         emit_insn (gen_cmpdf_eq_insn (op0, op1));
+         break;
+       case NE:
+         emit_insn (gen_cmpdf_ne_insn (op0, op1));
+         break;
+       default:
+         abort ();
        }
-
-      return "";
     }
-
-  if (GET_CODE (src) == MEM)
+  else if (GET_MODE(v850_compare_op0) == SFmode)
     {
-      int ptrreg = -1;
-      int dreg = REGNO (dst);
-      rtx inside = XEXP (src, 0);
+      switch (cond)
+       {
+       case LE:
+         emit_insn (gen_cmpsf_le_insn(op0, op1));
+         break;
+       case GE:
+         emit_insn (gen_cmpsf_ge_insn(op0, op1));
+         break;
+       case LT:
+         emit_insn (gen_cmpsf_lt_insn(op0, op1));
+         break;
+       case GT:
+         emit_insn (gen_cmpsf_gt_insn(op0, op1));
+         break;
+       case EQ:
+         emit_insn (gen_cmpsf_eq_insn(op0, op1));
+         break;
+       case NE:
+         emit_insn (gen_cmpsf_ne_insn(op0, op1));
+         break;
+       default:
+         abort ();
+       }
+    }
+  else
+    {
+      abort ();
+    }
 
-      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));
+  return v850_select_cc_mode (cond, op0, op1);
+}
 
-      if (dreg == ptrreg)
-       return "ld.w %R1,%R0\n\tld.w %1,%0";
+rtx
+v850_gen_compare (enum rtx_code cond, enum machine_mode mode, rtx op0, rtx op1)
+{
+  if (GET_MODE_CLASS(GET_MODE (op0)) != MODE_FLOAT)
+    {
+      emit_insn (gen_cmpsi_insn (op0, op1));
+      return gen_rtx_fmt_ee (cond, mode, gen_rtx_REG(CCmode, CC_REGNUM), const0_rtx);
     }
+  else
+    {
+      rtx cc_reg;
+      mode = v850_gen_float_compare (cond, mode, op0, op1);
+      cc_reg = gen_rtx_REG (mode, CC_REGNUM);
+      emit_insn (gen_rtx_SET(mode, cc_reg, gen_rtx_REG (mode, FCC_REGNUM)));  
 
-  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";
+      return gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx);
+    }
 }
 
-\f
 /* Return maximum offset supported for a short EP memory reference of mode
    MODE and signedness UNSIGNEDP.  */
 
@@ -973,9 +1046,8 @@ ep_memory_offset (enum machine_mode mode, int unsignedp ATTRIBUTE_UNUSED)
     case QImode:
       if (TARGET_SMALL_SLD)
        max_offset = (1 << 4);
-      else if (TARGET_V850E 
-              && (   (  unsignedp && ! TARGET_US_BIT_SET)
-                  || (! unsignedp &&   TARGET_US_BIT_SET)))
+      else if ((TARGET_V850E || TARGET_V850E2_ALL)
+               && unsignedp)
        max_offset = (1 << 4);
       else
        max_offset = (1 << 7);
@@ -984,9 +1056,8 @@ ep_memory_offset (enum machine_mode mode, int unsignedp ATTRIBUTE_UNUSED)
     case HImode:
       if (TARGET_SMALL_SLD)
        max_offset = (1 << 5);
-      else if (TARGET_V850E
-              && (   (  unsignedp && ! TARGET_US_BIT_SET)
-                  || (! unsignedp &&   TARGET_US_BIT_SET)))
+      else if ((TARGET_V850E || TARGET_V850E2_ALL)
+               && unsignedp)
        max_offset = (1 << 5);
       else
        max_offset = (1 << 8);
@@ -1013,6 +1084,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;
 
@@ -1054,133 +1132,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) != CONSTANT_P_RTX
-      && !(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.  */
@@ -1198,7 +1149,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);
     }
@@ -1503,18 +1454,15 @@ v850_reorg (void)
     }
 }
 
-\f
 /* # of registers saved by the interrupt handler.  */
-#define INTERRUPT_FIXED_NUM 4
+#define INTERRUPT_FIXED_NUM 5
 
 /* # of bytes for registers saved by the interrupt handler.  */
 #define INTERRUPT_FIXED_SAVE_SIZE (4 * INTERRUPT_FIXED_NUM)
 
-/* # of registers saved in register parameter area.  */
-#define INTERRUPT_REGPARM_NUM 4
 /* # of words saved for other registers.  */
 #define INTERRUPT_ALL_SAVE_NUM \
-  (30 - INTERRUPT_FIXED_NUM + INTERRUPT_REGPARM_NUM)
+  (30 - INTERRUPT_FIXED_NUM)
 
 #define INTERRUPT_ALL_SAVE_SIZE (4 * INTERRUPT_ALL_SAVE_NUM)
 
@@ -1524,12 +1472,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)
@@ -1538,7 +1489,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;
@@ -1557,6 +1508,7 @@ compute_register_save_size (long * p_reg_saved)
          case 1:               /* temp used to hold ep */
          case 4:               /* gp */
          case 10:              /* temp used to call interrupt save/restore */
+         case 11:              /* temp used to call interrupt save/restore (long call) */
          case EP_REGNUM:       /* ep */
            size += 4;
            break;
@@ -1566,7 +1518,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;
 
@@ -1598,7 +1550,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;
@@ -1607,7 +1559,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;
@@ -1627,22 +1579,53 @@ 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);
+}
+
+static int
+use_prolog_function (int num_save, int frame_size)
+{
+  int alloc_stack = (4 * num_save);
+  int unalloc_stack = frame_size - alloc_stack;
+  int save_func_len, restore_func_len;
+  int save_normal_len, restore_normal_len;
+
+  if (! TARGET_DISABLE_CALLT)
+      save_func_len = restore_func_len = 2;
+  else
+      save_func_len = restore_func_len = TARGET_LONG_CALLS ? (4+4+4+2+2) : 4;
+
+  if (unalloc_stack)
+    {
+      save_func_len += CONST_OK_FOR_J (-unalloc_stack) ? 2 : 4;
+      restore_func_len += CONST_OK_FOR_J (-unalloc_stack) ? 2 : 4;
+    }
+
+  /* See if we would have used ep to save the stack.  */
+  if (TARGET_EP && num_save > 3 && (unsigned)frame_size < 255)
+    save_normal_len = restore_normal_len = (3 * 2) + (2 * num_save);
+  else
+    save_normal_len = restore_normal_len = 4 * num_save;
+
+  save_normal_len += CONST_OK_FOR_J (-frame_size) ? 2 : 4;
+  restore_normal_len += (CONST_OK_FOR_J (frame_size) ? 2 : 4) + 2;
+
+  /* Don't bother checking if we don't actually save any space.
+     This happens for instance if one register is saved and additional
+     stack space is allocated.  */
+  return ((save_func_len + restore_func_len) < (save_normal_len + restore_normal_len));
 }
 
-\f
 void
 expand_prologue (void)
 {
   unsigned int i;
-  int offset;
   unsigned int size = get_frame_size ();
   unsigned int actual_fsize;
   unsigned int init_stack_alloc = 0;
   rtx save_regs[32];
   rtx save_all;
   unsigned int num_save;
-  unsigned int default_stack;
   int code;
   int interrupt_handler = v850_interrupt_function_p (current_function_decl);
   long reg_saved = 0;
@@ -1652,7 +1635,7 @@ expand_prologue (void)
   /* Save/setup global registers for interrupt functions right now.  */
   if (interrupt_handler)
     {
-      if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+      if (! TARGET_DISABLE_CALLT && (TARGET_V850E || TARGET_V850E2_ALL))
        emit_insn (gen_callt_save_interrupt ());
       else
        emit_insn (gen_save_interrupt ());
@@ -1663,93 +1646,48 @@ expand_prologue (void)
        actual_fsize -= INTERRUPT_ALL_SAVE_SIZE;
     }
 
-  /* Save arg registers to the stack if necessary.  */
-  else if (current_function_args_info.anonymous_args)
-    {
-      if (TARGET_PROLOG_FUNCTION && TARGET_V850E && !TARGET_DISABLE_CALLT)
-       emit_insn (gen_save_r6_r9_v850e ());
-      else if (TARGET_PROLOG_FUNCTION && ! TARGET_LONG_CALLS)
-       emit_insn (gen_save_r6_r9 ());
-      else
-       {
-         offset = 0;
-         for (i = 6; i < 10; i++)
-           {
-             emit_move_insn (gen_rtx_MEM (SImode,
-                                          plus_constant (stack_pointer_rtx,
-                                                         offset)),
-                             gen_rtx_REG (SImode, i));
-             offset += 4;
-           }
-       }
-    }
-
   /* Identify all of the saved registers.  */
   num_save = 0;
-  default_stack = 0;
-  for (i = 1; i < 31; i++)
+  for (i = 1; i < 32; i++)
     {
       if (((1L << i) & reg_saved) != 0)
        save_regs[num_save++] = gen_rtx_REG (Pmode, i);
     }
 
-  /* If the return pointer is saved, the helper functions also allocate
-     16 bytes of stack for arguments to be saved in.  */
-  if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
-    {
-      save_regs[num_save++] = gen_rtx_REG (Pmode, LINK_POINTER_REGNUM);
-      default_stack = 16;
-    }
-
   /* See if we have an insn that allocates stack space and saves the particular
      registers we want to.  */
   save_all = NULL_RTX;
-  if (TARGET_PROLOG_FUNCTION && num_save > 0 && actual_fsize >= default_stack)
+  if (TARGET_PROLOG_FUNCTION && num_save > 0)
     {
-      int alloc_stack = (4 * num_save) + default_stack;
-      int unalloc_stack = actual_fsize - alloc_stack;
-      int save_func_len = 4;
-      int save_normal_len;
-
-      if (unalloc_stack)
-       save_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4;
-
-      /* see if we would have used ep to save the stack */
-      if (TARGET_EP && num_save > 3 && (unsigned)actual_fsize < 255)
-       save_normal_len = (3 * 2) + (2 * num_save);
-      else
-       save_normal_len = 4 * num_save;
-
-      save_normal_len += CONST_OK_FOR_J (actual_fsize) ? 2 : 4;
-
-      /* Don't bother checking if we don't actually save any space.
-        This happens for instance if one register is saved and additional
-        stack space is allocated.  */
-      if (save_func_len < save_normal_len)
+      if (use_prolog_function (num_save, actual_fsize))
        {
+         int alloc_stack = 4 * num_save;
+         int offset = 0;
+
          save_all = gen_rtx_PARALLEL
            (VOIDmode,
             rtvec_alloc (num_save + 1
-                         + (TARGET_V850 ? (TARGET_LONG_CALLS ? 2 : 1) : 0)));
+                         + (TARGET_DISABLE_CALLT ? (TARGET_LONG_CALLS ? 2 : 1) : 0)));
 
          XVECEXP (save_all, 0, 0)
            = gen_rtx_SET (VOIDmode,
                           stack_pointer_rtx,
-                          plus_constant (stack_pointer_rtx, -alloc_stack));
-
-         offset = - default_stack;
+                          gen_rtx_PLUS (Pmode,
+                                        stack_pointer_rtx,
+                                        GEN_INT(-alloc_stack)));
          for (i = 0; i < num_save; i++)
            {
+             offset -= 4;
              XVECEXP (save_all, 0, i+1)
                = gen_rtx_SET (VOIDmode,
                               gen_rtx_MEM (Pmode,
-                                           plus_constant (stack_pointer_rtx,
-                                                          offset)),
+                                           gen_rtx_PLUS (Pmode,
+                                                         stack_pointer_rtx,
+                                                         GEN_INT(offset))),
                               save_regs[i]);
-             offset -= 4;
            }
 
-         if (TARGET_V850)
+         if (TARGET_DISABLE_CALLT)
            {
              XVECEXP (save_all, 0, num_save + 1)
                = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 10));
@@ -1759,6 +1697,8 @@ expand_prologue (void)
                  = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 11));
            }
 
+         v850_all_frame_related (save_all);
+
          code = recog (save_all, NULL_RTX, NULL);
          if (code >= 0)
            {
@@ -1766,12 +1706,6 @@ expand_prologue (void)
              INSN_CODE (insn) = code;
              actual_fsize -= alloc_stack;
              
-             if (TARGET_DEBUG)
-               fprintf (stderr, "\
-Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
-                        save_normal_len - save_func_len,
-                        save_normal_len, save_func_len,
-                        IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
            }
          else
            save_all = NULL_RTX;
@@ -1785,13 +1719,14 @@ Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
       /* Special case interrupt functions that save all registers for a call.  */
       if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
        {
-         if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+         if (! TARGET_DISABLE_CALLT && (TARGET_V850E || TARGET_V850E2_ALL))
            emit_insn (gen_callt_save_all_interrupt ());
          else
            emit_insn (gen_save_all_interrupt ());
        }
       else
        {
+         int offset;
          /* If the stack is too big, allocate it in chunks so we can do the
             register saves.  We use the register save size so we use the ep
             register.  */
@@ -1804,26 +1739,26 @@ Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
          offset = init_stack_alloc - 4;
          
          if (init_stack_alloc)
-           emit_insn (gen_addsi3 (stack_pointer_rtx,
+           F (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)
            {
-             emit_move_insn (gen_rtx_MEM (SImode,
+             F (emit_move_insn (gen_rtx_MEM (SImode,
                                           plus_constant (stack_pointer_rtx,
                                                          offset)),
-                             save_regs[--num_save]);
+                                save_regs[--num_save]));
              offset -= 4;
            }
          
          for (i = 0; i < num_save; i++)
            {
-             emit_move_insn (gen_rtx_MEM (SImode,
+             F (emit_move_insn (gen_rtx_MEM (SImode,
                                           plus_constant (stack_pointer_rtx,
                                                          offset)),
-                             save_regs[i]);
+                                save_regs[i]));
              offset -= 4;
            }
        }
@@ -1835,21 +1770,21 @@ Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
   if (actual_fsize > init_stack_alloc)
     {
       int diff = actual_fsize - init_stack_alloc;
-      if (CONST_OK_FOR_K (diff))
-       emit_insn (gen_addsi3 (stack_pointer_rtx,
+      if (CONST_OK_FOR_K (-diff))
+       F (emit_insn (gen_addsi3 (stack_pointer_rtx,
                               stack_pointer_rtx,
-                              GEN_INT (-diff)));
+                                 GEN_INT (-diff))));
       else
        {
          rtx reg = gen_rtx_REG (Pmode, 12);
-         emit_move_insn (reg, GEN_INT (-diff));
-         emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
+         F (emit_move_insn (reg, GEN_INT (-diff)));
+         F (emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg)));
        }
     }
 
   /* If we need a frame pointer, set it up now.  */
   if (frame_pointer_needed)
-    emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+    F (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
 }
 \f
 
@@ -1857,15 +1792,12 @@ void
 expand_epilogue (void)
 {
   unsigned int i;
-  int offset;
   unsigned int size = get_frame_size ();
   long reg_saved = 0;
-  unsigned int actual_fsize = compute_frame_size (size, &reg_saved);
-  unsigned int init_stack_free = 0;
+  int actual_fsize = compute_frame_size (size, &reg_saved);
   rtx restore_regs[32];
   rtx restore_all;
   unsigned int num_restore;
-  unsigned int default_stack;
   int code;
   int interrupt_handler = v850_interrupt_function_p (current_function_decl);
 
@@ -1883,52 +1815,29 @@ expand_epilogue (void)
 
   /* Identify all of the saved registers.  */
   num_restore = 0;
-  default_stack = 0;
-  for (i = 1; i < 31; i++)
+  for (i = 1; i < 32; i++)
     {
       if (((1L << i) & reg_saved) != 0)
        restore_regs[num_restore++] = gen_rtx_REG (Pmode, i);
     }
 
-  /* If the return pointer is saved, the helper functions also allocate
-     16 bytes of stack for arguments to be saved in.  */
-  if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
-    {
-      restore_regs[num_restore++] = gen_rtx_REG (Pmode, LINK_POINTER_REGNUM);
-      default_stack = 16;
-    }
-
   /* See if we have an insn that restores the particular registers we
      want to.  */
   restore_all = NULL_RTX;
-  
+
   if (TARGET_PROLOG_FUNCTION
       && num_restore > 0
-      && actual_fsize >= default_stack
       && !interrupt_handler)
     {
-      int alloc_stack = (4 * num_restore) + default_stack;
-      int unalloc_stack = actual_fsize - alloc_stack;
-      int restore_func_len = 4;
-      int restore_normal_len;
-
-      if (unalloc_stack)
-       restore_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4;
-
-      /* See if we would have used ep to restore the registers.  */
-      if (TARGET_EP && num_restore > 3 && (unsigned)actual_fsize < 255)
-       restore_normal_len = (3 * 2) + (2 * num_restore);
-      else
-       restore_normal_len = 4 * num_restore;
-
-      restore_normal_len += (CONST_OK_FOR_J (actual_fsize) ? 2 : 4) + 2;
+      int alloc_stack = (4 * num_restore);
 
       /* Don't bother checking if we don't actually save any space.  */
-      if (restore_func_len < restore_normal_len)
+      if (use_prolog_function (num_restore, actual_fsize))
        {
+         int offset;
          restore_all = gen_rtx_PARALLEL (VOIDmode,
                                          rtvec_alloc (num_restore + 2));
-         XVECEXP (restore_all, 0, 0) = gen_rtx_RETURN (VOIDmode);
+         XVECEXP (restore_all, 0, 0) = ret_rtx;
          XVECEXP (restore_all, 0, 1)
            = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
                            gen_rtx_PLUS (Pmode,
@@ -1942,8 +1851,9 @@ expand_epilogue (void)
                = gen_rtx_SET (VOIDmode,
                               restore_regs[i],
                               gen_rtx_MEM (Pmode,
-                                           plus_constant (stack_pointer_rtx,
-                                                          offset)));
+                                            gen_rtx_PLUS (Pmode,
+                                                          stack_pointer_rtx,
+                                                          GEN_INT(offset))));
              offset -= 4;
            }
 
@@ -1973,34 +1883,32 @@ expand_epilogue (void)
              insn = emit_jump_insn (restore_all);
              INSN_CODE (insn) = code;
 
-             if (TARGET_DEBUG)
-               fprintf (stderr, "\
-Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
-                        restore_normal_len - restore_func_len,
-                        restore_normal_len, restore_func_len,
-                        IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
            }
          else
            restore_all = NULL_RTX;
        }
     }
 
-  /* 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)
     {
+      unsigned int init_stack_free;
+
       /* If the stack is large, we need to cut it down in 2 pieces.  */
-      if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize))
+      if (interrupt_handler)
+       init_stack_free = 0;
+      else 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;
 
-         diff = actual_fsize - ((interrupt_handler) ? 0 : init_stack_free);
+         diff = actual_fsize - init_stack_free;
 
          if (CONST_OK_FOR_K (diff))
            emit_insn (gen_addsi3 (stack_pointer_rtx,
@@ -2020,7 +1928,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
         for a call.  */
       if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
        {
-         if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+         if (! TARGET_DISABLE_CALLT)
            emit_insn (gen_callt_restore_all_interrupt ());
          else
            emit_insn (gen_restore_all_interrupt ());
@@ -2028,7 +1936,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
       else
        {
          /* Restore registers from the beginning of the stack frame.  */
-         offset = init_stack_free - 4;
+         int offset = init_stack_free - 4;
 
          /* Restore the return pointer first.  */
          if (num_restore > 0
@@ -2048,7 +1956,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;
            }
 
@@ -2062,7 +1970,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
       /* And return or use reti for interrupt handlers.  */
       if (interrupt_handler)
         {
-          if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+          if (! TARGET_DISABLE_CALLT && (TARGET_V850E || TARGET_V850E2_ALL))
             emit_insn (gen_callt_return_interrupt ());
           else
             emit_jump_insn (gen_return_interrupt ());
@@ -2070,16 +1978,14 @@ 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;
   v850_interrupt_p = FALSE;
 }
 
-\f
 /* Update the condition code from the insn.  */
-
 void
 notice_update_cc (rtx body, rtx insn)
 {
@@ -2106,7 +2012,7 @@ notice_update_cc (rtx body, rtx insn)
 
     case CC_SET_ZNV:
       /* Insn sets the Z,N,V flags of CC to recog_data.operand[0].
-        C is in an unusable state.  */
+        C is in an unusable state.  */
       CC_STATUS_INIT;
       cc_status.flags |= CC_NO_CARRY;
       cc_status.value1 = recog_data.operand[0];
@@ -2122,9 +2028,12 @@ notice_update_cc (rtx body, rtx insn)
       /* Insn doesn't leave CC in a usable state.  */
       CC_STATUS_INIT;
       break;
+
+    default:
+      break;
     }
 }
-\f
+
 /* Retrieve the data area that has been chosen for the given decl.  */
 
 v850_data_area
@@ -2162,17 +2071,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
@@ -2184,8 +2082,8 @@ v850_handle_interrupt_attribute (tree * node,
 {
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
-      warning ("`%s' attribute only applies to functions",
-              IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute only applies to functions",
+              name);
       *no_add_attrs = true;
     }
 
@@ -2213,15 +2111,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;
        }
 
@@ -2231,8 +2130,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;
@@ -2308,13 +2207,13 @@ v850_encode_data_area (tree decl, rtx symbol)
          if (size <= 0)
            ;
 
-         else if (size <= small_memory [(int) SMALL_MEMORY_TDA].max)
+         else if (size <= small_memory_max [(int) SMALL_MEMORY_TDA])
            v850_set_data_area (decl, DATA_AREA_TDA);
 
-         else if (size <= small_memory [(int) SMALL_MEMORY_SDA].max)
+         else if (size <= small_memory_max [(int) SMALL_MEMORY_SDA])
            v850_set_data_area (decl, DATA_AREA_SDA);
 
-         else if (size <= small_memory [(int) SMALL_MEMORY_ZDA].max)
+         else if (size <= small_memory_max [(int) SMALL_MEMORY_ZDA])
            v850_set_data_area (decl, DATA_AREA_ZDA);
        }
       
@@ -2328,7 +2227,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;
 }
@@ -2343,80 +2242,12 @@ 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
    as well.  The code has already verified that the RTL matches these
    requirements.  */
+
 char *
 construct_restore_jr (rtx op)
 {
@@ -2430,18 +2261,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));
 
@@ -2449,7 +2277,7 @@ construct_restore_jr (rtx op)
   stack_bytes -= (count - 2) * 4;
 
   /* Make sure that the amount we are popping either 0 or 16 bytes.  */
-  if (stack_bytes != 0 && stack_bytes != 16)
+  if (stack_bytes != 0)
     {
       error ("bad amount of stack space removal: %d", stack_bytes);
       return NULL;
@@ -2461,12 +2289,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));
     }
@@ -2478,24 +2304,17 @@ 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 ();
-      
       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;
     }
@@ -2529,89 +2348,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
@@ -2628,21 +2364,17 @@ construct_save_jarl (rtx op)
   int i;
   static char buff [100]; /* XXX */
   
-  if (count <= 2)
+  if (count <= (TARGET_LONG_CALLS ? 3 : 2)) 
     {
-      error ("bogus JARL construction: %d\n", count);
+      error ("bogus JARL construction: %d", count);
       return NULL;
     }
 
   /* 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.  */
@@ -2652,7 +2384,7 @@ construct_save_jarl (rtx op)
   stack_bytes += (count - (TARGET_LONG_CALLS ? 3 : 2)) * 4;
 
   /* Make sure that the amount we are popping either 0 or 16 bytes.  */
-  if (stack_bytes != 0 && stack_bytes != -16)
+  if (stack_bytes != 0)
     {
       error ("bad amount of stack space removal: %d", stack_bytes);
       return NULL;
@@ -2664,12 +2396,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));
     }
@@ -2681,23 +2411,17 @@ 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 ();
-      
       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;
     }
@@ -2740,24 +2464,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;
     }
   
@@ -2876,7 +2600,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))
@@ -2923,67 +2647,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.  */
@@ -3000,18 +2663,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));
 
@@ -3022,7 +2682,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;
     }
 
@@ -3033,12 +2693,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;
@@ -3047,7 +2705,7 @@ construct_dispose_instruction (rtx op)
     }
 
   if (! TARGET_DISABLE_CALLT
-      && (use_callt || stack_bytes == 0 || stack_bytes == 16))
+      && (use_callt || stack_bytes == 0))
     {
       if (use_callt)
        {
@@ -3063,8 +2721,8 @@ construct_dispose_instruction (rtx op)
          if (i == 31)
            sprintf (buff, "callt ctoff(__callt_return_r31c)");
          else
-           sprintf (buff, "callt ctoff(__callt_return_r%d_r%d%s)",
-                    i, (mask & (1 << 31)) ? 31 : 29, stack_bytes ? "c" : "");
+           sprintf (buff, "callt ctoff(__callt_return_r%d_r%s)",
+                    i, (mask & (1 << 31)) ? "31c" : "29");
        }
     }
   else
@@ -3110,75 +2768,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.  */
@@ -3186,62 +2775,62 @@ pattern_is_ok_for_prepare (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 char *
 construct_prepare_instruction (rtx op)
 {
-  int                count = XVECLEN (op, 0);
+  int                count;
   int                stack_bytes;
   unsigned long int  mask;
   int               i;
   static char        buff[ 100 ]; /* XXX */
   int               use_callt = 0;
   
-  if (count <= 1)
+  if (XVECLEN (op, 0) <= 1)
     {
-      error ("Bogus PREPEARE construction: %d\n", count);
+      error ("bogus PREPEARE construction: %d", XVECLEN (op, 0));
       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));
 
-  /* Each push will put 4 bytes from the stack.  */
-  stack_bytes += (count - 1) * 4;
 
   /* Make sure that the amount we are popping
      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;
     }
 
   /* Now compute the bit mask of registers to push.  */
+  count = 0;
   mask = 0;
-  for (i = 1; i < count; i++)
+  for (i = 1; i < XVECLEN (op, 0); i++)
     {
       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 ();
+      if (GET_CODE (vector_element) == CLOBBER)
+       continue;
+      
+      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;
       else
        mask |= 1 << REGNO (SET_SRC (vector_element));
+      count++;
     }
 
+  stack_bytes += count * 4;
+
   if ((! TARGET_DISABLE_CALLT)
-      && (use_callt || stack_bytes == 0 || stack_bytes == -16))
+      && (use_callt || stack_bytes == 0))
     {
       if (use_callt)
        {
@@ -3256,8 +2845,8 @@ construct_prepare_instruction (rtx op)
       if (i == 31)
        sprintf (buff, "callt ctoff(__callt_save_r31c)");
       else
-       sprintf (buff, "callt ctoff(__callt_save_r%d_r%d%s)",
-                i, (mask & (1 << 31)) ? 31 : 29, stack_bytes ? "c" : "");
+       sprintf (buff, "callt ctoff(__callt_save_r%d_r%s)",
+                i, (mask & (1 << 31)) ? "31c" : "29");
     }
   else
     {
@@ -3302,48 +2891,7 @@ construct_prepare_instruction (rtx op)
   
   return buff;
 }
-\f
-/* Implement `va_arg'.  */
-
-rtx
-v850_va_arg (tree valist, tree type)
-{
-  HOST_WIDE_INT size, rsize;
-  tree addr, incr;
-  rtx addr_rtx;
-  int indirect;
-
-  /* Round up sizeof(type) to a word.  */
-  size = int_size_in_bytes (type);
-  rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
-  indirect = 0;
-
-  if (size > 8)
-    {
-      size = rsize = UNITS_PER_WORD;
-      indirect = 1;
-    }
-
-  addr = save_expr (valist);
-  incr = fold (build (PLUS_EXPR, ptr_type_node, addr,
-                     build_int_2 (rsize, 0)));
-
-  incr = build (MODIFY_EXPR, ptr_type_node, valist, incr);
-  TREE_SIDE_EFFECTS (incr) = 1;
-  expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
-  addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
-
-  if (indirect)
-    {
-      addr_rtx = force_reg (Pmode, addr_rtx);
-      addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
-      set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
-    }
 
-  return addr_rtx;
-}
-\f
 /* Return an RTX indicating where the return address to the
    calling function can be found.  */
 
@@ -3356,7 +2904,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)
@@ -3376,59 +2951,267 @@ 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 if (TREE_CODE (exp) == STRING_CST)
-    {
-      if (! flag_writable_strings)
-       readonly_data_section ();
-      else
-       data_section ();
-    }
-  else
-    readonly_data_section ();
+  return readonly_data_section;
 }
 \f
+/* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.  */
+
+static bool
+v850_function_value_regno_p (const unsigned int regno)
+{
+  return (regno == 10);
+}
+
 /* 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.  */
+
+static 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.  */
 
 static void
-v850_setup_incoming_varargs (CUMULATIVE_ARGS *ca,
+v850_setup_incoming_varargs (cumulative_args_t ca,
                             enum machine_mode mode ATTRIBUTE_UNUSED,
                             tree type ATTRIBUTE_UNUSED,
                             int *pretend_arg_size ATTRIBUTE_UNUSED,
                             int second_time ATTRIBUTE_UNUSED)
 {
-  ca->anonymous_args = (!TARGET_GHS ? 1 : 0);
+  get_cumulative_args (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);
+}
+
+/* Worker function for TARGET_CONDITIONAL_REGISTER_USAGE.
+
+   If TARGET_APP_REGS is not defined then add r2 and r5 to
+   the pool of fixed registers. See PR 14505.  */
+
+static void
+v850_conditional_register_usage (void)
+{
+  if (TARGET_APP_REGS)
+    {
+     fixed_regs[2] = 0;  call_used_regs[2] = 0;
+     fixed_regs[5] = 0;  call_used_regs[5] = 1;
+    }
+}
+\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);
+}
+
+static int
+v850_issue_rate (void)
+{
+  return (TARGET_V850E2_ALL? 2 : 1);
 }
+
+/* Implement TARGET_LEGITIMATE_CONSTANT_P.  */
+
+static bool
+v850_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  return (GET_CODE (x) == CONST_DOUBLE
+         || !(GET_CODE (x) == CONST
+              && GET_CODE (XEXP (x, 0)) == PLUS
+              && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+              && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+              && !CONST_OK_FOR_K (INTVAL (XEXP (XEXP (x, 0), 1)))));
+}
+
+static int
+v850_memory_move_cost (enum machine_mode mode,
+                      reg_class_t reg_class ATTRIBUTE_UNUSED,
+                      bool in)
+{
+  switch (GET_MODE_SIZE (mode))
+    {
+    case 0:
+      return in ? 24 : 8;
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return in ? 6 : 2;
+    default:
+      return (GET_MODE_SIZE (mode) / 2) * (in ? 3 : 1);
+    }
+}
+\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,
+       affects_type_identity } */
+  { "interrupt_handler", 0, 0, true,  false, false,
+    v850_handle_interrupt_attribute, false },
+  { "interrupt",         0, 0, true,  false, false,
+    v850_handle_interrupt_attribute, false },
+  { "sda",               0, 0, true,  false, false,
+    v850_handle_data_area_attribute, false },
+  { "tda",               0, 0, true,  false, false,
+    v850_handle_data_area_attribute, false },
+  { "zda",               0, 0, true,  false, false,
+    v850_handle_data_area_attribute, false },
+  { NULL,                0, 0, false, false, false, NULL, false }
+};
+\f
+/* Initialize the GCC target structure.  */
+
+#undef  TARGET_MEMORY_MOVE_COST
+#define TARGET_MEMORY_MOVE_COST v850_memory_move_cost
+
+#undef  TARGET_ASM_ALIGNED_HI_OP
+#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
+
+#undef  TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND v850_print_operand
+#undef  TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS v850_print_operand_address
+#undef  TARGET_PRINT_OPERAND_PUNCT_VALID_P
+#define TARGET_PRINT_OPERAND_PUNCT_VALID_P v850_print_operand_punct_valid_p
+
+#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
+#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA v850_output_addr_const_extra
+
+#undef  TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE v850_attribute_table
+
+#undef  TARGET_INSERT_ATTRIBUTES
+#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes
+
+#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_RTX_COSTS
+#define TARGET_RTX_COSTS v850_rtx_costs
+
+#undef  TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
+
+#undef  TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG v850_reorg
+
+#undef  TARGET_SCHED_ISSUE_RATE
+#define TARGET_SCHED_ISSUE_RATE v850_issue_rate
+
+#undef  TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P v850_function_value_regno_p
+#undef  TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE v850_function_value
+
+#undef  TARGET_PROMOTE_PROTOTYPES
+#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_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE v850_pass_by_reference
+
+#undef  TARGET_CALLEE_COPIES
+#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
+
+#undef  TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS v850_setup_incoming_varargs
+
+#undef  TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes
+
+#undef  TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG v850_function_arg
+
+#undef  TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE v850_function_arg_advance
+
+#undef  TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE v850_can_eliminate
+
+#undef  TARGET_CONDITIONAL_REGISTER_USAGE
+#define TARGET_CONDITIONAL_REGISTER_USAGE v850_conditional_register_usage
+
+#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
+
+#undef  TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING v850_strict_argument_naming
+
+#undef  TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P v850_legitimate_constant_p
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+#include "gt-v850.h"