OSDN Git Service

* system.h (STRIP_NAME_ENCODING): Poison it.
[pf3gnuchains/gcc-fork.git] / gcc / config / v850 / v850.c
index 319b6ab..e65dae5 100644 (file)
@@ -1,5 +1,6 @@
 /* Subroutines for insn-output.c for NEC V850 series
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
    Contributed by Jeff Law (law@cygnus.com).
 
 This file is part of GNU CC.
@@ -19,9 +20,8 @@ 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.  */
 
-#include <stdio.h>
-#include <ctype.h>
 #include "config.h"
+#include "system.h"
 #include "tree.h"
 #include "rtl.h"
 #include "regs.h"
@@ -29,70 +29,39 @@ Boston, MA 02111-1307, USA.  */
 #include "real.h"
 #include "insn-config.h"
 #include "conditions.h"
-#include "insn-flags.h"
 #include "output.h"
 #include "insn-attr.h"
 #include "flags.h"
 #include "recog.h"
 #include "expr.h"
-#include "obstack.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"
 
 #ifndef streq
 #define streq(a,b) (strcmp (a, b) == 0)
 #endif
 
-/* Function prototypes that cannot exist in v850.h due to dependency
-   compilcations.  */
-extern rtx    function_arg
-  PROTO ((CUMULATIVE_ARGS *, enum machine_mode, tree, int));
-extern int    function_arg_partial_nregs
-  PROTO ((CUMULATIVE_ARGS *, enum machine_mode, tree, int));
-extern void   asm_file_start                PROTO ((FILE *));
-extern void   print_operand                 PROTO ((FILE *, rtx, int ));
-extern void   print_operand_address         PROTO ((FILE *, rtx));
-extern void   v850_output_aligned_bss
-  PROTO ((FILE *, tree, char *, int, int));
-extern void   v850_output_common
-  PROTO ((FILE *, tree, char *, int, int));
-extern void   v850_output_local
-  PROTO ((FILE *, tree, char *, int, int));
-extern int    const_costs                   PROTO ((rtx, enum rtx_code));
-extern char * output_move_double            PROTO ((rtx *));
-extern char * output_move_single            PROTO ((rtx *));
-extern int    ep_memory_operand
-  PROTO ((rtx, enum machine_mode, int));
-extern int    reg_or_0_operand              PROTO ((rtx, enum machine_mode));
-extern int    reg_or_int5_operand           PROTO ((rtx, enum machine_mode));
-extern int    call_address_operand          PROTO ((rtx, enum machine_mode));
-extern int    movsi_source_operand          PROTO ((rtx, enum machine_mode));
-extern int    power_of_two_operand          PROTO ((rtx, enum machine_mode));
-extern int    not_power_of_two_operand      PROTO ((rtx, enum machine_mode));
-extern int    special_symbolref_operand     PROTO ((rtx, enum machine_mode));
-extern void   v850_reorg                    PROTO ((rtx));
-extern void   notice_update_cc              PROTO ((rtx, rtx));
-extern int    v850_valid_machine_decl_attribute
-  PROTO ((tree, tree, tree));
-extern int    v850_interrupt_function_p     PROTO ((tree));
-extern int    pattern_is_ok_for_prologue    PROTO ((rtx, enum machine_mode));
-extern int    pattern_is_ok_for_epilogue    PROTO ((rtx, enum machine_mode));
-extern int    register_is_ok_for_epilogue   PROTO ((rtx, enum machine_mode));
-extern char * construct_save_jarl           PROTO ((rtx));
-extern char * construct_restore_jr          PROTO ((rtx));
-extern void   v850_encode_data_area         PROTO ((tree));
-extern void   v850_set_default_decl_attr    PROTO ((tree));
-
 /* Function prototypes for stupid compilers:  */
-static void const_double_split
-  PROTO ((rtx, HOST_WIDE_INT *, HOST_WIDE_INT *));
-static int  const_costs_int        PROTO ((HOST_WIDE_INT, int));
-static void substitute_ep_register PROTO ((rtx, rtx, int, int, rtx *, rtx *));
-static int  push_data_area         PROTO ((v850_data_area));
-static int  pop_data_area          PROTO ((v850_data_area));
-static int  parse_ghs_pragma_token PROTO ((char *));
-static int  ep_memory_offset       PROTO ((enum machine_mode, int));
-static int  mark_current_function_as_interrupt PROTO ((void));
-static void v850_set_data_area     PROTO ((tree, v850_data_area));
+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));
+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 *));
+static void v850_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT));
+static void v850_encode_data_area    PARAMS ((tree));
+static void v850_encode_section_info PARAMS ((tree, int));
+static const char *v850_strip_name_encoding PARAMS ((const char *));
 
 /* True if the current function has anonymous arguments.  */
 int current_function_anonymous_args;
@@ -106,13 +75,40 @@ struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] =
   { "zda",     (char *)0,      0,              32768 },
 };
 
+/* Names of the various data areas used on the v850.  */
+tree GHS_default_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
+tree GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
+
+/* Track the current data area set by the data area pragma (which 
+   can be nested).  Tested by check_default_data_area.  */
+data_area_stack_element * data_area_stack = NULL;
+
 /* True if we don't need to check any more if the current
-   function is an interrupt handler */
+   function is an interrupt handler */
 static int v850_interrupt_cache_p = FALSE;
 
 /* 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
 
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO v850_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING v850_strip_name_encoding
+
+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
@@ -127,22 +123,22 @@ void
 override_options ()
 {
   int i;
-  extern int atoi PROTO ((const char *));
+  extern int atoi PARAMS ((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.",
+         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.",
+               error ("%s=%s is too large",
                   small_memory[i].name,
                   small_memory[i].value);
            }
@@ -199,16 +195,16 @@ function_arg (cum, mode, type, named)
   switch (cum->nbytes / UNITS_PER_WORD)
     {
     case 0:
-      result = gen_rtx (REG, mode, 6);
+      result = gen_rtx_REG (mode, 6);
       break;
     case 1:
-      result = gen_rtx (REG, mode, 7);
+      result = gen_rtx_REG (mode, 7);
       break;
     case 2:
-      result = gen_rtx (REG, mode, 8);
+      result = gen_rtx_REG (mode, 8);
       break;
     case 3:
-      result = gen_rtx (REG, mode, 9);
+      result = gen_rtx_REG (mode, 9);
       break;
     default:
       result = 0;
@@ -450,7 +446,7 @@ print_operand (file, x, code)
     case 'O':
       if (special_symbolref_operand (x, VOIDmode))
         {
-          char* name;
+          const char *name;
 
          if (GET_CODE (x) == SYMBOL_REF)
            name = XSTR (x, 0);
@@ -480,7 +476,7 @@ print_operand (file, x, code)
     case 'Q':
       if (special_symbolref_operand (x, VOIDmode))
         {
-          char* name;
+          const char *name;
 
          if (GET_CODE (x) == SYMBOL_REF)
            name = XSTR (x, 0);
@@ -508,8 +504,10 @@ print_operand (file, x, code)
          fprintf (file, reg_names[REGNO (x) + 1]);
          break;
        case MEM:
-         print_operand_address (file,
-                                XEXP (adj_offsettable_operand (x, 4), 0));
+         x = XEXP (adjust_address (x, SImode, 4), 0);
+         print_operand_address (file, x);
+         if (GET_CODE (x) == CONST_INT)
+           fprintf (file, "[r0]");
          break;
          
        default:
@@ -560,9 +558,8 @@ print_operand (file, x, code)
        {
        case MEM:
          if (GET_CODE (XEXP (x, 0)) == CONST_INT)
-           output_address (gen_rtx (PLUS, SImode,
-                                    gen_rtx (REG, SImode, 0),
-                                    XEXP (x, 0)));
+           output_address (gen_rtx_PLUS (SImode, gen_rtx (REG, SImode, 0),
+                                         XEXP (x, 0)));
          else
            output_address (XEXP (x, 0));
          break;
@@ -571,7 +568,7 @@ print_operand (file, x, code)
          fputs (reg_names[REGNO (x)], file);
          break;
        case SUBREG:
-         fputs (reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)], file);
+         fputs (reg_names[subreg_regno (x)], file);
          break;
        case CONST_INT:
        case SYMBOL_REF:
@@ -634,9 +631,9 @@ print_operand_address (file, addr)
     case SYMBOL_REF:
       if (ENCODED_NAME_P (XSTR (addr, 0)))
         {
-          char* name = XSTR (addr, 0);
-          char* off_name;
-          char* reg_name;
+          const char *name = XSTR (addr, 0);
+          const char *off_name;
+          const char *reg_name;
 
           if (ZDA_NAME_P (name))
             {
@@ -666,9 +663,9 @@ print_operand_address (file, addr)
     case CONST:
       if (special_symbolref_operand (addr, VOIDmode))
         {
-          char* name = XSTR (XEXP (XEXP (addr, 0), 0), 0);
-          char* off_name;
-          char* reg_name;
+          const char *name = XSTR (XEXP (XEXP (addr, 0), 0), 0);
+          const char *off_name;
+          const char *reg_name;
 
           if (ZDA_NAME_P (name))
             {
@@ -705,7 +702,7 @@ print_operand_address (file, addr)
 /* Return appropriate code to load up a 1, 2, or 4 integer/floating
    point value.  */
 
-char *
+const char *
 output_move_single (operands)
      rtx *operands;
 {
@@ -789,7 +786,7 @@ output_move_single (operands)
        return "%S0st%W0 %.,%0";
     }
 
-  fatal_insn ("output_move_single:", gen_rtx (SET, VOIDmode, dst, src));
+  fatal_insn ("output_move_single:", gen_rtx_SET (VOIDmode, dst, src));
   return "";
 }
 
@@ -797,7 +794,7 @@ output_move_single (operands)
 /* Return appropriate code to load up an 8 byte integer or
    floating point value */
 
-char *
+const char *
 output_move_double (operands)
     rtx *operands;
 {
@@ -836,7 +833,7 @@ output_move_double (operands)
 
       for (i = 0; i < 2; i++)
        {
-         xop[0] = gen_rtx (REG, SImode, REGNO (dst)+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);
        }
@@ -853,7 +850,7 @@ output_move_double (operands)
       if (GET_CODE (inside) == REG)
        ptrreg = REGNO (inside);
       else if (GET_CODE (inside) == SUBREG)
-       ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside);
+       ptrreg = subreg_regno (inside);
       else if (GET_CODE (inside) == PLUS)
        ptrreg = REGNO (XEXP (inside, 0));
       else if (GET_CODE (inside) == LO_SUM)
@@ -944,6 +941,7 @@ ep_memory_operand (op, mode, unsigned_load)
       op1 = XEXP (addr, 1);
       if (GET_CODE (op1) == CONST_INT
          && INTVAL (op1) < max_offset
+         && INTVAL (op1) >= 0
          && (INTVAL (op1) & mask) == 0)
        {
          if (GET_CODE (op0) == REG && REGNO (op0) == EP_REGNUM)
@@ -1064,7 +1062,7 @@ not_power_of_two_operand (op, mode)
   else if (mode == HImode)
     mask = 0xffff;
   else if (mode == SImode)
-    mask = 0xffffffff; 
+    mask = 0xffffffff;
   else
     return 0;
 
@@ -1089,14 +1087,14 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
      rtx *p_r1;
      rtx *p_ep;
 {
-  rtx reg = gen_rtx (REG, Pmode, regno);
+  rtx reg = gen_rtx_REG (Pmode, regno);
   rtx insn;
 
   if (!*p_r1)
     {
       regs_ever_live[1] = 1;
-      *p_r1 = gen_rtx (REG, Pmode, 1);
-      *p_ep = gen_rtx (REG, Pmode, 30);
+      *p_r1 = gen_rtx_REG (Pmode, 1);
+      *p_ep = gen_rtx_REG (Pmode, 30);
     }
 
   if (TARGET_DEBUG)
@@ -1140,19 +1138,21 @@ Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, end
                {
                  rtx addr = XEXP (*p_mem, 0);
 
-                 if (GET_CODE (addr) == REG && REGNO (addr) == regno)
+                 if (GET_CODE (addr) == REG && REGNO (addr) == (unsigned) regno)
                    *p_mem = change_address (*p_mem, VOIDmode, *p_ep);
 
                  else if (GET_CODE (addr) == PLUS
                           && GET_CODE (XEXP (addr, 0)) == REG
-                          && REGNO (XEXP (addr, 0)) == regno
+                          && REGNO (XEXP (addr, 0)) == (unsigned) regno
                           && GET_CODE (XEXP (addr, 1)) == CONST_INT
                           && ((INTVAL (XEXP (addr, 1)))
                               < ep_memory_offset (GET_MODE (*p_mem),
-                                                  unsignedp)))
+                                                  unsignedp))
+                          && ((INTVAL (XEXP (addr, 1))) >= 0))
                    *p_mem = change_address (*p_mem, VOIDmode,
-                                            gen_rtx (PLUS, Pmode,
-                                                     *p_ep, XEXP (addr, 1)));
+                                            gen_rtx_PLUS (Pmode,
+                                                          *p_ep,
+                                                          XEXP (addr, 1)));
                }
            }
        }
@@ -1166,10 +1166,10 @@ Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, end
       && SET_SRC (PATTERN (insn)) == *p_r1)
     delete_insn (insn);
   else
-    emit_insn_before (gen_rtx (SET, Pmode, *p_r1, *p_ep), first_insn);
+    emit_insn_before (gen_rtx_SET (Pmode, *p_r1, *p_ep), first_insn);
 
-  emit_insn_before (gen_rtx (SET, Pmode, *p_ep, reg), first_insn);
-  emit_insn_before (gen_rtx (SET, Pmode, *p_ep, *p_r1), last_insn);
+  emit_insn_before (gen_rtx_SET (Pmode, *p_ep, reg), first_insn);
+  emit_insn_before (gen_rtx_SET (Pmode, *p_ep, *p_r1), last_insn);
 }
 
 \f
@@ -1179,7 +1179,7 @@ Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, end
    as a C statement to act on the code starting at INSN.
 
    On the 850, we use it to implement the -mep mode to copy heavily used
-   pointers to ep to use the implicit addressing */
+   pointers to ep to use the implicit addressing */
 
 void v850_reorg (start_insn)
      rtx start_insn;
@@ -1199,7 +1199,7 @@ void v850_reorg (start_insn)
   rtx insn;
   rtx pattern;
 
-  /* If not ep mode, just return now */
+  /* If not ep mode, just return now */
   if (!TARGET_EP)
     return;
 
@@ -1261,12 +1261,15 @@ void v850_reorg (start_insn)
              int unsignedp = FALSE;
 
              /* We might have (SUBREG (MEM)) here, so just get rid of the
-                subregs to make this code simpler.  It is safe to call
-                alter_subreg any time after reload.  */
-             if (GET_CODE (dest) == SUBREG)
-               dest = alter_subreg (dest);
-             if (GET_CODE (src) == SUBREG)
-               src = alter_subreg (src);
+                subregs to make this code simpler.  */
+             if (GET_CODE (dest) == SUBREG
+                 && (GET_CODE (SUBREG_REG (dest)) == MEM
+                     || GET_CODE (SUBREG_REG (dest)) == REG))
+               alter_subreg (&dest);
+             if (GET_CODE (src) == SUBREG
+                 && (GET_CODE (SUBREG_REG (src)) == MEM
+                     || GET_CODE (SUBREG_REG (src)) == REG))
+               alter_subreg (&src);
 
              if (GET_CODE (dest) == MEM && GET_CODE (src) == MEM)
                mem = NULL_RTX;
@@ -1300,7 +1303,8 @@ void v850_reorg (start_insn)
                           && GET_CODE (XEXP (addr, 0)) == REG
                           && GET_CODE (XEXP (addr, 1)) == CONST_INT
                           && ((INTVAL (XEXP (addr, 1)))
-                              < ep_memory_offset (GET_MODE (mem), unsignedp)))
+                              < ep_memory_offset (GET_MODE (mem), unsignedp))
+                          && ((INTVAL (XEXP (addr, 1))) >= 0))
                    {
                      short_p = TRUE;
                      regno = REGNO (XEXP (addr, 0));
@@ -1403,7 +1407,7 @@ compute_register_save_size (p_reg_saved)
   long reg_saved = 0;
 
   /* Count the return pointer if we need to save it.  */
-  if (profile_flag && !call_p)
+  if (current_function_profile && !call_p)
     regs_ever_live [LINK_POINTER_REGNUM] = call_p = 1;
  
   /* Count space for the register saves.  */
@@ -1450,14 +1454,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)
            {
@@ -1505,8 +1506,6 @@ compute_frame_size (size, p_reg_saved)
      int size;
      long *p_reg_saved;
 {
-  extern int current_function_outgoing_args_size;
-
   return (size
          + compute_register_save_size (p_reg_saved)
          + current_function_outgoing_args_size);
@@ -1531,10 +1530,10 @@ expand_prologue ()
 
   actual_fsize = compute_frame_size (size, &reg_saved);
 
-  /* Save/setup global registers for interrupt functions right now */
+  /* Save/setup global registers for interrupt functions right now */
   if (interrupt_handler)
     {
-      emit_insn (gen_save_interrupt ());
+       emit_insn (gen_save_interrupt ());
       
       actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE;
       
@@ -1554,29 +1553,29 @@ expand_prologue ()
          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));
+             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 */
+  /* Identify all of the saved registers */
   num_save = 0;
   default_stack = 0;
   for (i = 1; i < 31; i++)
     {
       if (((1L << i) & reg_saved) != 0)
-       save_regs[num_save++] = gen_rtx (REG, Pmode, i);
+       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);
+      save_regs[num_save++] = gen_rtx_REG (Pmode, LINK_POINTER_REGNUM);
       default_stack = 16;
     }
 
@@ -1606,32 +1605,34 @@ expand_prologue ()
         stack space is allocated.  */
       if (save_func_len < save_normal_len)
        {
-         save_all = gen_rtx (PARALLEL, VOIDmode,
-                             rtvec_alloc (num_save + (TARGET_V850 ? 2 : 1)));
-         XVECEXP (save_all, 0, 0) = gen_rtx (SET, VOIDmode,
-                                             stack_pointer_rtx,
-                                             gen_rtx (PLUS, Pmode,
-                                                      stack_pointer_rtx,
-                                                      GEN_INT (-alloc_stack)));
+         save_all = gen_rtx_PARALLEL
+           (VOIDmode,
+            rtvec_alloc (num_save + (TARGET_V850 ? 2 : 1)));
+
+         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));
+             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++)
            {
-             XVECEXP (save_all, 0, i + 1)
-               = gen_rtx (SET, VOIDmode,
-                          gen_rtx (MEM, Pmode,
-                                   plus_constant (stack_pointer_rtx, offset)),
-                                   save_regs[i]);
+             XVECEXP (save_all, 0, i+1)
+               = gen_rtx_SET (VOIDmode,
+                              gen_rtx_MEM (Pmode,
+                                           plus_constant (stack_pointer_rtx,
+                                                          offset)),
+                              save_regs[i]);
              offset -= 4;
            }
 
-         code = recog (save_all, NULL_RTX, NULL_PTR);
+         code = recog (save_all, NULL_RTX, NULL);
          if (code >= 0)
            {
              rtx insn = emit_insn (save_all);
@@ -1680,18 +1681,18 @@ Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
          /* 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,
-                                      plus_constant (stack_pointer_rtx,
-                                                     offset)),
+             emit_move_insn (gen_rtx_MEM (SImode,
+                                          plus_constant (stack_pointer_rtx,
+                                                         offset)),
                              save_regs[--num_save]);
              offset -= 4;
            }
          
          for (i = 0; i < num_save; i++)
            {
-             emit_move_insn (gen_rtx (MEM, SImode,
-                                      plus_constant (stack_pointer_rtx,
-                                                     offset)),
+             emit_move_insn (gen_rtx_MEM (SImode,
+                                          plus_constant (stack_pointer_rtx,
+                                                         offset)),
                              save_regs[i]);
              offset -= 4;
            }
@@ -1710,7 +1711,7 @@ Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
                               GEN_INT (-diff)));
       else
        {
-         rtx reg = gen_rtx (REG, Pmode, 12);
+         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));
        }
@@ -1750,27 +1751,29 @@ expand_epilogue ()
   if (frame_pointer_needed)
     emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
 
-  /* Identify all of the saved registers */
+  /* Identify all of the saved registers */
   num_restore = 0;
   default_stack = 0;
   for (i = 1; i < 31; i++)
     {
       if (((1L << i) & reg_saved) != 0)
-       restore_regs[num_restore++] = gen_rtx (REG, Pmode, i);
+       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);
+      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
+  
+  if (TARGET_PROLOG_FUNCTION
+      && num_restore > 0
       && actual_fsize >= default_stack
       && !interrupt_handler)
     {
@@ -1782,7 +1785,7 @@ expand_epilogue ()
       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 */
+      /* 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
@@ -1793,28 +1796,29 @@ expand_epilogue ()
       /* Don't bother checking if we don't actually save any space.  */
       if (restore_func_len < restore_normal_len)
        {
-         restore_all = gen_rtx (PARALLEL, VOIDmode,
-                                rtvec_alloc (num_restore + 2));
-         XVECEXP (restore_all, 0, 0) = gen_rtx (RETURN, VOIDmode);
+         restore_all = gen_rtx_PARALLEL (VOIDmode,
+                                         rtvec_alloc (num_restore + 2));
+         XVECEXP (restore_all, 0, 0) = gen_rtx_RETURN (VOIDmode);
          XVECEXP (restore_all, 0, 1)
-           = gen_rtx (SET, VOIDmode, stack_pointer_rtx,
-                      gen_rtx (PLUS, Pmode,
-                               stack_pointer_rtx,
-                               GEN_INT (alloc_stack)));
+           = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+                           gen_rtx_PLUS (Pmode,
+                                         stack_pointer_rtx,
+                                         GEN_INT (alloc_stack)));
 
          offset = alloc_stack - 4;
          for (i = 0; i < num_restore; i++)
            {
              XVECEXP (restore_all, 0, i+2)
-               = gen_rtx (SET, VOIDmode,
-                          restore_regs[i],
-                          gen_rtx (MEM, Pmode,
-                                   plus_constant
-                                   (stack_pointer_rtx, offset)));
+               = gen_rtx_SET (VOIDmode,
+                              restore_regs[i],
+                              gen_rtx_MEM (Pmode,
+                                           plus_constant (stack_pointer_rtx,
+                                                          offset)));
              offset -= 4;
            }
 
-         code = recog (restore_all, NULL_RTX, NULL_PTR);
+         code = recog (restore_all, NULL_RTX, NULL);
+         
          if (code >= 0)
            {
              rtx insn;
@@ -1828,7 +1832,7 @@ expand_epilogue ()
                                           GEN_INT (actual_fsize)));
                  else
                    {
-                     rtx reg = gen_rtx (REG, Pmode, 12);
+                     rtx reg = gen_rtx_REG (Pmode, 12);
                      emit_move_insn (reg, GEN_INT (actual_fsize));
                      emit_insn (gen_addsi3 (stack_pointer_rtx,
                                             stack_pointer_rtx,
@@ -1852,7 +1856,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
-     old fashioned way (one by one). */
+     old fashioned way (one by one).  */
   if (!restore_all)
     {
       /* If the stack is large, we need to cut it down in 2 pieces.  */
@@ -1861,22 +1865,20 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
       else
        init_stack_free = actual_fsize;
 
-      /* Deallocate the rest of the stack if it is > 32K or if extra stack
-        was allocated for an interrupt handler that makes a call.  */
-      if (actual_fsize > init_stack_free
-         || (interrupt_handler && actual_fsize))
+      /* Deallocate the rest of the stack if it is > 32K.  */
+      if (actual_fsize > init_stack_free)
        {
          int diff;
 
          diff = actual_fsize - ((interrupt_handler) ? 0 : init_stack_free);
-         
+
          if (CONST_OK_FOR_K (diff))
            emit_insn (gen_addsi3 (stack_pointer_rtx,
                                   stack_pointer_rtx,
                                   GEN_INT (diff)));
          else
            {
-             rtx reg = gen_rtx (REG, Pmode, 12);
+             rtx reg = gen_rtx_REG (Pmode, 12);
              emit_move_insn (reg, GEN_INT (diff));
              emit_insn (gen_addsi3 (stack_pointer_rtx,
                                     stack_pointer_rtx,
@@ -1892,7 +1894,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
        }
       else
        {
-         /* Restore registers from the beginning of the stack frame */
+         /* Restore registers from the beginning of the stack frame */
          offset = init_stack_free - 4;
 
          /* Restore the return pointer first.  */
@@ -1900,19 +1902,20 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
              && REGNO (restore_regs [num_restore - 1]) == LINK_POINTER_REGNUM)
            {
              emit_move_insn (restore_regs[--num_restore],
-                             gen_rtx (MEM, SImode,
-                                      plus_constant (stack_pointer_rtx,
-                                                     offset)));
+                             gen_rtx_MEM (SImode,
+                                          plus_constant (stack_pointer_rtx,
+                                                         offset)));
              offset -= 4;
            }
 
          for (i = 0; i < num_restore; i++)
            {
              emit_move_insn (restore_regs[i],
-                             gen_rtx (MEM, SImode,
-                                      plus_constant (stack_pointer_rtx,
-                                                     offset)));
+                             gen_rtx_MEM (SImode,
+                                          plus_constant (stack_pointer_rtx,
+                                                         offset)));
 
+             emit_insn (gen_rtx_USE (VOIDmode, restore_regs[i]));
              offset -= 4;
            }
 
@@ -1954,24 +1957,24 @@ notice_update_cc (body, insn)
     case CC_NONE_0HIT:
       /* Insn does not change CC, but the 0'th operand has been changed.  */
       if (cc_status.value1 != 0
-         && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
+         && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
        cc_status.value1 = 0;
       break;
 
     case CC_SET_ZN:
-      /* Insn sets the Z,N flags of CC to recog_operand[0].
+      /* Insn sets the Z,N flags of CC to recog_data.operand[0].
         V,C is in an unusable state.  */
       CC_STATUS_INIT;
       cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
-      cc_status.value1 = recog_operand[0];
+      cc_status.value1 = recog_data.operand[0];
       break;
 
     case CC_SET_ZNV:
-      /* Insn sets the Z,N,V flags of CC to recog_operand[0].
+      /* Insn sets the Z,N,V flags of CC to recog_data.operand[0].
         C is in an unusable state.  */
       CC_STATUS_INIT;
       cc_status.flags |= CC_NO_CARRY;
-      cc_status.value1 = recog_operand[0];
+      cc_status.value1 = recog_data.operand[0];
       break;
 
     case CC_COMPARE:
@@ -1993,13 +1996,13 @@ v850_data_area
 v850_get_data_area (decl)
      tree decl;
 {
-  if (lookup_attribute ("sda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
+  if (lookup_attribute ("sda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
     return DATA_AREA_SDA;
   
-  if (lookup_attribute ("tda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
+  if (lookup_attribute ("tda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
     return DATA_AREA_TDA;
   
-  if (lookup_attribute ("zda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
+  if (lookup_attribute ("zda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
     return DATA_AREA_ZDA;
 
   return DATA_AREA_NORMAL;
@@ -2023,61 +2026,92 @@ v850_set_data_area (decl, data_area)
       return;
     }
 
-  DECL_MACHINE_ATTRIBUTES (decl) = tree_cons
-    (name, NULL, DECL_MACHINE_ATTRIBUTES (decl));
+  DECL_ATTRIBUTES (decl) = tree_cons
+    (name, NULL, DECL_ATTRIBUTES (decl));
 }
 \f
-/* Return nonzero if ATTR is a valid attribute for DECL.
-   ARGS are the arguments supplied with ATTR.  */
+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 }
+};
 
-int
-v850_valid_machine_decl_attribute (decl, attr, args)
-     tree decl;
-     tree attr;
-     tree args;
+/* 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;
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning ("`%s' attribute only applies to functions",
+              IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* 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_data_area data_area;
   v850_data_area area;
-  
-  if (args != NULL_TREE)
-    return 0;
-
-  if (is_attribute_p ("interrupt_handler", attr)
-      || is_attribute_p ("interrupt", attr))
-    return TREE_CODE (decl) == FUNCTION_DECL;
+  tree decl = *node;
 
   /* Implement data area attribute.  */
-  if (is_attribute_p ("sda", attr))
+  if (is_attribute_p ("sda", name))
     data_area = DATA_AREA_SDA;
-  else if (is_attribute_p ("tda", attr))
+  else if (is_attribute_p ("tda", name))
     data_area = DATA_AREA_TDA;
-  else if (is_attribute_p ("zda", attr))
+  else if (is_attribute_p ("zda", name))
     data_area = DATA_AREA_ZDA;
   else
-    return 0;
+    abort ();
   
   switch (TREE_CODE (decl))
     {
     case VAR_DECL:
       if (current_function_decl != NULL_TREE)
-       error_with_decl (decl, "\
+       {
+         error_with_decl (decl, "\
 a data area attribute cannot be specified for local variables");
-      
+         *no_add_attrs = true;
+       }
+
       /* Drop through.  */
 
     case FUNCTION_DECL:
       area = v850_get_data_area (decl);
       if (area != DATA_AREA_NORMAL && data_area != area)
-       error_with_decl (decl, "\
+       {
+         error_with_decl (decl, "\
 data area of '%s' conflicts with previous declaration");
-      
-      return 1;
+         *no_add_attrs = true;
+       }
+      break;
       
     default:
       break;
     }
-  
-  return 0;
+
+  return NULL_TREE;
 }
 
 \f
@@ -2097,13 +2131,13 @@ v850_interrupt_function_p (func)
   if (TREE_CODE (func) != FUNCTION_DECL)
     return 0;
 
-  a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func));
+  a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
   if (a != NULL_TREE)
     ret = 1;
 
   else
     {
-      a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
+      a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
       ret = a != NULL_TREE;
     }
 
@@ -2116,13 +2150,11 @@ v850_interrupt_function_p (func)
 }
 
 \f
-extern struct obstack * saveable_obstack;
-
-void
+static void
 v850_encode_data_area (decl)
      tree decl;
 {
-  char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+  const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
   int    len = strlen (str);
   char * newstr;
 
@@ -2131,7 +2163,7 @@ v850_encode_data_area (decl)
     {
       if (DECL_SECTION_NAME (decl))
        {
-         char * name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+         const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
          
          if (streq (name, ".zdata") || streq (name, ".zbss"))
            v850_set_data_area (decl, DATA_AREA_ZDA);
@@ -2164,7 +2196,7 @@ v850_encode_data_area (decl)
        return;
     }
 
-  newstr = obstack_alloc (saveable_obstack, len + 2);
+  newstr = alloca (len + 2);
 
   strcpy (newstr + 1, str);
 
@@ -2176,7 +2208,24 @@ v850_encode_data_area (decl)
     default: abort ();
     }
 
-  XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
+  XSTR (XEXP (DECL_RTL (decl), 0), 0) = ggc_alloc_string (newstr, len + 2);
+}
+
+static void
+v850_encode_section_info (decl, first)
+     tree decl;
+     int first;
+{
+  if (first && TREE_CODE (decl) == VAR_DECL
+      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+    v850_encode_data_area (decl);
+}
+
+static const char *
+v850_strip_name_encoding (str)
+     const char *str;
+{
+  return str + (ENCODED_NAME_P (str) || *str == '*');
 }
 
 /* Return true if the given RTX is a register which can be restored
@@ -2272,7 +2321,7 @@ construct_restore_jr (op)
   
   if (count <= 2)
     {
-      error ("Bogus JR construction: %d\n", count);
+      error ("bogus JR construction: %d\n", count);
       return NULL;
     }
 
@@ -2293,7 +2342,7 @@ construct_restore_jr (op)
   /* Make sure that the amount we are popping either 0 or 16 bytes.  */
   if (stack_bytes != 0 && stack_bytes != 16)
     {
-      error ("Bad amount of stack space removal: %d", stack_bytes);
+      error ("bad amount of stack space removal: %d", stack_bytes);
       return NULL;
     }
 
@@ -2347,11 +2396,26 @@ construct_restore_jr (op)
      be popping more registers than is strictly necessary, but
      it does save code space.  */
   
-  if (first == last)
-    sprintf (buff, "jr __return_%s", reg_names [first]);
+  if (TARGET_LONG_CALLS)
+    {
+      char name[40];
+      
+      if (first == last)
+       sprintf (name, "__return_%s", reg_names [first]);
+      else
+       sprintf (name, "__return_%s_%s", reg_names [first], reg_names [last]);
+      
+      sprintf (buff, "movhi hi(%s), r0, r6\n\tmovea lo(%s), r6, r6\n\tjmp r6",
+              name, name);
+    }
   else
-    sprintf (buff, "jr __return_%s_%s", reg_names [first], reg_names [last]);
-
+    {
+      if (first == last)
+       sprintf (buff, "jr __return_%s", reg_names [first]);
+      else
+       sprintf (buff, "jr __return_%s_%s", reg_names [first], reg_names [last]);
+    }
+  
   return buff;
 }
 
@@ -2456,7 +2520,7 @@ construct_save_jarl (op)
   
   if (count <= 2)
     {
-      error ("Bogus JARL construction: %d\n", count);
+      error ("bogus JARL construction: %d\n", count);
       return NULL;
     }
 
@@ -2480,7 +2544,7 @@ construct_save_jarl (op)
   /* Make sure that the amount we are popping either 0 or 16 bytes.  */
   if (stack_bytes != 0 && stack_bytes != -16)
     {
-      error ("Bad amount of stack space removal: %d", stack_bytes);
+      error ("bad amount of stack space removal: %d", stack_bytes);
       return NULL;
     }
 
@@ -2533,11 +2597,26 @@ construct_save_jarl (op)
      be pushing more registers than is strictly necessary, but
      it does save code space.  */
   
-  if (first == last)
-    sprintf (buff, "jarl __save_%s, r10", reg_names [first]);
+  if (TARGET_LONG_CALLS)
+    {
+      char name[40];
+      
+      if (first == last)
+       sprintf (name, "__save_%s", reg_names [first]);
+      else
+       sprintf (name, "__save_%s_%s", reg_names [first], reg_names [last]);
+      
+      sprintf (buff, "movhi hi(%s), r0, r11\n\tmovea lo(%s), r11, r11\n\tjarl .+4, r10\n\tadd 4, r10\n\tjmp r11",
+              name, name);
+    }
   else
-    sprintf (buff, "jarl __save_%s_%s, r10", reg_names [first],
-            reg_names [last]);
+    {
+      if (first == last)
+       sprintf (buff, "jarl __save_%s, r10", reg_names [first]);
+      else
+       sprintf (buff, "jarl __save_%s_%s, r10", reg_names [first],
+                reg_names [last]);
+    }
 
   return buff;
 }
@@ -2551,7 +2630,7 @@ void
 v850_output_aligned_bss (file, decl, name, size, align)
      FILE * file;
      tree decl;
-     char * name;
+     const char * name;
      int size;
      int align;
 {
@@ -2591,32 +2670,32 @@ void
 v850_output_common (file, decl, name, size, align)
      FILE * file;
      tree decl;
-     char * name;
+     const char * name;
      int size;
      int align;
 {
   if (decl == NULL_TREE)
     {
-      fprintf (file, "\t%s\t", COMMON_ASM_OP);
+      fprintf (file, "%s", COMMON_ASM_OP);
     }
   else
     {
       switch (v850_get_data_area (decl))
        {
        case DATA_AREA_ZDA:
-         fprintf (file, "\t%s\t", ZCOMMON_ASM_OP);
+         fprintf (file, "%s", ZCOMMON_ASM_OP);
          break;
 
        case DATA_AREA_SDA:
-         fprintf (file, "\t%s\t", SCOMMON_ASM_OP);
+         fprintf (file, "%s", SCOMMON_ASM_OP);
          break;
 
        case DATA_AREA_TDA:
-         fprintf (file, "\t%s\t", TCOMMON_ASM_OP);
+         fprintf (file, "%s", TCOMMON_ASM_OP);
          break;
       
        default:
-         fprintf (file, "\t%s\t", COMMON_ASM_OP);
+         fprintf (file, "%s", COMMON_ASM_OP);
          break;
        }
     }
@@ -2630,399 +2709,23 @@ void
 v850_output_local (file, decl, name, size, align)
      FILE * file;
      tree decl;
-     char * name;
+     const char * name;
      int size;
      int align;
 {
-  fprintf (file, "\t%s\t", LOCAL_ASM_OP);
+  fprintf (file, "%s", LOCAL_ASM_OP);
   assemble_name (file, name);
   fprintf (file, "\n");
   
   ASM_OUTPUT_ALIGNED_DECL_COMMON (file, decl, name, size, align);
 }
 
-/* The following code is for handling pragmas supported by the
-   v850 compiler produced by Green Hills Software.  This is at
-   the specific request of a customer.  */
-
-/* Track the current data area set by the data area pragma (which 
-   can be nested).  Tested by check_default_data_area. */
-
-typedef struct data_area_stack_element
-{
-  struct data_area_stack_element * prev;
-  v850_data_area                   data_area; /* current default data area. */
-} data_area_stack_element;
-
-static data_area_stack_element * data_area_stack = NULL;
-
-/* Names of the various data areas used on the v850.  */
-static tree GHS_default_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
-static tree GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
-
-/* Push a data area onto the stack.  */
-static int
-push_data_area (data_area)
-     v850_data_area data_area;
-{
-  data_area_stack_element * elem;
-
-  elem = (data_area_stack_element *) xmalloc (sizeof (* elem));
-
-  if (elem == NULL)
-    return 0;
-
-  elem->prev      = data_area_stack;
-  elem->data_area = data_area;
-
-  data_area_stack = elem;
-
-  return 1;
-}
-
-/* Remove a data area from the stack.  */
-static int
-pop_data_area (data_area)
-     v850_data_area data_area;
-{
-  if (data_area_stack == NULL)
-    warning ("#pragma GHS endXXXX found without previous startXXX");
-  else if (data_area != data_area_stack->data_area)
-    warning ("#pragma GHS endXXX does not match previous startXXX");
-  else
-    {
-      data_area_stack_element * elem;
-
-      elem = data_area_stack;
-      data_area_stack = data_area_stack->prev;
-
-      free (elem);
-
-      return 1;
-    }
-
-  return 0;
-}
-
-/* Set the machine specific 'interrupt' attribute on the current function.  */
-static int
-mark_current_function_as_interrupt ()
-{
-  tree name;
-  
-  if (current_function_decl ==  NULL_TREE)
-    {
-      warning ("Cannot set interrupt attribute: no current function");
-      return 0;
-    }
-
-  name = get_identifier ("interrupt");
-
-  if (name == NULL_TREE || TREE_CODE (name) != IDENTIFIER_NODE)
-    {
-      warning ("Cannot set interrupt attribute: no such identifier");
-      return 0;
-    }
-  
-  return valid_machine_attribute
-    (name, NULL_TREE, current_function_decl, NULL_TREE);
-}
-
-/* Parse STRING as part of a GHS pragma.
-   Returns 0 if the pragma has been parsed and there was a problem,
-   non-zero in all other cases.  */
-static int
-parse_ghs_pragma_token (string)
-     char * string;
-{
-  static enum v850_pragma_state state = V850_PS_START;
-  static enum v850_pragma_type  type  = V850_PT_UNKNOWN;
-  static v850_data_area         data_area = DATA_AREA_NORMAL;
-  static char *                 data_area_name;
-  static enum GHS_section_kind  GHS_section_kind = GHS_SECTION_KIND_DEFAULT;
-
-  /* If the string is NULL then we have reached the end of the
-     #pragma construct.  Make sure that we are in an end state, and
-     then implement the pragma's directive.  */
-  if (string == NULL)
-    {
-      int ret_val = 1;
-      
-      if (state != V850_PS_SHOULD_BE_DONE
-         && state != V850_PS_MAYBE_COMMA
-         && state != V850_PS_MAYBE_SECTION_NAME)
-       {
-         if (state != V850_PS_BAD)
-           warning ("Incomplete #pragma ghs");
-
-         ret_val = 0;
-       }
-      else switch (type)
-       {
-       case V850_PT_UNKNOWN:
-         warning ("Nothing follows #pragma ghs");
-         ret_val = 0;
-         break;
-         
-       case V850_PT_INTERRUPT:
-         ret_val = mark_current_function_as_interrupt ();
-         break;
-         
-       case V850_PT_SECTION:
-         /* If a section kind has not been specified, then reset
-            all section names back to their defaults.  */
-         if (GHS_section_kind == GHS_SECTION_KIND_DEFAULT)
-           {
-             int i;
-             
-             for (i = COUNT_OF_GHS_SECTION_KINDS; i--;)
-               GHS_current_section_names [i] = NULL;
-           }
-         /* If a section has been specified, then this will be handled
-            by check_default_section_name ().  */
-         break;
-         
-       case V850_PT_START_SECTION:
-         ret_val = push_data_area (data_area);
-         break;
-         
-       case V850_PT_END_SECTION:
-         ret_val = pop_data_area (data_area);
-         break;
-       }
-
-      state = V850_PS_START;
-      type  = V850_PT_UNKNOWN;
-      
-      return ret_val;
-    }
-  
-  switch (state)
-    {
-    case V850_PS_START:
-      data_area = DATA_AREA_NORMAL;
-      data_area_name = NULL;
-      
-      if (streq (string, "interrupt"))
-       {
-         type = V850_PT_INTERRUPT;
-         state = V850_PS_SHOULD_BE_DONE;
-       }
-      else if (streq (string, "section"))
-       {
-         type = V850_PT_SECTION;
-         state = V850_PS_MAYBE_SECTION_NAME;
-         GHS_section_kind = GHS_SECTION_KIND_DEFAULT;
-       }
-      else if (streq (string, "starttda"))
-       {
-         type = V850_PT_START_SECTION;
-         state = V850_PS_SHOULD_BE_DONE;
-         data_area = DATA_AREA_TDA;
-       }
-      else if (streq (string, "endtda"))
-       {
-         type = V850_PT_END_SECTION;
-         state = V850_PS_SHOULD_BE_DONE;
-         data_area = DATA_AREA_TDA;
-       }
-      else if (streq (string, "startsda"))
-       {
-         type = V850_PT_START_SECTION;
-         state = V850_PS_SHOULD_BE_DONE;
-         data_area = DATA_AREA_SDA;
-       }
-      else if (streq (string, "endsda"))
-       {
-         type = V850_PT_END_SECTION;
-         state = V850_PS_SHOULD_BE_DONE;
-         data_area = DATA_AREA_SDA;
-       }
-      else if (streq (string, "startzda"))
-       {
-         type = V850_PT_START_SECTION;
-         state = V850_PS_SHOULD_BE_DONE;
-         data_area = DATA_AREA_ZDA;
-       }
-      else if (streq (string, "endzda"))
-       {
-         type = V850_PT_END_SECTION;
-         state = V850_PS_SHOULD_BE_DONE;
-         data_area = DATA_AREA_ZDA;
-       }
-      else
-       {
-         warning ("Unrecognised GHS pragma: '%s'\n", string);
-         state = V850_PS_BAD;
-       }
-      break;
-      
-    case V850_PS_SHOULD_BE_DONE:
-      warning ("Extra text after valid #pragma: '%s'", string);
-      state = V850_PS_BAD;
-      break;
-      
-    case V850_PS_BAD:
-      /* Ignore tokens in a pragma that has been diagnosed as being corrupt. */
-      break;
-
-    case V850_PS_MAYBE_SECTION_NAME:
-      state = V850_PS_EXPECTING_EQUALS;
-      
-           if (streq (string, "data"))   GHS_section_kind = GHS_SECTION_KIND_DATA;
-      else if (streq (string, "text"))   GHS_section_kind = GHS_SECTION_KIND_TEXT;
-      else if (streq (string, "rodata"))  GHS_section_kind = GHS_SECTION_KIND_RODATA;
-      else if (streq (string, "const"))          GHS_section_kind = GHS_SECTION_KIND_RODATA;
-      else if (streq (string, "rosdata")) GHS_section_kind = GHS_SECTION_KIND_ROSDATA;
-      else if (streq (string, "rozdata")) GHS_section_kind = GHS_SECTION_KIND_ROZDATA;
-      else if (streq (string, "sdata"))          GHS_section_kind = GHS_SECTION_KIND_SDATA;
-      else if (streq (string, "tdata"))          GHS_section_kind = GHS_SECTION_KIND_TDATA;
-      else if (streq (string, "zdata"))          GHS_section_kind = GHS_SECTION_KIND_ZDATA;
-      /* According to GHS beta documentation, the following should not be allowed!  */
-      else if (streq (string, "bss"))    GHS_section_kind = GHS_SECTION_KIND_BSS;
-      else if (streq (string, "zbss"))   GHS_section_kind = GHS_SECTION_KIND_ZDATA;
-      else
-       {
-         warning ("Unrecognised section name '%s' in GHS section pragma",
-                  string);
-         state = V850_PS_BAD;
-       }
-      break;
-
-    case V850_PS_EXPECTING_EQUALS:
-      if (streq (string, "="))
-       state = V850_PS_EXPECTING_SECTION_ALIAS;
-      else
-       {
-         warning ("Missing '=' in GHS section pragma");
-         state = V850_PS_BAD;
-       }
-      break;
-      
-    case V850_PS_EXPECTING_SECTION_ALIAS:
-      if (streq (string, "default"))
-       GHS_current_section_names [GHS_section_kind] = NULL;
-      else
-       GHS_current_section_names [GHS_section_kind] =
-         build_string (strlen (string) + 1, string);
-      
-      state = V850_PS_MAYBE_COMMA;
-      break;
-      
-    case V850_PS_MAYBE_COMMA:
-      if (streq (string, ","))
-       state = V850_PS_MAYBE_SECTION_NAME;
-      else
-       {
-         warning
-           ("Malformed GHS section pragma: found '%s' instead of a comma",
-            string);
-         state = V850_PS_BAD;
-       }
-      break;
-    }
-  
-  return 1;
-}
-
-/* Handle the parsing of an entire GHS pragma.  */
-int
-v850_handle_pragma (p_getc, p_ungetc, name)
-     int (*  p_getc) PROTO ((void));
-     void (* p_ungetc) PROTO ((int));
-     char *  name;
-{
-  /* Parse characters in the input stream until:
-
-   * end of line
-   * end of file
-   * a complete GHS pragma has been parsed
-   * a corrupted GHS pragma has been parsed
-   * an unknown pragma is encountered.
-
-   If an unknown pragma is encountered, we must return with
-   the input stream in the same state as upon entry to this function.
-   
-   The first token in the input stream has already been parsed
-   for us, and is passed as 'name'.  */
-  
-  if (! streq (name, "ghs"))
-    return 0;
-
-  /* We now know that we are parsing a GHS pragma, so we do
-     not need to preserve the original input stream state.  */
-  for (;;)
-    {
-      static char buffer [128];
-      int         c;
-      char *      buff;
-      
-      /* Skip white space.  */
-      do
-       c = p_getc ();
-      while (c == ' ' || c == '\t');
-      
-      p_ungetc (c);
-      
-      if (c == '\n' || c == EOF || c == '\r')
-       return parse_ghs_pragma_token (NULL);
-
-      /* Read next word.  We have to do the parsing ourselves, rather
-        than calling yylex() because we can be built with front ends
-        that do not provide such functions.  */
-      buff = buffer;
-      * buff ++ = (c = p_getc ());
-
-      switch (c)
-       {
-       case ',':
-       case '=':
-         * buff ++ = (c = p_getc ());
-         break;
-         
-       case '"':
-         /* Skip opening double parenthesis.  */
-         -- buff;
-
-         /* Read string.  */
-         do
-           * buff ++ = (c = p_getc ());
-         while (c != EOF && isascii (c)
-                && (isalnum (c) || c == '_' || c == '.' || c == ' ')
-                && (buff < buffer + 126));
-         
-         if (c != '"')
-           warning ("Missing trailing \" in #pragma ghs");
-         else
-           c = p_getc ();
-         break;
-
-       default:
-         while (c != EOF && isascii (c)
-                && (isalnum (c) || c == '_' || c == '.')
-                && (buff < buffer + 126))
-           * buff ++ = (c = p_getc ());
-         break;
-       }
-
-      p_ungetc (c);
-
-      /* If nothing was read then terminate the parsing.  */
-      if (buff == buffer + 1)
-       return parse_ghs_pragma_token (NULL);
-
-      /* Parse and continue.  */
-      * -- buff = 0;
-      
-      parse_ghs_pragma_token (buffer);
-    }
-}
-
 /* Add data area to the given declaration if a ghs data area pragma is
    currently in effect (#pragma ghs startXXX/endXXX).  */
-void
-v850_set_default_decl_attr (decl)
+static void
+v850_insert_attributes (decl, attr_ptr)
      tree decl;
+     tree *attr_ptr ATTRIBUTE_UNUSED;
 {
   if (data_area_stack
       && data_area_stack->data_area
@@ -3116,3 +2819,115 @@ v850_set_default_decl_attr (decl)
        }
     }
 }
+\f
+/* Implement `va_arg'.  */
+
+rtx
+v850_va_arg (valist, type)
+     tree valist, 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.  */
+
+rtx
+v850_return_addr (count)
+     int count;
+{
+  if (count != 0)
+    return const0_rtx;
+
+  return get_hard_reg_initial_val (Pmode, LINK_POINTER_REGNUM);
+}
+\f
+static void
+v850_select_section (exp, reloc, align)
+     tree exp;
+     int reloc;
+     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:
+         if (is_const)
+           rozdata_section ();
+         else
+           zdata_section ();
+         break;
+
+        case DATA_AREA_TDA:
+         tdata_section ();
+         break;
+
+        case DATA_AREA_SDA:
+         if (is_const)
+           rosdata_section ();
+         else
+           sdata_section ();
+         break;
+
+        default:
+          if (is_const)
+           readonly_data_section ();
+         else
+           data_section ();
+         break;
+        }
+    }
+  else if (TREE_CODE (exp) == STRING_CST)
+    {
+      if (! flag_writable_strings)
+       readonly_data_section ();
+      else
+       data_section ();
+    }
+  else
+    readonly_data_section ();
+}