This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[committed] Remove imm_reloc from tc-mips.c
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: binutils at sourceware dot org
- Date: Sun, 14 Jul 2013 14:13:47 +0100
- Subject: [committed] Remove imm_reloc from tc-mips.c
There's no real need for both imm_reloc and offset_reloc, since an
instruction can have at most one set of relocations. This patch makes sure
that the relocatable field is always stored in offset_expr/offset_reloc
and that the global state of imm_expr and imm2_expr are only meaningful
for macros. (The variables are still used as temporary space for parsing
some constant operands, but that goes way with a later patch.)
Here too the "invalid unextended operand value" message is copied
from mips16_immed, just to emphasise the point about captilisation
in the last message.
Tested on various targets and applied.
Richard
gas/
* config/tc-mips.c (imm_expr, imm2_expr, offset_expr): Tweak commentary.
(imm_reloc): Delete.
(md_assemble): Remove imm_reloc handling.
(mips_ip): Update commentary. Use offset_expr and offset_reloc
rather than imm_expr and imm_reloc for 'i', 'j' and 'u'.
Use a temporary array rather than imm_reloc when parsing
constant expressions. Remove imm_reloc initialization.
(mips16_ip): Update commentary. Use offset_expr and offset_reloc
for the relaxable field. Use a relax_char variable to track the
type of this field. Remove imm_reloc initialization.
Index: gas/config/tc-mips.c
===================================================================
--- gas/config/tc-mips.c 2013-07-14 10:20:31.527543003 +0100
+++ gas/config/tc-mips.c 2013-07-14 10:23:53.659451249 +0100
@@ -1810,17 +1810,18 @@ mips_mark_labels (void)
static char *expr_end;
-/* Expressions which appear in instructions. These are set by
- mips_ip. */
+/* Expressions which appear in macro instructions. These are set by
+ mips_ip and read by macro. */
static expressionS imm_expr;
static expressionS imm2_expr;
-static expressionS offset_expr;
-/* Relocs associated with imm_expr and offset_expr. */
+/* The relocatable field in an instruction and the relocs associated
+ with it. These variables are used for instructions like LUI and
+ JAL as well as true offsets. They are also used for address
+ operands in macros. */
-static bfd_reloc_code_real_type imm_reloc[3]
- = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
+static expressionS offset_expr;
static bfd_reloc_code_real_type offset_reloc[3]
= {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
@@ -2970,9 +2971,6 @@ md_assemble (char *str)
imm_expr.X_op = O_absent;
imm2_expr.X_op = O_absent;
offset_expr.X_op = O_absent;
- imm_reloc[0] = BFD_RELOC_UNUSED;
- imm_reloc[1] = BFD_RELOC_UNUSED;
- imm_reloc[2] = BFD_RELOC_UNUSED;
offset_reloc[0] = BFD_RELOC_UNUSED;
offset_reloc[1] = BFD_RELOC_UNUSED;
offset_reloc[2] = BFD_RELOC_UNUSED;
@@ -3002,9 +3000,7 @@ md_assemble (char *str)
}
else
{
- if (imm_expr.X_op != O_absent)
- append_insn (&insn, &imm_expr, imm_reloc, FALSE);
- else if (offset_expr.X_op != O_absent)
+ if (offset_expr.X_op != O_absent)
append_insn (&insn, &offset_expr, offset_reloc, FALSE);
else
append_insn (&insn, NULL, unused_reloc, FALSE);
@@ -11187,10 +11183,12 @@ expr_const_in_range (expressionS *ep, of
&& ep->X_add_number < max << bit);
}
-/* This routine assembles an instruction into its binary format. As a
- side effect, it sets one of the global variables imm_reloc or
- offset_reloc to the type of relocation to do if one of the operands
- is an address expression. */
+/* Assemble an instruction into its binary format. If the instruction
+ is a macro, set imm_expr, imm2_expr and offset_expr to the values
+ associated with "I", "+I" and "A" operands respectively. Otherwise
+ store the value of the relocatable field (if any) in offset_expr.
+ In both cases set offset_reloc to the relocation operators applied
+ to offset_expr. */
static void
mips_ip (char *str, struct mips_cl_insn *ip)
@@ -11336,9 +11334,6 @@ mips_ip (char *str, struct mips_cl_insn
imm_expr.X_op = O_absent;
imm2_expr.X_op = O_absent;
offset_expr.X_op = O_absent;
- imm_reloc[0] = BFD_RELOC_UNUSED;
- imm_reloc[1] = BFD_RELOC_UNUSED;
- imm_reloc[2] = BFD_RELOC_UNUSED;
offset_reloc[0] = BFD_RELOC_UNUSED;
offset_reloc[1] = BFD_RELOC_UNUSED;
offset_reloc[2] = BFD_RELOC_UNUSED;
@@ -12099,6 +12094,8 @@ mips_ip (char *str, struct mips_cl_insn
{
int shift = 8;
size_t i;
+ bfd_reloc_code_real_type r[3];
+
/* Check whether there is only a single bracketed expression
left. If so, it must be the base register and the
constant must be zero. */
@@ -12108,7 +12105,7 @@ mips_ip (char *str, struct mips_cl_insn
/* If this value won't fit into the offset, then go find
a macro that will generate a 16- or 32-bit offset code
pattern. */
- i = my_getSmallExpression (&imm_expr, imm_reloc, s);
+ i = my_getSmallExpression (&imm_expr, r, s);
if ((i == 0 && (imm_expr.X_op != O_constant
|| imm_expr.X_add_number >= 1 << shift
|| imm_expr.X_add_number < -1 << shift))
@@ -12140,6 +12137,7 @@ mips_ip (char *str, struct mips_cl_insn
{
int shift = *args == '.' ? 9 : 11;
size_t i;
+ bfd_reloc_code_real_type r[3];
/* Check whether there is only a single bracketed expression
left. If so, it must be the base register and the
@@ -12150,7 +12148,7 @@ mips_ip (char *str, struct mips_cl_insn
/* If this value won't fit into the offset, then go find
a macro that will generate a 16- or 32-bit offset code
pattern. */
- i = my_getSmallExpression (&imm_expr, imm_reloc, s);
+ i = my_getSmallExpression (&imm_expr, r, s);
if ((i == 0 && (imm_expr.X_op != O_constant
|| imm_expr.X_add_number >= 1 << shift
|| imm_expr.X_add_number < -1 << shift))
@@ -12896,8 +12894,8 @@ mips_ip (char *str, struct mips_cl_insn
case 'i': /* 16-bit unsigned immediate. */
case 'j': /* 16-bit signed immediate. */
- *imm_reloc = BFD_RELOC_LO16;
- if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0)
+ *offset_reloc = BFD_RELOC_LO16;
+ if (my_getSmallExpression (&offset_expr, offset_reloc, s) == 0)
{
int more;
offsetT minval, maxval;
@@ -12915,14 +12913,14 @@ mips_ip (char *str, struct mips_cl_insn
else
minval = -0x8000, maxval = 0xffff;
- if (imm_expr.X_op != O_constant
- || imm_expr.X_add_number < minval
- || imm_expr.X_add_number > maxval)
+ if (offset_expr.X_op != O_constant
+ || offset_expr.X_add_number < minval
+ || offset_expr.X_add_number > maxval)
{
if (more)
break;
- if (imm_expr.X_op == O_constant
- || imm_expr.X_op == O_big)
+ if (offset_expr.X_op == O_constant
+ || offset_expr.X_op == O_big)
as_bad (_("Expression out of range"));
}
}
@@ -12963,13 +12961,13 @@ mips_ip (char *str, struct mips_cl_insn
continue;
case 'u': /* Upper 16 bits. */
- *imm_reloc = BFD_RELOC_LO16;
- 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))
+ *offset_reloc = BFD_RELOC_LO16;
+ if (my_getSmallExpression (&offset_expr, offset_reloc, s) == 0
+ && offset_expr.X_op == O_constant
+ && (offset_expr.X_add_number < 0
+ || offset_expr.X_add_number >= 0x10000))
as_bad (_("lui expression (%lu) not in range 0..65535"),
- (unsigned long) imm_expr.X_add_number);
+ (unsigned long) offset_expr.X_add_number);
s = expr_end;
continue;
@@ -13833,12 +13831,9 @@ mips_ip (char *str, struct mips_cl_insn
#define SKIP_SPACE_TABS(S) { while (*(S) == ' ' || *(S) == '\t') ++(S); }
-/* This routine assembles an instruction into its binary format when
- assembling for the mips16. As a side effect, it sets one of the
- global variables imm_reloc or offset_reloc to the type of relocation
- to do if one of the operands is an address expression. It also sets
- forced_insn_length to the resulting instruction size in bytes if the
- user explicitly requested a small or extended instruction. */
+/* As for mips_ip, but used when assembling MIPS16 code.
+ Also set forced_insn_length to the resulting instruction size in
+ bytes if the user explicitly requested a small or extended instruction. */
static void
mips16_ip (char *str, struct mips_cl_insn *ip)
@@ -13901,6 +13896,7 @@ mips16_ip (char *str, struct mips_cl_ins
for (;;)
{
bfd_boolean ok;
+ char relax_char;
gas_assert (strcmp (insn->name, str) == 0);
@@ -13930,14 +13926,12 @@ mips16_ip (char *str, struct mips_cl_ins
create_insn (ip, insn);
imm_expr.X_op = O_absent;
- imm_reloc[0] = BFD_RELOC_UNUSED;
- imm_reloc[1] = BFD_RELOC_UNUSED;
- imm_reloc[2] = BFD_RELOC_UNUSED;
imm2_expr.X_op = O_absent;
offset_expr.X_op = O_absent;
offset_reloc[0] = BFD_RELOC_UNUSED;
offset_reloc[1] = BFD_RELOC_UNUSED;
offset_reloc[2] = BFD_RELOC_UNUSED;
+ relax_char = 0;
for (args = insn->args; 1; ++args)
{
int c;
@@ -13958,19 +13952,31 @@ mips16_ip (char *str, struct mips_cl_ins
offsetT value;
/* Stuff the immediate value in now, if we can. */
- if (imm_expr.X_op == O_constant
- && *imm_reloc > BFD_RELOC_UNUSED
- && insn->pinfo != INSN_MACRO
- && calculate_reloc (*offset_reloc,
- imm_expr.X_add_number, &value))
- {
- mips16_immed (NULL, 0, *imm_reloc - BFD_RELOC_UNUSED,
- *offset_reloc, value, forced_insn_length,
- &ip->insn_opcode);
- imm_expr.X_op = O_absent;
- *imm_reloc = BFD_RELOC_UNUSED;
+ if (insn->pinfo == INSN_MACRO)
+ {
+ gas_assert (relax_char == 0);
+ gas_assert (*offset_reloc == BFD_RELOC_UNUSED);
+ }
+ else if (relax_char
+ && offset_expr.X_op == O_constant
+ && calculate_reloc (*offset_reloc,
+ offset_expr.X_add_number,
+ &value))
+ {
+ mips16_immed (NULL, 0, relax_char, *offset_reloc, value,
+ forced_insn_length, &ip->insn_opcode);
+ offset_expr.X_op = O_absent;
*offset_reloc = BFD_RELOC_UNUSED;
}
+ else if (relax_char && *offset_reloc != BFD_RELOC_UNUSED)
+ {
+ if (forced_insn_length == 2)
+ as_bad (_("invalid unextended operand value"));
+ forced_insn_length = 4;
+ ip->insn_opcode |= MIPS16_EXTEND;
+ }
+ else if (relax_char)
+ *offset_reloc = (int) BFD_RELOC_UNUSED + relax_char;
return;
}
@@ -14141,24 +14147,14 @@ mips16_ip (char *str, struct mips_cl_ins
case 'U':
case 'k':
case 'K':
- i = my_getSmallExpression (&imm_expr, imm_reloc, s);
+ i = my_getSmallExpression (&offset_expr, offset_reloc, s);
if (i > 0)
{
- if (imm_expr.X_op != O_constant)
- {
- forced_insn_length = 4;
- ip->insn_opcode |= MIPS16_EXTEND;
- }
- else
- {
- /* We need to relax this instruction. */
- *offset_reloc = *imm_reloc;
- *imm_reloc = (int) BFD_RELOC_UNUSED + c;
- }
+ relax_char = c;
s = expr_end;
continue;
}
- *imm_reloc = BFD_RELOC_UNUSED;
+ *offset_reloc = BFD_RELOC_UNUSED;
/* Fall through. */
case '<':
case '>':
@@ -14166,8 +14162,8 @@ mips16_ip (char *str, struct mips_cl_ins
case ']':
case '4':
case '8':
- my_getExpression (&imm_expr, s);
- if (imm_expr.X_op == O_register)
+ my_getExpression (&offset_expr, s);
+ if (offset_expr.X_op == O_register)
{
/* What we thought was an expression turned out to
be a register. */
@@ -14177,11 +14173,11 @@ mips16_ip (char *str, struct mips_cl_ins
/* It looks like the expression was omitted
before a register indirection, which means
that the expression is implicitly zero. We
- still set up imm_expr, so that we handle
+ still set up offset_expr, so that we handle
explicit extensions correctly. */
- imm_expr.X_op = O_constant;
- imm_expr.X_add_number = 0;
- *imm_reloc = (int) BFD_RELOC_UNUSED + c;
+ offset_expr.X_op = O_constant;
+ offset_expr.X_add_number = 0;
+ relax_char = c;
continue;
}
@@ -14189,7 +14185,7 @@ mips16_ip (char *str, struct mips_cl_ins
}
/* We need to relax this instruction. */
- *imm_reloc = (int) BFD_RELOC_UNUSED + c;
+ relax_char = c;
s = expr_end;
continue;
@@ -14207,7 +14203,7 @@ mips16_ip (char *str, struct mips_cl_ins
break;
/* We need to relax this instruction. */
- *offset_reloc = (int) BFD_RELOC_UNUSED + c;
+ relax_char = c;
s = expr_end;
continue;