comparison src/cpuinfo/SDL_cpuinfo.c @ 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
comparison
equal deleted inserted replaced
784:a2dde6aff60e 785:ca06a994f03c
34 #include <sys/sysctl.h> /* For AltiVec check */ 34 #include <sys/sysctl.h> /* For AltiVec check */
35 #endif 35 #endif
36 36
37 #define CPU_HAS_RDTSC 0x00000001 37 #define CPU_HAS_RDTSC 0x00000001
38 #define CPU_HAS_MMX 0x00000002 38 #define CPU_HAS_MMX 0x00000002
39 #define CPU_HAS_3DNOW 0x00000004 39 #define CPU_HAS_MMXEXT 0x00000004
40 #define CPU_HAS_SSE 0x00000008 40 #define CPU_HAS_3DNOW 0x00000010
41 #define CPU_HAS_ALTIVEC 0x00000010 41 #define CPU_HAS_3DNOWEXT 0x00000020
42 #define CPU_HAS_SSE 0x00000040
43 #define CPU_HAS_SSE2 0x00000080
44 #define CPU_HAS_ALTIVEC 0x00000100
42 45
43 static __inline__ int CPU_haveCPUID() 46 static __inline__ int CPU_haveCPUID()
44 { 47 {
45 int has_CPUID = 0; 48 int has_CPUID = 0;
46 #if defined(__GNUC__) && defined(i386) 49 #if defined(__GNUC__) && defined(i386)
47 __asm__ ( 50 __asm__ (
48 "push %%ecx\n"
49 " pushfl # Get original EFLAGS \n" 51 " pushfl # Get original EFLAGS \n"
50 " popl %%eax \n" 52 " popl %%eax \n"
51 " movl %%eax,%%ecx \n" 53 " movl %%eax,%%ecx \n"
52 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" 54 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n"
53 " pushl %%eax # Save new EFLAGS value on stack \n" 55 " pushl %%eax # Save new EFLAGS value on stack \n"
56 " popl %%eax # Store new EFLAGS in EAX \n" 58 " popl %%eax # Store new EFLAGS in EAX \n"
57 " xorl %%ecx,%%eax # Can not toggle ID bit, \n" 59 " xorl %%ecx,%%eax # Can not toggle ID bit, \n"
58 " jz 1f # Processor=80486 \n" 60 " jz 1f # Processor=80486 \n"
59 " movl $1,%0 # We have CPUID support \n" 61 " movl $1,%0 # We have CPUID support \n"
60 "1: \n" 62 "1: \n"
61 "pop %%ecx\n"
62 : "=m" (has_CPUID) 63 : "=m" (has_CPUID)
63 : 64 :
64 : "%eax", "%ecx" 65 : "%eax", "%ecx"
65 ); 66 );
66 #elif defined(_MSC_VER) 67 #elif defined(_MSC_VER)
85 static __inline__ int CPU_getCPUIDFeatures() 86 static __inline__ int CPU_getCPUIDFeatures()
86 { 87 {
87 int features = 0; 88 int features = 0;
88 #if defined(__GNUC__) && defined(i386) 89 #if defined(__GNUC__) && defined(i386)
89 __asm__ ( 90 __asm__ (
90 "push %%ebx\n" 91 " movl %%ebx,%%edi\n"
91 "push %%ecx\n"
92 "push %%edx\n"
93 " xorl %%eax,%%eax # Set up for CPUID instruction \n" 92 " xorl %%eax,%%eax # Set up for CPUID instruction \n"
94 " cpuid # Get and save vendor ID \n" 93 " cpuid # Get and save vendor ID \n"
95 " cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n" 94 " cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n"
96 " jl 1f # We dont have the CPUID instruction\n" 95 " jl 1f # We dont have the CPUID instruction\n"
97 " xorl %%eax,%%eax \n" 96 " xorl %%eax,%%eax \n"
98 " incl %%eax \n" 97 " incl %%eax \n"
99 " cpuid # Get family/model/stepping/features\n" 98 " cpuid # Get family/model/stepping/features\n"
100 " movl %%edx,%0 \n" 99 " movl %%edx,%0 \n"
101 "1: \n" 100 "1: \n"
102 "pop %%edx\n" 101 " movl %%edi,%%ebx\n"
103 "pop %%ecx\n"
104 "pop %%ebx\n"
105 : "=m" (features) 102 : "=m" (features)
106 : 103 :
107 : "%eax", "%ebx", "%ecx", "%edx" 104 : "%eax", "%ebx", "%ecx", "%edx", "%edi"
108 ); 105 );
109 #elif defined(_MSC_VER) 106 #elif defined(_MSC_VER)
110 __asm { 107 __asm {
111 xor eax, eax ; Set up for CPUID instruction 108 xor eax, eax ; Set up for CPUID instruction
112 cpuid ; Get and save vendor ID 109 cpuid ; Get and save vendor ID
120 } 117 }
121 #endif 118 #endif
122 return features; 119 return features;
123 } 120 }
124 121
125 static __inline__ int CPU_haveRDTSC() 122 static __inline__ int CPU_getCPUIDFeaturesExt()
126 { 123 {
127 if ( CPU_haveCPUID() ) { 124 int features = 0;
128 return (CPU_getCPUIDFeatures() & 0x00000010);
129 }
130 return 0;
131 }
132
133 static __inline__ int CPU_haveMMX()
134 {
135 if ( CPU_haveCPUID() ) {
136 return (CPU_getCPUIDFeatures() & 0x00800000);
137 }
138 return 0;
139 }
140
141 static __inline__ int CPU_have3DNow()
142 {
143 int has_3DNow = 0;
144 if ( !CPU_haveCPUID() ) {
145 return 0;
146 }
147 #if defined(__GNUC__) && defined(i386) 125 #if defined(__GNUC__) && defined(i386)
148 __asm__ ( 126 __asm__ (
149 "push %%ebx\n" 127 " movl %%ebx,%%edi\n"
150 "push %%ecx\n"
151 "push %%edx\n"
152 " movl $0x80000000,%%eax # Query for extended functions \n" 128 " movl $0x80000000,%%eax # Query for extended functions \n"
153 " cpuid # Get extended function limit \n" 129 " cpuid # Get extended function limit \n"
154 " cmpl $0x80000001,%%eax \n" 130 " cmpl $0x80000001,%%eax \n"
155 " jbe 1f # Nope, we dont have function 800000001h\n" 131 " jbe 1f # Nope, we dont have function 800000001h\n"
156 " movl $0x80000001,%%eax # Setup extended function 800000001h\n" 132 " movl $0x80000001,%%eax # Setup extended function 800000001h\n"
157 " cpuid # and get the information \n" 133 " cpuid # and get the information \n"
158 " testl $0x80000000,%%edx # Bit 31 is set if 3DNow! present \n" 134 " movl %%edx,%0 \n"
159 " jz 1f # Nope, we dont have 3DNow support\n"
160 " movl $1,%0 # Yep, we have 3DNow! support! \n"
161 "1: \n" 135 "1: \n"
162 "pop %%edx\n" 136 " movl %%edi,%%ebx\n"
163 "pop %%ecx\n" 137 : "=m" (features)
164 "pop %%ebx\n"
165 : "=m" (has_3DNow)
166 : 138 :
167 : "%eax", "%ebx", "%ecx", "%edx" 139 : "%eax", "%ebx", "%ecx", "%edx", "%edi"
168 ); 140 );
169 #elif defined(_MSC_VER) 141 #elif defined(_MSC_VER)
170 __asm { 142 __asm {
171 mov eax,80000000h ; Query for extended functions 143 mov eax,80000000h ; Query for extended functions
172 cpuid ; Get extended function limit 144 cpuid ; Get extended function limit
173 cmp eax,80000001h 145 cmp eax,80000001h
174 jbe done ; Nope, we dont have function 800000001h 146 jbe done ; Nope, we dont have function 800000001h
175 mov eax,80000001h ; Setup extended function 800000001h 147 mov eax,80000001h ; Setup extended function 800000001h
176 cpuid ; and get the information 148 cpuid ; and get the information
177 test edx,80000000h ; Bit 31 is set if 3DNow! present 149 mov features,edx
178 jz done ; Nope, we dont have 3DNow support
179 mov has_3DNow,1 ; Yep, we have 3DNow! support!
180 done: 150 done:
181 } 151 }
182 #endif 152 #endif
183 return has_3DNow; 153 return features;
154 }
155
156 static __inline__ int CPU_haveRDTSC()
157 {
158 if ( CPU_haveCPUID() ) {
159 return (CPU_getCPUIDFeatures() & 0x00000010);
160 }
161 return 0;
162 }
163
164 static __inline__ int CPU_haveMMX()
165 {
166 if ( CPU_haveCPUID() ) {
167 return (CPU_getCPUIDFeatures() & 0x00800000);
168 }
169 return 0;
170 }
171
172 static __inline__ int CPU_haveMMXExt()
173 {
174 if ( CPU_haveCPUID() ) {
175 return (CPU_getCPUIDFeaturesExt() & 0x00400000);
176 }
177 return 0;
178 }
179
180 static __inline__ int CPU_have3DNow()
181 {
182 if ( CPU_haveCPUID() ) {
183 return (CPU_getCPUIDFeaturesExt() & 0x80000000);
184 }
185 return 0;
186 }
187
188 static __inline__ int CPU_have3DNowExt()
189 {
190 if ( CPU_haveCPUID() ) {
191 return (CPU_getCPUIDFeaturesExt() & 0x40000000);
192 }
193 return 0;
184 } 194 }
185 195
186 static __inline__ int CPU_haveSSE() 196 static __inline__ int CPU_haveSSE()
187 { 197 {
188 if ( CPU_haveCPUID() ) { 198 if ( CPU_haveCPUID() ) {
189 return (CPU_getCPUIDFeatures() & 0x02000000); 199 return (CPU_getCPUIDFeatures() & 0x02000000);
200 }
201 return 0;
202 }
203
204 static __inline__ int CPU_haveSSE2()
205 {
206 if ( CPU_haveCPUID() ) {
207 return (CPU_getCPUIDFeatures() & 0x04000000);
190 } 208 }
191 return 0; 209 return 0;
192 } 210 }
193 211
194 static __inline__ int CPU_haveAltiVec() 212 static __inline__ int CPU_haveAltiVec()
227 SDL_CPUFeatures |= CPU_HAS_SSE; 245 SDL_CPUFeatures |= CPU_HAS_SSE;
228 } 246 }
229 if ( CPU_haveAltiVec() ) { 247 if ( CPU_haveAltiVec() ) {
230 SDL_CPUFeatures |= CPU_HAS_ALTIVEC; 248 SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
231 } 249 }
250 if ( CPU_haveMMXExt() ) {
251 SDL_CPUFeatures |= CPU_HAS_MMXEXT;
252 }
253 if ( CPU_have3DNowExt() ) {
254 SDL_CPUFeatures |= CPU_HAS_3DNOWEXT;
255 }
256 if ( CPU_haveSSE2() ) {
257 SDL_CPUFeatures |= CPU_HAS_SSE2;
258 }
232 } 259 }
233 return SDL_CPUFeatures; 260 return SDL_CPUFeatures;
234 } 261 }
235 262
236 SDL_bool SDL_HasRDTSC() 263 SDL_bool SDL_HasRDTSC()
269 { 296 {
270 if ( SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC ) { 297 if ( SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC ) {
271 return SDL_TRUE; 298 return SDL_TRUE;
272 } 299 }
273 return SDL_FALSE; 300 return SDL_FALSE;
301 }
302
303 SDL_bool SDL_HasMMXExt()
304 {
305 if ( SDL_GetCPUFeatures() & CPU_HAS_MMXEXT ) {
306 return SDL_TRUE;
307 }
308 return SDL_FALSE;
309 }
310
311 SDL_bool SDL_Has3DNowExt()
312 {
313 if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOWEXT ) {
314 return SDL_TRUE;
315 }
316 return SDL_FALSE;
317 }
318
319 SDL_bool SDL_HasSSE2()
320 {
321 if ( SDL_GetCPUFeatures() & CPU_HAS_SSE2 ) {
322 return SDL_TRUE;
323 }
324 return SDL_FALSE;
274 } 325 }
275 326
276 #ifdef TEST_MAIN 327 #ifdef TEST_MAIN
277 328
278 #include <stdio.h> 329 #include <stdio.h>
279 330
280 int main() 331 int main()
281 { 332 {
282 printf("RDTSC: %d\n", SDL_HasRDTSC()); 333 printf("RDTSC: %d\n", SDL_HasRDTSC());
283 printf("MMX: %d\n", SDL_HasMMX()); 334 printf("MMX: %d\n", SDL_HasMMX());
335 printf("MMXExt: %d\n", SDL_HasMMXExt());
284 printf("3DNow: %d\n", SDL_Has3DNow()); 336 printf("3DNow: %d\n", SDL_Has3DNow());
337 printf("3DNowExt: %d\n", SDL_Has3DNowExt());
285 printf("SSE: %d\n", SDL_HasSSE()); 338 printf("SSE: %d\n", SDL_HasSSE());
339 printf("SSE2: %d\n", SDL_HasSSE2());
286 printf("AltiVec: %d\n", SDL_HasAltiVec()); 340 printf("AltiVec: %d\n", SDL_HasAltiVec());
287 return 0; 341 return 0;
288 } 342 }
289 343
290 #endif /* TEST_MAIN */ 344 #endif /* TEST_MAIN */