[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 2/8] x86emul: support ADCX/ADOX



Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -885,10 +885,65 @@ int main(int argc, char **argv)
                               #which ": " insn "\n"                     \
                               ".equ " #which "_len, .-" #which "\n"     \
                               ".popsection"
-#define set_insn(which) (regs.eip = (unsigned long)memcpy(instr, which, \
-                                             (unsigned long)which##_len))
-#define check_eip(which) (regs.eip == (unsigned long)instr + \
+#define set_insn(which) (regs.eip = (unsigned long)(which))
+#define valid_eip(which) (regs.eip >= (unsigned long)(which) && \
+                          regs.eip < (unsigned long)(which) + \
                                       (unsigned long)which##_len)
+#define check_eip(which) (regs.eip == (unsigned long)(which) + \
+                                      (unsigned long)which##_len)
+
+    printf("%-40s", "Testing adcx/adox ...");
+    {
+        static const unsigned int data[] = {
+            0x01234567, 0x12345678, 0x23456789, 0x3456789a,
+            0x456789ab, 0x56789abc, 0x6789abcd, 0x789abcde,
+            0x89abcdef, 0x9abcdef0, 0xabcdef01, 0xbcdef012,
+            0xcdef0123, 0xdef01234, 0xef012345, 0xf0123456
+        };
+        decl_insn(adx);
+        unsigned int cf, of;
+
+        asm volatile ( put_insn(adx, ".Lloop%=:\n\t"
+                                     "adcx (%[addr]), %k[dst1]\n\t"
+                                     "adox 
-%c[full]-%c[elem](%[addr],%[cnt],2*%c[elem]), %k[dst2]\n\t"
+                                     "lea %c[elem](%[addr]),%[addr]\n\t"
+                                     "loop .Lloop%=\n\t"
+                                     "adcx %k[cnt], %k[dst1]\n\t"
+                                     "adox %k[cnt], %k[dst2]\n\t" )
+                       : [addr] "=S" (regs.esi), [cnt] "=c" (regs.ecx),
+                         [dst1] "=a" (regs.eax), [dst2] "=d" (regs.edx)
+                       : [full] "i" (sizeof(data)), [elem] "i" (sizeof(*data)),
+                         "[addr]" (data), "[cnt]" (ARRAY_SIZE(data)),
+                         "[dst1]" (0), "[dst2]" (0) );
+
+        set_insn(adx);
+        regs.eflags = 0x2d6;
+        of = cf = i = 0;
+        while ( (rc = x86_emulate(&ctxt, &emulops)) == X86EMUL_OKAY )
+        {
+            ++i;
+            /*
+             * Count CF/OF being set after each loop iteration during the
+             * first half (to observe different counts), in order to catch
+             * the wrong flag being fiddled with.
+             */
+            if ( i < ARRAY_SIZE(data) * 2 && !(i % 4) )
+            {
+                if ( regs.eflags & 0x001 )
+                   ++cf;
+                if ( regs.eflags & 0x800 )
+                   ++of;
+            }
+            if ( !valid_eip(adx) )
+                break;
+        }
+        if ( (rc != X86EMUL_OKAY) ||
+             i != ARRAY_SIZE(data) * 4 + 2 || cf != 1 || of != 5 ||
+             regs.eax != 0xffffffff || regs.ecx || regs.edx != 0xffffffff ||
+             !check_eip(adx) || regs.eflags != 0x2d6 )
+            goto fail;
+        printf("okay\n");
+    }
 
     printf("%-40s", "Testing movq %mm3,(%ecx)...");
     if ( stack_exec && cpu_has_mmx )
--- a/tools/tests/x86_emulator/x86_emulate.c
+++ b/tools/tests/x86_emulator/x86_emulate.c
@@ -60,6 +60,10 @@ int emul_test_cpuid(
     if ( leaf == 1 )
         res->c |= 1U << 22;
 
+    /* The emulator doesn't itself use ADCX/ADOX, so we can always run the 
test. */
+    if ( leaf == 7 && subleaf == 0 )
+        res->b |= 1U << 19;
+
     return X86EMUL_OKAY;
 }
 
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -1345,6 +1345,7 @@ static bool vcpu_has(
 #define vcpu_has_hle()         vcpu_has(         7, EBX,  4, ctxt, ops)
 #define vcpu_has_rtm()         vcpu_has(         7, EBX, 11, ctxt, ops)
 #define vcpu_has_mpx()         vcpu_has(         7, EBX, 14, ctxt, ops)
+#define vcpu_has_adx()         vcpu_has(         7, EBX, 19, ctxt, ops)
 #define vcpu_has_smap()        vcpu_has(         7, EBX, 20, ctxt, ops)
 #define vcpu_has_clflushopt()  vcpu_has(         7, EBX, 23, ctxt, ops)
 #define vcpu_has_clwb()        vcpu_has(         7, EBX, 24, ctxt, ops)
@@ -5864,6 +5865,40 @@ x86_emulate(
         }
         break;
 #endif
+
+    case X86EMUL_OPC_66(0x0f38, 0xf6): /* adcx r/m,r */
+    case X86EMUL_OPC_F3(0x0f38, 0xf6): /* adox r/m,r */
+    {
+        unsigned int mask = rep_prefix() ? EFLG_OF : EFLG_CF;
+        unsigned int aux = _regs._eflags & mask ? ~0 : 0;
+        bool carry;
+
+        vcpu_must_have(adx);
+#ifdef __x86_64__
+        if ( op_bytes == 8 )
+            asm ( "add %[aux],%[aux]\n\t"
+                  "adc %[src],%[dst]\n\t"
+                  ASM_FLAG_OUT(, "setc %[carry]")
+                  : [dst] "+r" (dst.val),
+                    [carry] ASM_FLAG_OUT("=@ccc", "=qm") (carry),
+                    [aux] "+r" (aux)
+                  : [src] "rm" (src.val) );
+        else
+#endif
+            asm ( "add %[aux],%[aux]\n\t"
+                  "adc %k[src],%k[dst]\n\t"
+                  ASM_FLAG_OUT(, "setc %[carry]")
+                  : [dst] "+r" (dst.val),
+                    [carry] ASM_FLAG_OUT("=@ccc", "=qm") (carry),
+                    [aux] "+r" (aux)
+                  : [src] "rm" (src.val) );
+        if ( carry )
+            _regs._eflags |= mask;
+        else
+            _regs._eflags &= ~mask;
+        break;
+    }
+
     default:
         goto cannot_emulate;
     }


Attachment: x86emul-ADX.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.