测试CPU的特性

/*
功能:测试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的特性)