]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gcc/config/v850/v850.c
Imported gcc-4.4.3
[msp430-gcc.git] / gcc / config / v850 / v850.c
index f3b17aa7f9b113a7dd9bf05fe9af372b3cbb9959..51146e65d43e600298c008f55cc81cde5134c5a4 100644 (file)
@@ -1,27 +1,28 @@
 /* Subroutines for insn-output.c for NEC V850 series
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
-   Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2006, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Jeff Law (law@cygnus.com).
 
-This file is part of GNU CC.
+   This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
 
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "rtl.h"
 #include "regs.h"
@@ -36,39 +37,50 @@ Boston, MA 02111-1307, USA.  */
 #include "expr.h"
 #include "function.h"
 #include "toplev.h"
-#include "cpplib.h"
-#include "c-lex.h"
 #include "ggc.h"
 #include "integrate.h"
 #include "tm_p.h"
 #include "target.h"
 #include "target-def.h"
+#include "df.h"
 
 #ifndef streq
 #define streq(a,b) (strcmp (a, b) == 0)
 #endif
 
 /* Function prototypes for stupid compilers:  */
-static void const_double_split       PARAMS ((rtx, HOST_WIDE_INT *, HOST_WIDE_INT *));
-static int  const_costs_int          PARAMS ((HOST_WIDE_INT, int));
-static void substitute_ep_register   PARAMS ((rtx, rtx, int, int, rtx *, rtx *));
-static int  ep_memory_offset         PARAMS ((enum machine_mode, int));
-static void v850_set_data_area       PARAMS ((tree, v850_data_area));
+static bool v850_handle_option       (size_t, const char *, int);
+static void const_double_split       (rtx, HOST_WIDE_INT *, HOST_WIDE_INT *);
+static int  const_costs_int          (HOST_WIDE_INT, int);
+static int  const_costs                     (rtx, enum rtx_code);
+static bool v850_rtx_costs          (rtx, int, int, int *, bool);
+static void substitute_ep_register   (rtx, rtx, int, int, rtx *, rtx *);
+static void v850_reorg              (void);
+static int  ep_memory_offset         (enum machine_mode, int);
+static void v850_set_data_area       (tree, v850_data_area);
 const struct attribute_spec v850_attribute_table[];
-static tree v850_handle_interrupt_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree v850_handle_data_area_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static void v850_insert_attributes   PARAMS ((tree, tree *));
-
-/* True if the current function has anonymous arguments.  */
-int current_function_anonymous_args;
+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_asm_init_sections   (void);
+static section *v850_select_section (tree, int, unsigned HOST_WIDE_INT);
+static void v850_encode_data_area    (tree, rtx);
+static void v850_encode_section_info (tree, rtx, int);
+static bool v850_return_in_memory    (const_tree, const_tree);
+static void v850_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
+                                        tree, int *, int);
+static bool v850_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
+                                   const_tree, bool);
+static int v850_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
+                                  tree, bool);
 
 /* Information about the various small memory areas.  */
 struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] =
 {
-  /* name      value           max             physical max */
-  { "tda",     (char *)0,      0,              256 },
-  { "sda",     (char *)0,      0,              65536 },
-  { "zda",     (char *)0,      0,              32768 },
+  /* name      max     physical max */
+  { "tda",     0,              256 },
+  { "sda",     0,              65536 },
+  { "zda",     0,              32768 },
 };
 
 /* Names of the various data areas used on the v850.  */
@@ -85,6 +97,12 @@ static int v850_interrupt_cache_p = FALSE;
 
 /* Whether current function is an interrupt handler.  */
 static int v850_interrupt_p = FALSE;
+
+static GTY(()) section *rosdata_section;
+static GTY(()) section *rozdata_section;
+static GTY(()) section *tdata_section;
+static GTY(()) section *zdata_section;
+static GTY(()) section *zbss_section;
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
@@ -96,64 +114,136 @@ static int v850_interrupt_p = FALSE;
 #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_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS (MASK_DEFAULT | MASK_APP_REGS)
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION v850_handle_option
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS v850_rtx_costs
+
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
+
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG v850_reorg
+
+#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
+
 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.
-
-   Don't use this macro to turn on various extra optimizations for
-   `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */
+/* Set the maximum size of small memory area TYPE to the value given
+   by VALUE.  Return true if VALUE was syntactically correct.  VALUE
+   starts with the argument separator: either "-" or "=".  */
 
-void
-override_options ()
+static bool
+v850_handle_memory_option (enum small_memory_type type, const char *value)
 {
-  int i;
-  extern int atoi PARAMS ((const char *));
+  int i, size;
 
-  /* Parse -m{s,t,z}da=nnn switches */
-  for (i = 0; i < (int)SMALL_MEMORY_max; i++)
-    {
-      if (small_memory[i].value)
-       {
-         if (!ISDIGIT (*small_memory[i].value))
-           error ("%s=%s is not numeric",
-                  small_memory[i].name,
-                  small_memory[i].value);
-         else
-           {
-             small_memory[i].max = atoi (small_memory[i].value);
-             if (small_memory[i].max > small_memory[i].physical_max)
-               error ("%s=%s is too large",
-                  small_memory[i].name,
-                  small_memory[i].value);
-           }
-       }
-    }
+  if (*value != '-' && *value != '=')
+    return false;
+
+  value++;
+  for (i = 0; value[i]; i++)
+    if (!ISDIGIT (value[i]))
+      return false;
+
+  size = atoi (value);
+  if (size > small_memory[type].physical_max)
+    error ("value passed to %<-m%s%> is too large", small_memory[type].name);
+  else
+    small_memory[type].max = size;
+  return true;
 }
 
-\f
-/* Output assembly code for the start of the file.  */
+/* Implement TARGET_HANDLE_OPTION.  */
 
-void
-asm_file_start (file)
-     FILE *file;
+static bool
+v850_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
 {
-  output_file_directive (file, main_input_filename);
+  switch (code)
+    {
+    case OPT_mspace:
+      target_flags |= MASK_EP | MASK_PROLOG_FUNCTION;
+      return true;
+
+    case OPT_mv850:
+      target_flags &= ~(MASK_CPU ^ MASK_V850);
+      return true;
+
+    case OPT_mv850e:
+    case OPT_mv850e1:
+      target_flags &= ~(MASK_CPU ^ MASK_V850E);
+      return true;
+
+    case OPT_mtda:
+      return v850_handle_memory_option (SMALL_MEMORY_TDA, arg);
+
+    case OPT_msda:
+      return v850_handle_memory_option (SMALL_MEMORY_SDA, arg);
+
+    case OPT_mzda:
+      return v850_handle_memory_option (SMALL_MEMORY_ZDA, arg);
+
+    default:
+      return true;
+    }
 }
 \f
+static bool
+v850_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+                       enum machine_mode mode, const_tree type,
+                       bool named ATTRIBUTE_UNUSED)
+{
+  unsigned HOST_WIDE_INT size;
+
+  if (type)
+    size = int_size_in_bytes (type);
+  else
+    size = GET_MODE_SIZE (mode);
+
+  return size > 8;
+}
 
 /* Return an RTX to represent where a value with mode MODE will be returned
    from a function.  If the result is 0, the argument is pushed.  */
 
 rtx
-function_arg (cum, mode, type, named)
-     CUMULATIVE_ARGS *cum;
-     enum machine_mode mode;
-     tree type;
-     int named;
+function_arg (CUMULATIVE_ARGS * cum,
+              enum machine_mode mode,
+              tree type,
+              int named)
 {
   rtx result = 0;
   int size, align;
@@ -166,6 +256,9 @@ function_arg (cum, mode, type, named)
   else
     size = GET_MODE_SIZE (mode);
 
+  if (size < 1)
+    return 0;
+
   if (type)
     align = TYPE_ALIGN (type) / BITS_PER_UNIT;
   else
@@ -202,15 +295,12 @@ function_arg (cum, mode, type, named)
 }
 
 \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 (cum, mode, type, named)
-     CUMULATIVE_ARGS *cum;
-     enum machine_mode mode;
-     tree type;
-     int named;
+static int
+v850_arg_partial_bytes (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+                        tree type, bool named)
 {
   int size, align;
 
@@ -239,17 +329,14 @@ function_arg_partial_nregs (cum, mode, type, named)
       && 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;
 }
 
 \f
 /* Return the high and low words of a CONST_DOUBLE */
 
 static void
-const_double_split (x, p_high, p_low)
-     rtx x;
-     HOST_WIDE_INT *p_high;
-     HOST_WIDE_INT *p_low;
+const_double_split (rtx x, HOST_WIDE_INT * p_high, HOST_WIDE_INT * p_low)
 {
   if (GET_CODE (x) == CONST_DOUBLE)
     {
@@ -289,9 +376,7 @@ const_double_split (x, p_high, p_low)
 /* Return the cost of the rtx R with code CODE.  */
 
 static int
-const_costs_int (value, zero_cost)
-     HOST_WIDE_INT value;
-     int zero_cost;
+const_costs_int (HOST_WIDE_INT value, int zero_cost)
 {
   if (CONST_OK_FOR_I (value))
       return zero_cost;
@@ -303,10 +388,8 @@ const_costs_int (value, zero_cost)
     return 4;
 }
 
-int
-const_costs (r, c)
-     rtx r;
-     enum rtx_code c;
+static int
+const_costs (rtx r, enum rtx_code c)
 {
   HOST_WIDE_INT high, low;
 
@@ -335,15 +418,62 @@ const_costs (r, c)
     }
 }
 
+static bool
+v850_rtx_costs (rtx x,
+                int code,
+                int outer_code ATTRIBUTE_UNUSED,
+                int * total, bool speed)
+{
+  switch (code)
+    {
+    case CONST_INT:
+    case CONST_DOUBLE:
+    case CONST:
+    case SYMBOL_REF:
+    case LABEL_REF:
+      *total = COSTS_N_INSNS (const_costs (x, code));
+      return true;
+
+    case MOD:
+    case DIV:
+    case UMOD:
+    case UDIV:
+      if (TARGET_V850E && !speed)
+        *total = 6;
+      else
+       *total = 60;
+      return true;
+
+    case MULT:
+      if (TARGET_V850E
+         && (   GET_MODE (x) == SImode
+             || GET_MODE (x) == HImode
+             || GET_MODE (x) == QImode))
+        {
+         if (GET_CODE (XEXP (x, 1)) == REG)
+           *total = 4;
+         else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+           {
+             if (CONST_OK_FOR_O (INTVAL (XEXP (x, 1))))
+               *total = 6;
+             else if (CONST_OK_FOR_K (INTVAL (XEXP (x, 1))))
+               *total = 10;
+           }
+        }
+      else
+       *total = 20;
+      return true;
+
+    default:
+      return false;
+    }
+}
 \f
 /* Print operand X using operand code CODE to assembly language output file
    FILE.  */
 
 void
-print_operand (file, x, code)
-     FILE *file;
-     rtx x;
-     int code;
+print_operand (FILE * file, rtx x, int code)
 {
   HOST_WIDE_INT high, low;
 
@@ -400,90 +530,84 @@ print_operand (file, x, 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", INTVAL (x) & 0xffff);
+      fprintf (file, "%d\n", (int)(INTVAL (x) & 0xffff));
       break;
     case 'M':
       fprintf (file, "%d", exact_log2 (INTVAL (x)));
       break;
     case 'O':
-      if (special_symbolref_operand (x, VOIDmode))
-        {
-          const char *name;
-
-         if (GET_CODE (x) == SYMBOL_REF)
-           name = XSTR (x, 0);
-         else if (GET_CODE (x) == CONST)
-           name = XSTR (XEXP (XEXP (x, 0), 0), 0);
-         else
-           abort ();
-
-          if (ZDA_NAME_P (name))
-            fprintf (file, "zdaoff");
-          else if (SDA_NAME_P (name))
-            fprintf (file, "sdaoff");
-          else if (TDA_NAME_P (name))
-            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))
-        {
-          const char *name;
-
-         if (GET_CODE (x) == SYMBOL_REF)
-           name = XSTR (x, 0);
-         else if (GET_CODE (x) == CONST)
-           name = XSTR (XEXP (XEXP (x, 0), 0), 0);
-         else
-           abort ();
-
-          if (ZDA_NAME_P (name))
-            fprintf (file, "r0");
-          else if (SDA_NAME_P (name))
-            fprintf (file, "gp");
-          else if (TDA_NAME_P (name))
-            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))
@@ -504,7 +628,7 @@ print_operand (file, x, 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);
 
@@ -522,7 +646,7 @@ print_operand (file, x, code)
       switch (GET_MODE (x))
        {
        default:
-         abort ();
+         gcc_unreachable ();
 
        case QImode: fputs (".b", file); break;
        case HImode: fputs (".h", file); break;
@@ -534,19 +658,20 @@ print_operand (file, x, code)
       fputs (reg_names[0], file);
       break;
     case 'z':                  /* reg or zero */
-      if (x == const0_rtx)
-       fputs (reg_names[0], file);
-      else if (GET_CODE (x) == REG)
+      if (GET_CODE (x) == REG)
        fputs (reg_names[REGNO (x)], file);
       else
-       abort ();
+       {
+         gcc_assert (x == const0_rtx);
+         fputs (reg_names[0], file);
+       }
       break;
     default:
       switch (GET_CODE (x))
        {
        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));
@@ -566,7 +691,7 @@ print_operand (file, x, code)
          print_operand_address (file, x);
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
       break;
 
@@ -577,9 +702,7 @@ print_operand (file, x, code)
 /* Output assembly language output for the address ADDR to FILE.  */
 
 void
-print_operand_address (file, addr)
-     FILE *file;
-     rtx addr;
+print_operand_address (FILE * file, rtx addr)
 {
   switch (GET_CODE (addr))
     {
@@ -617,61 +740,57 @@ print_operand_address (file, addr)
        }
       break;
     case SYMBOL_REF:
-      if (ENCODED_NAME_P (XSTR (addr, 0)))
-        {
-          const char *name = XSTR (addr, 0);
-          const char *off_name;
-          const char *reg_name;
-
-          if (ZDA_NAME_P (name))
-            {
-              off_name = "zdaoff";
-              reg_name = "r0";
-            }
-          else if (SDA_NAME_P (name))
-            {
-              off_name = "sdaoff";
-              reg_name = "gp";
-            }
-          else if (TDA_NAME_P (name))
-            {
-              off_name = "tdaoff";
-              reg_name = "ep";
-            }
-          else
-            abort ();
-
+      {
+        const char *off_name = NULL;
+        const char *reg_name = NULL;
+
+       if (SYMBOL_REF_ZDA_P (addr))
+          {
+            off_name = "zdaoff";
+            reg_name = "r0";
+          }
+        else if (SYMBOL_REF_SDA_P (addr))
+          {
+            off_name = "sdaoff";
+            reg_name = "gp";
+          }
+        else if (SYMBOL_REF_TDA_P (addr))
+          {
+            off_name = "tdaoff";
+            reg_name = "ep";
+          }
+
+       if (off_name)
           fprintf (file, "%s(", off_name);
-          output_addr_const (file, addr);
-          fprintf (file, ")[%s]", reg_name);
-        }
-      else
         output_addr_const (file, addr);
+       if (reg_name)
+          fprintf (file, ")[%s]", reg_name);
+      }
       break;
     case CONST:
       if (special_symbolref_operand (addr, VOIDmode))
         {
-          const char *name = XSTR (XEXP (XEXP (addr, 0), 0), 0);
+         rtx x = XEXP (XEXP (addr, 0), 0);
           const char *off_name;
           const char *reg_name;
 
-          if (ZDA_NAME_P (name))
+          if (SYMBOL_REF_ZDA_P (x))
             {
               off_name = "zdaoff";
               reg_name = "r0";
             }
-          else if (SDA_NAME_P (name))
+          else if (SYMBOL_REF_SDA_P (x))
             {
               off_name = "sdaoff";
               reg_name = "gp";
             }
-          else if (TDA_NAME_P (name))
+          else if (SYMBOL_REF_TDA_P (x))
             {
               off_name = "tdaoff";
               reg_name = "ep";
             }
           else
-            abort ();
+            gcc_unreachable ();
 
           fprintf (file, "%s(", off_name);
           output_addr_const (file, addr);
@@ -686,13 +805,42 @@ print_operand_address (file, addr)
     }
 }
 
+/* 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.  */
+
+int
+v850_output_addr_const_extra (FILE * file, rtx x)
+{
+  if (GET_CODE (x) != TRUNCATE)
+    return 0;
+
+  x = XEXP (x, 0);
+
+  /* We must also handle the case where the switch table was passed a
+     constant value and so has been collapsed.  In this case the first
+     label will have been deleted.  In such a case it is OK to emit
+     nothing, since the table will not be used.
+     (cf gcc.c-torture/compile/990801-1.c).  */
+  if (GET_CODE (x) == MINUS
+      && 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;
+
+  output_addr_const (file, x);
+  return 1;
+}
 \f
 /* Return appropriate code to load up a 1, 2, or 4 integer/floating
    point value.  */
 
 const char *
-output_move_single (operands)
-     rtx *operands;
+output_move_single (rtx * operands)
 {
   rtx dst = operands[0];
   rtx src = operands[1];
@@ -706,16 +854,19 @@ output_move_single (operands)
        {
          HOST_WIDE_INT value = INTVAL (src);
 
-         if (CONST_OK_FOR_J (value))           /* signed 5 bit immediate */
+         if (CONST_OK_FOR_J (value))           /* Signed 5-bit immediate.  */
            return "mov %1,%0";
 
-         else if (CONST_OK_FOR_K (value))      /* signed 16 bit immediate */
+         else if (CONST_OK_FOR_K (value))      /* Signed 16-bit immediate.  */
            return "movea lo(%1),%.,%0";
 
-         else if (CONST_OK_FOR_L (value))      /* upper 16 bits were set */
+         else if (CONST_OK_FOR_L (value))      /* Upper 16 bits were set.  */
            return "movhi hi(%1),%.,%0";
 
-         else                                  /* random constant */
+         /* A random constant.  */
+         else if (TARGET_V850E)
+             return "mov %1,%0";
+         else
            return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
        }
 
@@ -724,16 +875,21 @@ output_move_single (operands)
          HOST_WIDE_INT high, low;
 
          const_double_split (src, &high, &low);
-         if (CONST_OK_FOR_J (high))            /* signed 5 bit immediate */
+
+         if (CONST_OK_FOR_J (high))            /* Signed 5-bit immediate.  */
            return "mov %F1,%0";
 
-         else if (CONST_OK_FOR_K (high))       /* signed 16 bit immediate */
+         else if (CONST_OK_FOR_K (high))       /* Signed 16-bit immediate.  */
            return "movea lo(%F1),%.,%0";
 
-         else if (CONST_OK_FOR_L (high))       /* upper 16 bits were set */
+         else if (CONST_OK_FOR_L (high))       /* Upper 16 bits were set.  */
            return "movhi hi(%F1),%.,%0";
 
-         else                                  /* random constant */
+         /* A random constant.  */
+         else if (TARGET_V850E)
+             return "mov %F1,%0";
+
+         else
            return "movhi hi(%F1),%.,%0\n\tmovea lo(%F1),%0,%0";
        }
 
@@ -747,7 +903,10 @@ output_move_single (operands)
               || GET_CODE (src) == SYMBOL_REF
               || GET_CODE (src) == CONST)
        {
-         return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
+         if (TARGET_V850E)
+           return "mov hilo(%1),%0";
+         else
+           return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
        }
 
       else if (GET_CODE (src) == HIGH)
@@ -778,104 +937,37 @@ output_move_single (operands)
   return "";
 }
 
-\f
-/* Return appropriate code to load up an 8 byte integer or
-   floating point value */
-
-const char *
-output_move_double (operands)
-    rtx *operands;
-{
-  enum machine_mode mode = GET_MODE (operands[0]);
-  rtx dst = operands[0];
-  rtx src = operands[1];
-
-  if (register_operand (dst, mode)
-      && register_operand (src, mode))
-    {
-      if (REGNO (src) + 1 == REGNO (dst))
-       return "mov %R1,%R0\n\tmov %1,%0";
-      else
-       return "mov %1,%0\n\tmov %R1,%R0";
-    }
-
-  /* Storing 0 */
-  if (GET_CODE (dst) == MEM
-      && ((GET_CODE (src) == CONST_INT && INTVAL (src) == 0)
-         || (GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src))))
-    return "st.w %.,%0\n\tst.w %.,%R0";
-
-  if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
-    {
-      HOST_WIDE_INT high_low[2];
-      int i;
-      rtx xop[10];
-
-      if (GET_CODE (src) == CONST_DOUBLE)
-       const_double_split (src, &high_low[1], &high_low[0]);
-      else
-       {
-         high_low[0] = INTVAL (src);
-         high_low[1] = (INTVAL (src) >= 0) ? 0 : -1;
-       }
-
-      for (i = 0; i < 2; i++)
-       {
-         xop[0] = gen_rtx_REG (SImode, REGNO (dst)+i);
-         xop[1] = GEN_INT (high_low[i]);
-         output_asm_insn (output_move_single (xop), xop);
-       }
-
-      return "";
-    }
-
-  if (GET_CODE (src) == MEM)
-    {
-      int ptrreg = -1;
-      int dreg = REGNO (dst);
-      rtx inside = XEXP (src, 0);
-
-      if (GET_CODE (inside) == REG)
-       ptrreg = REGNO (inside);
-      else if (GET_CODE (inside) == SUBREG)
-       ptrreg = subreg_regno (inside);
-      else if (GET_CODE (inside) == PLUS)
-       ptrreg = REGNO (XEXP (inside, 0));
-      else if (GET_CODE (inside) == LO_SUM)
-       ptrreg = REGNO (XEXP (inside, 0));
-
-      if (dreg == ptrreg)
-       return "ld.w %R1,%R0\n\tld.w %1,%0";
-    }
-
-  if (GET_CODE (src) == MEM)
-    return "ld.w %1,%0\n\tld.w %R1,%R0";
-  
-  if (GET_CODE (dst) == MEM)
-    return "st.w %1,%0\n\tst.w %R1,%R0";
-
-  return "mov %1,%0\n\tmov %R1,%R0";
-}
-
 \f
 /* Return maximum offset supported for a short EP memory reference of mode
    MODE and signedness UNSIGNEDP.  */
 
 static int
-ep_memory_offset (mode, unsignedp)
-     enum machine_mode mode;
-     int ATTRIBUTE_UNUSED unsignedp;
+ep_memory_offset (enum machine_mode mode, int unsignedp ATTRIBUTE_UNUSED)
 {
   int max_offset = 0;
 
   switch (mode)
     {
     case QImode:
-      max_offset = (1 << 7);
+      if (TARGET_SMALL_SLD)
+       max_offset = (1 << 4);
+      else if (TARGET_V850E 
+              && (   (  unsignedp && ! TARGET_US_BIT_SET)
+                  || (! unsignedp &&   TARGET_US_BIT_SET)))
+       max_offset = (1 << 4);
+      else
+       max_offset = (1 << 7);
       break;
 
     case HImode:
-      max_offset = (1 << 8);
+      if (TARGET_SMALL_SLD)
+       max_offset = (1 << 5);
+      else if (TARGET_V850E
+              && (   (  unsignedp && ! TARGET_US_BIT_SET)
+                  || (! unsignedp &&   TARGET_US_BIT_SET)))
+       max_offset = (1 << 5);
+      else
+       max_offset = (1 << 8);
       break;
 
     case SImode:
@@ -893,15 +985,19 @@ ep_memory_offset (mode, unsignedp)
 /* Return true if OP is a valid short EP memory reference */
 
 int
-ep_memory_operand (op, mode, unsigned_load)
-     rtx op;
-     enum machine_mode mode;
-     int unsigned_load;
+ep_memory_operand (rtx op, enum machine_mode mode, int unsigned_load)
 {
   rtx addr, op0, op1;
   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;
 
@@ -919,7 +1015,7 @@ ep_memory_operand (op, mode, unsigned_load)
       break;
 
     case SYMBOL_REF:
-      return TDA_NAME_P (XSTR (addr, 0));
+      return SYMBOL_REF_TDA_P (addr);
 
     case REG:
       return REGNO (addr) == EP_REGNUM;
@@ -935,7 +1031,7 @@ ep_memory_operand (op, mode, unsigned_load)
          if (GET_CODE (op0) == REG && REGNO (op0) == EP_REGNUM)
            return TRUE;
 
-         if (GET_CODE (op0) == SYMBOL_REF && TDA_NAME_P (XSTR (op0, 0)))
+         if (GET_CODE (op0) == SYMBOL_REF && SYMBOL_REF_TDA_P (op0))
            return TRUE;
        }
       break;
@@ -943,144 +1039,24 @@ ep_memory_operand (op, mode, unsigned_load)
 
   return FALSE;
 }
-
-/* Return true if OP is either a register or 0 */
-
-int
-reg_or_0_operand (op, mode)
-     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 (op, mode)
-     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 a valid call operand.  */
-
-int
-call_address_operand (op, mode)
-     rtx op;
-     enum machine_mode ATTRIBUTE_UNUSED mode;
-{
-  /* 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 (op, mode)
-     rtx op;
-     enum machine_mode ATTRIBUTE_UNUSED mode;
-{
-  if (GET_CODE (op) == SYMBOL_REF)
-    return ENCODED_NAME_P (XSTR (op, 0));
-
-  else if (GET_CODE (op) == CONST)
-    return (GET_CODE (XEXP (op, 0)) == PLUS
-           && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
-           && ENCODED_NAME_P (XSTR (XEXP (XEXP (op, 0), 0), 0))
-           && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
-           && CONST_OK_FOR_K (INTVAL (XEXP (XEXP (op, 0), 1))));
-
-  return FALSE;
-}
-
-int
-movsi_source_operand (op, mode)
-     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 (op, mode)
-     rtx op;
-     enum machine_mode ATTRIBUTE_UNUSED mode;
-{
-  if (GET_CODE (op) != CONST_INT)
-    return 0;
-
-  if (exact_log2 (INTVAL (op)) == -1)
-    return 0;
-  return 1;
-}
-
-int
-not_power_of_two_operand (op, mode)
-     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.  */
 
 static void
-substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
-     rtx first_insn;
-     rtx last_insn;
-     int uses;
-     int regno;
-     rtx *p_r1;
-     rtx *p_ep;
+substitute_ep_register (rtx first_insn,
+                        rtx last_insn,
+                        int uses,
+                        int regno,
+                        rtx * p_r1,
+                        rtx * p_ep)
 {
   rtx reg = gen_rtx_REG (Pmode, regno);
   rtx 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);
     }
@@ -1119,6 +1095,16 @@ Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, end
              else if (GET_CODE (SET_SRC (pattern)) == MEM)
                p_mem = &SET_SRC (pattern);
 
+             else if (GET_CODE (SET_SRC (pattern)) == SIGN_EXTEND
+                      && GET_CODE (XEXP (SET_SRC (pattern), 0)) == MEM)
+               p_mem = &XEXP (SET_SRC (pattern), 0);
+
+             else if (GET_CODE (SET_SRC (pattern)) == ZERO_EXTEND
+                      && GET_CODE (XEXP (SET_SRC (pattern), 0)) == MEM)
+               {
+                 p_mem = &XEXP (SET_SRC (pattern), 0);
+                 unsignedp = TRUE;
+               }
              else
                p_mem = (rtx *)0;
 
@@ -1161,16 +1147,12 @@ Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, end
 }
 
 \f
-/* In rare cases, correct code generation requires extra machine
-   dependent processing between the second jump optimization pass and
-   delayed branch scheduling.  On those machines, define this macro
-   as a C statement to act on the code starting at INSN.
+/* TARGET_MACHINE_DEPENDENT_REORG.  On the 850, we use it to implement
+   the -mep mode to copy heavily used pointers to ep to use the implicit
+   addressing.  */
 
-   On the 850, we use it to implement the -mep mode to copy heavily used
-   pointers to ep to use the implicit addressing.  */
-
-void v850_reorg (start_insn)
-     rtx start_insn;
+static void
+v850_reorg (void)
 {
   struct
   {
@@ -1198,7 +1180,7 @@ void v850_reorg (start_insn)
       regs[i].last_insn = NULL_RTX;
     }
 
-  for (insn = start_insn; insn != NULL_RTX; insn = NEXT_INSN (insn))
+  for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
     {
       switch (GET_CODE (insn))
        {
@@ -1268,6 +1250,16 @@ void v850_reorg (start_insn)
              else if (GET_CODE (src) == MEM)
                mem = src;
 
+             else if (GET_CODE (src) == SIGN_EXTEND
+                      && GET_CODE (XEXP (src, 0)) == MEM)
+               mem = XEXP (src, 0);
+
+             else if (GET_CODE (src) == ZERO_EXTEND
+                      && GET_CODE (XEXP (src, 0)) == MEM)
+               {
+                 mem = XEXP (src, 0);
+                 unsignedp = TRUE;
+               }
              else
                mem = NULL_RTX;
 
@@ -1385,18 +1377,20 @@ void v850_reorg (start_insn)
 #define INTERRUPT_ALL_SAVE_SIZE (4 * INTERRUPT_ALL_SAVE_NUM)
 
 int
-compute_register_save_size (p_reg_saved)
-     long *p_reg_saved;
+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)
@@ -1405,7 +1399,7 @@ compute_register_save_size (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;
@@ -1433,7 +1427,7 @@ compute_register_save_size (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;
 
@@ -1442,14 +1436,11 @@ compute_register_save_size (p_reg_saved)
         need to cover the possibility that such a helper function will
         be used, despite the fact that there might be gaps in the list of
         registers that need to be saved.  To detect this we note that the
-        helper functions always push at least register r29 if the link
-        register is not used, and at least registers r27 - r31 if the
-        link register is used (and provided that the function is not an
-        interrupt handler).  */
+        helper functions always push at least register r29 (provided
+        that the function is not an interrupt handler).  */
         
       if (TARGET_PROLOG_FUNCTION
-         && (i == 2 || i >= 20)
-         && regs_ever_live[LINK_POINTER_REGNUM] ? (i < 28) : (i < 30))
+          && (i == 2 || ((i >= 20) && (i < 30))))
        {
          if (i == 2)
            {
@@ -1468,7 +1459,7 @@ compute_register_save_size (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;
@@ -1477,7 +1468,7 @@ compute_register_save_size (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;
@@ -1493,18 +1484,16 @@ compute_register_save_size (p_reg_saved)
 }
 
 int
-compute_frame_size (size, p_reg_saved)
-     int size;
-     long *p_reg_saved;
+compute_frame_size (int size, long * p_reg_saved)
 {
   return (size
          + compute_register_save_size (p_reg_saved)
-         + current_function_outgoing_args_size);
+         + crtl->outgoing_args_size);
 }
 
 \f
 void
-expand_prologue ()
+expand_prologue (void)
 {
   unsigned int i;
   int offset;
@@ -1524,8 +1513,11 @@ expand_prologue ()
   /* Save/setup global registers for interrupt functions right now.  */
   if (interrupt_handler)
     {
+      if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+       emit_insn (gen_callt_save_interrupt ());
+      else
        emit_insn (gen_save_interrupt ());
-      
+
       actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE;
       
       if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
@@ -1533,12 +1525,12 @@ expand_prologue ()
     }
 
   /* Save arg registers to the stack if necessary.  */
-  else if (current_function_anonymous_args)
+  else if (crtl->args.info.anonymous_args)
     {
-      if (TARGET_PROLOG_FUNCTION)
-       {
-         emit_insn (gen_save_r6_r9 ());
-       }
+      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;
@@ -1598,19 +1590,14 @@ expand_prologue ()
        {
          save_all = gen_rtx_PARALLEL
            (VOIDmode,
-            rtvec_alloc (num_save + (TARGET_V850 ? 2 : 1)));
+            rtvec_alloc (num_save + 1
+                         + (TARGET_V850 ? (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));
 
-         if (TARGET_V850)
-           {
-             XVECEXP (save_all, 0, num_save+1)
-               = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 10));
-           }
-
          offset = - default_stack;
          for (i = 0; i < num_save; i++)
            {
@@ -1623,6 +1610,16 @@ expand_prologue ()
              offset -= 4;
            }
 
+         if (TARGET_V850)
+           {
+             XVECEXP (save_all, 0, num_save + 1)
+               = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 10));
+
+             if (TARGET_LONG_CALLS)
+               XVECEXP (save_all, 0, num_save + 2)
+                 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 11));
+           }
+
          code = recog (save_all, NULL_RTX, NULL);
          if (code >= 0)
            {
@@ -1643,13 +1640,16 @@ Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
     }
 
   /* If no prolog save function is available, store the registers the old
-     fashioned way (one by one). */
+     fashioned way (one by one).  */
   if (!save_all)
     {
       /* Special case interrupt functions that save all registers for a call.  */
       if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
        {
-         emit_insn (gen_save_all_interrupt ());
+         if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+           emit_insn (gen_callt_save_all_interrupt ());
+         else
+           emit_insn (gen_save_all_interrupt ());
        }
       else
        {
@@ -1661,13 +1661,13 @@ Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
          else
            init_stack_alloc = actual_fsize;
              
-         /* Save registers at the beginning of the stack frame */
+         /* Save registers at the beginning of the stack frame */
          offset = init_stack_alloc - 4;
          
          if (init_stack_alloc)
            emit_insn (gen_addsi3 (stack_pointer_rtx,
                                   stack_pointer_rtx,
-                                  GEN_INT (-init_stack_alloc)));
+                                  GEN_INT (- (signed) init_stack_alloc)));
          
          /* Save the return pointer first.  */
          if (num_save > 0 && REGNO (save_regs[num_save-1]) == LINK_POINTER_REGNUM)
@@ -1715,13 +1715,13 @@ Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
 \f
 
 void
-expand_epilogue ()
+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);
+  int actual_fsize = compute_frame_size (size, &reg_saved);
   unsigned int init_stack_free = 0;
   rtx restore_regs[32];
   rtx restore_all;
@@ -1765,7 +1765,7 @@ expand_epilogue ()
   
   if (TARGET_PROLOG_FUNCTION
       && num_restore > 0
-      && actual_fsize >= default_stack
+      && actual_fsize >= (signed) default_stack
       && !interrupt_handler)
     {
       int alloc_stack = (4 * num_restore) + default_stack;
@@ -1846,7 +1846,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
        }
     }
 
-  /* If no epilog save function is available, restore the registers the
+  /* If no epilogue save function is available, restore the registers the
      old fashioned way (one by one).  */
   if (!restore_all)
     {
@@ -1854,7 +1854,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
       if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize))
        init_stack_free = 4 * num_restore;
       else
-       init_stack_free = actual_fsize;
+       init_stack_free = (signed) actual_fsize;
 
       /* Deallocate the rest of the stack if it is > 32K.  */
       if (actual_fsize > init_stack_free)
@@ -1881,7 +1881,10 @@ 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)
        {
-         emit_insn (gen_restore_all_interrupt ());
+         if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+           emit_insn (gen_callt_restore_all_interrupt ());
+         else
+           emit_insn (gen_restore_all_interrupt ());
        }
       else
        {
@@ -1906,7 +1909,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;
            }
 
@@ -1919,14 +1922,18 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
 
       /* And return or use reti for interrupt handlers.  */
       if (interrupt_handler)
-       emit_jump_insn (gen_restore_interrupt ());
+        {
+          if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+            emit_insn (gen_callt_return_interrupt ());
+          else
+            emit_jump_insn (gen_return_interrupt ());
+        }
       else if (actual_fsize)
        emit_jump_insn (gen_return_internal ());
       else
        emit_jump_insn (gen_return ());
     }
 
-  current_function_anonymous_args = 0;
   v850_interrupt_cache_p = FALSE;
   v850_interrupt_p = FALSE;
 }
@@ -1935,9 +1942,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
 /* Update the condition code from the insn.  */
 
 void
-notice_update_cc (body, insn)
-     rtx body;
-     rtx insn;
+notice_update_cc (rtx body, rtx insn)
 {
   switch (get_attr_cc (insn))
     {
@@ -1984,8 +1989,7 @@ notice_update_cc (body, insn)
 /* Retrieve the data area that has been chosen for the given decl.  */
 
 v850_data_area
-v850_get_data_area (decl)
-     tree decl;
+v850_get_data_area (tree decl)
 {
   if (lookup_attribute ("sda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
     return DATA_AREA_SDA;
@@ -2002,9 +2006,7 @@ v850_get_data_area (decl)
 /* Store the indicated data area in the decl's attributes.  */
 
 static void
-v850_set_data_area (decl, data_area)
-     tree decl;
-     v850_data_area data_area;
+v850_set_data_area (tree decl, v850_data_area data_area)
 {
   tree name;
   
@@ -2035,16 +2037,15 @@ const struct attribute_spec v850_attribute_table[] =
 /* Handle an "interrupt" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
-v850_handle_interrupt_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
+v850_handle_interrupt_attribute (tree * node,
+                                 tree name,
+                                 tree args ATTRIBUTE_UNUSED,
+                                 int flags ATTRIBUTE_UNUSED,
+                                 bool * no_add_attrs)
 {
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
-      warning ("`%s' attribute only applies to functions",
+      warning (OPT_Wattributes, "%qs attribute only applies to functions",
               IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
@@ -2055,12 +2056,11 @@ v850_handle_interrupt_attribute (node, name, args, flags, no_add_attrs)
 /* Handle a "sda", "tda" or "zda" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
-v850_handle_data_area_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
+v850_handle_data_area_attribute (tree* node,
+                                 tree name,
+                                 tree args ATTRIBUTE_UNUSED,
+                                 int flags ATTRIBUTE_UNUSED,
+                                 bool * no_add_attrs)
 {
   v850_data_area data_area;
   v850_data_area area;
@@ -2074,15 +2074,15 @@ v850_handle_data_area_attribute (node, name, args, flags, no_add_attrs)
   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_with_decl (decl, "\
-a data area attribute cannot be specified for local variables");
+          error ("%Jdata area attributes cannot be specified for "
+                 "local variables", decl);
          *no_add_attrs = true;
        }
 
@@ -2092,8 +2092,8 @@ a data area attribute cannot be specified for local variables");
       area = v850_get_data_area (decl);
       if (area != DATA_AREA_NORMAL && data_area != area)
        {
-         error_with_decl (decl, "\
-data area of '%s' conflicts with previous declaration");
+         error ("data area of %q+D conflicts with previous declaration",
+                 decl);
          *no_add_attrs = true;
        }
       break;
@@ -2110,8 +2110,7 @@ data area of '%s' conflicts with previous declaration");
    by the "interrupt" attribute.  */
 
 int
-v850_interrupt_function_p (func)
-     tree func;
+v850_interrupt_function_p (tree func)
 {
   tree a;
   int ret = 0;
@@ -2141,15 +2140,12 @@ v850_interrupt_function_p (func)
 }
 
 \f
-void
-v850_encode_data_area (decl)
-     tree decl;
+static void
+v850_encode_data_area (tree decl, rtx symbol)
 {
-  const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
-  int    len = strlen (str);
-  char * newstr;
+  int flags;
 
-  /* Map explict sections into the appropriate attribute */
+  /* Map explicit sections into the appropriate attribute */
   if (v850_get_data_area (decl) == DATA_AREA_NORMAL)
     {
       if (DECL_SECTION_NAME (decl))
@@ -2187,93 +2183,25 @@ v850_encode_data_area (decl)
        return;
     }
 
-  newstr = alloca (len + 2);
-
-  strcpy (newstr + 1, str);
-
+  flags = SYMBOL_REF_FLAGS (symbol);
   switch (v850_get_data_area (decl))
     {
-    case DATA_AREA_ZDA: *newstr = ZDA_NAME_FLAG_CHAR; break;
-    case DATA_AREA_TDA: *newstr = TDA_NAME_FLAG_CHAR; break;
-    case DATA_AREA_SDA: *newstr = SDA_NAME_FLAG_CHAR; break;
-    default: abort ();
+    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: gcc_unreachable ();
     }
-
-  XSTR (XEXP (DECL_RTL (decl), 0), 0) = ggc_alloc_string (newstr, len + 2);
-}
-
-/* Return true if the given RTX is a register which can be restored
-   by a function epilogue.  */
-int
-register_is_ok_for_epilogue (op, mode)
-     rtx op;
-     enum machine_mode ATTRIBUTE_UNUSED mode;
-{
-  /* The save/restore routines can only cope with registers 2, and 20 - 31 */
-  return (GET_CODE (op) == REG)
-         && (((REGNO (op) >= 20) && REGNO (op) <= 31)
-             || REGNO (op) == 2);
+  SYMBOL_REF_FLAGS (symbol) = flags;
 }
 
-/* Return non-zero if the given RTX is suitable for collapsing into
-   jump to a function epilogue.  */
-int
-pattern_is_ok_for_epilogue (op, mode)
-     rtx op;
-     enum machine_mode ATTRIBUTE_UNUSED mode;
+static void
+v850_encode_section_info (tree decl, rtx rtl, int first)
 {
-  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"))))
-     */
+  default_encode_section_info (decl, rtl, first);
 
-  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;
+  if (TREE_CODE (decl) == VAR_DECL
+      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+    v850_encode_data_area (decl, XEXP (rtl, 0));
 }
 
 /* Construct a JR instruction to a routine that will perform the equivalent of
@@ -2282,8 +2210,7 @@ pattern_is_ok_for_epilogue (op, mode)
    as well.  The code has already verified that the RTL matches these
    requirements.  */
 char *
-construct_restore_jr (op)
-     rtx op;
+construct_restore_jr (rtx op)
 {
   int count = XVECLEN (op, 0);
   int stack_bytes;
@@ -2295,22 +2222,19 @@ construct_restore_jr (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));
 
-  /* Each pop will remove 4 bytes from the stack... */
+  /* Each pop will remove 4 bytes from the stack... */
   stack_bytes -= (count - 2) * 4;
 
   /* Make sure that the amount we are popping either 0 or 16 bytes.  */
@@ -2326,12 +2250,10 @@ construct_restore_jr (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));
     }
@@ -2343,24 +2265,19 @@ construct_restore_jr (op)
        break;
     }
 
-  if (first >= 32)
-    abort ();
+  gcc_assert (first < 32);
 
   /* Discover the last register to pop.  */
   if (mask & (1 << LINK_POINTER_REGNUM))
     {
-      if (stack_bytes != 16)
-       abort ();
+      gcc_assert (stack_bytes == 16);
       
       last = LINK_POINTER_REGNUM;
     }
   else
     {
-      if (stack_bytes != 0)
-       abort ();
-      
-      if ((mask & (1 << 29)) == 0)
-       abort ();
+      gcc_assert (!stack_bytes);
+      gcc_assert (mask & (1 << 29));
       
       last = 29;
     }
@@ -2394,95 +2311,13 @@ construct_restore_jr (op)
 }
 
 
-/* Return non-zero if the given RTX is suitable for collapsing into
-   a jump to a function prologue.  */
-int
-pattern_is_ok_for_prologue (op, mode)
-     rtx op;
-     enum machine_mode ATTRIBUTE_UNUSED mode;
-{
-  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 - 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 entry in the vector is a clobber.  */
-  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)
-    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
    some stack space as well.  The code has already verified that the RTL
    matches these requirements.  */
 char *
-construct_save_jarl (op)
-     rtx op;
+construct_save_jarl (rtx op)
 {
   int count = XVECLEN (op, 0);
   int stack_bytes;
@@ -2499,21 +2334,17 @@ construct_save_jarl (op)
     }
 
   /* Paranoia.  */
-  if (GET_CODE (XVECEXP (op, 0, 0)) != SET)
-    abort ();
-  if (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != PLUS)
-    abort ();
-  if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) != REG)
-    abort ();
-  if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) != CONST_INT)
-    abort ();
+  gcc_assert (GET_CODE (XVECEXP (op, 0, 0)) == SET);
+  gcc_assert (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) == PLUS);
+  gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) == REG);
+  gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) == CONST_INT);
     
   /* Work out how many bytes to push onto the stack after storing the
      registers.  */
   stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1));
 
-  /* Each push will put 4 bytes from the stack... */
-  stack_bytes += (count - 2) * 4;
+  /* Each push will put 4 bytes from the stack... */
+  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)
@@ -2524,16 +2355,14 @@ construct_save_jarl (op)
 
   /* Now compute the bit mask of registers to push.  */
   mask = 0;
-  for (i = 1; i < count - 1; i++)
+  for (i = 1; i < count - (TARGET_LONG_CALLS ? 2 : 1); 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 ();
+      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));
     }
@@ -2545,23 +2374,19 @@ construct_save_jarl (op)
        break;
     }
 
-  if (first >= 32)
-    abort ();
+  gcc_assert (first < 32);
 
   /* Discover the last register to push.  */
   if (mask & (1 << LINK_POINTER_REGNUM))
     {
-      if (stack_bytes != -16)
-       abort ();
+      gcc_assert (stack_bytes == -16);
       
       last = LINK_POINTER_REGNUM;
     }
   else
     {
-      if (stack_bytes != 0)
-       abort ();
-      if ((mask & (1 << 29)) == 0)
-       abort ();
+      gcc_assert (!stack_bytes);
+      gcc_assert (mask & (1 << 29));
       
       last = 29;
     }
@@ -2599,32 +2424,29 @@ extern tree last_assemble_variable_decl;
 extern int size_directive_output;
 
 /* A version of asm_output_aligned_bss() that copes with the special
-   data areas of the v850. */
+   data areas of the v850.  */
 void
-v850_output_aligned_bss (file, decl, name, size, align)
-     FILE * file;
-     tree decl;
-     const char * name;
-     int size;
-     int align;
+v850_output_aligned_bss (FILE * file,
+                         tree decl,
+                         const char * name,
+                         unsigned HOST_WIDE_INT size,
+                         int align)
 {
-  ASM_GLOBALIZE_LABEL (file, name);
-  
   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;
     }
   
@@ -2641,12 +2463,11 @@ v850_output_aligned_bss (file, decl, name, size, align)
 
 /* Called via the macro ASM_OUTPUT_DECL_COMMON */
 void
-v850_output_common (file, decl, name, size, align)
-     FILE * file;
-     tree decl;
-     const char * name;
-     int size;
-     int align;
+v850_output_common (FILE * file,
+                    tree decl,
+                    const char * name,
+                    int size,
+                    int align)
 {
   if (decl == NULL_TREE)
     {
@@ -2680,12 +2501,11 @@ v850_output_common (file, decl, name, size, align)
 
 /* Called via the macro ASM_OUTPUT_DECL_LOCAL */
 void
-v850_output_local (file, decl, name, size, align)
-     FILE * file;
-     tree decl;
-     const char * name;
-     int size;
-     int align;
+v850_output_local (FILE * file,
+                   tree decl,
+                   const char * name,
+                   int size,
+                   int align)
 {
   fprintf (file, "%s", LOCAL_ASM_OP);
   assemble_name (file, name);
@@ -2697,9 +2517,7 @@ v850_output_local (file, decl, name, size, align)
 /* Add data area to the given declaration if a ghs data area pragma is
    currently in effect (#pragma ghs startXXX/endXXX).  */
 static void
-v850_insert_attributes (decl, attr_ptr)
-     tree decl;
-     tree *attr_ptr ATTRIBUTE_UNUSED;
+v850_insert_attributes (tree decl, tree * attr_ptr ATTRIBUTE_UNUSED )
 {
   if (data_area_stack
       && data_area_stack->data_area
@@ -2708,7 +2526,7 @@ v850_insert_attributes (decl, attr_ptr)
       && v850_get_data_area (decl) == DATA_AREA_NORMAL)
     v850_set_data_area (decl, data_area_stack->data_area);
 
-  /* Initialise the default names of the v850 specific sections,
+  /* Initialize the default names of the v850 specific sections,
      if this has not been done before.  */
   
   if (GHS_default_section_names [(int) GHS_SECTION_KIND_SDATA] == NULL)
@@ -2743,11 +2561,11 @@ v850_insert_attributes (decl, attr_ptr)
        kind = GHS_SECTION_KIND_TEXT;
       else
        {
-         /* First choose a section kind based on the data area of the decl. */
+         /* First choose a section kind based on the data area of the decl.  */
          switch (v850_get_data_area (decl))
            {
            default:
-             abort ();
+             gcc_unreachable ();
              
            case DATA_AREA_SDA:
              kind = ((TREE_READONLY (decl))
@@ -2776,11 +2594,11 @@ v850_insert_attributes (decl, attr_ptr)
        }
 
       /* Now, if the section kind has been explicitly renamed,
-         then attach a section attribute. */
+         then attach a section attribute.  */
       chosen_section = GHS_current_section_names [(int) kind];
 
       /* Otherwise, if this kind of section needs an explicit section
-         attribute, then also attach one. */
+         attribute, then also attach one.  */
       if (chosen_section == NULL)
         chosen_section = GHS_default_section_names [(int) kind];
 
@@ -2793,58 +2611,340 @@ v850_insert_attributes (decl, attr_ptr)
        }
     }
 }
-\f
-/* Implement `va_arg'.  */
 
-rtx
-v850_va_arg (valist, type)
-     tree valist, type;
+/* Construct a DISPOSE instruction that is the equivalent of
+   the given RTX.  We have already verified that this should
+   be possible.  */
+
+char *
+construct_dispose_instruction (rtx op)
 {
-  HOST_WIDE_INT size, rsize;
-  tree addr, incr;
-  rtx addr_rtx;
-  int indirect;
+  int                count = XVECLEN (op, 0);
+  int                stack_bytes;
+  unsigned long int  mask;
+  int               i;
+  static char        buff[ 100 ]; /* XXX */
+  int                use_callt = 0;
+  
+  if (count <= 2)
+    {
+      error ("bogus DISPOSE construction: %d", count);
+      return NULL;
+    }
 
-  /* Round up sizeof(type) to a word.  */
-  size = int_size_in_bytes (type);
-  rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
-  indirect = 0;
+  /* Work out how many bytes to pop off the
+     stack before retrieving registers.  */
+  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));
+
+  /* Each pop will remove 4 bytes from the stack....  */
+  stack_bytes -= (count - 2) * 4;
 
-  if (size > 8)
+  /* Make sure that the amount we are popping
+     will fit into the DISPOSE instruction.  */
+  if (stack_bytes > 128)
     {
-      size = rsize = UNITS_PER_WORD;
-      indirect = 1;
+      error ("too much stack space to dispose of: %d", stack_bytes);
+      return NULL;
     }
 
-  addr = save_expr (valist);
-  incr = fold (build (PLUS_EXPR, ptr_type_node, addr,
-                     build_int_2 (rsize, 0)));
+  /* Now compute the bit mask of registers to push.  */
+  mask = 0;
 
-  incr = build (MODIFY_EXPR, ptr_type_node, valist, incr);
-  TREE_SIDE_EFFECTS (incr) = 1;
-  expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
+  for (i = 2; i < count; i++)
+    {
+      rtx vector_element = XVECEXP (op, 0, i);
+      
+      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));
 
-  addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
+      if (REGNO (SET_DEST (vector_element)) == 2)
+       use_callt = 1;
+      else
+        mask |= 1 << REGNO (SET_DEST (vector_element));
+    }
 
-  if (indirect)
+  if (! TARGET_DISABLE_CALLT
+      && (use_callt || stack_bytes == 0 || stack_bytes == 16))
     {
-      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 ());
+      if (use_callt)
+       {
+         sprintf (buff, "callt ctoff(__callt_return_r2_r%d)", (mask & (1 << 31)) ? 31 : 29);
+         return buff;
+       }
+      else
+       {
+         for (i = 20; i < 32; i++)
+           if (mask & (1 << i))
+             break;
+         
+         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" : "");
+       }
+    }
+  else
+    {
+      static char        regs [100]; /* XXX */
+      int                done_one;
+      
+      /* Generate the DISPOSE instruction.  Note we could just issue the
+        bit mask as a number as the assembler can cope with this, but for
+        the sake of our readers we turn it into a textual description.  */
+      regs[0] = 0;
+      done_one = 0;
+      
+      for (i = 20; i < 32; i++)
+       {
+         if (mask & (1 << i))
+           {
+             int first;
+             
+             if (done_one)
+               strcat (regs, ", ");
+             else
+               done_one = 1;
+             
+             first = i;
+             strcat (regs, reg_names[ first ]);
+             
+             for (i++; i < 32; i++)
+               if ((mask & (1 << i)) == 0)
+                 break;
+             
+             if (i > first + 1)
+               {
+                 strcat (regs, " - ");
+                 strcat (regs, reg_names[ i - 1 ] );
+               }
+           }
+       }
+      
+      sprintf (buff, "dispose %d {%s}, r31", stack_bytes / 4, regs);
+    }
+  
+  return buff;
+}
+
+/* Construct a PREPARE instruction that is the equivalent of
+   the given RTL.  We have already verified that this should
+   be possible.  */
+
+char *
+construct_prepare_instruction (rtx op)
+{
+  int                count = XVECLEN (op, 0);
+  int                stack_bytes;
+  unsigned long int  mask;
+  int               i;
+  static char        buff[ 100 ]; /* XXX */
+  int               use_callt = 0;
+  
+  if (count <= 1)
+    {
+      error ("bogus PREPEARE construction: %d", count);
+      return NULL;
+    }
+
+  /* Work out how many bytes to push onto
+     the stack after storing the registers.  */
+  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);
+      return NULL;
     }
 
-  return addr_rtx;
+  /* Now compute the bit mask of registers to push.  */
+  mask = 0;
+  for (i = 1; i < count; i++)
+    {
+      rtx vector_element = XVECEXP (op, 0, i);
+      
+      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));
+    }
+
+  if ((! TARGET_DISABLE_CALLT)
+      && (use_callt || stack_bytes == 0 || stack_bytes == -16))
+    {
+      if (use_callt)
+       {
+         sprintf (buff, "callt ctoff(__callt_save_r2_r%d)", (mask & (1 << 31)) ? 31 : 29 );
+         return buff;
+       }
+      
+      for (i = 20; i < 32; i++)
+       if (mask & (1 << i))
+         break;
+
+      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" : "");
+    }
+  else
+    {
+      static char        regs [100]; /* XXX */
+      int                done_one;
+
+      
+      /* Generate the PREPARE instruction.  Note we could just issue the
+        bit mask as a number as the assembler can cope with this, but for
+        the sake of our readers we turn it into a textual description.  */      
+      regs[0] = 0;
+      done_one = 0;
+      
+      for (i = 20; i < 32; i++)
+       {
+         if (mask & (1 << i))
+           {
+             int first;
+             
+             if (done_one)
+               strcat (regs, ", ");
+             else
+               done_one = 1;
+             
+             first = i;
+             strcat (regs, reg_names[ first ]);
+             
+             for (i++; i < 32; i++)
+               if ((mask & (1 << i)) == 0)
+                 break;
+             
+             if (i > first + 1)
+               {
+                 strcat (regs, " - ");
+                 strcat (regs, reg_names[ i - 1 ] );
+               }
+           }
+       }
+        
+      sprintf (buff, "prepare {%s}, %d", regs, (- stack_bytes) / 4);
+    }
+  
+  return buff;
 }
 \f
 /* Return an RTX indicating where the return address to the
    calling function can be found.  */
 
 rtx
-v850_return_addr (count)
-     int count;
+v850_return_addr (int count)
 {
   if (count != 0)
     return const0_rtx;
 
   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)
+{
+  if (TREE_CODE (exp) == VAR_DECL)
+    {
+      int is_const;
+      if (!TREE_READONLY (exp)
+         || TREE_SIDE_EFFECTS (exp)
+         || !DECL_INITIAL (exp)
+         || (DECL_INITIAL (exp) != error_mark_node
+             && !TREE_CONSTANT (DECL_INITIAL (exp))))
+        is_const = FALSE;
+      else
+        is_const = TRUE;
+
+      switch (v850_get_data_area (exp))
+        {
+        case DATA_AREA_ZDA:
+         return is_const ? rozdata_section : zdata_section;
+
+        case DATA_AREA_TDA:
+         return tdata_section;
+
+        case DATA_AREA_SDA:
+         return is_const ? rosdata_section : sdata_section;
+
+        default:
+         return is_const ? readonly_data_section : data_section;
+        }
+    }
+  return readonly_data_section;
+}
+\f
+/* Worker function for TARGET_RETURN_IN_MEMORY.  */
+
+static bool
+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;
+}
+\f
+/* Worker function for TARGET_SETUP_INCOMING_VARARGS.  */
+
+static void
+v850_setup_incoming_varargs (CUMULATIVE_ARGS *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);
+}
+
+#include "gt-v850.h"