tests/tcg: i386: extend BMI test

Cover all BMI1 and BMI2 instructions, both 32- and 64-bit.

Due to the use of inlines, the test now has to be compiled with -O2.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
master
Paolo Bonzini 2022-08-25 12:58:18 +02:00
parent 9e8504c057
commit 7b764d4173
2 changed files with 162 additions and 8 deletions

View File

@ -18,6 +18,7 @@ test-i386-pcmpistri: CFLAGS += -msse4.2
run-test-i386-pcmpistri: QEMU_OPTS += -cpu max
run-plugin-test-i386-pcmpistri-%: QEMU_OPTS += -cpu max
test-i386-bmi2: CFLAGS=-O2
run-test-i386-bmi2: QEMU_OPTS += -cpu max
run-plugin-test-i386-bmi2-%: QEMU_OPTS += -cpu max

View File

@ -1,6 +1,66 @@
/* See if various BMI2 instructions give expected results */
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#define insn1q(name, arg0) \
static inline uint64_t name##q(uint64_t arg0) \
{ \
uint64_t result64; \
asm volatile (#name "q %1, %0" : "=r"(result64) : "rm"(arg0)); \
return result64; \
}
#define insn1l(name, arg0) \
static inline uint32_t name##l(uint32_t arg0) \
{ \
uint32_t result32; \
asm volatile (#name "l %k1, %k0" : "=r"(result32) : "rm"(arg0)); \
return result32; \
}
#define insn2q(name, arg0, c0, arg1, c1) \
static inline uint64_t name##q(uint64_t arg0, uint64_t arg1) \
{ \
uint64_t result64; \
asm volatile (#name "q %2, %1, %0" : "=r"(result64) : c0(arg0), c1(arg1)); \
return result64; \
}
#define insn2l(name, arg0, c0, arg1, c1) \
static inline uint32_t name##l(uint32_t arg0, uint32_t arg1) \
{ \
uint32_t result32; \
asm volatile (#name "l %k2, %k1, %k0" : "=r"(result32) : c0(arg0), c1(arg1)); \
return result32; \
}
#ifdef __x86_64
insn2q(pext, src, "r", mask, "rm")
insn2q(pdep, src, "r", mask, "rm")
insn2q(andn, clear, "rm", val, "r")
insn2q(bextr, range, "rm", val, "r")
insn2q(bzhi, pos, "rm", val, "r")
insn2q(rorx, val, "r", n, "i")
insn2q(sarx, val, "rm", n, "r")
insn2q(shlx, val, "rm", n, "r")
insn2q(shrx, val, "rm", n, "r")
insn1q(blsi, src)
insn1q(blsmsk, src)
insn1q(blsr, src)
#endif
insn2l(pext, src, "r", mask, "rm")
insn2l(pdep, src, "r", mask, "rm")
insn2l(andn, clear, "rm", val, "r")
insn2l(bextr, range, "rm", val, "r")
insn2l(bzhi, pos, "rm", val, "r")
insn2l(rorx, val, "r", n, "i")
insn2l(sarx, val, "rm", n, "r")
insn2l(shlx, val, "rm", n, "r")
insn2l(shrx, val, "rm", n, "r")
insn1l(blsi, src)
insn1l(blsmsk, src)
insn1l(blsr, src)
int main(int argc, char *argv[]) {
uint64_t ehlo = 0x202020204f4c4845ull;
@ -11,32 +71,125 @@ int main(int argc, char *argv[]) {
uint64_t result64;
/* 64 bits */
asm volatile ("pextq %2, %1, %0" : "=r"(result64) : "r"(ehlo), "m"(mask));
result64 = andnq(mask, ehlo);
assert(result64 == 0x002020204d4c4844);
result64 = pextq(ehlo, mask);
assert(result64 == 133);
asm volatile ("pdepq %2, %1, %0" : "=r"(result64) : "r"(result64), "m"(mask));
result64 = pdepq(result64, mask);
assert(result64 == (ehlo & mask));
asm volatile ("pextq %2, %1, %0" : "=r"(result64) : "r"(-1ull), "m"(mask));
result64 = pextq(-1ull, mask);
assert(result64 == 511); /* mask has 9 bits set */
asm volatile ("pdepq %2, %1, %0" : "=r"(result64) : "r"(-1ull), "m"(mask));
result64 = pdepq(-1ull, mask);
assert(result64 == mask);
result64 = bextrq(mask, 0x3f00);
assert(result64 == (mask & ~INT64_MIN));
result64 = bextrq(mask, 0x1038);
assert(result64 == 0xa0);
result64 = bextrq(mask, 0x10f8);
assert(result64 == 0);
result64 = blsiq(0x30);
assert(result64 == 0x10);
result64 = blsiq(0x30ull << 32);
assert(result64 == 0x10ull << 32);
result64 = blsmskq(0x30);
assert(result64 == 0x1f);
result64 = blsrq(0x30);
assert(result64 == 0x20);
result64 = blsrq(0x30ull << 32);
assert(result64 == 0x20ull << 32);
result64 = bzhiq(mask, 0x3f);
assert(result64 == (mask & ~INT64_MIN));
result64 = bzhiq(mask, 0x1f);
assert(result64 == (mask & ~(-1 << 30)));
result64 = rorxq(0x2132435465768798, 8);
assert(result64 == 0x9821324354657687);
result64 = sarxq(0xffeeddccbbaa9988, 8);
assert(result64 == 0xffffeeddccbbaa99);
result64 = sarxq(0x77eeddccbbaa9988, 8 | 64);
assert(result64 == 0x0077eeddccbbaa99);
result64 = shrxq(0xffeeddccbbaa9988, 8);
assert(result64 == 0x00ffeeddccbbaa99);
result64 = shrxq(0x77eeddccbbaa9988, 8 | 192);
assert(result64 == 0x0077eeddccbbaa99);
result64 = shlxq(0xffeeddccbbaa9988, 8);
assert(result64 == 0xeeddccbbaa998800);
#endif
/* 32 bits */
asm volatile ("pextl %2, %k1, %k0" : "=r"(result32) : "r"((uint32_t) ehlo), "m"(mask));
result32 = andnl(mask, ehlo);
assert(result32 == 0x04d4c4844);
result32 = pextl((uint32_t) ehlo, mask);
assert(result32 == 5);
asm volatile ("pdepl %2, %k1, %k0" : "=r"(result32) : "r"(result32), "m"(mask));
result32 = pdepl(result32, mask);
assert(result32 == (uint32_t)(ehlo & mask));
asm volatile ("pextl %2, %k1, %k0" : "=r"(result32) : "r"(-1ull), "m"(mask));
result32 = pextl(-1u, mask);
assert(result32 == 7); /* mask has 3 bits set */
asm volatile ("pdepl %2, %k1, %k0" : "=r"(result32) : "r"(-1ull), "m"(mask));
result32 = pdepl(-1u, mask);
assert(result32 == (uint32_t)mask);
result32 = bextrl(mask, 0x1f00);
assert(result32 == (mask & ~INT32_MIN));
result32 = bextrl(ehlo, 0x1018);
assert(result32 == 0x4f);
result32 = bextrl(mask, 0x1038);
assert(result32 == 0);
result32 = blsil(0xffff);
assert(result32 == 1);
result32 = blsmskl(0x300);
assert(result32 == 0x1ff);
result32 = blsrl(0xffc);
assert(result32 == 0xff8);
result32 = bzhil(mask, 0xf);
assert(result32 == 1);
result32 = rorxl(0x65768798, 8);
assert(result32 == 0x98657687);
result32 = sarxl(0xffeeddcc, 8);
assert(result32 == 0xffffeedd);
result32 = sarxl(0x77eeddcc, 8 | 32);
assert(result32 == 0x0077eedd);
result32 = shrxl(0xffeeddcc, 8);
assert(result32 == 0x00ffeedd);
result32 = shrxl(0x77eeddcc, 8 | 128);
assert(result32 == 0x0077eedd);
result32 = shlxl(0xffeeddcc, 8);
assert(result32 == 0xeeddcc00);
return 0;
}