/* 功能:测试CPU的特性 测试环境:Windows 8.1 64bit、Visual Studio 2013 Update1、Core i5-2500k 最后更新日期:2014-04-23 kagula 描述:我忘记这段代码从哪里download下来,但是经测试可以用, 通过这段代码的学习, 可以写一个测试CPU是否支持SSE/SSE2特性的函数。 如何运行源代码:在Visual Studio 2013下建立Windows Console项目,然后加入这个源代码编译,运行即可。 */ #include "stdafx.h" #include <stdio.h> #include <stdint.h> #include <string.h> enum { CPU_X86_FEATURE_SSE = (1 << 1), CPU_X86_FEATURE_SSE2 = (1 << 2), CPU_X86_FEATURE_SSE3 = (1 << 3), CPU_X86_FEATURE_SSSE3 = (1 << 4), CPU_X86_FEATURE_SSE4_1 = (1 << 5), CPU_X86_FEATURE_SSE4_2 = (1 << 6), CPU_X86_FEATURE_POPCNT = (1 << 7), CPU_X86_FEATURE_MOVBE = (1 << 8), CPU_X86_FEATURE_AESNI = (1 << 9), CPU_X86_FEATURE_RDRND = (1 << 10), CPU_X86_FEATURE_PCLMULQDQ = (1 << 11), CPU_X86_FEATURE_SMEP = (1 << 12), // CPUID.7.0.EBX[7] OS Guard CPU_X86_FEATURE_SHA = (1 << 13), // CPUID.7.0.EBX[29] http://software.intel.com/en-us/articles/intel-sha-extensions CPU_X86_FEATURE_ADX = (1 << 14), // CPUID.(EAX=07H, ECX=0H):EBX.ADX[bit 19]=1 indicates the processor supports ADCX and ADOX instructions CPU_X86_FEATURE_RDSEED = (1 << 15), // Hardware support for the RDSEED instruction is indicated by CPUID.(EAX=07H,ECX=0H):EBX.RDSEED[bit 18]. }; static uint64_t g_cpu_features = 0; #ifdef WIN32 #include <intrin.h> #else static void __cpuidex(unsigned int where[4], unsigned int leaf, unsigned int ECXValue) { asm volatile("cpuid":"=a"(*where), "=b"(*(where + 1)), "=c"(*(where + 2)), "=d"(*(where + 3)) : "a"(leaf), "c"(ECXValue)); return; } static void __cpuid(unsigned int where[4], unsigned int leaf) { asm volatile("cpuid":"=a"(*where), "=b"(*(where + 1)), "=c"(*(where + 2)), "=d"(*(where + 3)) : "a"(leaf)); return; } #endif static int get_cpu_features() { int cpuid_results[4]; __cpuid(cpuid_results, 0); if (cpuid_results[0] < 1) return 0; /* * MSB LSB * EBX = 'u' 'n' 'e' 'G' * EDX = 'I' 'e' 'n' 'i' * ECX = 'l' 'e' 't' 'n' */ /* According to http://en.wikipedia.org/wiki/CPUID */ if (memcmp((unsigned char *)&cpuid_results[1], "Genu", 4) != 0 || memcmp((unsigned char *)&cpuid_results[3], "ineI", 4) != 0 || memcmp((unsigned char *)&cpuid_results[2], "ntel", 4) != 0) return 0; __cpuid(cpuid_results, 1); printf("CPUID.1.ECX 0x%08x:\n", cpuid_results[2]); if ((cpuid_results[2] & (1 << 1)) != 0) { // CPUID.1.ECX[1] g_cpu_features |= CPU_X86_FEATURE_PCLMULQDQ; } if ((cpuid_results[2] & (1 << 9)) != 0) { g_cpu_features |= CPU_X86_FEATURE_SSSE3; } if ((cpuid_results[2] & (1 << 23)) != 0) { g_cpu_features |= CPU_X86_FEATURE_POPCNT; } if ((cpuid_results[2] & (1 << 25)) != 0) { g_cpu_features |= CPU_X86_FEATURE_AESNI; // aes-ni } if ((cpuid_results[2] & (1 << 30)) != 0) { //RDRAND is not an AVX instruction. It is a normal instruction. g_cpu_features |= CPU_X86_FEATURE_RDRND; // secure key } // vendorIsIntel if ((cpuid_results[2] & (1 << 22)) != 0) { g_cpu_features |= CPU_X86_FEATURE_MOVBE; } if ((cpuid_results[2] & (1 << 25)) != 0) { g_cpu_features |= CPU_X86_FEATURE_SSE; } if ((cpuid_results[2] & (1 << 26)) != 0) { g_cpu_features |= CPU_X86_FEATURE_SSE2; } if ((cpuid_results[2] & (1 << 0)) != 0) { g_cpu_features |= CPU_X86_FEATURE_SSE3; } if ((cpuid_results[2] & (1 << 19)) != 0) { g_cpu_features |= CPU_X86_FEATURE_SSE4_1; } if ((cpuid_results[2] & (1 << 20)) != 0) { g_cpu_features |= CPU_X86_FEATURE_SSE4_2; } // Look for CPUID.7.0.EBX // EAX = 7, ECX = 0 __cpuidex(cpuid_results, 7, 0); printf("CPUID.7.0.EBX 0x%08x:\n", cpuid_results[1]); if ((cpuid_results[1] & (1 << 7)) != 0) { // SMEP is identified by CPUID leaf 7 EBX[7], which is 0 before // CPUID.7.0.EBX[7] g_cpu_features |= CPU_X86_FEATURE_SMEP; } if ((cpuid_results[1] & (1 << 18)) != 0) { // Intel® RDSEED Extensions // CPUID.7.0.EBX[18] g_cpu_features |= CPU_X86_FEATURE_RDSEED; } if ((cpuid_results[1] & (1 << 19)) != 0) { // Intel® ADX Extensions // CPUID.7.0.EBX[19] g_cpu_features |= CPU_X86_FEATURE_ADX; } if ((cpuid_results[1] & (1 << 29)) != 0) { // Intel® SHA Extensions // CPUID.7.0.EBX[29] g_cpu_features |= CPU_X86_FEATURE_SHA; } return 1; } struct cpu_features { char name[16]; int value; }; struct cpu_features cpu_x86_features[] = { { "SSE ", CPU_X86_FEATURE_SSE }, { "SSE2 ", CPU_X86_FEATURE_SSE2 }, { "SSE3 ", CPU_X86_FEATURE_SSE3 }, { "SSSE3 ", CPU_X86_FEATURE_SSSE3 }, { "SSE4_1 ", CPU_X86_FEATURE_SSE4_1 }, { "SSE4_2 ", CPU_X86_FEATURE_SSE4_2 }, { "PCLMULQDQ ", CPU_X86_FEATURE_PCLMULQDQ }, { "AES-NI ", CPU_X86_FEATURE_AESNI }, { "RDRAND ", CPU_X86_FEATURE_RDRND }, { "SMEP ", CPU_X86_FEATURE_SMEP }, { "SHA ", CPU_X86_FEATURE_SHA }, { "ADX ", CPU_X86_FEATURE_ADX }, { "RDSEED ", CPU_X86_FEATURE_RDSEED } }; int _tmain(int argc, _TCHAR* argv[]) { int i = 0, num = 0; if (0 == g_cpu_features) get_cpu_features(); printf("This cpu features 0x%08x:\n", g_cpu_features); num = sizeof(cpu_x86_features) / sizeof(struct cpu_features); for (i = 0; i < num; i++) { printf(cpu_x86_features[i].name); if (g_cpu_features & cpu_x86_features[i].value) { printf("support\n"); } else { printf("not support\n"); } } //输入一个字符后,程序返回! getchar(); return 0; }