src/cpuinfo/SDL_cpuinfo.c
changeset 3579 3427271a2d75
parent 3515 d94e331e85fa
child 3580 951dd6a5d1a2
equal deleted inserted replaced
3578:0d1b16ee0bca 3579:3427271a2d75
    23 
    23 
    24 /* CPU feature detection for SDL */
    24 /* CPU feature detection for SDL */
    25 
    25 
    26 #include "SDL_cpuinfo.h"
    26 #include "SDL_cpuinfo.h"
    27 
    27 
       
    28 #ifdef HAVE_SYSCTLBYNAME
       
    29 #include <sys/types.h>
       
    30 #include <sys/sysctl.h>
       
    31 #endif
    28 #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
    32 #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
    29 #include <sys/sysctl.h>         /* For AltiVec check */
    33 #include <sys/sysctl.h>         /* For AltiVec check */
    30 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
    34 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
    31 #include <signal.h>
    35 #include <signal.h>
    32 #include <setjmp.h>
    36 #include <setjmp.h>
    33 #endif
    37 #endif
    34 
    38 
    35 #define CPU_HAS_RDTSC	0x00000001
    39 #define CPU_HAS_RDTSC   0x00000001
    36 #define CPU_HAS_MMX	0x00000002
    40 #define CPU_HAS_MMX     0x00000002
    37 #define CPU_HAS_MMXEXT	0x00000004
    41 #define CPU_HAS_MMXEXT  0x00000004
    38 #define CPU_HAS_3DNOW	0x00000010
    42 #define CPU_HAS_3DNOW   0x00000010
    39 #define CPU_HAS_3DNOWEXT 0x00000020
    43 #define CPU_HAS_3DNOWEXT 0x00000020
    40 #define CPU_HAS_SSE	0x00000040
    44 #define CPU_HAS_SSE     0x00000040
    41 #define CPU_HAS_SSE2	0x00000080
    45 #define CPU_HAS_SSE2    0x00000080
    42 #define CPU_HAS_ALTIVEC	0x00000100
    46 #define CPU_HAS_ALTIVEC 0x00000100
    43 
    47 
    44 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__
    48 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__
    45 /* This is the brute force way of detecting instruction sets...
    49 /* This is the brute force way of detecting instruction sets...
    46    the idea is borrowed from the libmpeg2 library - thanks!
    50    the idea is borrowed from the libmpeg2 library - thanks!
    47  */
    51  */
    57 CPU_haveCPUID(void)
    61 CPU_haveCPUID(void)
    58 {
    62 {
    59     int has_CPUID = 0;
    63     int has_CPUID = 0;
    60 /* *INDENT-OFF* */
    64 /* *INDENT-OFF* */
    61 #if defined(__GNUC__) && defined(i386)
    65 #if defined(__GNUC__) && defined(i386)
    62 	__asm__ (
    66     __asm__ (
    63 "        pushfl                      # Get original EFLAGS             \n"
    67 "        pushfl                      # Get original EFLAGS             \n"
    64 "        popl    %%eax                                                 \n"
    68 "        popl    %%eax                                                 \n"
    65 "        movl    %%eax,%%ecx                                           \n"
    69 "        movl    %%eax,%%ecx                                           \n"
    66 "        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
    70 "        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
    67 "        pushl   %%eax               # Save new EFLAGS value on stack  \n"
    71 "        pushl   %%eax               # Save new EFLAGS value on stack  \n"
    70 "        popl    %%eax               # Store new EFLAGS in EAX         \n"
    74 "        popl    %%eax               # Store new EFLAGS in EAX         \n"
    71 "        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
    75 "        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
    72 "        jz      1f                  # Processor=80486                 \n"
    76 "        jz      1f                  # Processor=80486                 \n"
    73 "        movl    $1,%0               # We have CPUID support           \n"
    77 "        movl    $1,%0               # We have CPUID support           \n"
    74 "1:                                                                    \n"
    78 "1:                                                                    \n"
    75 	: "=m" (has_CPUID)
    79     : "=m" (has_CPUID)
    76 	:
    80     :
    77 	: "%eax", "%ecx"
    81     : "%eax", "%ecx"
    78 	);
    82     );
    79 #elif defined(__GNUC__) && defined(__x86_64__)
    83 #elif defined(__GNUC__) && defined(__x86_64__)
    80 /* Technically, if this is being compiled under __x86_64__ then it has 
    84 /* Technically, if this is being compiled under __x86_64__ then it has 
    81 CPUid by definition.  But it's nice to be able to prove it.  :)      */
    85 CPUid by definition.  But it's nice to be able to prove it.  :)      */
    82 	__asm__ (
    86     __asm__ (
    83 "        pushfq                      # Get original EFLAGS             \n"
    87 "        pushfq                      # Get original EFLAGS             \n"
    84 "        popq    %%rax                                                 \n"
    88 "        popq    %%rax                                                 \n"
    85 "        movq    %%rax,%%rcx                                           \n"
    89 "        movq    %%rax,%%rcx                                           \n"
    86 "        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
    90 "        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
    87 "        pushq   %%rax               # Save new EFLAGS value on stack  \n"
    91 "        pushq   %%rax               # Save new EFLAGS value on stack  \n"
    90 "        popq    %%rax               # Store new EFLAGS in EAX         \n"
    94 "        popq    %%rax               # Store new EFLAGS in EAX         \n"
    91 "        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
    95 "        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
    92 "        jz      1f                  # Processor=80486                 \n"
    96 "        jz      1f                  # Processor=80486                 \n"
    93 "        movl    $1,%0               # We have CPUID support           \n"
    97 "        movl    $1,%0               # We have CPUID support           \n"
    94 "1:                                                                    \n"
    98 "1:                                                                    \n"
    95 	: "=m" (has_CPUID)
    99     : "=m" (has_CPUID)
    96 	:
   100     :
    97 	: "%rax", "%rcx"
   101     : "%rax", "%rcx"
    98 	);
   102     );
    99 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
   103 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
   100 	__asm {
   104     __asm {
   101         pushfd                      ; Get original EFLAGS
   105         pushfd                      ; Get original EFLAGS
   102         pop     eax
   106         pop     eax
   103         mov     ecx, eax
   107         mov     ecx, eax
   104         xor     eax, 200000h        ; Flip ID bit in EFLAGS
   108         xor     eax, 200000h        ; Flip ID bit in EFLAGS
   105         push    eax                 ; Save new EFLAGS value on stack
   109         push    eax                 ; Save new EFLAGS value on stack
   108         pop     eax                 ; Store new EFLAGS in EAX
   112         pop     eax                 ; Store new EFLAGS in EAX
   109         xor     eax, ecx            ; Can not toggle ID bit,
   113         xor     eax, ecx            ; Can not toggle ID bit,
   110         jz      done                ; Processor=80486
   114         jz      done                ; Processor=80486
   111         mov     has_CPUID,1         ; We have CPUID support
   115         mov     has_CPUID,1         ; We have CPUID support
   112 done:
   116 done:
   113 	}
   117     }
   114 #elif defined(__sun) && defined(__i386)
   118 #elif defined(__sun) && defined(__i386)
   115 	__asm (
   119     __asm (
   116 "       pushfl                 \n"
   120 "       pushfl                 \n"
   117 "	popl    %eax           \n"
   121 "   popl    %eax           \n"
   118 "	movl    %eax,%ecx      \n"
   122 "   movl    %eax,%ecx      \n"
   119 "	xorl    $0x200000,%eax \n"
   123 "   xorl    $0x200000,%eax \n"
   120 "	pushl   %eax           \n"
   124 "   pushl   %eax           \n"
   121 "	popfl                  \n"
   125 "   popfl                  \n"
   122 "	pushfl                 \n"
   126 "   pushfl                 \n"
   123 "	popl    %eax           \n"
   127 "   popl    %eax           \n"
   124 "	xorl    %ecx,%eax      \n"
   128 "   xorl    %ecx,%eax      \n"
   125 "	jz      1f             \n"
   129 "   jz      1f             \n"
   126 "	movl    $1,-8(%ebp)    \n"
   130 "   movl    $1,-8(%ebp)    \n"
   127 "1:                            \n"
   131 "1:                            \n"
   128 	);
   132     );
   129 #elif defined(__sun) && defined(__amd64)
   133 #elif defined(__sun) && defined(__amd64)
   130 	__asm (
   134     __asm (
   131 "       pushfq                 \n"
   135 "       pushfq                 \n"
   132 "       popq    %rax           \n"
   136 "       popq    %rax           \n"
   133 "       movq    %rax,%rcx      \n"
   137 "       movq    %rax,%rcx      \n"
   134 "       xorl    $0x200000,%eax \n"
   138 "       xorl    $0x200000,%eax \n"
   135 "       pushq   %rax           \n"
   139 "       pushq   %rax           \n"
   138 "       popq    %rax           \n"
   142 "       popq    %rax           \n"
   139 "       xorl    %ecx,%eax      \n"
   143 "       xorl    %ecx,%eax      \n"
   140 "       jz      1f             \n"
   144 "       jz      1f             \n"
   141 "       movl    $1,-8(%rbp)    \n"
   145 "       movl    $1,-8(%rbp)    \n"
   142 "1:                            \n"
   146 "1:                            \n"
   143 	);
   147     );
   144 #endif
   148 #endif
   145 /* *INDENT-ON* */
   149 /* *INDENT-ON* */
   146     return has_CPUID;
   150     return has_CPUID;
   147 }
   151 }
   148 
   152 
       
   153 #if defined(__GNUC__) && (defined(i386) || defined(__x86_64__))
       
   154 #define cpuid(func, ax, bx, cx, dx) \
       
   155     __asm__ __volatile__ ("cpuid": \
       
   156     "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func))
       
   157 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
       
   158 #define cpuid(func, ax, bx, cx, dx) \
       
   159     asm { \
       
   160         mov eax, func \
       
   161         cpuid
       
   162         mov ax, eax \
       
   163         mov bx, ebx \
       
   164         mov cx, ecx \
       
   165         mov dx, edx \
       
   166     }
       
   167 #else
       
   168 #define cpuid(func, ax, bx, cx, dx) \
       
   169     ax = bx = cx = dx = 0
       
   170 #endif
       
   171 
   149 static __inline__ int
   172 static __inline__ int
   150 CPU_getCPUIDFeatures(void)
   173 CPU_getCPUIDFeatures(void)
   151 {
   174 {
   152     int features = 0;
   175     int features = 0;
   153 /* *INDENT-OFF* */
   176     int ax, bx, cx, dx;
   154 #if defined(__GNUC__) && defined(i386)
   177 
   155 	__asm__ (
   178     cpuid(0, ax, bx, cx, dx);
   156 "        xorl    %%eax,%%eax         # Set up for CPUID instruction    \n"
   179     if (ax >= 1) {
   157 "        pushl   %%ebx                                                 \n"
   180         cpuid(1, ax, bx, cx, dx);
   158 "        cpuid                       # Get and save vendor ID          \n"
   181         features = dx;
   159 "        popl    %%ebx                                                 \n"
   182     }
   160 "        cmpl    $1,%%eax            # Make sure 1 is valid input for CPUID\n"
       
   161 "        jl      1f                  # We dont have the CPUID instruction\n"
       
   162 "        xorl    %%eax,%%eax                                           \n"
       
   163 "        incl    %%eax                                                 \n"
       
   164 "        pushl   %%ebx                                                 \n"
       
   165 "        cpuid                       # Get family/model/stepping/features\n"
       
   166 "        popl    %%ebx                                                 \n"
       
   167 "        movl    %%edx,%0                                              \n"
       
   168 "1:                                                                    \n"
       
   169 	: "=m" (features)
       
   170 	:
       
   171 	: "%eax", "%ecx", "%edx"
       
   172 	);
       
   173 #elif defined(__GNUC__) && defined(__x86_64__)
       
   174 	__asm__ (
       
   175 "        xorl    %%eax,%%eax         # Set up for CPUID instruction    \n"
       
   176 "        pushq   %%rbx                                                 \n"
       
   177 "        cpuid                       # Get and save vendor ID          \n"
       
   178 "        popq    %%rbx                                                 \n"
       
   179 "        cmpl    $1,%%eax            # Make sure 1 is valid input for CPUID\n"
       
   180 "        jl      1f                  # We dont have the CPUID instruction\n"
       
   181 "        xorl    %%eax,%%eax                                           \n"
       
   182 "        incl    %%eax                                                 \n"
       
   183 "        pushq   %%rbx                                                 \n"
       
   184 "        cpuid                       # Get family/model/stepping/features\n"
       
   185 "        popq    %%rbx                                                 \n"
       
   186 "        movl    %%edx,%0                                              \n"
       
   187 "1:                                                                    \n"
       
   188 	: "=m" (features)
       
   189 	:
       
   190 	: "%rax", "%rcx", "%rdx"
       
   191 	);
       
   192 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
       
   193 	__asm {
       
   194         xor     eax, eax            ; Set up for CPUID instruction
       
   195         push    ebx
       
   196         cpuid                       ; Get and save vendor ID
       
   197         pop     ebx
       
   198         cmp     eax, 1              ; Make sure 1 is valid input for CPUID
       
   199         jl      done                ; We dont have the CPUID instruction
       
   200         xor     eax, eax
       
   201         inc     eax
       
   202         push    ebx
       
   203         cpuid                       ; Get family/model/stepping/features
       
   204         pop     ebx
       
   205         mov     features, edx
       
   206 done:
       
   207 	}
       
   208 #elif defined(__sun) && (defined(__i386) || defined(__amd64))
       
   209 	    __asm(
       
   210 "        xorl    %eax,%eax         \n"
       
   211 "        pushl   %ebx              \n"
       
   212 "        cpuid                     \n"
       
   213 "        popl    %ebx              \n"
       
   214 "        cmpl    $1,%eax           \n"
       
   215 "        jl      1f                \n"
       
   216 "        xorl    %eax,%eax         \n"
       
   217 "        incl    %eax              \n"
       
   218 "        pushl   %ebx              \n"
       
   219 "        cpuid                     \n"
       
   220 "        popl    %ebx              \n"
       
   221 #ifdef __i386
       
   222 "        movl    %edx,-8(%ebp)     \n"
       
   223 #else
       
   224 "        movl    %edx,-8(%rbp)     \n"
       
   225 #endif
       
   226 "1:                                \n"
       
   227 #endif
       
   228 /* *INDENT-ON* */
       
   229     return features;
   183     return features;
   230 }
   184 }
   231 
   185 
   232 static __inline__ int
   186 static __inline__ int
   233 CPU_getCPUIDFeaturesExt(void)
   187 CPU_getCPUIDFeaturesExt(void)
   234 {
   188 {
   235     int features = 0;
   189     int features = 0;
   236 /* *INDENT-OFF* */
   190     int ax, bx, cx, dx;
   237 #if defined(__GNUC__) && defined(i386)
   191 
   238 	__asm__ (
   192     cpuid(0x80000000, ax, bx, cx, dx);
   239 "        movl    $0x80000000,%%eax   # Query for extended functions    \n"
   193     if (ax >= 0x80000001) {
   240 "        pushl   %%ebx                                                 \n"
   194         cpuid(0x80000001, ax, bx, cx, dx);
   241 "        cpuid                       # Get extended function limit     \n"
   195         features = dx;
   242 "        popl    %%ebx                                                 \n"
   196     }
   243 "        cmpl    $0x80000001,%%eax                                     \n"
       
   244 "        jl      1f                  # Nope, we dont have function 800000001h\n"
       
   245 "        movl    $0x80000001,%%eax   # Setup extended function 800000001h\n"
       
   246 "        pushl   %%ebx                                                 \n"
       
   247 "        cpuid                       # and get the information         \n"
       
   248 "        popl    %%ebx                                                 \n"
       
   249 "        movl    %%edx,%0                                              \n"
       
   250 "1:                                                                    \n"
       
   251 	: "=m" (features)
       
   252 	:
       
   253 	: "%eax", "%ecx", "%edx"
       
   254 	);
       
   255 #elif defined(__GNUC__) && defined (__x86_64__)
       
   256 	__asm__ (
       
   257 "        movl    $0x80000000,%%eax   # Query for extended functions    \n"
       
   258 "        pushq   %%rbx                                                 \n"
       
   259 "        cpuid                       # Get extended function limit     \n"
       
   260 "        popq    %%rbx                                                 \n"
       
   261 "        cmpl    $0x80000001,%%eax                                     \n"
       
   262 "        jl      1f                  # Nope, we dont have function 800000001h\n"
       
   263 "        movl    $0x80000001,%%eax   # Setup extended function 800000001h\n"
       
   264 "        pushq   %%rbx                                                 \n"
       
   265 "        cpuid                       # and get the information         \n"
       
   266 "        popq    %%rbx                                                 \n"
       
   267 "        movl    %%edx,%0                                              \n"
       
   268 "1:                                                                    \n"
       
   269 	: "=m" (features)
       
   270 	:
       
   271 	: "%rax", "%rcx", "%rdx"
       
   272 	);
       
   273 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
       
   274 	__asm {
       
   275         mov     eax,80000000h       ; Query for extended functions
       
   276         push    ebx
       
   277         cpuid                       ; Get extended function limit
       
   278         pop     ebx
       
   279         cmp     eax,80000001h
       
   280         jl      done                ; Nope, we dont have function 800000001h
       
   281         mov     eax,80000001h       ; Setup extended function 800000001h
       
   282         push    ebx
       
   283         cpuid                       ; and get the information
       
   284         pop     ebx
       
   285         mov     features,edx
       
   286 done:
       
   287 	}
       
   288 #elif defined(__sun) && ( defined(__i386) || defined(__amd64) )
       
   289 	    __asm (
       
   290 "        movl    $0x80000000,%eax \n"
       
   291 "        pushl   %ebx             \n"
       
   292 "        cpuid                    \n"
       
   293 "        popl    %ebx             \n"
       
   294 "        cmpl    $0x80000001,%eax \n"
       
   295 "        jl      1f               \n"
       
   296 "        movl    $0x80000001,%eax \n"
       
   297 "        pushl   %ebx             \n"
       
   298 "        cpuid                    \n"
       
   299 "        popl    %ebx             \n"
       
   300 #ifdef __i386
       
   301 "        movl    %edx,-8(%ebp)    \n"
       
   302 #else
       
   303 "        movl    %edx,-8(%rbp)    \n"
       
   304 #endif
       
   305 "1:                               \n"
       
   306 	    );
       
   307 #endif
       
   308 /* *INDENT-ON* */
       
   309     return features;
   197     return features;
   310 }
   198 }
   311 
   199 
   312 static __inline__ int
   200 static __inline__ int
   313 CPU_haveRDTSC(void)
   201 CPU_haveRDTSC(void)
   393     signal(SIGILL, handler);
   281     signal(SIGILL, handler);
   394 #endif
   282 #endif
   395     return altivec;
   283     return altivec;
   396 }
   284 }
   397 
   285 
       
   286 static int SDL_CPUCount = 0;
       
   287 
       
   288 int
       
   289 SDL_GetCPUCount()
       
   290 {
       
   291     if (!SDL_CPUCount) {
       
   292 #ifdef HAVE_SYSCTLBYNAME
       
   293         size_t size = sizeof(SDL_CPUCount);
       
   294         sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0);
       
   295 #endif
       
   296         /* There has to be at least 1, right? :) */
       
   297         if (!SDL_CPUCount) {
       
   298             SDL_CPUCount = 1;
       
   299         }
       
   300     }
       
   301     return SDL_CPUCount;
       
   302 }
       
   303 
       
   304 /* Oh, such a sweet sweet trick, just not very useful. :) */
       
   305 const char *
       
   306 SDL_GetCPUType()
       
   307 {
       
   308     static char SDL_CPUType[48];
       
   309 
       
   310     if (!SDL_CPUType[0]) {
       
   311         int i = 0;
       
   312         int ax, bx, cx, dx;
       
   313 
       
   314         if (CPU_haveCPUID()) {
       
   315             cpuid(0x80000000, ax, bx, cx, dx);
       
   316             if (ax >= 0x80000004) {
       
   317                 cpuid(0x80000002, ax, bx, cx, dx);
       
   318                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   319                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   320                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   321                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   322                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   323                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   324                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   325                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   326                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   327                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   328                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   329                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   330                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   331                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   332                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   333                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   334                 cpuid(0x80000003, ax, bx, cx, dx);
       
   335                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   336                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   337                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   338                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   339                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   340                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   341                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   342                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   343                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   344                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   345                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   346                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   347                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   348                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   349                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   350                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   351                 cpuid(0x80000004, ax, bx, cx, dx);
       
   352                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   353                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   354                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   355                 SDL_CPUType[i++] = (char)(ax & 0xff); ax >>= 8;
       
   356                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   357                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   358                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   359                 SDL_CPUType[i++] = (char)(bx & 0xff); bx >>= 8;
       
   360                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   361                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   362                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   363                 SDL_CPUType[i++] = (char)(cx & 0xff); cx >>= 8;
       
   364                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   365                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   366                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   367                 SDL_CPUType[i++] = (char)(dx & 0xff); dx >>= 8;
       
   368             }
       
   369         }
       
   370         if (!SDL_CPUType[0]) {
       
   371             SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
       
   372         }
       
   373     }
       
   374     return SDL_CPUType;
       
   375 }
       
   376 
   398 static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
   377 static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
   399 
   378 
   400 static Uint32
   379 static Uint32
   401 SDL_GetCPUFeatures(void)
   380 SDL_GetCPUFeatures(void)
   402 {
   381 {
   507 #include <stdio.h>
   486 #include <stdio.h>
   508 
   487 
   509 int
   488 int
   510 main()
   489 main()
   511 {
   490 {
       
   491     printf("CPU count: %d\n", SDL_GetCPUCount());
       
   492     printf("CPU name: %s\n", SDL_GetCPUType());
   512     printf("RDTSC: %d\n", SDL_HasRDTSC());
   493     printf("RDTSC: %d\n", SDL_HasRDTSC());
   513     printf("MMX: %d\n", SDL_HasMMX());
   494     printf("MMX: %d\n", SDL_HasMMX());
   514     printf("MMXExt: %d\n", SDL_HasMMXExt());
   495     printf("MMXExt: %d\n", SDL_HasMMXExt());
   515     printf("3DNow: %d\n", SDL_Has3DNow());
   496     printf("3DNow: %d\n", SDL_Has3DNow());
   516     printf("3DNowExt: %d\n", SDL_Has3DNowExt());
   497     printf("3DNowExt: %d\n", SDL_Has3DNowExt());