/*
功能:测试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;
}
测试CPU的特性
最新推荐文章于 2023-11-13 15:08:11 发布