src/cpuinfo/SDL_cpuinfo.c
changeset 3579 3427271a2d75
parent 3515 d94e331e85fa
child 3580 951dd6a5d1a2
     1.1 --- a/src/cpuinfo/SDL_cpuinfo.c	Wed Dec 16 04:48:11 2009 +0000
     1.2 +++ b/src/cpuinfo/SDL_cpuinfo.c	Wed Dec 16 06:53:53 2009 +0000
     1.3 @@ -25,6 +25,10 @@
     1.4  
     1.5  #include "SDL_cpuinfo.h"
     1.6  
     1.7 +#ifdef HAVE_SYSCTLBYNAME
     1.8 +#include <sys/types.h>
     1.9 +#include <sys/sysctl.h>
    1.10 +#endif
    1.11  #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
    1.12  #include <sys/sysctl.h>         /* For AltiVec check */
    1.13  #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
    1.14 @@ -32,14 +36,14 @@
    1.15  #include <setjmp.h>
    1.16  #endif
    1.17  
    1.18 -#define CPU_HAS_RDTSC	0x00000001
    1.19 -#define CPU_HAS_MMX	0x00000002
    1.20 -#define CPU_HAS_MMXEXT	0x00000004
    1.21 -#define CPU_HAS_3DNOW	0x00000010
    1.22 +#define CPU_HAS_RDTSC   0x00000001
    1.23 +#define CPU_HAS_MMX     0x00000002
    1.24 +#define CPU_HAS_MMXEXT  0x00000004
    1.25 +#define CPU_HAS_3DNOW   0x00000010
    1.26  #define CPU_HAS_3DNOWEXT 0x00000020
    1.27 -#define CPU_HAS_SSE	0x00000040
    1.28 -#define CPU_HAS_SSE2	0x00000080
    1.29 -#define CPU_HAS_ALTIVEC	0x00000100
    1.30 +#define CPU_HAS_SSE     0x00000040
    1.31 +#define CPU_HAS_SSE2    0x00000080
    1.32 +#define CPU_HAS_ALTIVEC 0x00000100
    1.33  
    1.34  #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__
    1.35  /* This is the brute force way of detecting instruction sets...
    1.36 @@ -59,7 +63,7 @@
    1.37      int has_CPUID = 0;
    1.38  /* *INDENT-OFF* */
    1.39  #if defined(__GNUC__) && defined(i386)
    1.40 -	__asm__ (
    1.41 +    __asm__ (
    1.42  "        pushfl                      # Get original EFLAGS             \n"
    1.43  "        popl    %%eax                                                 \n"
    1.44  "        movl    %%eax,%%ecx                                           \n"
    1.45 @@ -72,14 +76,14 @@
    1.46  "        jz      1f                  # Processor=80486                 \n"
    1.47  "        movl    $1,%0               # We have CPUID support           \n"
    1.48  "1:                                                                    \n"
    1.49 -	: "=m" (has_CPUID)
    1.50 -	:
    1.51 -	: "%eax", "%ecx"
    1.52 -	);
    1.53 +    : "=m" (has_CPUID)
    1.54 +    :
    1.55 +    : "%eax", "%ecx"
    1.56 +    );
    1.57  #elif defined(__GNUC__) && defined(__x86_64__)
    1.58  /* Technically, if this is being compiled under __x86_64__ then it has 
    1.59  CPUid by definition.  But it's nice to be able to prove it.  :)      */
    1.60 -	__asm__ (
    1.61 +    __asm__ (
    1.62  "        pushfq                      # Get original EFLAGS             \n"
    1.63  "        popq    %%rax                                                 \n"
    1.64  "        movq    %%rax,%%rcx                                           \n"
    1.65 @@ -92,12 +96,12 @@
    1.66  "        jz      1f                  # Processor=80486                 \n"
    1.67  "        movl    $1,%0               # We have CPUID support           \n"
    1.68  "1:                                                                    \n"
    1.69 -	: "=m" (has_CPUID)
    1.70 -	:
    1.71 -	: "%rax", "%rcx"
    1.72 -	);
    1.73 +    : "=m" (has_CPUID)
    1.74 +    :
    1.75 +    : "%rax", "%rcx"
    1.76 +    );
    1.77  #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
    1.78 -	__asm {
    1.79 +    __asm {
    1.80          pushfd                      ; Get original EFLAGS
    1.81          pop     eax
    1.82          mov     ecx, eax
    1.83 @@ -110,24 +114,24 @@
    1.84          jz      done                ; Processor=80486
    1.85          mov     has_CPUID,1         ; We have CPUID support
    1.86  done:
    1.87 -	}
    1.88 +    }
    1.89  #elif defined(__sun) && defined(__i386)
    1.90 -	__asm (
    1.91 +    __asm (
    1.92  "       pushfl                 \n"
    1.93 -"	popl    %eax           \n"
    1.94 -"	movl    %eax,%ecx      \n"
    1.95 -"	xorl    $0x200000,%eax \n"
    1.96 -"	pushl   %eax           \n"
    1.97 -"	popfl                  \n"
    1.98 -"	pushfl                 \n"
    1.99 -"	popl    %eax           \n"
   1.100 -"	xorl    %ecx,%eax      \n"
   1.101 -"	jz      1f             \n"
   1.102 -"	movl    $1,-8(%ebp)    \n"
   1.103 +"   popl    %eax           \n"
   1.104 +"   movl    %eax,%ecx      \n"
   1.105 +"   xorl    $0x200000,%eax \n"
   1.106 +"   pushl   %eax           \n"
   1.107 +"   popfl                  \n"
   1.108 +"   pushfl                 \n"
   1.109 +"   popl    %eax           \n"
   1.110 +"   xorl    %ecx,%eax      \n"
   1.111 +"   jz      1f             \n"
   1.112 +"   movl    $1,-8(%ebp)    \n"
   1.113  "1:                            \n"
   1.114 -	);
   1.115 +    );
   1.116  #elif defined(__sun) && defined(__amd64)
   1.117 -	__asm (
   1.118 +    __asm (
   1.119  "       pushfq                 \n"
   1.120  "       popq    %rax           \n"
   1.121  "       movq    %rax,%rcx      \n"
   1.122 @@ -140,92 +144,42 @@
   1.123  "       jz      1f             \n"
   1.124  "       movl    $1,-8(%rbp)    \n"
   1.125  "1:                            \n"
   1.126 -	);
   1.127 +    );
   1.128  #endif
   1.129  /* *INDENT-ON* */
   1.130      return has_CPUID;
   1.131  }
   1.132  
   1.133 +#if defined(__GNUC__) && (defined(i386) || defined(__x86_64__))
   1.134 +#define cpuid(func, ax, bx, cx, dx) \
   1.135 +    __asm__ __volatile__ ("cpuid": \
   1.136 +    "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func))
   1.137 +#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
   1.138 +#define cpuid(func, ax, bx, cx, dx) \
   1.139 +    asm { \
   1.140 +        mov eax, func \
   1.141 +        cpuid
   1.142 +        mov ax, eax \
   1.143 +        mov bx, ebx \
   1.144 +        mov cx, ecx \
   1.145 +        mov dx, edx \
   1.146 +    }
   1.147 +#else
   1.148 +#define cpuid(func, ax, bx, cx, dx) \
   1.149 +    ax = bx = cx = dx = 0
   1.150 +#endif
   1.151 +
   1.152  static __inline__ int
   1.153  CPU_getCPUIDFeatures(void)
   1.154  {
   1.155      int features = 0;
   1.156 -/* *INDENT-OFF* */
   1.157 -#if defined(__GNUC__) && defined(i386)
   1.158 -	__asm__ (
   1.159 -"        xorl    %%eax,%%eax         # Set up for CPUID instruction    \n"
   1.160 -"        pushl   %%ebx                                                 \n"
   1.161 -"        cpuid                       # Get and save vendor ID          \n"
   1.162 -"        popl    %%ebx                                                 \n"
   1.163 -"        cmpl    $1,%%eax            # Make sure 1 is valid input for CPUID\n"
   1.164 -"        jl      1f                  # We dont have the CPUID instruction\n"
   1.165 -"        xorl    %%eax,%%eax                                           \n"
   1.166 -"        incl    %%eax                                                 \n"
   1.167 -"        pushl   %%ebx                                                 \n"
   1.168 -"        cpuid                       # Get family/model/stepping/features\n"
   1.169 -"        popl    %%ebx                                                 \n"
   1.170 -"        movl    %%edx,%0                                              \n"
   1.171 -"1:                                                                    \n"
   1.172 -	: "=m" (features)
   1.173 -	:
   1.174 -	: "%eax", "%ecx", "%edx"
   1.175 -	);
   1.176 -#elif defined(__GNUC__) && defined(__x86_64__)
   1.177 -	__asm__ (
   1.178 -"        xorl    %%eax,%%eax         # Set up for CPUID instruction    \n"
   1.179 -"        pushq   %%rbx                                                 \n"
   1.180 -"        cpuid                       # Get and save vendor ID          \n"
   1.181 -"        popq    %%rbx                                                 \n"
   1.182 -"        cmpl    $1,%%eax            # Make sure 1 is valid input for CPUID\n"
   1.183 -"        jl      1f                  # We dont have the CPUID instruction\n"
   1.184 -"        xorl    %%eax,%%eax                                           \n"
   1.185 -"        incl    %%eax                                                 \n"
   1.186 -"        pushq   %%rbx                                                 \n"
   1.187 -"        cpuid                       # Get family/model/stepping/features\n"
   1.188 -"        popq    %%rbx                                                 \n"
   1.189 -"        movl    %%edx,%0                                              \n"
   1.190 -"1:                                                                    \n"
   1.191 -	: "=m" (features)
   1.192 -	:
   1.193 -	: "%rax", "%rcx", "%rdx"
   1.194 -	);
   1.195 -#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
   1.196 -	__asm {
   1.197 -        xor     eax, eax            ; Set up for CPUID instruction
   1.198 -        push    ebx
   1.199 -        cpuid                       ; Get and save vendor ID
   1.200 -        pop     ebx
   1.201 -        cmp     eax, 1              ; Make sure 1 is valid input for CPUID
   1.202 -        jl      done                ; We dont have the CPUID instruction
   1.203 -        xor     eax, eax
   1.204 -        inc     eax
   1.205 -        push    ebx
   1.206 -        cpuid                       ; Get family/model/stepping/features
   1.207 -        pop     ebx
   1.208 -        mov     features, edx
   1.209 -done:
   1.210 -	}
   1.211 -#elif defined(__sun) && (defined(__i386) || defined(__amd64))
   1.212 -	    __asm(
   1.213 -"        xorl    %eax,%eax         \n"
   1.214 -"        pushl   %ebx              \n"
   1.215 -"        cpuid                     \n"
   1.216 -"        popl    %ebx              \n"
   1.217 -"        cmpl    $1,%eax           \n"
   1.218 -"        jl      1f                \n"
   1.219 -"        xorl    %eax,%eax         \n"
   1.220 -"        incl    %eax              \n"
   1.221 -"        pushl   %ebx              \n"
   1.222 -"        cpuid                     \n"
   1.223 -"        popl    %ebx              \n"
   1.224 -#ifdef __i386
   1.225 -"        movl    %edx,-8(%ebp)     \n"
   1.226 -#else
   1.227 -"        movl    %edx,-8(%rbp)     \n"
   1.228 -#endif
   1.229 -"1:                                \n"
   1.230 -#endif
   1.231 -/* *INDENT-ON* */
   1.232 +    int ax, bx, cx, dx;
   1.233 +
   1.234 +    cpuid(0, ax, bx, cx, dx);
   1.235 +    if (ax >= 1) {
   1.236 +        cpuid(1, ax, bx, cx, dx);
   1.237 +        features = dx;
   1.238 +    }
   1.239      return features;
   1.240  }
   1.241  
   1.242 @@ -233,79 +187,13 @@
   1.243  CPU_getCPUIDFeaturesExt(void)
   1.244  {
   1.245      int features = 0;
   1.246 -/* *INDENT-OFF* */
   1.247 -#if defined(__GNUC__) && defined(i386)
   1.248 -	__asm__ (
   1.249 -"        movl    $0x80000000,%%eax   # Query for extended functions    \n"
   1.250 -"        pushl   %%ebx                                                 \n"
   1.251 -"        cpuid                       # Get extended function limit     \n"
   1.252 -"        popl    %%ebx                                                 \n"
   1.253 -"        cmpl    $0x80000001,%%eax                                     \n"
   1.254 -"        jl      1f                  # Nope, we dont have function 800000001h\n"
   1.255 -"        movl    $0x80000001,%%eax   # Setup extended function 800000001h\n"
   1.256 -"        pushl   %%ebx                                                 \n"
   1.257 -"        cpuid                       # and get the information         \n"
   1.258 -"        popl    %%ebx                                                 \n"
   1.259 -"        movl    %%edx,%0                                              \n"
   1.260 -"1:                                                                    \n"
   1.261 -	: "=m" (features)
   1.262 -	:
   1.263 -	: "%eax", "%ecx", "%edx"
   1.264 -	);
   1.265 -#elif defined(__GNUC__) && defined (__x86_64__)
   1.266 -	__asm__ (
   1.267 -"        movl    $0x80000000,%%eax   # Query for extended functions    \n"
   1.268 -"        pushq   %%rbx                                                 \n"
   1.269 -"        cpuid                       # Get extended function limit     \n"
   1.270 -"        popq    %%rbx                                                 \n"
   1.271 -"        cmpl    $0x80000001,%%eax                                     \n"
   1.272 -"        jl      1f                  # Nope, we dont have function 800000001h\n"
   1.273 -"        movl    $0x80000001,%%eax   # Setup extended function 800000001h\n"
   1.274 -"        pushq   %%rbx                                                 \n"
   1.275 -"        cpuid                       # and get the information         \n"
   1.276 -"        popq    %%rbx                                                 \n"
   1.277 -"        movl    %%edx,%0                                              \n"
   1.278 -"1:                                                                    \n"
   1.279 -	: "=m" (features)
   1.280 -	:
   1.281 -	: "%rax", "%rcx", "%rdx"
   1.282 -	);
   1.283 -#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
   1.284 -	__asm {
   1.285 -        mov     eax,80000000h       ; Query for extended functions
   1.286 -        push    ebx
   1.287 -        cpuid                       ; Get extended function limit
   1.288 -        pop     ebx
   1.289 -        cmp     eax,80000001h
   1.290 -        jl      done                ; Nope, we dont have function 800000001h
   1.291 -        mov     eax,80000001h       ; Setup extended function 800000001h
   1.292 -        push    ebx
   1.293 -        cpuid                       ; and get the information
   1.294 -        pop     ebx
   1.295 -        mov     features,edx
   1.296 -done:
   1.297 -	}
   1.298 -#elif defined(__sun) && ( defined(__i386) || defined(__amd64) )
   1.299 -	    __asm (
   1.300 -"        movl    $0x80000000,%eax \n"
   1.301 -"        pushl   %ebx             \n"
   1.302 -"        cpuid                    \n"
   1.303 -"        popl    %ebx             \n"
   1.304 -"        cmpl    $0x80000001,%eax \n"
   1.305 -"        jl      1f               \n"
   1.306 -"        movl    $0x80000001,%eax \n"
   1.307 -"        pushl   %ebx             \n"
   1.308 -"        cpuid                    \n"
   1.309 -"        popl    %ebx             \n"
   1.310 -#ifdef __i386
   1.311 -"        movl    %edx,-8(%ebp)    \n"
   1.312 -#else
   1.313 -"        movl    %edx,-8(%rbp)    \n"
   1.314 -#endif
   1.315 -"1:                               \n"
   1.316 -	    );
   1.317 -#endif
   1.318 -/* *INDENT-ON* */
   1.319 +    int ax, bx, cx, dx;
   1.320 +
   1.321 +    cpuid(0x80000000, ax, bx, cx, dx);
   1.322 +    if (ax >= 0x80000001) {
   1.323 +        cpuid(0x80000001, ax, bx, cx, dx);
   1.324 +        features = dx;
   1.325 +    }
   1.326      return features;
   1.327  }
   1.328  
   1.329 @@ -395,6 +283,97 @@
   1.330      return altivec;
   1.331  }
   1.332  
   1.333 +static int SDL_CPUCount = 0;
   1.334 +
   1.335 +int
   1.336 +SDL_GetCPUCount()
   1.337 +{
   1.338 +    if (!SDL_CPUCount) {
   1.339 +#ifdef HAVE_SYSCTLBYNAME
   1.340 +        size_t size = sizeof(SDL_CPUCount);
   1.341 +        sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0);
   1.342 +#endif
   1.343 +        /* There has to be at least 1, right? :) */
   1.344 +        if (!SDL_CPUCount) {
   1.345 +            SDL_CPUCount = 1;
   1.346 +        }
   1.347 +    }
   1.348 +    return SDL_CPUCount;
   1.349 +}
   1.350 +
   1.351 +/* Oh, such a sweet sweet trick, just not very useful. :) */
   1.352 +const char *
   1.353 +SDL_GetCPUType()
   1.354 +{
   1.355 +    static char SDL_CPUType[48];
   1.356 +
   1.357 +    if (!SDL_CPUType[0]) {
   1.358 +        int i = 0;
   1.359 +        int ax, bx, cx, dx;
   1.360 +
   1.361 +        if (CPU_haveCPUID()) {
   1.362 +            cpuid(0x80000000, ax, bx, cx, dx);
   1.363 +            if (ax >= 0x80000004) {
   1.364 +                cpuid(0x80000002, ax, bx, cx, dx);
   1.365 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.366 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.367 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.368 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.369 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.370 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.371 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.372 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.373 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.374 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.375 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.376 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.377 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.378 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.379 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.380 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.381 +                cpuid(0x80000003, ax, bx, cx, dx);
   1.382 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.383 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.384 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.385 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.386 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.387 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.388 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.389 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.390 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.391 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.392 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.393 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.394 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.395 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.396 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.397 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.398 +                cpuid(0x80000004, ax, bx, cx, dx);
   1.399 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.400 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.401 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.402 +                SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
   1.403 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.404 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.405 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.406 +                SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
   1.407 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.408 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.409 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.410 +                SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
   1.411 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.412 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.413 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.414 +                SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
   1.415 +            }
   1.416 +        }
   1.417 +        if (!SDL_CPUType[0]) {
   1.418 +            SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
   1.419 +        }
   1.420 +    }
   1.421 +    return SDL_CPUType;
   1.422 +}
   1.423 +
   1.424  static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
   1.425  
   1.426  static Uint32
   1.427 @@ -509,6 +488,8 @@
   1.428  int
   1.429  main()
   1.430  {
   1.431 +    printf("CPU count: %d\n", SDL_GetCPUCount());
   1.432 +    printf("CPU name: %s\n", SDL_GetCPUType());
   1.433      printf("RDTSC: %d\n", SDL_HasRDTSC());
   1.434      printf("MMX: %d\n", SDL_HasMMX());
   1.435      printf("MMXExt: %d\n", SDL_HasMMXExt());