changeset 785:ca06a994f03c

Fixed bugs in CPU feature detection and added extended feature detection
author Sam Lantinga <slouken@libsdl.org>
date Sat, 24 Jan 2004 05:47:19 +0000
parents a2dde6aff60e
children e1e0a0a94570
files include/SDL_cpuinfo.h src/cpuinfo/SDL_cpuinfo.c test/testcpuinfo.c
diffstat 3 files changed, 120 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/include/SDL_cpuinfo.h	Sat Jan 17 20:37:06 2004 +0000
+++ b/include/SDL_cpuinfo.h	Sat Jan 24 05:47:19 2004 +0000
@@ -45,14 +45,26 @@
  */
 extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX();
 
+/* This function returns true if the CPU has MMX Ext. features
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasMMXExt();
+
 /* This function returns true if the CPU has 3DNow features
  */
 extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNow();
 
+/* This function returns true if the CPU has 3DNow! Ext. features
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNowExt();
+
 /* This function returns true if the CPU has SSE features
  */
 extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE();
 
+/* This function returns true if the CPU has SSE2 features
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE2();
+
 /* This function returns true if the CPU has AltiVec features
  */
 extern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec();
--- a/src/cpuinfo/SDL_cpuinfo.c	Sat Jan 17 20:37:06 2004 +0000
+++ b/src/cpuinfo/SDL_cpuinfo.c	Sat Jan 24 05:47:19 2004 +0000
@@ -36,16 +36,18 @@
 
 #define CPU_HAS_RDTSC	0x00000001
 #define CPU_HAS_MMX	0x00000002
-#define CPU_HAS_3DNOW	0x00000004
-#define CPU_HAS_SSE	0x00000008
-#define CPU_HAS_ALTIVEC	0x00000010
+#define CPU_HAS_MMXEXT	0x00000004
+#define CPU_HAS_3DNOW	0x00000010
+#define CPU_HAS_3DNOWEXT 0x00000020
+#define CPU_HAS_SSE	0x00000040
+#define CPU_HAS_SSE2	0x00000080
+#define CPU_HAS_ALTIVEC	0x00000100
 
 static __inline__ int CPU_haveCPUID()
 {
 	int has_CPUID = 0;
 #if defined(__GNUC__) && defined(i386)
 	__asm__ (
-"push %%ecx\n"
 "        pushfl                      # Get original EFLAGS             \n"
 "        popl    %%eax                                                 \n"
 "        movl    %%eax,%%ecx                                           \n"
@@ -58,7 +60,6 @@
 "        jz      1f                  # Processor=80486                 \n"
 "        movl    $1,%0               # We have CPUID support           \n"
 "1:                                                                    \n"
-"pop %%ecx\n"
 	: "=m" (has_CPUID)
 	:
 	: "%eax", "%ecx"
@@ -87,9 +88,7 @@
 	int features = 0;
 #if defined(__GNUC__) && defined(i386)
 	__asm__ (
-"push %%ebx\n"
-"push %%ecx\n"
-"push %%edx\n"
+"        movl    %%ebx,%%edi\n"
 "        xorl    %%eax,%%eax         # Set up for CPUID instruction    \n"
 "        cpuid                       # Get and save vendor ID          \n"
 "        cmpl    $1,%%eax            # Make sure 1 is valid input for CPUID\n"
@@ -99,12 +98,10 @@
 "        cpuid                       # Get family/model/stepping/features\n"
 "        movl    %%edx,%0                                              \n"
 "1:                                                                    \n"
-"pop %%edx\n"
-"pop %%ecx\n"
-"pop %%ebx\n"
+"        movl    %%edi,%%ebx\n"
 	: "=m" (features)
 	:
-	: "%eax", "%ebx", "%ecx", "%edx"
+	: "%eax", "%ebx", "%ecx", "%edx", "%edi"
 	);
 #elif defined(_MSC_VER)
 	__asm {
@@ -122,6 +119,40 @@
 	return features;
 }
 
+static __inline__ int CPU_getCPUIDFeaturesExt()
+{
+	int features = 0;
+#if defined(__GNUC__) && defined(i386)
+	__asm__ (
+"        movl    %%ebx,%%edi\n"
+"        movl    $0x80000000,%%eax   # Query for extended functions    \n"
+"        cpuid                       # Get extended function limit     \n"
+"        cmpl    $0x80000001,%%eax                                     \n"
+"        jbe     1f                  # Nope, we dont have function 800000001h\n"
+"        movl    $0x80000001,%%eax   # Setup extended function 800000001h\n"
+"        cpuid                       # and get the information         \n"
+"        movl    %%edx,%0                                              \n"
+"1:                                                                    \n"
+"        movl    %%edi,%%ebx\n"
+	: "=m" (features)
+	:
+	: "%eax", "%ebx", "%ecx", "%edx", "%edi"
+	);
+#elif defined(_MSC_VER)
+	__asm {
+        mov     eax,80000000h       ; Query for extended functions
+        cpuid                       ; Get extended function limit
+        cmp     eax,80000001h
+        jbe     done                ; Nope, we dont have function 800000001h
+        mov     eax,80000001h       ; Setup extended function 800000001h
+        cpuid                       ; and get the information
+        mov     features,edx
+done:
+	}
+#endif
+	return features;
+}
+
 static __inline__ int CPU_haveRDTSC()
 {
 	if ( CPU_haveCPUID() ) {
@@ -138,49 +169,28 @@
 	return 0;
 }
 
+static __inline__ int CPU_haveMMXExt()
+{
+	if ( CPU_haveCPUID() ) {
+		return (CPU_getCPUIDFeaturesExt() & 0x00400000);
+	}
+	return 0;
+}
+
 static __inline__ int CPU_have3DNow()
 {
-	int has_3DNow = 0;
-	if ( !CPU_haveCPUID() ) {
-		return 0;
+	if ( CPU_haveCPUID() ) {
+		return (CPU_getCPUIDFeaturesExt() & 0x80000000);
 	}
-#if defined(__GNUC__) && defined(i386)
-	__asm__ (
-"push %%ebx\n"
-"push %%ecx\n"
-"push %%edx\n"
-"        movl    $0x80000000,%%eax   # Query for extended functions    \n"
-"        cpuid                       # Get extended function limit     \n"
-"        cmpl    $0x80000001,%%eax                                     \n"
-"        jbe     1f                  # Nope, we dont have function 800000001h\n"
-"        movl    $0x80000001,%%eax   # Setup extended function 800000001h\n"
-"        cpuid                       # and get the information         \n"
-"        testl   $0x80000000,%%edx   # Bit 31 is set if 3DNow! present \n"
-"        jz      1f                  # Nope, we dont have 3DNow support\n"
-"        movl    $1,%0               # Yep, we have 3DNow! support!    \n"
-"1:                                                                    \n"
-"pop %%edx\n"
-"pop %%ecx\n"
-"pop %%ebx\n"
-	: "=m" (has_3DNow)
-	:
-	: "%eax", "%ebx", "%ecx", "%edx"
-	);
-#elif defined(_MSC_VER)
-	__asm {
-        mov     eax,80000000h       ; Query for extended functions
-        cpuid                       ; Get extended function limit
-        cmp     eax,80000001h
-        jbe     done                ; Nope, we dont have function 800000001h
-        mov     eax,80000001h       ; Setup extended function 800000001h
-        cpuid                       ; and get the information
-        test    edx,80000000h       ; Bit 31 is set if 3DNow! present
-        jz      done                ; Nope, we dont have 3DNow support
-        mov     has_3DNow,1         ; Yep, we have 3DNow! support!
-done:
+	return 0;
+}
+
+static __inline__ int CPU_have3DNowExt()
+{
+	if ( CPU_haveCPUID() ) {
+		return (CPU_getCPUIDFeaturesExt() & 0x40000000);
 	}
-#endif
-	return has_3DNow;
+	return 0;
 }
 
 static __inline__ int CPU_haveSSE()
@@ -191,6 +201,14 @@
 	return 0;
 }
 
+static __inline__ int CPU_haveSSE2()
+{
+	if ( CPU_haveCPUID() ) {
+		return (CPU_getCPUIDFeatures() & 0x04000000);
+	}
+	return 0;
+}
+
 static __inline__ int CPU_haveAltiVec()
 {
 #ifdef MACOSX
@@ -229,6 +247,15 @@
 		if ( CPU_haveAltiVec() ) {
 			SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
 		}
+      if ( CPU_haveMMXExt() ) {
+         SDL_CPUFeatures |= CPU_HAS_MMXEXT;
+      }
+      if ( CPU_have3DNowExt() ) {
+         SDL_CPUFeatures |= CPU_HAS_3DNOWEXT;
+      }
+      if ( CPU_haveSSE2() ) {
+         SDL_CPUFeatures |= CPU_HAS_SSE2;
+      }
 	}
 	return SDL_CPUFeatures;
 }
@@ -273,6 +300,30 @@
 	return SDL_FALSE;
 }
 
+SDL_bool SDL_HasMMXExt()
+{
+   if ( SDL_GetCPUFeatures() & CPU_HAS_MMXEXT ) {
+      return SDL_TRUE;
+   }
+   return SDL_FALSE;
+}
+
+SDL_bool SDL_Has3DNowExt()
+{
+   if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOWEXT ) {
+      return SDL_TRUE;
+   }
+   return SDL_FALSE;
+}
+
+SDL_bool SDL_HasSSE2()
+{
+   if ( SDL_GetCPUFeatures() & CPU_HAS_SSE2 ) {
+      return SDL_TRUE;
+   }
+   return SDL_FALSE;
+}
+
 #ifdef TEST_MAIN
 
 #include <stdio.h>
@@ -281,8 +332,11 @@
 {
 	printf("RDTSC: %d\n", SDL_HasRDTSC());
 	printf("MMX: %d\n", SDL_HasMMX());
+	printf("MMXExt: %d\n", SDL_HasMMXExt());
 	printf("3DNow: %d\n", SDL_Has3DNow());
+	printf("3DNowExt: %d\n", SDL_Has3DNowExt());
 	printf("SSE: %d\n", SDL_HasSSE());
+	printf("SSE2: %d\n", SDL_HasSSE2());
 	printf("AltiVec: %d\n", SDL_HasAltiVec());
 	return 0;
 }
--- a/test/testcpuinfo.c	Sat Jan 17 20:37:06 2004 +0000
+++ b/test/testcpuinfo.c	Sat Jan 24 05:47:19 2004 +0000
@@ -10,8 +10,11 @@
 {
 	printf("RDTSC %s\n", SDL_HasRDTSC() ? "detected" : "not detected");
 	printf("MMX %s\n", SDL_HasMMX() ? "detected" : "not detected");
+	printf("MMX Ext %s\n", SDL_HasMMXExt() ? "detected" : "not detected");
 	printf("3DNow %s\n", SDL_Has3DNow() ? "detected" : "not detected");
+	printf("3DNow Ext %s\n", SDL_Has3DNowExt() ? "detected" : "not detected");
 	printf("SSE %s\n", SDL_HasSSE() ? "detected" : "not detected");
+	printf("SSE2 %s\n", SDL_HasSSE2() ? "detected" : "not detected");
 	printf("AltiVec %s\n", SDL_HasAltiVec() ? "detected" : "not detected");
 	return(0);
 }