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.
This commit is contained in:
parent
587ff49e9a
commit
6d8809aa62
4 changed files with 159 additions and 2 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue