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

📄 cpu_info.cpp

📁 墨香最新私服
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	// Attempt to get a starting tick count.
	QueryPerformanceCounter (&liEnd);
	
	// Get the difference...  NB: This is in seconds....
	QueryPerformanceFrequency (&liCountsPerSecond);
	dDifference = (((double) liEnd.QuadPart - (double) liStart.QuadPart) / (double) liCountsPerSecond.QuadPart);
	
	// Calculate the clock speed.
	if (ChipID.Family == 3) {
		// 80386 processors....  Loop time is 115 cycles!
		dFrequency = (((CLASSICAL_CPU_FREQ_LOOP * 115) / dDifference) / 1048576);
	} else if (ChipID.Family == 4) {
		// 80486 processors....  Loop time is 47 cycles!
		dFrequency = (((CLASSICAL_CPU_FREQ_LOOP * 47) / dDifference) / 1048576);
	} else if (ChipID.Family == 5) {
		// Pentium processors....  Loop time is 43 cycles!
		dFrequency = (((CLASSICAL_CPU_FREQ_LOOP * 43) / dDifference) / 1048576);
	}
	
	// Save the clock speed.
	Features.CPUSpeed = (int) dFrequency;
	
	return true;
}

bool __cdecl CPUInfo::RetrieveCPUExtendedLevelSupport (int CPULevelToCheck)
{
	int MaxCPUExtendedLevel = 0;
	
	// The extended CPUID is supported by various vendors starting with the following CPU models: 
	//
	//		Manufacturer & Chip Name			|		Family		 Model		Revision
	//
	//		AMD K6, K6-2						|		   5		   6			x		
	//		Cyrix GXm, Cyrix III "Joshua"		|		   5		   4			x
	//		IDT C6-2							|		   5		   8			x
	//		VIA Cyrix III						|		   6		   5			x
	//		Transmeta Crusoe					|		   5		   x			x
	//		Intel Pentium 4						|		   f		   x			x
	//
	
	// We check to see if a supported processor is present...
	if (ChipManufacturer == AMD) {
		if (ChipID.Family < 5) return false;
		if ((ChipID.Family == 5) && (ChipID.Model < 6)) return false;
	} else if (ChipManufacturer == Cyrix) {
		if (ChipID.Family < 5) return false;
		if ((ChipID.Family == 5) && (ChipID.Model < 4)) return false;
		if ((ChipID.Family == 6) && (ChipID.Model < 5)) return false;
	} else if (ChipManufacturer == IDT) {
		if (ChipID.Family < 5) return false;
		if ((ChipID.Family == 5) && (ChipID.Model < 8)) return false;
	} else if (ChipManufacturer == Transmeta) {
		if (ChipID.Family < 5) return false;
	} else if (ChipManufacturer == Intel) {
		if (ChipID.Family < 0xf) return false;
	}
	
	// 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 = 0x80000000 --> eax: maximum supported extended level
				mov eax,0x80000000
				CPUID_INSTRUCTION
				mov MaxCPUExtendedLevel, 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;
	}
	
	// Now we have to check the level wanted vs level returned...
	int nLevelWanted = (CPULevelToCheck & 0x7FFFFFFF);
	int nLevelReturn = (MaxCPUExtendedLevel & 0x7FFFFFFF);
	
	// Check to see if the level provided is supported...
	if (nLevelWanted > nLevelReturn) return false;
	
	return true;
}

bool __cdecl CPUInfo::RetrieveExtendedCPUFeatures ()
{
	int CPUExtendedFeatures = 0;
	
	// Check that we are not using an Intel processor as it does not support this.
	if (ChipManufacturer == Intel) return false;
	
	// Check to see if what we are about to do is supported...
	if (!RetrieveCPUExtendedLevelSupport (0x80000001)) return false;
	
	// 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 = 0x80000001 --> 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,0x80000001
				CPUID_INSTRUCTION
				mov CPUExtendedFeatures, 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;
	}
	
	// Retrieve the extended features of CPU present.
	Features.ExtendedFeatures.Has3DNow =		((CPUExtendedFeatures & 0x80000000) != 0);	// 3DNow Present --> Bit 31.
	Features.ExtendedFeatures.Has3DNowPlus =	((CPUExtendedFeatures & 0x40000000) != 0);	// 3DNow+ Present -- > Bit 30.
	Features.ExtendedFeatures.HasSSEMMX =		((CPUExtendedFeatures & 0x00400000) != 0);	// SSE MMX Present --> Bit 22.
	Features.ExtendedFeatures.SupportsMP =		((CPUExtendedFeatures & 0x00080000) != 0);	// MP Capable -- > Bit 19.
	
	// Retrieve AMD specific extended features.
	if (ChipManufacturer == AMD) {
		Features.ExtendedFeatures.HasMMXPlus =	((CPUExtendedFeatures &	0x00400000) != 0);	// AMD specific: MMX-SSE --> Bit 22
	}
	
	// Retrieve Cyrix specific extended features.
	if (ChipManufacturer == Cyrix) {
		Features.ExtendedFeatures.HasMMXPlus =	((CPUExtendedFeatures &	0x01000000) != 0);	// Cyrix specific: Extended MMX --> Bit 24
	}
	
	return true;
}

bool __cdecl CPUInfo::RetrieveProcessorSerialNumber ()
{
	int SerialNumber[3];
	
	// Check to see if the processor supports the processor serial number.
	if (!Features.HasSerial) return false;
	
	// 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 = 3 --> ebx: top 32 bits are the processor signature bits --> NB: Transmeta only ?!?
				;			  ecx: middle 32 bits are the processor signature bits
				;			  edx: bottom 32 bits are the processor signature bits
				mov eax, 3
				CPUID_INSTRUCTION
				mov SerialNumber[0 * TYPE int], ebx
				mov SerialNumber[1 * TYPE int], ecx
				mov SerialNumber[2 * 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;
	}
	
	// Process the returned information.
	sprintf (ChipID.SerialNumber, "%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x",
		((SerialNumber[0] & 0xff000000) >> 24),
		((SerialNumber[0] & 0x00ff0000) >> 16),
		((SerialNumber[0] & 0x0000ff00) >> 8),
		((SerialNumber[0] & 0x000000ff) >> 0),
		((SerialNumber[1] & 0xff000000) >> 24),
		((SerialNumber[1] & 0x00ff0000) >> 16),
		((SerialNumber[1] & 0x0000ff00) >> 8),
		((SerialNumber[1] & 0x000000ff) >> 0),
		((SerialNumber[2] & 0xff000000) >> 24),
		((SerialNumber[2] & 0x00ff0000) >> 16),
		((SerialNumber[2] & 0x0000ff00) >> 8),
		((SerialNumber[2] & 0x000000ff) >> 0));
	
	return true;
}

bool __cdecl CPUInfo::RetrieveCPUPowerManagement ()
{	
	int CPUPowerManagement = 0;
	
	// Check to see if what we are about to do is supported...
	if (!RetrieveCPUExtendedLevelSupport (0x80000007)) {
		Features.ExtendedFeatures.PowerManagement.HasFrequencyID = false;
		Features.ExtendedFeatures.PowerManagement.HasVoltageID = false;
		Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = false;
		return false;
	}
	
	// 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 = 0x80000007 --> edx: get processor power management
				mov eax,0x80000007
				CPUID_INSTRUCTION
				mov CPUPowerManagement, 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;
	}
	
	// Check for the power management capabilities of the CPU.
	Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode =	((CPUPowerManagement & 0x00000001) != 0);
	Features.ExtendedFeatures.PowerManagement.HasFrequencyID =		((CPUPowerManagement & 0x00000002) != 0);
	Features.ExtendedFeatures.PowerManagement.HasVoltageID =		((CPUPowerManagement & 0x00000004) != 0);
	
	return true;
}

bool __cdecl CPUInfo::RetrieveExtendedCPUIdentity ()
{
	int ProcessorNameStartPos = 0;
	int CPUExtendedIdentity[12];
	
	// Check to see if what we are about to do is supported...
	if (!RetrieveCPUExtendedLevelSupport (0x80000002)) return false;
	if (!RetrieveCPUExtendedLevelSupport (0x80000003)) return false;
	if (!RetrieveCPUExtendedLevelSupport (0x80000004)) return false;
	
	// 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 = 0x80000002 --> eax, ebx, ecx, edx: get processor name string (part 1)
				mov eax,0x80000002
				CPUID_INSTRUCTION
				mov CPUExtendedIdentity[0 * TYPE int], eax
				mov CPUExtendedIdentity[1 * TYPE int], ebx
				mov CPUExtendedIdentity[2 * TYPE int], ecx
				mov CPUExtendedIdentity[3 * TYPE int], edx
				
				; <<CPUID>> 
				; eax = 0x80000003 --> eax, ebx, ecx, edx: get processor name string (part 2)
				mov eax,0x80000003
				CPUID_INSTRUCTION
				mov CPUExtendedIdentity[4 * TYPE int], eax
				mov CPUExtendedIdentity[5 * TYPE int], ebx
				mov CPUExtendedIdentity[6 * TYPE int], ecx
				mov CPUExtendedIdentity[7 * TYPE int], edx
				
				; <<CPUID>> 
				; eax = 0x80000004 --> eax, ebx, ecx, edx: get processor name string (part 3)
				mov eax,0x80000004
				CPUID_INSTRUCTION
				mov CPUExtendedIdentity[8 * TYPE int], eax
				mov CPUExtendedIdentity[9 * TYPE int], ebx
				mov CPUExtendedIdentity[10 * TYPE int], ecx
				mov CPUExtendedIdentity[11 * 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;
	}
	
	// Process the returned information.
	memcpy (ChipID.ProcessorName, &(CPUExtendedIdentity[0]), sizeof (int));
	memcpy (&(ChipID.ProcessorName[4]), &(CPUExtendedIdentity[1]), sizeof (int));
	memcpy (&(ChipID.ProcessorName[8]), &(CPUExtendedIdentity[2]), sizeof (int));
	memcpy (&(ChipID.ProcessorName[12]), &(CPUExtendedIdentity[3]), sizeof (int));
	memcpy (&(ChipID.ProcessorName[16]), &(CPUExtendedIdentity[4]), sizeof (int));
	memcpy (&(ChipID.ProcessorName[20]), &(CPUExtendedIdentity[5]), sizeof (int));
	memcpy (&(ChipID.ProcessorName[24]), &(CPUExtendedIdentity[6]), sizeof (int));
	memcpy (&(ChipID.ProcessorName[28]), &(CPUExtendedIdentity[7]), sizeof (int));
	memcpy (&(ChipID.ProcessorName[32]), &(CPUExtendedIdentity[8]), sizeof (int));
	memcpy (&(ChipID.ProcessorName[36]), &(CPUExtendedIdentity[9]), sizeof (int));
	memcpy (&(ChipID.ProcessorName[40]), &(CPUExtendedIdentity[10]), sizeof (int));
	memcpy (&(ChipID.ProcessorName[44]), &(CPUExtendedIdentity[11]), sizeof (int));
	ChipID.ProcessorName[48] = '\0';
	
	// Because some manufacturers (<cough>Intel</cough>) have leading white space - we have to post-process the name.
	if (ChipManufacturer == Intel) {
		for (int nCounter = 0; nCounter < CHIPNAME_STRING_LENGTH; nCounter ++) {
			// There will either be NULL (\0) or spaces ( ) as the leading characters.
			if ((ChipID.ProcessorName[nCounter] != '\0') && (ChipID.ProcessorName[nCounter] != ' ')) {
				// We have found the starting position of the name.
				ProcessorNameStartPos = nCounter;
				
				// Terminate the loop.
				break;
			}
		}
		
		// Check to see if there is any white space at the start.
		if (ProcessorNameStartPos == 0) return true;
		
		// Now move the name forward so that there is no white space.
		memmove (ChipID.ProcessorName, &(ChipID.ProcessorName[ProcessorNameStartPos]), (CHIPNAME_STRING_LENGTH - ProcessorNameStartPos));
	}
	
	return true;
}

bool _cdecl CPUInfo::RetrieveClassicalCPUIdentity ()
{
	// Start by decided which manufacturer we are using....
	switch (ChipManufacturer) {
	case Intel:
		// Check the family / model / revision to determine the CPU ID.
		switch (ChipID.Family) {
		case 3:
			sprintf (ChipID.ProcessorName, "Newer i80386 family"); 
			break;
		case 4:
			switch (ChipID.Model) {
			case 0: STORE_CLASSICAL_NAME ("i80486DX-25/33"); break;
			case 1: STORE_CLASSICAL_NAME ("i80486DX-50"); break;
			case 2: STORE_CLASSICAL_NAME ("i80486SX"); break;
			case 3: STORE_CLASSICAL_NAME ("i80486DX2"); break;
			case 4: STORE_CLASSICAL_NAME ("i80486SL"); break;
			case 5: STORE_CLASSICAL_NAME ("i80486SX2"); break;
			case 7: STORE_CLASSICAL_NAME ("i80486DX2 WriteBack"); break;
			case 8: STORE_CLASSICAL_NAME ("i80486DX4"); break;
			case 9: STORE_CLASSICAL_NAME ("i80486DX4 WriteBack"); break;
			default: STORE_CLASSICAL_NAME ("Unknown 80486 family"); return false;
			}
			break;
			case 5:
				switch (ChipID.Model) {
				case 0: STORE_CLASSICAL_NAME ("P5 A-Step"); break;
				case 1: STORE_CLASSICAL_NAME ("P5"); break;
				case 2: STORE_CLASSICAL_NAME ("P54C"); break;
				case 3: STORE_CLASSICAL_NAME ("P24T OverDrive"); break;
				case 4: STORE_CLASSICAL_NAME ("P55C"); break;
				case 7: STORE_CLASSICAL_NAME ("P54C"); break;
				case 8: STORE_CLASSICAL_NAME ("P55C (0.25祄)"); break;
				default: STORE_CLASSICAL_NAME ("Unknown Pentium

⌨️ 快捷键说明

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