#include <stdio.h>
#include <windows.h>
#include <intrin.h>
#define CPU_X86_MMX (1<<0)
#define CPU_X86_3DNOW (1<<1)
#define CPU_X86_3DNOWEXT (1<<2)
#define CPU_X86_MMXEXT (1<<3)
#define CPU_X86_SSE (1<<4)
#define CPU_X86_SSE2 (1<<5)
#define CPU_X86_SSE3 (1<<6)
#define CPU_X86_SSSE3 (1<<7)
#define CPU_X86_SSE41 (1<<8)
#define CPU_X86_SSE42 (1<<9)
#define CPU_X86_SSE4a (1<<10)
enum CpuVendor {
CPU_V_Unknown,
CPU_V_Intel,
CPU_V_AMD,
CPU_V_Transmeta,
CPU_V_Cyrix,
CPU_V_IDT,
CPU_V_Rise,
CPU_V_NexGen,
CPU_V_UMC,
CPU_V_NSC,
CPU_V_Compaq,
CPU_V_EOT
};
void GetCpuid( int op, int& eax, int& ebx, int& ecx, int& edx)
{
int info[4] = {0,0,0,0};
__cpuid( info, op );
eax = info[0];
ebx = info[1];
ecx = info[2];
edx = info[3];
}
static int GetCpuVendor( int& max )
{
enum CpuVendor ret = CPU_V_Unknown;
int eax, ebx, ecx, edx;
GetCpuid( 0, eax, ebx, ecx, edx );
max = eax;
#define MAKE_VENDOR_CODE( a, b, c, d ) ( ((d) << 24) | ((c) << 16) | ((b) << 8) | (a) )
// GenuineIntel
static const int Intel_EBX = MAKE_VENDOR_CODE( 'G', 'e', 'n', 'u' );
static const int Intel_EDX = MAKE_VENDOR_CODE( 'i', 'n', 'e', 'I' );
static const int Intel_ECX = MAKE_VENDOR_CODE( 'n', 't', 'e', 'l' );
// AuthenticAMD
static const int AMD_EBX = MAKE_VENDOR_CODE( 'A', 'u', 't', 'h' );
static const int AMD_EDX = MAKE_VENDOR_CODE( 'e', 'n', 't', 'i' );
static const int AMD_ECX = MAKE_VENDOR_CODE( 'c', 'A', 'M', 'D' );
// GenuineTMx86
static const int Transmeta_EBX = MAKE_VENDOR_CODE( 'G', 'e', 'n', 'u' );
static const int Transmeta_EDX = MAKE_VENDOR_CODE( 'i', 'n', 'e', 'T' );
static const int Transmeta_ECX = MAKE_VENDOR_CODE( 'M', 'x', '8', '6' );
// CyrixInstead
static const int Cyrix_EBX = MAKE_VENDOR_CODE( 'C', 'y', 'r', 'i' );
static const int Cyrix_EDX = MAKE_VENDOR_CODE( 'x', 'I', 'n', 's' );
static const int Cyrix_ECX = MAKE_VENDOR_CODE( 't', 'e', 'a', 'd' );
// CentaurHauls
static const int IDT_EBX = MAKE_VENDOR_CODE( 'C', 'e', 'n', 't' );
static const int IDT_EDX = MAKE_VENDOR_CODE( 'a', 'u', 'r', 'H' );
static const int IDT_ECX = MAKE_VENDOR_CODE( 'a', 'u', 'l', 's' );
// RiseRiseRise
static const int Rise_EBX = MAKE_VENDOR_CODE( 'R', 'i', 's', 'e' );
static const int Rise_EDX = MAKE_VENDOR_CODE( 'R', 'i', 's', 'e' );
static const int Rise_ECX = MAKE_VENDOR_CODE( 'R', 'i', 's', 'e' );
// NexGenDriven
static const int NexGen_EBX = MAKE_VENDOR_CODE( 'N', 'e', 'x', 'G' );
static const int NexGen_EDX = MAKE_VENDOR_CODE( 'e', 'n', 'D', 'r' );
static const int NexGen_ECX = MAKE_VENDOR_CODE( 'i', 'v', 'e', 'n' );
// UMC UMC UMC
static const int UMC_EBX = MAKE_VENDOR_CODE( 'U', 'M', 'C', ' ' );
static const int UMC_EDX = MAKE_VENDOR_CODE( 'U', 'M', 'C', ' ' );
static const int UMC_ECX = MAKE_VENDOR_CODE( 'U', 'M', 'C', ' ' );
// Geode By NSC
static const int NSC_EBX = MAKE_VENDOR_CODE( 'G', 'e', 'o', 'd' );
static const int NSC_EDX = MAKE_VENDOR_CODE( 'e', ' ', 'B', 'y' );
static const int NSC_ECX = MAKE_VENDOR_CODE( 'N', 'S', 'C', ' ' );
// Compaq FX32!
static const int Compaq_EBX = MAKE_VENDOR_CODE( 'C', 'o', 'm', 'p' );
static const int Compaq_EDX = MAKE_VENDOR_CODE( 'a', 'q', ' ', 'F' );
static const int Compaq_ECX = MAKE_VENDOR_CODE( 'X', '3', '2', '!' );
#undef MAKE_VENDOR_CODE
if( ebx == Intel_EBX && edx == Intel_EDX && ecx == Intel_ECX ) {
ret = CPU_V_Intel;
} else if( ebx == AMD_EBX && edx == AMD_EDX && ecx == AMD_ECX ) {
ret = CPU_V_AMD;
} else if( ebx == Transmeta_EBX && edx == Transmeta_EDX && ecx == Transmeta_ECX ) {
ret = CPU_V_Transmeta;
} else if( ebx == Cyrix_EBX && edx == Cyrix_EDX && ecx == Cyrix_ECX ) {
ret = CPU_V_Cyrix;
} else if( ebx == IDT_EBX && edx == IDT_EDX && ecx == IDT_ECX ) {
ret = CPU_V_IDT;
} else if( ebx == Rise_EBX && edx == Rise_EDX && ecx == Rise_ECX ) {
ret = CPU_V_Rise;
} else if( ebx == NexGen_EBX && edx == NexGen_EDX && ecx == NexGen_ECX ) {
ret = CPU_V_NexGen;
} else if( ebx == UMC_EBX && edx == UMC_EDX && ecx == UMC_ECX ) {
ret = CPU_V_UMC;
} else if( ebx == NSC_EBX && edx == NSC_EDX && ecx == NSC_ECX ) {
ret = CPU_V_NSC;
} else if( ebx == Compaq_EBX && edx == Compaq_EDX && ecx == Compaq_ECX ) {
ret = CPU_V_Compaq;
}
return ret;
}
unsigned long GetCpuFeature( int& physicalCore )
{
physicalCore = 1;
int maxCpuId = 0;
int vendor = GetCpuVendor( maxCpuId );
unsigned long flags = 0;
int eax, ebx, ecx, edx;
GetCpuid( 0x80000000, eax, ebx, ecx, edx );
int maxCpuIdEx = eax;
int featureEx = 0, featureExEcx = 0;
if( maxCpuIdEx > 0x80000000 ) {
GetCpuid( 0x80000001, eax, ebx, ecx, edx );
featureExEcx = ecx;
featureEx = edx;
}
if( featureEx & (1<<22) ) flags |= CPU_X86_MMXEXT;
if( featureEx & (1<<31) ) flags |= CPU_X86_3DNOW;
if( featureEx & (1<<30) ) flags |= CPU_X86_3DNOWEXT;
if( featureExEcx & (1<<6) ) flags |= CPU_X86_SSE4a;
GetCpuid(1,eax,ebx,ecx,edx);
int featureEcx = ecx;
int feature = edx;
if( feature & (1<<23) ) flags |= CPU_X86_MMX;
if( feature & (1<<25) ) {
if( vendor == CPU_V_Intel ) flags |= CPU_X86_SSE|CPU_X86_MMXEXT;
else flags |= CPU_X86_SSE;
}
if( feature & (1<<26) ) flags |= CPU_X86_SSE2;
if( featureEcx & 1 ) flags |= CPU_X86_SSE3;
if( featureEcx & (1<<9) ) flags |= CPU_X86_SSSE3;
if( featureEcx & (1<<19) ) flags |= CPU_X86_SSE41;
if( featureEcx & (1<<20) ) flags |= CPU_X86_SSE42;
if( vendor == CPU_V_Intel && maxCpuId >= 0x00000004 ) {
GetCpuid( 0x00000004, eax, ebx, ecx, edx );
physicalCore = ((eax >> 26) & 0x3F) + 1;
}
if( vendor == CPU_V_AMD && maxCpuIdEx >= 0x80000008 ) {
GetCpuid( 0x80000008, eax, ebx, ecx, edx );
physicalCore = (ecx & 0xFF) + 1;
}
return flags;
}
#ifdef _TEST_
#include <iostream>
int main(int argc, char* argv[])
{
int logicalCore = 1;
DWORD pamask, samask;
if( GetProcessAffinityMask( GetCurrentProcess(), &pamask, &samask) ) {
unsigned long ret;
_BitScanReverse( &ret, pamask );
logicalCore = ret+1;
}
int physicalCore = 1;
unsigned long flag = GetCpuFeature( physicalCore );
std::cout << "Logical core : " << logicalCore << std::endl;
std::cout << "Physical core : " << physicalCore << std::endl;
std::cout << "Supported feature :";
if( flag & CPU_X86_MMX ) std::cout << " MMX";
if( flag & CPU_X86_3DNOW ) std::cout << " 3DNow";
if( flag & CPU_X86_3DNOWEXT ) std::cout << " 3DNowEx";
if( flag & CPU_X86_MMXEXT ) std::cout << " MMX2";
if( flag & CPU_X86_SSE ) std::cout << " SSE";
if( flag & CPU_X86_SSE2 ) std::cout << " SSE2";
if( flag & CPU_X86_SSE3 ) std::cout << " SSE3";
if( flag & CPU_X86_SSSE3 ) std::cout << " SSSE3";
if( flag & CPU_X86_SSE41 ) std::cout << " SSE4.1";
if( flag & CPU_X86_SSE42 ) std::cout << " SSE4.2";
if( flag & CPU_X86_SSE4a ) std::cout << " SSE4a";
std::cout << std::endl;
return 0;
}
#endif // _TEST_
|