Mercurial > sdl-ios-xcode
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: */ |