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.
Signed-off-by: Paolo Bonzini
---
tests/tcg/i386/Makefile.target | 1 +
tests/tcg/i386/test-i386-bmi2.c | 169 ++--
2 files changed, 162 insertions(+), 8 deletions(-)
diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target
index 5614838ffc..646b4ac13e 100644
--- a/tests/tcg/i386/Makefile.target
+++ b/tests/tcg/i386/Makefile.target
@@ -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
diff --git a/tests/tcg/i386/test-i386-bmi2.c b/tests/tcg/i386/test-i386-bmi2.c
index 935a4d2a73..5fadf47510 100644
--- a/tests/tcg/i386/test-i386-bmi2.c
+++ b/tests/tcg/i386/test-i386-bmi2.c
@@ -1,6 +1,66 @@
/* See if various BMI2 instructions give expected results */
#include
#include
+#include
+
+#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);
+