comparison src/cpuinfo/SDL_cpuinfo.c @ 1895:c121d94672cb

SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 21:04:37 +0000
parents 7bea26ad3130
children 99210400e8b9
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
25 25
26 #include "SDL.h" 26 #include "SDL.h"
27 #include "SDL_cpuinfo.h" 27 #include "SDL_cpuinfo.h"
28 28
29 #if defined(__MACOSX__) && defined(__ppc__) 29 #if defined(__MACOSX__) && defined(__ppc__)
30 #include <sys/sysctl.h> /* For AltiVec check */ 30 #include <sys/sysctl.h> /* For AltiVec check */
31 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP 31 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
32 #include <signal.h> 32 #include <signal.h>
33 #include <setjmp.h> 33 #include <setjmp.h>
34 #endif 34 #endif
35 35
45 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ 45 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__
46 /* This is the brute force way of detecting instruction sets... 46 /* This is the brute force way of detecting instruction sets...
47 the idea is borrowed from the libmpeg2 library - thanks! 47 the idea is borrowed from the libmpeg2 library - thanks!
48 */ 48 */
49 static jmp_buf jmpbuf; 49 static jmp_buf jmpbuf;
50 static void illegal_instruction(int sig) 50 static void
51 { 51 illegal_instruction(int sig)
52 longjmp(jmpbuf, 1); 52 {
53 longjmp(jmpbuf, 1);
53 } 54 }
54 #endif /* HAVE_SETJMP */ 55 #endif /* HAVE_SETJMP */
55 56
56 static __inline__ int CPU_haveCPUID(void) 57 static __inline__ int
57 { 58 CPU_haveCPUID(void)
58 int has_CPUID = 0; 59 {
60 int has_CPUID = 0;
61 /* *INDENT-OFF* */
59 #if defined(__GNUC__) && defined(i386) 62 #if defined(__GNUC__) && defined(i386)
60 __asm__ ( 63 __asm__ (
61 " pushfl # Get original EFLAGS \n" 64 " pushfl # Get original EFLAGS \n"
62 " popl %%eax \n" 65 " popl %%eax \n"
63 " movl %%eax,%%ecx \n" 66 " movl %%eax,%%ecx \n"
138 " jz 1f \n" 141 " jz 1f \n"
139 " movl $1,-8(%rbp) \n" 142 " movl $1,-8(%rbp) \n"
140 "1: \n" 143 "1: \n"
141 ); 144 );
142 #endif 145 #endif
143 return has_CPUID; 146 /* *INDENT-ON* */
144 } 147 return has_CPUID;
145 148 }
146 static __inline__ int CPU_getCPUIDFeatures(void) 149
147 { 150 static __inline__ int
148 int features = 0; 151 CPU_getCPUIDFeatures(void)
152 {
153 int features = 0;
154 /* *INDENT-OFF* */
149 #if defined(__GNUC__) && ( defined(i386) || defined(__x86_64__) ) 155 #if defined(__GNUC__) && ( defined(i386) || defined(__x86_64__) )
150 __asm__ ( 156 __asm__ (
151 " movl %%ebx,%%edi\n" 157 " movl %%ebx,%%edi\n"
152 " xorl %%eax,%%eax # Set up for CPUID instruction \n" 158 " xorl %%eax,%%eax # Set up for CPUID instruction \n"
153 " cpuid # Get and save vendor ID \n" 159 " cpuid # Get and save vendor ID \n"
191 " movl %edx,-8(%rbp) \n" 197 " movl %edx,-8(%rbp) \n"
192 #endif 198 #endif
193 "1: \n" 199 "1: \n"
194 " movl %edi,%ebx\n" ); 200 " movl %edi,%ebx\n" );
195 #endif 201 #endif
196 return features; 202 /* *INDENT-ON* */
197 } 203 return features;
198 204 }
199 static __inline__ int CPU_getCPUIDFeaturesExt(void) 205
200 { 206 static __inline__ int
201 int features = 0; 207 CPU_getCPUIDFeaturesExt(void)
208 {
209 int features = 0;
210 /* *INDENT-OFF* */
202 #if defined(__GNUC__) && (defined(i386) || defined (__x86_64__) ) 211 #if defined(__GNUC__) && (defined(i386) || defined (__x86_64__) )
203 __asm__ ( 212 __asm__ (
204 " movl %%ebx,%%edi\n" 213 " movl %%ebx,%%edi\n"
205 " movl $0x80000000,%%eax # Query for extended functions \n" 214 " movl $0x80000000,%%eax # Query for extended functions \n"
206 " cpuid # Get extended function limit \n" 215 " cpuid # Get extended function limit \n"
242 #endif 251 #endif
243 "1: \n" 252 "1: \n"
244 " movl %edi,%ebx\n" 253 " movl %edi,%ebx\n"
245 ); 254 );
246 #endif 255 #endif
247 return features; 256 /* *INDENT-ON* */
248 } 257 return features;
249 258 }
250 static __inline__ int CPU_haveRDTSC(void) 259
251 { 260 static __inline__ int
252 if ( CPU_haveCPUID() ) { 261 CPU_haveRDTSC(void)
253 return (CPU_getCPUIDFeatures() & 0x00000010); 262 {
254 } 263 if (CPU_haveCPUID()) {
255 return 0; 264 return (CPU_getCPUIDFeatures() & 0x00000010);
256 } 265 }
257 266 return 0;
258 static __inline__ int CPU_haveMMX(void) 267 }
259 { 268
260 if ( CPU_haveCPUID() ) { 269 static __inline__ int
261 return (CPU_getCPUIDFeatures() & 0x00800000); 270 CPU_haveMMX(void)
262 } 271 {
263 return 0; 272 if (CPU_haveCPUID()) {
264 } 273 return (CPU_getCPUIDFeatures() & 0x00800000);
265 274 }
266 static __inline__ int CPU_haveMMXExt(void) 275 return 0;
267 { 276 }
268 if ( CPU_haveCPUID() ) { 277
269 return (CPU_getCPUIDFeaturesExt() & 0x00400000); 278 static __inline__ int
270 } 279 CPU_haveMMXExt(void)
271 return 0; 280 {
272 } 281 if (CPU_haveCPUID()) {
273 282 return (CPU_getCPUIDFeaturesExt() & 0x00400000);
274 static __inline__ int CPU_have3DNow(void) 283 }
275 { 284 return 0;
276 if ( CPU_haveCPUID() ) { 285 }
277 return (CPU_getCPUIDFeaturesExt() & 0x80000000); 286
278 } 287 static __inline__ int
279 return 0; 288 CPU_have3DNow(void)
280 } 289 {
281 290 if (CPU_haveCPUID()) {
282 static __inline__ int CPU_have3DNowExt(void) 291 return (CPU_getCPUIDFeaturesExt() & 0x80000000);
283 { 292 }
284 if ( CPU_haveCPUID() ) { 293 return 0;
285 return (CPU_getCPUIDFeaturesExt() & 0x40000000); 294 }
286 } 295
287 return 0; 296 static __inline__ int
288 } 297 CPU_have3DNowExt(void)
289 298 {
290 static __inline__ int CPU_haveSSE(void) 299 if (CPU_haveCPUID()) {
291 { 300 return (CPU_getCPUIDFeaturesExt() & 0x40000000);
292 if ( CPU_haveCPUID() ) { 301 }
293 return (CPU_getCPUIDFeatures() & 0x02000000); 302 return 0;
294 } 303 }
295 return 0; 304
296 } 305 static __inline__ int
297 306 CPU_haveSSE(void)
298 static __inline__ int CPU_haveSSE2(void) 307 {
299 { 308 if (CPU_haveCPUID()) {
300 if ( CPU_haveCPUID() ) { 309 return (CPU_getCPUIDFeatures() & 0x02000000);
301 return (CPU_getCPUIDFeatures() & 0x04000000); 310 }
302 } 311 return 0;
303 return 0; 312 }
304 } 313
305 314 static __inline__ int
306 static __inline__ int CPU_haveAltiVec(void) 315 CPU_haveSSE2(void)
307 { 316 {
308 volatile int altivec = 0; 317 if (CPU_haveCPUID()) {
318 return (CPU_getCPUIDFeatures() & 0x04000000);
319 }
320 return 0;
321 }
322
323 static __inline__ int
324 CPU_haveAltiVec(void)
325 {
326 volatile int altivec = 0;
309 #if defined(__MACOSX__) && defined(__ppc__) 327 #if defined(__MACOSX__) && defined(__ppc__)
310 int selectors[2] = { CTL_HW, HW_VECTORUNIT }; 328 int selectors[2] = { CTL_HW, HW_VECTORUNIT };
311 int hasVectorUnit = 0; 329 int hasVectorUnit = 0;
312 size_t length = sizeof(hasVectorUnit); 330 size_t length = sizeof(hasVectorUnit);
313 int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0); 331 int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
314 if( 0 == error ) 332 if (0 == error)
315 altivec = (hasVectorUnit != 0); 333 altivec = (hasVectorUnit != 0);
316 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP 334 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
317 void (*handler)(int sig); 335 void (*handler) (int sig);
318 handler = signal(SIGILL, illegal_instruction); 336 handler = signal(SIGILL, illegal_instruction);
319 if ( setjmp(jmpbuf) == 0 ) { 337 if (setjmp(jmpbuf) == 0) {
320 asm volatile ("mtspr 256, %0\n\t" 338 asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1));
321 "vand %%v0, %%v0, %%v0" 339 altivec = 1;
322 : 340 }
323 : "r" (-1)); 341 signal(SIGILL, handler);
324 altivec = 1; 342 #endif
325 } 343 return altivec;
326 signal(SIGILL, handler);
327 #endif
328 return altivec;
329 } 344 }
330 345
331 static Uint32 SDL_CPUFeatures = 0xFFFFFFFF; 346 static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
332 347
333 static Uint32 SDL_GetCPUFeatures(void) 348 static Uint32
334 { 349 SDL_GetCPUFeatures(void)
335 if ( SDL_CPUFeatures == 0xFFFFFFFF ) { 350 {
336 SDL_CPUFeatures = 0; 351 if (SDL_CPUFeatures == 0xFFFFFFFF) {
337 if ( CPU_haveRDTSC() ) { 352 SDL_CPUFeatures = 0;
338 SDL_CPUFeatures |= CPU_HAS_RDTSC; 353 if (CPU_haveRDTSC()) {
339 } 354 SDL_CPUFeatures |= CPU_HAS_RDTSC;
340 if ( CPU_haveMMX() ) { 355 }
341 SDL_CPUFeatures |= CPU_HAS_MMX; 356 if (CPU_haveMMX()) {
342 } 357 SDL_CPUFeatures |= CPU_HAS_MMX;
343 if ( CPU_haveMMXExt() ) { 358 }
344 SDL_CPUFeatures |= CPU_HAS_MMXEXT; 359 if (CPU_haveMMXExt()) {
345 } 360 SDL_CPUFeatures |= CPU_HAS_MMXEXT;
346 if ( CPU_have3DNow() ) { 361 }
347 SDL_CPUFeatures |= CPU_HAS_3DNOW; 362 if (CPU_have3DNow()) {
348 } 363 SDL_CPUFeatures |= CPU_HAS_3DNOW;
349 if ( CPU_have3DNowExt() ) { 364 }
350 SDL_CPUFeatures |= CPU_HAS_3DNOWEXT; 365 if (CPU_have3DNowExt()) {
351 } 366 SDL_CPUFeatures |= CPU_HAS_3DNOWEXT;
352 if ( CPU_haveSSE() ) { 367 }
353 SDL_CPUFeatures |= CPU_HAS_SSE; 368 if (CPU_haveSSE()) {
354 } 369 SDL_CPUFeatures |= CPU_HAS_SSE;
355 if ( CPU_haveSSE2() ) { 370 }
356 SDL_CPUFeatures |= CPU_HAS_SSE2; 371 if (CPU_haveSSE2()) {
357 } 372 SDL_CPUFeatures |= CPU_HAS_SSE2;
358 if ( CPU_haveAltiVec() ) { 373 }
359 SDL_CPUFeatures |= CPU_HAS_ALTIVEC; 374 if (CPU_haveAltiVec()) {
360 } 375 SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
361 } 376 }
362 return SDL_CPUFeatures; 377 }
363 } 378 return SDL_CPUFeatures;
364 379 }
365 SDL_bool SDL_HasRDTSC(void) 380
366 { 381 SDL_bool
367 if ( SDL_GetCPUFeatures() & CPU_HAS_RDTSC ) { 382 SDL_HasRDTSC(void)
368 return SDL_TRUE; 383 {
369 } 384 if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) {
370 return SDL_FALSE; 385 return SDL_TRUE;
371 } 386 }
372 387 return SDL_FALSE;
373 SDL_bool SDL_HasMMX(void) 388 }
374 { 389
375 if ( SDL_GetCPUFeatures() & CPU_HAS_MMX ) { 390 SDL_bool
376 return SDL_TRUE; 391 SDL_HasMMX(void)
377 } 392 {
378 return SDL_FALSE; 393 if (SDL_GetCPUFeatures() & CPU_HAS_MMX) {
379 } 394 return SDL_TRUE;
380 395 }
381 SDL_bool SDL_HasMMXExt(void) 396 return SDL_FALSE;
382 { 397 }
383 if ( SDL_GetCPUFeatures() & CPU_HAS_MMXEXT ) { 398
384 return SDL_TRUE; 399 SDL_bool
385 } 400 SDL_HasMMXExt(void)
386 return SDL_FALSE; 401 {
387 } 402 if (SDL_GetCPUFeatures() & CPU_HAS_MMXEXT) {
388 403 return SDL_TRUE;
389 SDL_bool SDL_Has3DNow(void) 404 }
390 { 405 return SDL_FALSE;
391 if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOW ) { 406 }
392 return SDL_TRUE; 407
393 } 408 SDL_bool
394 return SDL_FALSE; 409 SDL_Has3DNow(void)
395 } 410 {
396 411 if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) {
397 SDL_bool SDL_Has3DNowExt(void) 412 return SDL_TRUE;
398 { 413 }
399 if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOWEXT ) { 414 return SDL_FALSE;
400 return SDL_TRUE; 415 }
401 } 416
402 return SDL_FALSE; 417 SDL_bool
403 } 418 SDL_Has3DNowExt(void)
404 419 {
405 SDL_bool SDL_HasSSE(void) 420 if (SDL_GetCPUFeatures() & CPU_HAS_3DNOWEXT) {
406 { 421 return SDL_TRUE;
407 if ( SDL_GetCPUFeatures() & CPU_HAS_SSE ) { 422 }
408 return SDL_TRUE; 423 return SDL_FALSE;
409 } 424 }
410 return SDL_FALSE; 425
411 } 426 SDL_bool
412 427 SDL_HasSSE(void)
413 SDL_bool SDL_HasSSE2(void) 428 {
414 { 429 if (SDL_GetCPUFeatures() & CPU_HAS_SSE) {
415 if ( SDL_GetCPUFeatures() & CPU_HAS_SSE2 ) { 430 return SDL_TRUE;
416 return SDL_TRUE; 431 }
417 } 432 return SDL_FALSE;
418 return SDL_FALSE; 433 }
419 } 434
420 435 SDL_bool
421 SDL_bool SDL_HasAltiVec(void) 436 SDL_HasSSE2(void)
422 { 437 {
423 if ( SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC ) { 438 if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) {
424 return SDL_TRUE; 439 return SDL_TRUE;
425 } 440 }
426 return SDL_FALSE; 441 return SDL_FALSE;
442 }
443
444 SDL_bool
445 SDL_HasAltiVec(void)
446 {
447 if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) {
448 return SDL_TRUE;
449 }
450 return SDL_FALSE;
427 } 451 }
428 452
429 #ifdef TEST_MAIN 453 #ifdef TEST_MAIN
430 454
431 #include <stdio.h> 455 #include <stdio.h>
432 456
433 int main() 457 int
434 { 458 main()
435 printf("RDTSC: %d\n", SDL_HasRDTSC()); 459 {
436 printf("MMX: %d\n", SDL_HasMMX()); 460 printf("RDTSC: %d\n", SDL_HasRDTSC());
437 printf("MMXExt: %d\n", SDL_HasMMXExt()); 461 printf("MMX: %d\n", SDL_HasMMX());
438 printf("3DNow: %d\n", SDL_Has3DNow()); 462 printf("MMXExt: %d\n", SDL_HasMMXExt());
439 printf("3DNowExt: %d\n", SDL_Has3DNowExt()); 463 printf("3DNow: %d\n", SDL_Has3DNow());
440 printf("SSE: %d\n", SDL_HasSSE()); 464 printf("3DNowExt: %d\n", SDL_Has3DNowExt());
441 printf("SSE2: %d\n", SDL_HasSSE2()); 465 printf("SSE: %d\n", SDL_HasSSE());
442 printf("AltiVec: %d\n", SDL_HasAltiVec()); 466 printf("SSE2: %d\n", SDL_HasSSE2());
443 return 0; 467 printf("AltiVec: %d\n", SDL_HasAltiVec());
468 return 0;
444 } 469 }
445 470
446 #endif /* TEST_MAIN */ 471 #endif /* TEST_MAIN */
472
473 /* vi: set ts=4 sw=4 expandtab: */