src/cpuinfo/SDL_cpuinfo.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 31 Dec 2011 09:28:07 -0500
changeset 6138 4c64952a58fb
parent 5981 75caa8a7d559
child 6363 8506dd64e859
permissions -rwxr-xr-x
Happy New Year!
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 /* CPU feature detection for SDL */
    24 
    25 #include "SDL_cpuinfo.h"
    26 
    27 #ifdef HAVE_SYSCONF
    28 #include <unistd.h>
    29 #endif
    30 #ifdef HAVE_SYSCTLBYNAME
    31 #include <sys/types.h>
    32 #include <sys/sysctl.h>
    33 #endif
    34 #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
    35 #include <sys/sysctl.h>         /* For AltiVec check */
    36 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
    37 #include <signal.h>
    38 #include <setjmp.h>
    39 #endif
    40 #ifdef __WIN32__
    41 #include "../core/windows/SDL_windows.h"
    42 #endif
    43 
    44 #define CPU_HAS_RDTSC   0x00000001
    45 #define CPU_HAS_ALTIVEC 0x00000002
    46 #define CPU_HAS_MMX     0x00000004
    47 #define CPU_HAS_3DNOW   0x00000008
    48 #define CPU_HAS_SSE     0x00000010
    49 #define CPU_HAS_SSE2    0x00000020
    50 #define CPU_HAS_SSE3    0x00000040
    51 #define CPU_HAS_SSE41   0x00000100
    52 #define CPU_HAS_SSE42   0x00000200
    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 
    66 static __inline__ int
    67 CPU_haveCPUID(void)
    68 {
    69     int has_CPUID = 0;
    70 /* *INDENT-OFF* */
    71 #if defined(__GNUC__) && defined(i386)
    72     __asm__ (
    73 "        pushfl                      # Get original EFLAGS             \n"
    74 "        popl    %%eax                                                 \n"
    75 "        movl    %%eax,%%ecx                                           \n"
    76 "        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
    77 "        pushl   %%eax               # Save new EFLAGS value on stack  \n"
    78 "        popfl                       # Replace current EFLAGS value    \n"
    79 "        pushfl                      # Get new EFLAGS                  \n"
    80 "        popl    %%eax               # Store new EFLAGS in EAX         \n"
    81 "        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
    82 "        jz      1f                  # Processor=80486                 \n"
    83 "        movl    $1,%0               # We have CPUID support           \n"
    84 "1:                                                                    \n"
    85     : "=m" (has_CPUID)
    86     :
    87     : "%eax", "%ecx"
    88     );
    89 #elif defined(__GNUC__) && defined(__x86_64__)
    90 /* Technically, if this is being compiled under __x86_64__ then it has 
    91 CPUid by definition.  But it's nice to be able to prove it.  :)      */
    92     __asm__ (
    93 "        pushfq                      # Get original EFLAGS             \n"
    94 "        popq    %%rax                                                 \n"
    95 "        movq    %%rax,%%rcx                                           \n"
    96 "        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
    97 "        pushq   %%rax               # Save new EFLAGS value on stack  \n"
    98 "        popfq                       # Replace current EFLAGS value    \n"
    99 "        pushfq                      # Get new EFLAGS                  \n"
   100 "        popq    %%rax               # Store new EFLAGS in EAX         \n"
   101 "        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
   102 "        jz      1f                  # Processor=80486                 \n"
   103 "        movl    $1,%0               # We have CPUID support           \n"
   104 "1:                                                                    \n"
   105     : "=m" (has_CPUID)
   106     :
   107     : "%rax", "%rcx"
   108     );
   109 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
   110     __asm {
   111         pushfd                      ; Get original EFLAGS
   112         pop     eax
   113         mov     ecx, eax
   114         xor     eax, 200000h        ; Flip ID bit in EFLAGS
   115         push    eax                 ; Save new EFLAGS value on stack
   116         popfd                       ; Replace current EFLAGS value
   117         pushfd                      ; Get new EFLAGS
   118         pop     eax                 ; Store new EFLAGS in EAX
   119         xor     eax, ecx            ; Can not toggle ID bit,
   120         jz      done                ; Processor=80486
   121         mov     has_CPUID,1         ; We have CPUID support
   122 done:
   123     }
   124 #elif defined(__sun) && defined(__i386)
   125     __asm (
   126 "       pushfl                 \n"
   127 "       popl    %eax           \n"
   128 "       movl    %eax,%ecx      \n"
   129 "       xorl    $0x200000,%eax \n"
   130 "       pushl   %eax           \n"
   131 "       popfl                  \n"
   132 "       pushfl                 \n"
   133 "       popl    %eax           \n"
   134 "       xorl    %ecx,%eax      \n"
   135 "       jz      1f             \n"
   136 "       movl    $1,-8(%ebp)    \n"
   137 "1:                            \n"
   138     );
   139 #elif defined(__sun) && defined(__amd64)
   140     __asm (
   141 "       pushfq                 \n"
   142 "       popq    %rax           \n"
   143 "       movq    %rax,%rcx      \n"
   144 "       xorl    $0x200000,%eax \n"
   145 "       pushq   %rax           \n"
   146 "       popfq                  \n"
   147 "       pushfq                 \n"
   148 "       popq    %rax           \n"
   149 "       xorl    %ecx,%eax      \n"
   150 "       jz      1f             \n"
   151 "       movl    $1,-8(%rbp)    \n"
   152 "1:                            \n"
   153     );
   154 #endif
   155 /* *INDENT-ON* */
   156     return has_CPUID;
   157 }
   158 
   159 #if defined(__GNUC__) && defined(i386)
   160 #define cpuid(func, a, b, c, d) \
   161     __asm__ __volatile__ ( \
   162 "        pushl %%ebx        \n" \
   163 "        cpuid              \n" \
   164 "        movl %%ebx, %%esi  \n" \
   165 "        popl %%ebx         \n" : \
   166             "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
   167 #elif defined(__GNUC__) && defined(__x86_64__)
   168 #define cpuid(func, a, b, c, d) \
   169     __asm__ __volatile__ ( \
   170 "        pushq %%rbx        \n" \
   171 "        cpuid              \n" \
   172 "        movq %%rbx, %%rsi  \n" \
   173 "        popq %%rbx         \n" : \
   174             "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
   175 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
   176 #define cpuid(func, a, b, c, d) \
   177     __asm { \
   178         __asm mov eax, func \
   179         __asm cpuid \
   180         __asm mov a, eax \
   181         __asm mov b, ebx \
   182         __asm mov c, ecx \
   183         __asm mov d, edx \
   184     }
   185 #else
   186 #define cpuid(func, a, b, c, d) \
   187     a = b = c = d = 0
   188 #endif
   189 
   190 static __inline__ int
   191 CPU_getCPUIDFeatures(void)
   192 {
   193     int features = 0;
   194     int a, b, c, d;
   195 
   196     cpuid(0, a, b, c, d);
   197     if (a >= 1) {
   198         cpuid(1, a, b, c, d);
   199         features = d;
   200     }
   201     return features;
   202 }
   203 
   204 static __inline__ int
   205 CPU_haveRDTSC(void)
   206 {
   207     if (CPU_haveCPUID()) {
   208         return (CPU_getCPUIDFeatures() & 0x00000010);
   209     }
   210     return 0;
   211 }
   212 
   213 static __inline__ int
   214 CPU_haveAltiVec(void)
   215 {
   216     volatile int altivec = 0;
   217 #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
   218     int selectors[2] = { CTL_HW, HW_VECTORUNIT };
   219     int hasVectorUnit = 0;
   220     size_t length = sizeof(hasVectorUnit);
   221     int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
   222     if (0 == error)
   223         altivec = (hasVectorUnit != 0);
   224 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
   225     void (*handler) (int sig);
   226     handler = signal(SIGILL, illegal_instruction);
   227     if (setjmp(jmpbuf) == 0) {
   228         asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1));
   229         altivec = 1;
   230     }
   231     signal(SIGILL, handler);
   232 #endif
   233     return altivec;
   234 }
   235 
   236 static __inline__ int
   237 CPU_haveMMX(void)
   238 {
   239     if (CPU_haveCPUID()) {
   240         return (CPU_getCPUIDFeatures() & 0x00800000);
   241     }
   242     return 0;
   243 }
   244 
   245 static __inline__ int
   246 CPU_have3DNow(void)
   247 {
   248     if (CPU_haveCPUID()) {
   249         int a, b, c, d;
   250 
   251         cpuid(0x80000000, a, b, c, d);
   252         if (a >= 0x80000001) {
   253             cpuid(0x80000001, a, b, c, d);
   254             return (d & 0x80000000);
   255         }
   256     }
   257     return 0;
   258 }
   259 
   260 static __inline__ int
   261 CPU_haveSSE(void)
   262 {
   263     if (CPU_haveCPUID()) {
   264         return (CPU_getCPUIDFeatures() & 0x02000000);
   265     }
   266     return 0;
   267 }
   268 
   269 static __inline__ int
   270 CPU_haveSSE2(void)
   271 {
   272     if (CPU_haveCPUID()) {
   273         return (CPU_getCPUIDFeatures() & 0x04000000);
   274     }
   275     return 0;
   276 }
   277 
   278 static __inline__ int
   279 CPU_haveSSE3(void)
   280 {
   281     if (CPU_haveCPUID()) {
   282         int a, b, c, d;
   283 
   284         cpuid(0, a, b, c, d);
   285         if (a >= 1) {
   286             cpuid(1, a, b, c, d);
   287             return (c & 0x00000001);
   288         }
   289     }
   290     return 0;
   291 }
   292 
   293 static __inline__ int
   294 CPU_haveSSE41(void)
   295 {
   296     if (CPU_haveCPUID()) {
   297         int a, b, c, d;
   298 
   299         cpuid(1, a, b, c, d);
   300         if (a >= 1) {
   301             cpuid(1, a, b, c, d);
   302             return (c & 0x00080000);
   303         }
   304     }
   305     return 0;
   306 }
   307 
   308 static __inline__ int
   309 CPU_haveSSE42(void)
   310 {
   311     if (CPU_haveCPUID()) {
   312         int a, b, c, d;
   313 
   314         cpuid(1, a, b, c, d);
   315         if (a >= 1) {
   316             cpuid(1, a, b, c, d);
   317             return (c & 0x00100000);
   318         }
   319     }
   320     return 0;
   321 }
   322 
   323 static int SDL_CPUCount = 0;
   324 
   325 int
   326 SDL_GetCPUCount(void)
   327 {
   328     if (!SDL_CPUCount) {
   329 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
   330         if (SDL_CPUCount <= 0) {
   331             SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN);
   332         }
   333 #endif
   334 #ifdef HAVE_SYSCTLBYNAME
   335         if (SDL_CPUCount <= 0) {
   336             size_t size = sizeof(SDL_CPUCount);
   337             sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0);
   338         }
   339 #endif
   340 #ifdef __WIN32__
   341         if (SDL_CPUCount <= 0) {
   342             SYSTEM_INFO info;
   343             GetSystemInfo(&info);
   344             SDL_CPUCount = info.dwNumberOfProcessors;
   345         }
   346 #endif
   347         /* There has to be at least 1, right? :) */
   348         if (SDL_CPUCount <= 0) {
   349             SDL_CPUCount = 1;
   350         }
   351     }
   352     return SDL_CPUCount;
   353 }
   354 
   355 /* Oh, such a sweet sweet trick, just not very useful. :) */
   356 static const char *
   357 SDL_GetCPUType(void)
   358 {
   359     static char SDL_CPUType[13];
   360 
   361     if (!SDL_CPUType[0]) {
   362         int i = 0;
   363         int a, b, c, d;
   364 
   365         if (CPU_haveCPUID()) {
   366             cpuid(0x00000000, a, b, c, d);
   367             SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   368             SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   369             SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   370             SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   371             SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   372             SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   373             SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   374             SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   375             SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   376             SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   377             SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   378             SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   379         }
   380         if (!SDL_CPUType[0]) {
   381             SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
   382         }
   383     }
   384     return SDL_CPUType;
   385 }
   386 
   387 
   388 #ifdef TEST_MAIN  /* !!! FIXME: only used for test at the moment. */
   389 static const char *
   390 SDL_GetCPUName(void)
   391 {
   392     static char SDL_CPUName[48];
   393 
   394     if (!SDL_CPUName[0]) {
   395         int i = 0;
   396         int a, b, c, d;
   397 
   398         if (CPU_haveCPUID()) {
   399             cpuid(0x80000000, a, b, c, d);
   400             if (a >= 0x80000004) {
   401                 cpuid(0x80000002, a, b, c, d);
   402                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   403                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   404                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   405                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   406                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   407                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   408                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   409                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   410                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   411                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   412                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   413                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   414                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   415                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   416                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   417                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   418                 cpuid(0x80000003, a, b, c, d);
   419                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   420                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   421                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   422                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   423                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   424                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   425                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   426                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   427                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   428                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   429                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   430                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   431                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   432                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   433                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   434                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   435                 cpuid(0x80000004, a, b, c, d);
   436                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   437                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   438                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   439                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   440                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   441                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   442                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   443                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   444                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   445                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   446                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   447                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   448                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   449                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   450                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   451                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   452             }
   453         }
   454         if (!SDL_CPUName[0]) {
   455             SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName));
   456         }
   457     }
   458     return SDL_CPUName;
   459 }
   460 #endif
   461 
   462 int
   463 SDL_GetCPUCacheLineSize(void)
   464 {
   465     const char *cpuType = SDL_GetCPUType();
   466 
   467     if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
   468         int a, b, c, d;
   469 
   470         cpuid(0x00000001, a, b, c, d);
   471         return (((b >> 8) & 0xff) * 8);
   472     } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) {
   473         int a, b, c, d;
   474 
   475         cpuid(0x80000005, a, b, c, d);
   476         return (c & 0xff);
   477     } else {
   478         /* Just make a guess here... */
   479         return SDL_CACHELINE_SIZE;
   480     }
   481 }
   482 
   483 static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
   484 
   485 static Uint32
   486 SDL_GetCPUFeatures(void)
   487 {
   488     if (SDL_CPUFeatures == 0xFFFFFFFF) {
   489         SDL_CPUFeatures = 0;
   490         if (CPU_haveRDTSC()) {
   491             SDL_CPUFeatures |= CPU_HAS_RDTSC;
   492         }
   493         if (CPU_haveAltiVec()) {
   494             SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
   495         }
   496         if (CPU_haveMMX()) {
   497             SDL_CPUFeatures |= CPU_HAS_MMX;
   498         }
   499         if (CPU_have3DNow()) {
   500             SDL_CPUFeatures |= CPU_HAS_3DNOW;
   501         }
   502         if (CPU_haveSSE()) {
   503             SDL_CPUFeatures |= CPU_HAS_SSE;
   504         }
   505         if (CPU_haveSSE2()) {
   506             SDL_CPUFeatures |= CPU_HAS_SSE2;
   507         }
   508         if (CPU_haveSSE3()) {
   509             SDL_CPUFeatures |= CPU_HAS_SSE3;
   510         }
   511         if (CPU_haveSSE41()) {
   512             SDL_CPUFeatures |= CPU_HAS_SSE41;
   513         }
   514         if (CPU_haveSSE42()) {
   515             SDL_CPUFeatures |= CPU_HAS_SSE42;
   516         }
   517     }
   518     return SDL_CPUFeatures;
   519 }
   520 
   521 SDL_bool
   522 SDL_HasRDTSC(void)
   523 {
   524     if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) {
   525         return SDL_TRUE;
   526     }
   527     return SDL_FALSE;
   528 }
   529 
   530 SDL_bool
   531 SDL_HasAltiVec(void)
   532 {
   533     if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) {
   534         return SDL_TRUE;
   535     }
   536     return SDL_FALSE;
   537 }
   538 
   539 SDL_bool
   540 SDL_HasMMX(void)
   541 {
   542     if (SDL_GetCPUFeatures() & CPU_HAS_MMX) {
   543         return SDL_TRUE;
   544     }
   545     return SDL_FALSE;
   546 }
   547 
   548 SDL_bool
   549 SDL_Has3DNow(void)
   550 {
   551     if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) {
   552         return SDL_TRUE;
   553     }
   554     return SDL_FALSE;
   555 }
   556 
   557 SDL_bool
   558 SDL_HasSSE(void)
   559 {
   560     if (SDL_GetCPUFeatures() & CPU_HAS_SSE) {
   561         return SDL_TRUE;
   562     }
   563     return SDL_FALSE;
   564 }
   565 
   566 SDL_bool
   567 SDL_HasSSE2(void)
   568 {
   569     if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) {
   570         return SDL_TRUE;
   571     }
   572     return SDL_FALSE;
   573 }
   574 
   575 SDL_bool
   576 SDL_HasSSE3(void)
   577 {
   578     if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) {
   579         return SDL_TRUE;
   580     }
   581     return SDL_FALSE;
   582 }
   583 
   584 SDL_bool
   585 SDL_HasSSE41(void)
   586 {
   587     if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) {
   588         return SDL_TRUE;
   589     }
   590     return SDL_FALSE;
   591 }
   592 
   593 SDL_bool
   594 SDL_HasSSE42(void)
   595 {
   596     if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) {
   597         return SDL_TRUE;
   598     }
   599     return SDL_FALSE;
   600 }
   601 
   602 #ifdef TEST_MAIN
   603 
   604 #include <stdio.h>
   605 
   606 int
   607 main()
   608 {
   609     printf("CPU count: %d\n", SDL_GetCPUCount());
   610     printf("CPU type: %s\n", SDL_GetCPUType());
   611     printf("CPU name: %s\n", SDL_GetCPUName());
   612     printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize());
   613     printf("RDTSC: %d\n", SDL_HasRDTSC());
   614     printf("Altivec: %d\n", SDL_HasAltiVec());
   615     printf("MMX: %d\n", SDL_HasMMX());
   616     printf("3DNow: %d\n", SDL_Has3DNow());
   617     printf("SSE: %d\n", SDL_HasSSE());
   618     printf("SSE2: %d\n", SDL_HasSSE2());
   619     printf("SSE3: %d\n", SDL_HasSSE3());
   620     printf("SSE4.1: %d\n", SDL_HasSSE41());
   621     printf("SSE4.2: %d\n", SDL_HasSSE42());
   622     return 0;
   623 }
   624 
   625 #endif /* TEST_MAIN */
   626 
   627 /* vi: set ts=4 sw=4 expandtab: */