⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpu_info.cpp

📁 墨香最新私服
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		}
	} else {
		// Set the advanced SSE capabilities to not available.
		Features.HasSSEFP = false;
	}
	
	// Retrieve Intel specific extended features.
	if (ChipManufacturer == Intel) {
		Features.ExtendedFeatures.SupportsHyperthreading =	((CPUFeatures &	0x10000000) != 0);	// Intel specific: Hyperthreading --> Bit 28
		Features.ExtendedFeatures.LogicalProcessorsPerPhysical = (Features.ExtendedFeatures.SupportsHyperthreading) ? ((CPUAdvanced & 0x00FF0000) >> 16) : 1;
		
		if ((Features.ExtendedFeatures.SupportsHyperthreading) && (Features.HasAPIC)){
			// Retrieve APIC information if there is one present.
			Features.ExtendedFeatures.APIC_ID = ((CPUAdvanced & 0xFF000000) >> 24);
		}
	}
	
	return true;
}

bool __cdecl CPUInfo::RetrieveCPUIdentity ()
{
	int CPUVendor[3];
	int CPUSignature;
	
	// Use assembly to detect CPUID information...
	__try {
		_asm {
#ifdef CPUID_AWARE_COMPILER
			; we must push/pop the registers <<CPUID>> writes to, as the
				; optimiser doesn't know about <<CPUID>>, and so doesn't expect
				; these registers to change.
				push eax
				push ebx
				push ecx
				push edx
#endif
				; <<CPUID>>
				; eax = 0 --> eax: maximum value of CPUID instruction.
				;			  ebx: part 1 of 3; CPU signature.
				;			  edx: part 2 of 3; CPU signature.
				;			  ecx: part 3 of 3; CPU signature.
				mov eax, 0
				CPUID_INSTRUCTION
				mov CPUVendor[0 * TYPE int], ebx
				mov CPUVendor[1 * TYPE int], edx
				mov CPUVendor[2 * TYPE int], ecx
				
				; <<CPUID>> 
				; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
				;			  ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
				;			  edx: CPU feature flags
				mov eax,1
				CPUID_INSTRUCTION
				mov CPUSignature, eax
				
#ifdef CPUID_AWARE_COMPILER
				pop edx
				pop ecx
				pop ebx
				pop eax
#endif
		}
	}
	
	// A generic catch-all just to be sure...
	__except (1) {
		return false;
	}
	
	// Process the returned information.
	memcpy (ChipID.Vendor, &(CPUVendor[0]), sizeof (int));
	memcpy (&(ChipID.Vendor[4]), &(CPUVendor[1]), sizeof (int));
	memcpy (&(ChipID.Vendor[8]), &(CPUVendor[2]), sizeof (int));
	ChipID.Vendor[12] = '\0';
	
	// Attempt to retrieve the manufacturer from the vendor string.
	if (strcmp (ChipID.Vendor, "GenuineIntel") == 0)		ChipManufacturer = Intel;				// Intel Corp.
	else if (strcmp (ChipID.Vendor, "UMC UMC UMC ") == 0)	ChipManufacturer = UMC;					// United Microelectronics Corp.
	else if (strcmp (ChipID.Vendor, "AuthenticAMD") == 0)	ChipManufacturer = AMD;					// Advanced Micro Devices
	else if (strcmp (ChipID.Vendor, "AMD ISBETTER") == 0)	ChipManufacturer = AMD;					// Advanced Micro Devices (1994)
	else if (strcmp (ChipID.Vendor, "CyrixInstead") == 0)	ChipManufacturer = Cyrix;				// Cyrix Corp., VIA Inc.
	else if (strcmp (ChipID.Vendor, "NexGenDriven") == 0)	ChipManufacturer = NexGen;				// NexGen Inc. (now AMD)
	else if (strcmp (ChipID.Vendor, "CentaurHauls") == 0)	ChipManufacturer = IDT;					// IDT/Centaur (now VIA)
	else if (strcmp (ChipID.Vendor, "RiseRiseRise") == 0)	ChipManufacturer = Rise;				// Rise
	else if (strcmp (ChipID.Vendor, "GenuineTMx86") == 0)	ChipManufacturer = Transmeta;			// Transmeta
	else if (strcmp (ChipID.Vendor, "TransmetaCPU") == 0)	ChipManufacturer = Transmeta;			// Transmeta
	else if (strcmp (ChipID.Vendor, "Geode By NSC") == 0)	ChipManufacturer = NSC;					// National Semiconductor
	else													ChipManufacturer = UnknownManufacturer;	// Unknown manufacturer
	
	// Retrieve the family of CPU present.
	ChipID.ExtendedFamily =		((CPUSignature & 0x0FF00000) >> 20);	// Bits 27..20 Used
	ChipID.ExtendedModel =		((CPUSignature & 0x000F0000) >> 16);	// Bits 19..16 Used
	ChipID.Type =				((CPUSignature & 0x0000F000) >> 12);	// Bits 15..12 Used
	ChipID.Family =				((CPUSignature & 0x00000F00) >> 8);		// Bits 11..8 Used
	ChipID.Model =				((CPUSignature & 0x000000F0) >> 4);		// Bits 7..4 Used
	ChipID.Revision =			((CPUSignature & 0x0000000F) >> 0);		// Bits 3..0 Used
	
	return true;
}

bool __cdecl CPUInfo::RetrieveCPUCacheDetails ()
{
	int L1Cache[4] = { 0, 0, 0, 0 };
	int L2Cache[4] = { 0, 0, 0, 0 };
	
	// Check to see if what we are about to do is supported...
	if (RetrieveCPUExtendedLevelSupport (0x80000005)) {
		// Use assembly to retrieve the L1 cache information ...
		__try {
			_asm {
#ifdef CPUID_AWARE_COMPILER
				; we must push/pop the registers <<CPUID>> writes to, as the
					; optimiser doesn't know about <<CPUID>>, and so doesn't expect
					; these registers to change.
					push eax
					push ebx
					push ecx
					push edx
#endif
					; <<CPUID>>
					; eax = 0x80000005 --> eax: L1 cache information - Part 1 of 4.
					;					   ebx: L1 cache information - Part 2 of 4.
					;					   edx: L1 cache information - Part 3 of 4.
					;			 		   ecx: L1 cache information - Part 4 of 4.
					mov eax, 0x80000005
					CPUID_INSTRUCTION
					mov L1Cache[0 * TYPE int], eax
					mov L1Cache[1 * TYPE int], ebx
					mov L1Cache[2 * TYPE int], ecx
					mov L1Cache[3 * TYPE int], edx
					
#ifdef CPUID_AWARE_COMPILER
					pop edx
					pop ecx
					pop ebx
					pop eax
#endif
			}
		}
		
		// A generic catch-all just to be sure...
		__except (1) {
			return false;
		}
		
		// Save the L1 data cache size (in KB) from ecx: bits 31..24 as well as data cache size from edx: bits 31..24.
		Features.L1CacheSize = ((L1Cache[2] & 0xFF000000) >> 24);
		Features.L1CacheSize += ((L1Cache[3] & 0xFF000000) >> 24);
	} else {
		// Store -1 to indicate the cache could not be queried.
		Features.L1CacheSize = -1;
	}
	
	// Check to see if what we are about to do is supported...
	if (RetrieveCPUExtendedLevelSupport (0x80000006)) {
		// Use assembly to retrieve the L2 cache information ...
		__try {
			_asm {
#ifdef CPUID_AWARE_COMPILER
				; we must push/pop the registers <<CPUID>> writes to, as the
					; optimiser doesn't know about <<CPUID>>, and so doesn't expect
					; these registers to change.
					push eax
					push ebx
					push ecx
					push edx
#endif
					; <<CPUID>>
					; eax = 0x80000006 --> eax: L2 cache information - Part 1 of 4.
					;					   ebx: L2 cache information - Part 2 of 4.
					;					   edx: L2 cache information - Part 3 of 4.
					;			 		   ecx: L2 cache information - Part 4 of 4.
					mov eax, 0x80000006
					CPUID_INSTRUCTION
					mov L2Cache[0 * TYPE int], eax
					mov L2Cache[1 * TYPE int], ebx
					mov L2Cache[2 * TYPE int], ecx
					mov L2Cache[3 * TYPE int], edx
					
#ifdef CPUID_AWARE_COMPILER
					pop edx
					pop ecx
					pop ebx
					pop eax
#endif			
			}
		}
		
		// A generic catch-all just to be sure...
		__except (1) {
			return false;
		}
		
		// Save the L2 unified cache size (in KB) from ecx: bits 31..16.
		Features.L2CacheSize = ((L2Cache[2] & 0xFFFF0000) >> 16);
	} else {
		// Store -1 to indicate the cache could not be queried.
		Features.L2CacheSize = -1;
	}
	
	// Define L3 as being not present as we cannot test for it.
	Features.L3CacheSize = -1;
	
	// Return failure if we cannot detect either cache with this method.
	return ((Features.L1CacheSize == -1) && (Features.L2CacheSize == -1)) ? false : true;
}

bool __cdecl CPUInfo::RetrieveClassicalCPUCacheDetails ()
{
	int TLBCode = -1, TLBData = -1, L1Code = -1, L1Data = -1, L1Trace = -1, L2Unified = -1, L3Unified = -1;
	int TLBCacheData[4] = { 0, 0, 0, 0 };
	int TLBPassCounter = 0;
	int TLBCacheUnit = 0;
	
	do {
		// Use assembly to retrieve the L2 cache information ...
		__try {
			_asm {
#ifdef CPUID_AWARE_COMPILER
				; we must push/pop the registers <<CPUID>> writes to, as the
					; optimiser doesn't know about <<CPUID>>, and so doesn't expect
					; these registers to change.
					push eax
					push ebx
					push ecx
					push edx
#endif
					; <<CPUID>>
					; eax = 2 --> eax: TLB and cache information - Part 1 of 4.
					;			  ebx: TLB and cache information - Part 2 of 4.
					;			  ecx: TLB and cache information - Part 3 of 4.
					;			  edx: TLB and cache information - Part 4 of 4.
					mov eax, 2
					CPUID_INSTRUCTION
					mov TLBCacheData[0 * TYPE int], eax
					mov TLBCacheData[1 * TYPE int], ebx
					mov TLBCacheData[2 * TYPE int], ecx
					mov TLBCacheData[3 * TYPE int], edx
					
#ifdef CPUID_AWARE_COMPILER
					pop edx
					pop ecx
					pop ebx
					pop eax
#endif
			}
		}
		
		// A generic catch-all just to be sure...
		__except (1) {
			return false;
		}
		
		int bob = ((TLBCacheData[0] & 0x00FF0000) >> 16);
		
		// Process the returned TLB and cache information.
		for (int nCounter = 0; nCounter < TLBCACHE_INFO_UNITS; nCounter ++) {
			
			// First of all - decide which unit we are dealing with.
			switch (nCounter) {
				
				// eax: bits 8..15 : bits 16..23 : bits 24..31
			case 0: TLBCacheUnit = ((TLBCacheData[0] & 0x0000FF00) >> 8); break;
			case 1: TLBCacheUnit = ((TLBCacheData[0] & 0x00FF0000) >> 16); break;
			case 2: TLBCacheUnit = ((TLBCacheData[0] & 0xFF000000) >> 24); break;
				
				// ebx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
			case 3: TLBCacheUnit = ((TLBCacheData[1] & 0x000000FF) >> 0); break;
			case 4: TLBCacheUnit = ((TLBCacheData[1] & 0x0000FF00) >> 8); break;
			case 5: TLBCacheUnit = ((TLBCacheData[1] & 0x00FF0000) >> 16); break;
			case 6: TLBCacheUnit = ((TLBCacheData[1] & 0xFF000000) >> 24); break;
				
				// ecx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
			case 7: TLBCacheUnit = ((TLBCacheData[2] & 0x000000FF) >> 0); break;
			case 8: TLBCacheUnit = ((TLBCacheData[2] & 0x0000FF00) >> 8); break;
			case 9: TLBCacheUnit = ((TLBCacheData[2] & 0x00FF0000) >> 16); break;
			case 10: TLBCacheUnit = ((TLBCacheData[2] & 0xFF000000) >> 24); break;
				
				// edx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
			case 11: TLBCacheUnit = ((TLBCacheData[3] & 0x000000FF) >> 0); break;
			case 12: TLBCacheUnit = ((TLBCacheData[3] & 0x0000FF00) >> 8); break;
			case 13: TLBCacheUnit = ((TLBCacheData[3] & 0x00FF0000) >> 16); break;
			case 14: TLBCacheUnit = ((TLBCacheData[3] & 0xFF000000) >> 24); break;
				
				// Default case - an error has occured.
			default: return false;
			}
			
			// Now process the resulting unit to see what it means....
			switch (TLBCacheUnit) {
			case 0x00: break;
			case 0x01: STORE_TLBCACHE_INFO (TLBCode, 4); break;
			case 0x02: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
			case 0x03: STORE_TLBCACHE_INFO (TLBData, 4); break;
			case 0x04: STORE_TLBCACHE_INFO (TLBData, 4096); break;
			case 0x06: STORE_TLBCACHE_INFO (L1Code, 8); break;
			case 0x08: STORE_TLBCACHE_INFO (L1Code, 16); break;
			case 0x0a: STORE_TLBCACHE_INFO (L1Data, 8); break;
			case 0x0c: STORE_TLBCACHE_INFO (L1Data, 16); break;
			case 0x10: STORE_TLBCACHE_INFO (L1Data, 16); break;			// <-- FIXME: IA-64 Only
			case 0x15: STORE_TLBCACHE_INFO (L1Code, 16); break;			// <-- FIXME: IA-64 Only
			case 0x1a: STORE_TLBCACHE_INFO (L2Unified, 96); break;		// <-- FIXME: IA-64 Only
			case 0x22: STORE_TLBCACHE_INFO (L3Unified, 512); break;
			case 0x23: STORE_TLBCACHE_INFO (L3Unified, 1024); break;
			case 0x25: STORE_TLBCACHE_INFO (L3Unified, 2048); break;
			case 0x29: STORE_TLBCACHE_INFO (L3Unified, 4096); break;
			case 0x39: STORE_TLBCACHE_INFO (L2Unified, 128); break;
			case 0x3c: STORE_TLBCACHE_INFO (L2Unified, 256); break;
			case 0x40: STORE_TLBCACHE_INFO (L2Unified, 0); break;		// <-- FIXME: No integrated L2 cache (P6 core) or L3 cache (P4 core).
			case 0x41: STORE_TLBCACHE_INFO (L2Unified, 128); break;
			case 0x42: STORE_TLBCACHE_INFO (L2Unified, 256); break;
			case 0x43: STORE_TLBCACHE_INFO (L2Unified, 512); break;
			case 0x44: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
			case 0x45: STORE_TLBCACHE_INFO (L2Unified, 2048); break;
			case 0x50: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
			case 0x51: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
			case 0x52: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
			case 0x5b: STORE_TLBCACHE_INFO (TLBData, 4096); break;
			case 0x5c: STORE_TLBCACHE_INFO (TLBData, 4096); break;
			case 0x5d: STORE_TLBCACHE_INFO (TLBData, 4096); break;
			case 0x66: STORE_TLBCACHE_INFO (L1Data, 8); break;
			case 0x67: STORE_TLBCACHE_INFO (L1Data, 16); break;
			case 0x68: STORE_TLBCACHE_INFO (L1Data, 32); break;
			case 0x70: STORE_TLBCACHE_INFO (L1Trace, 12); break;
			case 0x71: STORE_TLBCACHE_INFO (L1Trace, 16); break;
			case 0x72: STORE_TLBCACHE_INFO (L1Trace, 32); break;
			case 0x77: STORE_TLBCACHE_INFO (L1Code, 16); break;			// <-- FIXME: IA-64 Only
			case 0x79: STORE_TLBCACHE_INFO (L2Unified, 128); break;
			case 0x7a: STORE_TLBCACHE_INFO (L2Unified, 256); break;
			case 0x7b: STORE_TLBCACHE_INFO (L2Unified, 512); break;
			case 0x7c: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
			case 0x7e: STORE_TLBCACHE_INFO (L2Unified, 256); break;
			case 0x81: STORE_TLBCACHE_INFO (L2Unified, 128); break;
			case 0x82: STORE_TLBCACHE_INFO (L2Unified, 256); break;
			case 0x83: STORE_TLBCACHE_INFO (L2Unified, 512); break;
			case 0x84: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
			case 0x85: STORE_TLBCACHE_INFO (L2Unified, 2048); break;
			case 0x88: STORE_TLBCACHE_INFO (L3Unified, 2048); break;	// <-- FIXME: IA-64 Only
			case 0x89: STORE_TLBCACHE_INFO (L3Unified, 4096); break;	// <-- FIXME: IA-64 Only
			case 0x8a: STORE_TLBCACHE_INFO (L3Unified, 8192); break;	// <-- FIXME: IA-64 Only
			case 0x8d: STORE_TLBCACHE_INFO (L3Unified, 3096); break;	// <-- FIXME: IA-64 Only
			case 0x90: STORE_TLBCACHE_INFO (TLBCode, 262144); break;	// <-- FIXME: IA-64 Only
			case 0x96: STORE_TLBCACHE_INFO (TLBCode, 262144); break;	// <-- FIXME: IA-64 Only
			case 0x9b: STORE_TLBCACHE_INFO (TLBCode, 262144); break;	// <-- FIXME: IA-64 Only
				
				// Default case - an error has occured.
			default: return false;
			}
		}
		
		// Increment the TLB pass counter.
		TLBPassCounter ++;
		
	} while ((TLBCacheData[0] & 0x000000FF) > TLBPassCounter);
	
	// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
	if ((L1Code == -1) && (L1Data == -1) && (L1Trace == -1)) Features.L1CacheSize = -1;
	else if ((L1Code == -1) && (L1Data == -1) && (L1Trace != -1)) Features.L1CacheSize = L1Trace;
	else if ((L1Code != -1) && (L1Data == -1)) Features.L1CacheSize = L1Code;
	else if ((L1Code == -1) && (L1Data != -1)) Features.L1CacheSize = L1Data;
	else if ((L1Code != -1) && (L1Data != -1)) Features.L1CacheSize = L1Code + L1Data;
	else Features.L1CacheSize = -1;
	
	// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
	if (L2Unified == -1) Features.L2CacheSize = -1;
	else Features.L2CacheSize = L2Unified;
	
	// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
	if (L3Unified == -1) Features.L3CacheSize = -1;
	else Features.L3CacheSize = L3Unified;
	
	return true;
}

bool __cdecl CPUInfo::RetrieveCPUClockSpeed ()
{
	// First of all we check to see if the RDTSC (0x0F, 0x31) instruction is supported.
	if (!Features.HasTSC) return false;
	
	// Get the clock speed.
	Speed = new CPUSpeed ();
	if (Speed == NULL) return false;
	
	return true;
}

bool __cdecl CPUInfo::RetrieveClassicalCPUClockSpeed ()
{
	LARGE_INTEGER liStart, liEnd, liCountsPerSecond;
	double dFrequency, dDifference;
	
	// Attempt to get a starting tick count.
	QueryPerformanceCounter (&liStart);
	
	__try {
		_asm {
			mov eax, 0x80000000
				mov ebx, CLASSICAL_CPU_FREQ_LOOP
Timer_Loop: 
			bsf ecx,eax
				dec ebx
				jnz Timer_Loop
		}	
	}
	
	// A generic catch-all just to be sure...
	__except (1) {
		return false;
	}
	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -