-
-
Save aktau/6068f058fda797bfd6de to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if defined(__GNUC__) | |
#include <stdint.h> | |
#include <cpuid.h> | |
#elif defined(_WIN32) | |
#include <intrin.h> | |
typedef unsigned __int32 uint32_t; | |
#endif | |
#include <stdio.h> | |
/** | |
* Calls cpuid with op and store results of eax,ebx,ecx,edx | |
* \param op cpuid function (eax input) | |
* \param eax content of eax after the call to cpuid | |
* \param ebx content of ebx after the call to cpuid | |
* \param ecx content of ecx after the call to cpuid | |
* \param edx content of edx after the call to cpuid | |
*/ | |
void cpuid( uint32_t op, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx ) | |
{ | |
#if defined(__GNUC__) | |
uint32_t r_eax; | |
uint32_t r_ebx; | |
uint32_t r_ecx; | |
uint32_t r_edx; | |
// GCC won't allow us to clobber EBX since its used to store the GOT. So we need to | |
// lie to GCC and backup/restore EBX without declaring it as clobbered. | |
asm volatile( "pushl %%ebx \n\t" | |
"cpuid \n\t" | |
"movl %%ebx, %1\n\t" | |
"popl %%ebx \n\t" | |
: "=a"(r_eax), "=r"(r_ebx), "=c"(r_ecx), "=d"(r_edx) | |
: "a"(op) | |
: "cc" ); | |
*eax = r_eax; | |
*ebx = r_ebx; | |
*ecx = r_ecx; | |
*edx = r_edx; | |
#elif defined(_WIN32) | |
// MSVC provides a __cpuid function | |
int regs[4]; | |
__cpuid( regs, op ); | |
*eax = (uint32_t)regs[0]; | |
*ebx = (uint32_t)regs[1]; | |
*ecx = (uint32_t)regs[2]; | |
*edx = (uint32_t)regs[3]; | |
#endif | |
} | |
void | |
print_feature( uint32_t test, const char* name ) | |
{ | |
printf("%s - %s\n", (test)?"YES":"NO ", name ); | |
} | |
int | |
main( void ) | |
{ | |
uint32_t eax; | |
uint32_t ebx; | |
uint32_t ecx; | |
uint32_t edx; | |
cpuid( 0, &eax, &ebx, &ecx, &edx ); | |
uint32_t ids = eax; | |
cpuid( 0x80000000, &eax, &ebx, &ecx, &edx ); | |
uint32_t ex_ids = eax; | |
if ( ids >= 1 ) | |
{ | |
cpuid( 1, &eax, &ebx, &ecx, &edx ); | |
print_feature( edx & (1<< 0), "FPU (Floating-point Unit on-chip)"); | |
print_feature( edx & (1<< 1), "VME (Virtual Mode Extension)"); | |
print_feature( edx & (1<< 2), "DE (Debugging Extension)"); | |
print_feature( edx & (1<< 3), "PSE (Page Size Extension)"); | |
print_feature( edx & (1<< 4), "TSC (Time Stamp Counter)"); | |
print_feature( edx & (1<< 5), "MSR (Model Specific Registers)"); | |
print_feature( edx & (1<< 6), "PAE (Physical Address Extension)"); | |
print_feature( edx & (1<< 7), "MCE (Machine Check Exception)"); | |
print_feature( edx & (1<< 8), "CX8 (CMPXCHG8 Instructions)"); | |
print_feature( edx & (1<< 9), "APIC (On-chip APIC hardware)"); | |
print_feature( edx & (1<<11), "SEP (Fast System Call)"); | |
print_feature( edx & (1<<12), "MTRR (Memory type Range Registers)"); | |
print_feature( edx & (1<<13), "PGE (Page Global Enable)"); | |
print_feature( edx & (1<<14), "MCA (Machine Check Architecture)"); | |
print_feature( edx & (1<<15), "CMOV (Conditional Move Instruction)"); | |
print_feature( edx & (1<<16), "PAT (Page Attribute Table)"); | |
print_feature( edx & (1<<17), "PSE36 (36bit Page Size Extension"); | |
print_feature( edx & (1<<18), "PSN (Processor Serial Number)"); | |
print_feature( edx & (1<<19), "CLFSH (CFLUSH Instruction)"); | |
print_feature( edx & (1<<21), "DS (Debug Store)"); | |
print_feature( edx & (1<<22), "ACPI (Thermal Monitor & Software Controlled Clock)"); | |
print_feature( edx & (1<<23), "MMX (Multi-Media Extension)"); | |
print_feature( edx & (1<<24), "FXSR (Fast Floating Point Save & Restore)"); | |
print_feature( edx & (1<<25), "SSE (Streaming SIMD Extension 1)"); | |
print_feature( edx & (1<<26), "SSE2 (Streaming SIMD Extension 2)"); | |
print_feature( edx & (1<<27), "SS (Self Snoop)"); | |
print_feature( edx & (1<<28), "HTT (Hyper Threading Technology)"); | |
print_feature( edx & (1<<29), "TM (Thermal Monitor)"); | |
print_feature( edx & (1<<31), "PBE (Pend Break Enabled)"); | |
print_feature( ecx & (1<< 0), "SSE3 (Streaming SMD Extension 3)"); | |
print_feature( ecx & (1<< 3), "MW (Monitor Wait Instruction"); | |
print_feature( ecx & (1<< 4), "CPL (CPL-qualified Debug Store)"); | |
print_feature( ecx & (1<< 5), "VMX (Virtual Machine Extensions)"); | |
print_feature( ecx & (1<< 7), "EST (Enchanced Speed Test)"); | |
print_feature( ecx & (1<< 8), "TM2 (Thermal Monitor 2)"); | |
print_feature( ecx & (1<< 9), "SSSE3 (Supplemental Streaming SIMD Extensions 3)"); | |
print_feature( ecx & (1<<10), "L1 (L1 Context ID)"); | |
print_feature( ecx & (1<<12), "FMA3 (Fused Multiply-Add 3-operand Form)"); | |
print_feature( ecx & (1<<13), "CAE (Compare And Exchange 16B)"); | |
print_feature( ecx & (1<<19), "SSE41 (Streaming SIMD Extensions 4.1)"); | |
print_feature( ecx & (1<<20), "SSE42 (Streaming SIMD Extensions 4.2)"); | |
print_feature( ecx & (1<<25), "AES (Advanced Encryption Standard)"); | |
print_feature( ecx & (1<<28), "AVX (Advanced Vector Extensions)"); | |
print_feature( ecx & (1<<30), "RDRAND (Random Number Generator)"); | |
} | |
if ( ids >= 7 ) | |
{ | |
cpuid( 7, &eax, &ebx, &ecx, &edx ); | |
print_feature( ebx & (1<< 5), "AVX2 (Advanced Vector Extensions 2)"); | |
print_feature( ebx & (1<< 3), "BMI1 (Bit Manipulations Instruction Set 1)"); | |
print_feature( ebx & (1<< 8), "BMI2 (Bit Manipulations Instruction Set 2)"); | |
print_feature( ebx & (1<<19), "ADX (Multi-Precision Add-Carry Instruction Extensions)"); | |
print_feature( ebx & (1<<16), "AVX512F (512-bit extensions to Advanced Vector Extensions Foundation)"); | |
print_feature( ebx & (1<<26), "AVX512PFI (512-bit extensions to Advanced Vector Extensions Prefetch Instructions)"); | |
print_feature( ebx & (1<<27), "AVX512ERI (512-bit extensions to Advanced Vector Extensions Exponential and Reciprocal Instructions)"); | |
print_feature( ebx & (1<<28), "AVX512CDI (512-bit extensions to Advanced Vector Extensions Conflict Detection Instructions)"); | |
print_feature( ebx & (1<<29), "SHA (Secure Hash Algorithm)"); | |
} | |
if ( ex_ids >= 0x80000001 ) | |
{ | |
cpuid( 0x80000001, &eax, &ebx, &ecx, &edx ); | |
print_feature( edx & (1<<29), "X64 (64-bit Extensions)"); | |
print_feature( ecx & (1<< 5), "LZCNT (Leading Zero Bit Count Instruction)"); | |
print_feature( ecx & (1<< 6), "SSE4A (Streaming SIMD Extensions 4a)"); | |
print_feature( ecx & (1<<16), "FMA4 (Fused Multiply-Add 4-operand Form)"); | |
print_feature( ecx & (1<<11), "XOP (Extended Operations)"); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment