OSDN Git Service

Add support for v850 special data areas.
authornickc <nickc@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 1 Oct 1998 15:11:18 +0000 (15:11 +0000)
committernickc <nickc@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 1 Oct 1998 15:11:18 +0000 (15:11 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22716 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/v850/v850.c
gcc/config/v850/v850.h

index f4e7eab..149eeaa 100644 (file)
@@ -13,6 +13,11 @@ Thu Oct  1 15:56:01 1998  Gavin Romig-Koch  <gavin@cygnus.com>
 
 Thu Oct  1 10:42:27 1998  Nick Clifton  <nickc@cygnus.com>
 
+       * config/v850/v850.c: Add function prototypes.
+       Add support for v850 special data areas.
+
+       * config/v850/v850.h: Add support for v850 special data areas.
+       
        * c-pragma.c: Add support for HANDLE_PRAGMA_PACK and
        HANDLE_PRAGMA_PACK_PUSH_POP.
        (push_alignment): New function: Cache an alignment requested
index 93fa830..8d9981c 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines for insn-output.c for NEC V850 series
-   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
    Contributed by Jeff Law (law@cygnus.com).
 
 This file is part of GNU CC.
@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA.  */
 #include <stdio.h>
 #include <ctype.h>
 #include "config.h"
+#include "tree.h"
 #include "rtl.h"
 #include "regs.h"
 #include "hard-reg-set.h"
@@ -34,8 +35,64 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "recog.h"
 #include "expr.h"
-#include "tree.h"
 #include "obstack.h"
+#include "toplev.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));
 
 /* True if the current function has anonymous arguments.  */
 int current_function_anonymous_args;
@@ -70,7 +127,7 @@ void
 override_options ()
 {
   int i;
-  extern int atoi ();
+  extern int atoi PROTO ((const char *));
 
   /* Parse -m{s,t,z}da=nnn switches */
   for (i = 0; i < (int)SMALL_MEMORY_max; i++)
@@ -235,6 +292,9 @@ const_double_split (x, p_high, p_low)
          *p_high = CONST_DOUBLE_HIGH (x);
          *p_low  = CONST_DOUBLE_LOW (x);
          return;
+
+       default:
+         break;
        }
     }
 
@@ -437,13 +497,16 @@ print_operand (file, x, code)
     case 'R':          /* 2nd word of a double.  */
       switch (GET_CODE (x))
        {
-         case REG:
-           fprintf (file, reg_names[REGNO (x) + 1]);
-           break;
-         case MEM:
-           print_operand_address (file,
-                                  XEXP (adj_offsettable_operand (x, 4), 0));
-           break;
+       case REG:
+         fprintf (file, reg_names[REGNO (x) + 1]);
+         break;
+       case MEM:
+         print_operand_address (file,
+                                XEXP (adj_offsettable_operand (x, 4), 0));
+         break;
+         
+       default:
+         break;
        }
       break;
     case 'S':
@@ -724,7 +787,8 @@ output_move_single (operands)
 }
 
 \f
-/* Return appropriate code to load up an 8 byte integer or floating point value */
+/* Return appropriate code to load up an 8 byte integer or
+   floating point value */
 
 char *
 output_move_double (operands)
@@ -805,10 +869,10 @@ output_move_double (operands)
 /* Return maximum offset supported for a short EP memory reference of mode
    MODE and signedness UNSIGNEDP.  */
 
-int
+static int
 ep_memory_offset (mode, unsignedp)
      enum machine_mode mode;
-     int unsignedp;
+     int ATTRIBUTE_UNUSED unsignedp;
 {
   int max_offset = 0;
 
@@ -826,6 +890,9 @@ ep_memory_offset (mode, unsignedp)
     case SFmode:
       max_offset = (1 << 8);
       break;
+      
+    default:
+      break;
     }
 
   return max_offset;
@@ -920,7 +987,7 @@ reg_or_int5_operand (op, mode)
 int
 call_address_operand (op, mode)
      rtx op;
-     enum machine_mode mode;
+     enum machine_mode ATTRIBUTE_UNUSED mode;
 {
   /* Only registers are valid call operands if TARGET_LONG_CALLS.  */
   if (TARGET_LONG_CALLS)
@@ -931,7 +998,7 @@ call_address_operand (op, mode)
 int
 special_symbolref_operand (op, mode)
      rtx op;
-     enum machine_mode mode;
+     enum machine_mode ATTRIBUTE_UNUSED mode;
 {
   if (GET_CODE (op) == SYMBOL_REF)
     return ENCODED_NAME_P (XSTR (op, 0));
@@ -968,7 +1035,7 @@ movsi_source_operand (op, mode)
 int
 power_of_two_operand (op, mode)
      rtx op;
-     enum machine_mode mode;
+     enum machine_mode ATTRIBUTE_UNUSED mode;
 {
   if (GET_CODE (op) != CONST_INT)
     return 0;
@@ -1017,7 +1084,6 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
 {
   rtx reg = gen_rtx (REG, Pmode, regno);
   rtx insn;
-  int i;
 
   if (!*p_r1)
     {
@@ -1027,7 +1093,8 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
     }
 
   if (TARGET_DEBUG)
-    fprintf (stderr, "Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d\n",
+    fprintf (stderr, "\
+Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d\n",
             2 * (uses - 3), uses, reg_names[regno],
             IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
             INSN_UID (first_insn), INSN_UID (last_insn));
@@ -1073,7 +1140,7 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
                           && GET_CODE (XEXP (addr, 0)) == REG
                           && REGNO (XEXP (addr, 0)) == regno
                           && GET_CODE (XEXP (addr, 1)) == CONST_INT
-                          && (((unsigned)INTVAL (XEXP (addr, 1)))
+                          && ((INTVAL (XEXP (addr, 1)))
                               < ep_memory_offset (GET_MODE (*p_mem),
                                                   unsignedp)))
                    *p_mem = change_address (*p_mem, VOIDmode,
@@ -1110,11 +1177,13 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
 void v850_reorg (start_insn)
      rtx start_insn;
 {
-  struct {
+  struct
+  {
     int uses;
     rtx first_insn;
     rtx last_insn;
-  } regs[FIRST_PSEUDO_REGISTER];
+  }
+  regs[FIRST_PSEUDO_REGISTER];
 
   int i;
   int use_ep = FALSE;
@@ -1215,7 +1284,7 @@ void v850_reorg (start_insn)
                  else if (GET_CODE (addr) == PLUS
                           && GET_CODE (XEXP (addr, 0)) == REG
                           && GET_CODE (XEXP (addr, 1)) == CONST_INT
-                          && (((unsigned)INTVAL (XEXP (addr, 1)))
+                          && ((INTVAL (XEXP (addr, 1)))
                               < ep_memory_offset (GET_MODE (mem), unsignedp)))
                    {
                      short_p = TRUE;
@@ -1274,7 +1343,8 @@ void v850_reorg (start_insn)
                        {
                          substitute_ep_register (regs[max_regno].first_insn,
                                                  regs[max_regno].last_insn,
-                                                 max_uses, max_regno, &r1, &ep);
+                                                 max_uses, max_regno, &r1,
+                                                 &ep);
 
                          /* Since we made a substitution, zap all remembered
                             registers.  */
@@ -1397,8 +1467,8 @@ expand_prologue ()
   unsigned int init_stack_alloc = 0;
   rtx save_regs[32];
   rtx save_all;
-  int num_save;
-  int default_stack;
+  unsigned int num_save;
+  unsigned int default_stack;
   int code;
   int interrupt_handler = v850_interrupt_function_p (current_function_decl);
   long reg_saved = 0;
@@ -1476,7 +1546,8 @@ 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)));
+         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,
@@ -1508,7 +1579,8 @@ expand_prologue ()
              actual_fsize -= alloc_stack;
 
              if (TARGET_DEBUG)
-               fprintf (stderr, "Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
+               fprintf (stderr, "\
+Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
                         save_normal_len - save_func_len,
                         save_normal_len, save_func_len,
                         IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
@@ -1518,8 +1590,8 @@ expand_prologue ()
        }
     }
 
-  /* If no prolog save function is available, store the registers the old fashioned
-     way (one by one). */
+  /* If no prolog save function is available, store the registers the old
+     fashioned way (one by one). */
   if (!save_all)
     {
       /* Special case interrupt functions that save all registers for a call.  */
@@ -1600,8 +1672,8 @@ expand_epilogue ()
   unsigned int init_stack_free = 0;
   rtx restore_regs[32];
   rtx restore_all;
-  int num_restore;
-  int default_stack;
+  unsigned int num_restore;
+  unsigned int default_stack;
   int code;
   int interrupt_handler = v850_interrupt_function_p (current_function_decl);
 
@@ -1637,7 +1709,8 @@ expand_epilogue ()
   /* See if we have an insn that restores the particular registers we
      want to.  */
   restore_all = NULL_RTX;
-  if (TARGET_PROLOG_FUNCTION && num_restore > 0 && actual_fsize >= default_stack
+  if (TARGET_PROLOG_FUNCTION && num_restore > 0
+      && actual_fsize >= default_stack
       && !interrupt_handler)
     {
       int alloc_stack = (4 * num_restore) + default_stack;
@@ -1675,7 +1748,8 @@ expand_epilogue ()
                = gen_rtx (SET, VOIDmode,
                           restore_regs[i],
                           gen_rtx (MEM, Pmode,
-                                   plus_constant (stack_pointer_rtx, offset)));
+                                   plus_constant
+                                   (stack_pointer_rtx, offset)));
              offset -= 4;
            }
 
@@ -1705,7 +1779,8 @@ expand_epilogue ()
              INSN_CODE (insn) = code;
 
              if (TARGET_DEBUG)
-               fprintf (stderr, "Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
+               fprintf (stderr, "\
+Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
                         restore_normal_len - restore_func_len,
                         restore_normal_len, restore_func_len,
                         IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
@@ -1727,9 +1802,13 @@ expand_epilogue ()
 
       /* 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))
+      if (actual_fsize > init_stack_free
+         || (interrupt_handler && actual_fsize))
        {
-         int diff = actual_fsize - ((interrupt_handler) ? 0 : 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,
@@ -1843,24 +1922,59 @@ notice_update_cc (body, insn)
       break;
     }
 }
-
 \f
-/* Return nonzero if ATTR is a valid attribute for DECL.
-   ATTRIBUTES are any existing attributes and ARGS are the arguments
-   supplied with ATTR.
+/* Retrieve the data area that has been chosen for the given decl.  */
 
-   Supported attributes:
+v850_data_area
+v850_get_data_area (decl)
+     tree decl;
+{
+  if (lookup_attribute ("sda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
+    return DATA_AREA_SDA;
+  
+  if (lookup_attribute ("tda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
+    return DATA_AREA_TDA;
+  
+  if (lookup_attribute ("zda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
+    return DATA_AREA_ZDA;
+
+  return DATA_AREA_NORMAL;
+}
 
-   interrupt_handler or interrupt: output a prologue and epilogue suitable
-   for an interrupt handler.  */
+/* 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;
+{
+  tree name;
+  
+  switch (data_area)
+    {
+    case DATA_AREA_SDA: name = get_identifier ("sda"); break;
+    case DATA_AREA_TDA: name = get_identifier ("tda"); break;
+    case DATA_AREA_ZDA: name = get_identifier ("zda"); break;
+    default:
+      return;
+    }
+
+  DECL_MACHINE_ATTRIBUTES (decl) = tree_cons
+    (name, NULL, DECL_MACHINE_ATTRIBUTES (decl));
+}
+\f
+/* Return nonzero if ATTR is a valid attribute for DECL.
+   ARGS are the arguments supplied with ATTR.  */
 
 int
-v850_valid_machine_decl_attribute (decl, attributes, attr, args)
+v850_valid_machine_decl_attribute (decl, attr, args)
      tree decl;
-     tree attributes;
      tree attr;
      tree args;
 {
+  v850_data_area data_area;
+  v850_data_area area;
+  
   if (args != NULL_TREE)
     return 0;
 
@@ -1868,6 +1982,37 @@ v850_valid_machine_decl_attribute (decl, attributes, attr, args)
       || is_attribute_p ("interrupt", attr))
     return TREE_CODE (decl) == FUNCTION_DECL;
 
+  /* Implement data area attribute.  */
+  if (is_attribute_p ("sda", attr))
+    data_area = DATA_AREA_SDA;
+  else if (is_attribute_p ("tda", attr))
+    data_area = DATA_AREA_TDA;
+  else if (is_attribute_p ("zda", attr))
+    data_area = DATA_AREA_ZDA;
+  else
+    return 0;
+  
+  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");
+      
+      /* Drop through.  */
+
+    case FUNCTION_DECL:
+      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");
+      
+      return 1;
+      
+    default:
+      break;
+    }
+  
   return 0;
 }
 
@@ -1907,18 +2052,67 @@ v850_interrupt_function_p (func)
 }
 
 \f
-extern struct obstack *saveable_obstack;
+extern struct obstack * saveable_obstack;
 
+void
 v850_encode_data_area (decl)
      tree decl;
 {
-  char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
-  int len = strlen (str);
-  char *newstr;
+  char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+  int    len = strlen (str);
+  char * newstr;
+
+  /* Map explict sections into the appropriate attribute */
+  if (v850_get_data_area (decl) == DATA_AREA_NORMAL)
+    {
+      if (DECL_SECTION_NAME (decl))
+       {
+         char * name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+         
+         if (streq (name, ".zdata") || streq (name, ".zbss"))
+           v850_set_data_area (decl, DATA_AREA_ZDA);
+
+         else if (streq (name, ".sdata") || streq (name, ".sbss"))
+           v850_set_data_area (decl, DATA_AREA_SDA);
+
+         else if (streq (name, ".tdata"))
+           v850_set_data_area (decl, DATA_AREA_TDA);
+       }
+
+      /* If no attribute, support -m{zda,sda,tda}=n */
+      else
+       {
+         int size = int_size_in_bytes (TREE_TYPE (decl));
+         if (size <= 0)
+           ;
+
+         else if (size <= small_memory [(int) SMALL_MEMORY_TDA].max)
+           v850_set_data_area (decl, DATA_AREA_TDA);
+
+         else if (size <= small_memory [(int) SMALL_MEMORY_SDA].max)
+           v850_set_data_area (decl, DATA_AREA_SDA);
+
+         else if (size <= small_memory [(int) SMALL_MEMORY_ZDA].max)
+           v850_set_data_area (decl, DATA_AREA_ZDA);
+       }
+      
+      if (v850_get_data_area (decl) == DATA_AREA_NORMAL)
+       return;
+    }
+
+  newstr = obstack_alloc (saveable_obstack, len + 2);
 
-  /* In the Cygnus sources we actually do something; this is just
-     here to make merges easier.  */
-  return;
+  strcpy (newstr + 1, str);
+
+  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 ();
+    }
+
+  XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
 }
 
 /* Return true if the given RTX is a register which can be restored
@@ -1926,7 +2120,7 @@ v850_encode_data_area (decl)
 int
 register_is_ok_for_epilogue (op, mode)
      rtx op;
-     enum machine_mode mode;
+     enum machine_mode ATTRIBUTE_UNUSED mode;
 {
   /* The save/restore routines can only cope with registers 2, and 20 - 31 */
   return (GET_CODE (op) == REG)
@@ -1939,7 +2133,7 @@ register_is_ok_for_epilogue (op, mode)
 int
 pattern_is_ok_for_epilogue (op, mode)
      rtx op;
-     enum machine_mode mode;
+     enum machine_mode ATTRIBUTE_UNUSED mode;
 {
   int count = XVECLEN (op, 0);
   int i;
@@ -2085,7 +2279,7 @@ construct_restore_jr (op)
 
   /* Note, it is possible to have gaps in the register mask.
      We ignore this here, and generate a JR anyway.  We will
-     be popping more registers thatn is strictly necessary, but
+     be popping more registers than is strictly necessary, but
      it does save code space.  */
   
   if (first == last)
@@ -2102,7 +2296,7 @@ construct_restore_jr (op)
 int
 pattern_is_ok_for_prologue (op, mode)
      rtx op;
-     enum machine_mode mode;
+     enum machine_mode ATTRIBUTE_UNUSED mode;
 {
   int count = XVECLEN (op, 0);
   int i; 
@@ -2271,7 +2465,7 @@ construct_save_jarl (op)
 
   /* Note, it is possible to have gaps in the register mask.
      We ignore this here, and generate a JARL anyway.  We will
-     be pushing more registers thatn is strictly necessary, but
+     be pushing more registers than is strictly necessary, but
      it does save code space.  */
   
   if (first == last)
@@ -2283,3 +2477,577 @@ construct_save_jarl (op)
   return buff;
 }
 
+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. */
+void
+v850_output_aligned_bss (file, decl, name, size, align)
+     FILE * file;
+     tree decl;
+     char * name;
+     int size;
+     int align;
+{
+  ASM_GLOBALIZE_LABEL (file, name);
+  
+  switch (v850_get_data_area (decl))
+    {
+    case DATA_AREA_ZDA:
+      zbss_section ();
+      break;
+
+    case DATA_AREA_SDA:
+      sbss_section ();
+      break;
+
+    case DATA_AREA_TDA:
+      tdata_section ();
+      
+    default:
+      bss_section ();
+      break;
+    }
+  
+  ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
+#ifdef ASM_DECLARE_OBJECT_NAME
+  last_assemble_variable_decl = decl;
+  ASM_DECLARE_OBJECT_NAME (file, name, decl);
+#else
+  /* Standard thing is just output label for the object.  */
+  ASM_OUTPUT_LABEL (file, name);
+#endif /* ASM_DECLARE_OBJECT_NAME */
+  ASM_OUTPUT_SKIP (file, size ? size : 1);
+}
+
+/* Called via the macro ASM_OUTPUT_DECL_COMMON */
+void
+v850_output_common (file, decl, name, size, align)
+     FILE * file;
+     tree decl;
+     char * name;
+     int size;
+     int align;
+{
+  if (decl == NULL_TREE)
+    {
+      fprintf (file, "\t%s\t", COMMON_ASM_OP);
+    }
+  else
+    {
+      switch (v850_get_data_area (decl))
+       {
+       case DATA_AREA_ZDA:
+         fprintf (file, "\t%s\t", ZCOMMON_ASM_OP);
+         break;
+
+       case DATA_AREA_SDA:
+         fprintf (file, "\t%s\t", SCOMMON_ASM_OP);
+         break;
+
+       case DATA_AREA_TDA:
+         fprintf (file, "\t%s\t", TCOMMON_ASM_OP);
+         break;
+      
+       default:
+         fprintf (file, "\t%s\t", COMMON_ASM_OP);
+         break;
+       }
+    }
+  
+  assemble_name (file, name);
+  fprintf (file, ",%u,%u\n", size, align / BITS_PER_UNIT);
+}
+
+/* Called via the macro ASM_OUTPUT_DECL_LOCAL */
+void
+v850_output_local (file, decl, name, size, align)
+     FILE * file;
+     tree decl;
+     char * name;
+     int size;
+     int align;
+{
+  fprintf (file, "\t%s\t", 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)
+     tree decl;
+{
+  if (data_area_stack
+      && data_area_stack->data_area
+      && current_function_decl == NULL_TREE
+      && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONST_DECL)
+      && 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,
+     if this has not been done before.  */
+  
+  if (GHS_default_section_names [(int) GHS_SECTION_KIND_SDATA] == NULL)
+    {
+      GHS_default_section_names [(int) GHS_SECTION_KIND_SDATA]
+       = build_string (sizeof (".sdata")-1, ".sdata");
+
+      GHS_default_section_names [(int) GHS_SECTION_KIND_ROSDATA]
+       = build_string (sizeof (".rosdata")-1, ".rosdata");
+
+      GHS_default_section_names [(int) GHS_SECTION_KIND_TDATA]
+       = build_string (sizeof (".tdata")-1, ".tdata");
+      
+      GHS_default_section_names [(int) GHS_SECTION_KIND_ZDATA]
+       = build_string (sizeof (".zdata")-1, ".zdata");
+
+      GHS_default_section_names [(int) GHS_SECTION_KIND_ROZDATA]
+       = build_string (sizeof (".rozdata")-1, ".rozdata");
+    }
+  
+  if (current_function_decl == NULL_TREE
+      && (TREE_CODE (decl) == VAR_DECL
+         || TREE_CODE (decl) == CONST_DECL
+         || TREE_CODE (decl) == FUNCTION_DECL)
+      && (!DECL_EXTERNAL (decl) || DECL_INITIAL (decl))
+      && !DECL_SECTION_NAME (decl))
+    {
+      enum GHS_section_kind kind = GHS_SECTION_KIND_DEFAULT;
+      tree chosen_section;
+
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       kind = GHS_SECTION_KIND_TEXT;
+      else
+       {
+         /* First choose a section kind based on the data area of the decl. */
+         switch (v850_get_data_area (decl))
+           {
+           default:
+             abort ();
+             
+           case DATA_AREA_SDA:
+             kind = ((TREE_READONLY (decl))
+                     ? GHS_SECTION_KIND_ROSDATA
+                     : GHS_SECTION_KIND_SDATA);
+             break;
+             
+           case DATA_AREA_TDA:
+             kind = GHS_SECTION_KIND_TDATA;
+             break;
+             
+           case DATA_AREA_ZDA:
+             kind = ((TREE_READONLY (decl))
+                     ? GHS_SECTION_KIND_ROZDATA
+                     : GHS_SECTION_KIND_ZDATA);
+             break;
+             
+           case DATA_AREA_NORMAL:               /* default data area */
+             if (TREE_READONLY (decl))
+               kind = GHS_SECTION_KIND_RODATA;
+             else if (DECL_INITIAL (decl))
+               kind = GHS_SECTION_KIND_DATA;
+             else
+               kind = GHS_SECTION_KIND_BSS;
+           }
+       }
+
+      /* Now, if the section kind has been explicitly renamed,
+         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. */
+      if (chosen_section == NULL)
+        chosen_section = GHS_default_section_names [(int) kind];
+
+      if (chosen_section)
+       {
+         /* Only set the section name if specified by a pragma, because
+            otherwise it will force those variables to get allocated storage
+            in this module, rather than by the linker.  */
+         DECL_SECTION_NAME (decl) = chosen_section;
+       }
+    }
+}
index 2ccbe98..8a417f0 100644 (file)
@@ -20,6 +20,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 #include "svr4.h"      /* Automatically does #undef CPP_PREDEFINES */
+#include "gansidecl.h" /* For the PROTO macro  */
 
 #undef ASM_SPEC
 #define ASM_SPEC "%{mv*:-mv%*}"
@@ -78,7 +79,7 @@ extern int target_flags;
      * Doubles are normally 4 byte aligned, except in argument
      lists where they are 8 byte aligned.  Is the alignment
      in the argument list based on the first parameter,
-     first stack parameter, etc., etc.
+     first stack parameter, etc etc.
 
      * Passing/returning of large structures probably isn't the same
      as GHS.  We don't have enough documentation on their conventions
@@ -112,21 +113,27 @@ extern int target_flags;
    An empty string NAME is used to identify the default VALUE.  */
 
 #define TARGET_SWITCHES                                                        \
-  {{ "ghs",                     MASK_GHS },                            \
-   { "no-ghs",                 -MASK_GHS },                            \
-   { "long-calls",              MASK_LONG_CALLS },                     \
-   { "no-long-calls",          -MASK_LONG_CALLS },                     \
-   { "ep",                      MASK_EP },                             \
-   { "no-ep",                  -MASK_EP },                             \
-   { "prolog-function",                 MASK_PROLOG_FUNCTION },                \
-   { "no-prolog-function",     -MASK_PROLOG_FUNCTION },                \
-   { "space",                   MASK_EP | MASK_PROLOG_FUNCTION },      \
-   { "debug",                   MASK_DEBUG },                          \
-   { "v850",                    MASK_V850 },                           \
-   { "v850",                    -(MASK_V850 ^ MASK_CPU) },             \
-   { "big-switch",              MASK_BIG_SWITCH },                     \
+  {{ "ghs",                     MASK_GHS, "Support Green Hills ABI" }, \
+   { "no-ghs",                 -MASK_GHS, "" },                        \
+   { "long-calls",              MASK_LONG_CALLS,                       \
+                                       "Prohibit PC relative function calls" },\
+   { "no-long-calls",          -MASK_LONG_CALLS, "" },                 \
+   { "ep",                      MASK_EP,                               \
+                                "Reuse r30 on a per function basis" },  \
+   { "no-ep",                  -MASK_EP, "" },                         \
+   { "prolog-function",                 MASK_PROLOG_FUNCTION,                  \
+                                       "Use stubs for function prologues" },   \
+   { "no-prolog-function",     -MASK_PROLOG_FUNCTION, "" },            \
+   { "space",                   MASK_EP | MASK_PROLOG_FUNCTION,        \
+                                       "Same as: -mep -mprolog-function" },    \
+   { "debug",                   MASK_DEBUG, "Enable backend debugging" }, \
+   { "v850",                    MASK_V850,                             \
+                                "Compile for the v850 processor" },    \
+   { "v850",                    -(MASK_V850 ^ MASK_CPU), "" },         \
+   { "big-switch",              MASK_BIG_SWITCH,                       \
+                                       "Use 4 byte entries in switch tables" },\
    EXTRA_SWITCHES                                                      \
-   { "",                        TARGET_DEFAULT}}
+   { "",                        TARGET_DEFAULT, ""}}
 
 #ifndef EXTRA_SWITCHES
 #define EXTRA_SWITCHES
@@ -176,12 +183,15 @@ extern struct small_memory_info small_memory[(int)SMALL_MEMORY_max];
 
 #define TARGET_OPTIONS                                                 \
 {                                                                      \
-  { "tda=",    &small_memory[ (int)SMALL_MEMORY_TDA ].value },         \
-  { "tda-",    &small_memory[ (int)SMALL_MEMORY_TDA ].value },         \
-  { "sda=",    &small_memory[ (int)SMALL_MEMORY_SDA ].value },         \
-  { "sda-",    &small_memory[ (int)SMALL_MEMORY_SDA ].value },         \
-  { "zda=",    &small_memory[ (int)SMALL_MEMORY_ZDA ].value },         \
-  { "zda-",    &small_memory[ (int)SMALL_MEMORY_ZDA ].value },         \
+  { "tda=",    &small_memory[ (int)SMALL_MEMORY_TDA ].value,           \
+      "Set the max size of data eligible for the TDA area"  },         \
+  { "tda-",    &small_memory[ (int)SMALL_MEMORY_TDA ].value, "" },     \
+  { "sda=",    &small_memory[ (int)SMALL_MEMORY_SDA ].value,           \
+      "Set the max size of data eligible for the SDA area"  },         \
+  { "sda-",    &small_memory[ (int)SMALL_MEMORY_SDA ].value, "" },     \
+  { "zda=",    &small_memory[ (int)SMALL_MEMORY_ZDA ].value,           \
+      "Set the max size of data eligible for the ZDA area"  },         \
+  { "zda-",    &small_memory[ (int)SMALL_MEMORY_ZDA ].value, "" },     \
 }
 
 /* Sometimes certain combinations of command options do not make
@@ -405,7 +415,8 @@ extern struct small_memory_info small_memory[(int)SMALL_MEMORY_max];
    For any two classes, it is very desirable that there be another
    class that represents their union.  */
    
-enum reg_class {
+enum reg_class
+{
   NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
 };
 
@@ -581,13 +592,14 @@ enum reg_class {
 
    Do not define this macro if it would be the same as
    `FRAME_POINTER_REGNUM'. */
+#undef  HARD_FRAME_POINTER_REGNUM 
 #define HARD_FRAME_POINTER_REGNUM 29
 
 /* Base register for access to arguments of the function.  */
 #define ARG_POINTER_REGNUM 33
 
 /* Register in which static-chain is passed to a function.  */
-#define STATIC_CHAIN_REGNUM 5
+#define STATIC_CHAIN_REGNUM 20
 
 /* Value should be nonzero if functions must have frame pointers.
    Zero means the frame pointer need not be set up (and parms
@@ -690,7 +702,6 @@ struct cum_arg { int nbytes; };
    NAMED is nonzero if this argument is a named parameter
     (otherwise it is an extra parameter matching an ellipsis).  */
 
-struct rtx_def *function_arg();
 #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
   function_arg (&CUM, MODE, TYPE, NAMED)
 
@@ -1035,17 +1046,29 @@ do {                                                                    \
    into an indirect call.  */
 #define NO_FUNCTION_CSE
 
+/* The four different data regions on the v850.  */
+typedef enum 
+{
+  DATA_AREA_NORMAL,
+  DATA_AREA_SDA,
+  DATA_AREA_TDA,
+  DATA_AREA_ZDA
+} v850_data_area;
+
 /* A list of names for sections other than the standard two, which are
    `in_text' and `in_data'.  You need not define this macro on a
    system with no other sections (that GCC needs to use).  */
 #undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_tdata, in_sdata, in_zdata, in_const, in_ctors, in_dtors
+#define EXTRA_SECTIONS in_tdata, in_sdata, in_zdata, in_const, in_ctors, \
+in_dtors, in_rozdata, in_rosdata, in_sbss, in_zbss, in_zcommon, in_scommon
 
 /* One or more functions to be defined in `varasm.c'.  These
    functions should do jobs analogous to those of `text_section' and
    `data_section', for your additional sections.  Do not define this
    macro if you do not define `EXTRA_SECTIONS'. */
 #undef EXTRA_SECTION_FUNCTIONS
+
+/* This could be done a lot more cleanly using ANSI C ... */
 #define EXTRA_SECTION_FUNCTIONS                                                \
 CONST_SECTION_FUNCTION                                                 \
 CTORS_SECTION_FUNCTION                                                 \
@@ -1062,6 +1085,26 @@ sdata_section ()                                                 \
 }                                                                      \
                                                                        \
 void                                                                   \
+rosdata_section ()                                                     \
+{                                                                      \
+  if (in_section != in_rosdata)                                                \
+    {                                                                  \
+      fprintf (asm_out_file, "%s\n", ROSDATA_SECTION_ASM_OP);          \
+      in_section = in_sdata;                                           \
+    }                                                                  \
+}                                                                      \
+                                                                       \
+void                                                                   \
+sbss_section ()                                                                \
+{                                                                      \
+  if (in_section != in_sbss)                                           \
+    {                                                                  \
+      fprintf (asm_out_file, "%s\n", SBSS_SECTION_ASM_OP);             \
+      in_section = in_sbss;                                            \
+    }                                                                  \
+}                                                                      \
+                                                                       \
+void                                                                   \
 tdata_section ()                                                       \
 {                                                                      \
   if (in_section != in_tdata)                                          \
@@ -1079,16 +1122,42 @@ zdata_section ()                                                        \
       fprintf (asm_out_file, "%s\n", ZDATA_SECTION_ASM_OP);            \
       in_section = in_zdata;                                           \
     }                                                                  \
+}                                                                      \
+                                                                       \
+void                                                                   \
+rozdata_section ()                                                     \
+{                                                                      \
+  if (in_section != in_rozdata)                                                \
+    {                                                                  \
+      fprintf (asm_out_file, "%s\n", ROZDATA_SECTION_ASM_OP);          \
+      in_section = in_rozdata;                                         \
+    }                                                                  \
+}                                                                      \
+                                                                       \
+void                                                                   \
+zbss_section ()                                                                \
+{                                                                      \
+  if (in_section != in_zbss)                                           \
+    {                                                                  \
+      fprintf (asm_out_file, "%s\n", ZBSS_SECTION_ASM_OP);             \
+      in_section = in_zbss;                                            \
+    }                                                                  \
 }
 
-#define TEXT_SECTION_ASM_OP "\t.section .text"
-#define DATA_SECTION_ASM_OP "\t.section .data"
-#define BSS_SECTION_ASM_OP "\t.section .bss"
+#define TEXT_SECTION_ASM_OP  "\t.section .text"
+#define DATA_SECTION_ASM_OP  "\t.section .data"
+#define BSS_SECTION_ASM_OP   "\t.section .bss"
 #define SDATA_SECTION_ASM_OP "\t.section .sdata,\"aw\""
-#define SBSS_SECTION_ASM_OP "\t.section .sbss,\"aw\""
+#define SBSS_SECTION_ASM_OP  "\t.section .sbss,\"aw\""
 #define ZDATA_SECTION_ASM_OP "\t.section .zdata,\"aw\""
-#define ZBSS_SECTION_ASM_OP "\t.section .zbss,\"aw\""
+#define ZBSS_SECTION_ASM_OP  "\t.section .zbss,\"aw\""
 #define TDATA_SECTION_ASM_OP "\t.section .tdata,\"aw\""
+#define ROSDATA_SECTION_ASM_OP "\t.section .rosdata,\"a\""
+#define ROZDATA_SECTION_ASM_OP "\t.section .rozdata,\"a\""
+
+#define SCOMMON_ASM_OP                ".scomm"
+#define ZCOMMON_ASM_OP                ".zcomm"
+#define TCOMMON_ASM_OP                ".tcomm"
 
 /* A C statement or statements to switch to the appropriate section
    for output of EXP.  You can assume that EXP is either a `VAR_DECL'
@@ -1099,18 +1168,48 @@ zdata_section ()                                                        \
 
    Do not define this macro if you put all read-only variables and
    constants in the read-only data section (usually the text section).  */
-#undef SELECT_SECTION
+#undef  SELECT_SECTION
 #define SELECT_SECTION(EXP, RELOC)                                     \
 do {                                                                   \
   if (TREE_CODE (EXP) == VAR_DECL)                                     \
     {                                                                  \
-      if (!TREE_READONLY (EXP) || TREE_SIDE_EFFECTS (EXP)              \
+      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))))                  \
-       data_section ();                                                \
+        is_const = FALSE;                                              \
       else                                                             \
-       const_section ();                                               \
+        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)                                                        \
+           const_section ();                                           \
+         else                                                          \
+           data_section ();                                            \
+         break;                                                        \
+        }                                                              \
     }                                                                  \
   else if (TREE_CODE (EXP) == STRING_CST)                              \
     {                                                                  \
@@ -1203,6 +1302,24 @@ do { char dstr[30];                                      \
 #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
   asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
 
+#undef  ASM_OUTPUT_ALIGNED_BSS 
+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+  v850_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+
+/* This says how to output the assembler to define a global
+   uninitialized, common symbol. */
+#undef  ASM_OUTPUT_ALIGNED_COMMON
+#undef  ASM_OUTPUT_COMMON
+#define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN) \
+     v850_output_common (FILE, DECL, NAME, SIZE, ALIGN)
+
+/* This says how to output the assembler to define a local
+   uninitialized symbol. */
+#undef  ASM_OUTPUT_ALIGNED_LOCAL
+#undef  ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
+     v850_output_local (FILE, DECL, NAME, SIZE, ALIGN)
+     
 /* This is how to output the definition of a user-level label named NAME,
    such as the label on a static function or variable NAME.  */
 
@@ -1266,7 +1383,7 @@ do { char dstr[30];                                       \
 /* Print an instruction operand X on file FILE.
    look in v850.c for details */
 
-#define PRINT_OPERAND(FILE, X, CODE)  print_operand(FILE,X,CODE)
+#define PRINT_OPERAND(FILE, X, CODE)  print_operand (FILE, X, CODE)
 
 #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
   ((CODE) == '.')
@@ -1377,15 +1494,69 @@ do { char dstr[30];                                     \
    is a valid machine specific attribute for DECL.
    The attributes in ATTRIBUTES have previously been assigned to DECL.  */
 #define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
-v850_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
+  v850_valid_machine_decl_attribute (DECL, IDENTIFIER, ARGS)
 
-/* Tell compiler we have {ZDA,TDA,SDA} small data regions */
-#define HAVE_ZDA 1
-#define HAVE_SDA 1
-#define HAVE_TDA 1
+/* A C statement that assigns default attributes to a newly created DECL.  */
+#define SET_DEFAULT_DECL_ATTRIBUTES(decl, attr) \
+     v850_set_default_decl_attr (decl)
 
 /* Tell compiler we want to support GHS pragmas */
-#define HANDLE_GHS_PRAGMA
+#define HANDLE_PRAGMA(get, unget, name) v850_handle_pragma (get, unget, name)
+
+enum v850_pragma_state
+{
+  V850_PS_START,
+  V850_PS_SHOULD_BE_DONE,
+  V850_PS_BAD,
+  V850_PS_MAYBE_SECTION_NAME,
+  V850_PS_EXPECTING_EQUALS,
+  V850_PS_EXPECTING_SECTION_ALIAS,
+  V850_PS_MAYBE_COMMA
+};
+
+enum v850_pragma_type
+{
+  V850_PT_UNKNOWN,
+  V850_PT_INTERRUPT,
+  V850_PT_SECTION,
+  V850_PT_START_SECTION,
+  V850_PT_END_SECTION
+};
+
+/* enum GHS_SECTION_KIND is an enumeration of the kinds of sections that
+   can appear in the "ghs section" pragma.  These names are used to index
+   into the GHS_default_section_names[] and GHS_current_section_names[]
+   that are defined in v850.c, and so the ordering of each must remain
+   consistant. 
+
+   These arrays give the default and current names for each kind of 
+   section defined by the GHS pragmas.  The current names can be changed
+   by the "ghs section" pragma.  If the current names are null, use 
+   the default names.  Note that the two arrays have different types.
+
+   For the *normal* section kinds (like .data, .text, etc.) we do not
+   want to explicitly force the name of these sections, but would rather
+   let the linker (or at least the back end) choose the name of the 
+   section, UNLESS the user has force a specific name for these section
+   kinds.  To accomplish this set the name in ghs_default_section_names
+   to null.  */
+
+enum GHS_section_kind
+{ 
+  GHS_SECTION_KIND_DEFAULT,
+
+  GHS_SECTION_KIND_TEXT,
+  GHS_SECTION_KIND_DATA, 
+  GHS_SECTION_KIND_RODATA,
+  GHS_SECTION_KIND_BSS,
+  GHS_SECTION_KIND_SDATA,
+  GHS_SECTION_KIND_ROSDATA,
+  GHS_SECTION_KIND_TDATA,
+  GHS_SECTION_KIND_ZDATA,
+  GHS_SECTION_KIND_ROZDATA,
+
+  COUNT_OF_GHS_SECTION_KINDS  /* must be last */
+};
 
 /* The assembler op to start the file.  */
 
@@ -1444,34 +1615,52 @@ do {                                                                    \
 { "register_is_ok_for_epilogue",{ REG }},                              \
 { "not_power_of_two_operand",  { CONST_INT }},
 
-extern void override_options ();
-extern void asm_file_start ();
-extern int function_arg_partial_nregs ();
-extern int const_costs ();
-extern void print_operand ();
-extern void print_operand_address ();
-extern char *output_move_double ();
-extern char *output_move_single ();
-extern int ep_operand ();
-extern int reg_or_0_operand ();
-extern int reg_or_int5_operand ();
-extern int call_address_operand ();
-extern int movsi_source_operand ();
-extern int power_of_two_operand ();
-extern int not_power_of_two_operand ();
-extern void v850_reorg ();
-extern int compute_register_save_size ();
-extern int compute_frame_size ();
-extern void expand_prologue ();
-extern void expand_epilogue ();
-extern void notice_update_cc ();
-extern int v850_valid_machine_decl_attribute ();
-extern int v850_interrupt_function_p ();
-
-extern int pattern_is_ok_for_prologue();
-extern int pattern_is_ok_for_epilogue();
-extern int register_is_ok_for_epilogue ();
-extern char *construct_save_jarl ();
-extern char *construct_restore_jr ();
-
-
+  /* Note, due to dependency and search path conflicts, prototypes
+     involving the FILE, rtx or tree types cannot be included here.
+     They are included at the start of v850.c  */
+  
+extern void   asm_file_start                ();
+extern void   print_operand                 ();
+extern void   print_operand_address         ();
+extern int    function_arg_partial_nregs    ();
+extern int    const_costs                   ();
+extern char * output_move_double            ();
+extern char * output_move_single            ();
+extern int    ep_memory_operand             ();
+extern int    reg_or_0_operand              ();
+extern int    reg_or_int5_operand           ();
+extern int    call_address_operand          ();
+extern int    movsi_source_operand          ();
+extern int    power_of_two_operand          ();
+extern int    not_power_of_two_operand      ();
+extern int    special_symbolref_operand     ();
+extern void   v850_reorg                    ();
+extern void   notice_update_cc              ();
+extern int    v850_valid_machine_decl_attribute ();
+extern int    v850_interrupt_function_p     ();
+extern int    pattern_is_ok_for_prologue    ();
+extern int    pattern_is_ok_for_epilogue    ();
+extern int    register_is_ok_for_epilogue   ();
+extern char * construct_save_jarl           ();
+extern char * construct_restore_jr          ();
+
+extern void   override_options              PROTO ((void));
+extern int    compute_register_save_size    PROTO ((long *));
+extern int    compute_frame_size            PROTO ((int, long *));
+extern void   expand_prologue               PROTO ((void));
+extern void   expand_epilogue               PROTO ((void));
+
+extern void   v850_output_aligned_bss       ();
+extern void   v850_output_common            ();
+extern void   v850_output_local             ();
+extern void   sdata_section                 PROTO ((void));
+extern void   rosdata_section               PROTO ((void));
+extern void   sbss_section                  PROTO ((void));
+extern void   tdata_section                 PROTO ((void));
+extern void   zdata_section                 PROTO ((void));
+extern void   rozdata_section               PROTO ((void));
+extern void   zbss_section                  PROTO ((void));
+extern int    v850_handle_pragma            PROTO ((int (*)(void), void (*)(int), char *));
+extern void   v850_encode_data_area         ();
+extern void   v850_set_default_decl_attr    ();
+extern v850_data_area v850_get_data_area    ();