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