mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86emul: extend decoding / mem access testing to XOP-encoded insns
Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
1 parent
5e6dc9b8e5
commit
3cb82fe3ff
1 file changed
+147
@@ -1474,6 +1474,96 @@ static const struct {
|
||||
{ vex_0f3a, ARRAY_SIZE(vex_0f3a) },
|
||||
};
|
||||
|
||||
static const struct xop {
|
||||
uint8_t opc[2];
|
||||
uint8_t w:2;
|
||||
uint8_t l:2;
|
||||
} xop_08[] = {
|
||||
{ { 0x85 }, W0, L0 }, /* vpmacssww */
|
||||
{ { 0x86 }, W0, L0 }, /* vpmacsswd */
|
||||
{ { 0x87 }, W0, L0 }, /* vpmacssdql */
|
||||
{ { 0x8e }, W0, L0 }, /* vpmacssdd */
|
||||
{ { 0x8f }, W0, L0 }, /* vpmacssdqh */
|
||||
{ { 0x95 }, W0, L0 }, /* vpmacsww */
|
||||
{ { 0x96 }, W0, L0 }, /* vpmacswd */
|
||||
{ { 0x97 }, W0, L0 }, /* vpmacsdql */
|
||||
{ { 0x9e }, W0, L0 }, /* vpmacsdd */
|
||||
{ { 0x9f }, W0, L0 }, /* vpmacsdqh */
|
||||
{ { 0xa2 }, Wn, Ln }, /* vpcmov */
|
||||
{ { 0xa3 }, Wn, L0 }, /* vpperm */
|
||||
{ { 0xa6 }, W0, L0 }, /* vpmadcsswd */
|
||||
{ { 0xb6 }, W0, L0 }, /* vpmadcswd */
|
||||
{ { 0xc0 }, W0, L0 }, /* vprotb */
|
||||
{ { 0xc1 }, W0, L0 }, /* vprotw */
|
||||
{ { 0xc2 }, W0, L0 }, /* vprotd */
|
||||
{ { 0xc3 }, W0, L0 }, /* vprotq */
|
||||
{ { 0xcc }, W0, L0 }, /* vpcomb */
|
||||
{ { 0xcd }, W0, L0 }, /* vpcomw */
|
||||
{ { 0xce }, W0, L0 }, /* vpcomd */
|
||||
{ { 0xcf }, W0, L0 }, /* vpcomq */
|
||||
{ { 0xec }, W0, L0 }, /* vpcomub */
|
||||
{ { 0xed }, W0, L0 }, /* vpcomuw */
|
||||
{ { 0xee }, W0, L0 }, /* vpcomud */
|
||||
{ { 0xef }, W0, L0 }, /* vpcomuq */
|
||||
}, xop_09[] = {
|
||||
{ { 0x01, 0x08 }, Wn, L0 }, /* blcfill */
|
||||
{ { 0x01, 0x10 }, Wn, L0 }, /* blsfill */
|
||||
{ { 0x01, 0x18 }, Wn, L0 }, /* blcs */
|
||||
{ { 0x01, 0x20 }, Wn, L0 }, /* tzmsk */
|
||||
{ { 0x01, 0x28 }, Wn, L0 }, /* blcic */
|
||||
{ { 0x01, 0x30 }, Wn, L0 }, /* blsic */
|
||||
{ { 0x01, 0x38 }, Wn, L0 }, /* t1mskc */
|
||||
{ { 0x02, 0x08 }, Wn, L0 }, /* blcmsk */
|
||||
{ { 0x02, 0x30 }, Wn, L0 }, /* blci */
|
||||
{ { 0x02, 0xc0 }, Wn, L0 }, /* llwpcb */
|
||||
{ { 0x02, 0xc8 }, Wn, L0 }, /* slwpcb */
|
||||
{ { 0x80 }, W0, Ln }, /* vfrczps */
|
||||
{ { 0x81 }, W0, Ln }, /* vfrczpd */
|
||||
{ { 0x82 }, W0, L0 }, /* vfrczss */
|
||||
{ { 0x83 }, W0, L0 }, /* vfrczsd */
|
||||
{ { 0x90 }, Wn, L0 }, /* vprotb */
|
||||
{ { 0x91 }, Wn, L0 }, /* vprotw */
|
||||
{ { 0x92 }, Wn, L0 }, /* vprotd */
|
||||
{ { 0x93 }, Wn, L0 }, /* vprotq */
|
||||
{ { 0x94 }, Wn, L0 }, /* vpshlb */
|
||||
{ { 0x95 }, Wn, L0 }, /* vpshlw */
|
||||
{ { 0x96 }, Wn, L0 }, /* vpshld */
|
||||
{ { 0x97 }, Wn, L0 }, /* vpshlq */
|
||||
{ { 0x9c }, Wn, L0 }, /* vpshab */
|
||||
{ { 0x9d }, Wn, L0 }, /* vpshaw */
|
||||
{ { 0x9e }, Wn, L0 }, /* vpshad */
|
||||
{ { 0x9f }, Wn, L0 }, /* vpshaq */
|
||||
{ { 0xc1 }, W0, L0 }, /* vphaddbw */
|
||||
{ { 0xc2 }, W0, L0 }, /* vphaddbd */
|
||||
{ { 0xc3 }, W0, L0 }, /* vphaddbq */
|
||||
{ { 0xc6 }, W0, L0 }, /* vphaddwd */
|
||||
{ { 0xc7 }, W0, L0 }, /* vphaddwq */
|
||||
{ { 0xcb }, W0, L0 }, /* vphadddq */
|
||||
{ { 0xd1 }, W0, L0 }, /* vphaddubw */
|
||||
{ { 0xd2 }, W0, L0 }, /* vphaddubd */
|
||||
{ { 0xd3 }, W0, L0 }, /* vphaddubq */
|
||||
{ { 0xd6 }, W0, L0 }, /* vphadduwd */
|
||||
{ { 0xd7 }, W0, L0 }, /* vphadduwq */
|
||||
{ { 0xdb }, W0, L0 }, /* vphaddudq */
|
||||
{ { 0xe1 }, W0, L0 }, /* vphsubbw */
|
||||
{ { 0xe2 }, W0, L0 }, /* vphsubwd */
|
||||
{ { 0xe3 }, W0, L0 }, /* vphsubdq */
|
||||
}, xop_0a[] = {
|
||||
{ { 0x10 }, Wn, L0 }, /* bextr */
|
||||
{ { 0x12, 0x00 }, Wn, L0 }, /* lwpins */
|
||||
{ { 0x12, 0x08 }, Wn, L0 }, /* lwpval */
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const struct xop *tbl;
|
||||
unsigned int num;
|
||||
unsigned int imm;
|
||||
} xop[] = {
|
||||
{ xop_08, ARRAY_SIZE(xop_08), 1 },
|
||||
{ xop_09, ARRAY_SIZE(xop_09), 0 },
|
||||
{ xop_0a, ARRAY_SIZE(xop_0a), 4 },
|
||||
};
|
||||
|
||||
#undef Wn
|
||||
#undef Ln
|
||||
|
||||
@@ -1738,6 +1828,63 @@ void predicates_test(void *instr, struct x86_emulate_ctxt *ctxt,
|
||||
}
|
||||
}
|
||||
|
||||
for ( x = 0; x < ARRAY_SIZE(xop); ++x )
|
||||
{
|
||||
for ( t = 0; t < xop[x].num; ++t )
|
||||
{
|
||||
uint8_t *ptr = instr;
|
||||
unsigned int modrm;
|
||||
enum mem_access mem;
|
||||
|
||||
memset(instr + 5, 0xcc, 10);
|
||||
|
||||
*ptr++ = 0x8f;
|
||||
*ptr++ = 0xe8 + x;
|
||||
*ptr++ = 0x78;
|
||||
memcpy(ptr, xop[x].tbl[t].opc, 2);
|
||||
memset(ptr + 2, 0, xop[x].imm);
|
||||
|
||||
modrm = ptr[1] & 0xc0 ? 0 : 4;
|
||||
mem = ptr[1] & 0xc0 ? mem_none : mem_read;
|
||||
|
||||
assert(xop[x].tbl[t].w != WIG);
|
||||
assert(xop[x].tbl[t].l != LIG);
|
||||
|
||||
if ( xop[x].tbl[t].w & W0 )
|
||||
{
|
||||
if ( xop[x].tbl[t].l & L0 )
|
||||
do_test(instr, 5 + xop[x].imm, modrm, mem, ctxt, fetch);
|
||||
|
||||
if ( xop[x].tbl[t].l & L1 )
|
||||
{
|
||||
ptr[-1] = 0x7c;
|
||||
ptr[1] = mem != mem_none ? 0x00 : 0xc0;
|
||||
|
||||
do_test(instr, 5 + xop[x].imm, modrm, mem, ctxt, fetch);
|
||||
}
|
||||
}
|
||||
|
||||
if ( xop[x].tbl[t].w & W1 )
|
||||
{
|
||||
if ( xop[x].tbl[t].l & L0 )
|
||||
{
|
||||
ptr[-1] = 0xf8;
|
||||
ptr[1] = mem != mem_none ? 0x00 : 0xc0;
|
||||
|
||||
do_test(instr, 5 + xop[x].imm, modrm, mem, ctxt, fetch);
|
||||
}
|
||||
|
||||
if ( xop[x].tbl[t].l & L1 )
|
||||
{
|
||||
ptr[-1] = 0xfc;
|
||||
ptr[1] = mem != mem_none ? 0x00 : 0xc0;
|
||||
|
||||
do_test(instr, 5 + xop[x].imm, modrm, mem, ctxt, fetch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( errors )
|
||||
exit(1);
|
||||
|
||||
|
||||