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