Commit 7592b40b391f15f7c1476f2fc777a03f212e8a6c

Ryan C. Gordon 2016-11-16T22:49:04

cpuinfo: Removed code duplication, cached CPUID details.

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