[PATCH 13/20] MIPS/GAS: Improve instruction's mnemonic processing
Maciej W. Rozycki
macro@codesourcery.com
Thu Dec 2 19:21:00 GMT 2010
Hi Richard,
Following your earlier comment addressing microMIPS code:
On Sun, 23 May 2010, Richard Sandiford wrote:
> Message-ID: <87y6fa9u3t.fsf@firetop.home>
> You could use alloca to create an opcode without the "16" or "32",
> which would make the error-reporting code simpler. It's best not
> to change the user's source line if we can help it.
I have made a complementing adjustment to original code currently present
in mips_ip(), making the whole piece much simpler and less fragile.
2010-12-02 Maciej W. Rozycki <macro@codesourcery.com>
gas/
* config/tc-mips.c (mips_ip): Make a copy of the instruction's
mnemonic and use it for further processing.
OK to apply?
Maciej
binutils-gas-mips-ip-insn-copy.diff
Index: binutils-fsf-trunk-quilt/gas/config/tc-mips.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/gas/config/tc-mips.c 2010-12-02 01:48:16.000000000 +0000
+++ binutils-fsf-trunk-quilt/gas/config/tc-mips.c 2010-12-02 01:49:28.000000000 +0000
@@ -8642,67 +8642,54 @@ mips_ip (char *str, struct mips_cl_insn
unsigned int lastpos = 0;
unsigned int limlo, limhi;
char *s_reset;
- char save_c = 0;
offsetT min_range, max_range;
+ char *name;
int argnum;
unsigned int rtype;
+ char *dot;
+ long end;
insn_error = NULL;
+ insn = NULL;
+
/* If the instruction contains a '.', we first try to match an instruction
including the '.'. Then we try again without the '.'. */
- insn = NULL;
- for (s = str; *s != '\0' && !ISSPACE (*s); ++s)
+ for (end = 0; str[end] != '\0' && !ISSPACE (str[end]); end++)
continue;
- /* If we stopped on whitespace, then replace the whitespace with null for
- the call to hash_find. Save the character we replaced just in case we
- have to re-parse the instruction. */
- if (ISSPACE (*s))
+ /* Make a copy of the instruction so that we can fiddle with it. */
+ name = alloca (end + 1);
+ memcpy (name, str, end);
+ name[end] = '\0';
+
+ for (;;)
{
- save_c = *s;
- *s++ = '\0';
- }
+ insn = (struct mips_opcode *) hash_find (op_hash, name);
- insn = (struct mips_opcode *) hash_find (op_hash, str);
+ if (insn != NULL)
+ break;
- /* If we didn't find the instruction in the opcode table, try again, but
- this time with just the instruction up to, but not including the
- first '.'. */
+ /* If we didn't find the instruction in the opcode table, try again,
+ but this time with just the instruction up to, but not including
+ the first '.'. */
+ dot = strchr (name, '.');
+ if (dot == NULL)
+ break;
+ *dot = '\0';
+ }
if (insn == NULL)
{
- /* Restore the character we overwrite above (if any). */
- if (save_c)
- *(--s) = save_c;
-
- /* Scan up to the first '.' or whitespace. */
- for (s = str;
- *s != '\0' && *s != '.' && !ISSPACE (*s);
- ++s)
- continue;
-
- /* If we did not find a '.', then we can quit now. */
- if (*s != '.')
- {
- insn_error = _("Unrecognized opcode");
- return;
- }
-
- /* Lookup the instruction in the hash table. */
- *s++ = '\0';
- if ((insn = (struct mips_opcode *) hash_find (op_hash, str)) == NULL)
- {
- insn_error = _("Unrecognized opcode");
- return;
- }
+ insn_error = _("Unrecognized opcode");
+ return;
}
- argsStart = s;
+ argsStart = s = str + end;
for (;;)
{
bfd_boolean ok;
- gas_assert (strcmp (insn->name, str) == 0);
+ gas_assert (strcmp (insn->name, name) == 0);
ok = is_opcode_valid (insn);
if (! ok)
@@ -8724,8 +8711,6 @@ mips_ip (char *str, struct mips_cl_insn
mips_cpu_info_from_isa (mips_opts.isa)->name);
insn_error = buf;
}
- if (save_c)
- *(--s) = save_c;
return;
}
}
@@ -10114,8 +10099,6 @@ mips_ip (char *str, struct mips_cl_insn
insn_error = _("Illegal operands");
continue;
}
- if (save_c)
- *(--argsStart) = save_c;
insn_error = _("Illegal operands");
return;
}
More information about the Binutils
mailing list