|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v4 27/28] x86emul: enable block scale register insns for ACE
BSRINIT is an encoding sibling of TILEZERO and hence the code there merely
needs EVEX.W handling to be adjusted. BSRMOV* are at an entirely new code
point, with EVEX.W controlling the direction of the move.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
SDE: ???
---
v4: New.
--- a/tools/tests/x86_emulator/evex-disp8.c
+++ b/tools/tests/x86_emulator/evex-disp8.c
@@ -1203,6 +1203,12 @@ static const struct test amx_tile[] = {
};
static const struct test ace[] = {
+ /* Element sizes are arbitrary here, for test_one() to set W correctly. */
+ INSN(bsrmovf, , map6, 95, vl, q_nb, vl),
+ INSN(bsrmovh, f2, map6, 95, vl, d_nb, vl),
+ INSN(bsrmovh, f2, map6, 95, vl, q_nb, vl),
+ INSN(bsrmovl, f3, map6, 95, vl, d_nb, vl),
+ INSN(bsrmovl, f3, map6, 95, vl, q_nb, vl),
/* Element size is set arbitrarily here. See test_one(). */
INSN(ldtilecfg, , 0f38, 49, el, b, no),
INSN(sttilecfg, 66, 0f38, 49, el, b, no),
--- a/tools/tests/x86_emulator/predicates.c
+++ b/tools/tests/x86_emulator/predicates.c
@@ -1347,6 +1347,7 @@ static const struct vex {
{ { 0x49, 0x00 }, 2, F, W, pfx_66, W0, L0 }, /* sttilecfg */
{ { 0x49, 0xc0 }, 2, F, N, pfx_no, W0, L0 }, /* tilerelease */
{ { 0x49, 0xc0 }, 2, F, N, pfx_f2, W0, L0 }, /* tilezero */
+ { { 0x49, 0xc0 }, 2, F, N, pfx_f2, W1, L0 }, /* bsrinit */
{ { 0x4a, VSIB(0) }, 3, F, R, pfx_66, W0, L0 }, /* tileloaddrst1 */
{ { 0x4a, VSIB(0) }, 3, F, R, pfx_f2, W0, L0 }, /* tileloaddrs */
{ { 0x4b, VSIB(0) }, 3, F, R, pfx_66, W0, L0 }, /* tileloaddt1 */
@@ -2567,6 +2568,11 @@ static const struct evex {
{ { 0x80 }, 2, T, R, pfx_no, W0, L1 | L2 }, /* vbmacor16x16x16 */
{ { 0x80 }, 2, T, R, pfx_no, W1, L1 | L2 }, /* vbmacxor16x16x16 */
{ { 0x81 }, 2, T, R, pfx_no, W0, Ln }, /* vbitrev */
+ { { 0x95 }, 2, F, R, pfx_no, W1, L2 }, /* bsrmovf */
+ { { 0x95 }, 2, F, W, pfx_f3, W0, L2 }, /* bsrmovl */
+ { { 0x95 }, 2, F, R, pfx_f3, W1, L2 }, /* bsrmovl */
+ { { 0x95 }, 2, F, W, pfx_f2, W0, L2 }, /* bsrmovh */
+ { { 0x95 }, 2, F, R, pfx_f2, W1, L2 }, /* bsrmovh */
{ { 0x96 }, 2, T, R, pfx_66, W0, Ln }, /* vfmaddsub132ph */
{ { 0x97 }, 2, T, R, pfx_66, W0, Ln }, /* vfmsubadd132ph */
{ { 0x98 }, 2, T, R, pfx_66, W0, Ln }, /* vfmadd132ph */
--- a/xen/arch/x86/x86_emulate/decode.c
+++ b/xen/arch/x86/x86_emulate/decode.c
@@ -406,6 +406,7 @@ static const struct ext0f38_table {
[0x8e] = { .simd_size = simd_packed_int, .to_mem = 1 },
[0x8f] = { .simd_size = simd_packed_int, .d8s = d8s_vl },
[0x90 ... 0x93] = { .simd_size = simd_other, .vsib = 1, .d8s = d8s_dq },
+ [0x95] = { .simd_size = simd_other, .d8s = d8s_vl },
[0x96 ... 0x98] = { .simd_size = simd_packed_fp, .d8s = d8s_vl },
[0x99] = { .simd_size = simd_scalar_vexw, .d8s = d8s_dq },
[0x9a] = { .simd_size = simd_packed_fp, .d8s = d8s_vl },
@@ -1559,6 +1560,26 @@ decode_map5(struct x86_emulate_state *s,
return rc;
}
+static int
+decode_map6(struct x86_emulate_state *s,
+ struct x86_emulate_ctxt *ctxt,
+ const struct x86_emulate_ops *ops)
+{
+ int rc = X86EMUL_OKAY;
+
+ switch ( ctxt->opcode & 0xff )
+ {
+ case 0x95: /* bsrmov{f,h,l} */
+ if ( !s->evex.w )
+ s->desc = DstMem | SrcReg;
+ if ( s->evex.pfx )
+ s->desc |= TwoOp;
+ break;
+ }
+
+ return rc;
+}
+
#define ad_bytes (s->ad_bytes) /* for truncate_ea() */
int x86emul_decode(struct x86_emulate_state *s,
@@ -2706,6 +2727,9 @@ int x86emul_decode(struct x86_emulate_st
break;
case ext_map6:
+ rc = decode_map6(s, ctxt, ops);
+ break;
+
case ext_map7:
case ext_8f09:
case ext_8f0a:
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -6794,18 +6794,29 @@ x86_emulate(
goto unrecognized_insn;
case X86EMUL_OPC_VEX_F2(0x0f38, 0x49):
- generate_exception_if(!mode_64bit() || vex.l || vex.w, X86_EXC_UD);
+ generate_exception_if(!mode_64bit() || vex.l, X86_EXC_UD);
if ( ea.type == OP_REG )
{
switch ( modrm_rm & 7 )
{
- case 0: /* tilezero */
- if ( !vcpu_has_ace() )
- vcpu_must_have(amx_tile);
- get_fpu(X86EMUL_FPU_tile);
+ case 0:
+ if ( !vex.w ) /* tilezero */
+ {
+ if ( !vcpu_has_ace() )
+ vcpu_must_have(amx_tile);
+ get_fpu(X86EMUL_FPU_tile);
+ }
+ else /* bsrinit */
+ {
+ vcpu_must_have(ace);
+ get_fpu(X86EMUL_FPU_ace);
+ }
sttilecfg(&mmvalp->tilecfg);
- generate_exception_if(!tile_valid(modrm_reg, &mmvalp->tilecfg,
- PALETTE(AMX, ACE)),
+ generate_exception_if(vex.w
+ ? mmvalp->tilecfg.palette != PALETTE_ACE
||
+ modrm_reg
+ : !tile_valid(modrm_reg,
&mmvalp->tilecfg,
+ PALETTE(AMX, ACE)),
X86_EXC_UD);
op_bytes = 1; /* fake */
goto simd_0f_common;
@@ -9415,6 +9426,41 @@ x86_emulate(
avx512_vlen_check(false);
goto simd_zmm;
+ case X86EMUL_OPC_EVEX (6, 0x95): /* bsrmovf zmm/m512,zmm,%bsr0 */
+ generate_exception_if(!evex.w, X86_EXC_UD);
+ fallthrough;
+ case X86EMUL_OPC_EVEX_F3(6, 0x95): /* bsrmovl zmm/m512,%bsr0 */
+ /* bsrmovl %bsr0,zmm/m512 */
+ case X86EMUL_OPC_EVEX_F2(6, 0x95): /* bsrmovh zmm/m512,%bsr0 */
+ /* bsrmovh %bsr0,zmm/m512 */
+ vcpu_must_have(ace);
+ generate_exception_if((evex.brs || evex.opmsk || evex.lr != 2),
+ X86_EXC_UD);
+
+ get_fpu(X86EMUL_FPU_zmm_ace);
+ sttilecfg(&mmvalp->tilecfg);
+ generate_exception_if(mmvalp->tilecfg.palette != PALETTE_ACE,
+ X86_EXC_UD);
+
+ generate_exception_if(modrm_reg, X86_EXC_UD);
+
+ opc = init_evex(stub);
+ opc[0] = b;
+ opc[1] = modrm;
+ if ( ea.type == OP_MEM )
+ {
+ generate_exception_if(!evex.RX && !(state->xcr0 & X86_XCR0_APX),
+ X86_EXC_UD);
+
+ /* convert memory operand to (%rAX) */
+ evex.b3 = 1;
+ evex.b4 = 0;
+ opc[1] &= 0x38;
+ }
+ insn_bytes = EVEX_PFX_BYTES + 2;
+ op_bytes = 64;
+ break;
+
case X86EMUL_OPC_XOP(08, 0x85): /* vpmacssww xmm,xmm/m128,xmm,xmm */
case X86EMUL_OPC_XOP(08, 0x86): /* vpmacsswd xmm,xmm/m128,xmm,xmm */
case X86EMUL_OPC_XOP(08, 0x87): /* vpmacssdql xmm,xmm/m128,xmm,xmm */
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |