aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>1999-07-30 21:39:53 +0000
committerRichard Henderson <rth@redhat.com>1999-07-30 21:39:53 +0000
commit6d8809aa625bfe3e0cc7a5558b37240c74c623a9 (patch)
tree6ce3648023e7e8539d89ae091351c4b96a3ca7cd /gas
parent587ff49e9a50b61e86ea78ba3271f3ca24c1b0e8 (diff)
downloadgdb-6d8809aa625bfe3e0cc7a5558b37240c74c623a9.zip
gdb-6d8809aa625bfe3e0cc7a5558b37240c74c623a9.tar.gz
gdb-6d8809aa625bfe3e0cc7a5558b37240c74c623a9.tar.bz2
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.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog11
-rw-r--r--gas/config/tc-sparc.c139
-rw-r--r--gas/config/tc-sparc.h4
-rw-r--r--gas/doc/c-sparc.texi7
4 files changed, 159 insertions, 2 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index eea3d40..244750c 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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
diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c
index 1bced29..40bbc49 100644
--- a/gas/config/tc-sparc.c
+++ b/gas/config/tc-sparc.c
@@ -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
diff --git a/gas/config/tc-sparc.h b/gas/config/tc-sparc.h
index 5df81b7..bf7b6f9 100644
--- a/gas/config/tc-sparc.h
+++ b/gas/config/tc-sparc.h
@@ -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
diff --git a/gas/doc/c-sparc.texi b/gas/doc/c-sparc.texi
index adbe299..ab54eb2 100644
--- a/gas/doc/c-sparc.texi
+++ b/gas/doc/c-sparc.texi
@@ -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