(tc_gen_reloc): Handle BFD_RELOC_SPARC_WDISP22 relocation.

(s_local) [OBJ_ELF]: New function.
(md_pseudo_table) [OBJ_ELF]: Call it for "local".
(s_common): Rearrange to handle Solaris .common pseudo, which may sometimes use
bss space instead of common.
(md_parse_option) [OBJ_ELF]: Print version id for -V.  Ignore -Q and -s options
for now.
This commit is contained in:
Ken Raeburn 1993-06-25 09:51:47 +00:00
parent a32ebcfd6b
commit ed9638af53

View file

@ -43,6 +43,8 @@ static enum sparc_architecture current_architecture = v6;
static int architecture_requested; static int architecture_requested;
static int warn_on_bump; static int warn_on_bump;
extern int target_big_endian;
const relax_typeS md_relax_table[1]; const relax_typeS md_relax_table[1];
/* handle of the OPCODE hash table */ /* handle of the OPCODE hash table */
@ -50,7 +52,7 @@ static struct hash_control *op_hash = NULL;
static void s_seg (), s_proc (), s_data1 (), s_reserve (), s_common (); static void s_seg (), s_proc (), s_data1 (), s_reserve (), s_common ();
extern void s_globl (), s_long (), s_short (), s_space (), cons (); extern void s_globl (), s_long (), s_short (), s_space (), cons ();
extern void s_align_bytes (), s_ignore (); extern void s_align_bytes (), s_ignore (), s_local();
/* start-sanitize-v9 */ /* start-sanitize-v9 */
#ifndef NO_V9 #ifndef NO_V9
static void s_xword (); static void s_xword ();
@ -78,6 +80,9 @@ const pseudo_typeS md_pseudo_table[] =
{"common", s_common, 0}, {"common", s_common, 0},
{"global", s_globl, 0}, {"global", s_globl, 0},
{"half", cons, 2}, {"half", cons, 2},
#ifdef OBJ_ELF
{"local", s_local, 0},
#endif
{"optim", s_ignore, 0}, {"optim", s_ignore, 0},
{"proc", s_proc, 0}, {"proc", s_proc, 0},
{"reserve", s_reserve, 0}, {"reserve", s_reserve, 0},
@ -294,14 +299,45 @@ s_reserve ()
#endif #endif
} }
#ifdef OBJ_ELF
/* Currently used only by Solaris 2. */
void
s_local ()
{
char *name;
int c;
symbolS *symbolP;
do
{
name = input_line_pointer;
c = get_symbol_end ();
symbolP = symbol_find_or_make (name);
*input_line_pointer = c;
SKIP_WHITESPACE ();
S_CLEAR_EXTERNAL (symbolP);
symbolP->local = 1;
if (c == ',')
{
input_line_pointer++;
SKIP_WHITESPACE ();
if (*input_line_pointer == '\n')
c = '\n';
}
}
while (c == ',');
demand_empty_rest_of_line ();
}
#endif
static void static void
s_common () s_common ()
{ {
register char *name; char *name;
register char c; char c;
register char *p; char *p;
register int temp; int temp, size;
register symbolS *symbolP; symbolS *symbolP;
name = input_line_pointer; name = input_line_pointer;
c = get_symbol_end (); c = get_symbol_end ();
@ -322,6 +358,7 @@ s_common ()
ignore_rest_of_line (); ignore_rest_of_line ();
return; return;
} }
size = temp;
*p = 0; *p = 0;
symbolP = symbol_find_or_make (name); symbolP = symbol_find_or_make (name);
*p = c; *p = c;
@ -333,27 +370,24 @@ s_common ()
} }
if (S_GET_VALUE (symbolP) != 0) if (S_GET_VALUE (symbolP) != 0)
{ {
if (S_GET_VALUE (symbolP) != temp) if (S_GET_VALUE (symbolP) != size)
{ {
as_warn ("Length of .comm \"%s\" is already %d. Not changed to %d.", as_warn ("Length of .comm \"%s\" is already %d. Not changed to %d.",
S_GET_NAME (symbolP), S_GET_VALUE (symbolP), temp); S_GET_NAME (symbolP), S_GET_VALUE (symbolP), size);
} }
} }
else else
{ {
S_SET_VALUE (symbolP, temp); #ifndef OBJ_ELF
S_SET_VALUE (symbolP, size);
S_SET_EXTERNAL (symbolP); S_SET_EXTERNAL (symbolP);
#ifdef OBJ_ELF
/* But not for a.out ... find some sensible way to characterize
this. */
S_SET_SEGMENT (symbolP, now_seg);
#endif #endif
} }
know (symbolP->sy_frag == &zero_address_frag); know (symbolP->sy_frag == &zero_address_frag);
#ifdef OBJ_ELF #ifdef OBJ_ELF
if (*input_line_pointer != ',') if (*input_line_pointer != ',')
{ {
as_bad ("Expected command (and alignment) after common length"); as_bad ("Expected comma and alignment after common length");
ignore_rest_of_line (); ignore_rest_of_line ();
return; return;
} }
@ -369,7 +403,34 @@ s_common ()
temp = 0; temp = 0;
as_warn ("Common alignment negative; 0 assumed"); as_warn ("Common alignment negative; 0 assumed");
} }
record_alignment (S_GET_SEGMENT (symbolP), temp); if (symbolP->local)
{
segT old_sec = now_seg;
int old_subsec = now_subseg;
char *p;
int align = temp;
record_alignment (bss_section, align);
subseg_set (bss_section, 0);
if (align)
frag_align (align, 0);
if (S_GET_SEGMENT (symbolP) == bss_section)
symbolP->sy_frag->fr_symbol = 0;
symbolP->sy_frag = frag_now;
p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
(char *) 0);
*p = 0;
S_SET_SEGMENT (symbolP, bss_section);
S_CLEAR_EXTERNAL (symbolP);
subseg_set (old_sec, old_subsec);
}
else
{
S_SET_VALUE (symbolP, size);
S_SET_EXTERNAL (symbolP);
/* should be common, but this is how gas does it for now */
S_SET_SEGMENT (symbolP, &bfd_und_section);
}
#else #else
if (strncmp (input_line_pointer, ",\"bss\"", 6) != 0 if (strncmp (input_line_pointer, ",\"bss\"", 6) != 0
&& strncmp (input_line_pointer, ",\"data\"", 7) != 0) && strncmp (input_line_pointer, ",\"data\"", 7) != 0)
@ -482,6 +543,26 @@ struct priv_reg_entry priv_reg_table[] =
{"", -1}, /* end marker */ {"", -1}, /* end marker */
}; };
struct membar_masks
{
char *name;
int len;
int mask;
};
#define MEMBAR_MASKS_SIZE 7
struct membar_masks membar_masks[MEMBAR_MASKS_SIZE] =
{
{"Sync", 4, 0x40},
{"MemIssue", 8, 0x20},
{"Lookaside", 9, 0x10},
{"StoreStore", 10, 0x08},
{"LoadStore", 9, 0x04},
{"StoreLoad", 9, 0x02},
{"LoadLoad", 8, 0x01},
};
static int static int
cmp_reg_entry (p, q) cmp_reg_entry (p, q)
struct priv_reg_entry *p, *q; struct priv_reg_entry *p, *q;
@ -547,6 +628,8 @@ md_begin ()
sizeof (priv_reg_table[0]), cmp_reg_entry); sizeof (priv_reg_table[0]), cmp_reg_entry);
#endif #endif
/* end-sanitize-v9 */ /* end-sanitize-v9 */
target_big_endian = 1;
} /* md_begin() */ } /* md_begin() */
void void
@ -709,36 +792,50 @@ sparc_ip (str)
#ifndef NO_V9 #ifndef NO_V9
case 'K': case 'K':
{ {
/* Load is 0; Store is 1.
We compute the mask based on the values
we find in S. OK is set set
if we see something we don't like. */
int ok = 1;
int mask = 0; int mask = 0;
while (ok == 1) int i;
/* Parse a series of masks. */
if (*s == '#')
{ {
int lo = 0, hi = 0; while (*s == '#')
if (*s == '#')
{ {
s += 1; ++s;
if (!(lo = (s[0] == 'S'))) for (i = 0; i < MEMBAR_MASKS_SIZE; i++)
ok = (s[0] == 'L'); if (!strncmp (s, membar_masks[i].name,
if (!(hi = (s[1] == 'S'))) membar_masks[i].len))
ok = (s[1] == 'L'); break;
mask |= (1 << ((hi << 1) | lo)); if (i < MEMBAR_MASKS_SIZE)
s += 2; {
mask |= membar_masks[i].mask;
s += membar_masks[i].len;
}
else
{
error_message = ": invalid membar mask name";
goto error;
}
if (*s == '|')
++s;
} }
else
{
/* Parse a number, somehow. */
ok = 0;
}
if (s[2] != '|')
break;
} }
if (!ok) else if (isdigit (*s))
{ {
error_message = "unrecognizable mmask"; while (isdigit (*s))
{
mask = mask * 10 + *s - '0';
++s;
}
if (mask < 0 || mask > 127)
{
error_message = ": invalid membar mask number";
goto error;
}
}
else
{
error_message = ": unrecognizable membar mask";
goto error; goto error;
} }
opcode |= SIMM13 (mask); opcode |= SIMM13 (mask);
@ -746,35 +843,51 @@ sparc_ip (str)
} }
case '*': case '*':
/* Parse a prefetch function. */ {
if (*s == '#') int prefetch_fcn = 0;
{
int prefetch_fcn = 0;
s += 1; /* Parse a prefetch function. */
if (!strncmp (s, "n_reads", 7)) if (*s == '#')
prefetch_fcn = 0, s += 7; {
else if (!strncmp (s, "one_read", 8)) s += 1;
prefetch_fcn = 1, s += 8; if (!strncmp (s, "n_reads", 7))
else if (!strncmp (s, "n_writes", 8)) prefetch_fcn = 0, s += 7;
prefetch_fcn = 2, s += 8; else if (!strncmp (s, "one_read", 8))
else if (!strncmp (s, "one_write", 9)) prefetch_fcn = 1, s += 8;
prefetch_fcn = 3, s += 9; else if (!strncmp (s, "n_writes", 8))
else if (!strncmp (s, "page", 4)) prefetch_fcn = 2, s += 8;
prefetch_fcn = 4, s += 4; else if (!strncmp (s, "one_write", 9))
else prefetch_fcn = 3, s += 9;
{ else if (!strncmp (s, "page", 4))
error_message = "unrecognizable prefetch fucntion"; prefetch_fcn = 4, s += 4;
goto error; else
} {
} error_message = ": invalid prefetch function name";
else goto error;
{ }
/* Parse a number, somehow. */ }
error_message = "unrecognizable prefetch fucntion"; else if (isdigit (*s))
goto error; {
} while (isdigit (*s))
continue; {
prefetch_fcn = prefetch_fcn * 10 + *s - '0';
++s;
}
if (prefetch_fcn < 0 || prefetch_fcn > 31)
{
error_message = ": invalid prefetch function number";
goto error;
}
}
else
{
error_message = ": unrecognizable prefetch function";
goto error;
}
opcode |= RD (prefetch_fcn);
continue;
}
case '!': case '!':
case '?': case '?':
@ -796,7 +909,7 @@ sparc_ip (str)
} }
if (p->name[0] != s[0]) if (p->name[0] != s[0])
{ {
error_message = "unrecognizable privileged register"; error_message = ": unrecognizable privileged register";
goto error; goto error;
} }
if (*args == '?') if (*args == '?')
@ -808,7 +921,7 @@ sparc_ip (str)
} }
else else
{ {
error_message = "unrecognizable privileged register"; error_message = ": unrecognizable privileged register";
goto error; goto error;
} }
#endif #endif
@ -1491,6 +1604,9 @@ sparc_ip (str)
case 'A': case 'A':
{ {
/* start-sanitize-v9 */
#ifdef NO_V9
/* end-sanitize-v9 */
char *push = input_line_pointer; char *push = input_line_pointer;
expressionS e; expressionS e;
@ -1505,6 +1621,55 @@ sparc_ip (str)
} /* if absolute */ } /* if absolute */
break; break;
/* start-sanitize-v9 */
#else
int asi = 0;
/* Parse an asi. */
if (*s == '#')
{
s += 1;
if (!strncmp (s, "ASI_AIUP", 8))
asi = 0x10, s += 8;
else if (!strncmp (s, "ASI_AIUS", 8))
asi = 0x11, s += 8;
else if (!strncmp (s, "ASI_PNF", 7))
asi = 0x82, s += 7;
else if (!strncmp (s, "ASI_SNF", 7))
asi = 0x83, s += 7;
else if (!strncmp (s, "ASI_P", 5))
asi = 0x80, s += 5;
else if (!strncmp (s, "ASI_S", 5))
asi = 0x81, s += 5;
else
{
error_message = ": invalid asi name";
goto error;
}
}
else if (isdigit (*s))
{
char *push = input_line_pointer;
input_line_pointer = s;
asi = get_absolute_expression ();
s = input_line_pointer;
input_line_pointer = push;
if (asi < 0 || asi > 255)
{
error_message = ": invalid asi number";
goto error;
}
}
else
{
error_message = ": unrecognizable asi";
goto error;
}
opcode |= ASI (asi);
continue;
#endif
/* end-sanitize-v9 */
} /* alternate space */ } /* alternate space */
case 'p': case 'p':
@ -1748,8 +1913,8 @@ md_atof (type, litP, sizeP)
md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
litP += sizeof (LITTLENUM_TYPE); litP += sizeof (LITTLENUM_TYPE);
} }
return ""; /* Someone should teach Dean about null pointers */ return 0;
} /* md_atof() */ }
/* /*
* Write out big-endian. * Write out big-endian.
@ -2012,21 +2177,19 @@ tc_gen_reloc (section, fixp)
if (fixp->fx_pcrel == 0) if (fixp->fx_pcrel == 0)
reloc->addend = fixp->fx_addnumber; reloc->addend = fixp->fx_addnumber;
else else
#ifdef OBJ_ELF switch (OUTPUT_FLAVOR)
reloc->addend = 0; {
#else case bfd_target_elf_flavour:
reloc->addend = - reloc->address; reloc->addend = 0;
#endif break;
case bfd_target_aout_flavour:
reloc->addend = - reloc->address;
break;
default:
/* What's a good default here? Is there any?? */
abort ();
}
#if 0
printf ("addr %04x addend=%08x fx_pcrel=%d fx_addnumber=%08x\n",
reloc->address, reloc->addend, fixp->fx_pcrel, fixp->fx_addnumber);
if (fixp->fx_addsy->sy_frag)
printf ("\tsy_frag->fr_address=%08x sym=`%s'\n",
fixp->fx_addsy->sy_frag->fr_address,
fixp->fx_addsy->bsym->name);
#endif
switch (fixp->fx_r_type) switch (fixp->fx_r_type)
{ {
case BFD_RELOC_32: case BFD_RELOC_32:
@ -2034,6 +2197,7 @@ tc_gen_reloc (section, fixp)
case BFD_RELOC_LO10: case BFD_RELOC_LO10:
case BFD_RELOC_32_PCREL_S2: case BFD_RELOC_32_PCREL_S2:
case BFD_RELOC_SPARC_BASE13: case BFD_RELOC_SPARC_BASE13:
case BFD_RELOC_SPARC_WDISP22:
code = fixp->fx_r_type; code = fixp->fx_r_type;
break; break;
default: default:
@ -2265,6 +2429,22 @@ md_parse_option (argP, cntP, vecP)
architecture_requested = 1; architecture_requested = 1;
} }
} }
#ifdef OBJ_ELF
else if (**argP == 'V')
{
extern void print_version_id ();
print_version_id ();
}
else if (**argP == 'Q')
{
/* Qy - do emit .comment
Qn - do not emit .comment */
}
else if (**argP == 's')
{
/* use .stab instead of .stab.excl */
}
#endif
else else
{ {
/* Unknown option */ /* Unknown option */