mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 03:29:47 +08:00
fix for pr1371: heed fx_offset in pcrel relocs
This commit is contained in:
@ -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.
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user