summaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@nildram.co.uk>2013-08-19 18:56:59 +0000
committerRichard Sandiford <rsandifo@nildram.co.uk>2013-08-19 18:56:59 +0000
commitbec029bce1bf374e05b16b6ba4714d5dba1633a4 (patch)
treea003046d538e88bcd095ce386572580fec869922 /gas
parentac0f0fea863a323ae0f6ef70996a0cedaf4b0220 (diff)
downloadbinutils-redhat-bec029bce1bf374e05b16b6ba4714d5dba1633a4.tar.gz
include/opcode/
* mips.h (OP_OPTIONAL_REG): New mips_operand_type. (mips_optional_operand_p): New function. opcodes/ * mips-formats.h (OPTIONAL_REG, OPTIONAL_MAPPED_REG): New macros. * micromips-opc.c (decode_micromips_operand): Use OPTIONAL_REG and OPTIONAL_MAPPED_REG. * mips-opc.c (decode_mips_operand): Likewise. * mips16-opc.c (decode_mips16_operand): Likewise. * mips-dis.c (print_insn_arg): Handle OP_OPTIONAL_REG. gas/ * config/tc-mips.c (operand_reg_mask, match_operand): Handle OP_OPTIONAL_REG. (mips_ip, mips16_ip): Use mips_optional_operand_p to check for optional operands.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog7
-rw-r--r--gas/config/tc-mips.c85
2 files changed, 37 insertions, 55 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index f0ca044b21..92ad6f6575 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,10 @@
+2013-08-19 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/tc-mips.c (operand_reg_mask, match_operand): Handle
+ OP_OPTIONAL_REG.
+ (mips_ip, mips16_ip): Use mips_optional_operand_p to check
+ for optional operands.
+
2013-08-16 Alan Modra <amodra@gmail.com>
* config/tc-ppc.c (ppc_elf_cons): Allow @l and other reloc
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index f35dbe0784..814b218209 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -3868,6 +3868,7 @@ operand_reg_mask (const struct mips_cl_insn *insn,
abort ();
case OP_REG:
+ case OP_OPTIONAL_REG:
{
const struct mips_reg_operand *reg_op;
@@ -5283,6 +5284,7 @@ match_operand (struct mips_arg_info *arg,
return match_msb_operand (arg, operand);
case OP_REG:
+ case OP_OPTIONAL_REG:
return match_reg_operand (arg, operand);
case OP_REG_PAIR:
@@ -12393,7 +12395,6 @@ mips_ip (char *str, struct mips_cl_insn *ip)
const struct mips_operand *operand;
struct mips_arg_info arg;
struct mips_operand_token *tokens;
- bfd_boolean optional_reg;
unsigned int opcode_extra;
insn_error = NULL;
@@ -12522,17 +12523,17 @@ mips_ip (char *str, struct mips_cl_insn *ip)
/* Handle unary instructions in which only one operand is given.
The source is then the same as the destination. */
if (arg.opnum == 1 && *args == ',')
- switch (args[1])
- {
- case 'r':
- case 'v':
- case 'w':
- case 'W':
- case 'V':
- arg.token = tokens;
- arg.argnum = 1;
- continue;
- }
+ {
+ operand = (mips_opts.micromips
+ ? decode_micromips_operand (args + 1)
+ : decode_mips_operand (args + 1));
+ if (operand && mips_optional_operand_p (operand))
+ {
+ arg.token = tokens;
+ arg.argnum = 1;
+ continue;
+ }
+ }
/* Treat elided base registers as $0. */
if (strcmp (args, "(b)") == 0)
@@ -12593,7 +12594,6 @@ mips_ip (char *str, struct mips_cl_insn *ip)
other operands. */
arg.opnum += 1;
arg.lax_max = FALSE;
- optional_reg = FALSE;
switch (*args)
{
case '+':
@@ -12668,17 +12668,6 @@ mips_ip (char *str, struct mips_cl_insn *ip)
arg.soft_match = FALSE;
break;
- case 'r':
- case 'v':
- case 'w':
- case 'W':
- case 'V':
- /* We have already matched a comma by this point, so the register
- is only optional if there is another operand to come. */
- gas_assert (arg.opnum == 2);
- optional_reg = (args[1] == ',');
- break;
-
case 'I':
if (match_const_int (&arg, &imm_expr.X_add_number, 0))
imm_expr.X_op = O_constant;
@@ -12766,16 +12755,6 @@ mips_ip (char *str, struct mips_cl_insn *ip)
c = args[1];
switch (c)
{
- case 't':
- case 'c':
- case 'e':
- /* We have already matched a comma by this point,
- so the register is only optional if there is another
- operand to come. */
- gas_assert (arg.opnum == 2);
- optional_reg = (args[2] == ',');
- break;
-
case 'D':
case 'E':
if (!forced_insn_length)
@@ -12795,7 +12774,12 @@ mips_ip (char *str, struct mips_cl_insn *ip)
if (!operand)
abort ();
- if (optional_reg
+ /* Skip prefixes. */
+ if (*args == '+' || *args == 'm')
+ args++;
+
+ if (mips_optional_operand_p (operand)
+ && args[1] == ','
&& (arg.token[0].type != OT_REG
|| arg.token[1].type == OT_END))
{
@@ -12808,10 +12792,6 @@ mips_ip (char *str, struct mips_cl_insn *ip)
if (!match_operand (&arg, operand))
break;
- /* Skip prefixes. */
- if (*args == '+' || *args == 'm')
- args++;
-
continue;
}
/* Args don't match. */
@@ -12848,7 +12828,6 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
const struct mips_operand *ext_operand;
struct mips_arg_info arg;
struct mips_operand_token *tokens;
- bfd_boolean optional_reg;
insn_error = NULL;
@@ -12961,14 +12940,15 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
/* Handle unary instructions in which only one operand is given.
The source is then the same as the destination. */
if (arg.opnum == 1 && *args == ',')
- switch (args[1])
- {
- case 'v':
- case 'w':
- arg.token = tokens;
- arg.argnum = 1;
- continue;
- }
+ {
+ operand = decode_mips16_operand (args[1], FALSE);
+ if (operand && mips_optional_operand_p (operand))
+ {
+ arg.token = tokens;
+ arg.argnum = 1;
+ continue;
+ }
+ }
/* Fail the match if there were too few operands. */
if (*args)
@@ -13020,15 +13000,9 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
}
arg.opnum += 1;
- optional_reg = FALSE;
c = *args;
switch (c)
{
- case 'v':
- case 'w':
- optional_reg = (args[1] == ',');
- break;
-
case 'p':
case 'q':
case 'A':
@@ -13094,7 +13068,8 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
}
}
- if (optional_reg
+ if (mips_optional_operand_p (operand)
+ && args[1] == ','
&& (arg.token[0].type != OT_REG
|| arg.token[1].type == OT_END))
{