Rewrote CPU detection.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@221 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
0325f55d68
commit
99c0d7b899
|
@ -22,26 +22,27 @@
|
||||||
|
|
||||||
//#include <config/i386/cpuid.h>
|
//#include <config/i386/cpuid.h>
|
||||||
#include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
|
// fake cpuid for linux. todo: make a real one. EAX EBX ECX EDX is the right order.
|
||||||
void __cpuid(int info[4], int x) {memset(info, 0, sizeof(info));}
|
void __cpuid(int info[4], int x) {memset(info, 0, sizeof(info));}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "CPUDetect.h"
|
#include "CPUDetect.h"
|
||||||
|
#include "StringUtil.h"
|
||||||
|
|
||||||
// This code was adapted from an example in MSDN:
|
CPUInfo cpu_info;
|
||||||
CPUInfoStruct cpu_info;
|
|
||||||
|
|
||||||
void CPUInfoStruct::Detect()
|
void CPUInfo::Detect()
|
||||||
{
|
{
|
||||||
|
memset(this, 0, sizeof(*this));
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
Mode64bit = false;
|
Mode64bit = false;
|
||||||
#elif defined (_M_X64)
|
#elif defined (_M_X64)
|
||||||
Mode64bit = true;
|
Mode64bit = true;
|
||||||
OS64bit = true;
|
OS64bit = true;
|
||||||
#endif
|
#endif
|
||||||
numCores = 1;
|
num_cores = 1;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
|
@ -50,197 +51,102 @@ void CPUInfoStruct::Detect()
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// __cpuid with an InfoType argument of 0 returns the number of
|
// Set obvious defaults, for extra safety
|
||||||
// valid Ids in CPUInfo[0] and the CPU identification string in
|
if (Mode64bit)
|
||||||
// the other three array elements. The CPU identification string is
|
|
||||||
// not in linear order. The code below arranges the information
|
|
||||||
// in a human readable form.
|
|
||||||
__cpuid(CPUInfo, 0);
|
|
||||||
nIds = CPUInfo[0];
|
|
||||||
memset(CPUString, 0, sizeof(CPUString));
|
|
||||||
*((int*)CPUString) = CPUInfo[1];
|
|
||||||
*((int*)(CPUString + 4)) = CPUInfo[3];
|
|
||||||
*((int*)(CPUString + 8)) = CPUInfo[2];
|
|
||||||
|
|
||||||
// Assume that everything non-intel is AMD
|
|
||||||
if (memcmp(CPUString, "GenuineIntel", 12) == 0)
|
|
||||||
{
|
{
|
||||||
isAMD = false;
|
bSSE = true;
|
||||||
|
bSSE2 = true;
|
||||||
|
bLongMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assume CPU supports the CPUID instruction. Those that don't can barely boot modern OS:es anyway.
|
||||||
|
int cpu_id[4];
|
||||||
|
memset(cpu_string, 0, sizeof(cpu_string));
|
||||||
|
|
||||||
|
// Detect CPU's CPUID capabilities, and grab cpu string
|
||||||
|
__cpuid(cpu_id, 0x00000000);
|
||||||
|
u32 max_std_fn = cpu_id[0]; // EAX
|
||||||
|
*((int *)cpu_string) = cpu_id[1];
|
||||||
|
*((int *)(cpu_string + 4)) = cpu_id[3];
|
||||||
|
*((int *)(cpu_string + 8)) = cpu_id[2];
|
||||||
|
__cpuid(cpu_id, 0x80000000);
|
||||||
|
u32 max_ex_fn = cpu_id[0];
|
||||||
|
if (!strcmp(cpu_string, "GenuineIntel"))
|
||||||
|
vendor = VENDOR_INTEL;
|
||||||
|
else if (!strcmp(cpu_string, "AuthenticAMD"))
|
||||||
|
vendor = VENDOR_AMD;
|
||||||
else
|
else
|
||||||
{
|
vendor = VENDOR_OTHER;
|
||||||
isAMD = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nIds >= 2)
|
// Set reasonable default brand string even if brand string not available.
|
||||||
{
|
strcpy(brand_string, cpu_string);
|
||||||
// Get the information associated with each valid Id
|
|
||||||
__cpuid(CPUInfo, 1);
|
|
||||||
|
|
||||||
nSteppingID = CPUInfo[0] & 0xf;
|
|
||||||
nModel = (CPUInfo[0] >> 4) & 0xf;
|
|
||||||
nFamily = (CPUInfo[0] >> 8) & 0xf;
|
|
||||||
nProcessorType = (CPUInfo[0] >> 12) & 0x3;
|
|
||||||
nExtendedmodel = (CPUInfo[0] >> 16) & 0xf;
|
|
||||||
nExtendedfamily = (CPUInfo[0] >> 20) & 0xff;
|
|
||||||
nBrandIndex = CPUInfo[1] & 0xff;
|
|
||||||
nCLFLUSHcachelinesize = ((CPUInfo[1] >> 8) & 0xff) * 8;
|
|
||||||
nAPICPhysicalID = (CPUInfo[1] >> 24) & 0xff;
|
|
||||||
bSSE3 = (CPUInfo[2] & 0x1) || false;
|
|
||||||
bSSSE3 = (CPUInfo[2] & 0x200) || false;
|
|
||||||
bMONITOR_MWAIT = (CPUInfo[2] & 0x8) || false;
|
|
||||||
bCPLQualifiedDebugStore = (CPUInfo[2] & 0x10) || false;
|
|
||||||
bThermalMonitor2 = (CPUInfo[2] & 0x100) || false;
|
|
||||||
nFeatureInfo = CPUInfo[3];
|
|
||||||
|
|
||||||
if (CPUInfo[2] & (1 << 23))
|
// Detect family and other misc stuff.
|
||||||
{
|
bool HTT = false;
|
||||||
bPOPCNT = true;
|
int logical_cpu_count = 1;
|
||||||
}
|
if (max_std_fn >= 1) {
|
||||||
|
__cpuid(cpu_id, 0x00000001);
|
||||||
if (CPUInfo[2] & (1 << 19))
|
logical_cpu_count = (cpu_id[1] >> 16) & 0xFF;
|
||||||
{
|
if ((cpu_id[3] >> 28) & 1) {
|
||||||
bSSE4_1 = true;
|
// wtf, we get here on my core 2
|
||||||
}
|
HTT = true;
|
||||||
|
|
||||||
if (CPUInfo[2] & (1 << 20))
|
|
||||||
{
|
|
||||||
bSSE4_2 = true;
|
|
||||||
}
|
}
|
||||||
|
if ((cpu_id[3] >> 25) & 1) bSSE = true;
|
||||||
|
if ((cpu_id[3] >> 26) & 1) bSSE2 = true;
|
||||||
|
if (cpu_id[2] & 1) bSSE3 = true;
|
||||||
|
if ((cpu_id[2] >> 9) & 1) bSSSE3 = true;
|
||||||
|
if ((cpu_id[2] >> 19) & 1) bSSE4_1 = true;
|
||||||
|
if ((cpu_id[2] >> 20) & 1) bSSE4_2 = true;
|
||||||
}
|
}
|
||||||
|
if (max_std_fn >= 4) {
|
||||||
if (bSSE3)
|
// Extract brand string
|
||||||
{
|
__cpuid(cpu_id, 0x80000002);
|
||||||
// Only SSE3 CPU-s support extended infotypes
|
memcpy(brand_string, cpu_id, sizeof(cpu_id));
|
||||||
// Calling __cpuid with 0x80000000 as the InfoType argument
|
__cpuid(cpu_id, 0x80000003);
|
||||||
// gets the number of valid extended IDs.
|
memcpy(brand_string + 16, cpu_id, sizeof(cpu_id));
|
||||||
__cpuid(CPUInfo, 0x80000000);
|
__cpuid(cpu_id, 0x80000004);
|
||||||
nExIds = CPUInfo[0];
|
memcpy(brand_string + 32, cpu_id, sizeof(cpu_id));
|
||||||
memset(CPUBrandString, 0, sizeof(CPUBrandString));
|
}
|
||||||
|
if (max_ex_fn >= 0x80000001) {
|
||||||
// Get the information associated with each extended ID.
|
// Check for more features.
|
||||||
for (unsigned int i = 0x80000000; i <= nExIds; ++i)
|
__cpuid(cpu_id, 0x80000001);
|
||||||
{
|
bool cmp_legacy = false;
|
||||||
__cpuid(CPUInfo, i);
|
if (cpu_id[2] & 1) bLAHFSAHF64 = true;
|
||||||
|
if (cpu_id[2] & 2) cmp_legacy = true; //wtf is this?
|
||||||
// Interpret CPU brand string and cache information.
|
if ((cpu_id[3] >> 29) & 1) bLongMode = true;
|
||||||
if (i == 0x80000001)
|
}
|
||||||
{
|
if (max_ex_fn >= 0x80000008) {
|
||||||
// This block seems bugged.
|
// Get number of cores. This is a bit complicated. Following AMD manual here.
|
||||||
nFeatureInfo2 = CPUInfo[1]; // ECX
|
__cpuid(cpu_id, 0x80000008);
|
||||||
bSSE5 = (nFeatureInfo2 & (1 << 11)) ? true : false;
|
int apic_id_core_id_size = (cpu_id[2] >> 12) & 0xF;
|
||||||
bLZCNT = (nFeatureInfo2 & (1 << 5)) ? true : false;
|
if (apic_id_core_id_size == 0) {
|
||||||
bSSE4A = (nFeatureInfo2 & (1 << 6)) ? true : false;
|
// Use what AMD calls the "legacy method" to determine # of cores.
|
||||||
bLAHFSAHF64 = (nFeatureInfo2 & (1 << 0)) ? true : false;
|
if (HTT) {
|
||||||
|
num_cores = logical_cpu_count;
|
||||||
CPU64bit = (CPUInfo[2] & (1 << 29)) ? true : false;
|
} else {
|
||||||
}
|
num_cores = 1;
|
||||||
else if (i == 0x80000002)
|
|
||||||
{
|
|
||||||
memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
|
|
||||||
}
|
|
||||||
else if (i == 0x80000003)
|
|
||||||
{
|
|
||||||
memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
|
|
||||||
}
|
|
||||||
else if (i == 0x80000004)
|
|
||||||
{
|
|
||||||
memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
|
|
||||||
}
|
|
||||||
else if (i == 0x80000006)
|
|
||||||
{
|
|
||||||
nCacheLineSize = CPUInfo[2] & 0xff;
|
|
||||||
nL2Associativity = (CPUInfo[2] >> 12) & 0xf;
|
|
||||||
nCacheSizeK = (CPUInfo[2] >> 16) & 0xffff;
|
|
||||||
}
|
|
||||||
else if (i == 0x80000008)
|
|
||||||
{
|
|
||||||
int numLSB = (CPUInfo[2] >> 12) & 0xF;
|
|
||||||
numCores = 1 << numLSB;
|
|
||||||
//int coresPerDie = CPUInfo[2] & 0xFF;
|
|
||||||
// numCores = coresPerDie;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Use AMD's new method.
|
||||||
|
num_cores = (cpu_id[2] & 0xFF) + 1;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
// Wild guess
|
||||||
// Display all the information in user-friendly format.
|
if (logical_cpu_count)
|
||||||
// printf_s("\n\nCPU String: %s\n", CPUString);
|
num_cores = logical_cpu_count;
|
||||||
|
|
||||||
if (nIds < 1)
|
|
||||||
{
|
|
||||||
bOldCPU = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
nIds = 1;
|
|
||||||
bx87FPUOnChip = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bVirtual_8086ModeEnhancement = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bDebuggingExtensions = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bPageSizeExtensions = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bTimeStampCounter = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bRDMSRandWRMSRSupport = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bPhysicalAddressExtensions = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bMachineCheckException = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bCMPXCHG8BInstruction = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bAPICOnChip = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bUnknown1 = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bSYSENTERandSYSEXIT = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bMemoryTypeRangeRegisters = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bPTEGlobalBit = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bMachineCheckArchitecture = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bConditionalMove_CompareInstruction = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bPageAttributeTable = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bPageSizeExtension = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bProcessorSerialNumber = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bCFLUSHExtension = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bUnknown2 = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bDebugStore = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bThermalMonitorandClockCtrl = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bMMXTechnology = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bFXSAVE_FXRSTOR = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bSSE = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bSSE2 = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bSelfSnoop = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bHyper_threadingTechnology = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bThermalMonitor = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bUnknown4 = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
bPendBrkEN = (nFeatureInfo & nIds) ? true : false;
|
|
||||||
nIds <<= 1;
|
|
||||||
|
|
||||||
if (nExIds < 0x80000004)
|
|
||||||
{
|
|
||||||
strcpy(CPUBrandString, "(unknown)");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CPUInfo::Summarize()
|
||||||
|
{
|
||||||
|
std::string sum = StringFromFormat("%s : %i cores. ", cpu_string, num_cores);
|
||||||
|
if (bSSE) sum += "SSE";
|
||||||
|
if (bSSE2) sum += ", SSE2";
|
||||||
|
if (bSSE3) sum += ", SSE3";
|
||||||
|
if (bSSSE3) sum += ", SSSE3";
|
||||||
|
if (bSSE4_1) sum += ", SSE4.1";
|
||||||
|
if (bSSE4_2) sum += ", SSE4.2";
|
||||||
|
if (bLongMode) sum += ", 64-bit support";
|
||||||
|
sum += " (wrong? report)";
|
||||||
|
return sum;
|
||||||
|
}
|
|
@ -18,70 +18,25 @@
|
||||||
#ifndef _CPUDETECT_H
|
#ifndef _CPUDETECT_H
|
||||||
#define _CPUDETECT_H
|
#define _CPUDETECT_H
|
||||||
|
|
||||||
struct CPUInfoStruct
|
enum CPUVendor
|
||||||
{
|
{
|
||||||
bool isAMD;
|
VENDOR_INTEL = 0,
|
||||||
|
VENDOR_AMD = 1,
|
||||||
|
VENDOR_OTHER = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CPUInfo
|
||||||
|
{
|
||||||
|
CPUVendor vendor;
|
||||||
|
|
||||||
|
char cpu_string[0x21];
|
||||||
|
char brand_string[0x41];
|
||||||
bool OS64bit;
|
bool OS64bit;
|
||||||
bool CPU64bit;
|
bool CPU64bit;
|
||||||
bool Mode64bit;
|
bool Mode64bit;
|
||||||
int numCores;
|
|
||||||
|
|
||||||
char CPUString[0x20];
|
bool hyper_threaded;
|
||||||
char CPUBrandString[0x40];
|
int num_cores;
|
||||||
int CPUInfo[4];
|
|
||||||
int nSteppingID;
|
|
||||||
int nModel;
|
|
||||||
int nFamily;
|
|
||||||
int nProcessorType;
|
|
||||||
int nExtendedmodel;
|
|
||||||
int nExtendedfamily;
|
|
||||||
int nBrandIndex;
|
|
||||||
int nCLFLUSHcachelinesize;
|
|
||||||
int nAPICPhysicalID;
|
|
||||||
int nFeatureInfo;
|
|
||||||
int nFeatureInfo2;
|
|
||||||
int nCacheLineSize;
|
|
||||||
int nL2Associativity;
|
|
||||||
int nCacheSizeK;
|
|
||||||
int nRet;
|
|
||||||
unsigned int nIds, nExIds;
|
|
||||||
|
|
||||||
bool bMONITOR_MWAIT;
|
|
||||||
bool bCPLQualifiedDebugStore;
|
|
||||||
bool bThermalMonitor2;
|
|
||||||
|
|
||||||
bool bOldCPU;
|
|
||||||
bool bx87FPUOnChip;
|
|
||||||
bool bVirtual_8086ModeEnhancement;
|
|
||||||
bool bDebuggingExtensions;
|
|
||||||
bool bPageSizeExtensions;
|
|
||||||
bool bTimeStampCounter;
|
|
||||||
bool bRDMSRandWRMSRSupport;
|
|
||||||
bool bPhysicalAddressExtensions;
|
|
||||||
bool bMachineCheckException;
|
|
||||||
bool bCMPXCHG8BInstruction;
|
|
||||||
bool bAPICOnChip;
|
|
||||||
bool bUnknown1;
|
|
||||||
bool bSYSENTERandSYSEXIT;
|
|
||||||
bool bMemoryTypeRangeRegisters;
|
|
||||||
bool bPTEGlobalBit;
|
|
||||||
bool bMachineCheckArchitecture;
|
|
||||||
bool bConditionalMove_CompareInstruction;
|
|
||||||
bool bPageAttributeTable;
|
|
||||||
bool bPageSizeExtension;
|
|
||||||
bool bProcessorSerialNumber;
|
|
||||||
bool bCFLUSHExtension;
|
|
||||||
bool bUnknown2;
|
|
||||||
bool bDebugStore;
|
|
||||||
bool bThermalMonitorandClockCtrl;
|
|
||||||
bool bMMXTechnology;
|
|
||||||
bool bFXSAVE_FXRSTOR;
|
|
||||||
bool bSelfSnoop;
|
|
||||||
bool bHyper_threadingTechnology;
|
|
||||||
bool bThermalMonitor;
|
|
||||||
bool bUnknown4;
|
|
||||||
bool bPendBrkEN;
|
|
||||||
|
|
||||||
bool bSSE;
|
bool bSSE;
|
||||||
bool bSSE2;
|
bool bSSE2;
|
||||||
|
@ -90,16 +45,17 @@ struct CPUInfoStruct
|
||||||
bool bPOPCNT;
|
bool bPOPCNT;
|
||||||
bool bSSE4_1;
|
bool bSSE4_1;
|
||||||
bool bSSE4_2;
|
bool bSSE4_2;
|
||||||
bool bSSE5;
|
|
||||||
bool bLZCNT;
|
bool bLZCNT;
|
||||||
bool bSSE4A;
|
bool bSSE4A;
|
||||||
bool bLAHFSAHF64;
|
bool bLAHFSAHF64;
|
||||||
|
bool bLongMode;
|
||||||
|
|
||||||
void Detect();
|
void Detect();
|
||||||
|
std::string Summarize();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern CPUInfoStruct cpu_info;
|
extern CPUInfo cpu_info;
|
||||||
|
|
||||||
inline void DetectCPU() {cpu_info.Detect();}
|
inline void DetectCPU() {cpu_info.Detect();}
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ bool Init(const SCoreStartupParameter _CoreParameter)
|
||||||
// all right ... here we go
|
// all right ... here we go
|
||||||
Host_SetWaitCursor(false);
|
Host_SetWaitCursor(false);
|
||||||
|
|
||||||
DisplayMessage(cpu_info.CPUBrandString, 3000);
|
DisplayMessage("CPU: " + cpu_info.Summarize(), 8000);
|
||||||
DisplayMessage(_CoreParameter.m_strFilename, 3000);
|
DisplayMessage(_CoreParameter.m_strFilename, 3000);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue