x86: introduce operand type "instance"

Special register "class" instances can't be combined with one another
(neither in templates nor in register entries), and hence it is not a
good use of resources (memory as well as execution time) to represent
them as individual bits of a bit field.

Furthermore the generalization becoming possible will allow
improvements to the handling of insns accepting only individual
registers as their operands.
This commit is contained in:
Jan Beulich 2019-11-12 09:07:34 +01:00
parent aa16be3993
commit 75e5731b8f
9 changed files with 14307 additions and 14228 deletions

View File

@ -1,3 +1,14 @@
2019-11-12 Jan Beulich <jbeulich@suse.com>
* config/tc-i386.c (operand_type_set, operand_type_and,
operand_type_and_not, operand_type_or, operand_type_xor): Handle
"instance" field specially.
(operand_size_match, md_assemble, match_template, process_suffix,
check_byte_reg, check_long_reg, check_qword_reg, check_word_reg,
process_operands, build_modrm_byte): Use "instance" instead of
"acc" / "inoutportreg" / "shiftcount" fields.
(optimize_imm): Adjust comment.
2019-11-11 Jan Beulich <jbeulich@suse.com>
* testsuite/gas/aarch64/illegal-sve2.s: Add smaxp/sminp cases

View File

@ -1613,6 +1613,7 @@ operand_type_set (union i386_operand_type *x, unsigned int v)
}
x->bitfield.class = ClassNone;
x->bitfield.instance = InstanceNone;
}
static INLINE int
@ -1829,6 +1830,8 @@ operand_type_and (i386_operand_type x, i386_operand_type y)
{
if (x.bitfield.class != y.bitfield.class)
x.bitfield.class = ClassNone;
if (x.bitfield.instance != y.bitfield.instance)
x.bitfield.instance = InstanceNone;
switch (ARRAY_SIZE (x.array))
{
@ -1851,6 +1854,7 @@ static INLINE i386_operand_type
operand_type_and_not (i386_operand_type x, i386_operand_type y)
{
gas_assert (y.bitfield.class == ClassNone);
gas_assert (y.bitfield.instance == InstanceNone);
switch (ARRAY_SIZE (x.array))
{
@ -1875,6 +1879,9 @@ operand_type_or (i386_operand_type x, i386_operand_type y)
gas_assert (x.bitfield.class == ClassNone ||
y.bitfield.class == ClassNone ||
x.bitfield.class == y.bitfield.class);
gas_assert (x.bitfield.instance == InstanceNone ||
y.bitfield.instance == InstanceNone ||
x.bitfield.instance == y.bitfield.instance);
switch (ARRAY_SIZE (x.array))
{
@ -1897,6 +1904,7 @@ static INLINE i386_operand_type
operand_type_xor (i386_operand_type x, i386_operand_type y)
{
gas_assert (y.bitfield.class == ClassNone);
gas_assert (y.bitfield.instance == InstanceNone);
switch (ARRAY_SIZE (x.array))
{
@ -2084,7 +2092,7 @@ operand_size_match (const insn_template *t)
break;
}
if (t->operand_types[j].bitfield.acc
if (t->operand_types[j].bitfield.instance == Accum
&& (!match_operand_size (t, j, j) || !match_simd_size (t, j, j)))
{
match = 0;
@ -2121,7 +2129,7 @@ mismatch:
&& !match_simd_size (t, j, given))
goto mismatch;
if (t->operand_types[j].bitfield.acc
if (t->operand_types[j].bitfield.instance == Accum
&& (!match_operand_size (t, j, given)
|| !match_simd_size (t, j, given)))
goto mismatch;
@ -4453,9 +4461,8 @@ md_assemble (char *line)
with 3 operands or less. */
if (i.operands <= 3)
for (j = 0; j < i.operands; j++)
if (i.types[j].bitfield.inoutportreg
|| i.types[j].bitfield.shiftcount
|| (i.types[j].bitfield.acc && !i.types[j].bitfield.xmmword))
if (i.types[j].bitfield.instance != InstanceNone
&& !i.types[j].bitfield.xmmword)
i.reg_operands--;
/* ImmExt should be processed after SSE2AVX. */
@ -5076,9 +5083,9 @@ optimize_imm (void)
else if (i.reg_operands)
{
/* Figure out a suffix from the last register operand specified.
We can't do this properly yet, ie. excluding InOutPortReg,
but the following works for instructions with immediates.
In any case, we can't set i.suffix yet. */
We can't do this properly yet, i.e. excluding special register
instances, but the following works for instructions with
immediates. In any case, we can't set i.suffix yet. */
for (op = i.operands; --op >= 0;)
if (i.types[op].bitfield.class != Reg)
continue;
@ -5897,15 +5904,17 @@ match_template (char mnem_suffix)
zero-extend %eax to %rax. */
if (flag_code == CODE_64BIT
&& t->base_opcode == 0x90
&& i.types[0].bitfield.acc && i.types[0].bitfield.dword
&& i.types[1].bitfield.acc && i.types[1].bitfield.dword)
&& i.types[0].bitfield.instance == Accum
&& i.types[0].bitfield.dword
&& i.types[1].bitfield.instance == Accum
&& i.types[1].bitfield.dword)
continue;
/* xrelease mov %eax, <disp> is another special case. It must not
match the accumulator-only encoding of mov. */
if (flag_code != CODE_64BIT
&& i.hle_prefix
&& t->base_opcode == 0xa0
&& i.types[0].bitfield.acc
&& i.types[0].bitfield.instance == Accum
&& (i.flags[1] & Operand_Mem))
continue;
/* Fall through. */
@ -6284,8 +6293,8 @@ process_suffix (void)
}
for (op = i.operands; --op >= 0;)
if (!i.tm.operand_types[op].bitfield.inoutportreg
&& !i.tm.operand_types[op].bitfield.shiftcount)
if (i.tm.operand_types[op].bitfield.instance == InstanceNone
|| i.tm.operand_types[op].bitfield.instance == Accum)
{
if (i.types[op].bitfield.class != Reg)
continue;
@ -6502,8 +6511,10 @@ process_suffix (void)
&& ! (i.operands == 2
&& i.tm.base_opcode == 0x90
&& i.tm.extension_opcode == None
&& i.types[0].bitfield.acc && i.types[0].bitfield.qword
&& i.types[1].bitfield.acc && i.types[1].bitfield.qword))
&& i.types[0].bitfield.instance == Accum
&& i.types[0].bitfield.qword
&& i.types[1].bitfield.instance == Accum
&& i.types[1].bitfield.qword))
i.rex |= REX_W;
break;
@ -6565,7 +6576,8 @@ check_byte_reg (void)
continue;
/* I/O port address operands are OK too. */
if (i.tm.operand_types[op].bitfield.inoutportreg)
if (i.tm.operand_types[op].bitfield.instance == RegD
&& i.tm.operand_types[op].bitfield.word)
continue;
/* crc32 doesn't generate this warning. */
@ -6626,7 +6638,7 @@ check_long_reg (void)
them. (eg. movzb) */
else if (i.types[op].bitfield.byte
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
|| i.tm.operand_types[op].bitfield.instance == Accum)
&& (i.tm.operand_types[op].bitfield.word
|| i.tm.operand_types[op].bitfield.dword))
{
@ -6641,7 +6653,7 @@ check_long_reg (void)
else if ((!quiet_warnings || flag_code == CODE_64BIT)
&& i.types[op].bitfield.word
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
|| i.tm.operand_types[op].bitfield.instance == Accum)
&& i.tm.operand_types[op].bitfield.dword)
{
/* Prohibit these changes in the 64bit mode, since the
@ -6663,7 +6675,7 @@ check_long_reg (void)
/* Warn if the r prefix on a general reg is present. */
else if (i.types[op].bitfield.qword
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
|| i.tm.operand_types[op].bitfield.instance == Accum)
&& i.tm.operand_types[op].bitfield.dword)
{
if (intel_syntax
@ -6697,7 +6709,7 @@ check_qword_reg (void)
them. (eg. movzb) */
else if (i.types[op].bitfield.byte
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
|| i.tm.operand_types[op].bitfield.instance == Accum)
&& (i.tm.operand_types[op].bitfield.word
|| i.tm.operand_types[op].bitfield.dword))
{
@ -6712,7 +6724,7 @@ check_qword_reg (void)
else if ((i.types[op].bitfield.word
|| i.types[op].bitfield.dword)
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
|| i.tm.operand_types[op].bitfield.instance == Accum)
&& i.tm.operand_types[op].bitfield.qword)
{
/* Prohibit these changes in the 64bit mode, since the
@ -6747,7 +6759,7 @@ check_word_reg (void)
them. (eg. movzb) */
else if (i.types[op].bitfield.byte
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
|| i.tm.operand_types[op].bitfield.instance == Accum)
&& (i.tm.operand_types[op].bitfield.word
|| i.tm.operand_types[op].bitfield.dword))
{
@ -6763,7 +6775,7 @@ check_word_reg (void)
&& (i.types[op].bitfield.dword
|| i.types[op].bitfield.qword)
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
|| i.tm.operand_types[op].bitfield.instance == Accum)
&& i.tm.operand_types[op].bitfield.word)
{
/* Prohibit these changes in the 64bit mode, since the
@ -6888,14 +6900,14 @@ process_operands (void)
&& MAX_OPERANDS > dupl
&& operand_type_equal (&i.types[dest], &regxmm));
if (i.tm.operand_types[0].bitfield.acc
if (i.tm.operand_types[0].bitfield.instance == Accum
&& i.tm.operand_types[0].bitfield.xmmword)
{
if (i.tm.opcode_modifier.vexsources == VEX3SOURCES)
{
/* Keep xmm0 for instructions with VEX prefix and 3
sources. */
i.tm.operand_types[0].bitfield.acc = 0;
i.tm.operand_types[0].bitfield.instance = InstanceNone;
i.tm.operand_types[0].bitfield.class = RegSIMD;
goto duplicate;
}
@ -6960,7 +6972,7 @@ duplicate:
if (i.tm.opcode_modifier.immext)
process_immext ();
}
else if (i.tm.operand_types[0].bitfield.acc
else if (i.tm.operand_types[0].bitfield.instance == Accum
&& i.tm.operand_types[0].bitfield.xmmword)
{
unsigned int j;
@ -7207,9 +7219,11 @@ build_modrm_byte (void)
gas_assert (i.imm_operands == 1
|| (i.imm_operands == 0
&& (i.tm.opcode_modifier.vexvvvv == VEXXDS
|| i.types[0].bitfield.shiftcount)));
|| (i.types[0].bitfield.instance == RegC
&& i.types[0].bitfield.byte))));
if (operand_type_check (i.types[0], imm)
|| i.types[0].bitfield.shiftcount)
|| (i.types[0].bitfield.instance == RegC
&& i.types[0].bitfield.byte))
source = 1;
else
source = 0;
@ -10320,7 +10334,8 @@ i386_att_operand (char *operand_string)
/* Special case for (%dx) while doing input/output op. */
if (i.base_reg
&& i.base_reg->reg_type.bitfield.inoutportreg
&& i.base_reg->reg_type.bitfield.instance == RegD
&& i.base_reg->reg_type.bitfield.word
&& i.index_reg == 0
&& i.log2_scale_factor == 0
&& i.seg[i.mem_operands] == 0

View File

@ -1,3 +1,24 @@
2019-11-12 Jan Beulich <jbeulich@suse.com>
* i386-gen.c (operand_type_init): Adjust
OPERAND_TYPE_INOUTPORTREG, OPERAND_TYPE_SHIFTCOUNT,
OPERAND_TYPE_FLOATACC, OPERAND_TYPE_ACC8, OPERAND_TYPE_ACC16,
OPERAND_TYPE_ACC32, and OPERAND_TYPE_ACC64 entries.
(operand_instances): New.
(operand_types): Drop InOutPortReg, ShiftCount, and Acc entries.
(output_operand_type): New parameter "instance". Process it.
(process_i386_operand_type): New local variable "instance".
(main): Adjust static assertions.
* i386-opc.h (INSTANCE_WIDTH): Define.
(enum operand_instance): New.
(Acc, InOutPortReg, ShiftCount): Replace by ClassInstance.
(union i386_operand_type): Replace acc, inoutportreg, and
shiftcount by instance.
* i386-opc.tbl (Acc, InOutPortReg, ShiftCount): Define.
* i386-reg.tbl (st, al, cl, ax, dx, eax, rax, xmm0, st(0)):
Add Instance=.
* i386-init.h, i386-tbl.h: Re-generate.
2019-11-11 Jan Beulich <jbeulich@suse.com>
* aarch64-tbl.h (aarch64_opcode_table): Switch SVE2's

View File

@ -422,9 +422,9 @@ static initializer operand_type_init[] =
{ "OPERAND_TYPE_DISP64",
"Disp64" },
{ "OPERAND_TYPE_INOUTPORTREG",
"InOutPortReg" },
"Instance=RegD|Word" },
{ "OPERAND_TYPE_SHIFTCOUNT",
"ShiftCount" },
"Instance=RegC|Byte" },
{ "OPERAND_TYPE_CONTROL",
"Class=RegCR" },
{ "OPERAND_TYPE_TEST",
@ -434,7 +434,7 @@ static initializer operand_type_init[] =
{ "OPERAND_TYPE_FLOATREG",
"Class=Reg|Tbyte" },
{ "OPERAND_TYPE_FLOATACC",
"Acc|Tbyte" },
"Instance=Accum|Tbyte" },
{ "OPERAND_TYPE_SREG",
"Class=SReg" },
{ "OPERAND_TYPE_JUMPABSOLUTE",
@ -454,13 +454,13 @@ static initializer operand_type_init[] =
{ "OPERAND_TYPE_ESSEG",
"EsSeg" },
{ "OPERAND_TYPE_ACC8",
"Acc|Byte" },
"Instance=Accum|Byte" },
{ "OPERAND_TYPE_ACC16",
"Acc|Word" },
"Instance=Accum|Word" },
{ "OPERAND_TYPE_ACC32",
"Acc|Dword" },
"Instance=Accum|Dword" },
{ "OPERAND_TYPE_ACC64",
"Acc|Qword" },
"Instance=Accum|Qword" },
{ "OPERAND_TYPE_DISP16_32",
"Disp16|Disp32" },
{ "OPERAND_TYPE_ANYDISP",
@ -695,6 +695,19 @@ static const struct {
#undef CLASS
#define INSTANCE(n) #n, n
static const struct {
const char *name;
enum operand_instance value;
} operand_instances[] = {
INSTANCE (Accum),
INSTANCE (RegC),
INSTANCE (RegD),
};
#undef INSTANCE
static bitfield operand_types[] =
{
BITFIELD (Imm1),
@ -710,9 +723,6 @@ static bitfield operand_types[] =
BITFIELD (Disp32),
BITFIELD (Disp32S),
BITFIELD (Disp64),
BITFIELD (InOutPortReg),
BITFIELD (ShiftCount),
BITFIELD (Acc),
BITFIELD (JumpAbsolute),
BITFIELD (EsSeg),
BITFIELD (Byte),
@ -1147,20 +1157,21 @@ enum stage {
static void
output_operand_type (FILE *table, enum operand_class class,
enum operand_instance instance,
const bitfield *types, unsigned int size,
enum stage stage, const char *indent)
{
unsigned int i;
fprintf (table, "{ { %d, ", class);
fprintf (table, "{ { %d, %d, ", class, instance);
for (i = 0; i < size - 1; i++)
{
if (((i + 2) % 20) != 0)
if (((i + 3) % 20) != 0)
fprintf (table, "%d, ", types[i].value);
else
fprintf (table, "%d,", types[i].value);
if (((i + 2) % 20) == 0)
if (((i + 3) % 20) == 0)
{
/* We need \\ for macro. */
if (stage == stage_macros)
@ -1179,6 +1190,7 @@ process_i386_operand_type (FILE *table, char *op, enum stage stage,
{
char *str, *next, *last;
enum operand_class class = ClassNone;
enum operand_instance instance = InstanceNone;
bitfield types [ARRAY_SIZE (operand_types)];
/* Copy the default operand type. */
@ -1206,6 +1218,17 @@ process_i386_operand_type (FILE *table, char *op, enum stage stage,
break;
}
}
if (str && !strncmp(str, "Instance=", 9))
{
for (i = 0; i < ARRAY_SIZE(operand_instances); ++i)
if (!strcmp(str + 9, operand_instances[i].name))
{
instance = operand_instances[i].value;
str = NULL;
break;
}
}
}
if (str)
{
@ -1226,8 +1249,8 @@ process_i386_operand_type (FILE *table, char *op, enum stage stage,
set_bitfield("Disp32S", types, 1, ARRAY_SIZE (types), lineno);
}
}
output_operand_type (table, class, types, ARRAY_SIZE (types), stage,
indent);
output_operand_type (table, class, instance, types, ARRAY_SIZE (types),
stage, indent);
}
static void
@ -1717,9 +1740,11 @@ main (int argc, char **argv)
/* Check the unused bitfield in i386_operand_type. */
#ifdef OTUnused
static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH == OTNum + 1);
static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
== OTNum + 1);
#else
static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH == OTNum);
static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
== OTNum);
c = OTNumOfBits - OTMax - 1;
if (c)

View File

@ -1365,196 +1365,196 @@
#define OPERAND_TYPE_NONE \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_REG8 \
{ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_REG16 \
{ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_REG32 \
{ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_REG64 \
{ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } }
0, 1, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM1 \
{ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM8 \
{ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM8S \
{ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM16 \
{ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM32 \
{ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM32S \
{ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM64 \
{ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_BASEINDEX \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_DISP8 \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_DISP16 \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_DISP32 \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_DISP32S \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_DISP64 \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_INOUTPORTREG \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_SHIFTCOUNT \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_CONTROL \
{ { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_TEST \
{ { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_DEBUG \
{ { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_FLOATREG \
{ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 } }
0, 0, 1, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_FLOATACC \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 } }
{ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 1, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_SREG \
{ { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_JUMPABSOLUTE \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_REGMMX \
{ { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_REGXMM \
{ { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 } }
0, 0, 0, 1, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_REGYMM \
{ { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } }
0, 0, 0, 0, 1, 0, 0, 0, 0 } }
#define OPERAND_TYPE_REGZMM \
{ { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 } }
0, 0, 0, 0, 0, 1, 0, 0, 0 } }
#define OPERAND_TYPE_REGMASK \
{ { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_REGBND \
{ { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_ESSEG \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_ACC8 \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_ACC16 \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, \
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_ACC32 \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, \
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_ACC64 \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 1, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_DISP16_32 \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_ANYDISP \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM16_32 \
{ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM16_32S \
{ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM16_32_32S \
{ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM32_64 \
{ { 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM32_32S_DISP32 \
{ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM64_DISP64 \
{ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM32_32S_64_DISP32 \
{ { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_IMM32_32S_64_DISP32_64 \
{ { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }
#define OPERAND_TYPE_ANYIMM \
{ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
{ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0 } }

View File

@ -719,12 +719,23 @@ enum operand_class
RegBND, /* Bound register */
};
/* Special operand instances. */
#define INSTANCE_WIDTH 3
enum operand_instance
{
InstanceNone,
Accum, /* Accumulator %al/%ax/%eax/%rax/%st(0)/%xmm0 */
RegC, /* Register to hold shift count = %cl */
RegD, /* Register to hold in/out port addr = %dx */
};
/* Position of operand_type bits. */
enum
{
/* Class */
Class = CLASS_WIDTH - 1,
/* Class and Instance */
ClassInstance = CLASS_WIDTH + INSTANCE_WIDTH - 1,
/* 1 bit immediate */
Imm1,
/* 8 bit immediate */
@ -756,14 +767,8 @@ enum
Disp32S,
/* 64 bit displacement */
Disp64,
/* Accumulator %al/%ax/%eax/%rax/%st(0)/%xmm0 */
Acc,
/* Register which can be used for base or index in memory operand. */
BaseIndex,
/* Register to hold in/out port addr = dx */
InOutPortReg,
/* Register to hold shift count = cl */
ShiftCount,
/* Absolute address for jump. */
JumpAbsolute,
/* String insn operand with fixed es segment */
@ -809,6 +814,7 @@ typedef union i386_operand_type
struct
{
unsigned int class:CLASS_WIDTH;
unsigned int instance:INSTANCE_WIDTH;
unsigned int imm1:1;
unsigned int imm8:1;
unsigned int imm8s:1;
@ -821,10 +827,7 @@ typedef union i386_operand_type
unsigned int disp32:1;
unsigned int disp32s:1;
unsigned int disp64:1;
unsigned int acc:1;
unsigned int baseindex:1;
unsigned int inoutportreg:1;
unsigned int shiftcount:1;
unsigned int jumpabsolute:1;
unsigned int esseg:1;
unsigned int byte:1;

View File

@ -27,6 +27,10 @@
#define Reg32 Class=Reg|Dword
#define Reg64 Class=Reg|Qword
#define Acc Instance=Accum
#define ShiftCount Instance=RegC|Byte
#define InOutPortReg Instance=RegD|Word
#define FloatAcc Acc|Tbyte
#define FloatReg Class=Reg|Tbyte

View File

@ -19,10 +19,10 @@
// 02110-1301, USA.
// Make %st first as we test for it.
st, Class=Reg|Acc|Tbyte, 0, 0, 11, 33
st, Class=Reg|Instance=Accum|Tbyte, 0, 0, 11, 33
// 8 bit regs
al, Class=Reg|Acc|Byte, 0, 0, Dw2Inval, Dw2Inval
cl, Class=Reg|Byte|ShiftCount, 0, 1, Dw2Inval, Dw2Inval
al, Class=Reg|Instance=Accum|Byte, 0, 0, Dw2Inval, Dw2Inval
cl, Class=Reg|Instance=RegC|Byte, 0, 1, Dw2Inval, Dw2Inval
dl, Class=Reg|Byte, 0, 2, Dw2Inval, Dw2Inval
bl, Class=Reg|Byte, 0, 3, Dw2Inval, Dw2Inval
ah, Class=Reg|Byte, 0, 4, Dw2Inval, Dw2Inval
@ -46,9 +46,9 @@ r13b, Class=Reg|Byte, RegRex|RegRex64, 5, Dw2Inval, Dw2Inval
r14b, Class=Reg|Byte, RegRex|RegRex64, 6, Dw2Inval, Dw2Inval
r15b, Class=Reg|Byte, RegRex|RegRex64, 7, Dw2Inval, Dw2Inval
// 16 bit regs
ax, Class=Reg|Acc|Word, 0, 0, Dw2Inval, Dw2Inval
ax, Class=Reg|Instance=Accum|Word, 0, 0, Dw2Inval, Dw2Inval
cx, Class=Reg|Word, 0, 1, Dw2Inval, Dw2Inval
dx, Class=Reg|Word|InOutPortReg, 0, 2, Dw2Inval, Dw2Inval
dx, Class=Reg|Instance=RegD|Word, 0, 2, Dw2Inval, Dw2Inval
bx, Class=Reg|Word|BaseIndex, 0, 3, Dw2Inval, Dw2Inval
sp, Class=Reg|Word, 0, 4, Dw2Inval, Dw2Inval
bp, Class=Reg|Word|BaseIndex, 0, 5, Dw2Inval, Dw2Inval
@ -63,7 +63,7 @@ r13w, Class=Reg|Word, RegRex, 5, Dw2Inval, Dw2Inval
r14w, Class=Reg|Word, RegRex, 6, Dw2Inval, Dw2Inval
r15w, Class=Reg|Word, RegRex, 7, Dw2Inval, Dw2Inval
// 32 bit regs
eax, Class=Reg|Acc|Dword|BaseIndex, 0, 0, 0, Dw2Inval
eax, Class=Reg|Instance=Accum|Dword|BaseIndex, 0, 0, 0, Dw2Inval
ecx, Class=Reg|Dword|BaseIndex, 0, 1, 1, Dw2Inval
edx, Class=Reg|Dword|BaseIndex, 0, 2, 2, Dw2Inval
ebx, Class=Reg|Dword|BaseIndex, 0, 3, 3, Dw2Inval
@ -79,7 +79,7 @@ r12d, Class=Reg|Dword|BaseIndex, RegRex, 4, Dw2Inval, Dw2Inval
r13d, Class=Reg|Dword|BaseIndex, RegRex, 5, Dw2Inval, Dw2Inval
r14d, Class=Reg|Dword|BaseIndex, RegRex, 6, Dw2Inval, Dw2Inval
r15d, Class=Reg|Dword|BaseIndex, RegRex, 7, Dw2Inval, Dw2Inval
rax, Class=Reg|Acc|Qword|BaseIndex, 0, 0, Dw2Inval, 0
rax, Class=Reg|Instance=Accum|Qword|BaseIndex, 0, 0, Dw2Inval, 0
rcx, Class=Reg|Qword|BaseIndex, 0, 1, Dw2Inval, 2
rdx, Class=Reg|Qword|BaseIndex, 0, 2, Dw2Inval, 1
rbx, Class=Reg|Qword|BaseIndex, 0, 3, Dw2Inval, 3
@ -180,7 +180,7 @@ mm4, Class=RegMMX, 0, 4, 33, 45
mm5, Class=RegMMX, 0, 5, 34, 46
mm6, Class=RegMMX, 0, 6, 35, 47
mm7, Class=RegMMX, 0, 7, 36, 48
xmm0, Class=RegSIMD|Acc|Xmmword, 0, 0, 21, 17
xmm0, Class=RegSIMD|Instance=Accum|Xmmword, 0, 0, 21, 17
xmm1, Class=RegSIMD|Xmmword, 0, 1, 22, 18
xmm2, Class=RegSIMD|Xmmword, 0, 2, 23, 19
xmm3, Class=RegSIMD|Xmmword, 0, 3, 24, 20
@ -292,7 +292,7 @@ eip, Dword, RegRex64, RegIP, 8, Dw2Inval
riz, Qword|BaseIndex, RegRex64, RegIZ, Dw2Inval, Dw2Inval
eiz, Dword|BaseIndex, 0, RegIZ, Dw2Inval, Dw2Inval
// fp regs.
st(0), Class=Reg|Acc|Tbyte, 0, 0, 11, 33
st(0), Class=Reg|Instance=Accum|Tbyte, 0, 0, 11, 33
st(1), Class=Reg|Tbyte, 0, 1, 12, 34
st(2), Class=Reg|Tbyte, 0, 2, 13, 35
st(3), Class=Reg|Tbyte, 0, 3, 14, 36

File diff suppressed because it is too large Load Diff