| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | // 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>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __linux__
 | 
					
						
							|  |  |  | //#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; | 
					
						
							|  |  |  | 			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) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2008-07-20 21:20:22 +00:00
										 |  |  | 			// This block seems bugged.
 | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | 			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)"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 |