//{ /*********************************************************************/ /* Copyright 2009, 2010 The University of Texas at Austin. */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or */ /* without modification, are permitted provided that the following */ /* conditions are met: */ /* */ /* 1. Redistributions of source code must retain the above */ /* copyright notice, this list of conditions and the following */ /* disclaimer. */ /* */ /* 2. Redistributions in binary form must reproduce the above */ /* copyright notice, this list of conditions and the following */ /* disclaimer in the documentation and/or other materials */ /* provided with the distribution. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF TEXAS AT */ /* AUSTIN ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, */ /* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ /* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ /* DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT */ /* AUSTIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */ /* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR */ /* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT */ /* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ /* POSSIBILITY OF SUCH DAMAGE. */ /* */ /* The views and conclusions contained in the software and */ /* documentation are those of the authors and should not be */ /* interpreted as representing official policies, either expressed */ /* or implied, of The University of Texas at Austin. */ /*********************************************************************/ #include #include #include "cpuid.h" #if defined(_MSC_VER) && !defined(__clang__) #define C_INLINE __inline #else #define C_INLINE inline #endif /* #ifdef NO_AVX #define CPUTYPE_HASWELL CPUTYPE_NEHALEM #define CORE_HASWELL CORE_NEHALEM #define CPUTYPE_SKYLAKEX CPUTYPE_NEHALEM #define CORE_SKYLAKEX CORE_NEHALEM #define CPUTYPE_SANDYBRIDGE CPUTYPE_NEHALEM #define CORE_SANDYBRIDGE CORE_NEHALEM #define CPUTYPE_BULLDOZER CPUTYPE_BARCELONA #define CORE_BULLDOZER CORE_BARCELONA #define CPUTYPE_PILEDRIVER CPUTYPE_BARCELONA #define CORE_PILEDRIVER CORE_BARCELONA #endif */ #if defined(_MSC_VER) && !defined(__clang__) void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx) { int cpuInfo[4] = {-1}; __cpuid(cpuInfo, op); *eax = cpuInfo[0]; *ebx = cpuInfo[1]; *ecx = cpuInfo[2]; *edx = cpuInfo[3]; } void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx, int *edx) { int cpuInfo[4] = {-1}; __cpuidex(cpuInfo, op, count); *eax = cpuInfo[0]; *ebx = cpuInfo[1]; *ecx = cpuInfo[2]; *edx = cpuInfo[3]; } #else #ifndef CPUIDEMU #if defined(__APPLE__) && defined(__i386__) void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx); void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx, int *edx); #else static C_INLINE void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx) { #if defined(__i386__) && defined(__PIC__) __asm__ __volatile__("mov %%ebx, %%edi;" "cpuid;" "xchgl %%ebx, %%edi;" : "=a"(*eax), "=D"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(op), "c"(0) : "cc"); #else __asm__ __volatile__("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(op), "c"(0) : "cc"); #endif } static C_INLINE void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx, int *edx) { #if defined(__i386__) && defined(__PIC__) __asm__ __volatile__("mov %%ebx, %%edi;" "cpuid;" "xchgl %%ebx, %%edi;" : "=a"(*eax), "=D"(*ebx), "=c"(*ecx), "=d"(*edx) : "0"(op), "2"(count) : "cc"); #else __asm__ __volatile__("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "0"(op), "2"(count) : "cc"); #endif } #endif #else typedef struct { unsigned int id, a, b, c, d; } idlist_t; typedef struct { char *vendor; char *name; int start, stop; } vendor_t; extern idlist_t idlist[]; extern vendor_t vendor[]; static int cv = VENDOR; void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { static int current = 0; int start = vendor[cv].start; int stop = vendor[cv].stop; int count = stop - start; if ((current < start) || (current > stop)) current = start; while ((count > 0) && (idlist[current].id != op)) { current++; if (current > stop) current = start; count--; } *eax = idlist[current].a; *ebx = idlist[current].b; *ecx = idlist[current].c; *edx = idlist[current].d; } void cpuid_count(unsigned int op, unsigned int count, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { return cpuid(op, eax, ebx, ecx, edx); } #endif #endif // _MSC_VER static C_INLINE int have_cpuid(void) { int eax, ebx, ecx, edx; cpuid(0, &eax, &ebx, &ecx, &edx); return eax; } static C_INLINE int have_excpuid(void) { int eax, ebx, ecx, edx; cpuid(0x80000000, &eax, &ebx, &ecx, &edx); return eax & 0xffff; } #ifndef NO_AVX static C_INLINE void xgetbv(int op, int *eax, int *edx) { //Use binary code for xgetbv #if defined(_MSC_VER) && !defined(__clang__) *eax = __xgetbv(op); #else __asm__ __volatile__(".byte 0x0f, 0x01, 0xd0" : "=a"(*eax), "=d"(*edx) : "c"(op) : "cc"); #endif } #endif int support_avx(void) { #ifndef NO_AVX int eax, ebx, ecx, edx; int ret = 0; cpuid(1, &eax, &ebx, &ecx, &edx); if ((ecx & (1 << 28)) != 0 && (ecx & (1 << 27)) != 0 && (ecx & (1 << 26)) != 0) { xgetbv(0, &eax, &edx); if ((eax & 6) == 6) { ret = 1; //OS supports saving xmm and ymm registers (6 = (1<<1) | (1<<2)) } } return ret; #else return 0; #endif } int support_avx2(void) { #ifndef NO_AVX2 int eax, ebx, ecx = 0, edx; int ret = 0; if (!support_avx()) return 0; cpuid(7, &eax, &ebx, &ecx, &edx); if ((ebx & (1 << 5)) != 0) ret = 1; //CPU supports AVX2 return ret; #else return 0; #endif } int support_avx512(void) { #if !defined(NO_AVX) && !defined(NO_AVX512) int eax, ebx, ecx, edx; int ret = 0; if (!support_avx()) return 0; cpuid(7, &eax, &ebx, &ecx, &edx); if ((ebx & (1 << 5)) == 0) { ret = 0; //cpu does not have avx2 flag } if ((ebx & (1 << 31)) != 0) { //AVX512VL flag xgetbv(0, &eax, &edx); if ((eax & 0xe0) == 0xe0) ret = 1; //OS supports saving zmm registers } return ret; #else return 0; #endif } int support_avx512_bf16(void) { #if !defined(NO_AVX) && !defined(NO_AVX512) int eax, ebx, ecx, edx; int ret = 0; if (!support_avx512()) return 0; cpuid_count(7, 1, &eax, &ebx, &ecx, &edx); if ((eax & 32) == 32) { ret = 1; // CPUID.7.1:EAX[bit 5] indicates whether avx512_bf16 supported or not } return ret; #else return 0; #endif } #define BIT_AMX_TILE 0x01000000 #define BIT_AMX_BF16 0x00400000 #define BIT_AMX_ENBD 0x00060000 int support_amx_bf16(void) { #if !defined(NO_AVX) && !defined(NO_AVX512) int eax, ebx, ecx, edx; int ret = 0; if (!support_avx512()) return 0; // CPUID.7.0:EDX indicates AMX support cpuid_count(7, 0, &eax, &ebx, &ecx, &edx); if ((edx & BIT_AMX_TILE) && (edx & BIT_AMX_BF16)) { // CPUID.D.0:EAX[17:18] indicates AMX enabled cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); if ((eax & BIT_AMX_ENBD) == BIT_AMX_ENBD) ret = 1; } return ret; #else return 0; #endif } int get_vendor(void) { int eax, ebx, ecx, edx; char vendor[13]; cpuid(0, &eax, &ebx, &ecx, &edx); *(int *)(&vendor[0]) = ebx; *(int *)(&vendor[4]) = edx; *(int *)(&vendor[8]) = ecx; vendor[12] = (char)0; if (!strcmp(vendor, "GenuineIntel")) return VENDOR_INTEL; if (!strcmp(vendor, " UMC UMC UMC")) return VENDOR_UMC; if (!strcmp(vendor, "AuthenticAMD")) return VENDOR_AMD; if (!strcmp(vendor, "CyrixInstead")) return VENDOR_CYRIX; if (!strcmp(vendor, "NexGenDriven")) return VENDOR_NEXGEN; if (!strcmp(vendor, "CentaurHauls")) return VENDOR_CENTAUR; if (!strcmp(vendor, " Shanghai ")) return VENDOR_ZHAOXIN; if (!strcmp(vendor, "RiseRiseRise")) return VENDOR_RISE; if (!strcmp(vendor, " SiS SiS SiS")) return VENDOR_SIS; if (!strcmp(vendor, "GenuineTMx86")) return VENDOR_TRANSMETA; if (!strcmp(vendor, "Geode by NSC")) return VENDOR_NSC; if (!strcmp(vendor, "HygonGenuine")) return VENDOR_HYGON; if ((eax == 0) || ((eax & 0x500) != 0)) return VENDOR_INTEL; return VENDOR_UNKNOWN; } int get_cputype(int gettype) { int eax, ebx, ecx, edx; /* int extend_family, family; int extend_model, model; int type, stepping; */ int feature = 0; cpuid(1, &eax, &ebx, &ecx, &edx); switch (gettype) { case GET_EXFAMILY: return BITMASK(eax, 20, 0xff); case GET_EXMODEL: return BITMASK(eax, 16, 0x0f); case GET_TYPE: return BITMASK(eax, 12, 0x03); case GET_FAMILY: return BITMASK(eax, 8, 0x0f); case GET_MODEL: return BITMASK(eax, 4, 0x0f); case GET_APICID: return BITMASK(ebx, 24, 0x0f); case GET_LCOUNT: return BITMASK(ebx, 16, 0x0f); case GET_CHUNKS: return BITMASK(ebx, 8, 0x0f); case GET_STEPPING: return BITMASK(eax, 0, 0x0f); case GET_BLANDID: return BITMASK(ebx, 0, 0xff); case GET_NUMSHARE: if (have_cpuid() < 4) return 0; cpuid(4, &eax, &ebx, &ecx, &edx); return BITMASK(eax, 14, 0xfff); case GET_NUMCORES: if (have_cpuid() < 4) return 0; cpuid(4, &eax, &ebx, &ecx, &edx); return BITMASK(eax, 26, 0x3f); case GET_FEATURE: if ((edx & (1 << 3)) != 0) feature |= HAVE_PSE; if ((edx & (1 << 15)) != 0) feature |= HAVE_CMOV; if ((edx & (1 << 19)) != 0) feature |= HAVE_CFLUSH; if ((edx & (1 << 23)) != 0) feature |= HAVE_MMX; if ((edx & (1 << 25)) != 0) feature |= HAVE_SSE; if ((edx & (1 << 26)) != 0) feature |= HAVE_SSE2; if ((edx & (1 << 27)) != 0) { if (BITMASK(ebx, 16, 0x0f) > 0) feature |= HAVE_HIT; } if ((ecx & (1 << 0)) != 0) feature |= HAVE_SSE3; if ((ecx & (1 << 9)) != 0) feature |= HAVE_SSSE3; if ((ecx & (1 << 19)) != 0) feature |= HAVE_SSE4_1; if ((ecx & (1 << 20)) != 0) feature |= HAVE_SSE4_2; #ifndef NO_AVX if (support_avx()) feature |= HAVE_AVX; if (support_avx2()) feature |= HAVE_AVX2; if (support_avx512()) feature |= HAVE_AVX512VL; if (support_avx512_bf16()) feature |= HAVE_AVX512BF16; if (support_amx_bf16()) feature |= HAVE_AMXBF16; if ((ecx & (1 << 12)) != 0) feature |= HAVE_FMA3; #endif if (have_excpuid() >= 0x01) { cpuid(0x80000001, &eax, &ebx, &ecx, &edx); if ((ecx & (1 << 6)) != 0) feature |= HAVE_SSE4A; if ((ecx & (1 << 7)) != 0) feature |= HAVE_MISALIGNSSE; #ifndef NO_AVX if ((ecx & (1 << 16)) != 0) feature |= HAVE_FMA4; #endif if ((edx & (1 << 30)) != 0) feature |= HAVE_3DNOWEX; if ((edx & (1 << 31)) != 0) feature |= HAVE_3DNOW; } if (have_excpuid() >= 0x1a) { cpuid(0x8000001a, &eax, &ebx, &ecx, &edx); if ((eax & (1 << 0)) != 0) feature |= HAVE_128BITFPU; if ((eax & (1 << 1)) != 0) feature |= HAVE_FASTMOVU; } } return feature; } int get_cacheinfo(int type, cache_info_t *cacheinfo) { int eax, ebx, ecx, edx, cpuid_level; int info[15]; int i; cache_info_t LC1, LD1, L2, L3, ITB, DTB, LITB, LDTB, L2ITB, L2DTB, L2LITB, L2LDTB; LC1.size = 0; LC1.associative = 0; LC1.linesize = 0; LC1.shared = 0; LD1.size = 0; LD1.associative = 0; LD1.linesize = 0; LD1.shared = 0; L2.size = 0; L2.associative = 0; L2.linesize = 0; L2.shared = 0; L3.size = 0; L3.associative = 0; L3.linesize = 0; L3.shared = 0; ITB.size = 0; ITB.associative = 0; ITB.linesize = 0; ITB.shared = 0; DTB.size = 0; DTB.associative = 0; DTB.linesize = 0; DTB.shared = 0; LITB.size = 0; LITB.associative = 0; LITB.linesize = 0; LITB.shared = 0; LDTB.size = 0; LDTB.associative = 0; LDTB.linesize = 0; LDTB.shared = 0; L2ITB.size = 0; L2ITB.associative = 0; L2ITB.linesize = 0; L2ITB.shared = 0; L2DTB.size = 0; L2DTB.associative = 0; L2DTB.linesize = 0; L2DTB.shared = 0; L2LITB.size = 0; L2LITB.associative = 0; L2LITB.linesize = 0; L2LITB.shared = 0; L2LDTB.size = 0; L2LDTB.associative = 0; L2LDTB.linesize = 0; L2LDTB.shared = 0; cpuid(0, &cpuid_level, &ebx, &ecx, &edx); if (cpuid_level > 1) { int numcalls; cpuid(2, &eax, &ebx, &ecx, &edx); numcalls = BITMASK(eax, 0, 0xff); //FIXME some systems may require repeated calls to read all entries info[0] = BITMASK(eax, 8, 0xff); info[1] = BITMASK(eax, 16, 0xff); info[2] = BITMASK(eax, 24, 0xff); info[3] = BITMASK(ebx, 0, 0xff); info[4] = BITMASK(ebx, 8, 0xff); info[5] = BITMASK(ebx, 16, 0xff); info[6] = BITMASK(ebx, 24, 0xff); info[7] = BITMASK(ecx, 0, 0xff); info[8] = BITMASK(ecx, 8, 0xff); info[9] = BITMASK(ecx, 16, 0xff); info[10] = BITMASK(ecx, 24, 0xff); info[11] = BITMASK(edx, 0, 0xff); info[12] = BITMASK(edx, 8, 0xff); info[13] = BITMASK(edx, 16, 0xff); info[14] = BITMASK(edx, 24, 0xff); for (i = 0; i < 15; i++) { switch (info[i]) { /* This table is from http://www.sandpile.org/x86/cpuid.htm */ case 0x01: ITB.size = 4; ITB.associative = 4; ITB.linesize = 32; break; case 0x02: LITB.size = 4096; LITB.associative = 0; LITB.linesize = 2; break; case 0x03: DTB.size = 4; DTB.associative = 4; DTB.linesize = 64; break; case 0x04: LDTB.size = 4096; LDTB.associative = 4; LDTB.linesize = 8; break; case 0x05: LDTB.size = 4096; LDTB.associative = 4; LDTB.linesize = 32; break; case 0x06: LC1.size = 8; LC1.associative = 4; LC1.linesize = 32; break; case 0x08: LC1.size = 16; LC1.associative = 4; LC1.linesize = 32; break; case 0x09: LC1.size = 32; LC1.associative = 4; LC1.linesize = 64; break; case 0x0a: LD1.size = 8; LD1.associative = 2; LD1.linesize = 32; break; case 0x0b: LITB.size = 4096; LITB.associative= 4; LITB.linesize = 4; break; case 0x0c: LD1.size = 16; LD1.associative = 4; LD1.linesize = 32; break; case 0x0d: LD1.size = 16; LD1.associative = 4; LD1.linesize = 64; break; case 0x0e: LD1.size = 24; LD1.associative = 6; LD1.linesize = 64; break; case 0x10: LD1.size = 16; LD1.associative = 4; LD1.linesize = 32; break; case 0x15: LC1.size = 16; LC1.associative = 4; LC1.linesize = 32; break; case 0x1a: L2.size = 96; L2.associative = 6; L2.linesize = 64; break; case 0x1d: L2.size = 128; L2.associative = 2; L2.linesize = 64; break; case 0x21: L2.size = 256; L2.associative = 8; L2.linesize = 64; break; case 0x22: L3.size = 512; L3.associative = 4; L3.linesize = 64; break; case 0x23: L3.size = 1024; L3.associative = 8; L3.linesize = 64; break; case 0x24: L2.size = 1024; L2.associative = 16; L2.linesize = 64; case 0x25: L3.size = 2048; L3.associative = 8; L3.linesize = 64; break; case 0x29: L3.size = 4096; L3.associative = 8; L3.linesize = 64; break; case 0x2c: LD1.size = 32; LD1.associative = 8; LD1.linesize = 64; break; case 0x30: LC1.size = 32; LC1.associative = 8; LC1.linesize = 64; break; case 0x39: L2.size = 128; L2.associative = 4; L2.linesize = 64; break; case 0x3a: L2.size = 192; L2.associative = 6; L2.linesize = 64; break; case 0x3b: L2.size = 128; L2.associative = 2; L2.linesize = 64; break; case 0x3c: L2.size = 256; L2.associative = 4; L2.linesize = 64; break; case 0x3d: L2.size = 384; L2.associative = 6; L2.linesize = 64; break; case 0x3e: L2.size = 512; L2.associative = 4; L2.linesize = 64; break; case 0x40: // no integrated L2 or L3 cache, old P4/P6 break; case 0x41: L2.size = 128; L2.associative = 4; L2.linesize = 32; break; case 0x42: L2.size = 256; L2.associative = 4; L2.linesize = 32; break; case 0x43: L2.size = 512; L2.associative = 4; L2.linesize = 32; break; case 0x44: L2.size = 1024; L2.associative = 4; L2.linesize = 32; break; case 0x45: L2.size = 2048; L2.associative = 4; L2.linesize = 32; break; case 0x46: L3.size = 4096; L3.associative = 4; L3.linesize = 64; break; case 0x47: L3.size = 8192; L3.associative = 8; L3.linesize = 64; break; case 0x48: L2.size = 3184; L2.associative = 12; L2.linesize = 64; break; case 0x49: if ((get_cputype(GET_FAMILY) == 0x0f) && (get_cputype(GET_MODEL) == 0x06)) { L3.size = 4096; L3.associative = 16; L3.linesize = 64; } else { L2.size = 4096; L2.associative = 16; L2.linesize = 64; } break; case 0x4a: L3.size = 6144; L3.associative = 12; L3.linesize = 64; break; case 0x4b: L3.size = 8192; L3.associative = 16; L3.linesize = 64; break; case 0x4c: L3.size = 12280; L3.associative = 12; L3.linesize = 64; break; case 0x4d: L3.size = 16384; L3.associative = 16; L3.linesize = 64; break; case 0x4e: L2.size = 6144; L2.associative = 24; L2.linesize = 64; break; case 0x4f: ITB.size = 4; ITB.associative = 0; ITB.linesize = 32; break; case 0x50: ITB.size = 4; ITB.associative = 0; ITB.linesize = 64; LITB.size = 4096; LITB.associative = 0; LITB.linesize = 64; LITB.shared = 1; break; case 0x51: ITB.size = 4; ITB.associative = 0; ITB.linesize = 128; LITB.size = 4096; LITB.associative = 0; LITB.linesize = 128; LITB.shared = 1; break; case 0x52: ITB.size = 4; ITB.associative = 0; ITB.linesize = 256; LITB.size = 4096; LITB.associative = 0; LITB.linesize = 256; LITB.shared = 1; break; case 0x55: LITB.size = 4096; LITB.associative = 0; LITB.linesize = 7; LITB.shared = 1; break; case 0x56: LDTB.size = 4096; LDTB.associative = 4; LDTB.linesize = 16; break; case 0x57: DTB.size = 4; DTB.associative = 4; DTB.linesize = 16; break; case 0x59: DTB.size = 4; DTB.associative = 0; DTB.linesize = 16; break; case 0x5a: LDTB.size = 4096; LDTB.associative = 4; LDTB.linesize = 32; break; case 0x5b: DTB.size = 4; DTB.associative = 0; DTB.linesize = 64; LDTB.size = 4096; LDTB.associative = 0; LDTB.linesize = 64; LDTB.shared = 1; break; case 0x5c: DTB.size = 4; DTB.associative = 0; DTB.linesize = 128; LDTB.size = 4096; LDTB.associative = 0; LDTB.linesize = 128; LDTB.shared = 1; break; case 0x5d: DTB.size = 4; DTB.associative = 0; DTB.linesize = 256; LDTB.size = 4096; LDTB.associative = 0; LDTB.linesize = 256; LDTB.shared = 1; break; case 0x60: LD1.size = 16; LD1.associative = 8; LD1.linesize = 64; break; case 0x61: ITB.size = 4096; ITB.associative = 0; ITB.linesize = 48; case 0x63: DTB.size = 2048; DTB.associative = 4; DTB.linesize = 32; LDTB.size = 4096; LDTB.associative = 4; LDTB.linesize = 32; break; case 0x64: DTB.size = 4; DTB.associative = 4; DTB.linesize = 512; case 0x66: LD1.size = 8; LD1.associative = 4; LD1.linesize = 64; break; case 0x67: LD1.size = 16; LD1.associative = 4; LD1.linesize = 64; break; case 0x68: LD1.size = 32; LD1.associative = 4; LD1.linesize = 64; break; case 0x6a: DTB.size = 4; DTB.associative = 8; DTB.linesize = 64; break; case 0x6b: DTB.size = 4; DTB.associative = 8; DTB.linesize = 256; break; case 0x6c: LDTB.size = 4096; LDTB.associative= 8; LDTB.linesize = 126; break; case 0x6d: LDTB.size = 1048576; LDTB.associative= 0; LDTB.linesize = 16; break; case 0x70: LC1.size = 12; LC1.associative = 8; break; case 0x71: LC1.size = 16; LC1.associative = 8; break; case 0x72: LC1.size = 32; LC1.associative = 8; break; case 0x73: LC1.size = 64; LC1.associative = 8; break; case 0x76: ITB.size = 2048; ITB.associative = 0; ITB.linesize = 8; LITB.size = 4096; LITB.associative = 0; LITB.linesize = 8; break; case 0x77: LC1.size = 16; LC1.associative = 4; LC1.linesize = 64; break; case 0x78: L2.size = 1024; L2.associative = 4; L2.linesize = 64; break; case 0x79: L2.size = 128; L2.associative = 8; L2.linesize = 64; break; case 0x7a: L2.size = 256; L2.associative = 8; L2.linesize = 64; break; case 0x7b: L2.size = 512; L2.associative = 8; L2.linesize = 64; break; case 0x7c: L2.size = 1024; L2.associative = 8; L2.linesize = 64; break; case 0x7d: L2.size = 2048; L2.associative = 8; L2.linesize = 64; break; case 0x7e: L2.size = 256; L2.associative = 8; L2.linesize = 128; break; case 0x7f: L2.size = 512; L2.associative = 2; L2.linesize = 64; break; case 0x80: L2.size = 512; L2.associative = 8; L2.linesize = 64; break; case 0x81: L2.size = 128; L2.associative = 8; L2.linesize = 32; break; case 0x82: L2.size = 256; L2.associative = 8; L2.linesize = 32; break; case 0x83: L2.size = 512; L2.associative = 8; L2.linesize = 32; break; case 0x84: L2.size = 1024; L2.associative = 8; L2.linesize = 32; break; case 0x85: L2.size = 2048; L2.associative = 8; L2.linesize = 32; break; case 0x86: L2.size = 512; L2.associative = 4; L2.linesize = 64; break; case 0x87: L2.size = 1024; L2.associative = 8; L2.linesize = 64; break; case 0x88: L3.size = 2048; L3.associative = 4; L3.linesize = 64; break; case 0x89: L3.size = 4096; L3.associative = 4; L3.linesize = 64; break; case 0x8a: L3.size = 8192; L3.associative = 4; L3.linesize = 64; break; case 0x8d: L3.size = 3096; L3.associative = 12; L3.linesize = 128; break; case 0x90: ITB.size = 4; ITB.associative = 0; ITB.linesize = 64; break; case 0x96: DTB.size = 4; DTB.associative = 0; DTB.linesize = 32; break; case 0x9b: L2DTB.size = 4; L2DTB.associative = 0; L2DTB.linesize = 96; break; case 0xa0: DTB.size = 4; DTB.associative = 0; DTB.linesize = 32; break; case 0xb0: ITB.size = 4; ITB.associative = 4; ITB.linesize = 128; break; case 0xb1: LITB.size = 4096; LITB.associative = 4; LITB.linesize = 4; break; case 0xb2: ITB.size = 4; ITB.associative = 4; ITB.linesize = 64; break; case 0xb3: DTB.size = 4; DTB.associative = 4; DTB.linesize = 128; break; case 0xb4: DTB.size = 4; DTB.associative = 4; DTB.linesize = 256; break; case 0xb5: ITB.size = 4; ITB.associative = 8; ITB.linesize = 64; break; case 0xb6: ITB.size = 4; ITB.associative = 8; ITB.linesize = 128; break; case 0xba: DTB.size = 4; DTB.associative = 4; DTB.linesize = 64; break; case 0xc0: DTB.size = 4; DTB.associative = 4; DTB.linesize = 8; LDTB.size = 4096; LDTB.associative= 4; LDTB.linesize = 8; break; case 0xc1: L2.size = 4; L2.associative = 8; L2.linesize = 1024; break; case 0xc2: DTB.size = 2048; DTB.associative= 4; DTB.linesize = 16; break; case 0xc3: L2.size = 4; L2.associative = 6; L2.linesize = 1536; break; case 0xc4: DTB.size = 2048; DTB.associative= 4; DTB.linesize = 32; break; case 0xca: L2.size = 4; L2.associative = 4; L2.linesize = 512; break; case 0xd0: L3.size = 512; L3.associative = 4; L3.linesize = 64; break; case 0xd1: L3.size = 1024; L3.associative = 4; L3.linesize = 64; break; case 0xd2: L3.size = 2048; L3.associative = 4; L3.linesize = 64; break; case 0xd6: L3.size = 1024; L3.associative = 8; L3.linesize = 64; break; case 0xd7: L3.size = 2048; L3.associative = 8; L3.linesize = 64; break; case 0xd8: L3.size = 4096; L3.associative = 8; L3.linesize = 64; break; case 0xdc: L3.size = 1536; L3.associative = 12; L3.linesize = 64; break; case 0xdd: L3.size = 3072; L3.associative = 12; L3.linesize = 64; break; case 0xde: L3.size = 6144; L3.associative = 12; L3.linesize = 64; break; case 0xe2: L3.size = 2048; L3.associative = 16; L3.linesize = 64; break; case 0xe3: L3.size = 4096; L3.associative = 16; L3.linesize = 64; break; case 0xe4: L3.size = 8192; L3.associative = 16; L3.linesize = 64; break; case 0xea: L3.size = 12288; L3.associative = 24; L3.linesize = 64; break; case 0xeb: L3.size = 18432; L3.associative = 24; L3.linesize = 64; break; case 0xec: L3.size = 24576; L3.associative = 24; L3.linesize = 64; break; } } } if (get_vendor() == VENDOR_INTEL) { if (LD1.size <= 0 || LC1.size <= 0) { //If we didn't detect L1 correctly before, int count; for (count = 0; count < 4; count++) { cpuid_count(4, count, &eax, &ebx, &ecx, &edx); switch (eax & 0x1f) { case 0: continue; case 1: case 3: { switch ((eax >> 5) & 0x07) { case 1: { // fprintf(stderr,"L1 data cache...\n"); int sets = ecx + 1; int lines = (ebx & 0x0fff) + 1; ebx >>= 12; int part = (ebx & 0x03ff) + 1; ebx >>= 10; int assoc = (ebx & 0x03ff) + 1; LD1.size = (assoc * part * lines * sets) / 1024; LD1.associative = assoc; LD1.linesize = lines; break; } default: break; } break; } case 2: { switch ((eax >> 5) & 0x07) { case 1: { // fprintf(stderr,"L1 instruction cache...\n"); int sets = ecx + 1; int lines = (ebx & 0x0fff) + 1; ebx >>= 12; int part = (ebx & 0x03ff) + 1; ebx >>= 10; int assoc = (ebx & 0x03ff) + 1; LC1.size = (assoc * part * lines * sets) / 1024; LC1.associative = assoc; LC1.linesize = lines; break; } default: break; } break; } default: break; } } } cpuid(0x80000000, &cpuid_level, &ebx, &ecx, &edx); if (cpuid_level >= 0x80000006) { if (L2.size <= 0) { //If we didn't detect L2 correctly before, cpuid(0x80000006, &eax, &ebx, &ecx, &edx); L2.size = BITMASK(ecx, 16, 0xffff); L2.associative = BITMASK(ecx, 12, 0x0f); switch (L2.associative) { case 0x06: L2.associative = 8; break; case 0x08: L2.associative = 16; break; } L2.linesize = BITMASK(ecx, 0, 0xff); } } } if ((get_vendor() == VENDOR_AMD) || (get_vendor() == VENDOR_HYGON) || (get_vendor() == VENDOR_CENTAUR) || (get_vendor() == VENDOR_ZHAOXIN)) { cpuid(0x80000005, &eax, &ebx, &ecx, &edx); LDTB.size = 4096; LDTB.associative = BITMASK(eax, 24, 0xff); if (LDTB.associative == 0xff) LDTB.associative = 0; LDTB.linesize = BITMASK(eax, 16, 0xff); LITB.size = 4096; LITB.associative = BITMASK(eax, 8, 0xff); if (LITB.associative == 0xff) LITB.associative = 0; LITB.linesize = BITMASK(eax, 0, 0xff); DTB.size = 4; DTB.associative = BITMASK(ebx, 24, 0xff); if (DTB.associative == 0xff) DTB.associative = 0; DTB.linesize = BITMASK(ebx, 16, 0xff); ITB.size = 4; ITB.associative = BITMASK(ebx, 8, 0xff); if (ITB.associative == 0xff) ITB.associative = 0; ITB.linesize = BITMASK(ebx, 0, 0xff); LD1.size = BITMASK(ecx, 24, 0xff); LD1.associative = BITMASK(ecx, 16, 0xff); if (LD1.associative == 0xff) LD1.associative = 0; LD1.linesize = BITMASK(ecx, 0, 0xff); LC1.size = BITMASK(ecx, 24, 0xff); LC1.associative = BITMASK(ecx, 16, 0xff); if (LC1.associative == 0xff) LC1.associative = 0; LC1.linesize = BITMASK(ecx, 0, 0xff); cpuid(0x80000006, &eax, &ebx, &ecx, &edx); L2LDTB.size = 4096; L2LDTB.associative = BITMASK(eax, 24, 0xff); if (L2LDTB.associative == 0xff) L2LDTB.associative = 0; L2LDTB.linesize = BITMASK(eax, 16, 0xff); L2LITB.size = 4096; L2LITB.associative = BITMASK(eax, 8, 0xff); if (L2LITB.associative == 0xff) L2LITB.associative = 0; L2LITB.linesize = BITMASK(eax, 0, 0xff); L2DTB.size = 4; L2DTB.associative = BITMASK(ebx, 24, 0xff); if (L2DTB.associative == 0xff) L2DTB.associative = 0; L2DTB.linesize = BITMASK(ebx, 16, 0xff); L2ITB.size = 4; L2ITB.associative = BITMASK(ebx, 8, 0xff); if (L2ITB.associative == 0xff) L2ITB.associative = 0; L2ITB.linesize = BITMASK(ebx, 0, 0xff); if (L2.size <= 0) { //If we didn't detect L2 correctly before, L2.size = BITMASK(ecx, 16, 0xffff); L2.associative = BITMASK(ecx, 12, 0xf); switch (L2.associative) { case 0x06: L2.associative = 8; break; case 0x08: L2.associative = 16; break; } if (L2.associative == 0xff) L2.associative = 0; L2.linesize = BITMASK(ecx, 0, 0xff); } L3.size = BITMASK(edx, 18, 0x3fff) * 512; L3.associative = BITMASK(edx, 12, 0xf); if (L3.associative == 0xff) L2.associative = 0; L3.linesize = BITMASK(edx, 0, 0xff); } switch (type) { case CACHE_INFO_L1_I: *cacheinfo = LC1; break; case CACHE_INFO_L1_D: *cacheinfo = LD1; break; case CACHE_INFO_L2: *cacheinfo = L2; break; case CACHE_INFO_L3: *cacheinfo = L3; break; case CACHE_INFO_L1_DTB: *cacheinfo = DTB; break; case CACHE_INFO_L1_ITB: *cacheinfo = ITB; break; case CACHE_INFO_L1_LDTB: *cacheinfo = LDTB; break; case CACHE_INFO_L1_LITB: *cacheinfo = LITB; break; case CACHE_INFO_L2_DTB: *cacheinfo = L2DTB; break; case CACHE_INFO_L2_ITB: *cacheinfo = L2ITB; break; case CACHE_INFO_L2_LDTB: *cacheinfo = L2LDTB; break; case CACHE_INFO_L2_LITB: *cacheinfo = L2LITB; break; } return 0; } int get_cpuname(void) { int family, exfamily, model, vendor, exmodel, stepping; if (!have_cpuid()) return CPUTYPE_80386; family = get_cputype(GET_FAMILY); exfamily = get_cputype(GET_EXFAMILY); model = get_cputype(GET_MODEL); exmodel = get_cputype(GET_EXMODEL); stepping = get_cputype(GET_STEPPING); vendor = get_vendor(); if (vendor == VENDOR_INTEL) { switch (family) { case 0x4: return CPUTYPE_80486; case 0x5: return CPUTYPE_PENTIUM; case 0x6: switch (exmodel) { case 0: switch (model) { case 1: case 3: case 5: case 6: #if defined(__x86_64__) || defined(__amd64__) return CPUTYPE_CORE2; #else return CPUTYPE_PENTIUM2; #endif case 7: case 8: case 10: case 11: return CPUTYPE_PENTIUM3; case 9: case 13: case 14: return CPUTYPE_PENTIUMM; case 15: return CPUTYPE_CORE2; } break; case 1: // family 6 exmodel 1 switch (model) { case 6: return CPUTYPE_CORE2; case 7: return CPUTYPE_PENRYN; case 10: case 11: case 14: case 15: return CPUTYPE_NEHALEM; case 12: return CPUTYPE_ATOM; case 13: return CPUTYPE_DUNNINGTON; } break; case 2: // family 6 exmodel 2 switch (model) { case 5: //Intel Core (Clarkdale) / Core (Arrandale) // Pentium (Clarkdale) / Pentium Mobile (Arrandale) // Xeon (Clarkdale), 32nm return CPUTYPE_NEHALEM; case 10: //Intel Core i5-2000 /i7-2000 (Sandy Bridge) if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; //OS doesn't support AVX case 12: //Xeon Processor 5600 (Westmere-EP) return CPUTYPE_NEHALEM; case 13: //Intel Core i7-3000 / Xeon E5 (Sandy Bridge) if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 14: // Xeon E7540 case 15: //Xeon Processor E7 (Westmere-EX) return CPUTYPE_NEHALEM; } break; case 3: // family 6 exmodel 3 switch (model) { case 7: // Bay Trail return CPUTYPE_ATOM; case 10: case 14: // Ivy Bridge if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 12: case 15: if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 13: //Broadwell if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; } break; case 4: // family 6 exmodel 4 switch (model) { case 5: case 6: if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 7: case 15: //Broadwell if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 14: //Skylake if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 12: // Braswell case 13: // Avoton return CPUTYPE_NEHALEM; } break; case 5: // family 6 exmodel 5 switch (model) { case 6: //Broadwell if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 5: // Skylake X if (support_avx512_bf16()) return CPUTYPE_COOPERLAKE; if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 14: // Skylake if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 7: // Xeon Phi Knights Landing if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 12: // Apollo Lake case 15: // Denverton return CPUTYPE_NEHALEM; } break; case 6: // family 6 exmodel 6 switch (model) { case 6: // Cannon Lake if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 10: // Ice Lake SP if (support_avx512_bf16()) return CPUTYPE_COOPERLAKE; if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; } break; case 7: // family 6 exmodel 7 switch (model) { case 10: // Goldmont Plus return CPUTYPE_NEHALEM; case 14: // Ice Lake if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; } break; case 8: switch (model) { case 12: // Tiger Lake case 13: // Tiger Lake (11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz) if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 14: // Kaby Lake and refreshes if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 15: // Sapphire Rapids if (support_amx_bf16()) return CPUTYPE_SAPPHIRERAPIDS; if (support_avx512_bf16()) return CPUTYPE_COOPERLAKE; if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; } break; case 9: switch (model) { case 7: // Alder Lake desktop case 10: // Alder Lake mobile if (support_avx512_bf16()) return CPUTYPE_COOPERLAKE; if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 12: // Jasper Lake Celeron N5105 return CPUTYPE_NEHALEM; case 13: // Ice Lake NNPI if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 14: // Kaby Lake and refreshes if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; } break; case 10: //family 6 exmodel 10 switch (model) { case 13: // Granite Rapids if (support_amx_bf16()) return CPUTYPE_SAPPHIRERAPIDS; if (support_avx512_bf16()) return CPUTYPE_COOPERLAKE; if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 5: // Comet Lake H and S case 6: // Comet Lake U case 10: // Meteor Lake if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 0: // Meteor Lake case 7: // Rocket Lake if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; } break; case 11: //family 6 exmodel 11 switch (model) { case 7: // Raptor Lake case 10: case 15: case 14: // Alder Lake N case 13: // Lunar Lake if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; } break; case 12: //family 6 exmodel 12 switch (model) { case 6: // Arrow Lake if (support_avx512()) return CPUTYPE_SAPPHIRERAPIDS; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 12: // Panther Lake if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; break; case 15: // Emerald Rapids if (support_amx_bf16()) return CPUTYPE_SAPPHIRERAPIDS; if (support_avx512_bf16()) return CPUTYPE_COOPERLAKE; if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; } break; } break; case 0x7: return CPUTYPE_ITANIUM; case 0xf: switch (exfamily) { case 0: return CPUTYPE_PENTIUM4; case 1: return CPUTYPE_ITANIUM; } // new family 15 - 2026 and beyond if (support_amx_bf16()) return CPUTYPE_SAPPHIRERAPIDS; if (support_avx512_bf16()) return CPUTYPE_COOPERLAKE; if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; break; } // other new cpu family numbers if (support_amx_bf16()) return CPUTYPE_SAPPHIRERAPIDS; if (support_avx512_bf16()) return CPUTYPE_COOPERLAKE; if (support_avx512()) return CPUTYPE_SKYLAKEX; if (support_avx2()) return CPUTYPE_HASWELL; if (support_avx()) return CPUTYPE_SANDYBRIDGE; return CPUTYPE_INTEL_UNKNOWN; } if (vendor == VENDOR_AMD) { switch (family) { case 0x4: return CPUTYPE_AMD5X86; case 0x5: return CPUTYPE_AMDK6; case 0x6: #if defined(__x86_64__) || defined(__amd64__) return CPUTYPE_BARCELONA; #else return CPUTYPE_ATHLON; #endif case 0xf: switch (exfamily) { case 0: case 2: return CPUTYPE_OPTERON; case 1: case 3: // case 7: // case 10: return CPUTYPE_BARCELONA; case 5: case 7: return CPUTYPE_BOBCAT; case 6: switch (model) { case 1: //AMD Bulldozer Opteron 6200 / Opteron 4200 / AMD FX-Series if (support_avx()) return CPUTYPE_BULLDOZER; else return CPUTYPE_BARCELONA; //OS don't support AVX. case 2: //AMD Piledriver case 3: //AMD Richland if (support_avx()) return CPUTYPE_PILEDRIVER; else return CPUTYPE_BARCELONA; //OS don't support AVX. case 5: // New EXCAVATOR CPUS if (support_avx()) return CPUTYPE_EXCAVATOR; else return CPUTYPE_BARCELONA; //OS don't support AVX. case 0: case 8: switch (exmodel) { case 1: //AMD Trinity if (support_avx()) return CPUTYPE_PILEDRIVER; else return CPUTYPE_BARCELONA; //OS don't support AVX. case 3: if (support_avx()) return CPUTYPE_STEAMROLLER; else return CPUTYPE_BARCELONA; //OS don't support AVX. case 6: if (support_avx()) return CPUTYPE_EXCAVATOR; else return CPUTYPE_BARCELONA; //OS don't support AVX. } break; } break; case 8: switch (model) { case 1: // AMD Ryzen case 8: // AMD Ryzen2 default: // Matisse/Renoir and other recent Ryzen2 if (support_avx()) #ifndef NO_AVX2 return CPUTYPE_ZEN; #else return CPUTYPE_SANDYBRIDGE; // Zen is closer in architecture to Sandy Bridge than to Excavator #endif else return CPUTYPE_BARCELONA; } case 10: // Zen3/4 case 11: // Zen5 #ifndef NO_AVX512 if (support_avx512_bf16()) return CPUTYPE_COOPERLAKE; if (support_avx512()) return CPUTYPE_SKYLAKEX; #endif if (support_avx()) #ifndef NO_AVX2 return CPUTYPE_ZEN; #else return CPUTYPE_SANDYBRIDGE; // Zen is closer in architecture to Sandy Bridge than to Excavator #endif else return CPUTYPE_BARCELONA; } break; } return CPUTYPE_AMD_UNKNOWN; } if (vendor == VENDOR_HYGON) { switch (family) { case 0xf: switch (exfamily) { case 9: //Hygon Dhyana if (support_avx()) #ifndef NO_AVX2 return CPUTYPE_ZEN; #else return CPUTYPE_SANDYBRIDGE; // closer in architecture to Sandy Bridge than to Excavator #endif else return CPUTYPE_BARCELONA; } break; } return CPUTYPE_HYGON_UNKNOWN; } if (vendor == VENDOR_CYRIX) { switch (family) { case 0x4: return CPUTYPE_CYRIX5X86; case 0x5: return CPUTYPE_CYRIXM1; case 0x6: return CPUTYPE_CYRIXM2; } return CPUTYPE_CYRIX_UNKNOWN; } if (vendor == VENDOR_NEXGEN) { switch (family) { case 0x5: return CPUTYPE_NEXGENNX586; } return CPUTYPE_NEXGEN_UNKNOWN; } if (vendor == VENDOR_CENTAUR) { switch (family) { case 0x5: return CPUTYPE_CENTAURC6; case 0x6: if (model == 0xf && stepping < 0xe) return CPUTYPE_NANO; return CPUTYPE_NEHALEM; case 0x7: switch (exmodel) { case 5: if (support_avx2()) return CPUTYPE_ZEN; else return CPUTYPE_DUNNINGTON; default: return CPUTYPE_NEHALEM; } default: if (family >= 0x8) return CPUTYPE_NEHALEM; else return CPUTYPE_VIAC3; } } if (vendor == VENDOR_ZHAOXIN) { switch (family) { case 0x7: switch (exmodel) { case 5: if (support_avx2()) return CPUTYPE_ZEN; else return CPUTYPE_DUNNINGTON; default: if (support_avx2()) return CPUTYPE_ZEN; return CPUTYPE_NEHALEM; } default: if (support_avx2()) return CPUTYPE_ZEN; return CPUTYPE_NEHALEM; } } if (vendor == VENDOR_RISE) { switch (family) { case 0x5: return CPUTYPE_RISEMP6; } return CPUTYPE_RISE_UNKNOWN; } if (vendor == VENDOR_SIS) { switch (family) { case 0x5: return CPUTYPE_SYS55X; } return CPUTYPE_SIS_UNKNOWN; } if (vendor == VENDOR_TRANSMETA) { switch (family) { case 0x5: return CPUTYPE_CRUSOETM3X; } return CPUTYPE_TRANSMETA_UNKNOWN; } if (vendor == VENDOR_NSC) { switch (family) { case 0x5: return CPUTYPE_NSGEODE; } return CPUTYPE_NSC_UNKNOWN; } return CPUTYPE_UNKNOWN; } static char *cpuname[] = { "UNKNOWN", "INTEL_UNKNOWN", "UMC_UNKNOWN", "AMD_UNKNOWN", "CYRIX_UNKNOWN", "NEXGEN_UNKNOWN", "CENTAUR_UNKNOWN", "RISE_UNKNOWN", "SIS_UNKNOWN", "TRANSMETA_UNKNOWN", "NSC_UNKNOWN", "80386", "80486", "PENTIUM", "PENTIUM2", "PENTIUM3", "PENTIUMM", "PENTIUM4", "CORE2", "PENRYN", "DUNNINGTON", "NEHALEM", "ATOM", "ITANIUM", "ITANIUM2", "5X86", "K6", "ATHLON", "DURON", "OPTERON", "BARCELONA", "SHANGHAI", "ISTANBUL", "CYRIX5X86", "CYRIXM1", "CYRIXM2", "NEXGENNX586", "CENTAURC6", "RISEMP6", "SYS55X", "TM3X00", "NSGEODE", "VIAC3", "NANO", "SANDYBRIDGE", "BOBCAT", "BULLDOZER", "PILEDRIVER", "HASWELL", "STEAMROLLER", "EXCAVATOR", "ZEN", "SKYLAKEX", "DHYANA", "COOPERLAKE", "SAPPHIRERAPIDS", }; static char *lowercpuname[] = { "unknown", "intel_unknown", "umc_unknown", "amd_unknown", "cyrix_unknown", "nexgen_unknown", "centaur_unknown", "rise_unknown", "sis_unknown", "transmeta_unknown", "nsc_unknown", "80386", "80486", "pentium", "pentium2", "pentium3", "pentiumm", "pentium4", "core2", "penryn", "dunnington", "nehalem", "atom", "itanium", "itanium2", "5x86", "k6", "athlon", "duron", "opteron", "barcelona", "shanghai", "istanbul", "cyrix5x86", "cyrixm1", "cyrixm2", "nexgennx586", "centaurc6", "risemp6", "sys55x", "tms3x00", "nsgeode", "nano", "sandybridge", "bobcat", "bulldozer", "piledriver", "haswell", "steamroller", "excavator", "zen", "skylakex", "dhyana", "cooperlake", "sapphirerapids", }; static char *corename[] = { "UNKNOWN", "80486", "P5", "P6", "KATMAI", "COPPERMINE", "NORTHWOOD", "PRESCOTT", "BANIAS", "ATHLON", "OPTERON", "BARCELONA", "VIAC3", "YONAH", "CORE2", "PENRYN", "DUNNINGTON", "NEHALEM", "ATOM", "NANO", "SANDYBRIDGE", "BOBCAT", "BULLDOZER", "PILEDRIVER", "HASWELL", "STEAMROLLER", "EXCAVATOR", "ZEN", "SKYLAKEX", "DHYANA", "COOPERLAKE", "SAPPHIRERAPIDS", }; static char *corename_lower[] = { "unknown", "80486", "p5", "p6", "katmai", "coppermine", "northwood", "prescott", "banias", "athlon", "opteron", "barcelona", "viac3", "yonah", "core2", "penryn", "dunnington", "nehalem", "atom", "nano", "sandybridge", "bobcat", "bulldozer", "piledriver", "haswell", "steamroller", "excavator", "zen", "skylakex", "dhyana", "cooperlake", "sapphirerapids", }; char *get_cpunamechar(void) { return cpuname[get_cpuname()]; } char *get_lower_cpunamechar(void) { return lowercpuname[get_cpuname()]; } int get_coretype(void) { int family, exfamily, model, exmodel, vendor, stepping; if (!have_cpuid()) return CORE_80486; family = get_cputype(GET_FAMILY); exfamily = get_cputype(GET_EXFAMILY); model = get_cputype(GET_MODEL); exmodel = get_cputype(GET_EXMODEL); stepping = get_cputype(GET_STEPPING); vendor = get_vendor(); if (vendor == VENDOR_INTEL) { switch (family) { case 4: return CORE_80486; case 5: return CORE_P5; case 6: switch (exmodel) { case 0: switch (model) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: #if defined(__x86_64__) || defined(__amd64__) return CORE_CORE2; #else return CORE_P6; #endif case 7: return CORE_KATMAI; case 8: case 10: case 11: return CORE_COPPERMINE; case 9: case 13: case 14: return CORE_BANIAS; case 15: return CORE_CORE2; } break; case 1: switch (model) { case 6: return CORE_CORE2; case 7: return CORE_PENRYN; case 10: case 11: case 14: case 15: return CORE_NEHALEM; case 12: return CORE_ATOM; case 13: return CORE_DUNNINGTON; } break; case 2: switch (model) { case 5: //Intel Core (Clarkdale) / Core (Arrandale) // Pentium (Clarkdale) / Pentium Mobile (Arrandale) // Xeon (Clarkdale), 32nm return CORE_NEHALEM; case 10: //Intel Core i5-2000 /i7-2000 (Sandy Bridge) if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; //OS doesn't support AVX case 12: //Xeon Processor 5600 (Westmere-EP) return CORE_NEHALEM; case 13: //Intel Core i7-3000 / Xeon E5 (Sandy Bridge) if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; //OS doesn't support AVX case 14: //Xeon E7540 case 15: //Xeon Processor E7 (Westmere-EX) return CORE_NEHALEM; } break; case 3: switch (model) { case 7: return CORE_ATOM; case 10: case 14: if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; //OS doesn't support AVX case 12: case 15: if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; case 13: //broadwell if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; } break; case 4: switch (model) { case 5: case 6: if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; case 7: case 15: //broadwell if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; case 14: //Skylake if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; case 12: // Braswell case 13: // Avoton return CORE_NEHALEM; } break; case 5: switch (model) { case 6: //broadwell if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; case 5: // Skylake X #ifndef NO_AVX512 if (support_avx512_bf16()) return CORE_COOPERLAKE; return CORE_SKYLAKEX; #else if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; #endif case 14: // Skylake if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; case 7: // Phi Knights Landing if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; case 12: // Apollo Lake return CORE_NEHALEM; } break; case 6: if (model == 6) #ifndef NO_AVX512 return CORE_SKYLAKEX; #else if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; #endif if (model == 10 || model == 12) #ifndef NO_AVX512 if (support_avx512_bf16()) return CORE_COOPERLAKE; return CORE_SKYLAKEX; #else if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; #endif case 7: if (model == 10) return CORE_NEHALEM; if (model == 13 || model == 14) // Ice Lake #ifndef NO_AVX512 return CORE_SKYLAKEX; #else if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; #endif break; case 8: if (model == 12 || model == 13) { // Tiger Lake if (support_avx512()) return CORE_SKYLAKEX; if (support_avx2()) return CORE_HASWELL; if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; } if (model == 14) { // Kaby Lake mobile if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; } if (model == 15) { // Sapphire Rapids if (support_amx_bf16()) return CORE_SAPPHIRERAPIDS; if (support_avx512_bf16()) return CORE_COOPERLAKE; if (support_avx512()) return CORE_SKYLAKEX; if (support_avx2()) return CORE_HASWELL; if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; } break; case 9: if (model == 7 || model == 10) { // Alder Lake if (support_avx2()) return CORE_HASWELL; if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; } if (model == 12) // Jasper Lake return CORE_NEHALEM; if (model == 13) { // Ice Lake NNPI if (support_avx512()) return CORE_SKYLAKEX; if (support_avx2()) return CORE_HASWELL; if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; } if (model == 14) { // Kaby Lake desktop if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; } break; case 10: switch (model) { case 13: // Granite Rapids if (support_amx_bf16()) return CORE_SAPPHIRERAPIDS; if (support_avx512_bf16()) return CORE_COOPERLAKE; if (support_avx512()) return CORE_SKYLAKEX; if (support_avx2()) return CORE_HASWELL; if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; case 5: // Comet Lake H and S case 6: // Comet Lake U case 10: // Meteor Lake if (support_avx()) #ifndef NO_AVX2 return CORE_HASWELL; #else return CORE_SANDYBRIDGE; #endif else return CORE_NEHALEM; case 0: // Meteor Lake case 7: // Rocket Lake #ifndef NO_AVX512 if (support_avx512()) return CORE_SKYLAKEX; #endif #ifndef NO_AVX2 if (support_avx2()) return CORE_HASWELL; #endif if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; } case 11: switch (model) { case 7: // Raptor Lake case 10: case 15: case 14: // Alder Lake N case 13: // Lunar Lake #ifndef NO_AVX2 if (support_avx2()) return CORE_HASWELL; #endif if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; } case 12: switch (model) { case 6: // Arrow Lake if (support_amx_bf16()) return CORE_SAPPHIRERAPIDS; if (support_avx512_bf16()) return CORE_COOPERLAKE; if (support_avx512()) return CORE_SKYLAKEX; if (support_avx2()) return CORE_HASWELL; if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; break; case 12: // Panther Lake if (support_avx2()) return CORE_HASWELL; if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; case 15: // Emerald Rapids if (support_amx_bf16()) return CORE_SAPPHIRERAPIDS; if (support_avx512_bf16()) return CORE_COOPERLAKE; if (support_avx512()) return CORE_SKYLAKEX; if (support_avx2()) return CORE_HASWELL; if (support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; } } case 15: if (model <= 0x2) return CORE_NORTHWOOD; if (support_amx_bf16()) return CORE_SAPPHIRERAPIDS; if (support_avx512_bf16()) return CORE_COOPERLAKE; if (support_avx512()) return CORE_SKYLAKEX; if (support_avx2()) return CORE_HASWELL; if (support_avx()) return CORE_SANDYBRIDGE; return CORE_PRESCOTT; default: // family types since 2026 if (support_amx_bf16()) return CORE_SAPPHIRERAPIDS; if (support_avx512_bf16()) return CORE_COOPERLAKE; if (support_avx512()) return CORE_SKYLAKEX; if (support_avx2()) return CORE_HASWELL; if (support_avx()) return CORE_SANDYBRIDGE; return CORE_NEHALEM; } } if (vendor == VENDOR_AMD) { if (family <= 0x5) return CORE_80486; #if defined(__x86_64__) || defined(__amd64__) if (family <= 0xe) return CORE_BARCELONA; #else if (family <= 0xe) return CORE_ATHLON; #endif if (family == 0xf) { if ((exfamily == 0) || (exfamily == 2)) return CORE_OPTERON; else if (exfamily == 5) return CORE_BOBCAT; else if (exfamily == 6) { switch (model) { case 1: //AMD Bulldozer Opteron 6200 / Opteron 4200 / AMD FX-Series if (support_avx()) return CORE_BULLDOZER; else return CORE_BARCELONA; //OS don't support AVX. case 2: //AMD Piledriver case 3: //AMD Richland if (support_avx()) return CORE_PILEDRIVER; else return CORE_BARCELONA; //OS don't support AVX. case 5: // New EXCAVATOR if (support_avx()) return CORE_EXCAVATOR; else return CORE_BARCELONA; //OS don't support AVX. case 0: case 8: switch (exmodel) { case 1: //AMD Trinity if (support_avx()) return CORE_PILEDRIVER; else return CORE_BARCELONA; //OS don't support AVX. case 3: if (support_avx()) return CORE_STEAMROLLER; else return CORE_BARCELONA; //OS don't support AVX. case 6: if (support_avx()) return CORE_EXCAVATOR; else return CORE_BARCELONA; //OS don't support AVX. } break; } } else if (exfamily == 8 || exfamily == 10 || exfamily == 11) { switch (model) { case 1: // AMD Ryzen case 8: // Ryzen 2 default: // Matisse,Renoir Ryzen2 models #ifndef NO_AVX512 if (support_avx512_bf16()) return CORE_COOPERLAKE; if (support_avx512()) return CORE_SKYLAKEX; #endif if (support_avx()) #ifndef NO_AVX2 return CORE_ZEN; #else return CORE_SANDYBRIDGE; // Zen is closer in architecture to Sandy Bridge than to Excavator #endif else return CORE_BARCELONA; } } else { return CORE_BARCELONA; } } } if (vendor == VENDOR_HYGON) { if (family == 0xf) { if (exfamily == 9) { if (support_avx()) #ifndef NO_AVX2 return CORE_ZEN; #else return CORE_SANDYBRIDGE; // closer in architecture to Sandy Bridge than to Excavator #endif else return CORE_BARCELONA; } else { return CORE_BARCELONA; } } } if (vendor == VENDOR_CENTAUR) { switch (family) { case 0x6: if (model == 0xf && stepping < 0xe) return CORE_NANO; return CORE_NEHALEM; case 0x7: switch (exmodel) { case 5: if (support_avx2()) return CORE_ZEN; else return CORE_DUNNINGTON; default: return CORE_NEHALEM; } default: if (family >= 0x8) return CORE_NEHALEM; else return CORE_VIAC3; } } if (vendor == VENDOR_ZHAOXIN) { switch (family) { case 0x7: switch (exmodel) { case 5: case 6: if (support_avx2()) return CORE_ZEN; else return CORE_DUNNINGTON; default: return CORE_NEHALEM; } default: return CORE_NEHALEM; } } return CORE_UNKNOWN; } void get_cpuconfig(void) { cache_info_t info; int features; printf("#define %s\n", cpuname[get_cpuname()]); if (get_coretype() != CORE_P5) { get_cacheinfo(CACHE_INFO_L1_I, &info); if (info.size > 0) { printf("#define L1_CODE_SIZE %d\n", info.size * 1024); printf("#define L1_CODE_ASSOCIATIVE %d\n", info.associative); printf("#define L1_CODE_LINESIZE %d\n", info.linesize); } get_cacheinfo(CACHE_INFO_L1_D, &info); if (info.size > 0) { printf("#define L1_DATA_SIZE %d\n", info.size * 1024); printf("#define L1_DATA_ASSOCIATIVE %d\n", info.associative); printf("#define L1_DATA_LINESIZE %d\n", info.linesize); } get_cacheinfo(CACHE_INFO_L2, &info); if (info.size > 0) { printf("#define L2_SIZE %d\n", info.size * 1024); printf("#define L2_ASSOCIATIVE %d\n", info.associative); printf("#define L2_LINESIZE %d\n", info.linesize); } else { //fall back for some virtual machines. printf("#define L2_SIZE 1048576\n"); printf("#define L2_ASSOCIATIVE 6\n"); printf("#define L2_LINESIZE 64\n"); } get_cacheinfo(CACHE_INFO_L3, &info); if (info.size > 0) { printf("#define L3_SIZE %d\n", info.size * 1024); printf("#define L3_ASSOCIATIVE %d\n", info.associative); printf("#define L3_LINESIZE %d\n", info.linesize); } get_cacheinfo(CACHE_INFO_L1_ITB, &info); if (info.size > 0) { printf("#define ITB_SIZE %d\n", info.size * 1024); printf("#define ITB_ASSOCIATIVE %d\n", info.associative); printf("#define ITB_ENTRIES %d\n", info.linesize); } get_cacheinfo(CACHE_INFO_L1_DTB, &info); if (info.size > 0) { printf("#define DTB_SIZE %d\n", info.size * 1024); printf("#define DTB_ASSOCIATIVE %d\n", info.associative); printf("#define DTB_DEFAULT_ENTRIES %d\n", info.linesize); } else { //fall back for some virtual machines. printf("#define DTB_DEFAULT_ENTRIES 32\n"); } features = get_cputype(GET_FEATURE); if (features & HAVE_CMOV) printf("#define HAVE_CMOV\n"); if (features & HAVE_MMX) printf("#define HAVE_MMX\n"); if (features & HAVE_SSE) printf("#define HAVE_SSE\n"); if (features & HAVE_SSE2) printf("#define HAVE_SSE2\n"); if (features & HAVE_SSE3) printf("#define HAVE_SSE3\n"); if (features & HAVE_SSSE3) printf("#define HAVE_SSSE3\n"); if (features & HAVE_SSE4_1) printf("#define HAVE_SSE4_1\n"); if (features & HAVE_SSE4_2) printf("#define HAVE_SSE4_2\n"); if (features & HAVE_SSE4A) printf("#define HAVE_SSE4A\n"); if (features & HAVE_SSE5) printf("#define HAVE_SSSE5\n"); if (features & HAVE_AVX) printf("#define HAVE_AVX\n"); if (features & HAVE_AVX2) printf("#define HAVE_AVX2\n"); if (features & HAVE_AVX512VL) printf("#define HAVE_AVX512VL\n"); if (features & HAVE_AVX512BF16) printf("#define HAVE_AVX512BF16\n"); if (features & HAVE_AMXBF16) printf("#define HAVE_AMXBF16\n"); if (features & HAVE_3DNOWEX) printf("#define HAVE_3DNOWEX\n"); if (features & HAVE_3DNOW) printf("#define HAVE_3DNOW\n"); if (features & HAVE_FMA4) printf("#define HAVE_FMA4\n"); if (features & HAVE_FMA3) printf("#define HAVE_FMA3\n"); if (features & HAVE_CFLUSH) printf("#define HAVE_CFLUSH\n"); if (features & HAVE_HIT) printf("#define HAVE_HIT 1\n"); if (features & HAVE_MISALIGNSSE) printf("#define HAVE_MISALIGNSSE\n"); if (features & HAVE_128BITFPU) printf("#define HAVE_128BITFPU\n"); if (features & HAVE_FASTMOVU) printf("#define HAVE_FASTMOVU\n"); printf("#define NUM_SHAREDCACHE %d\n", get_cputype(GET_NUMSHARE) + 1); printf("#define NUM_CORES %d\n", get_cputype(GET_NUMCORES) + 1); features = get_coretype(); if (features > 0) printf("#define CORE_%s\n", corename[features]); } else { printf("#define DTB_DEFAULT_ENTRIES 16\n"); printf("#define L1_CODE_SIZE 8192\n"); printf("#define L1_DATA_SIZE 8192\n"); printf("#define L2_SIZE 0\n"); } } void get_architecture(void) { #ifndef __64BIT__ printf("X86"); #else printf("X86_64"); #endif } void get_subarchitecture(void) { printf("%s", get_cpunamechar()); } void get_subdirname(void) { #ifndef __64BIT__ printf("x86"); #else printf("x86_64"); #endif } char *get_corename(void) { return corename[get_coretype()]; } void get_libname(void) { printf("%s", corename_lower[get_coretype()]); } /* This if for Makefile */ void get_sse(void) { int features; features = get_cputype(GET_FEATURE); if (features & HAVE_MMX) printf("HAVE_MMX=1\n"); if (features & HAVE_SSE) printf("HAVE_SSE=1\n"); if (features & HAVE_SSE2) printf("HAVE_SSE2=1\n"); if (features & HAVE_SSE3) printf("HAVE_SSE3=1\n"); if (features & HAVE_SSSE3) printf("HAVE_SSSE3=1\n"); if (features & HAVE_SSE4_1) printf("HAVE_SSE4_1=1\n"); if (features & HAVE_SSE4_2) printf("HAVE_SSE4_2=1\n"); if (features & HAVE_SSE4A) printf("HAVE_SSE4A=1\n"); if (features & HAVE_SSE5) printf("HAVE_SSSE5=1\n"); if (features & HAVE_AVX) printf("HAVE_AVX=1\n"); if (features & HAVE_AVX2) printf("HAVE_AVX2=1\n"); if (features & HAVE_AVX512VL) printf("HAVE_AVX512VL=1\n"); if (features & HAVE_AVX512BF16) printf("HAVE_AVX512BF16=1\n"); if (features & HAVE_AMXBF16) printf("HAVE_AMXBF16=1\n"); if (features & HAVE_3DNOWEX) printf("HAVE_3DNOWEX=1\n"); if (features & HAVE_3DNOW) printf("HAVE_3DNOW=1\n"); if (features & HAVE_FMA4) printf("HAVE_FMA4=1\n"); if (features & HAVE_FMA3) printf("HAVE_FMA3=1\n"); } //}