This is the mail archive of the binutils@sourceware.cygnus.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Support for SPARC STT_REGISTER


Hi!

Sparcv9 ABI requires any object using %g2, %g3 registers and optionally also
%g6 and %g7 registers to announce this support by an STT_REGISTER symbol.
In assembler, the syntax looks like this:
	.register %g2, #scratch
	.register %g3, somesymbol
The first one bounds %g2 to symbol "" (st_name 0).
This information is then used in linking, where it is forbidden to link two
objects which both declare a particular register to a different symbol.
A shared object ought to have these symbols in the dynamic symbol section as
well, and .dynamic sections should contain DT_REGISTER to point into the
.dynsym to these declarations so that dynamic linker can check them quickly.
I have started writing support for all this, but am looking for opinions in
the middle of the implementation.
Basically it adds complexity not yet present in bfd elf linking code,
because
1) there maybe more symbol entries with the same name (one can have
%g2,%g3,%g6,%g7 all #scratch registers)
2) a STT_REGISTER is basically indexed by st_value (the register number),
not its name
3) for the .dynsym case the names should not be present in the .hash

I'd like to hear what you think how to support this. The patch below does
everything but the dynamic sections (but does not honour stripping of the
.symtab STT_REGISTER entries yet). As the symbols can have identical names,
I'm not storing them into the symbol hash table, but I wonder whether it
would be better to force them into the hash table eventhough they have
identical names as most of elflink.h just traverses those hash tables.

--- ./bfd/bfd-in2.h.jj	Tue Jun 29 10:46:31 1999
+++ ./bfd/bfd-in2.h	Wed Jun 30 12:37:16 1999
@@ -2312,6 +2312,9 @@ typedef struct symbol_cache_entry
           others someday.  */
 #define BSF_OBJECT        0x10000
 
+	/* Processor specific symbol type.  */
+#define BSF_PROC	  0x20000
+
   flagword flags;
 
         /* A pointer to the section to which this symbol is
--- ./bfd/elf.c.jj	Tue Jun 29 10:47:02 1999
+++ ./bfd/elf.c	Wed Jun 30 15:00:22 1999
@@ -756,8 +756,24 @@ bfd_elf_print_symbol (abfd, filep, symbo
     case bfd_print_symbol_all:
       {
 	CONST char *section_name;
+	CONST char *name = NULL;
+	struct elf_backend_data *bed;
+	
 	section_name = symbol->section ? symbol->section->name : "(*none*)";
-	bfd_print_symbol_vandf ((PTR) file, symbol);
+
+	if (symbol->flags & BSF_PROC)
+	  {
+	    bed = get_elf_backend_data (abfd);
+	    if (bed->elf_backend_print_symbol_all)
+	      name = (*bed->elf_backend_print_symbol_all) (abfd, filep, symbol);
+	  }
+
+	if (name == NULL)
+	  {
+	    name = symbol->name;  
+	    bfd_print_symbol_vandf ((PTR) file, symbol);
+	  }
+
 	fprintf (file, " %s\t", section_name);
 	/* Print the "other" value for a symbol.  For common symbols,
 	   we've already printed the size; now print the alignment.
@@ -825,7 +841,7 @@ bfd_elf_print_symbol (abfd, filep, symbo
 		   ((unsigned int)
 		    ((elf_symbol_type *) symbol)->internal_elf_sym.st_other));
 
-	fprintf (file, " %s", symbol->name);
+	fprintf (file, " %s", name);
       }
       break;
     }
@@ -3982,6 +3998,25 @@ swap_out_syms (abfd, sttp, relocatable_p
 	  }
 
 	type_ptr = elf_symbol_from (abfd, syms[idx]);
+	
+	if ((flags & BSF_PROC) && type_ptr)
+	  {
+	    /* We don't know much about this symbol, so copy it
+	       as is.  */
+	    unsigned long name = sym.st_name;
+	    int bind = STB_LOCAL;
+
+	    sym = type_ptr->internal_elf_sym;
+	    sym.st_name = name;
+	    if (flags & BSF_GLOBAL)
+	      bind = STB_GLOBAL;
+	    else if (flags & BSF_WEAK)
+	      bind = STB_WEAK;
+	    sym.st_info = ELF_ST_INFO (bind, ELF_ST_TYPE (sym.st_info));
+	    bed->s->swap_symbol_out (abfd, &sym, (PTR) outbound_syms);
+	    outbound_syms += bed->s->sizeof_sym;	    
+	    continue;
+	  }
 
 	if ((flags & BSF_SECTION_SYM) == 0
 	    && bfd_is_com_section (syms[idx]->section))
--- ./bfd/elfcode.h.jj	Tue Jun 29 10:47:12 1999
+++ ./bfd/elfcode.h	Wed Jun 30 15:02:48 1999
@@ -1137,6 +1137,13 @@ elf_slurp_symbol_table (abfd, symptrs, d
 	    case STT_OBJECT:
 	      sym->symbol.flags |= BSF_OBJECT;
 	      break;
+	    case STT_LOPROC:
+	    case STT_LOPROC+1:
+	    case STT_HIPROC:
+	      sym->symbol.flags |= BSF_PROC;
+	      if (ELF_ST_BIND (i_sym.st_info) == STB_GLOBAL)
+		sym->symbol.flags |= BSF_GLOBAL;
+	      break;
 	    }
 
 	  if (dynamic)
--- ./bfd/elflink.h.jj	Tue Jun 29 10:47:22 1999
+++ ./bfd/elflink.h	Sat Jul  3 21:43:13 1999
@@ -4064,6 +4064,18 @@ elf_bfd_final_link (abfd, info)
   if (eoinfo.failed)
     return false;
 
+  /* If backend needs to output some symbols not present in the hash
+     table, do it now.  */
+  if (bed->elf_backend_output_arch_syms)
+    {
+      if (! (*bed->elf_backend_output_arch_syms)
+	      (info, (PTR) &finfo,
+	       (boolean (*) PARAMS ((PTR, const char *,
+	                    Elf_Internal_Sym *, asection *)))
+	       elf_link_output_sym))
+	return false;
+    }      
+
   /* Flush all symbols to the file.  */
   if (! elf_link_flush_output_syms (&finfo))
     return false;
--- ./bfd/elf-bfd.h.jj	Tue Jun 29 10:46:50 1999
+++ ./bfd/elf-bfd.h	Sat Jul  3 21:41:12 1999
@@ -517,6 +517,16 @@ struct elf_backend_data
   void (*elf_backend_post_process_headers)
     PARAMS ((bfd *, struct bfd_link_info *));
 
+  /* This function, if defined, prints a BSF_PROC symbol to file
+     and returns the name of the symbol to be printed.  */
+  const char *(*elf_backend_print_symbol_all)
+    PARAMS ((bfd *, PTR, asymbol *));
+
+  boolean (*elf_backend_output_arch_syms)
+    PARAMS ((struct bfd_link_info *, PTR,
+	    boolean (*) PARAMS ((PTR, const char *,
+             Elf_Internal_Sym *, asection *))));
+
   /* The swapping table to use when dealing with ECOFF information.
      Used for the MIPS ELF .mdebug section.  */
   const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap;
--- ./bfd/elfxx-target.h.jj	Wed Jun  9 09:51:35 1999
+++ ./bfd/elfxx-target.h	Sat Jul  3 21:07:17 1999
@@ -294,6 +294,12 @@ Foundation, Inc., 59 Temple Place - Suit
 #ifndef elf_backend_post_process_headers
 #define elf_backend_post_process_headers	NULL
 #endif
+#ifndef elf_backend_print_symbol_all
+#define elf_backend_print_symbol_all		NULL
+#endif
+#ifndef elf_backend_output_arch_syms
+#define elf_backend_output_arch_syms		NULL
+#endif
 
 /* Previously, backends could only use SHT_REL or SHT_RELA relocation
    sections, but not both.  They defined USE_REL to indicate SHT_REL
@@ -366,6 +372,8 @@ static CONST struct elf_backend_data elf
   elf_backend_gc_mark_hook,
   elf_backend_gc_sweep_hook,
   elf_backend_post_process_headers,
+  elf_backend_print_symbol_all,
+  elf_backend_output_arch_syms,
   elf_backend_ecoff_debug_swap,
   ELF_MACHINE_ALT1,
   ELF_MACHINE_ALT2,
--- ./bfd/elf64-sparc.c.jj	Tue Jun 29 10:47:08 1999
+++ ./bfd/elf64-sparc.c	Sun Jul  4 17:28:42 1999
@@ -32,6 +32,9 @@ Foundation, Inc., 59 Temple Place - Suit
 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
 #define MINUS_ONE (~ (bfd_vma) 0)
 
+static struct bfd_link_hash_table * sparc64_elf_bfd_link_hash_table_create
+  PARAMS((bfd *));
+
 static reloc_howto_type *sparc64_elf_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
 static void sparc64_elf_info_to_howto
@@ -53,6 +56,9 @@ static boolean sparc64_elf_size_dynamic_
   PARAMS((bfd *, struct bfd_link_info *));
 static boolean sparc64_elf_adjust_dynindx
   PARAMS((struct elf_link_hash_entry *, PTR));
+static boolean sparc64_elf_add_symbol_hook
+  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+	  const char **, flagword *, asection **, bfd_vma *));
 
 static boolean sparc64_elf_merge_private_bfd_data
   PARAMS ((bfd *, bfd *));
@@ -217,6 +223,52 @@ sparc64_elf_info_to_howto (abfd, cache_p
   cache_ptr->howto = &sparc64_elf_howto_table[ELF64_R_TYPE (dst->r_info)];
 }
 
+/* Sparc64 ELF linker hash table.  */
+
+struct sparc64_elf_app_reg
+{
+  unsigned char bind;
+  unsigned short shndx;
+  bfd *abfd;
+  char *name;
+};
+
+struct sparc64_elf_link_hash_table
+{
+  struct elf_link_hash_table root;
+
+  struct sparc64_elf_app_reg app_regs [4];
+};
+
+/* Get the Sparc64 ELF linker hash table from a link_info structure.  */
+
+#define sparc64_elf_hash_table(p) \
+  ((struct sparc64_elf_link_hash_table *) ((p)->hash))
+  
+/* Create a Sparc64 ELF linker hash table.  */
+
+static struct bfd_link_hash_table *
+sparc64_elf_bfd_link_hash_table_create (abfd)
+     bfd *abfd;
+{
+  struct sparc64_elf_link_hash_table *ret;
+
+  ret = ((struct sparc64_elf_link_hash_table *)
+	 bfd_zalloc (abfd, sizeof (struct sparc64_elf_link_hash_table)));
+  if (ret == (struct sparc64_elf_link_hash_table *) NULL)
+    return NULL;
+
+  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
+				       _bfd_elf_link_hash_newfunc))
+    {
+      bfd_release (abfd, ret);
+      return NULL;
+    }
+
+  return &ret->root.root;
+}
+
+
 /* Utility for performing the standard initial work of an instruction
    relocation.
    *PRELOCATION will contain the relocated item.
@@ -817,6 +869,148 @@ sparc64_elf_check_relocs (abfd, info, se
   return true;
 }
 
+/* Hook called by the linker routine which adds symbols from an object
+   file.  We use it for STT_REGISTER symbols.  */
+
+static boolean
+sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     const Elf_Internal_Sym *sym;
+     const char **namep;
+     flagword *flagsp;
+     asection **secp;
+     bfd_vma *valp;
+{
+  if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
+    {
+      int reg;
+      struct sparc64_elf_app_reg *p;
+      
+      *flagsp |= BSF_PROC;
+      if (ELF_ST_BIND (sym->st_info) == STB_GLOBAL)
+	*flagsp |= BSF_GLOBAL;
+	
+      reg = (int)sym->st_value;
+      switch (reg & ~1)
+	{
+	case 2: reg -= 2; break;
+	case 6: reg -= 4; break;
+	default:
+          (*_bfd_error_handler)
+            (_("%s: Only registers %%g[2367] can be declared using STT_REGISTER"),
+             bfd_get_filename (abfd));
+	  return false;
+	}
+
+      if (info->hash->creator != abfd->xvec)
+        {
+	  *namep = NULL;
+	  return true;
+        }
+
+      p = sparc64_elf_hash_table(info)->app_regs + reg;
+
+      if (p->name != NULL && strcmp (p->name, *namep))
+	{
+          (*_bfd_error_handler)
+            (_("Register %%g%d used incompatibly: "
+               "previously declared in %s to %s, in %s redefined to %s"),
+             (int)sym->st_value,
+             bfd_get_filename (p->abfd), *p->name ? p->name : "#scratch",
+             bfd_get_filename (abfd), **namep ? *namep : "#scratch");
+	  return false;
+	}
+
+      if ((abfd->flags & DYNAMIC) != 0)
+	{
+	  /* If STT_REGISTER comes from a dynamic object, don't put it into
+	     the output bfd.  The dynamic linker will recheck it.  */
+	  *namep = NULL;
+	  return true;
+	}
+
+      if (p->name == NULL)
+	{
+	  if (**namep)
+	    {
+	      struct elf_link_hash_entry *h;
+	      
+	      h = (struct elf_link_hash_entry *)
+		bfd_link_hash_lookup (info->hash, *namep, false, false, false);
+
+	      if (h != NULL)
+		{
+		  static char *stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
+		  unsigned char type = h->type;
+
+		  if (type > STT_FUNC) type = 0;
+		  (*_bfd_error_handler)
+		    (_("Symbol `%s' has differing types: "
+		       "previously %s, REGISTER in %s"),
+		     *namep, stt_types [type], bfd_get_filename (abfd));
+		  return false;
+		}
+
+	      p->name = bfd_hash_allocate (&info->hash->table,
+					   strlen (*namep) + 1);
+	      if (!p->name)
+		return false;
+
+	      strcpy (p->name, *namep);
+	    }
+	  else
+	    p->name = "";
+	  p->bind = ELF_ST_BIND (sym->st_info);
+	  p->abfd = abfd;
+	  p->shndx = sym->st_shndx;
+	}
+      else
+	{
+	  if (p->bind == STB_WEAK
+	      && ELF_ST_BIND (sym->st_info) == STB_GLOBAL)
+	    {
+	      p->bind = STB_GLOBAL;
+	      p->abfd = abfd;
+	    }
+	}
+      *namep = NULL;
+      return true;
+    }
+  return true;
+}
+
+/* This function takes care of emmiting STT_REGISTER symbols
+   which we cannot easily keep in the symbol hash table.  */
+static boolean
+sparc64_elf_output_arch_syms (info, finfo, func)
+     struct bfd_link_info *info;
+     PTR finfo;
+     boolean (*func) PARAMS ((PTR, const char *,
+			      Elf_Internal_Sym *, asection *));
+{
+  int reg;
+  struct sparc64_elf_app_reg *app_regs =
+    sparc64_elf_hash_table(info)->app_regs;
+  Elf_Internal_Sym sym;
+  
+  for (reg = 0; reg < 4; reg++)
+    if (app_regs [reg].name != NULL)
+      {
+	sym.st_value = reg < 2 ? reg + 2 : reg + 4;
+	sym.st_size = 0;
+	sym.st_other = 0;
+	sym.st_info = ELF_ST_INFO (app_regs [reg].bind, STT_REGISTER);
+	sym.st_shndx = app_regs [reg].shndx;
+	if (! (*func) (finfo, app_regs [reg].name, &sym,
+		       sym.st_shndx == SHN_ABS
+			 ? bfd_abs_section_ptr : bfd_und_section_ptr))
+	  return false;
+      }
+
+  return true;
+}                               
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -2210,7 +2404,34 @@ sparc64_elf_merge_private_bfd_data (ibfd
     }
   return true;
 }
+
+/* Print a STT_REGISTER symbol to file FILE.  */
 
+static const char *
+sparc64_elf_print_symbol_all (abfd, filep, symbol)
+     bfd *abfd;
+     PTR filep;
+     asymbol *symbol;
+{
+  FILE *file = (FILE *) filep;
+  int reg, type;
+  
+  if (ELF_ST_TYPE (((elf_symbol_type *) symbol)->internal_elf_sym.st_info)
+      != STT_REGISTER)
+    return NULL;
+
+  reg = ((elf_symbol_type *) symbol)->internal_elf_sym.st_value;
+  type = symbol->flags;
+  fprintf (file, "REG_%c%c%11s%c%c    R", "GOLI" [reg / 8], '0' + (reg & 7), "",
+		 ((type & BSF_LOCAL)
+		  ? (type & BSF_GLOBAL) ? '!' : 'l'
+  	          : (type & BSF_GLOBAL) ? 'g' : ' '),
+  	         (type & BSF_WEAK) ? 'w' : ' ');
+  if (symbol->name == NULL || symbol->name [0] == '\0')
+    return "#scratch";
+  else
+    return symbol->name;
+}
 
 /* Set the right machine number for a SPARC64 ELF file.  */
 
@@ -2236,6 +2457,9 @@ sparc64_elf_object_p (abfd)
 /* This is the value that we used before the ABI was released.  */
 #define ELF_MACHINE_ALT1 EM_OLD_SPARCV9
 
+#define bfd_elf64_bfd_link_hash_table_create \
+  sparc64_elf_bfd_link_hash_table_create
+  
 #define elf_info_to_howto \
   sparc64_elf_info_to_howto
 #define bfd_elf64_bfd_reloc_type_lookup \
@@ -2243,6 +2467,8 @@ sparc64_elf_object_p (abfd)
 
 #define elf_backend_create_dynamic_sections \
   _bfd_elf_create_dynamic_sections
+#define elf_backend_add_symbol_hook \
+  sparc64_elf_add_symbol_hook
 #define elf_backend_check_relocs \
   sparc64_elf_check_relocs
 #define elf_backend_adjust_dynamic_symbol \
@@ -2255,6 +2481,10 @@ sparc64_elf_object_p (abfd)
   sparc64_elf_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
   sparc64_elf_finish_dynamic_sections
+#define elf_backend_print_symbol_all \
+  sparc64_elf_print_symbol_all
+#define elf_backend_output_arch_syms \
+  sparc64_elf_output_arch_syms
 
 #define bfd_elf64_bfd_merge_private_bfd_data \
   sparc64_elf_merge_private_bfd_data
--- ./binutils/readelf.c.jj	Tue Jun 29 10:48:20 1999
+++ ./binutils/readelf.c	Fri Jul  2 15:44:56 1999
@@ -414,6 +414,8 @@ guess_is_rela (e_machine)
       
       /* Targets that use RELA relocations.  */
     case EM_68K:
+    case EM_SPARC32PLUS:
+    case EM_SPARCV9:
     case EM_SPARC:
     case EM_PPC:
     case EM_CYGNUS_V850:
@@ -1062,6 +1064,29 @@ get_machine_flags (e_flags, e_machine)
 	  if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
 	    strcat (buf, ", mips4");
 	  break;
+
+	case EM_SPARCV9:
+	  if (e_flags & EF_SPARC_32PLUS)
+	    strcat (buf, ", v8+");
+
+	  if (e_flags & EF_SPARC_SUN_US1)
+	    strcat (buf, ", ultrasparc");
+
+	  if (e_flags & EF_SPARC_HAL_R1)
+	    strcat (buf, ", halr1");
+
+	  if (e_flags & EF_SPARC_LEDATA)
+	    strcat (buf, ", ledata");
+
+	  if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_TSO)
+	    strcat (buf, ", tso");
+
+	  if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_PSO)
+	    strcat (buf, ", pso");
+
+	  if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_RMO)
+	    strcat (buf, ", rmo");
+	  break;
 	}
     }
 
@@ -3393,6 +3418,9 @@ get_symbol_type (type)
 	{
 	  if (elf_header.e_machine == EM_ARM && type == STT_ARM_TFUNC)
 	    return _("THUMB_FUNC");
+	    
+	  if (elf_header.e_machine == EM_SPARCV9 && type == STT_REGISTER)
+	    return _("REGISTER");
 	  
 	  sprintf (buff, _("<processor specific>: %d"), type);
 	}
--- ./gas/config/tc-sparc.c.jj	Tue Jun 29 10:49:38 1999
+++ ./gas/config/tc-sparc.c	Sat Jul  3 18:31:35 1999
@@ -87,6 +87,10 @@ static int warn_on_bump;
    architecture, issue a warning.  */
 static enum sparc_opcode_arch_val warn_after_architecture;
 
+/* Non-zero if as should generate error if an undeclared g[23] register
+   has been used in -64.  */
+static int no_undeclared_regs;
+
 /* Non-zero if we are generating PIC code.  */
 int sparc_pic_code;
 
@@ -97,6 +101,9 @@ extern int target_big_endian;
 
 static int target_little_endian_data;
 
+/* Symbols for global registers on v9.  */
+static symbolS *globals[8];
+
 /* V9 and 86x have big and little endian data, but instructions are always big
    endian.  The sparclet has bi-endian support but both data and insns have
    the same endianness.  Global `target_big_endian' is used for data.
@@ -119,6 +126,7 @@ static void s_common PARAMS ((int));
 static void s_empty PARAMS ((int));
 static void s_uacons PARAMS ((int));
 static void s_ncons PARAMS ((int));
+static void s_register PARAMS ((int));
 
 const pseudo_typeS md_pseudo_table[] =
 {
@@ -143,6 +151,7 @@ const pseudo_typeS md_pseudo_table[] =
   {"2byte", s_uacons, 2},
   {"4byte", s_uacons, 4},
   {"8byte", s_uacons, 8},
+  {"register", s_register, 0},
 #endif
   {NULL, 0, 0},
 };
@@ -400,6 +409,10 @@ struct option md_longopts[] = {
   {"enforce-aligned-data", no_argument, NULL, OPTION_ENFORCE_ALIGNED_DATA},
 #define OPTION_LITTLE_ENDIAN_DATA (OPTION_MD_BASE + 11)
   {"little-endian-data", no_argument, NULL, OPTION_LITTLE_ENDIAN_DATA},
+#ifdef OBJ_ELF
+#define OPTION_NO_UNDECLARED_REGS (OPTION_MD_BASE + 12)
+  {"no-undeclared-regs", no_argument, NULL, OPTION_NO_UNDECLARED_REGS},
+#endif
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof(md_longopts);
@@ -549,6 +562,10 @@ md_parse_option (c, arg)
       else
 	sparc_pic_code = 1;
       break;
+
+    case OPTION_NO_UNDECLARED_REGS:
+      no_undeclared_regs = 1;
+      break;
 #endif
 
     default:
@@ -1865,6 +1882,11 @@ sparc_ip (str, pinsn)
 		      goto error;
 		    }
 
+		  if ((mask & ~1) == 2 && sparc_arch_size == 64
+		      && no_undeclared_regs && ! globals [mask])
+		    as_bad (_("detected global register use not "
+			      "covered by .register pseudo-op"));
+
 		  /* Got the register, now figure out where
 		     it goes in the opcode.  */
 		  switch (*args)
@@ -3677,6 +3699,87 @@ s_ncons (bytes)
 {
   cons (sparc_arch_size == 32 ? 4 : 8);
 }
+
+#ifdef OBJ_ELF
+/* Handle the SPARC ELF .register pseudo-op.  This sets the binding of a
+   global register.
+   The syntax is:
+   
+   .register %g[2367],{#scratch|symbolname}
+   */
+
+static void
+s_register (ignore)
+     int ignore;
+{
+  char c;
+  int reg;
+  int flags;
+  const char *regname;
+
+  if (input_line_pointer[0] != '%'
+      || input_line_pointer[1] != 'g'
+      || ((input_line_pointer[2] & ~1) != '2'
+	  && (input_line_pointer[2] & ~1) != '6')
+      || input_line_pointer[3] != ',')
+    as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname}"));
+  reg = input_line_pointer[2] - '0';
+  input_line_pointer += 4;
+
+  if (*input_line_pointer == '#')
+    {
+      ++input_line_pointer;
+      regname = input_line_pointer;
+      c = get_symbol_end ();
+      if (strcmp (regname, "scratch"))
+	as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname}"));
+      regname = "";
+    }
+  else
+    {
+      regname = input_line_pointer;
+      c = get_symbol_end ();
+    }
+  if (sparc_arch_size == 64)
+    {
+      if (globals [reg])
+	{
+	  if (strcmp (S_GET_NAME (globals [reg]), regname))
+	    as_bad (_("redefinition of global register"));
+	}
+      else
+	{
+	  if (*regname)
+	    {
+	      if (symbol_find (regname))
+		as_bad (_("Register symbol %s already defined."), regname);
+	    }
+	  globals [reg] = symbol_make (regname);
+	  flags = symbol_get_bfdsym (globals [reg])->flags;
+	  flags |= BSF_PROC;
+	  if (! *regname)
+	    flags = flags & ~(BSF_GLOBAL|BSF_LOCAL|BSF_WEAK);
+	  if (! (flags & (BSF_GLOBAL|BSF_LOCAL|BSF_WEAK)))
+	    flags |= BSF_GLOBAL;
+	  symbol_get_bfdsym (globals [reg])->flags = flags;
+	  S_SET_VALUE (globals [reg], (valueT)reg);
+	  S_SET_ALIGN (globals [reg], reg);
+	  S_SET_SIZE (globals [reg], 0);
+	  S_SET_SEGMENT (globals [reg], absolute_section);
+	  S_SET_OTHER (globals [reg], 0);
+	  elf_symbol (symbol_get_bfdsym (globals [reg]))
+	    ->internal_elf_sym.st_info =
+	      ELF_ST_INFO(STB_GLOBAL, STT_REGISTER);
+	  elf_symbol (symbol_get_bfdsym (globals [reg]))
+	    ->internal_elf_sym.st_shndx = SHN_UNDEF;
+	}
+    }
+
+  *input_line_pointer = c;
+
+  demand_empty_rest_of_line ();
+}
+#endif
 
 /* If the --enforce-aligned-data option is used, we require .word,
    et. al., to be aligned correctly.  We do it by setting up an
--- ./gas/doc/c-sparc.texi.jj	Mon May  3 09:28:45 1999
+++ ./gas/doc/c-sparc.texi	Sat Jul  3 18:38:25 1999
@@ -145,11 +145,24 @@ syntax is different.
 @item .half
 This is functionally identical to @code{.short}.
 
+@cindex @code{nword} directive, SPARC
+@item .nword
+On the Sparc, the @code{.nword} directive produces native word sized value,
+ie. if assembling with -32 it is equivalent to @code{.word}, if assembling
+with -64 it is equivalent to @code{.xword}.
+
 @cindex @code{proc} directive, SPARC
 @item .proc
 This directive is ignored.  Any text following it on the same
 line is also ignored.
 
+@cindex @code{register} directive, SPARC
+@item .register
+This directive declares use of a global application or system register.
+It must be followed by a register name %g2, %g3, %g6 or %g7, comma and
+the symbol name for that register or @code{#scratch} if it is a scratch
+register.
+
 @cindex @code{reserve} directive, SPARC
 @item .reserve
 This must be followed by a symbol name, a positive number, and
@@ -176,4 +189,3 @@ instead of the 16 bit values it produces
 On the Sparc V9 processor, the @code{.xword} directive produces
 64 bit values.
 @end table
-


Cheers,
    Jakub
___________________________________________________________________
Jakub Jelinek | jj@sunsite.mff.cuni.cz | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
UltraLinux  |  http://ultra.linux.cz/  |  http://ultra.penguin.cz/
Linux version 2.2.10 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]