|
[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 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |