Fixed bugs in CPU feature detection and added extended feature detection
authorSam Lantinga <slouken@libsdl.org>
Sat, 24 Jan 2004 05:47:19 +0000
changeset 785ca06a994f03c
parent 784 a2dde6aff60e
child 786 e1e0a0a94570
Fixed bugs in CPU feature detection and added extended feature detection
include/SDL_cpuinfo.h
src/cpuinfo/SDL_cpuinfo.c
test/testcpuinfo.c
     1.1 --- a/include/SDL_cpuinfo.h	Sat Jan 17 20:37:06 2004 +0000
     1.2 +++ b/include/SDL_cpuinfo.h	Sat Jan 24 05:47:19 2004 +0000
     1.3 @@ -45,14 +45,26 @@
     1.4   */
     1.5  extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX();
     1.6  
     1.7 +/* This function returns true if the CPU has MMX Ext. features
     1.8 + */
     1.9 +extern DECLSPEC SDL_bool SDLCALL SDL_HasMMXExt();
    1.10 +
    1.11  /* This function returns true if the CPU has 3DNow features
    1.12   */
    1.13  extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNow();
    1.14  
    1.15 +/* This function returns true if the CPU has 3DNow! Ext. features
    1.16 + */
    1.17 +extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNowExt();
    1.18 +
    1.19  /* This function returns true if the CPU has SSE features
    1.20   */
    1.21  extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE();
    1.22  
    1.23 +/* This function returns true if the CPU has SSE2 features
    1.24 + */
    1.25 +extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE2();
    1.26 +
    1.27  /* This function returns true if the CPU has AltiVec features
    1.28   */
    1.29  extern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec();
     2.1 --- a/src/cpuinfo/SDL_cpuinfo.c	Sat Jan 17 20:37:06 2004 +0000
     2.2 +++ b/src/cpuinfo/SDL_cpuinfo.c	Sat Jan 24 05:47:19 2004 +0000
     2.3 @@ -36,16 +36,18 @@
     2.4  
     2.5  #define CPU_HAS_RDTSC	0x00000001
     2.6  #define CPU_HAS_MMX	0x00000002
     2.7 -#define CPU_HAS_3DNOW	0x00000004
     2.8 -#define CPU_HAS_SSE	0x00000008
     2.9 -#define CPU_HAS_ALTIVEC	0x00000010
    2.10 +#define CPU_HAS_MMXEXT	0x00000004
    2.11 +#define CPU_HAS_3DNOW	0x00000010
    2.12 +#define CPU_HAS_3DNOWEXT 0x00000020
    2.13 +#define CPU_HAS_SSE	0x00000040
    2.14 +#define CPU_HAS_SSE2	0x00000080
    2.15 +#define CPU_HAS_ALTIVEC	0x00000100
    2.16  
    2.17  static __inline__ int CPU_haveCPUID()
    2.18  {
    2.19  	int has_CPUID = 0;
    2.20  #if defined(__GNUC__) && defined(i386)
    2.21  	__asm__ (
    2.22 -"push %%ecx\n"
    2.23  "        pushfl                      # Get original EFLAGS             \n"
    2.24  "        popl    %%eax                                                 \n"
    2.25  "        movl    %%eax,%%ecx                                           \n"
    2.26 @@ -58,7 +60,6 @@
    2.27  "        jz      1f                  # Processor=80486                 \n"
    2.28  "        movl    $1,%0               # We have CPUID support           \n"
    2.29  "1:                                                                    \n"
    2.30 -"pop %%ecx\n"
    2.31  	: "=m" (has_CPUID)
    2.32  	:
    2.33  	: "%eax", "%ecx"
    2.34 @@ -87,9 +88,7 @@
    2.35  	int features = 0;
    2.36  #if defined(__GNUC__) && defined(i386)
    2.37  	__asm__ (
    2.38 -"push %%ebx\n"
    2.39 -"push %%ecx\n"
    2.40 -"push %%edx\n"
    2.41 +"        movl    %%ebx,%%edi\n"
    2.42  "        xorl    %%eax,%%eax         # Set up for CPUID instruction    \n"
    2.43  "        cpuid                       # Get and save vendor ID          \n"
    2.44  "        cmpl    $1,%%eax            # Make sure 1 is valid input for CPUID\n"
    2.45 @@ -99,12 +98,10 @@
    2.46  "        cpuid                       # Get family/model/stepping/features\n"
    2.47  "        movl    %%edx,%0                                              \n"
    2.48  "1:                                                                    \n"
    2.49 -"pop %%edx\n"
    2.50 -"pop %%ecx\n"
    2.51 -"pop %%ebx\n"
    2.52 +"        movl    %%edi,%%ebx\n"
    2.53  	: "=m" (features)
    2.54  	:
    2.55 -	: "%eax", "%ebx", "%ecx", "%edx"
    2.56 +	: "%eax", "%ebx", "%ecx", "%edx", "%edi"
    2.57  	);
    2.58  #elif defined(_MSC_VER)
    2.59  	__asm {
    2.60 @@ -122,6 +119,40 @@
    2.61  	return features;
    2.62  }
    2.63  
    2.64 +static __inline__ int CPU_getCPUIDFeaturesExt()
    2.65 +{
    2.66 +	int features = 0;
    2.67 +#if defined(__GNUC__) && defined(i386)
    2.68 +	__asm__ (
    2.69 +"        movl    %%ebx,%%edi\n"
    2.70 +"        movl    $0x80000000,%%eax   # Query for extended functions    \n"
    2.71 +"        cpuid                       # Get extended function limit     \n"
    2.72 +"        cmpl    $0x80000001,%%eax                                     \n"
    2.73 +"        jbe     1f                  # Nope, we dont have function 800000001h\n"
    2.74 +"        movl    $0x80000001,%%eax   # Setup extended function 800000001h\n"
    2.75 +"        cpuid                       # and get the information         \n"
    2.76 +"        movl    %%edx,%0                                              \n"
    2.77 +"1:                                                                    \n"
    2.78 +"        movl    %%edi,%%ebx\n"
    2.79 +	: "=m" (features)
    2.80 +	:
    2.81 +	: "%eax", "%ebx", "%ecx", "%edx", "%edi"
    2.82 +	);
    2.83 +#elif defined(_MSC_VER)
    2.84 +	__asm {
    2.85 +        mov     eax,80000000h       ; Query for extended functions
    2.86 +        cpuid                       ; Get extended function limit
    2.87 +        cmp     eax,80000001h
    2.88 +        jbe     done                ; Nope, we dont have function 800000001h
    2.89 +        mov     eax,80000001h       ; Setup extended function 800000001h
    2.90 +        cpuid                       ; and get the information
    2.91 +        mov     features,edx
    2.92 +done:
    2.93 +	}
    2.94 +#endif
    2.95 +	return features;
    2.96 +}
    2.97 +
    2.98  static __inline__ int CPU_haveRDTSC()
    2.99  {
   2.100  	if ( CPU_haveCPUID() ) {
   2.101 @@ -138,49 +169,28 @@
   2.102  	return 0;
   2.103  }
   2.104  
   2.105 +static __inline__ int CPU_haveMMXExt()
   2.106 +{
   2.107 +	if ( CPU_haveCPUID() ) {
   2.108 +		return (CPU_getCPUIDFeaturesExt() & 0x00400000);
   2.109 +	}
   2.110 +	return 0;
   2.111 +}
   2.112 +
   2.113  static __inline__ int CPU_have3DNow()
   2.114  {
   2.115 -	int has_3DNow = 0;
   2.116 -	if ( !CPU_haveCPUID() ) {
   2.117 -		return 0;
   2.118 +	if ( CPU_haveCPUID() ) {
   2.119 +		return (CPU_getCPUIDFeaturesExt() & 0x80000000);
   2.120  	}
   2.121 -#if defined(__GNUC__) && defined(i386)
   2.122 -	__asm__ (
   2.123 -"push %%ebx\n"
   2.124 -"push %%ecx\n"
   2.125 -"push %%edx\n"
   2.126 -"        movl    $0x80000000,%%eax   # Query for extended functions    \n"
   2.127 -"        cpuid                       # Get extended function limit     \n"
   2.128 -"        cmpl    $0x80000001,%%eax                                     \n"
   2.129 -"        jbe     1f                  # Nope, we dont have function 800000001h\n"
   2.130 -"        movl    $0x80000001,%%eax   # Setup extended function 800000001h\n"
   2.131 -"        cpuid                       # and get the information         \n"
   2.132 -"        testl   $0x80000000,%%edx   # Bit 31 is set if 3DNow! present \n"
   2.133 -"        jz      1f                  # Nope, we dont have 3DNow support\n"
   2.134 -"        movl    $1,%0               # Yep, we have 3DNow! support!    \n"
   2.135 -"1:                                                                    \n"
   2.136 -"pop %%edx\n"
   2.137 -"pop %%ecx\n"
   2.138 -"pop %%ebx\n"
   2.139 -	: "=m" (has_3DNow)
   2.140 -	:
   2.141 -	: "%eax", "%ebx", "%ecx", "%edx"
   2.142 -	);
   2.143 -#elif defined(_MSC_VER)
   2.144 -	__asm {
   2.145 -        mov     eax,80000000h       ; Query for extended functions
   2.146 -        cpuid                       ; Get extended function limit
   2.147 -        cmp     eax,80000001h
   2.148 -        jbe     done                ; Nope, we dont have function 800000001h
   2.149 -        mov     eax,80000001h       ; Setup extended function 800000001h
   2.150 -        cpuid                       ; and get the information
   2.151 -        test    edx,80000000h       ; Bit 31 is set if 3DNow! present
   2.152 -        jz      done                ; Nope, we dont have 3DNow support
   2.153 -        mov     has_3DNow,1         ; Yep, we have 3DNow! support!
   2.154 -done:
   2.155 +	return 0;
   2.156 +}
   2.157 +
   2.158 +static __inline__ int CPU_have3DNowExt()
   2.159 +{
   2.160 +	if ( CPU_haveCPUID() ) {
   2.161 +		return (CPU_getCPUIDFeaturesExt() & 0x40000000);
   2.162  	}
   2.163 -#endif
   2.164 -	return has_3DNow;
   2.165 +	return 0;
   2.166  }
   2.167  
   2.168  static __inline__ int CPU_haveSSE()
   2.169 @@ -191,6 +201,14 @@
   2.170  	return 0;
   2.171  }
   2.172  
   2.173 +static __inline__ int CPU_haveSSE2()
   2.174 +{
   2.175 +	if ( CPU_haveCPUID() ) {
   2.176 +		return (CPU_getCPUIDFeatures() & 0x04000000);
   2.177 +	}
   2.178 +	return 0;
   2.179 +}
   2.180 +
   2.181  static __inline__ int CPU_haveAltiVec()
   2.182  {
   2.183  #ifdef MACOSX
   2.184 @@ -229,6 +247,15 @@
   2.185  		if ( CPU_haveAltiVec() ) {
   2.186  			SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
   2.187  		}
   2.188 +      if ( CPU_haveMMXExt() ) {
   2.189 +         SDL_CPUFeatures |= CPU_HAS_MMXEXT;
   2.190 +      }
   2.191 +      if ( CPU_have3DNowExt() ) {
   2.192 +         SDL_CPUFeatures |= CPU_HAS_3DNOWEXT;
   2.193 +      }
   2.194 +      if ( CPU_haveSSE2() ) {
   2.195 +         SDL_CPUFeatures |= CPU_HAS_SSE2;
   2.196 +      }
   2.197  	}
   2.198  	return SDL_CPUFeatures;
   2.199  }
   2.200 @@ -273,6 +300,30 @@
   2.201  	return SDL_FALSE;
   2.202  }
   2.203  
   2.204 +SDL_bool SDL_HasMMXExt()
   2.205 +{
   2.206 +   if ( SDL_GetCPUFeatures() & CPU_HAS_MMXEXT ) {
   2.207 +      return SDL_TRUE;
   2.208 +   }
   2.209 +   return SDL_FALSE;
   2.210 +}
   2.211 +
   2.212 +SDL_bool SDL_Has3DNowExt()
   2.213 +{
   2.214 +   if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOWEXT ) {
   2.215 +      return SDL_TRUE;
   2.216 +   }
   2.217 +   return SDL_FALSE;
   2.218 +}
   2.219 +
   2.220 +SDL_bool SDL_HasSSE2()
   2.221 +{
   2.222 +   if ( SDL_GetCPUFeatures() & CPU_HAS_SSE2 ) {
   2.223 +      return SDL_TRUE;
   2.224 +   }
   2.225 +   return SDL_FALSE;
   2.226 +}
   2.227 +
   2.228  #ifdef TEST_MAIN
   2.229  
   2.230  #include <stdio.h>
   2.231 @@ -281,8 +332,11 @@
   2.232  {
   2.233  	printf("RDTSC: %d\n", SDL_HasRDTSC());
   2.234  	printf("MMX: %d\n", SDL_HasMMX());
   2.235 +	printf("MMXExt: %d\n", SDL_HasMMXExt());
   2.236  	printf("3DNow: %d\n", SDL_Has3DNow());
   2.237 +	printf("3DNowExt: %d\n", SDL_Has3DNowExt());
   2.238  	printf("SSE: %d\n", SDL_HasSSE());
   2.239 +	printf("SSE2: %d\n", SDL_HasSSE2());
   2.240  	printf("AltiVec: %d\n", SDL_HasAltiVec());
   2.241  	return 0;
   2.242  }
     3.1 --- a/test/testcpuinfo.c	Sat Jan 17 20:37:06 2004 +0000
     3.2 +++ b/test/testcpuinfo.c	Sat Jan 24 05:47:19 2004 +0000
     3.3 @@ -10,8 +10,11 @@
     3.4  {
     3.5  	printf("RDTSC %s\n", SDL_HasRDTSC() ? "detected" : "not detected");
     3.6  	printf("MMX %s\n", SDL_HasMMX() ? "detected" : "not detected");
     3.7 +	printf("MMX Ext %s\n", SDL_HasMMXExt() ? "detected" : "not detected");
     3.8  	printf("3DNow %s\n", SDL_Has3DNow() ? "detected" : "not detected");
     3.9 +	printf("3DNow Ext %s\n", SDL_Has3DNowExt() ? "detected" : "not detected");
    3.10  	printf("SSE %s\n", SDL_HasSSE() ? "detected" : "not detected");
    3.11 +	printf("SSE2 %s\n", SDL_HasSSE2() ? "detected" : "not detected");
    3.12  	printf("AltiVec %s\n", SDL_HasAltiVec() ? "detected" : "not detected");
    3.13  	return(0);
    3.14  }