* config/tc-mips.c (enum small_ex_type): Remove.
	(imm_unmatched_hi): Remove.
	(md_assemble): Remove use of imm_unmatched_hi.  Remove the last
	argument from calls to append_insn.
	(append_insn): Remove unmatched_hi parameter; check reloc_type[0]
	instead.
	(macro_build): Update append_insn calls.
	(mips16_macro_build, macro_build_lui): Likewise.
	(mips_ip): Rework handling of small expressions.  Move explicit
	relocation handling into my_getSmallExpression.  Assume that the
	value of 'o' operands is zero if there is only one bracketed
	expression left.
	(percent_op): Make constant.  Record the BFD relocation code
	associated with each operator.
	(my_getSmallParser, my_getPercentOp): Remove.
	(parse_relocation): New function.
	(my_getSamllExpression): Rework.  Fill in relocations here
	rather than in mips_ip.

gas/testsuite
	* gas/mips/elf-rel8.[sd], gas/mips/elf-rel9.[sd],
	gas/mips/elf-rel10.[sd], gas/mips/elf-rel11.[sd]: New tests.
	* gas/mips/mips.exp: Run elf-rel8 and elf-rel9 for all elf
	targets.  Run elf-rel10 and elf-rel11 for NewABI targets.
This commit is contained in:
Richard Sandiford 2003-02-02 19:37:20 +00:00
parent 5f601589e1
commit 5e0116d519
12 changed files with 544 additions and 372 deletions

View File

@ -1,3 +1,24 @@
2003-02-02 Richard Sandiford <rsandifo@redhat.com>
* config/tc-mips.c (enum small_ex_type): Remove.
(imm_unmatched_hi): Remove.
(md_assemble): Remove use of imm_unmatched_hi. Remove the last
argument from calls to append_insn.
(append_insn): Remove unmatched_hi parameter; check reloc_type[0]
instead.
(macro_build): Update append_insn calls.
(mips16_macro_build, macro_build_lui): Likewise.
(mips_ip): Rework handling of small expressions. Move explicit
relocation handling into my_getSmallExpression. Assume that the
value of 'o' operands is zero if there is only one bracketed
expression left.
(percent_op): Make constant. Record the BFD relocation code
associated with each operator.
(my_getSmallParser, my_getPercentOp): Remove.
(parse_relocation): New function.
(my_getSamllExpression): Rework. Fill in relocations here
rather than in mips_ip.
2003-01-29 Nick Clifton <nickc@redhat.com>
* config/tc-i386.c (line_comment_chars): Add '#'. This makes the

View File

@ -810,7 +810,7 @@ static void mips16_mark_labels
PARAMS ((void));
static void append_insn
PARAMS ((char *place, struct mips_cl_insn * ip, expressionS * p,
bfd_reloc_code_real_type *r, bfd_boolean));
bfd_reloc_code_real_type *r));
static void mips_no_prev_insn
PARAMS ((int));
static void mips_emit_delays
@ -856,12 +856,10 @@ static void mips16_ip
static void mips16_immed
PARAMS ((char *, unsigned int, int, offsetT, bfd_boolean, bfd_boolean,
bfd_boolean, unsigned long *, bfd_boolean *, unsigned short *));
static int my_getPercentOp
PARAMS ((char **, unsigned int *, int *));
static int my_getSmallParser
PARAMS ((char **, unsigned int *, int *));
static int my_getSmallExpression
PARAMS ((expressionS *, char *));
static bfd_boolean parse_relocation
PARAMS ((char **, bfd_reloc_code_real_type *));
static size_t my_getSmallExpression
PARAMS ((expressionS *, bfd_reloc_code_real_type *, char *));
static void my_getExpression
PARAMS ((expressionS *, char *));
#ifdef OBJ_ELF
@ -946,32 +944,6 @@ static int mips_need_elf_addend_fixup
PARAMS ((fixS *));
#endif
/* Return values of my_getSmallExpression(). */
enum small_ex_type
{
S_EX_NONE = 0,
S_EX_REGISTER,
/* Direct relocation creation by %percent_op(). */
S_EX_HALF,
S_EX_HI,
S_EX_LO,
S_EX_GP_REL,
S_EX_GOT,
S_EX_CALL16,
S_EX_GOT_DISP,
S_EX_GOT_PAGE,
S_EX_GOT_OFST,
S_EX_GOT_HI,
S_EX_GOT_LO,
S_EX_NEG,
S_EX_HIGHER,
S_EX_HIGHEST,
S_EX_CALL_HI,
S_EX_CALL_LO
};
/* Table and functions used to map between CPU/ISA names, and
ISA levels, and CPU numbers. */
@ -1136,10 +1108,6 @@ static bfd_reloc_code_real_type imm_reloc[3]
static bfd_reloc_code_real_type offset_reloc[3]
= {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
/* This is set by mips_ip if imm_reloc is an unmatched HI16_S reloc. */
static bfd_boolean imm_unmatched_hi;
/* These are set by mips16_ip if an explicit extension is used. */
static bfd_boolean mips16_small, mips16_ext;
@ -1430,7 +1398,6 @@ md_assemble (str)
= {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
imm_expr.X_op = O_absent;
imm_unmatched_hi = FALSE;
offset_expr.X_op = O_absent;
imm_reloc[0] = BFD_RELOC_UNUSED;
imm_reloc[1] = BFD_RELOC_UNUSED;
@ -1464,11 +1431,11 @@ md_assemble (str)
else
{
if (imm_expr.X_op != O_absent)
append_insn (NULL, &insn, &imm_expr, imm_reloc, imm_unmatched_hi);
append_insn (NULL, &insn, &imm_expr, imm_reloc);
else if (offset_expr.X_op != O_absent)
append_insn (NULL, &insn, &offset_expr, offset_reloc, FALSE);
append_insn (NULL, &insn, &offset_expr, offset_reloc);
else
append_insn (NULL, &insn, NULL, unused_reloc, FALSE);
append_insn (NULL, &insn, NULL, unused_reloc);
}
}
@ -1616,23 +1583,24 @@ mips16_mark_labels ()
used with RELOC_TYPE. */
static void
append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
append_insn (place, ip, address_expr, reloc_type)
char *place;
struct mips_cl_insn *ip;
expressionS *address_expr;
bfd_reloc_code_real_type *reloc_type;
bfd_boolean unmatched_hi;
{
register unsigned long prev_pinfo, pinfo;
char *f;
fixS *fixp[3];
int nops = 0;
bfd_boolean unmatched_reloc_p;
/* Mark instruction labels in mips16 mode. */
mips16_mark_labels ();
prev_pinfo = prev_insn.insn_mo->pinfo;
pinfo = ip->insn_mo->pinfo;
unmatched_reloc_p = FALSE;
if (place == NULL && (! mips_opts.noreorder || prev_nop_frag != NULL))
{
@ -2176,17 +2144,17 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
|| *reloc_type == BFD_RELOC_MIPS_RELGOT))
fixp[0]->fx_no_overflow = 1;
if (unmatched_hi)
if (reloc_type[0] == BFD_RELOC_HI16_S)
{
struct mips_hi_fixup *hi_fixup;
assert (*reloc_type == BFD_RELOC_HI16_S);
hi_fixup = ((struct mips_hi_fixup *)
xmalloc (sizeof (struct mips_hi_fixup)));
hi_fixup->fixp = fixp[0];
hi_fixup->seg = now_seg;
hi_fixup->next = mips_hi_fixup_list;
mips_hi_fixup_list = hi_fixup;
unmatched_reloc_p = TRUE;
}
if (reloc_type[1] != BFD_RELOC_UNUSED)
@ -2743,7 +2711,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
reloc does not become a variant frag. Otherwise, the
rearrangement of %hi relocs in frob_file may confuse
tc_gen_reloc. */
if (unmatched_hi)
if (unmatched_reloc_p)
{
frag_wane (frag_now);
frag_new (0);
@ -3140,7 +3108,7 @@ macro_build (place, counter, ep, name, fmt, va_alist)
va_end (args);
assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
append_insn (place, &insn, ep, r, FALSE);
append_insn (place, &insn, ep, r);
}
static void
@ -3266,7 +3234,7 @@ mips16_macro_build (place, counter, ep, name, fmt, args)
assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
append_insn (place, &insn, ep, r, FALSE);
append_insn (place, &insn, ep, r);
}
/*
@ -3356,10 +3324,10 @@ macro_build_lui (place, counter, ep, regnum)
if (*r == BFD_RELOC_UNUSED)
{
insn.insn_opcode |= high_expr.X_add_number;
append_insn (place, &insn, NULL, r, FALSE);
append_insn (place, &insn, NULL, r);
}
else
append_insn (place, &insn, &high_expr, r, FALSE);
append_insn (place, &insn, &high_expr, r);
}
/* Generate a sequence of instructions to do a load or store from a constant
@ -9065,122 +9033,70 @@ mips_ip (str, ip)
case 'i': /* 16 bit unsigned immediate */
case 'j': /* 16 bit signed immediate */
*imm_reloc = BFD_RELOC_LO16;
c = my_getSmallExpression (&imm_expr, s);
if (c != S_EX_NONE)
{
if (c != S_EX_LO)
{
if (c == S_EX_HI)
{
*imm_reloc = BFD_RELOC_HI16_S;
imm_unmatched_hi = TRUE;
}
#ifdef OBJ_ELF
else if (c == S_EX_HIGHEST)
*imm_reloc = BFD_RELOC_MIPS_HIGHEST;
else if (c == S_EX_HIGHER)
*imm_reloc = BFD_RELOC_MIPS_HIGHER;
else if (c == S_EX_GP_REL)
{
/* This occurs in NewABI only. */
c = my_getSmallExpression (&imm_expr, s);
if (c != S_EX_NEG)
as_bad (_("bad composition of relocations"));
else
{
c = my_getSmallExpression (&imm_expr, s);
if (c != S_EX_LO)
as_bad (_("bad composition of relocations"));
else
{
imm_reloc[0] = BFD_RELOC_GPREL16;
imm_reloc[1] = BFD_RELOC_MIPS_SUB;
imm_reloc[2] = BFD_RELOC_LO16;
}
}
}
#endif
else
*imm_reloc = BFD_RELOC_HI16;
}
else if (imm_expr.X_op == O_constant)
imm_expr.X_add_number &= 0xffff;
}
if (*args == 'i')
{
if ((c == S_EX_NONE && imm_expr.X_op != O_constant)
|| ((imm_expr.X_add_number < 0
|| imm_expr.X_add_number >= 0x10000)
&& imm_expr.X_op == O_constant))
{
if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
!strcmp (insn->name, insn[1].name))
break;
if (imm_expr.X_op == O_constant
|| imm_expr.X_op == O_big)
as_bad (_("16 bit expression not in range 0..65535"));
}
}
else
if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0)
{
int more;
offsetT max;
offsetT minval, maxval;
/* The upper bound should be 0x8000, but
unfortunately the MIPS assembler accepts numbers
from 0x8000 to 0xffff and sign extends them, and
we want to be compatible. We only permit this
extended range for an instruction which does not
provide any further alternates, since those
alternates may handle other cases. People should
use the numbers they mean, rather than relying on
a mysterious sign extension. */
more = (insn + 1 < &mips_opcodes[NUMOPCODES] &&
strcmp (insn->name, insn[1].name) == 0);
if (more)
max = 0x8000;
more = (insn + 1 < &mips_opcodes[NUMOPCODES]
&& strcmp (insn->name, insn[1].name) == 0);
/* If the expression was written as an unsigned number,
only treat it as signed if there are no more
alternatives. */
if (more
&& *args == 'j'
&& sizeof (imm_expr.X_add_number) <= 4
&& imm_expr.X_op == O_constant
&& imm_expr.X_add_number < 0
&& imm_expr.X_unsigned
&& HAVE_64BIT_GPRS)
break;
/* For compatibility with older assemblers, we accept
0x8000-0xffff as signed 16-bit numbers when only
signed numbers are allowed. */
if (*args == 'i')
minval = 0, maxval = 0xffff;
else if (more)
minval = -0x8000, maxval = 0x7fff;
else
max = 0x10000;
if ((c == S_EX_NONE && imm_expr.X_op != O_constant)
|| ((imm_expr.X_add_number < -0x8000
|| imm_expr.X_add_number >= max)
&& imm_expr.X_op == O_constant)
|| (more
&& imm_expr.X_add_number < 0
&& HAVE_64BIT_GPRS
&& imm_expr.X_unsigned
&& sizeof (imm_expr.X_add_number) <= 4))
minval = -0x8000, maxval = 0xffff;
if (imm_expr.X_op != O_constant
|| imm_expr.X_add_number < minval
|| imm_expr.X_add_number > maxval)
{
if (more)
break;
if (imm_expr.X_op == O_constant
|| imm_expr.X_op == O_big)
as_bad (_("16 bit expression not in range -32768..32767"));
as_bad (_("expression out of range"));
}
}
s = expr_end;
continue;
case 'o': /* 16 bit offset */
c = my_getSmallExpression (&offset_expr, s);
/* Check whether there is only a single bracketed expression
left. If so, it must be the base register and the
constant must be zero. */
if (*s == '(' && strchr (s + 1, '(') == 0)
{
offset_expr.X_op = O_constant;
offset_expr.X_add_number = 0;
continue;
}
/* If this value won't fit into a 16 bit offset, then go
find a macro that will generate the 32 bit offset
code pattern. */
if (c == S_EX_NONE
if (my_getSmallExpression (&offset_expr, offset_reloc, s) == 0
&& (offset_expr.X_op != O_constant
|| offset_expr.X_add_number >= 0x8000
|| offset_expr.X_add_number < -0x8000))
break;
if (c == S_EX_HI)
{
if (offset_expr.X_op != O_constant)
break;
offset_expr.X_add_number =
(offset_expr.X_add_number >> 16) & 0xffff;
}
*offset_reloc = BFD_RELOC_LO16;
s = expr_end;
continue;
@ -9191,49 +9107,10 @@ mips_ip (str, ip)
continue;
case 'u': /* upper 16 bits */
c = my_getSmallExpression (&imm_expr, s);
*imm_reloc = BFD_RELOC_LO16;
if (c != S_EX_NONE)
{
if (c != S_EX_LO)
{
if (c == S_EX_HI)
{
*imm_reloc = BFD_RELOC_HI16_S;
imm_unmatched_hi = TRUE;
}
#ifdef OBJ_ELF
else if (c == S_EX_HIGHEST)
*imm_reloc = BFD_RELOC_MIPS_HIGHEST;
else if (c == S_EX_GP_REL)
{
/* This occurs in NewABI only. */
c = my_getSmallExpression (&imm_expr, s);
if (c != S_EX_NEG)
as_bad (_("bad composition of relocations"));
else
{
c = my_getSmallExpression (&imm_expr, s);
if (c != S_EX_HI)
as_bad (_("bad composition of relocations"));
else
{
imm_reloc[0] = BFD_RELOC_GPREL16;
imm_reloc[1] = BFD_RELOC_MIPS_SUB;
imm_reloc[2] = BFD_RELOC_HI16_S;
}
}
}
#endif
else
*imm_reloc = BFD_RELOC_HI16;
}
else if (imm_expr.X_op == O_constant)
imm_expr.X_add_number &= 0xffff;
}
else if (imm_expr.X_op == O_constant
&& (imm_expr.X_add_number < 0
|| imm_expr.X_add_number >= 0x10000))
if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0
&& imm_expr.X_op == O_constant
&& (imm_expr.X_add_number < 0
|| imm_expr.X_add_number >= 0x10000))
as_bad (_("lui expression not in range 0..65535"));
s = expr_end;
continue;
@ -10070,222 +9947,118 @@ mips16_immed (file, line, type, val, warn, small, ext, insn, use_extend,
}
}
static struct percent_op_match
static const struct percent_op_match
{
const char *str;
const enum small_ex_type type;
const char *str;
bfd_reloc_code_real_type reloc;
} percent_op[] =
{
{"%lo", S_EX_LO},
{"%lo", BFD_RELOC_LO16},
#ifdef OBJ_ELF
{"%call_hi", S_EX_CALL_HI},
{"%call_lo", S_EX_CALL_LO},
{"%call16", S_EX_CALL16},
{"%got_disp", S_EX_GOT_DISP},
{"%got_page", S_EX_GOT_PAGE},
{"%got_ofst", S_EX_GOT_OFST},
{"%got_hi", S_EX_GOT_HI},
{"%got_lo", S_EX_GOT_LO},
{"%got", S_EX_GOT},
{"%gp_rel", S_EX_GP_REL},
{"%half", S_EX_HALF},
{"%highest", S_EX_HIGHEST},
{"%higher", S_EX_HIGHER},
{"%neg", S_EX_NEG},
{"%call_hi", BFD_RELOC_MIPS_CALL_HI16},
{"%call_lo", BFD_RELOC_MIPS_CALL_LO16},
{"%call16", BFD_RELOC_MIPS_CALL16},
{"%got_disp", BFD_RELOC_MIPS_GOT_DISP},
{"%got_page", BFD_RELOC_MIPS_GOT_PAGE},
{"%got_ofst", BFD_RELOC_MIPS_GOT_OFST},
{"%got_hi", BFD_RELOC_MIPS_GOT_HI16},
{"%got_lo", BFD_RELOC_MIPS_GOT_LO16},
{"%got", BFD_RELOC_MIPS_GOT16},
{"%gp_rel", BFD_RELOC_GPREL16},
{"%half", BFD_RELOC_16},
{"%highest", BFD_RELOC_MIPS_HIGHEST},
{"%higher", BFD_RELOC_MIPS_HIGHER},
{"%neg", BFD_RELOC_MIPS_SUB},
#endif
{"%hi", S_EX_HI}
{"%hi", BFD_RELOC_HI16_S}
};
/* Parse small expression input. STR gets adjusted to eat up whitespace.
It detects valid "%percent_op(...)" and "($reg)" strings. Percent_op's
can be nested, this is handled by blanking the innermost, parsing the
rest by subsequent calls. */
static int
my_getSmallParser (str, len, nestlevel)
/* Return true if *STR points to a relocation operator. When returning true,
move *STR over the operator and store its relocation code in *RELOC.
Leave both *STR and *RELOC alone when returning false. */
static bfd_boolean
parse_relocation (str, reloc)
char **str;
unsigned int *len;
int *nestlevel;
bfd_reloc_code_real_type *reloc;
{
*len = 0;
*str += strspn (*str, " \t");
/* Check for expression in parentheses. */
if (**str == '(')
{
char *b = *str + 1 + strspn (*str + 1, " \t");
char *e;
size_t i;
/* Check for base register. */
if (b[0] == '$')
{
if (strchr (b, ')')
&& (e = b + strcspn (b, ") \t"))
&& e - b > 1 && e - b < 4)
{
if ((e - b == 3
&& ((b[1] == 'f' && b[2] == 'p')
|| (b[1] == 's' && b[2] == 'p')
|| (b[1] == 'g' && b[2] == 'p')
|| (b[1] == 'a' && b[2] == 't')
|| (ISDIGIT (b[1])
&& ISDIGIT (b[2]))))
|| (ISDIGIT (b[1])))
{
*len = strcspn (*str, ")") + 1;
return S_EX_REGISTER;
}
}
}
/* Check for percent_op (in parentheses). */
else if (b[0] == '%')
{
*str = b;
return my_getPercentOp (str, len, nestlevel);
}
/* Some other expression in the parentheses, which can contain
parentheses itself. Attempt to find the matching one. */
for (i = 0; i < ARRAY_SIZE (percent_op); i++)
if (strncasecmp (*str, percent_op[i].str, strlen (percent_op[i].str)) == 0)
{
int pcnt = 1;
char *s;
*str += strlen (percent_op[i].str);
*reloc = percent_op[i].reloc;
*len = 1;
for (s = *str + 1; *s && pcnt; s++, (*len)++)
/* Check whether the output BFD supports this relocation.
If not, issue an error and fall back on something safe. */
if (!bfd_reloc_type_lookup (stdoutput, percent_op[i].reloc))
{
if (*s == '(')
++pcnt;
else if (*s == ')')
--pcnt;
as_bad ("relocation %s isn't supported by the current ABI",
percent_op[i].str);
*reloc = BFD_RELOC_LO16;
}
return TRUE;
}
}
/* Check for percent_op (outside of parentheses). */
else if (*str[0] == '%')
return my_getPercentOp (str, len, nestlevel);
/* Any other expression. */
return S_EX_NONE;
return FALSE;
}
static int
my_getPercentOp (str, len, nestlevel)
char **str;
unsigned int *len;
int *nestlevel;
{
char *tmp = *str + 1;
unsigned int i = 0;
while (ISALPHA (*tmp) || *tmp == '_')
{
*tmp = TOLOWER (*tmp);
tmp++;
}
while (i < (sizeof (percent_op) / sizeof (struct percent_op_match)))
{
if (strncmp (*str, percent_op[i].str, strlen (percent_op[i].str)))
i++;
else
{
int type = percent_op[i].type;
/* Parse string STR as a 16-bit relocatable operand. Store the
expression in *EP and the relocations in the array starting
at RELOC. Return the number of relocation operators used.
/* Only %hi and %lo are allowed for OldABI. */
if (! HAVE_NEWABI && type != S_EX_HI && type != S_EX_LO)
return S_EX_NONE;
On exit, EXPR_END points to the first character after the expression.
If no relocation operators are used, RELOC[0] is set to BFD_RELOC_LO16. */
*len = strlen (percent_op[i].str);
++(*nestlevel);
return type;
}
}
return S_EX_NONE;
}
static int
my_getSmallExpression (ep, str)
static size_t
my_getSmallExpression (ep, reloc, str)
expressionS *ep;
bfd_reloc_code_real_type *reloc;
char *str;
{
static char *oldstr = NULL;
int c = S_EX_NONE;
int oldc;
int nestlevel = -1;
unsigned int len;
bfd_reloc_code_real_type reversed_reloc[3];
size_t reloc_index, i;
int bracket_depth;
/* Don't update oldstr if the last call had nested percent_op's. We need
it to parse the outer ones later. */
if (! oldstr)
oldstr = str;
reloc_index = 0;
bracket_depth = 0;
do
/* Search for the start of the main expression, recoding relocations
in REVERSED_RELOC. */
for (;;)
{
oldc = c;
c = my_getSmallParser (&str, &len, &nestlevel);
if (c != S_EX_NONE && c != S_EX_REGISTER)
str += len;
}
while (c != S_EX_NONE && c != S_EX_REGISTER);
if (nestlevel >= 0)
{
/* A percent_op was encountered. Don't try to get an expression if
it is already blanked out. */
if (*(str + strspn (str + 1, " )")) != ')')
{
char save;
/* Let my_getExpression() stop at the closing parenthesis. */
save = *(str + len);
*(str + len) = '\0';
my_getExpression (ep, str);
*(str + len) = save;
}
if (nestlevel > 0)
{
/* Blank out including the % sign and the proper matching
parenthesis. */
int pcnt = 1;
char *s = strrchr (oldstr, '%');
char *end;
for (end = strchr (s, '(') + 1; *end && pcnt; end++)
{
if (*end == '(')
++pcnt;
else if (*end == ')')
--pcnt;
}
memset (s, ' ', end - s);
str = oldstr;
}
if (*str == '(')
bracket_depth++, str++;
else if (*str == ' ' || *str == '\t')
str++;
else if (*str == '%'
&& reloc_index < (HAVE_NEWABI ? 3 : 1)
&& parse_relocation (&str, &reversed_reloc[reloc_index]))
reloc_index++;
else
expr_end = str + len;
c = oldc;
}
else if (c == S_EX_NONE)
{
my_getExpression (ep, str);
}
else if (c == S_EX_REGISTER)
{
ep->X_op = O_constant;
expr_end = str;
ep->X_add_symbol = NULL;
ep->X_op_symbol = NULL;
ep->X_add_number = 0;
}
else
{
as_fatal (_("internal error"));
break;
}
if (nestlevel <= 0)
/* All percent_op's have been handled. */
oldstr = NULL;
my_getExpression (ep, str);
str = expr_end;
return c;
/* Match every open bracket. */
while (bracket_depth > 0 && (*str == ')' || *str == ' ' || *str == '\t'))
if (*str++ == ')')
bracket_depth--;
if (bracket_depth > 0)
as_bad ("unclosed '('");
expr_end = str;
reloc[0] = BFD_RELOC_LO16;
for (i = 0; i < reloc_index; i++)
reloc[i] = reversed_reloc[reloc_index - 1 - i];
return reloc_index;
}
static void

View File

@ -1,3 +1,10 @@
2003-02-02 Richard Sandiford <rsandifo@redhat.com>
* gas/mips/elf-rel8.[sd], gas/mips/elf-rel9.[sd],
gas/mips/elf-rel10.[sd], gas/mips/elf-rel11.[sd]: New tests.
* gas/mips/mips.exp: Run elf-rel8 and elf-rel9 for all elf
targets. Run elf-rel10 and elf-rel11 for NewABI targets.
2003-01-27 Alexandre Oliva <aoliva@redhat.com>
* gas/mips/n32-consec.d: New.

View File

@ -0,0 +1,29 @@
#as: -march=mips3 -mabi=n32 -KPIC
#readelf: --relocs
#name: MIPS ELF reloc 10
Relocation section '\.rela\.text' at offset .* contains 22 entries:
*Offset * Info * Type * Sym\.Value * Sym\. Name \+ Addend
0+0000 * 0+..07 * R_MIPS_GPREL16 * 0+0000 * foo \+ 0
0+0000 * 0+0018 * R_MIPS_SUB * 0+0000
0+0000 * 0+0005 * R_MIPS_HI16 * 0+0000
0+0004 * 0+..07 * R_MIPS_GPREL16 * 0+0000 * foo \+ 0
0+0004 * 0+0018 * R_MIPS_SUB * 0+0000
0+0004 * 0+0006 * R_MIPS_LO16 * 0+0000
0+000c * 0+..07 * R_MIPS_GPREL16 * 0+0000 * \.text \+ c
0+000c * 0+0018 * R_MIPS_SUB * 0+0000
0+000c * 0+0005 * R_MIPS_HI16 * 0+0000
0+0010 * 0+..07 * R_MIPS_GPREL16 * 0+0000 * \.text \+ c
0+0010 * 0+0018 * R_MIPS_SUB * 0+0000
0+0010 * 0+0006 * R_MIPS_LO16 * 0+0000
0+0018 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * foo \+ 0
0+001c * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * foo \+ 0
0+0020 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * foo \+ 1234
0+0024 * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * foo \+ 1234
0+0028 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * \.text \+ c
0+002c * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * \.text \+ c
0+0030 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * \.text \+ 33221d
0+0034 * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * \.text \+ 33221d
0+0038 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * frob \+ 0
0+003c * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * frob \+ 0
#pass

View File

@ -0,0 +1,31 @@
.globl foo
.ent foo
foo:
lui $gp,%hi(%neg(%gp_rel(foo)))
addiu $gp,$gp,%lo(%neg(%gp_rel(foo)))
daddu $gp,$gp,$25
.end foo
.ent bar
bar:
lui $gp,%hi(%neg(%gp_rel(bar)))
addiu $gp,$gp,%lo(%neg(%gp_rel(bar)))
daddu $gp,$gp,$25
.end bar
.ent frob
lw $4,%got_page(foo)($gp)
addiu $4,$4,%got_ofst(foo)
lw $4,%got_page(foo + 0x1234)($gp)
addiu $4,$4,%got_ofst(foo + 0x1234)
lw $4,%got_page(bar)($gp)
addiu $4,$4,%got_ofst(bar)
lw $4,%got_page(bar + 0x332211)($gp)
addiu $4,$4,%got_ofst(bar + 0x332211)
lw $4,%got_page(frob)($gp)
addiu $4,$4,%got_ofst(frob)
.end frob

View File

@ -0,0 +1,43 @@
#as: -march=mips3 -mabi=64
#readelf: --relocs
#name: MIPS ELF reloc 11
Relocation section '\.rela\.text' at offset .* contains 12 entries:
*Offset * Info * Type * Sym\. Value * Sym\. Name \+ Addend
0+0000 * 0+..0000001d * R_MIPS_HIGHEST * 0+0000 * bar \+ 0
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
0+0008 * 0+..0000001c * R_MIPS_HIGHER * 0+0000 * bar \+ 0
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
0+0004 * 0+..00000005 * R_MIPS_HI16 * 0+0000 * bar \+ 0
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
0+000c * 0+..00000006 * R_MIPS_LO16 * 0+0000 * bar \+ 0
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
0+0018 * 0+..0000001d * R_MIPS_HIGHEST * 0+0000 * bar \+ 12345678
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
0+0020 * 0+..0000001c * R_MIPS_HIGHER * 0+0000 * bar \+ 12345678
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
0+001c * 0+..00000005 * R_MIPS_HI16 * 0+0000 * bar \+ 12345678
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
0+0024 * 0+..00000006 * R_MIPS_LO16 * 0+0000 * bar \+ 12345678
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
0+0030 * 0+..0000001d * R_MIPS_HIGHEST * 0+0000 * \.data \+ 10
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
0+0034 * 0+..0000001c * R_MIPS_HIGHER * 0+0000 * \.data \+ 10
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
0+003c * 0+..00000005 * R_MIPS_HI16 * 0+0000 * \.data \+ 10
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
0+0044 * 0+..00000006 * R_MIPS_LO16 * 0+0000 * \.data \+ 10
* Type2: R_MIPS_NONE *
* Type3: R_MIPS_NONE *
#pass

View File

@ -0,0 +1,27 @@
.ent foo
foo:
lui $4,%highest(bar)
lui $5,%hi(bar)
daddiu $4,$4,%higher(bar)
daddiu $5,$5,%lo(bar)
dsll32 $4,$4,0
daddu $4,$4,$5
lui $4,%highest(bar + 0x12345678)
lui $5,%hi(bar + 0x12345678)
daddiu $4,$4,%higher(bar + 0x12345678)
daddiu $5,$5,%lo(bar + 0x12345678)
dsll32 $4,$4,0
daddu $4,$4,$5
lui $4,%highest(l1)
daddiu $4,$4,%higher(l1)
dsll $4,$4,16
daddiu $4,$4,%hi(l1)
dsll $4,$4,16
lw $4,%lo(l1)($4)
.end foo
.data
.word 1,2,3,4
l1: .word 4,5

View File

@ -0,0 +1,57 @@
#as: -march=mips2 -mabi=32
#objdump: -M gpr-names=numeric -dr
#name: MIPS ELF reloc 8
.*: file format .*
Disassembly of section \.text:
0+00 <foo>:
0: 3c040000 lui \$4,0x0
0: R_MIPS_HI16 gvar
4: 24840000 addiu \$4,\$4,0
4: R_MIPS_LO16 gvar
8: 8ca40000 lw \$4,0\(\$5\)
8: R_MIPS_LO16 gvar
c: 8fc40002 lw \$4,2\(\$30\)
10: 3c040000 lui \$4,0x0
10: R_MIPS_CALL_HI16 gfunc
14: 009c2021 addu \$4,\$4,\$28
18: 8c990000 lw \$25,0\(\$4\)
18: R_MIPS_CALL_LO16 gfunc
1c: 3c040000 lui \$4,0x0
1c: R_MIPS_GOT_HI16 gvar
20: 009c2021 addu \$4,\$4,\$28
24: 8c850000 lw \$5,0\(\$4\)
24: R_MIPS_GOT_LO16 gvar
28: 8f840000 lw \$4,0\(\$28\)
28: R_MIPS_GOT16 \.data
2c: a0850000 sb \$5,0\(\$4\)
2c: R_MIPS_LO16 \.data
30: 3c040000 lui \$4,0x0
30: R_MIPS_CALL_HI16 gfunc
34: 24840000 addiu \$4,\$4,0
34: R_MIPS_CALL_LO16 gfunc
38: 3c040000 lui \$4,0x0
38: R_MIPS_GOT_HI16 gvar
3c: 24840000 addiu \$4,\$4,0
3c: R_MIPS_GOT_LO16 gvar
40: 8f840000 lw \$4,0\(\$28\)
40: R_MIPS_GOT16 \.data
44: 24840000 addiu \$4,\$4,0
44: R_MIPS_LO16 \.data
48: 8f990000 lw \$25,0\(\$28\)
48: R_MIPS_CALL16 gfunc
4c: 27840000 addiu \$4,\$28,0
4c: R_MIPS_CALL16 gfunc
50: 8f840000 lw \$4,0\(\$28\)
50: R_MIPS_GOT_DISP gvar
54: 27840000 addiu \$4,\$28,0
54: R_MIPS_GOT_DISP gvar
58: 8f840000 lw \$4,0\(\$28\)
58: R_MIPS_GPREL16 gvar
5c: af840000 sw \$4,0\(\$28\)
5c: R_MIPS_GPREL16 gvar
60: 27840000 addiu \$4,\$28,0
60: R_MIPS_GPREL16 gvar
\.\.\.

View File

@ -0,0 +1,53 @@
.equ $fprel, 2
.ent foo
foo:
# Test various forms of relocation syntax.
lui $4,(%hi gvar)
addiu $4,$4,(%lo (gvar))
lw $4,%lo gvar($5)
# Check that registers aren't confused with $ identifiers.
lw $4,($fprel)($fp)
# Check various forms of paired relocations.
lui $4,%call_hi(gfunc)
addu $4,$4,$gp
lw $25,%call_lo(gfunc)($4)
lui $4,%got_hi(gvar)
addu $4,$4,$gp
lw $5,%got_lo(gvar)($4)
lw $4,%got(lvar)($28)
sb $5,%lo(lvar)($4)
lui $4,%call_hi(gfunc)
addiu $4,$4,%call_lo(gfunc)
lui $4,%got_hi(gvar)
addiu $4,$4,%got_lo(gvar)
lw $4,%got(lvar)($28)
addiu $4,$4,%lo(lvar)
# Check individual relocations.
lw $25,%call16(gfunc)($28)
addiu $4,$28,%call16(gfunc)
lw $4,%got_disp(gvar)($28)
addiu $4,$28,%got_disp(gvar)
lw $4,%gp_rel(gvar)($28)
sw $4,%gp_rel(gvar)($28)
addiu $4,$28,%gp_rel(gvar)
.space 64
.end foo
.data
lvar: .word 1,2

View File

@ -0,0 +1,68 @@
#as: -march=mips2 -mabi=32
#objdump: -M gpr-names=numeric -dr
#name: MIPS ELF reloc 9
.*: file format .*
Disassembly of section \.text:
0+00 <foo>:
0: 8f840000 lw \$4,0\(\$28\)
0: R_MIPS_GOT16 \.data
4: 24840010 addiu \$4,\$4,16
4: R_MIPS_LO16 \.data
8: 8f840000 lw \$4,0\(\$28\)
8: R_MIPS_GOT16 \.data
c: 24840020 addiu \$4,\$4,32
c: R_MIPS_LO16 \.data
10: 8f840000 lw \$4,0\(\$28\)
10: R_MIPS_GOT16 \.data
14: 24847ffc addiu \$4,\$4,32764
14: R_MIPS_LO16 \.data
18: 8f840001 lw \$4,1\(\$28\)
18: R_MIPS_GOT16 \.data
1c: 24848000 addiu \$4,\$4,-32768
1c: R_MIPS_LO16 \.data
20: 8f840001 lw \$4,1\(\$28\)
20: R_MIPS_GOT16 \.data
24: 2484fffc addiu \$4,\$4,-4
24: R_MIPS_LO16 \.data
28: 8f840001 lw \$4,1\(\$28\)
28: R_MIPS_GOT16 \.data
2c: 24840000 addiu \$4,\$4,0
2c: R_MIPS_LO16 \.data
30: 8f840002 lw \$4,2\(\$28\)
30: R_MIPS_GOT16 \.data
34: 24848010 addiu \$4,\$4,-32752
34: R_MIPS_LO16 \.data
38: 8f840002 lw \$4,2\(\$28\)
38: R_MIPS_GOT16 \.data
3c: 2484f000 addiu \$4,\$4,-4096
3c: R_MIPS_LO16 \.data
40: 8f840002 lw \$4,2\(\$28\)
40: R_MIPS_GOT16 \.data
44: 2484ffff addiu \$4,\$4,-1
44: R_MIPS_LO16 \.data
48: 8f840002 lw \$4,2\(\$28\)
48: R_MIPS_GOT16 \.data
4c: 2484f100 addiu \$4,\$4,-3840
4c: R_MIPS_LO16 \.data
50: 8f840003 lw \$4,3\(\$28\)
50: R_MIPS_GOT16 \.data
54: 24841345 addiu \$4,\$4,4933
54: R_MIPS_LO16 \.data
58: 8f84c000 lw \$4,-16384\(\$28\)
58: R_MIPS_GPREL16 \.sdata\+0x4000
5c: 8f84c004 lw \$4,-16380\(\$28\)
5c: R_MIPS_GPREL16 \.sdata\+0x4000
60: 8f84c004 lw \$4,-16380\(\$28\)
60: R_MIPS_GPREL16 \.sdata\+0x4000
64: 8f84c008 lw \$4,-16376\(\$28\)
64: R_MIPS_GPREL16 \.sdata\+0x4000
68: 8f84c00c lw \$4,-16372\(\$28\)
68: R_MIPS_GPREL16 \.sdata\+0x4000
6c: 8f84c014 lw \$4,-16364\(\$28\)
6c: R_MIPS_GPREL16 \.sdata\+0x4000
70: 8f84c018 lw \$4,-16360\(\$28\)
70: R_MIPS_GPREL16 \.sdata\+0x4000
\.\.\.

View File

@ -0,0 +1,57 @@
.ent foo
foo:
lw $4,%got(l1)($28)
addiu $4,$4,%lo(l1)
lw $4,%got(l1 + 16)($28)
addiu $4,$4,%lo(l1 + 16)
lw $4,%got(l1 + 0x7fec)($28)
addiu $4,$4,%lo(l1 + 0x7fec)
lw $4,%got(l1 + 0x7ff0)($28)
addiu $4,$4,%lo(l1 + 0x7ff0)
lw $4,%got(l1 + 0xffec)($28)
addiu $4,$4,%lo(l1 + 0xffec)
lw $4,%got(l1 + 0xfff0)($28)
addiu $4,$4,%lo(l1 + 0xfff0)
lw $4,%got(l1 + 0x18000)($28)
addiu $4,$4,%lo(l1 + 0x18000)
lw $4,%got(l2)($28)
addiu $4,$4,%lo(l2)
lw $4,%got(l2 + 0xfff)($28)
addiu $4,$4,%lo(l2 + 0xfff)
lw $4,%got(l2 + 0x1000)($28)
addiu $4,$4,%lo(l2 + 0x100)
lw $4,%got(l2 + 0x12345)($28)
addiu $4,$4,%lo(l2 + 0x12345)
lw $4,%gp_rel(l3)($28)
lw $4,%gp_rel(l3 + 4)($28)
lw $4,%gp_rel(l4)($28)
lw $4,%gp_rel(l4 + 4)($28)
lw $4,%gp_rel(l5)($28)
lw $4,%gp_rel(l5 + 8)($28)
lw $4,%gp_rel(l5 + 12)($28)
.space 64
.end foo
.data
.word 1,2,3,4
l1: .word 4,5
.space 0x1f000 - 24
l2: .word 7,8
.sdata
l3: .word 1
l4: .word 2
.word 3
l5: .word 4

View File

@ -376,7 +376,7 @@ if { [istarget mips*-*-*] } then {
set ilocks [istarget mipstx39*-*-*]
set gpr_ilocks [expr [istarget mipstx39*-*-*]]
set addr32 [expr [istarget mipstx39*-*-*]]
set hasn32 [expr [istarget *-*-irix6*] || [istarget mips64*-*-linux*]]
set has_newabi [expr [istarget *-*-irix6*] || [istarget mips64*-*-linux*]]
if { [istarget "mips*-*-*linux*"] } then {
set tmips "t"
@ -602,6 +602,12 @@ if { [istarget mips*-*-*] } then {
run_dump_test "elf-rel5"
run_dump_test "elf-rel6"
run_dump_test "elf-rel7"
run_dump_test "elf-rel8"
run_dump_test "elf-rel9"
if $has_newabi {
run_dump_test "elf-rel10"
run_dump_test "elf-rel11"
}
run_dump_test "${tmips}${el}empic"
run_dump_test "empic2"
run_dump_test "empic3_e"
@ -614,7 +620,7 @@ if { [istarget mips*-*-*] } then {
run_dump_test "elf-consthilo"
}
if $hasn32 {
if $has_newabi {
run_dump_test "n32-consec"
}