x86: introduce operand type "class"

Many operand types, in particular the various kinds of registers, 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.
This commit is contained in:
Jan Beulich 2019-11-08 09:03:23 +01:00
parent 831bd6aa3b
commit bab6aec125
8 changed files with 238 additions and 146 deletions

View File

@ -1,3 +1,17 @@
2019-11-08 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
"class" field specially.
(anyimm): New.
(operand_type_check, operand_size_match,
operand_type_register_match, pi, md_assemble, is_short_form,
process_suffix, check_byte_reg, check_long_reg, check_qword_reg,
check_word_reg, process_operands, build_modrm_byte): Use "class"
instead of "reg" field.
(optimize_imm): Likewise. Reduce redundancy. Adjust calculation
of "allowed".
2019-11-07 Mihail Ionescu <mihail.ionescu@arm.com>
* testsuite/gas/aarch64/dgh.s: New test.

View File

@ -1611,6 +1611,8 @@ operand_type_set (union i386_operand_type *x, unsigned int v)
default:
abort ();
}
x->bitfield.class = ClassNone;
}
static INLINE int
@ -1825,6 +1827,9 @@ cpu_flags_match (const insn_template *t)
static INLINE i386_operand_type
operand_type_and (i386_operand_type x, i386_operand_type y)
{
if (x.bitfield.class != y.bitfield.class)
x.bitfield.class = ClassNone;
switch (ARRAY_SIZE (x.array))
{
case 3:
@ -1845,6 +1850,8 @@ operand_type_and (i386_operand_type x, i386_operand_type y)
static INLINE i386_operand_type
operand_type_and_not (i386_operand_type x, i386_operand_type y)
{
gas_assert (y.bitfield.class == ClassNone);
switch (ARRAY_SIZE (x.array))
{
case 3:
@ -1865,6 +1872,10 @@ operand_type_and_not (i386_operand_type x, i386_operand_type y)
static INLINE i386_operand_type
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);
switch (ARRAY_SIZE (x.array))
{
case 3:
@ -1885,6 +1896,8 @@ operand_type_or (i386_operand_type x, i386_operand_type y)
static INLINE i386_operand_type
operand_type_xor (i386_operand_type x, i386_operand_type y)
{
gas_assert (y.bitfield.class == ClassNone);
switch (ARRAY_SIZE (x.array))
{
case 3:
@ -1906,8 +1919,8 @@ static const i386_operand_type disp16 = OPERAND_TYPE_DISP16;
static const i386_operand_type disp32 = OPERAND_TYPE_DISP32;
static const i386_operand_type disp32s = OPERAND_TYPE_DISP32S;
static const i386_operand_type disp16_32 = OPERAND_TYPE_DISP16_32;
static const i386_operand_type anydisp
= OPERAND_TYPE_ANYDISP;
static const i386_operand_type anydisp = OPERAND_TYPE_ANYDISP;
static const i386_operand_type anyimm = OPERAND_TYPE_ANYIMM;
static const i386_operand_type regxmm = OPERAND_TYPE_REGXMM;
static const i386_operand_type regmask = OPERAND_TYPE_REGMASK;
static const i386_operand_type imm8 = OPERAND_TYPE_IMM8;
@ -1934,7 +1947,7 @@ operand_type_check (i386_operand_type t, enum operand_type c)
switch (c)
{
case reg:
return t.bitfield.reg;
return t.bitfield.class == Reg;
case imm:
return (t.bitfield.imm8
@ -2052,11 +2065,11 @@ operand_size_match (const insn_template *t)
/* Check memory and accumulator operand size. */
for (j = 0; j < i.operands; j++)
{
if (!i.types[j].bitfield.reg && !i.types[j].bitfield.regsimd
if (i.types[j].bitfield.class != Reg && !i.types[j].bitfield.regsimd
&& t->operand_types[j].bitfield.anysize)
continue;
if (t->operand_types[j].bitfield.reg
if (t->operand_types[j].bitfield.class == Reg
&& !match_operand_size (t, j, j))
{
match = 0;
@ -2099,7 +2112,7 @@ mismatch:
{
unsigned int given = i.operands - j - 1;
if (t->operand_types[j].bitfield.reg
if (t->operand_types[j].bitfield.class == Reg
&& !match_operand_size (t, j, given))
goto mismatch;
@ -2159,14 +2172,14 @@ operand_type_register_match (i386_operand_type g0,
i386_operand_type g1,
i386_operand_type t1)
{
if (!g0.bitfield.reg
if (g0.bitfield.class != Reg
&& !g0.bitfield.regsimd
&& (!operand_type_check (g0, anymem)
|| g0.bitfield.unspecified
|| !t0.bitfield.regsimd))
return 1;
if (!g1.bitfield.reg
if (g1.bitfield.class != Reg
&& !g1.bitfield.regsimd
&& (!operand_type_check (g1, anymem)
|| g1.bitfield.unspecified
@ -3032,7 +3045,7 @@ pi (const char *line, i386_insn *x)
fprintf (stdout, " #%d: ", j + 1);
pt (x->types[j]);
fprintf (stdout, "\n");
if (x->types[j].bitfield.reg
if (x->types[j].bitfield.class == Reg
|| x->types[j].bitfield.regmmx
|| x->types[j].bitfield.regsimd
|| x->types[j].bitfield.sreg
@ -4506,12 +4519,12 @@ md_assemble (char *line)
instruction already has a prefix, we need to convert old
registers to new ones. */
if ((i.types[0].bitfield.reg && i.types[0].bitfield.byte
if ((i.types[0].bitfield.class == Reg && i.types[0].bitfield.byte
&& (i.op[0].regs->reg_flags & RegRex64) != 0)
|| (i.types[1].bitfield.reg && i.types[1].bitfield.byte
|| (i.types[1].bitfield.class == Reg && i.types[1].bitfield.byte
&& (i.op[1].regs->reg_flags & RegRex64) != 0)
|| (((i.types[0].bitfield.reg && i.types[0].bitfield.byte)
|| (i.types[1].bitfield.reg && i.types[1].bitfield.byte))
|| (((i.types[0].bitfield.class == Reg && i.types[0].bitfield.byte)
|| (i.types[1].bitfield.class == Reg && i.types[1].bitfield.byte))
&& i.rex != 0))
{
int x;
@ -4520,7 +4533,7 @@ md_assemble (char *line)
for (x = 0; x < 2; x++)
{
/* Look for 8 bit operand that uses old registers. */
if (i.types[x].bitfield.reg && i.types[x].bitfield.byte
if (i.types[x].bitfield.class == Reg && i.types[x].bitfield.byte
&& (i.op[x].regs->reg_flags & RegRex64) == 0)
{
/* In case it is "hi" register, give up. */
@ -4545,7 +4558,7 @@ md_assemble (char *line)
the REX_OPCODE byte. */
int x;
for (x = 0; x < 2; x++)
if (i.types[x].bitfield.reg
if (i.types[x].bitfield.class == Reg
&& i.types[x].bitfield.byte
&& (i.op[x].regs->reg_flags & RegRex64) == 0
&& i.op[x].regs->reg_num > 3)
@ -5066,22 +5079,24 @@ optimize_imm (void)
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.reg && i.types[op].bitfield.byte)
if (i.types[op].bitfield.class != Reg)
continue;
else if (i.types[op].bitfield.byte)
{
guess_suffix = BYTE_MNEM_SUFFIX;
break;
}
else if (i.types[op].bitfield.reg && i.types[op].bitfield.word)
else if (i.types[op].bitfield.word)
{
guess_suffix = WORD_MNEM_SUFFIX;
break;
}
else if (i.types[op].bitfield.reg && i.types[op].bitfield.dword)
else if (i.types[op].bitfield.dword)
{
guess_suffix = LONG_MNEM_SUFFIX;
break;
}
else if (i.types[op].bitfield.reg && i.types[op].bitfield.qword)
else if (i.types[op].bitfield.qword)
{
guess_suffix = QWORD_MNEM_SUFFIX;
break;
@ -5170,8 +5185,10 @@ optimize_imm (void)
for (t = current_templates->start;
t < current_templates->end;
++t)
allowed = operand_type_or (allowed,
t->operand_types[op]);
{
allowed = operand_type_or (allowed, t->operand_types[op]);
allowed = operand_type_and (allowed, anyimm);
}
switch (guess_suffix)
{
case QWORD_MNEM_SUFFIX:
@ -6248,7 +6265,8 @@ process_suffix (void)
Destination register type is more significant than source
register type. crc32 in SSE4.2 prefers source register
type. */
if (i.tm.base_opcode == 0xf20f38f0 && i.types[0].bitfield.reg)
if (i.tm.base_opcode == 0xf20f38f0
&& i.types[0].bitfield.class == Reg)
{
if (i.types[0].bitfield.byte)
i.suffix = BYTE_MNEM_SUFFIX;
@ -6276,7 +6294,7 @@ process_suffix (void)
if (!i.tm.operand_types[op].bitfield.inoutportreg
&& !i.tm.operand_types[op].bitfield.shiftcount)
{
if (!i.types[op].bitfield.reg)
if (i.types[op].bitfield.class != Reg)
continue;
if (i.types[op].bitfield.byte)
i.suffix = BYTE_MNEM_SUFFIX;
@ -6451,7 +6469,7 @@ process_suffix (void)
size prefix, except for instructions that will ignore this
prefix anyway. */
if (i.reg_operands > 0
&& i.types[0].bitfield.reg
&& i.types[0].bitfield.class == Reg
&& i.tm.opcode_modifier.addrprefixopreg
&& (i.tm.opcode_modifier.immext
|| i.operands == 1))
@ -6519,7 +6537,7 @@ process_suffix (void)
}
for (op = 0; op < i.operands; op++)
if (i.types[op].bitfield.reg
if (i.types[op].bitfield.class == Reg
&& ((need == need_word
&& !i.op[op].regs->reg_type.bitfield.word)
|| (need == need_dword
@ -6544,7 +6562,7 @@ check_byte_reg (void)
for (op = i.operands; --op >= 0;)
{
/* Skip non-register operands. */
if (!i.types[op].bitfield.reg)
if (i.types[op].bitfield.class != Reg)
continue;
/* If this is an eight bit register, it's OK. If it's the 16 or
@ -6583,7 +6601,7 @@ check_byte_reg (void)
continue;
}
/* Any other register is bad. */
if (i.types[op].bitfield.reg
if (i.types[op].bitfield.class == Reg
|| i.types[op].bitfield.regmmx
|| i.types[op].bitfield.regsimd
|| i.types[op].bitfield.sreg
@ -6609,12 +6627,12 @@ check_long_reg (void)
for (op = i.operands; --op >= 0;)
/* Skip non-register operands. */
if (!i.types[op].bitfield.reg)
if (i.types[op].bitfield.class != Reg)
continue;
/* Reject eight bit registers, except where the template requires
them. (eg. movzb) */
else if (i.types[op].bitfield.byte
&& (i.tm.operand_types[op].bitfield.reg
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
&& (i.tm.operand_types[op].bitfield.word
|| i.tm.operand_types[op].bitfield.dword))
@ -6629,7 +6647,7 @@ check_long_reg (void)
/* Warn if the e prefix on a general reg is missing. */
else if ((!quiet_warnings || flag_code == CODE_64BIT)
&& i.types[op].bitfield.word
&& (i.tm.operand_types[op].bitfield.reg
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
&& i.tm.operand_types[op].bitfield.dword)
{
@ -6651,7 +6669,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.reg
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
&& i.tm.operand_types[op].bitfield.dword)
{
@ -6680,12 +6698,12 @@ check_qword_reg (void)
for (op = i.operands; --op >= 0; )
/* Skip non-register operands. */
if (!i.types[op].bitfield.reg)
if (i.types[op].bitfield.class != Reg)
continue;
/* Reject eight bit registers, except where the template requires
them. (eg. movzb) */
else if (i.types[op].bitfield.byte
&& (i.tm.operand_types[op].bitfield.reg
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
&& (i.tm.operand_types[op].bitfield.word
|| i.tm.operand_types[op].bitfield.dword))
@ -6700,7 +6718,7 @@ check_qword_reg (void)
/* Warn if the r prefix on a general reg is missing. */
else if ((i.types[op].bitfield.word
|| i.types[op].bitfield.dword)
&& (i.tm.operand_types[op].bitfield.reg
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
&& i.tm.operand_types[op].bitfield.qword)
{
@ -6730,12 +6748,12 @@ check_word_reg (void)
int op;
for (op = i.operands; --op >= 0;)
/* Skip non-register operands. */
if (!i.types[op].bitfield.reg)
if (i.types[op].bitfield.class != Reg)
continue;
/* Reject eight bit registers, except where the template requires
them. (eg. movzb) */
else if (i.types[op].bitfield.byte
&& (i.tm.operand_types[op].bitfield.reg
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
&& (i.tm.operand_types[op].bitfield.word
|| i.tm.operand_types[op].bitfield.dword))
@ -6751,7 +6769,7 @@ check_word_reg (void)
else if ((!quiet_warnings || flag_code == CODE_64BIT)
&& (i.types[op].bitfield.dword
|| i.types[op].bitfield.qword)
&& (i.tm.operand_types[op].bitfield.reg
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.acc)
&& i.tm.operand_types[op].bitfield.word)
{
@ -7049,7 +7067,7 @@ duplicate:
{
/* The register or float register operand is in operand
0 or 1. */
unsigned int op = !i.tm.operand_types[0].bitfield.reg;
unsigned int op = i.tm.operand_types[0].bitfield.class != Reg;
/* Register goes in low 3 bits of opcode. */
i.tm.base_opcode |= i.op[op].regs->reg_num;
@ -7284,7 +7302,7 @@ build_modrm_byte (void)
op = i.tm.operand_types[vvvv];
if ((dest + 1) >= i.operands
|| ((!op.bitfield.reg
|| ((op.bitfield.class != Reg
|| (!op.bitfield.dword && !op.bitfield.qword))
&& !op.bitfield.regsimd
&& !operand_type_equal (&op, &regmask)))
@ -7661,7 +7679,7 @@ build_modrm_byte (void)
for (op = 0; op < i.operands; op++)
{
if (i.types[op].bitfield.reg
if (i.types[op].bitfield.class == Reg
|| i.types[op].bitfield.regbnd
|| i.types[op].bitfield.regmask
|| i.types[op].bitfield.sreg
@ -7743,7 +7761,7 @@ build_modrm_byte (void)
{
i386_operand_type *type = &i.tm.operand_types[vex_reg];
if ((!type->bitfield.reg
if ((type->bitfield.class != Reg
|| (!type->bitfield.dword && !type->bitfield.qword))
&& !type->bitfield.regsimd
&& !operand_type_equal (type, &regmask))

View File

@ -1,3 +1,21 @@
2019-11-08 Jan Beulich <jbeulich@suse.com>
* i386-gen.c (operand_type_init): Add Class=. New
OPERAND_TYPE_ANYIMM entry.
(operand_classes): New.
(operand_types): Drop Reg entry.
(output_operand_type): New parameter "class". Process it.
(process_i386_operand_type): New local variable "class".
(main): Adjust static assertions.
* i386-opc.h (CLASS_WIDTH): Define.
(enum operand_class): New.
(Reg): Replace by Class. Adjust comment.
(union i386_operand_type): Replace reg by class.
* i386-opc.tbl (Reg8, Reg16, Reg32, Reg64, FloatReg): Add
Class=.
* i386-reg.tbl: Replace Reg by Class=Reg.
* i386-init.h: Re-generate.
2019-11-07 Mihail Ionescu <mihail.ionescu@arm.com>
* opcodes/aarch64-tbl.h (V8_6_INSN): New macro for v8.6 instructions.

View File

@ -388,13 +388,13 @@ static initializer operand_type_init[] =
{ "OPERAND_TYPE_NONE",
"0" },
{ "OPERAND_TYPE_REG8",
"Reg|Byte" },
"Class=Reg|Byte" },
{ "OPERAND_TYPE_REG16",
"Reg|Word" },
"Class=Reg|Word" },
{ "OPERAND_TYPE_REG32",
"Reg|Dword" },
"Class=Reg|Dword" },
{ "OPERAND_TYPE_REG64",
"Reg|Qword" },
"Class=Reg|Qword" },
{ "OPERAND_TYPE_IMM1",
"Imm1" },
{ "OPERAND_TYPE_IMM8",
@ -432,7 +432,7 @@ static initializer operand_type_init[] =
{ "OPERAND_TYPE_DEBUG",
"Debug" },
{ "OPERAND_TYPE_FLOATREG",
"Reg|Tbyte" },
"Class=Reg|Tbyte" },
{ "OPERAND_TYPE_FLOATACC",
"Acc|Tbyte" },
{ "OPERAND_TYPE_SREG",
@ -479,6 +479,8 @@ static initializer operand_type_init[] =
"Imm32|Imm32S|Imm64|Disp32" },
{ "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
"Imm32|Imm32S|Imm64|Disp32|Disp64" },
{ "OPERAND_TYPE_ANYIMM",
"Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
{ "OPERAND_TYPE_REGBND",
"RegBND" },
};
@ -674,9 +676,19 @@ static bitfield opcode_modifiers[] =
BITFIELD (Intel64),
};
#define CLASS(n) #n, n
static const struct {
const char *name;
enum operand_class value;
} operand_classes[] = {
CLASS (Reg),
};
#undef CLASS
static bitfield operand_types[] =
{
BITFIELD (Reg),
BITFIELD (RegMMX),
BITFIELD (RegSIMD),
BITFIELD (RegMask),
@ -1134,20 +1146,21 @@ enum stage {
};
static void
output_operand_type (FILE *table, bitfield *types, unsigned int size,
output_operand_type (FILE *table, enum operand_class class,
const bitfield *types, unsigned int size,
enum stage stage, const char *indent)
{
unsigned int i;
fprintf (table, "{ { ");
fprintf (table, "{ { %d, ", class);
for (i = 0; i < size - 1; i++)
{
if (((i + 1) % 20) != 0)
if (((i + 2) % 20) != 0)
fprintf (table, "%d, ", types[i].value);
else
fprintf (table, "%d,", types[i].value);
if (((i + 1) % 20) == 0)
if (((i + 2) % 20) == 0)
{
/* We need \\ for macro. */
if (stage == stage_macros)
@ -1165,6 +1178,7 @@ process_i386_operand_type (FILE *table, char *op, enum stage stage,
const char *indent, int lineno)
{
char *str, *next, *last;
enum operand_class class = ClassNone;
bitfield types [ARRAY_SIZE (operand_types)];
/* Copy the default operand type. */
@ -1178,6 +1192,21 @@ process_i386_operand_type (FILE *table, char *op, enum stage stage,
for (next = op; next && next < last; )
{
str = next_field (next, '|', &next, last);
if (str)
{
unsigned int i;
if (!strncmp(str, "Class=", 6))
{
for (i = 0; i < ARRAY_SIZE(operand_classes); ++i)
if (!strcmp(str + 6, operand_classes[i].name))
{
class = operand_classes[i].value;
str = NULL;
break;
}
}
}
if (str)
{
set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
@ -1197,7 +1226,7 @@ process_i386_operand_type (FILE *table, char *op, enum stage stage,
set_bitfield("Disp32S", types, 1, ARRAY_SIZE (types), lineno);
}
}
output_operand_type (table, types, ARRAY_SIZE (types), stage,
output_operand_type (table, class, types, ARRAY_SIZE (types), stage,
indent);
}
@ -1688,9 +1717,9 @@ main (int argc, char **argv)
/* Check the unused bitfield in i386_operand_type. */
#ifdef OTUnused
static_assert (ARRAY_SIZE (operand_types) == OTNum + 1);
static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH == OTNum + 1);
#else
static_assert (ARRAY_SIZE (operand_types) == OTNum);
static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH == OTNum);
c = OTNumOfBits - OTMax - 1;
if (c)

View File

@ -1551,6 +1551,10 @@
{ { 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, 0, 0, 0, 0 } }
#define OPERAND_TYPE_ANYIMM \
{ { 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, 0, 0, 0, 0 } }
#define OPERAND_TYPE_REGBND \
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 } }

View File

@ -702,12 +702,21 @@ typedef struct i386_opcode_modifier
unsigned int intel64:1;
} i386_opcode_modifier;
/* Operand classes. */
#define CLASS_WIDTH 4
enum operand_class
{
ClassNone,
Reg, /* GPRs and FP regs, distinguished by operand size */
};
/* Position of operand_type bits. */
enum
{
/* Register (qualified by Byte, Word, etc) */
Reg = 0,
/* Class */
Class = CLASS_WIDTH - 1,
/* MMX register */
RegMMX,
/* Vector registers */
@ -791,7 +800,7 @@ enum
/* Bound register. */
RegBND,
/* The number of bitfields in i386_operand_type. */
/* The number of bits in i386_operand_type. */
OTNum
};
@ -808,7 +817,7 @@ typedef union i386_operand_type
{
struct
{
unsigned int reg:1;
unsigned int class:CLASS_WIDTH;
unsigned int regmmx:1;
unsigned int regsimd:1;
unsigned int regmask:1;

View File

@ -22,13 +22,13 @@
#include "i386-opc.h"
#undef None
#define Reg8 Reg|Byte
#define Reg16 Reg|Word
#define Reg32 Reg|Dword
#define Reg64 Reg|Qword
#define Reg8 Class=Reg|Byte
#define Reg16 Class=Reg|Word
#define Reg32 Class=Reg|Dword
#define Reg64 Class=Reg|Qword
#define FloatAcc Acc|Tbyte
#define FloatReg Reg|Tbyte
#define FloatReg Class=Reg|Tbyte
#define RegXMM RegSIMD|Xmmword
#define RegYMM RegSIMD|Ymmword

View File

@ -19,82 +19,82 @@
// 02110-1301, USA.
// Make %st first as we test for it.
st, Reg|Acc|Tbyte, 0, 0, 11, 33
st, Class=Reg|Acc|Tbyte, 0, 0, 11, 33
// 8 bit regs
al, Reg|Acc|Byte, 0, 0, Dw2Inval, Dw2Inval
cl, Reg|Byte|ShiftCount, 0, 1, Dw2Inval, Dw2Inval
dl, Reg|Byte, 0, 2, Dw2Inval, Dw2Inval
bl, Reg|Byte, 0, 3, Dw2Inval, Dw2Inval
ah, Reg|Byte, 0, 4, Dw2Inval, Dw2Inval
ch, Reg|Byte, 0, 5, Dw2Inval, Dw2Inval
dh, Reg|Byte, 0, 6, Dw2Inval, Dw2Inval
bh, Reg|Byte, 0, 7, Dw2Inval, Dw2Inval
axl, Reg|Byte, RegRex64, 0, Dw2Inval, Dw2Inval
cxl, Reg|Byte, RegRex64, 1, Dw2Inval, Dw2Inval
dxl, Reg|Byte, RegRex64, 2, Dw2Inval, Dw2Inval
bxl, Reg|Byte, RegRex64, 3, Dw2Inval, Dw2Inval
spl, Reg|Byte, RegRex64, 4, Dw2Inval, Dw2Inval
bpl, Reg|Byte, RegRex64, 5, Dw2Inval, Dw2Inval
sil, Reg|Byte, RegRex64, 6, Dw2Inval, Dw2Inval
dil, Reg|Byte, RegRex64, 7, Dw2Inval, Dw2Inval
r8b, Reg|Byte, RegRex|RegRex64, 0, Dw2Inval, Dw2Inval
r9b, Reg|Byte, RegRex|RegRex64, 1, Dw2Inval, Dw2Inval
r10b, Reg|Byte, RegRex|RegRex64, 2, Dw2Inval, Dw2Inval
r11b, Reg|Byte, RegRex|RegRex64, 3, Dw2Inval, Dw2Inval
r12b, Reg|Byte, RegRex|RegRex64, 4, Dw2Inval, Dw2Inval
r13b, Reg|Byte, RegRex|RegRex64, 5, Dw2Inval, Dw2Inval
r14b, Reg|Byte, RegRex|RegRex64, 6, Dw2Inval, Dw2Inval
r15b, Reg|Byte, RegRex|RegRex64, 7, Dw2Inval, Dw2Inval
al, Class=Reg|Acc|Byte, 0, 0, Dw2Inval, Dw2Inval
cl, Class=Reg|Byte|ShiftCount, 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
ch, Class=Reg|Byte, 0, 5, Dw2Inval, Dw2Inval
dh, Class=Reg|Byte, 0, 6, Dw2Inval, Dw2Inval
bh, Class=Reg|Byte, 0, 7, Dw2Inval, Dw2Inval
axl, Class=Reg|Byte, RegRex64, 0, Dw2Inval, Dw2Inval
cxl, Class=Reg|Byte, RegRex64, 1, Dw2Inval, Dw2Inval
dxl, Class=Reg|Byte, RegRex64, 2, Dw2Inval, Dw2Inval
bxl, Class=Reg|Byte, RegRex64, 3, Dw2Inval, Dw2Inval
spl, Class=Reg|Byte, RegRex64, 4, Dw2Inval, Dw2Inval
bpl, Class=Reg|Byte, RegRex64, 5, Dw2Inval, Dw2Inval
sil, Class=Reg|Byte, RegRex64, 6, Dw2Inval, Dw2Inval
dil, Class=Reg|Byte, RegRex64, 7, Dw2Inval, Dw2Inval
r8b, Class=Reg|Byte, RegRex|RegRex64, 0, Dw2Inval, Dw2Inval
r9b, Class=Reg|Byte, RegRex|RegRex64, 1, Dw2Inval, Dw2Inval
r10b, Class=Reg|Byte, RegRex|RegRex64, 2, Dw2Inval, Dw2Inval
r11b, Class=Reg|Byte, RegRex|RegRex64, 3, Dw2Inval, Dw2Inval
r12b, Class=Reg|Byte, RegRex|RegRex64, 4, Dw2Inval, Dw2Inval
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, Reg|Acc|Word, 0, 0, Dw2Inval, Dw2Inval
cx, Reg|Word, 0, 1, Dw2Inval, Dw2Inval
dx, Reg|Word|InOutPortReg, 0, 2, Dw2Inval, Dw2Inval
bx, Reg|Word|BaseIndex, 0, 3, Dw2Inval, Dw2Inval
sp, Reg|Word, 0, 4, Dw2Inval, Dw2Inval
bp, Reg|Word|BaseIndex, 0, 5, Dw2Inval, Dw2Inval
si, Reg|Word|BaseIndex, 0, 6, Dw2Inval, Dw2Inval
di, Reg|Word|BaseIndex, 0, 7, Dw2Inval, Dw2Inval
r8w, Reg|Word, RegRex, 0, Dw2Inval, Dw2Inval
r9w, Reg|Word, RegRex, 1, Dw2Inval, Dw2Inval
r10w, Reg|Word, RegRex, 2, Dw2Inval, Dw2Inval
r11w, Reg|Word, RegRex, 3, Dw2Inval, Dw2Inval
r12w, Reg|Word, RegRex, 4, Dw2Inval, Dw2Inval
r13w, Reg|Word, RegRex, 5, Dw2Inval, Dw2Inval
r14w, Reg|Word, RegRex, 6, Dw2Inval, Dw2Inval
r15w, Reg|Word, RegRex, 7, Dw2Inval, Dw2Inval
ax, Class=Reg|Acc|Word, 0, 0, Dw2Inval, Dw2Inval
cx, Class=Reg|Word, 0, 1, Dw2Inval, Dw2Inval
dx, Class=Reg|Word|InOutPortReg, 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
si, Class=Reg|Word|BaseIndex, 0, 6, Dw2Inval, Dw2Inval
di, Class=Reg|Word|BaseIndex, 0, 7, Dw2Inval, Dw2Inval
r8w, Class=Reg|Word, RegRex, 0, Dw2Inval, Dw2Inval
r9w, Class=Reg|Word, RegRex, 1, Dw2Inval, Dw2Inval
r10w, Class=Reg|Word, RegRex, 2, Dw2Inval, Dw2Inval
r11w, Class=Reg|Word, RegRex, 3, Dw2Inval, Dw2Inval
r12w, Class=Reg|Word, RegRex, 4, Dw2Inval, Dw2Inval
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, Reg|Acc|Dword|BaseIndex, 0, 0, 0, Dw2Inval
ecx, Reg|Dword|BaseIndex, 0, 1, 1, Dw2Inval
edx, Reg|Dword|BaseIndex, 0, 2, 2, Dw2Inval
ebx, Reg|Dword|BaseIndex, 0, 3, 3, Dw2Inval
esp, Reg|Dword, 0, 4, 4, Dw2Inval
ebp, Reg|Dword|BaseIndex, 0, 5, 5, Dw2Inval
esi, Reg|Dword|BaseIndex, 0, 6, 6, Dw2Inval
edi, Reg|Dword|BaseIndex, 0, 7, 7, Dw2Inval
r8d, Reg|Dword|BaseIndex, RegRex, 0, Dw2Inval, Dw2Inval
r9d, Reg|Dword|BaseIndex, RegRex, 1, Dw2Inval, Dw2Inval
r10d, Reg|Dword|BaseIndex, RegRex, 2, Dw2Inval, Dw2Inval
r11d, Reg|Dword|BaseIndex, RegRex, 3, Dw2Inval, Dw2Inval
r12d, Reg|Dword|BaseIndex, RegRex, 4, Dw2Inval, Dw2Inval
r13d, Reg|Dword|BaseIndex, RegRex, 5, Dw2Inval, Dw2Inval
r14d, Reg|Dword|BaseIndex, RegRex, 6, Dw2Inval, Dw2Inval
r15d, Reg|Dword|BaseIndex, RegRex, 7, Dw2Inval, Dw2Inval
rax, Reg|Acc|Qword|BaseIndex, 0, 0, Dw2Inval, 0
rcx, Reg|Qword|BaseIndex, 0, 1, Dw2Inval, 2
rdx, Reg|Qword|BaseIndex, 0, 2, Dw2Inval, 1
rbx, Reg|Qword|BaseIndex, 0, 3, Dw2Inval, 3
rsp, Reg|Qword, 0, 4, Dw2Inval, 7
rbp, Reg|Qword|BaseIndex, 0, 5, Dw2Inval, 6
rsi, Reg|Qword|BaseIndex, 0, 6, Dw2Inval, 4
rdi, Reg|Qword|BaseIndex, 0, 7, Dw2Inval, 5
r8, Reg|Qword|BaseIndex, RegRex, 0, Dw2Inval, 8
r9, Reg|Qword|BaseIndex, RegRex, 1, Dw2Inval, 9
r10, Reg|Qword|BaseIndex, RegRex, 2, Dw2Inval, 10
r11, Reg|Qword|BaseIndex, RegRex, 3, Dw2Inval, 11
r12, Reg|Qword|BaseIndex, RegRex, 4, Dw2Inval, 12
r13, Reg|Qword|BaseIndex, RegRex, 5, Dw2Inval, 13
r14, Reg|Qword|BaseIndex, RegRex, 6, Dw2Inval, 14
r15, Reg|Qword|BaseIndex, RegRex, 7, Dw2Inval, 15
eax, Class=Reg|Acc|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
esp, Class=Reg|Dword, 0, 4, 4, Dw2Inval
ebp, Class=Reg|Dword|BaseIndex, 0, 5, 5, Dw2Inval
esi, Class=Reg|Dword|BaseIndex, 0, 6, 6, Dw2Inval
edi, Class=Reg|Dword|BaseIndex, 0, 7, 7, Dw2Inval
r8d, Class=Reg|Dword|BaseIndex, RegRex, 0, Dw2Inval, Dw2Inval
r9d, Class=Reg|Dword|BaseIndex, RegRex, 1, Dw2Inval, Dw2Inval
r10d, Class=Reg|Dword|BaseIndex, RegRex, 2, Dw2Inval, Dw2Inval
r11d, Class=Reg|Dword|BaseIndex, RegRex, 3, Dw2Inval, Dw2Inval
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
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
rsp, Class=Reg|Qword, 0, 4, Dw2Inval, 7
rbp, Class=Reg|Qword|BaseIndex, 0, 5, Dw2Inval, 6
rsi, Class=Reg|Qword|BaseIndex, 0, 6, Dw2Inval, 4
rdi, Class=Reg|Qword|BaseIndex, 0, 7, Dw2Inval, 5
r8, Class=Reg|Qword|BaseIndex, RegRex, 0, Dw2Inval, 8
r9, Class=Reg|Qword|BaseIndex, RegRex, 1, Dw2Inval, 9
r10, Class=Reg|Qword|BaseIndex, RegRex, 2, Dw2Inval, 10
r11, Class=Reg|Qword|BaseIndex, RegRex, 3, Dw2Inval, 11
r12, Class=Reg|Qword|BaseIndex, RegRex, 4, Dw2Inval, 12
r13, Class=Reg|Qword|BaseIndex, RegRex, 5, Dw2Inval, 13
r14, Class=Reg|Qword|BaseIndex, RegRex, 6, Dw2Inval, 14
r15, Class=Reg|Qword|BaseIndex, RegRex, 7, Dw2Inval, 15
// Vector mask registers.
k0, RegMask, 0, 0, 93, 118
k1, RegMask, 0, 1, 94, 119
@ -283,23 +283,23 @@ bnd0, RegBND, 0, 0, Dw2Inval, Dw2Inval
bnd1, RegBND, 0, 1, Dw2Inval, Dw2Inval
bnd2, RegBND, 0, 2, Dw2Inval, Dw2Inval
bnd3, RegBND, 0, 3, Dw2Inval, Dw2Inval
// No Reg will make these registers rejected for all purposes except
// No Class=Reg will make these registers rejected for all purposes except
// for addressing. This saves creating one extra type for RIP/EIP.
rip, Qword, RegRex64, RegIP, Dw2Inval, 16
eip, Dword, RegRex64, RegIP, 8, Dw2Inval
// No Reg will make these registers rejected for all purposes except
// No Class=Reg will make these registers rejected for all purposes except
// for addressing.
riz, Qword|BaseIndex, RegRex64, RegIZ, Dw2Inval, Dw2Inval
eiz, Dword|BaseIndex, 0, RegIZ, Dw2Inval, Dw2Inval
// fp regs.
st(0), Reg|Acc|Tbyte, 0, 0, 11, 33
st(1), Reg|Tbyte, 0, 1, 12, 34
st(2), Reg|Tbyte, 0, 2, 13, 35
st(3), Reg|Tbyte, 0, 3, 14, 36
st(4), Reg|Tbyte, 0, 4, 15, 37
st(5), Reg|Tbyte, 0, 5, 16, 38
st(6), Reg|Tbyte, 0, 6, 17, 39
st(7), Reg|Tbyte, 0, 7, 18, 40
st(0), Class=Reg|Acc|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
st(4), Class=Reg|Tbyte, 0, 4, 15, 37
st(5), Class=Reg|Tbyte, 0, 5, 16, 38
st(6), Class=Reg|Tbyte, 0, 6, 17, 39
st(7), Class=Reg|Tbyte, 0, 7, 18, 40
// Pseudo-register names only used in .cfi_* directives
eflags, 0, 0, 0, 9, 49
rflags, 0, 0, 0, Dw2Inval, 49