|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v4 17/28] x86emul: support APX forms of TILE{LOADD{,T1},STORED}
While, like elsewhere, pre-existing code can largely be re-used, EVEX
Disp8 testing requires some special care: .
Note that the calculation of ->sib_index can be left as is, as long as
all SIBMEM insns don't use EVEX.vvvv (and hence EVEX.V4 is required to
be set).
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
TBD: How to reasonably test AMX+APX isn't entirely clear yet. Simply
re-compiling matrix.c with -mapfx is unlikely to produce good uses
of eGPR-s. Yet fiddling with intermediate assembly isn't quite
nice either, and even then there's no guarantee that we'd end up
with any useful uses of eGPR-s.
---
v4: New.
--- a/tools/tests/x86_emulator/evex-disp8.c
+++ b/tools/tests/x86_emulator/evex-disp8.c
@@ -1196,6 +1196,10 @@ static const struct test amx_tile[] = {
/* Element size is set arbitrarily here. See test_one(). */
INSN(ldtilecfg, , 0f38, 49, el, b, no),
INSN(sttilecfg, 66, 0f38, 49, el, b, no),
+ /* Element size assumes a 1x1 matrix here. See test_one(). */
+ INSN(tileloadd, f2, 0f38, 4b, el, d, no),
+ INSN(tileloaddt1, 66, 0f38, 4b, el, d, no),
+ INSN(tilestored, f3, 0f38, 4b, el, d, no),
};
static const unsigned char vl_all[] = { VL_512, VL_128, VL_256 };
@@ -1316,6 +1320,7 @@ static void test_one(const struct test *
int rc;
bool sg = strstr(test->mnemonic, "gather") ||
strstr(test->mnemonic, "scatter");
+ bool tile = false;
unsigned int imm = test->spc == SPC_0f3a ||
(test->spc == SPC_0f &&
(imm0f[test->opc >> 4] & (1 << (test->opc & 0xf))));
@@ -1437,8 +1442,8 @@ static void test_one(const struct test *
}
/*
- * Note: SIB addressing is used here, such that S/G insns can be handled
- * without extra conditionals.
+ * Note: SIB addressing is used here, such that S/G and SIBMEM insns can
+ * be handled without extra conditionals.
*/
instr[0] = 0x62;
again:
@@ -1465,6 +1470,24 @@ static void test_one(const struct test *
*/
if ( test->spc == SPC_0f38 && test->opc == 0x49 )
vsz = 64;
+
+ /*
+ * Tile loads/stores require a valid tile configuration. Set up a 1x1
+ * tile for %tmm0.
+ */
+ if ( test->spc == SPC_0f38 && test->opc == 0x4b )
+ {
+ static const struct x86_tilecfg tilecfg = {
+ .palette = 1,
+ .colsb[0] = 4,
+ .rows[0] = 1,
+ };
+
+ /* ldtilecfg (%rax) */
+ asm volatile ( ".byte 0xc4, 0xe2, 0x78, 0x49, 0x00"
+ :: "a" (&tilecfg), "m" (tilecfg) );
+ tile = true;
+ }
}
else
{
@@ -1554,7 +1577,12 @@ static void test_one(const struct test *
*/
if ( test->spc != SPC_map4 || (test->opc | 0xf) != 0x4f ||
test->pfx > PFX_66 || (evex.bcst && evex.opmsk) )
+ {
+ /* Issue TILERELEASE if we fiddled with tiles. */
+ if ( tile )
+ asm volatile ( ".byte 0xc4, 0xe2, 0x78, 0x49, 0xc0" );
return;
+ }
evex.bcst = !evex.bcst;
if ( !evex.bcst )
--- a/tools/tests/x86_emulator/predicates.c
+++ b/tools/tests/x86_emulator/predicates.c
@@ -1939,6 +1939,9 @@ static const struct evex {
{ { 0x47 }, 2, T, R, pfx_66, Wn, Ln }, /* vpsllv{d,q} */
{ { 0x49, 0x00 }, 2, F, R, pfx_no, W0, L0 }, /* ldtilecfg */
{ { 0x49, 0x00 }, 2, F, W, pfx_66, W0, L0 }, /* sttilecfg */
+ { { 0x4b, VSIB(0) }, 3, F, R, pfx_66, W0, L0 }, /* tileloaddt1 */
+ { { 0x4b, VSIB(0) }, 3, F, W, pfx_f3, W0, L0 }, /* tilestored */
+ { { 0x4b, VSIB(0) }, 3, F, R, pfx_f2, W0, L0 }, /* tileloadd */
{ { 0x4c }, 2, T, R, pfx_66, Wn, Ln }, /* vrcp14p{s,d} */
{ { 0x4d }, 2, T, R, pfx_66, Wn, LIG }, /* vrcp14s{s,d} */
{ { 0x4e }, 2, T, R, pfx_66, Wn, Ln }, /* vrsqrt14p{s,d} */
--- a/xen/arch/x86/x86_emulate/decode.c
+++ b/xen/arch/x86/x86_emulate/decode.c
@@ -1272,6 +1272,7 @@ decode_0f38(struct x86_emulate_state *s,
break;
case X86EMUL_OPC_EVEX_66(0, 0x49): /* sttilecfg */
+ case X86EMUL_OPC_EVEX_F3(0, 0x4b): /* tilestored */
s->promoted_evex = true;
fallthrough;
case X86EMUL_OPC_VEX_66(0, 0x49): /* sttilecfg */
@@ -1312,6 +1313,8 @@ decode_0f38(struct x86_emulate_state *s,
break;
case X86EMUL_OPC_EVEX(0, 0x49): /* ldtilecfg */
+ case X86EMUL_OPC_EVEX_66(0, 0x4b): /* tileloaddt1 */
+ case X86EMUL_OPC_EVEX_F2(0, 0x4b): /* tileloadd */
case X86EMUL_OPC_EVEX_66(0, 0xe0) ...
X86EMUL_OPC_EVEX_66(0, 0xef): /* cmp<cc>xadd */
case X86EMUL_OPC_EVEX(0, 0xf2): /* andn */
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -6771,6 +6771,12 @@ x86_emulate(
}
goto unrecognized_insn;
+ case X86EMUL_OPC_EVEX_66(0x0f38, 0x4b): /* tileloaddt1 mem,tmm */
+ case X86EMUL_OPC_EVEX_F3(0x0f38, 0x4b): /* tilestored tmm,mem */
+ case X86EMUL_OPC_EVEX_F2(0x0f38, 0x4b): /* tileloadd mem,tmm */
+ generate_exception_if(evex.lr || evex.brs || evex.opmsk || !evex.RX,
+ X86_EXC_UD);
+ fallthrough;
case X86EMUL_OPC_VEX_66(0x0f38, 0x4b): /* tileloaddt1 mem,tmm */
case X86EMUL_OPC_VEX_F3(0x0f38, 0x4b): /* tilestored tmm,mem */
case X86EMUL_OPC_VEX_F2(0x0f38, 0x4b): /* tileloadd mem,tmm */
@@ -6795,7 +6801,7 @@ x86_emulate(
/* Calculate stride. */
if ( state->sib_index != 4 )
- ea.val = truncate_ea(*decode_gpr(ctxt->regs, NULL,
+ ea.val = truncate_ea(*decode_gpr(ctxt->regs, &state->egpr,
state->sib_index) <<
state->sib_scale);
@@ -6847,7 +6853,7 @@ x86_emulate(
opc[1] = modrm & 0x3f;
opc[2] = 0x20;
place_ret(&opc[3]);
- copy_VEX(opc, vex, false);
+ copy_VEX(opc, vex, state->promoted_evex);
do {
if ( row >= n )
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |