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

📄 cpu_info.cpp

📁 s/w handheld terminal ( based on Cygnal 8051f230)
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	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 + -