qemu/tests/tcg/i386/test-i386-bmi2.c
Richard Henderson 93ff84d4c0 tests/tcg/i386: Introduce and use reg_t consistently
Define reg_t based on the actual register width.
Define the inlines using that type.  This will allow
input registers to 32-bit insns to be set to 64-bit
values on x86-64, which allows testing various edge cases.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20230114230542.3116013-2-richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 5d62d6649c)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2023-03-29 10:20:04 +03:00

200 lines
5.9 KiB
C

/* See if various BMI2 instructions give expected results */
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#ifdef __x86_64
typedef uint64_t reg_t;
#else
typedef uint32_t reg_t;
#endif
#define insn1q(name, arg0) \
static inline reg_t name##q(reg_t arg0) \
{ \
reg_t result64; \
asm volatile (#name "q %1, %0" : "=r"(result64) : "rm"(arg0)); \
return result64; \
}
#define insn1l(name, arg0) \
static inline reg_t name##l(reg_t arg0) \
{ \
reg_t result32; \
asm volatile (#name "l %k1, %k0" : "=r"(result32) : "rm"(arg0)); \
return result32; \
}
#define insn2q(name, arg0, c0, arg1, c1) \
static inline reg_t name##q(reg_t arg0, reg_t arg1) \
{ \
reg_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 reg_t name##l(reg_t arg0, reg_t arg1) \
{ \
reg_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;
uint64_t mask = 0xa080800302020001ull;
reg_t result;
#ifdef __x86_64
/* 64 bits */
result = andnq(mask, ehlo);
assert(result == 0x002020204d4c4844);
result = pextq(ehlo, mask);
assert(result == 133);
result = pdepq(result, mask);
assert(result == (ehlo & mask));
result = pextq(-1ull, mask);
assert(result == 511); /* mask has 9 bits set */
result = pdepq(-1ull, mask);
assert(result == mask);
result = bextrq(mask, 0x3f00);
assert(result == (mask & ~INT64_MIN));
result = bextrq(mask, 0x1038);
assert(result == 0xa0);
result = bextrq(mask, 0x10f8);
assert(result == 0);
result = blsiq(0x30);
assert(result == 0x10);
result = blsiq(0x30ull << 32);
assert(result == 0x10ull << 32);
result = blsmskq(0x30);
assert(result == 0x1f);
result = blsrq(0x30);
assert(result == 0x20);
result = blsrq(0x30ull << 32);
assert(result == 0x20ull << 32);
result = bzhiq(mask, 0x3f);
assert(result == (mask & ~INT64_MIN));
result = bzhiq(mask, 0x1f);
assert(result == (mask & ~(-1 << 30)));
result = rorxq(0x2132435465768798, 8);
assert(result == 0x9821324354657687);
result = sarxq(0xffeeddccbbaa9988, 8);
assert(result == 0xffffeeddccbbaa99);
result = sarxq(0x77eeddccbbaa9988, 8 | 64);
assert(result == 0x0077eeddccbbaa99);
result = shrxq(0xffeeddccbbaa9988, 8);
assert(result == 0x00ffeeddccbbaa99);
result = shrxq(0x77eeddccbbaa9988, 8 | 192);
assert(result == 0x0077eeddccbbaa99);
result = shlxq(0xffeeddccbbaa9988, 8);
assert(result == 0xeeddccbbaa998800);
#endif
/* 32 bits */
result = andnl(mask, ehlo);
assert(result == 0x04d4c4844);
result = pextl((uint32_t) ehlo, mask);
assert(result == 5);
result = pdepl(result, mask);
assert(result == (uint32_t)(ehlo & mask));
result = pextl(-1u, mask);
assert(result == 7); /* mask has 3 bits set */
result = pdepl(-1u, mask);
assert(result == (uint32_t)mask);
result = bextrl(mask, 0x1f00);
assert(result == (mask & ~INT32_MIN));
result = bextrl(ehlo, 0x1018);
assert(result == 0x4f);
result = bextrl(mask, 0x1038);
assert(result == 0);
result = blsil(0xffff);
assert(result == 1);
result = blsmskl(0x300);
assert(result == 0x1ff);
result = blsrl(0xffc);
assert(result == 0xff8);
result = bzhil(mask, 0xf);
assert(result == 1);
result = rorxl(0x65768798, 8);
assert(result == 0x98657687);
result = sarxl(0xffeeddcc, 8);
assert(result == 0xffffeedd);
result = sarxl(0x77eeddcc, 8 | 32);
assert(result == 0x0077eedd);
result = shrxl(0xffeeddcc, 8);
assert(result == 0x00ffeedd);
result = shrxl(0x77eeddcc, 8 | 128);
assert(result == 0x0077eedd);
result = shlxl(0xffeeddcc, 8);
assert(result == 0xeeddcc00);
return 0;
}