Mercurial > sdl-ios-xcode
comparison src/cpuinfo/SDL_cpuinfo.c @ 5264:6a65c1fc07af
Updated CPU detection code for SSE3 and SSE4 and removed obsolete 3DNow! and Altivec support.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 11 Feb 2011 14:51:04 -0800 |
parents | b3f075368b1f |
children | b530ef003506 |
comparison
equal
deleted
inserted
replaced
5263:f26314c20071 | 5264:6a65c1fc07af |
---|---|
30 #endif | 30 #endif |
31 #ifdef HAVE_SYSCTLBYNAME | 31 #ifdef HAVE_SYSCTLBYNAME |
32 #include <sys/types.h> | 32 #include <sys/types.h> |
33 #include <sys/sysctl.h> | 33 #include <sys/sysctl.h> |
34 #endif | 34 #endif |
35 #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__)) | |
36 #include <sys/sysctl.h> /* For AltiVec check */ | |
37 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP | |
38 #include <signal.h> | |
39 #include <setjmp.h> | |
40 #endif | |
41 #ifdef __WIN32__ | 35 #ifdef __WIN32__ |
42 #include "../core/windows/SDL_windows.h" | 36 #include "../core/windows/SDL_windows.h" |
43 #endif | 37 #endif |
44 | 38 |
45 #define CPU_HAS_RDTSC 0x00000001 | 39 #define CPU_HAS_RDTSC 0x00000001 |
46 #define CPU_HAS_MMX 0x00000002 | 40 #define CPU_HAS_MMX 0x00000002 |
47 #define CPU_HAS_MMXEXT 0x00000004 | 41 #define CPU_HAS_SSE 0x00000010 |
48 #define CPU_HAS_3DNOW 0x00000010 | 42 #define CPU_HAS_SSE2 0x00000020 |
49 #define CPU_HAS_3DNOWEXT 0x00000020 | 43 #define CPU_HAS_SSE3 0x00000040 |
50 #define CPU_HAS_SSE 0x00000040 | 44 #define CPU_HAS_SSE4 0x00000080 |
51 #define CPU_HAS_SSE2 0x00000080 | 45 |
52 #define CPU_HAS_ALTIVEC 0x00000100 | |
53 | |
54 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ | |
55 /* This is the brute force way of detecting instruction sets... | |
56 the idea is borrowed from the libmpeg2 library - thanks! | |
57 */ | |
58 static jmp_buf jmpbuf; | |
59 static void | |
60 illegal_instruction(int sig) | |
61 { | |
62 longjmp(jmpbuf, 1); | |
63 } | |
64 #endif /* HAVE_SETJMP */ | |
65 | 46 |
66 static __inline__ int | 47 static __inline__ int |
67 CPU_haveCPUID(void) | 48 CPU_haveCPUID(void) |
68 { | 49 { |
69 int has_CPUID = 0; | 50 int has_CPUID = 0; |
200 } | 181 } |
201 return features; | 182 return features; |
202 } | 183 } |
203 | 184 |
204 static __inline__ int | 185 static __inline__ int |
205 CPU_getCPUIDFeaturesExt(void) | |
206 { | |
207 int features = 0; | |
208 int a, b, c, d; | |
209 | |
210 cpuid(0x80000000, a, b, c, d); | |
211 if (a >= 0x80000001) { | |
212 cpuid(0x80000001, a, b, c, d); | |
213 features = d; | |
214 } | |
215 return features; | |
216 } | |
217 | |
218 static __inline__ int | |
219 CPU_haveRDTSC(void) | 186 CPU_haveRDTSC(void) |
220 { | 187 { |
221 if (CPU_haveCPUID()) { | 188 if (CPU_haveCPUID()) { |
222 return (CPU_getCPUIDFeatures() & 0x00000010); | 189 return (CPU_getCPUIDFeatures() & 0x00000010); |
223 } | 190 } |
232 } | 199 } |
233 return 0; | 200 return 0; |
234 } | 201 } |
235 | 202 |
236 static __inline__ int | 203 static __inline__ int |
237 CPU_haveMMXExt(void) | |
238 { | |
239 if (CPU_haveCPUID()) { | |
240 return (CPU_getCPUIDFeaturesExt() & 0x00400000); | |
241 } | |
242 return 0; | |
243 } | |
244 | |
245 static __inline__ int | |
246 CPU_have3DNow(void) | |
247 { | |
248 if (CPU_haveCPUID()) { | |
249 return (CPU_getCPUIDFeaturesExt() & 0x80000000); | |
250 } | |
251 return 0; | |
252 } | |
253 | |
254 static __inline__ int | |
255 CPU_have3DNowExt(void) | |
256 { | |
257 if (CPU_haveCPUID()) { | |
258 return (CPU_getCPUIDFeaturesExt() & 0x40000000); | |
259 } | |
260 return 0; | |
261 } | |
262 | |
263 static __inline__ int | |
264 CPU_haveSSE(void) | 204 CPU_haveSSE(void) |
265 { | 205 { |
266 if (CPU_haveCPUID()) { | 206 if (CPU_haveCPUID()) { |
267 return (CPU_getCPUIDFeatures() & 0x02000000); | 207 return (CPU_getCPUIDFeatures() & 0x02000000); |
268 } | 208 } |
277 } | 217 } |
278 return 0; | 218 return 0; |
279 } | 219 } |
280 | 220 |
281 static __inline__ int | 221 static __inline__ int |
282 CPU_haveAltiVec(void) | 222 CPU_haveSSE3(void) |
283 { | 223 { |
284 volatile int altivec = 0; | 224 if (CPU_haveCPUID()) { |
285 #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__)) | 225 int a, b, c, d; |
286 int selectors[2] = { CTL_HW, HW_VECTORUNIT }; | 226 |
287 int hasVectorUnit = 0; | 227 cpuid(0, a, b, c, d); |
288 size_t length = sizeof(hasVectorUnit); | 228 if (a >= 1) { |
289 int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0); | 229 cpuid(1, a, b, c, d); |
290 if (0 == error) | 230 return (c & 0x00000001); |
291 altivec = (hasVectorUnit != 0); | 231 } |
292 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP | 232 } |
293 void (*handler) (int sig); | 233 return 0; |
294 handler = signal(SIGILL, illegal_instruction); | 234 } |
295 if (setjmp(jmpbuf) == 0) { | 235 |
296 asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1)); | 236 static __inline__ int |
297 altivec = 1; | 237 CPU_haveSSE4(void) |
298 } | 238 { |
299 signal(SIGILL, handler); | 239 if (CPU_haveCPUID()) { |
300 #endif | 240 int a, b, c, d; |
301 return altivec; | 241 |
242 cpuid(0, a, b, c, d); | |
243 if (a >= 1) { | |
244 cpuid(1, a, b, c, d); | |
245 return (c & 0x00000100); | |
246 } | |
247 } | |
248 return 0; | |
302 } | 249 } |
303 | 250 |
304 static int SDL_CPUCount = 0; | 251 static int SDL_CPUCount = 0; |
305 | 252 |
306 int | 253 int |
469 SDL_CPUFeatures |= CPU_HAS_RDTSC; | 416 SDL_CPUFeatures |= CPU_HAS_RDTSC; |
470 } | 417 } |
471 if (CPU_haveMMX()) { | 418 if (CPU_haveMMX()) { |
472 SDL_CPUFeatures |= CPU_HAS_MMX; | 419 SDL_CPUFeatures |= CPU_HAS_MMX; |
473 } | 420 } |
474 if (CPU_haveMMXExt()) { | |
475 SDL_CPUFeatures |= CPU_HAS_MMXEXT; | |
476 } | |
477 if (CPU_have3DNow()) { | |
478 SDL_CPUFeatures |= CPU_HAS_3DNOW; | |
479 } | |
480 if (CPU_have3DNowExt()) { | |
481 SDL_CPUFeatures |= CPU_HAS_3DNOWEXT; | |
482 } | |
483 if (CPU_haveSSE()) { | 421 if (CPU_haveSSE()) { |
484 SDL_CPUFeatures |= CPU_HAS_SSE; | 422 SDL_CPUFeatures |= CPU_HAS_SSE; |
485 } | 423 } |
486 if (CPU_haveSSE2()) { | 424 if (CPU_haveSSE2()) { |
487 SDL_CPUFeatures |= CPU_HAS_SSE2; | 425 SDL_CPUFeatures |= CPU_HAS_SSE2; |
488 } | 426 } |
489 if (CPU_haveAltiVec()) { | 427 if (CPU_haveSSE3()) { |
490 SDL_CPUFeatures |= CPU_HAS_ALTIVEC; | 428 SDL_CPUFeatures |= CPU_HAS_SSE3; |
429 } | |
430 if (CPU_haveSSE4()) { | |
431 SDL_CPUFeatures |= CPU_HAS_SSE4; | |
491 } | 432 } |
492 } | 433 } |
493 return SDL_CPUFeatures; | 434 return SDL_CPUFeatures; |
494 } | 435 } |
495 | 436 |
510 } | 451 } |
511 return SDL_FALSE; | 452 return SDL_FALSE; |
512 } | 453 } |
513 | 454 |
514 SDL_bool | 455 SDL_bool |
515 SDL_HasMMXExt(void) | |
516 { | |
517 if (SDL_GetCPUFeatures() & CPU_HAS_MMXEXT) { | |
518 return SDL_TRUE; | |
519 } | |
520 return SDL_FALSE; | |
521 } | |
522 | |
523 SDL_bool | |
524 SDL_Has3DNow(void) | |
525 { | |
526 if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) { | |
527 return SDL_TRUE; | |
528 } | |
529 return SDL_FALSE; | |
530 } | |
531 | |
532 SDL_bool | |
533 SDL_Has3DNowExt(void) | |
534 { | |
535 if (SDL_GetCPUFeatures() & CPU_HAS_3DNOWEXT) { | |
536 return SDL_TRUE; | |
537 } | |
538 return SDL_FALSE; | |
539 } | |
540 | |
541 SDL_bool | |
542 SDL_HasSSE(void) | 456 SDL_HasSSE(void) |
543 { | 457 { |
544 if (SDL_GetCPUFeatures() & CPU_HAS_SSE) { | 458 if (SDL_GetCPUFeatures() & CPU_HAS_SSE) { |
545 return SDL_TRUE; | 459 return SDL_TRUE; |
546 } | 460 } |
555 } | 469 } |
556 return SDL_FALSE; | 470 return SDL_FALSE; |
557 } | 471 } |
558 | 472 |
559 SDL_bool | 473 SDL_bool |
560 SDL_HasAltiVec(void) | 474 SDL_HasSSE3(void) |
561 { | 475 { |
562 if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) { | 476 if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) { |
477 return SDL_TRUE; | |
478 } | |
479 return SDL_FALSE; | |
480 } | |
481 | |
482 SDL_bool | |
483 SDL_HasSSE4(void) | |
484 { | |
485 if (SDL_GetCPUFeatures() & CPU_HAS_SSE4) { | |
563 return SDL_TRUE; | 486 return SDL_TRUE; |
564 } | 487 } |
565 return SDL_FALSE; | 488 return SDL_FALSE; |
566 } | 489 } |
567 | 490 |
576 printf("CPU type: %s\n", SDL_GetCPUType()); | 499 printf("CPU type: %s\n", SDL_GetCPUType()); |
577 printf("CPU name: %s\n", SDL_GetCPUName()); | 500 printf("CPU name: %s\n", SDL_GetCPUName()); |
578 printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize()); | 501 printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize()); |
579 printf("RDTSC: %d\n", SDL_HasRDTSC()); | 502 printf("RDTSC: %d\n", SDL_HasRDTSC()); |
580 printf("MMX: %d\n", SDL_HasMMX()); | 503 printf("MMX: %d\n", SDL_HasMMX()); |
581 printf("MMXExt: %d\n", SDL_HasMMXExt()); | |
582 printf("3DNow: %d\n", SDL_Has3DNow()); | |
583 printf("3DNowExt: %d\n", SDL_Has3DNowExt()); | |
584 printf("SSE: %d\n", SDL_HasSSE()); | 504 printf("SSE: %d\n", SDL_HasSSE()); |
585 printf("SSE2: %d\n", SDL_HasSSE2()); | 505 printf("SSE2: %d\n", SDL_HasSSE2()); |
586 printf("AltiVec: %d\n", SDL_HasAltiVec()); | 506 printf("SSE3: %d\n", SDL_HasSSE3()); |
507 printf("SSE4: %d\n", SDL_HasSSE4()); | |
587 return 0; | 508 return 0; |
588 } | 509 } |
589 | 510 |
590 #endif /* TEST_MAIN */ | 511 #endif /* TEST_MAIN */ |
591 | 512 |