mirror of
https://github.com/DrBeef/Raze.git
synced 2024-12-15 23:21:21 +00:00
718112a8fe
Currently none of these is being used, but eventually they will, once more code gets ported over. So it's better to have them right away and avoid editing the project file too much, only to revert that later.
218 lines
4.4 KiB
C
218 lines
4.4 KiB
C
/* CpuArch.c -- CPU specific code
|
|
2018-02-18: Igor Pavlov : Public domain */
|
|
|
|
#include "Precomp.h"
|
|
|
|
#include "CpuArch.h"
|
|
|
|
#ifdef MY_CPU_X86_OR_AMD64
|
|
|
|
#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
|
|
#define USE_ASM
|
|
#endif
|
|
|
|
#if !defined(USE_ASM) && _MSC_VER >= 1500
|
|
#include <intrin.h>
|
|
#endif
|
|
|
|
#if defined(USE_ASM) && !defined(MY_CPU_AMD64)
|
|
static UInt32 CheckFlag(UInt32 flag)
|
|
{
|
|
#ifdef _MSC_VER
|
|
__asm pushfd;
|
|
__asm pop EAX;
|
|
__asm mov EDX, EAX;
|
|
__asm xor EAX, flag;
|
|
__asm push EAX;
|
|
__asm popfd;
|
|
__asm pushfd;
|
|
__asm pop EAX;
|
|
__asm xor EAX, EDX;
|
|
__asm push EDX;
|
|
__asm popfd;
|
|
__asm and flag, EAX;
|
|
#else
|
|
__asm__ __volatile__ (
|
|
"pushf\n\t"
|
|
"pop %%EAX\n\t"
|
|
"movl %%EAX,%%EDX\n\t"
|
|
"xorl %0,%%EAX\n\t"
|
|
"push %%EAX\n\t"
|
|
"popf\n\t"
|
|
"pushf\n\t"
|
|
"pop %%EAX\n\t"
|
|
"xorl %%EDX,%%EAX\n\t"
|
|
"push %%EDX\n\t"
|
|
"popf\n\t"
|
|
"andl %%EAX, %0\n\t":
|
|
"=c" (flag) : "c" (flag) :
|
|
"%eax", "%edx");
|
|
#endif
|
|
return flag;
|
|
}
|
|
#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
|
|
#else
|
|
#define CHECK_CPUID_IS_SUPPORTED
|
|
#endif
|
|
|
|
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
|
|
{
|
|
#ifdef USE_ASM
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
UInt32 a2, b2, c2, d2;
|
|
__asm xor EBX, EBX;
|
|
__asm xor ECX, ECX;
|
|
__asm xor EDX, EDX;
|
|
__asm mov EAX, function;
|
|
__asm cpuid;
|
|
__asm mov a2, EAX;
|
|
__asm mov b2, EBX;
|
|
__asm mov c2, ECX;
|
|
__asm mov d2, EDX;
|
|
|
|
*a = a2;
|
|
*b = b2;
|
|
*c = c2;
|
|
*d = d2;
|
|
|
|
#else
|
|
|
|
__asm__ __volatile__ (
|
|
#if defined(MY_CPU_AMD64) && defined(__PIC__)
|
|
"mov %%rbx, %%rdi;"
|
|
"cpuid;"
|
|
"xchg %%rbx, %%rdi;"
|
|
: "=a" (*a) ,
|
|
"=D" (*b) ,
|
|
#elif defined(MY_CPU_X86) && defined(__PIC__)
|
|
"mov %%ebx, %%edi;"
|
|
"cpuid;"
|
|
"xchgl %%ebx, %%edi;"
|
|
: "=a" (*a) ,
|
|
"=D" (*b) ,
|
|
#else
|
|
"cpuid"
|
|
: "=a" (*a) ,
|
|
"=b" (*b) ,
|
|
#endif
|
|
"=c" (*c) ,
|
|
"=d" (*d)
|
|
: "0" (function)) ;
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
int CPUInfo[4];
|
|
__cpuid(CPUInfo, function);
|
|
*a = CPUInfo[0];
|
|
*b = CPUInfo[1];
|
|
*c = CPUInfo[2];
|
|
*d = CPUInfo[3];
|
|
|
|
#endif
|
|
}
|
|
|
|
BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p)
|
|
{
|
|
CHECK_CPUID_IS_SUPPORTED
|
|
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
|
|
MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
|
|
return True;
|
|
}
|
|
|
|
static const UInt32 kVendors[][3] =
|
|
{
|
|
{ 0x756E6547, 0x49656E69, 0x6C65746E},
|
|
{ 0x68747541, 0x69746E65, 0x444D4163},
|
|
{ 0x746E6543, 0x48727561, 0x736C7561}
|
|
};
|
|
|
|
int x86cpuid_GetFirm(const Cx86cpuid *p)
|
|
{
|
|
unsigned i;
|
|
for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
|
|
{
|
|
const UInt32 *v = kVendors[i];
|
|
if (v[0] == p->vendor[0] &&
|
|
v[1] == p->vendor[1] &&
|
|
v[2] == p->vendor[2])
|
|
return (int)i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
BoolInt CPU_Is_InOrder()
|
|
{
|
|
Cx86cpuid p;
|
|
int firm;
|
|
UInt32 family, model;
|
|
if (!x86cpuid_CheckAndRead(&p))
|
|
return True;
|
|
|
|
family = x86cpuid_GetFamily(p.ver);
|
|
model = x86cpuid_GetModel(p.ver);
|
|
|
|
firm = x86cpuid_GetFirm(&p);
|
|
|
|
switch (firm)
|
|
{
|
|
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
|
|
/* In-Order Atom CPU */
|
|
model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */
|
|
|| model == 0x26 /* 45 nm, Z6xx */
|
|
|| model == 0x27 /* 32 nm, Z2460 */
|
|
|| model == 0x35 /* 32 nm, Z2760 */
|
|
|| model == 0x36 /* 32 nm, N2xxx, D2xxx */
|
|
)));
|
|
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
|
|
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
|
|
}
|
|
return True;
|
|
}
|
|
|
|
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
|
|
#include <windows.h>
|
|
static BoolInt CPU_Sys_Is_SSE_Supported()
|
|
{
|
|
OSVERSIONINFO vi;
|
|
vi.dwOSVersionInfoSize = sizeof(vi);
|
|
if (!GetVersionEx(&vi))
|
|
return False;
|
|
return (vi.dwMajorVersion >= 5);
|
|
}
|
|
#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
|
|
#else
|
|
#define CHECK_SYS_SSE_SUPPORT
|
|
#endif
|
|
|
|
BoolInt CPU_Is_Aes_Supported()
|
|
{
|
|
Cx86cpuid p;
|
|
CHECK_SYS_SSE_SUPPORT
|
|
if (!x86cpuid_CheckAndRead(&p))
|
|
return False;
|
|
return (p.c >> 25) & 1;
|
|
}
|
|
|
|
BoolInt CPU_IsSupported_PageGB()
|
|
{
|
|
Cx86cpuid cpuid;
|
|
if (!x86cpuid_CheckAndRead(&cpuid))
|
|
return False;
|
|
{
|
|
UInt32 d[4] = { 0 };
|
|
MyCPUID(0x80000000, &d[0], &d[1], &d[2], &d[3]);
|
|
if (d[0] < 0x80000001)
|
|
return False;
|
|
}
|
|
{
|
|
UInt32 d[4] = { 0 };
|
|
MyCPUID(0x80000001, &d[0], &d[1], &d[2], &d[3]);
|
|
return (d[3] >> 26) & 1;
|
|
}
|
|
}
|
|
|
|
#endif
|