]> xenbits.xensource.com Git - people/sstabellini/xen-unstable.git/.git/commitdiff
x86emul: support AVX512F move duplicate insns
authorJan Beulich <jbeulich@suse.com>
Tue, 21 May 2019 13:45:59 +0000 (15:45 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 21 May 2019 13:45:59 +0000 (15:45 +0200)
Judging from insn prefixes, these are scalar insns, but their (memory)
operands are vector ones (with the exception of 128-bit VMOVDDUP). For
this some adjustments to disp8scale calculation code are needed.

No explicit test harness additions other than the overrides, as the
compiler already makes use of the insns.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
tools/tests/x86_emulator/evex-disp8.c
tools/tests/x86_emulator/simd.h
xen/arch/x86/x86_emulate/x86_emulate.c

index ff721ef354505ad3ce7a022c8630a169f47419f1..bff18dd3f6fc133a0a87a454e0a9fd691e8ab96e 100644 (file)
@@ -146,6 +146,7 @@ static const struct test avx512f_all[] = {
     INSN_SFP(mov,            0f, 11),
     INSN_PFP_NB(mova,        0f, 28),
     INSN_PFP_NB(mova,        0f, 29),
+    INSN(movddup,      f2,   0f, 12,    vl,   q_nb, vl),
     INSN(movdqa32,     66,   0f, 6f,    vl,   d_nb, vl),
     INSN(movdqa32,     66,   0f, 7f,    vl,   d_nb, vl),
     INSN(movdqa64,     66,   0f, 6f,    vl,   q_nb, vl),
@@ -157,6 +158,8 @@ static const struct test avx512f_all[] = {
     INSN(movntdq,      66,   0f, e7,    vl,   d_nb, vl),
     INSN(movntdqa,     66, 0f38, 2a,    vl,   d_nb, vl),
     INSN_PFP_NB(movnt,       0f, 2b),
+    INSN(movshdup,     f3,   0f, 16,    vl,   d_nb, vl),
+    INSN(movsldup,     f3,   0f, 12,    vl,   d_nb, vl),
     INSN_PFP_NB(movu,        0f, 10),
     INSN_PFP_NB(movu,        0f, 11),
     INSN_FP(mul,             0f, 59),
@@ -694,6 +697,19 @@ static void test_group(const struct test tests[], unsigned int nr_test,
 
             switch ( tests[i].esz )
             {
+            case ESZ_q_nb:
+                /* The 128-bit form of VMOVDDUP needs special casing. */
+                if ( vl[j] == VL_128 && tests[i].spc == SPC_0f &&
+                     tests[i].opc == 0x12 && tests[i].pfx == PFX_f2 )
+                {
+                    struct test test = tests[i];
+
+                    test.vsz = VSZ_el;
+                    test.scale = SC_el;
+                    test_one(&test, vl[j], instr, ctxt);
+                    continue;
+                }
+                /* fall through */
             default:
                 test_one(&tests[i], vl[j], instr, ctxt);
                 break;
index f3cf2490adce38a16d1ea38a9d608577f093b39c..0a3eccca84e38de2d38c596f9f425e4082f2c0d7 100644 (file)
@@ -326,8 +326,11 @@ REN(pandn, , d);
 REN(por, , d);
 REN(pxor, , d);
 #  endif
+OVR(movddup);
 OVR(movntdq);
 OVR(movntdqa);
+OVR(movshdup);
+OVR(movsldup);
 OVR(pmovsxbd);
 OVR(pmovsxbq);
 OVR(pmovsxdq);
index 4fb888053307f588048a2d70094d4f146579d125..9f3c3780d8cc4a04731048878031eddde9ac6e68 100644 (file)
@@ -3016,6 +3016,15 @@ x86_decode(
 
             switch ( b )
             {
+            case 0x12: /* vmovsldup / vmovddup */
+                if ( evex.pfx == vex_f2 )
+                    disp8scale = evex.lr ? 4 + evex.lr : 3;
+                /* fall through */
+            case 0x16: /* vmovshdup */
+                if ( evex.pfx == vex_f3 )
+                    disp8scale = 4 + evex.lr;
+                break;
+
             case 0x20: /* mov cr,reg */
             case 0x21: /* mov dr,reg */
             case 0x22: /* mov reg,cr */
@@ -6040,6 +6049,20 @@ x86_emulate(
         host_and_vcpu_must_have(sse3);
         goto simd_0f_xmm;
 
+    case X86EMUL_OPC_EVEX_F3(0x0f, 0x12):   /* vmovsldup [xyz]mm/mem,[xyz]mm{k} */
+    case X86EMUL_OPC_EVEX_F2(0x0f, 0x12):   /* vmovddup [xyz]mm/mem,[xyz]mm{k} */
+    case X86EMUL_OPC_EVEX_F3(0x0f, 0x16):   /* vmovshdup [xyz]mm/mem,[xyz]mm{k} */
+        generate_exception_if((evex.brs ||
+                               evex.w != (evex.pfx & VEX_PREFIX_DOUBLE_MASK)),
+                              EXC_UD);
+        host_and_vcpu_must_have(avx512f);
+        avx512_vlen_check(false);
+        d |= TwoOp;
+        op_bytes = !(evex.pfx & VEX_PREFIX_DOUBLE_MASK) || evex.lr
+                   ? 16 << evex.lr : 8;
+        fault_suppression = false;
+        goto simd_zmm;
+
     CASE_SIMD_PACKED_FP(_EVEX, 0x0f, 0x14): /* vunpcklp{s,d} [xyz]mm/mem,[xyz]mm,[xyz]mm{k} */
     CASE_SIMD_PACKED_FP(_EVEX, 0x0f, 0x15): /* vunpckhp{s,d} [xyz]mm/mem,[xyz]mm,[xyz]mm{k} */
         generate_exception_if(evex.w != (evex.pfx & VEX_PREFIX_DOUBLE_MASK),