fix for pr1371: heed fx_offset in pcrel relocs

This commit is contained in:
Ken Raeburn
1992-08-01 23:20:55 +00:00
parent 3dfa6cfb66
commit 680227f309
2 changed files with 1607 additions and 1421 deletions

View File

@ -1,3 +1,8 @@
Sat Aug 1 19:10:13 1992 Ken Raeburn (raeburn@cygnus.com)
* config/tc-sparc.c (tc_aout_fix_to_chars): If pc-relative, take
fx_offset into account.
Fri Jul 31 21:53:28 1992 Ken Raeburn (raeburn@cygnus.com)
* configure.in (mips host): Accept "ultrix" with version number.

View File

@ -55,17 +55,17 @@ extern void s_globl(), s_long(), s_short(), s_space(), cons();
extern void s_align_bytes(), s_ignore();
const pseudo_typeS md_pseudo_table[] = {
{ "align", s_align_bytes, 0 }, /* Defaulting is invalid (0) */
{ "common", s_common, 0 },
{ "global", s_globl, 0 },
{ "half", cons, 2 },
{ "optim", s_ignore, 0 },
{ "proc", s_proc, 0 },
{ "reserve", s_reserve, 0 },
{ "seg", s_seg, 0 },
{ "skip", s_space, 0 },
{ "word", cons, 4 },
{ NULL, 0, 0 },
{ "align", s_align_bytes, 0 }, /* Defaulting is invalid (0) */
{ "common", s_common, 0 },
{ "global", s_globl, 0 },
{ "half", cons, 2 },
{ "optim", s_ignore, 0 },
{ "proc", s_proc, 0 },
{ "reserve", s_reserve, 0 },
{ "seg", s_seg, 0 },
{ "skip", s_space, 0 },
{ "word", cons, 4 },
{ NULL, 0, 0 },
};
const int md_short_jump_size = 4;
@ -105,11 +105,11 @@ static unsigned char octal[256];
struct sparc_it {
char *error;
unsigned long opcode;
struct nlist *nlistp;
expressionS exp;
int pcrel;
enum reloc_type reloc;
unsigned long opcode;
struct nlist *nlistp;
expressionS exp;
int pcrel;
enum reloc_type reloc;
} the_insn, set_insn;
#if __STDC__ == 1
@ -343,6 +343,39 @@ static void s_proc() {
return;
} /* s_proc() */
/* start-sanitize-v9 */
#ifndef NO_V9
struct priv_reg_entry { char *name; int regnum; };
struct priv_reg_entry priv_reg_table[] =
{
{ "tpc", 0 },
{ "tnpc", 1 },
{ "tstate", 2 },
{ "tt", 3 },
{ "tick", 4 },
{ "tba", 5 },
{ "pstate", 6 },
{ "tl", 7 },
{ "pil", 8 },
{ "cwp", 9 },
{ "cansave", 10 },
{ "canrestore", 11 },
{ "cleanwin", 12 },
{ "otherwin", 13 },
{ "wstate", 14},
{ "fpq", 15},
{ "ver", 31 },
{ "", -1 }, /* end marker */
};
static int cmp_reg_entry (p, q)
struct priv_reg_entry *p, *q;
{
return strcmp (q->name, p->name);
}
#endif
/* end-sanitize-v9 */
/* This function is called once, at assembler startup time. It should
set up all the tables, etc. that the MD part of the assembler will need. */
void md_begin() {
@ -385,6 +418,13 @@ void md_begin() {
toHex[i] = i + 10 - 'a';
for (i = 'A'; i <= 'F'; ++i)
toHex[i] = i + 10 - 'A';
/* start-sanitize-v9 */
#ifndef NO_V9
qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]),
sizeof (priv_reg_table[0]), cmp_reg_entry);
#endif
/* end-sanitize-v9 */
} /* md_begin() */
void md_end() {
@ -392,7 +432,7 @@ void md_end() {
} /* md_end() */
void md_assemble(str)
char *str;
char *str;
{
char *toP;
int rsd;
@ -473,7 +513,7 @@ void md_assemble(str)
} /* md_assemble() */
static void sparc_ip(str)
char *str;
char *str;
{
char *error_message = "";
char *s;
@ -526,6 +566,115 @@ static void sparc_ip(str)
for (args = insn->args; ; ++args) {
switch (*args) {
/* start-sanitize-v9 */
#ifndef NO_V9
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;
while (ok == 1)
{
int lo = 0, hi = 0;
if (*s == '#')
{
s += 1;
if (! (lo = (s[0] == 'S')))
ok = (s[0] == 'L');
if (! (hi = (s[1] == 'S')))
ok = (s[1] == 'L');
mask |= (1 << ((hi<<1) | lo));
s += 2;
}
else
{
/* Parse a number, somehow. */
ok = 0;
}
if (s[2] != '|')
break;
}
if (! ok)
{
error_message = "unrecognizable mmask";
goto error;
}
opcode |= SIMM13(mask);
continue;
}
case '*':
/* Parse a prefetch function. */
if (*s == '#')
{
int prefetch_fcn = 0;
s += 1;
if (! strncmp (s, "n_reads", 7))
prefetch_fcn = 0, s += 7;
else if (! strncmp (s, "one_read", 8))
prefetch_fcn = 1, s += 8;
else if (! strncmp (s, "n_writes", 8))
prefetch_fcn = 2, s += 8;
else if (! strncmp (s, "one_write", 9))
prefetch_fcn = 3, s += 9;
else if (! strncmp (s, "page", 4))
prefetch_fcn = 4, s += 4;
else
{
error_message = "unrecognizable prefetch fucntion";
goto error;
}
}
else
{
/* Parse a number, somehow. */
error_message = "unrecognizable prefetch fucntion";
goto error;
}
continue;
case '!':
case '?':
/* Parse a privileged register. */
if (*s == '%')
{
struct priv_reg_entry *p = priv_reg_table;
int len;
s += 1;
while (p->name[0] > s[0])
p++;
while (p->name[0] == s[0])
{
len = strlen (p->name);
if (strncmp (p->name, s, len) == 0)
break;
p++;
}
if (p->name[0] != s[0])
{
error_message = "unrecognizable privileged register";
goto error;
}
if (*args == '?')
opcode |= (p->regnum << 14);
else
opcode |= (p->regnum << 25);
s += len;
continue;
}
else
{
error_message = "unrecognizable privileged register";
goto error;
}
#endif
/* end-sanitize-v9 */
case 'M':
case 'm':
if (strncmp(s, "%asr", 4) == 0) {
@ -1120,6 +1269,22 @@ static void sparc_ip(str)
}
break;
/* start-sanitize-v9 */
#ifndef NO_V9
case 's':
if (strncmp (s, "%usr", 4) != 0)
break;
s += 4;
continue;
case 'o':
if (strncmp (s, "%asi", 4) != 0)
break;
s += 4;
continue;
#endif /* NO_V9 */
/* end-sanitize-v9 */
case 't':
if (strncmp(s, "%tbr", 4) != 0)
break;
@ -1157,8 +1322,19 @@ static void sparc_ip(str)
}
} else {
if (insn->architecture > current_architecture) {
if (!architecture_requested || warn_on_bump) {
if ((!architecture_requested || warn_on_bump)
&&
/* start-sanitize-v9 */
#ifndef NO_V9
! ARCHITECTURES_CONFLICT_P (current_architecture,
insn->architecture)
#else
/* end-sanitize-v9 */
1
/* start-sanitize-v9 */
#endif
/* end-sanitize-v9 */
) {
if (warn_on_bump) {
as_warn("architecture bumped from \"%s\" to \"%s\" on \"%s\"",
architecture_pname[current_architecture],
@ -1185,7 +1361,7 @@ static void sparc_ip(str)
} /* sparc_ip() */
static int getExpression(str)
char *str;
char *str;
{
char *save_in;
segT seg;
@ -1229,9 +1405,9 @@ static int getExpression(str)
#define MAX_LITTLENUMS 6
char *md_atof(type,litP,sizeP)
char type;
char *litP;
int *sizeP;
char type;
char *litP;
int *sizeP;
{
int prec;
LITTLENUM_TYPE words[MAX_LITTLENUMS];
@ -1284,9 +1460,9 @@ char *md_atof(type,litP,sizeP)
* Write out big-endian.
*/
void md_number_to_chars(buf,val,n)
char *buf;
long val;
int n;
char *buf;
long val;
int n;
{
switch(n) {
@ -1310,8 +1486,8 @@ void md_number_to_chars(buf,val,n)
hold. */
void md_apply_fix(fixP, val)
fixS *fixP;
long val;
fixS *fixP;
long val;
{
char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
@ -1475,11 +1651,11 @@ void md_apply_fix(fixP, val)
/* should never be called for sparc */
void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
char *ptr;
long from_addr;
long to_addr;
fragS *frag;
symbolS *to_symbol;
char *ptr;
long from_addr;
long to_addr;
fragS *frag;
symbolS *to_symbol;
{
as_fatal("sparc_create_short_jmp\n");
} /* md_create_short_jump() */
@ -1491,7 +1667,8 @@ void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
bit 7 as external, bits 6 & 5 unused, and the lower
five bits as relocation type. Next 4 bytes are long addend. */
/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
void
tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
char *where;
fixS *fixP;
relax_addressT segment_address_in_file;
@ -1503,7 +1680,7 @@ void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
know(fixP->fx_addsy);
if ((S_GET_TYPE(fixP->fx_addsy)) == N_UNDF) {
if (!S_IS_DEFINED(fixP->fx_addsy)) {
r_extern = 1;
r_index = fixP->fx_addsy->sy_number;
} else {
@ -1528,7 +1705,7 @@ void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
}
if (fixP->fx_pcrel) {
r_addend -= r_address;
r_addend += fixP->fx_offset - r_address;
} else {
r_addend = fixP->fx_addnumber;
}
@ -1540,26 +1717,26 @@ void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
/* should never be called for sparc */
void md_convert_frag(headers, fragP)
object_headers *headers;
register fragS *fragP;
object_headers *headers;
register fragS *fragP;
{
as_fatal("sparc_convert_frag\n");
} /* md_convert_frag() */
/* should never be called for sparc */
void md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
char *ptr;
long from_addr, to_addr;
fragS *frag;
symbolS *to_symbol;
char *ptr;
long from_addr, to_addr;
fragS *frag;
symbolS *to_symbol;
{
as_fatal("sparc_create_long_jump\n");
} /* md_create_long_jump() */
/* should never be called for sparc */
int md_estimate_size_before_relax(fragP, segtype)
fragS *fragP;
segT segtype;
fragS *fragP;
segT segtype;
{
as_fatal("sparc_estimate_size_before_relax\n");
return(1);
@ -1568,7 +1745,7 @@ int md_estimate_size_before_relax(fragP, segtype)
#if 0
/* for debugging only */
static void print_insn(insn)
struct sparc_it *insn;
struct sparc_it *insn;
{
char *Reloc[] = {
"RELOC_8",
@ -1637,8 +1814,8 @@ static void print_insn(insn)
*/
#if defined(OBJ_AOUT) || defined(OBJ_BOUT)
void emit_sparc_reloc(fixP, segment_address_in_file)
register fixS *fixP;
relax_addressT segment_address_in_file;
register fixS *fixP;
relax_addressT segment_address_in_file;
{
struct reloc_info_generic ri;
register symbolS *symbolP;
@ -1690,7 +1867,7 @@ void emit_sparc_reloc(fixP, segment_address_in_file)
* -bump
* Warn on architecture bumps. See also -A.
*
* -Av6, -Av7, -Av8
* -Av6, -Av7, -Av8, -Asparclite
* Select the architecture. Instructions or features not
* supported by the selected architecture cause fatal errors.
*
@ -1708,14 +1885,18 @@ void emit_sparc_reloc(fixP, segment_address_in_file)
* architecture starts at the specified level, but bumps are
* warnings.
*
* start-sanitize-v9
* Bumping between incompatible architectures is always an
* error. For example, from sparclite to v9.
* end-sanitize-v9
*/
/* start-sanitize-v9 */
/* There is also a -Av9 architecture option. xoxorich. */
/* end-sanitize-v9 */
int md_parse_option(argP, cntP, vecP)
char **argP;
int *cntP;
char ***vecP;
char **argP;
int *cntP;
char ***vecP;
{
char *p;
const char **arch;
@ -1751,7 +1932,7 @@ int md_parse_option(argP, cntP, vecP)
/* ARGSUSED */
symbolS *md_undefined_symbol(name)
char *name;
char *name;
{
return 0;
} /* md_undefined_symbol() */
@ -1762,14 +1943,14 @@ symbolS *md_undefined_symbol(name)
/* ARGSUSED */
void md_operand(expressionP)
expressionS *expressionP;
expressionS *expressionP;
{
} /* md_operand() */
/* Round up a section size to the appropriate boundary. */
long md_section_align (segment, size)
segT segment;
long size;
segT segment;
long size;
{
return (size + 7) & ~7; /* Round all sects to multiple of 8 */
} /* md_section_align() */
@ -1779,13 +1960,13 @@ long md_section_align (segment, size)
its size. This gets us to the following instruction.
(??? Is this right? FIXME-SOON) */
long md_pcrel_from(fixP)
fixS *fixP;
fixS *fixP;
{
return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
} /* md_pcrel_from() */
void tc_aout_pre_write_hook(headers)
object_headers *headers;
object_headers *headers;
{
H_SET_VERSION(headers, 1);
return;