cpuinfo: Removed code duplication, cached CPUID details.

This commit is contained in:
Ryan C. Gordon 2016-11-16 22:49:04 -05:00
parent 6fe15d6347
commit 7592b40b39
1 changed files with 66 additions and 189 deletions

View File

@ -78,6 +78,7 @@ static int
CPU_haveCPUID(void) CPU_haveCPUID(void)
{ {
int has_CPUID = 0; int has_CPUID = 0;
/* *INDENT-OFF* */ /* *INDENT-OFF* */
#ifndef SDL_CPUINFO_DISABLED #ifndef SDL_CPUINFO_DISABLED
#if defined(__GNUC__) && defined(i386) #if defined(__GNUC__) && defined(i386)
@ -215,59 +216,47 @@ done:
a = b = c = d = 0 a = b = c = d = 0
#endif #endif
static int static int CPU_CPUIDFeatures[4];
CPU_getCPUIDFeatures(void) static int CPU_CPUIDMaxFunction = 0;
static SDL_bool CPU_OSSavesYMM = SDL_FALSE;
static void
CPU_calcCPUIDFeatures(void)
{ {
int features = 0; static SDL_bool checked = SDL_FALSE;
int a, b, c, d; if (!checked) {
checked = SDL_TRUE;
if (CPU_haveCPUID()) {
int a, b, c, d;
cpuid(0, a, b, c, d);
CPU_CPUIDMaxFunction = a;
if (CPU_CPUIDMaxFunction >= 1) {
cpuid(1, a, b, c, d);
CPU_CPUIDFeatures[0] = a;
CPU_CPUIDFeatures[1] = b;
CPU_CPUIDFeatures[2] = c;
CPU_CPUIDFeatures[3] = d;
cpuid(0, a, b, c, d); /* Check to make sure we can call xgetbv */
if (a >= 1) { if (c & 0x08000000) {
cpuid(1, a, b, c, d); /* Call xgetbv to see if YMM register state is saved */
features = d;
}
return features;
}
static SDL_bool
CPU_OSSavesYMM(void)
{
int a, b, c, d;
/* Check to make sure we can call xgetbv */
cpuid(0, a, b, c, d);
if (a < 1) {
return SDL_FALSE;
}
cpuid(1, a, b, c, d);
if (!(c & 0x08000000)) {
return SDL_FALSE;
}
/* Call xgetbv to see if YMM register state is saved */
a = 0;
#if defined(__GNUC__) && (defined(i386) || defined(__x86_64__)) #if defined(__GNUC__) && (defined(i386) || defined(__x86_64__))
asm(".byte 0x0f, 0x01, 0xd0" : "=a" (a) : "c" (0) : "%edx"); asm(".byte 0x0f, 0x01, 0xd0" : "=a" (a) : "c" (0) : "%edx");
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) /* VS2010 SP1 */ #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) /* VS2010 SP1 */
a = (int)_xgetbv(0); a = (int)_xgetbv(0);
#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
__asm __asm
{ {
xor ecx, ecx xor ecx, ecx
_asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0 _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0
mov a, eax mov a, eax
} }
#endif #endif
return ((a & 6) == 6) ? SDL_TRUE : SDL_FALSE; CPU_OSSavesYMM = ((a & 6) == 6) ? SDL_TRUE : SDL_FALSE;
} }
}
static int }
CPU_haveRDTSC(void)
{
if (CPU_haveCPUID()) {
return (CPU_getCPUIDFeatures() & 0x00000010);
} }
return 0;
} }
static int static int
@ -299,21 +288,11 @@ CPU_haveAltiVec(void)
return altivec; return altivec;
} }
static int
CPU_haveMMX(void)
{
if (CPU_haveCPUID()) {
return (CPU_getCPUIDFeatures() & 0x00800000);
}
return 0;
}
static int static int
CPU_have3DNow(void) CPU_have3DNow(void)
{ {
if (CPU_haveCPUID()) { if (CPU_CPUIDMaxFunction > 0) { /* that is, do we have CPUID at all? */
int a, b, c, d; int a, b, c, d;
cpuid(0x80000000, a, b, c, d); cpuid(0x80000000, a, b, c, d);
if (a >= 0x80000001) { if (a >= 0x80000001) {
cpuid(0x80000001, a, b, c, d); cpuid(0x80000001, a, b, c, d);
@ -323,95 +302,22 @@ CPU_have3DNow(void)
return 0; return 0;
} }
static int #define CPU_haveRDTSC() (CPU_CPUIDFeatures[3] & 0x00000010)
CPU_haveSSE(void) #define CPU_haveMMX() (CPU_CPUIDFeatures[3] & 0x00800000)
{ #define CPU_haveSSE() (CPU_CPUIDFeatures[3] & 0x02000000)
if (CPU_haveCPUID()) { #define CPU_haveSSE2() (CPU_CPUIDFeatures[3] & 0x04000000)
return (CPU_getCPUIDFeatures() & 0x02000000); #define CPU_haveSSE3() (CPU_CPUIDFeatures[2] & 0x00000001)
} #define CPU_haveSSE41() (CPU_CPUIDFeatures[2] & 0x00080000)
return 0; #define CPU_haveSSE42() (CPU_CPUIDFeatures[2] & 0x00100000)
} #define CPU_haveAVX() (CPU_OSSavesYMM && (CPU_CPUIDFeatures[2] & 0x10000000))
static int
CPU_haveSSE2(void)
{
if (CPU_haveCPUID()) {
return (CPU_getCPUIDFeatures() & 0x04000000);
}
return 0;
}
static int
CPU_haveSSE3(void)
{
if (CPU_haveCPUID()) {
int a, b, c, d;
cpuid(0, a, b, c, d);
if (a >= 1) {
cpuid(1, a, b, c, d);
return (c & 0x00000001);
}
}
return 0;
}
static int
CPU_haveSSE41(void)
{
if (CPU_haveCPUID()) {
int a, b, c, d;
cpuid(0, a, b, c, d);
if (a >= 1) {
cpuid(1, a, b, c, d);
return (c & 0x00080000);
}
}
return 0;
}
static int
CPU_haveSSE42(void)
{
if (CPU_haveCPUID()) {
int a, b, c, d;
cpuid(0, a, b, c, d);
if (a >= 1) {
cpuid(1, a, b, c, d);
return (c & 0x00100000);
}
}
return 0;
}
static int
CPU_haveAVX(void)
{
if (CPU_haveCPUID() && CPU_OSSavesYMM()) {
int a, b, c, d;
cpuid(0, a, b, c, d);
if (a >= 1) {
cpuid(1, a, b, c, d);
return (c & 0x10000000);
}
}
return 0;
}
static int static int
CPU_haveAVX2(void) CPU_haveAVX2(void)
{ {
if (CPU_haveCPUID() && CPU_OSSavesYMM()) { if (CPU_OSSavesYMM && (CPU_CPUIDMaxFunction >= 7)) {
int a, b, c, d; int a, b, c, d;
cpuid(7, a, b, c, d);
cpuid(0, a, b, c, d); return (b & 0x00000020);
if (a >= 7) {
cpuid(7, a, b, c, d);
return (b & 0x00000020);
}
} }
return 0; return 0;
} }
@ -459,7 +365,8 @@ SDL_GetCPUType(void)
if (!SDL_CPUType[0]) { if (!SDL_CPUType[0]) {
int i = 0; int i = 0;
if (CPU_haveCPUID()) { CPU_calcCPUIDFeatures();
if (CPU_CPUIDMaxFunction > 0) { /* do we have CPUID at all? */
int a, b, c, d; int a, b, c, d;
cpuid(0x00000000, a, b, c, d); cpuid(0x00000000, a, b, c, d);
(void) a; (void) a;
@ -496,7 +403,8 @@ SDL_GetCPUName(void)
int i = 0; int i = 0;
int a, b, c, d; int a, b, c, d;
if (CPU_haveCPUID()) { CPU_calcCPUIDFeatures();
if (CPU_CPUIDMaxFunction > 0) { /* do we have CPUID at all? */
cpuid(0x80000000, a, b, c, d); cpuid(0x80000000, a, b, c, d);
if (a >= 0x80000004) { if (a >= 0x80000004) {
cpuid(0x80000002, a, b, c, d); cpuid(0x80000002, a, b, c, d);
@ -584,6 +492,7 @@ static Uint32
SDL_GetCPUFeatures(void) SDL_GetCPUFeatures(void)
{ {
if (SDL_CPUFeatures == 0xFFFFFFFF) { if (SDL_CPUFeatures == 0xFFFFFFFF) {
CPU_calcCPUIDFeatures();
SDL_CPUFeatures = 0; SDL_CPUFeatures = 0;
if (CPU_haveRDTSC()) { if (CPU_haveRDTSC()) {
SDL_CPUFeatures |= CPU_HAS_RDTSC; SDL_CPUFeatures |= CPU_HAS_RDTSC;
@ -622,103 +531,71 @@ SDL_GetCPUFeatures(void)
return SDL_CPUFeatures; return SDL_CPUFeatures;
} }
SDL_bool #define CPU_FEATURE_AVAILABLE(f) ((SDL_GetCPUFeatures() & f) ? SDL_TRUE : SDL_FALSE)
SDL_HasRDTSC(void)
SDL_bool SDL_HasRDTSC(void)
{ {
if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) { return CPU_FEATURE_AVAILABLE(CPU_HAS_RDTSC);
return SDL_TRUE;
}
return SDL_FALSE;
} }
SDL_bool SDL_bool
SDL_HasAltiVec(void) SDL_HasAltiVec(void)
{ {
if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) { return CPU_FEATURE_AVAILABLE(CPU_HAS_ALTIVEC);
return SDL_TRUE;
}
return SDL_FALSE;
} }
SDL_bool SDL_bool
SDL_HasMMX(void) SDL_HasMMX(void)
{ {
if (SDL_GetCPUFeatures() & CPU_HAS_MMX) { return CPU_FEATURE_AVAILABLE(CPU_HAS_MMX);
return SDL_TRUE;
}
return SDL_FALSE;
} }
SDL_bool SDL_bool
SDL_Has3DNow(void) SDL_Has3DNow(void)
{ {
if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) { return CPU_FEATURE_AVAILABLE(CPU_HAS_3DNOW);
return SDL_TRUE;
}
return SDL_FALSE;
} }
SDL_bool SDL_bool
SDL_HasSSE(void) SDL_HasSSE(void)
{ {
if (SDL_GetCPUFeatures() & CPU_HAS_SSE) { return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE);
return SDL_TRUE;
}
return SDL_FALSE;
} }
SDL_bool SDL_bool
SDL_HasSSE2(void) SDL_HasSSE2(void)
{ {
if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) { return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE2);
return SDL_TRUE;
}
return SDL_FALSE;
} }
SDL_bool SDL_bool
SDL_HasSSE3(void) SDL_HasSSE3(void)
{ {
if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) { return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE3);
return SDL_TRUE;
}
return SDL_FALSE;
} }
SDL_bool SDL_bool
SDL_HasSSE41(void) SDL_HasSSE41(void)
{ {
if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) { return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE41);
return SDL_TRUE;
}
return SDL_FALSE;
} }
SDL_bool SDL_bool
SDL_HasSSE42(void) SDL_HasSSE42(void)
{ {
if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) { return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE42);
return SDL_TRUE;
}
return SDL_FALSE;
} }
SDL_bool SDL_bool
SDL_HasAVX(void) SDL_HasAVX(void)
{ {
if (SDL_GetCPUFeatures() & CPU_HAS_AVX) { return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX);
return SDL_TRUE;
}
return SDL_FALSE;
} }
SDL_bool SDL_bool
SDL_HasAVX2(void) SDL_HasAVX2(void)
{ {
if (SDL_GetCPUFeatures() & CPU_HAS_AVX2) { return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX2);
return SDL_TRUE;
}
return SDL_FALSE;
} }
static int SDL_SystemRAM = 0; static int SDL_SystemRAM = 0;