simplified the code implementing Sys_GetProcessorId (and removed the inline asm)

This commit is contained in:
myT 2016-12-31 02:16:36 +01:00
parent 511291bb97
commit d449e35e2d

View file

@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../qcommon/q_shared.h" #include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h" #include "../qcommon/qcommon.h"
#include "win_local.h" #include "win_local.h"
#include <intrin.h>
int Sys_Milliseconds() int Sys_Milliseconds()
@ -36,134 +37,56 @@ int Sys_Milliseconds()
} }
// disable all optimizations temporarily so this code works correctly!
#ifdef _MSC_VER
#pragma optimize( "", off )
#pragma warning(disable : 4748) // don't fkn WHINE about using that pragma
#endif
static void CPUID( int func, unsigned regs[4] )
{
unsigned regEAX, regEBX, regECX, regEDX;
__asm mov eax, func
__asm __emit 00fh
__asm __emit 0a2h
__asm mov regEAX, eax
__asm mov regEBX, ebx
__asm mov regECX, ecx
__asm mov regEDX, edx
regs[0] = regEAX;
regs[1] = regEBX;
regs[2] = regECX;
regs[3] = regEDX;
}
static qbool IsPentium()
{
__asm
{
pushfd // save eflags
pop eax
test eax, 0x00200000 // check ID bit
jz set21 // bit 21 is not set, so jump to set_21
and eax, 0xffdfffff // clear bit 21
push eax // save new value in register
popfd // store new value in flags
pushfd
pop eax
test eax, 0x00200000 // check ID bit
jz good
jmp err // cpuid not supported
set21:
or eax, 0x00200000 // set ID bit
push eax // store new value
popfd // store new value in EFLAGS
pushfd
pop eax
test eax, 0x00200000 // if bit 21 is on
jnz good
jmp err
}
err:
return qfalse;
good:
return qtrue;
}
static const char* CPU_Name() static const char* CPU_Name()
{ {
static unsigned regs[4]; static int regs[4];
CPUID( 0, regs );
__cpuid( regs, 0 );
regs[0] = regs[1]; regs[0] = regs[1];
regs[1] = regs[3]; regs[1] = regs[3];
regs[3] = 0; regs[3] = 0;
return (const char*)regs; return (const char*)regs;
} }
static int CPU_Cores()
{
unsigned regs[4];
CPUID( 1, regs );
return ((regs[1] & 0x00FF0000) >> 16);
}
struct CPU_FeatureBit { const char* s; int reg, bit; } CPU_FeatureBits[] = struct CPU_FeatureBit { const char* s; int reg, bit; } CPU_FeatureBits[] =
{ {
#if id386 // x64 always has those anyway
{ " MMX", 3, 23 }, { " MMX", 3, 23 },
{ " SSE", 3, 25 }, { " SSE", 3, 25 },
{ " SSE2", 3, 26 }, { " SSE2", 3, 26 },
{ " SSE3", 2, 26 }, #endif
{ 0 } { " SSE3", 2, 0 },
{ " SSSE3", 2, 9 },
{ " SSE4.1", 2, 19 },
{ " SSE4.2", 2, 20 },
{ " AVX", 2, 28 }
// for AVX2 and later, you'd need to call cpuid with eax=7 and ecx=0 ("extended features")
}; };
static const int CPU_FeatureBitCount = sizeof(CPU_FeatureBits) / sizeof(CPU_FeatureBits[0]);
int Sys_GetProcessorId() int Sys_GetProcessorId()
{ {
#if defined _M_ALPHA char s[256] = "";
return CPUID_AXP;
#elif !defined _M_IX86
return CPUID_GENERIC;
#else
// verify we're at least a Pentium or 486 w/ CPUID support
if ( !IsPentium() ) {
Cvar_Set( "sys_cpustring", "x86 (pre-Pentium)" );
return CPUID_UNSUPPORTED;
}
char s[64] = "";
Q_strcat( s, sizeof(s), CPU_Name() ); Q_strcat( s, sizeof(s), CPU_Name() );
if (CPU_Cores() > 1) int regs[4];
Q_strcat( s, sizeof(s), va(" %d cores", CPU_Cores()) ); __cpuid( regs, 1 );
unsigned regs[4]; for (int i = 0; i < CPU_FeatureBitCount; ++i) {
CPUID( 1, regs );
for (int i = 0; CPU_FeatureBits[i].s; ++i) {
if (regs[CPU_FeatureBits[i].reg] & (1 << regs[CPU_FeatureBits[i].bit])) { if (regs[CPU_FeatureBits[i].reg] & (1 << regs[CPU_FeatureBits[i].bit])) {
Q_strcat( s, sizeof(s), CPU_FeatureBits[i].s ); Q_strcat( s, sizeof(s), CPU_FeatureBits[i].s );
} }
} }
Cvar_Set( "sys_cpustring", s ); Cvar_Set( "sys_cpustring", s );
return CPUID_GENERIC; return CPUID_GENERIC;
#endif
} }
#ifdef _MSC_VER
#pragma optimize( "", on )
#endif
const char* Sys_GetCurrentUser() const char* Sys_GetCurrentUser()
{ {
return "player"; return "player";