src/cpuinfo/SDL_cpuinfo.c
changeset 5389 24903690f48a
parent 5263 e1122f31fec5
child 5535 96594ac5fd1a
     1.1 --- a/src/cpuinfo/SDL_cpuinfo.c	Mon Feb 21 23:45:48 2011 -0800
     1.2 +++ b/src/cpuinfo/SDL_cpuinfo.c	Tue Feb 22 21:44:36 2011 -0800
     1.3 @@ -32,18 +32,37 @@
     1.4  #include <sys/types.h>
     1.5  #include <sys/sysctl.h>
     1.6  #endif
     1.7 +#if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
     1.8 +#include <sys/sysctl.h>         /* For AltiVec check */
     1.9 +#elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
    1.10 +#include <signal.h>
    1.11 +#include <setjmp.h>
    1.12 +#endif
    1.13  #ifdef __WIN32__
    1.14  #include "../core/windows/SDL_windows.h"
    1.15  #endif
    1.16  
    1.17  #define CPU_HAS_RDTSC   0x00000001
    1.18 -#define CPU_HAS_MMX     0x00000002
    1.19 +#define CPU_HAS_ALTIVEC 0x00000002
    1.20 +#define CPU_HAS_MMX     0x00000004
    1.21 +#define CPU_HAS_3DNOW   0x00000008
    1.22  #define CPU_HAS_SSE     0x00000010
    1.23  #define CPU_HAS_SSE2    0x00000020
    1.24  #define CPU_HAS_SSE3    0x00000040
    1.25 -#define CPU_HAS_SSE41   0x00000080
    1.26 -#define CPU_HAS_SSE42   0x00000100
    1.27 +#define CPU_HAS_SSE41   0x00000100
    1.28 +#define CPU_HAS_SSE42   0x00000200
    1.29  
    1.30 +#if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__
    1.31 +/* This is the brute force way of detecting instruction sets...
    1.32 +   the idea is borrowed from the libmpeg2 library - thanks!
    1.33 + */
    1.34 +static jmp_buf jmpbuf;
    1.35 +static void
    1.36 +illegal_instruction(int sig)
    1.37 +{
    1.38 +    longjmp(jmpbuf, 1);
    1.39 +}
    1.40 +#endif /* HAVE_SETJMP */
    1.41  
    1.42  static __inline__ int
    1.43  CPU_haveCPUID(void)
    1.44 @@ -193,6 +212,29 @@
    1.45  }
    1.46  
    1.47  static __inline__ int
    1.48 +CPU_haveAltiVec(void)
    1.49 +{
    1.50 +    volatile int altivec = 0;
    1.51 +#if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
    1.52 +    int selectors[2] = { CTL_HW, HW_VECTORUNIT };
    1.53 +    int hasVectorUnit = 0;
    1.54 +    size_t length = sizeof(hasVectorUnit);
    1.55 +    int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
    1.56 +    if (0 == error)
    1.57 +        altivec = (hasVectorUnit != 0);
    1.58 +#elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
    1.59 +    void (*handler) (int sig);
    1.60 +    handler = signal(SIGILL, illegal_instruction);
    1.61 +    if (setjmp(jmpbuf) == 0) {
    1.62 +        asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1));
    1.63 +        altivec = 1;
    1.64 +    }
    1.65 +    signal(SIGILL, handler);
    1.66 +#endif
    1.67 +    return altivec;
    1.68 +}
    1.69 +
    1.70 +static __inline__ int
    1.71  CPU_haveMMX(void)
    1.72  {
    1.73      if (CPU_haveCPUID()) {
    1.74 @@ -202,6 +244,21 @@
    1.75  }
    1.76  
    1.77  static __inline__ int
    1.78 +CPU_have3DNow(void)
    1.79 +{
    1.80 +    if (CPU_haveCPUID()) {
    1.81 +        int a, b, c, d;
    1.82 +
    1.83 +        cpuid(0x80000000, a, b, c, d);
    1.84 +        if (a >= 0x80000001) {
    1.85 +            cpuid(0x80000001, a, b, c, d);
    1.86 +            return (d & 0x80000000);
    1.87 +        }
    1.88 +    }
    1.89 +    return 0;
    1.90 +}
    1.91 +
    1.92 +static __inline__ int
    1.93  CPU_haveSSE(void)
    1.94  {
    1.95      if (CPU_haveCPUID()) {
    1.96 @@ -431,9 +488,15 @@
    1.97          if (CPU_haveRDTSC()) {
    1.98              SDL_CPUFeatures |= CPU_HAS_RDTSC;
    1.99          }
   1.100 +        if (CPU_haveAltiVec()) {
   1.101 +            SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
   1.102 +        }
   1.103          if (CPU_haveMMX()) {
   1.104              SDL_CPUFeatures |= CPU_HAS_MMX;
   1.105          }
   1.106 +        if (CPU_have3DNow()) {
   1.107 +            SDL_CPUFeatures |= CPU_HAS_3DNOW;
   1.108 +        }
   1.109          if (CPU_haveSSE()) {
   1.110              SDL_CPUFeatures |= CPU_HAS_SSE;
   1.111          }
   1.112 @@ -463,6 +526,15 @@
   1.113  }
   1.114  
   1.115  SDL_bool
   1.116 +SDL_HasAltiVec(void)
   1.117 +{
   1.118 +    if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) {
   1.119 +        return SDL_TRUE;
   1.120 +    }
   1.121 +    return SDL_FALSE;
   1.122 +}
   1.123 +
   1.124 +SDL_bool
   1.125  SDL_HasMMX(void)
   1.126  {
   1.127      if (SDL_GetCPUFeatures() & CPU_HAS_MMX) {
   1.128 @@ -472,6 +544,15 @@
   1.129  }
   1.130  
   1.131  SDL_bool
   1.132 +SDL_Has3DNow(void)
   1.133 +{
   1.134 +    if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) {
   1.135 +        return SDL_TRUE;
   1.136 +    }
   1.137 +    return SDL_FALSE;
   1.138 +}
   1.139 +
   1.140 +SDL_bool
   1.141  SDL_HasSSE(void)
   1.142  {
   1.143      if (SDL_GetCPUFeatures() & CPU_HAS_SSE) {
   1.144 @@ -528,7 +609,9 @@
   1.145      printf("CPU name: %s\n", SDL_GetCPUName());
   1.146      printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize());
   1.147      printf("RDTSC: %d\n", SDL_HasRDTSC());
   1.148 +    printf("Altivec: %d\n", SDL_HasAltiVec());
   1.149      printf("MMX: %d\n", SDL_HasMMX());
   1.150 +    printf("3DNow: %d\n", SDL_Has3DNow());
   1.151      printf("SSE: %d\n", SDL_HasSSE());
   1.152      printf("SSE2: %d\n", SDL_HasSSE2());
   1.153      printf("SSE3: %d\n", SDL_HasSSE3());