164 lines
3.2 KiB
C++
164 lines
3.2 KiB
C++
/*=============================================================================
|
|
CPUDetect.cpp : CPU detection.
|
|
Copyright 2001 Crytek Studios. All Rights Reserved.
|
|
|
|
Revision history:
|
|
* Created by Honitch Andrey
|
|
|
|
=============================================================================*/
|
|
|
|
#ifndef __CPUDETECT_H__
|
|
#define __CPUDETECT_H__
|
|
|
|
//-------------------------------------------------------
|
|
/// Cpu class
|
|
//-------------------------------------------------------
|
|
|
|
#define MAX_CPU 32
|
|
|
|
/// Cpu Features
|
|
#define CFI_FPUEMULATION 1
|
|
#define CFI_MMX 2
|
|
#define CFI_3DNOW 4
|
|
#define CFI_SSE 8
|
|
#define CFI_SSE2 0x10
|
|
|
|
/// Type of Cpu Vendor.
|
|
enum ECpuVendor
|
|
{
|
|
eCVendor_Unknown,
|
|
eCVendor_Intel,
|
|
eCVendor_Cyrix,
|
|
eCVendor_AMD,
|
|
eCVendor_Centaur,
|
|
eCVendor_NexGen,
|
|
eCVendor_UMC,
|
|
eCVendor_M68K
|
|
};
|
|
|
|
/// Type of Cpu Model.
|
|
enum ECpuModel
|
|
{
|
|
eCpu_Unknown,
|
|
|
|
eCpu_8086,
|
|
eCpu_80286,
|
|
eCpu_80386,
|
|
eCpu_80486,
|
|
eCpu_Pentium,
|
|
eCpu_PentiumPro,
|
|
eCpu_Pentium2,
|
|
eCpu_Pentium3,
|
|
eCpu_Pentium4,
|
|
eCpu_Pentium2Xeon,
|
|
eCpu_Pentium3Xeon,
|
|
eCpu_Celeron,
|
|
eCpu_CeleronA,
|
|
|
|
eCpu_Am5x86,
|
|
eCpu_AmK5,
|
|
eCpu_AmK6,
|
|
eCpu_AmK6_2,
|
|
eCpu_AmK6_3,
|
|
eCpu_AmK6_3D,
|
|
eCpu_AmAthlon,
|
|
eCpu_AmDuron,
|
|
|
|
eCpu_CyrixMediaGX,
|
|
eCpu_Cyrix6x86,
|
|
eCpu_CyrixGXm,
|
|
eCpu_Cyrix6x86MX,
|
|
|
|
eCpu_CenWinChip,
|
|
eCpu_CenWinChip2,
|
|
};
|
|
|
|
struct SCpu
|
|
{
|
|
ECpuVendor meVendor;
|
|
ECpuModel meModel;
|
|
unsigned long mFeatures;
|
|
bool mbSerialPresent;
|
|
char mSerialNumber[30];
|
|
int mFamily;
|
|
int mModel;
|
|
int mStepping;
|
|
char mVendor[64];
|
|
char mCpuType[64];
|
|
char mFpuType[64];
|
|
int mSpeed;
|
|
double m_SecondsPerCycle;
|
|
};
|
|
|
|
class CCpuFeatures
|
|
{
|
|
private:
|
|
int m_NumSystemProcessors;
|
|
int m_NumAvailProcessors;
|
|
bool m_bOS_ISSE;
|
|
bool m_bOS_ISSE_EXCEPTIONS;
|
|
public:
|
|
|
|
SCpu m_Cpu[MAX_CPU];
|
|
|
|
public:
|
|
CCpuFeatures()
|
|
{
|
|
m_NumSystemProcessors = 0;
|
|
m_NumAvailProcessors = 0;
|
|
m_bOS_ISSE = 0;
|
|
m_bOS_ISSE_EXCEPTIONS = 0;
|
|
}
|
|
|
|
void Detect(void);
|
|
bool hasSSE() { return (m_Cpu[0].mFeatures & CFI_SSE) != 0; }
|
|
bool hasSSE2() { return (m_Cpu[0].mFeatures & CFI_SSE2) != 0; }
|
|
bool has3DNow() { return (m_Cpu[0].mFeatures & CFI_3DNOW) != 0; }
|
|
bool hasMMX() { return (m_Cpu[0].mFeatures & CFI_MMX) != 0; }
|
|
};
|
|
|
|
#if defined(WIN64) || defined(LINUX64)
|
|
inline bool IsAMD64()
|
|
{
|
|
#ifdef _AMD64_
|
|
return true;
|
|
#else
|
|
#error not supported here
|
|
#endif
|
|
}
|
|
#else
|
|
inline bool
|
|
IsAMD64()
|
|
{
|
|
#if defined(LINUX32)
|
|
return false;
|
|
#else
|
|
_asm
|
|
{
|
|
// make sure cpuid is available
|
|
pushfd // save EFLAGS
|
|
pop eax // store EFLAGS in EAX
|
|
mov ebx, eax // save in EBX for later testing
|
|
xor eax, 00200000h // toggle bit 21
|
|
push eax // push to stack
|
|
popfd // save changed EAX to EFLAGS
|
|
pushfd // push EFLAGS to TOS
|
|
pop eax // store EFLAGS in EAX
|
|
cmp eax, ebx // see if bit 21 has changed
|
|
mov eax, 0 // clear eax to return "false"
|
|
jz QUIT // if no change, no CPUID
|
|
|
|
// perform AMD64 detection
|
|
mov eax, 0x80000001 // load argument "Processor Signature and AMD Features" to call cpuid
|
|
cpuid // call cpuid
|
|
mov eax, edx // edx contains "AMD Feature Support" flags
|
|
shr eax, 29 // test bit 29 (support for "Long Mode")
|
|
and eax, 0x00000001 // mask out bit for proper return value
|
|
QUIT:
|
|
}
|
|
#endif
|
|
}
|
|
#endif // WIN32
|
|
|
|
#endif
|