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.
This commit is contained in:
parent
33b60d5831
commit
0f35dbc4d9
@ -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
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -1,3 +1,8 @@
|
||||
2013-08-19 Richard Sandiford <rdsandiford@googlemail.com>
|
||||
|
||||
* mips.h (OP_OPTIONAL_REG): New mips_operand_type.
|
||||
(mips_optional_operand_p): New function.
|
||||
|
||||
2013-08-04 Jürgen Urban <JuergenUrban@gmx.de>
|
||||
Richard Sandiford <rdsandiford@googlemail.com>
|
||||
|
||||
|
@ -346,6 +346,10 @@ enum mips_operand_type {
|
||||
/* Described by mips_reg_operand. */
|
||||
OP_REG,
|
||||
|
||||
/* Like OP_REG, but can be omitted if the register is the same as the
|
||||
previous operand. */
|
||||
OP_OPTIONAL_REG,
|
||||
|
||||
/* Described by mips_reg_pair_operand. */
|
||||
OP_REG_PAIR,
|
||||
|
||||
@ -574,6 +578,15 @@ struct mips_pcrel_operand
|
||||
unsigned int flip_isa_bit : 1;
|
||||
};
|
||||
|
||||
/* Return true if the assembly syntax allows OPERAND to be omitted. */
|
||||
|
||||
static inline bfd_boolean
|
||||
mips_optional_operand_p (const struct mips_operand *operand)
|
||||
{
|
||||
return (operand->type == OP_OPTIONAL_REG
|
||||
|| operand->type == OP_REPEAT_PREV_REG);
|
||||
}
|
||||
|
||||
/* Return a version of INSN in which the field specified by OPERAND
|
||||
has value UVAL. */
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
2013-08-19 Richard Sandiford <rdsandiford@googlemail.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2013-08-19 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* i386-dis.c (PREFIX_EVEX_0F3A3E): Removed.
|
||||
|
@ -53,9 +53,9 @@ decode_micromips_operand (const char *p)
|
||||
{
|
||||
case 'a': MAPPED_REG (0, 0, GP, reg_28_map);
|
||||
case 'b': MAPPED_REG (3, 23, GP, reg_m16_map);
|
||||
case 'c': MAPPED_REG (3, 4, GP, reg_m16_map);
|
||||
case 'c': OPTIONAL_MAPPED_REG (3, 4, GP, reg_m16_map);
|
||||
case 'd': MAPPED_REG (3, 7, GP, reg_m16_map);
|
||||
case 'e': MAPPED_REG (3, 1, GP, reg_m16_map);
|
||||
case 'e': OPTIONAL_MAPPED_REG (3, 1, GP, reg_m16_map);
|
||||
case 'f': MAPPED_REG (3, 3, GP, reg_m16_map);
|
||||
case 'g': MAPPED_REG (3, 0, GP, reg_m16_map);
|
||||
case 'h': REG_PAIR (3, 7, GP, reg_h_map);
|
||||
@ -144,7 +144,7 @@ decode_micromips_operand (const char *p)
|
||||
case 'R': REG (5, 6, FP);
|
||||
case 'S': REG (5, 16, FP);
|
||||
case 'T': REG (5, 21, FP);
|
||||
case 'V': REG (5, 16, FP);
|
||||
case 'V': OPTIONAL_REG (5, 16, FP);
|
||||
|
||||
case 'a': JUMP (26, 0, 1);
|
||||
case 'b': REG (5, 16, GP);
|
||||
@ -158,12 +158,12 @@ decode_micromips_operand (const char *p)
|
||||
case 'o': SINT (16, 0);
|
||||
case 'p': BRANCH (16, 0, 1);
|
||||
case 'q': HINT (10, 6);
|
||||
case 'r': REG (5, 16, GP);
|
||||
case 'r': OPTIONAL_REG (5, 16, GP);
|
||||
case 's': REG (5, 16, GP);
|
||||
case 't': REG (5, 21, GP);
|
||||
case 'u': HINT (16, 0);
|
||||
case 'v': REG (5, 16, GP);
|
||||
case 'w': REG (5, 21, GP);
|
||||
case 'v': OPTIONAL_REG (5, 16, GP);
|
||||
case 'w': OPTIONAL_REG (5, 21, GP);
|
||||
case 'y': REG (5, 6, GP);
|
||||
case 'z': MAPPED_REG (0, 0, GP, reg_0_map);
|
||||
}
|
||||
|
@ -1042,6 +1042,7 @@ print_insn_arg (struct disassemble_info *info,
|
||||
break;
|
||||
|
||||
case OP_REG:
|
||||
case OP_OPTIONAL_REG:
|
||||
{
|
||||
const struct mips_reg_operand *reg_op;
|
||||
|
||||
|
@ -69,6 +69,14 @@
|
||||
return &op.root; \
|
||||
}
|
||||
|
||||
#define OPTIONAL_REG(SIZE, LSB, BANK) \
|
||||
{ \
|
||||
static const struct mips_reg_operand op = { \
|
||||
{ OP_OPTIONAL_REG, SIZE, LSB }, OP_REG_##BANK, 0 \
|
||||
}; \
|
||||
return &op.root; \
|
||||
}
|
||||
|
||||
#define MAPPED_REG(SIZE, LSB, BANK, MAP) \
|
||||
{ \
|
||||
typedef char ATTRIBUTE_UNUSED \
|
||||
@ -79,6 +87,16 @@
|
||||
return &op.root; \
|
||||
}
|
||||
|
||||
#define OPTIONAL_MAPPED_REG(SIZE, LSB, BANK, MAP) \
|
||||
{ \
|
||||
typedef char ATTRIBUTE_UNUSED \
|
||||
static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \
|
||||
static const struct mips_reg_operand op = { \
|
||||
{ OP_OPTIONAL_REG, SIZE, LSB }, OP_REG_##BANK, MAP \
|
||||
}; \
|
||||
return &op.root; \
|
||||
}
|
||||
|
||||
#define REG_PAIR(SIZE, LSB, BANK, MAP) \
|
||||
{ \
|
||||
typedef char ATTRIBUTE_UNUSED \
|
||||
|
@ -134,8 +134,8 @@ decode_mips_operand (const char *p)
|
||||
case 'S': REG (5, 11, FP);
|
||||
case 'T': REG (5, 16, FP);
|
||||
case 'U': SPECIAL (10, 11, CLO_CLZ_DEST);
|
||||
case 'V': REG (5, 11, FP);
|
||||
case 'W': REG (5, 16, FP);
|
||||
case 'V': OPTIONAL_REG (5, 11, FP);
|
||||
case 'W': OPTIONAL_REG (5, 16, FP);
|
||||
case 'X': REG (5, 6, VEC);
|
||||
case 'Y': REG (5, 11, VEC);
|
||||
case 'Z': REG (5, 16, VEC);
|
||||
@ -153,12 +153,12 @@ decode_mips_operand (const char *p)
|
||||
case 'o': SINT (16, 0);
|
||||
case 'p': BRANCH (16, 0, 2);
|
||||
case 'q': HINT (10, 6);
|
||||
case 'r': REG (5, 21, GP);
|
||||
case 'r': OPTIONAL_REG (5, 21, GP);
|
||||
case 's': REG (5, 21, GP);
|
||||
case 't': REG (5, 16, GP);
|
||||
case 'u': HINT (16, 0);
|
||||
case 'v': REG (5, 21, GP);
|
||||
case 'w': REG (5, 16, GP);
|
||||
case 'v': OPTIONAL_REG (5, 21, GP);
|
||||
case 'w': OPTIONAL_REG (5, 16, GP);
|
||||
case 'x': REG (0, 0, GP);
|
||||
case 'z': MAPPED_REG (0, 0, GP, reg_0_map);
|
||||
}
|
||||
|
@ -66,8 +66,8 @@ decode_mips16_operand (char type, bfd_boolean extended_p)
|
||||
case 'i': JALX (26, 0, 2);
|
||||
case 'l': SPECIAL (6, 5, ENTRY_EXIT_LIST);
|
||||
case 'm': SPECIAL (7, 0, SAVE_RESTORE_LIST);
|
||||
case 'v': MAPPED_REG (3, 8, GP, reg_m16_map);
|
||||
case 'w': MAPPED_REG (3, 5, GP, reg_m16_map);
|
||||
case 'v': OPTIONAL_MAPPED_REG (3, 8, GP, reg_m16_map);
|
||||
case 'w': OPTIONAL_MAPPED_REG (3, 5, GP, reg_m16_map);
|
||||
case 'x': MAPPED_REG (3, 8, GP, reg_m16_map);
|
||||
case 'y': MAPPED_REG (3, 5, GP, reg_m16_map);
|
||||
case 'z': MAPPED_REG (3, 2, GP, reg_m16_map);
|
||||
|
Loading…
Reference in New Issue
Block a user