247 lines
7.0 KiB
C++
247 lines
7.0 KiB
C++
// Copyright (C) 2003-2008 Dolphin Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official SVN repository and contact information can be found at
|
|
// http://code.google.com/p/dolphin-emu/
|
|
|
|
#ifdef _WIN32
|
|
#include <intrin.h>
|
|
#else
|
|
|
|
//#include <config/i386/cpuid.h>
|
|
#include <xmmintrin.h>
|
|
void __cpuid(int info[4], int x) {}
|
|
|
|
#endif
|
|
|
|
#include <memory.h>
|
|
|
|
#include "Common.h"
|
|
#include "CPUDetect.h"
|
|
|
|
// This code was adapted from an example in MSDN:
|
|
CPUInfoStruct cpu_info;
|
|
|
|
void CPUInfoStruct::Detect()
|
|
{
|
|
#ifdef _M_IX86
|
|
Mode64bit = false;
|
|
#elif defined (_M_X64)
|
|
Mode64bit = true;
|
|
OS64bit = true;
|
|
#endif
|
|
numCores = 1;
|
|
|
|
#ifdef _WIN32
|
|
#ifdef _M_IX86
|
|
BOOL f64 = FALSE;
|
|
OS64bit = IsWow64Process(GetCurrentProcess(), &f64) && f64;
|
|
#endif
|
|
#endif
|
|
|
|
// __cpuid with an InfoType argument of 0 returns the number of
|
|
// valid Ids in CPUInfo[0] and the CPU identification string in
|
|
// 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;
|
|
}
|
|
else
|
|
{
|
|
isAMD = true;
|
|
}
|
|
|
|
// Get the information associated with each valid Id
|
|
for (unsigned int i = 0; i <= nIds; ++i)
|
|
{
|
|
__cpuid(CPUInfo, i);
|
|
|
|
// Interpret CPU feature information.
|
|
if (i == 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;
|
|
bSSE3NewInstructions = (CPUInfo[2] & 0x1) || false;
|
|
bSSSE3NewInstructions = (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))
|
|
{
|
|
bPOPCNT = true;
|
|
}
|
|
|
|
if (CPUInfo[2] & (1 << 19))
|
|
{
|
|
bSSE4_1 = true;
|
|
}
|
|
|
|
if (CPUInfo[2] & (1 << 20))
|
|
{
|
|
bSSE4_2 = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Calling __cpuid with 0x80000000 as the InfoType argument
|
|
// gets the number of valid extended IDs.
|
|
__cpuid(CPUInfo, 0x80000000);
|
|
nExIds = CPUInfo[0];
|
|
memset(CPUBrandString, 0, sizeof(CPUBrandString));
|
|
|
|
// Get the information associated with each extended ID.
|
|
for (unsigned int i = 0x80000000; i <= nExIds; ++i)
|
|
{
|
|
__cpuid(CPUInfo, i);
|
|
|
|
// Interpret CPU brand string and cache information.
|
|
if (i == 0x80000001)
|
|
{
|
|
// This block seems bugged.
|
|
nFeatureInfo2 = CPUInfo[1]; // ECX
|
|
bSSE5 = (nFeatureInfo2 & (1 << 11)) ? true : false;
|
|
bLZCNT = (nFeatureInfo2 & (1 << 5)) ? true : false;
|
|
bSSE4A = (nFeatureInfo2 & (1 << 6)) ? true : false;
|
|
bLAHFSAHF64 = (nFeatureInfo2 & (1 << 0)) ? true : false;
|
|
|
|
CPU64bit = (CPUInfo[2] & (1 << 29)) ? true : false;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
// Display all the information in user-friendly format.
|
|
// printf_s("\n\nCPU String: %s\n", CPUString);
|
|
|
|
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;
|
|
bSSEExtensions = (nFeatureInfo & nIds) ? true : false;
|
|
nIds <<= 1;
|
|
bSSE2Extensions = (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)");
|
|
}
|
|
}
|
|
|
|
|