#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_CPUID4_H_ #define COSMOPOLITAN_LIBC_NEXGEN32E_CPUID4_H_ #include "libc/nexgen32e/kcpuids.h" #define CPUID4_KEY (eax & 0xff) #define CPUID4_CACHE_TYPE (((eax & 0x0000001fu) >> 000) + 0) #define CPUID4_CACHE_LEVEL (((eax & 0x000000e0u) >> 005) + 0) #define CPUID4_IS_FULLY_ASSOCIATIVE (!!(eax & (1u << 9))) #define CPUID4_IS_SELF_INITIALIZING_LEVEL (!!(eax & (1u << 8))) #define CPUID4_MAX_THREADS_SHARING_CACHE (((eax & 0x03ffc000u) >> 016) + 1) #define CPUID4_MAX_CORES_IN_PHYSICAL_CPU (((eax & 0xfc000000u) >> 032) + 1) #define CPUID4_SYSTEM_COHERENCY_LINE_SIZE (((Ebx & 0x00000fffu) >> 000) + 1) #define CPUID4_PHYSICAL_LINE_PARTITIONS (((Ebx & 0x003ff000u) >> 014) + 1) #define CPUID4_WAYS_OF_ASSOCIATIVITY (((Ebx & 0xffc00000u) >> 026) + 1) #define CPUID4_NUMBER_OF_SETS (Ecx + 1u) #define CPUID4_WBINVD_INVD_BEHAVIOR (!!(Edx & (1u << 0))) #define CPUID4_INCLUSIVE_OF_LOWER_LEVELS (!!(Edx & (1u << 1))) #define CPUID4_COMPLEX_INDEXING (!!(Edx & (1u << 2))) #define CPUID4_CACHE_SIZE_IN_BYTES \ (CPUID4_WAYS_OF_ASSOCIATIVITY * CPUID4_PHYSICAL_LINE_PARTITIONS * \ CPUID4_SYSTEM_COHERENCY_LINE_SIZE * CPUID4_NUMBER_OF_SETS) #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ #define CPUID4_ITERATE(I, FORM) \ do { \ uint32_t eax, Ebx, Ecx, Edx; \ if (KCPUIDS(0H, EAX) >= 4) { \ for (I = 0;; ++I) { \ asm("push\t%%rbx\n\t" \ "cpuid\n\t" \ "mov\t%%ebx,%1\n\t" \ "pop\t%%rbx" \ : "=a"(eax), "=rm"(Ebx), "=c"(Ecx), "=d"(Edx) \ : "0"(4), "2"(I)); \ (void)Ebx; \ (void)Ecx; \ (void)Edx; \ if (CPUID4_CACHE_TYPE) { \ FORM; \ } else { \ break; \ } \ } \ } \ } while (0) COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_NEXGEN32E_CPUID4_H_ */