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

📄 cpu_info.cpp

📁 s/w handheld terminal ( based on Cygnal 8051f230)
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// Camel - CPU Identifying Tool
// Copyright (C) 2002, Iain Chesworth
// 
// 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; either version 2 of the License, or
// any later version.

// 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 for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "cpu_info.h"

// --------------------------------------------------------
//
//         Constructor Functions - CPUInfo Class
//
// --------------------------------------------------------

CPUInfo::CPUInfo ()
{
	// Check to see if this processor supports CPUID.
	if (DoesCPUSupportCPUID ()) {
		// Retrieve the CPU details.
		RetrieveCPUIdentity ();
		RetrieveCPUFeatures ();
		if (!RetrieveCPUClockSpeed ()) RetrieveClassicalCPUClockSpeed ();

		// Attempt to retrieve cache information.
		if (!RetrieveCPUCacheDetails ()) RetrieveClassicalCPUCacheDetails ();

		// Retrieve the extended CPU details.
		if (!RetrieveExtendedCPUIdentity ()) RetrieveClassicalCPUIdentity ();
		RetrieveExtendedCPUFeatures ();

		// Now attempt to retrieve the serial number (if possible).
		RetrieveProcessorSerialNumber ();
	}
}

CPUInfo::~CPUInfo ()
{
}

// --------------------------------------------------------
//
//         Public Functions - CPUInfo Class
//
// --------------------------------------------------------

char * CPUInfo::GetVendorString ()
{
	// Return the vendor string.
	return ChipID.Vendor;
}

char * CPUInfo::GetVendorID ()
{
	// Return the vendor ID.
	switch (ChipManufacturer) {
		case Intel:
			return "Intel Corporation";
		case AMD:
			return "Advanced Micro Devices";
		case NSC:
			return "National Semiconductor";
		case Cyrix:
			return "Cyrix Corp., VIA Inc.";
		case NexGen:
			return "NexGen Inc., Advanced Micro Devices";
		case IDT:
			return "IDT\\Centaur, Via Inc.";
		case UMC:
			return "United Microelectronics Corp.";
		case Rise:
			return "Rise";
		case Transmeta:
			return "Transmeta";
		default:
			return "Unknown Manufacturer";
	}
}

char * CPUInfo::GetTypeID ()
{
	// Return the type ID of the CPU.
	char * szTypeID = new char [32];
	itoa (ChipID.Type, szTypeID, 10);
	return szTypeID;
}

char * CPUInfo::GetFamilyID ()
{
	// Return the family of the CPU present.
	char * szFamilyID = new char [32];
	itoa (ChipID.Family, szFamilyID, 10);
	return szFamilyID;
}

char * CPUInfo::GetModelID ()
{
	// Return the model of CPU present.
	char * szModelID = new char [32];
	itoa (ChipID.Model, szModelID, 10);
	return szModelID;
}

char * CPUInfo::GetSteppingCode ()
{
	// Return the stepping code of the CPU present.
	char * szSteppingCode = new char [32];
	itoa (ChipID.Revision, szSteppingCode, 10);
	return szSteppingCode;
}

char * CPUInfo::GetExtendedProcessorName ()
{
	// Return the stepping code of the CPU present.
	return ChipID.ProcessorName;
}

char * CPUInfo::GetProcessorSerialNumber ()
{
	// Return the serial number of the processor in hexadecimal: xxxx-xxxx-xxxx-xxxx-xxxx-xxxx.
	return ChipID.SerialNumber;
}

int CPUInfo::GetLogicalProcessorsPerPhysical ()
{
	// Return the logical processors per physical.
	return Features.ExtendedFeatures.LogicalProcessorsPerPhysical;
}

int CPUInfo::GetProcessorClockFrequency ()
{
	// Return the processor clock frequency.
	if (Speed != NULL)
		return Speed->CPUSpeedInMHz;
	else 
		// Display the error condition.
		return -1;
}

int CPUInfo::GetProcessorAPICID ()
{
	// Return the APIC ID.
	return Features.ExtendedFeatures.APIC_ID;
}

int CPUInfo::GetProcessorCacheXSize (DWORD dwCacheID)
{
	// Return the chosen cache size.
	switch (dwCacheID) {
		case L1CACHE_FEATURE:
			return Features.L1CacheSize;

		case L2CACHE_FEATURE:
			return Features.L2CacheSize;

		case L3CACHE_FEATURE:
			return Features.L3CacheSize;
	}

	// The user did something strange just return and error.
	return -1;
}

bool CPUInfo::DoesCPUSupportFeature (DWORD dwFeature)
{
	bool bHasFeature = false;

	// Check for MMX instructions.
	if (((dwFeature & MMX_FEATURE) != 0) && Features.HasMMX) bHasFeature = true;

	// Check for MMX+ instructions.
	if (((dwFeature & MMX_PLUS_FEATURE) != 0) && Features.ExtendedFeatures.HasMMXPlus) bHasFeature = true;

	// Check for SSE FP instructions.
	if (((dwFeature & SSE_FEATURE) != 0) && Features.HasSSE) bHasFeature = true;

	// Check for SSE FP instructions.
	if (((dwFeature & SSE_FP_FEATURE) != 0) && Features.HasSSEFP) bHasFeature = true;

	// Check for SSE MMX instructions.
	if (((dwFeature & SSE_MMX_FEATURE) != 0) && Features.ExtendedFeatures.HasSSEMMX) bHasFeature = true;

	// Check for SSE2 instructions.
	if (((dwFeature & SSE2_FEATURE) != 0) && Features.HasSSE2) bHasFeature = true;

	// Check for 3DNow! instructions.
	if (((dwFeature & AMD_3DNOW_FEATURE) != 0) && Features.ExtendedFeatures.Has3DNow) bHasFeature = true;

	// Check for 3DNow+ instructions.
	if (((dwFeature & AMD_3DNOW_PLUS_FEATURE) != 0) && Features.ExtendedFeatures.Has3DNowPlus) bHasFeature = true;

	// Check for IA64 instructions.
	if (((dwFeature & IA64_FEATURE) != 0) && Features.HasIA64) bHasFeature = true;

	// Check for MP capable.
	if (((dwFeature & MP_CAPABLE) != 0) && Features.ExtendedFeatures.SupportsMP) bHasFeature = true;

	// Check for a serial number for the processor.
	if (((dwFeature & SERIALNUMBER_FEATURE) != 0) && Features.HasSerial) bHasFeature = true;

	// Check for a local APIC in the processor.
	if (((dwFeature & APIC_FEATURE) != 0) && Features.HasAPIC) bHasFeature = true;

	// Check for CMOV instructions.
	if (((dwFeature & CMOV_FEATURE) != 0) && Features.HasCMOV) bHasFeature = true;

	// Check for MTRR instructions.
	if (((dwFeature & MTRR_FEATURE) != 0) && Features.HasMTRR) bHasFeature = true;

	// Check for L1 cache size.
	if (((dwFeature & L1CACHE_FEATURE) != 0) && (Features.L1CacheSize != -1)) bHasFeature = true;

	// Check for L2 cache size.
	if (((dwFeature & L2CACHE_FEATURE) != 0) && (Features.L2CacheSize != -1)) bHasFeature = true;

	// Check for L3 cache size.
	if (((dwFeature & L3CACHE_FEATURE) != 0) && (Features.L3CacheSize != -1)) bHasFeature = true;

	// Check for ACPI capability.
	if (((dwFeature & ACPI_FEATURE) != 0) && Features.HasACPI) bHasFeature = true;

	// Check for thermal monitor support.
	if (((dwFeature & THERMALMONITOR_FEATURE) != 0) && Features.HasThermal) bHasFeature = true;

	// Check for temperature sensing diode support.
	if (((dwFeature & TEMPSENSEDIODE_FEATURE) != 0) && Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode) bHasFeature = true;

	// Check for frequency ID support.
	if (((dwFeature & FREQUENCYID_FEATURE) != 0) && Features.ExtendedFeatures.PowerManagement.HasFrequencyID) bHasFeature = true;

	// Check for voltage ID support.
	if (((dwFeature & VOLTAGEID_FREQUENCY) != 0) && Features.ExtendedFeatures.PowerManagement.HasVoltageID) bHasFeature = true;

	return bHasFeature;
}

// --------------------------------------------------------
//
//         Private Functions - CPUInfo Class
//
// --------------------------------------------------------

bool __cdecl CPUInfo::DoesCPUSupportCPUID ()
{
	int CPUIDPresent = 0;

#ifdef _WIN32 
	
	// Use SEH to determine CPUID presence
    __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>> 
            mov eax, 0
			CPUID_INSTRUCTION

#ifdef CPUID_AWARE_COMPILER
			pop edx
			pop ecx
			pop ebx
			pop eax
#endif
        }
    }

	// A generic catch-all just to be sure...
	__except (1) {
        // Stop the class from trying to use CPUID again!
        CPUIDPresent = false;
		return false;
    }
#else
    // The "right" way, which doesn't work under certain Windows versions
	__try {
		_asm {
			pushfd                      ; save EFLAGS to stack.
			pop     eax                 ; store EFLAGS in eax.
			mov     edx, eax            ; save in ebx for testing later.
			xor     eax, 0200000h       ; switch bit 21.
			push    eax                 ; copy "changed" value to stack.
			popfd                       ; save "changed" eax to EFLAGS.
			pushfd
			pop     eax
			xor     eax, edx            ; See if bit changeable.
			jnz     short cpuid_present ; if so, mark 
			mov     eax, -1             ; CPUID not present - disable its usage
			jmp     no_features

	cpuid_present:
			mov		eax, 0				; CPUID capable CPU - enable its usage.
			
	no_features:
			mov     CPUIDPresent, eax	; Save the value in eax to a variable.
		}
	}
	
	// A generic catch-all just to be sure...
	__except (1) {
		// Stop the class from trying to use CPUID again!
        CPUIDPresent = false;
		return false;
    }
		
#endif

	// Return true to indicate support or false to indicate lack.
	return (CPUIDPresent == 0) ? true : false;
}

bool __cdecl CPUInfo::RetrieveCPUFeatures ()
{
	int CPUFeatures = 0;
	int CPUAdvanced = 0;

	// 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 = 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 CPUFeatures, edx
			mov CPUAdvanced, ebx

#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 features of CPU present.
	Features.HasFPU =		((CPUFeatures & 0x00000001) != 0);		// FPU Present --> Bit 0
	Features.HasTSC =		((CPUFeatures & 0x00000010) != 0);		// TSC Present --> Bit 4
	Features.HasAPIC =		((CPUFeatures & 0x00000200) != 0);		// APIC Present --> Bit 9
	Features.HasMTRR =		((CPUFeatures & 0x00001000) != 0);		// MTRR Present --> Bit 12
	Features.HasCMOV =		((CPUFeatures & 0x00008000) != 0);		// CMOV Present --> Bit 15
	Features.HasSerial =	((CPUFeatures & 0x00040000) != 0);		// Serial Present --> Bit 18
	Features.HasACPI =		((CPUFeatures & 0x00400000) != 0);		// ACPI Capable --> Bit 22
    Features.HasMMX =		((CPUFeatures & 0x00800000) != 0);		// MMX Present --> Bit 23
	Features.HasSSE =		((CPUFeatures & 0x02000000) != 0);		// SSE Present --> Bit 25
	Features.HasSSE2 =		((CPUFeatures & 0x04000000) != 0);		// SSE2 Present --> Bit 26
	Features.HasThermal =	((CPUFeatures & 0x20000000) != 0);		// Thermal Monitor Present --> Bit 29
	Features.HasIA64 =		((CPUFeatures & 0x40000000) != 0);		// IA64 Present --> Bit 30

	// Retrieve extended SSE capabilities if SSE is available.
	if (Features.HasSSE) {
		
		// Attempt to __try some SSE FP instructions.
		__try {
			// Perform: orps xmm0, xmm0
			_asm {
				_emit 0x0f
	    		_emit 0x56
	    		_emit 0xc0	
			}

			// SSE FP capable processor.
			Features.HasSSEFP = true;
	    }
	    
		// A generic catch-all just to be sure...
		__except (1) {
	    	// bad instruction - processor or OS cannot handle SSE FP.
			Features.HasSSEFP = false;
		}
	} else {
		// Set the advanced SSE capabilities to not available.
		Features.HasSSEFP = false;
	}

	// Retrieve Intel specific extended features.

⌨️ 快捷键说明

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