mirror of
https://github.com/herumi/xbyak
synced 2024-11-21 16:09:11 -07:00
d700f6c357
The XSAVE cpuid flag determines if the processor supports the XSAVE instructions(`xsave`, `xrestor`, `xsetbv`, `xgetbv`). The OSXSAVE cpuid flag determines if the _operating system_ has XSAVE **enabled**. Userland code has to use OSXSAVE for features such as AVX and AVX512 but it still matters to know if the processor itself supports it but not the operating system such as some virtual-machine contexts.
151 lines
4.3 KiB
C++
151 lines
4.3 KiB
C++
#include <stdio.h>
|
|
#include "xbyak/xbyak_util.h"
|
|
|
|
#define NUM_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))
|
|
|
|
struct PopCountTest : public Xbyak::CodeGenerator {
|
|
PopCountTest(int n)
|
|
: Xbyak::CodeGenerator(4096, Xbyak::DontSetProtectRWE)
|
|
{
|
|
mov(eax, n);
|
|
popcnt(eax, eax);
|
|
ret();
|
|
}
|
|
};
|
|
|
|
void putCPUinfo(bool onlyCpuidFeature)
|
|
{
|
|
using namespace Xbyak::util;
|
|
Cpu cpu;
|
|
printf("vendor %s\n", cpu.has(Cpu::tINTEL) ? "intel" : "amd");
|
|
static const struct {
|
|
Cpu::Type type;
|
|
const char *str;
|
|
} tbl[] = {
|
|
{ Cpu::tMMX, "mmx" },
|
|
{ Cpu::tMMX2, "mmx2" },
|
|
{ Cpu::tCMOV, "cmov" },
|
|
{ Cpu::tSSE, "sse" },
|
|
{ Cpu::tSSE2, "sse2" },
|
|
{ Cpu::tSSE3, "sse3" },
|
|
{ Cpu::tSSSE3, "ssse3" },
|
|
{ Cpu::tSSE41, "sse41" },
|
|
{ Cpu::tSSE42, "sse42" },
|
|
{ Cpu::tPOPCNT, "popcnt" },
|
|
{ Cpu::t3DN, "3dn" },
|
|
{ Cpu::tE3DN, "e3dn" },
|
|
{ Cpu::tAESNI, "aesni" },
|
|
{ Cpu::tRDTSCP, "rdtscp" },
|
|
{ Cpu::tXSAVE, "xsave(xgetvb)" },
|
|
{ Cpu::tOSXSAVE, "osxsave" },
|
|
{ Cpu::tPCLMULQDQ, "pclmulqdq" },
|
|
{ Cpu::tAVX, "avx" },
|
|
{ Cpu::tFMA, "fma" },
|
|
{ Cpu::tAVX2, "avx2" },
|
|
{ Cpu::tBMI1, "bmi1" },
|
|
{ Cpu::tBMI2, "bmi2" },
|
|
{ Cpu::tLZCNT, "lzcnt" },
|
|
{ Cpu::tPREFETCHW, "prefetchw" },
|
|
{ Cpu::tENHANCED_REP, "enh_rep" },
|
|
{ Cpu::tRDRAND, "rdrand" },
|
|
{ Cpu::tADX, "adx" },
|
|
{ Cpu::tRDSEED, "rdseed" },
|
|
{ Cpu::tSMAP, "smap" },
|
|
{ Cpu::tHLE, "hle" },
|
|
{ Cpu::tRTM, "rtm" },
|
|
{ Cpu::tMPX, "mpx" },
|
|
{ Cpu::tSHA, "sha" },
|
|
{ Cpu::tPREFETCHWT1, "prefetchwt1" },
|
|
{ Cpu::tF16C, "f16c" },
|
|
{ Cpu::tMOVBE, "movbe" },
|
|
{ Cpu::tAVX512F, "avx512f" },
|
|
{ Cpu::tAVX512DQ, "avx512dq" },
|
|
{ Cpu::tAVX512IFMA, "avx512_ifma" },
|
|
{ Cpu::tAVX512PF, "avx512pf" },
|
|
{ Cpu::tAVX512ER, "avx512er" },
|
|
{ Cpu::tAVX512CD, "avx512cd" },
|
|
{ Cpu::tAVX512BW, "avx512bw" },
|
|
{ Cpu::tAVX512VL, "avx512vl" },
|
|
{ Cpu::tAVX512VBMI, "avx512_vbmi" },
|
|
{ Cpu::tAVX512_4VNNIW, "avx512_4vnniw" },
|
|
{ Cpu::tAVX512_4FMAPS, "avx512_4fmaps" },
|
|
|
|
{ Cpu::tAVX512_VBMI2, "avx512_vbmi2" },
|
|
{ Cpu::tGFNI, "gfni" },
|
|
{ Cpu::tVAES, "vaes" },
|
|
{ Cpu::tVPCLMULQDQ, "vpclmulqdq" },
|
|
{ Cpu::tAVX512_VNNI, "avx512_vnni" },
|
|
{ Cpu::tAVX512_BITALG, "avx512_bitalg" },
|
|
{ Cpu::tAVX512_VPOPCNTDQ, "avx512_vpopcntdq" },
|
|
{ Cpu::tAVX512_BF16, "avx512_bf16" },
|
|
{ Cpu::tAVX512_VP2INTERSECT, "avx512_vp2intersect" },
|
|
{ Cpu::tAMX_TILE, "amx(tile)" },
|
|
{ Cpu::tAMX_INT8, "amx(int8)" },
|
|
{ Cpu::tAMX_BF16, "amx(bf16)" },
|
|
{ Cpu::tAVX_VNNI, "avx_vnni" },
|
|
{ Cpu::tAVX512_FP16, "avx512_fp16" },
|
|
{ Cpu::tWAITPKG, "waitpkg" },
|
|
{ Cpu::tCLFLUSHOPT, "clflushopt" },
|
|
{ Cpu::tCLDEMOTE, "cldemote" },
|
|
{ Cpu::tMOVDIRI, "movdiri" },
|
|
{ Cpu::tMOVDIR64B, "movdir64b" },
|
|
{ Cpu::tUINTR, "uintr" },
|
|
{ Cpu::tSERIALIZE, "serialize" },
|
|
{ Cpu::tCLZERO, "clzero" },
|
|
{ Cpu::tAMX_FP16, "amx_fp16" },
|
|
{ Cpu::tAVX_VNNI_INT8, "avx_vnni_int8" },
|
|
{ Cpu::tAVX_NE_CONVERT, "avx_ne_convert" },
|
|
{ Cpu::tAVX_IFMA, "avx_ifma" },
|
|
{ Cpu::tRAO_INT, "rao-int" },
|
|
{ Cpu::tCMPCCXADD, "cmpccxadd" },
|
|
{ Cpu::tPREFETCHITI, "prefetchiti" },
|
|
};
|
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
|
if (cpu.has(tbl[i].type)) printf(" %s", tbl[i].str);
|
|
}
|
|
printf("\n");
|
|
if (onlyCpuidFeature) return;
|
|
if (cpu.has(Cpu::tPOPCNT)) {
|
|
const int n = 0x12345678; // bitcount = 13
|
|
const int ok = 13;
|
|
PopCountTest code(n);
|
|
code.setProtectModeRE();
|
|
int (*f)() = code.getCode<int (*)()>();
|
|
int r = f();
|
|
if (r == ok) {
|
|
puts("popcnt ok");
|
|
} else {
|
|
printf("popcnt ng %d %d\n", r, ok);
|
|
}
|
|
code.setProtectModeRW();
|
|
}
|
|
/*
|
|
displayFamily displayModel
|
|
Opteron 2376 10 4
|
|
Core2 Duo T7100 6 F
|
|
Core i3-2120T 6 2A
|
|
Core i7-2600 6 2A
|
|
Xeon X5650 6 2C
|
|
Core i7-3517 6 3A
|
|
Core i7-3930K 6 2D
|
|
*/
|
|
cpu.putFamily();
|
|
for (unsigned int i = 0; i < cpu.getDataCacheLevels(); i++) {
|
|
printf("cache level=%u data cache size=%u cores sharing data cache=%u\n", i, cpu.getDataCacheSize(i), cpu.getCoresSharingDataCache(i));
|
|
}
|
|
printf("SmtLevel =%u\n", cpu.getNumCores(Xbyak::util::SmtLevel));
|
|
printf("CoreLevel=%u\n", cpu.getNumCores(Xbyak::util::CoreLevel));
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
bool onlyCpuidFeature = argc == 2 && strcmp(argv[1], "-cpuid") == 0;
|
|
if (!onlyCpuidFeature) {
|
|
#ifdef XBYAK32
|
|
puts("32bit");
|
|
#else
|
|
puts("64bit");
|
|
#endif
|
|
}
|
|
putCPUinfo(onlyCpuidFeature);
|
|
}
|