Jakub Jelinek <jj@ultra.linux.cz>
authorRichard Henderson <rth@redhat.com>
Fri, 30 Jul 1999 21:39:53 +0000 (21:39 +0000)
committerRichard Henderson <rth@redhat.com>
Fri, 30 Jul 1999 21:39:53 +0000 (21:39 +0000)
        * config/tc-sparc.c (md_longopts): Add --no-undeclared-regs option.
        (sparc_ip): Warn if %g2 or %g3 register is used and not covered
        by .register pseudo-op if -64 and --no-undeclared-regs.
        (s_register, sparc_adjust_symtab): New functions.
        * config/tc-sparc.h (tc_adjust_symtab, sparc_adjust_symtab):
        Declare sparc_adjust_symtab as tc_adjust_symtab.
        * doc/c-sparc.texi: Add description of #ignore special literal
        for .register pseudo-op.

gas/ChangeLog
gas/config/tc-sparc.c
gas/config/tc-sparc.h
gas/doc/c-sparc.texi

index eea3d4069b18224817db5e3bf1baf31252c9f9c8..244750cb96af2a060638335f3d243b3684fc8816 100644 (file)
@@ -1,3 +1,14 @@
+1999-07-30  Jakub Jelinek  <jj@ultra.linux.cz>
+
+       * config/tc-sparc.c (md_longopts): Add --no-undeclared-regs option.
+       (sparc_ip): Warn if %g2 or %g3 register is used and not covered
+       by .register pseudo-op if -64 and --no-undeclared-regs.
+       (s_register, sparc_adjust_symtab): New functions.
+       * config/tc-sparc.h (tc_adjust_symtab, sparc_adjust_symtab):
+       Declare sparc_adjust_symtab as tc_adjust_symtab.
+       * doc/c-sparc.texi: Add description of #ignore special literal
+       for .register pseudo-op.
+
 1999-07-30  Catherine Moore  <clm@cygnus.com>
 
        * config/tc-arm.c (tc_gen_reloc):  Record the vtable entry in
index 1bced2942f6538b8a0d3f34eb5e590d0be6dfea1..40bbc4927ec94e7a1b30b9462fa868c7c2423e90 100644 (file)
@@ -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)
@@ -3707,6 +3729,123 @@ 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|#ignore}
+   */
+
+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|#ignore}"));
+  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") && strcmp (regname, "ignore"))
+       as_bad (_("register syntax is .register %%g[2367],{#scratch|symbolname|#ignore}"));
+      if (regname [0] == 'i')
+       regname = NULL;
+      else
+       regname = "";
+    }
+  else
+    {
+      regname = input_line_pointer;
+      c = get_symbol_end ();
+    }
+  if (sparc_arch_size == 64)
+    {
+      if (globals [reg])
+       {
+         if ((regname && globals [reg] != (symbolS *)1
+              && strcmp (S_GET_NAME (globals [reg]), regname))
+             || ((regname != NULL) ^ (globals [reg] != (symbolS *)1)))
+           as_bad (_("redefinition of global register"));
+       }
+      else
+       {
+         if (regname == NULL)
+           globals [reg] = (symbolS *)1;
+         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;
+             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);
+             /* Although we actually want undefined_section here,
+                we have to use absolute_section, because otherwise
+                generic as code will make it a COM section.
+                We fix this up in sparc_adjust_symtab.  */
+             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 ();
+}
+
+/* Adjust the symbol table.  We set undefined sections for STT_REGISTER
+   symbols which need it.  */
+   
+void
+sparc_adjust_symtab ()
+{
+  symbolS *sym;
+     
+  for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
+    {
+      if (ELF_ST_TYPE (elf_symbol (symbol_get_bfdsym (sym))
+                      ->internal_elf_sym.st_info) != STT_REGISTER)
+       continue;
+
+      if (ELF_ST_TYPE (elf_symbol (symbol_get_bfdsym (sym))
+                      ->internal_elf_sym.st_shndx != SHN_UNDEF))
+       continue;
+
+      S_SET_SEGMENT (sym, undefined_section);
+    }
+}
+#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
    rs_align_code frag, and checking in HANDLE_ALIGN to make sure that
index 5df81b743310ea990e4edfd8a1dadf9648335e93..bf7b6f93a29d4e9fa58720c79223243f7463b704 100644 (file)
@@ -139,6 +139,10 @@ extern int elf32_sparc_force_relocation PARAMS ((struct fix *));
           && (S_GET_SEGMENT ((FIX)->fx_subsy)                          \
               == S_GET_SEGMENT ((FIX)->fx_addsy)))                     \
        || S_IS_LOCAL ((FIX)->fx_addsy)))
+
+/* Finish up the entire symtab.  */
+#define tc_adjust_symtab() sparc_adjust_symtab ()
+extern void sparc_adjust_symtab PARAMS ((void));
 #endif
 
 #ifdef OBJ_AOUT
index adbe29956a018453ad36175c4b665189349baf25..ab54eb2d8895aa62f9d1a5d2e8f9b392da2415e8 100644 (file)
@@ -160,8 +160,11 @@ line is also ignored.
 @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.
+the symbol name for that register.  If symbol name is @code{#scratch},
+it is a scratch register, if it is @code{#ignore}, it just surpresses any
+errors about using undeclared global register, but does not emit any
+information about it into the object file.  This can be useful e.g. if you
+save the register before use and restore it after.
 
 @cindex @code{reserve} directive, SPARC
 @item .reserve