src/cpuinfo/SDL_cpuinfo.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 02 Feb 2014 00:33:31 -0800
changeset 8148 56ba41ac64fe
parent 8093 b43765095a6f
child 8149 681eb46b8ac4
permissions -rw-r--r--
Fixed bug 2376 - no SDL_HasAVX

Haneef Mubarak

AVX is the successor to SSE* and is fairly widely available. As such, it really ought to be detectable.

This functionality ought to be trivial to implement, and not having it means being forced to write an ugly workaround to check for AVX (so that normal SSE can be used if AVX is not available).

Here is an example on detecting AVX from SO (it actually shows ways to cehck for all of teh fancy instructions):

http://stackoverflow.com/questions/6121792/how-to-check-if-a-cpu-supports-the-sse3-instruction-set
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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 #ifdef TEST_MAIN
    22 #include "SDL_config.h"
    23 #else
    24 #include "../SDL_internal.h"
    25 #endif
    26 
    27 #if defined(__WIN32__)
    28 #include "../core/windows/SDL_windows.h"
    29 #endif
    30 
    31 /* CPU feature detection for SDL */
    32 
    33 #include "SDL_cpuinfo.h"
    34 
    35 #ifdef HAVE_SYSCONF
    36 #include <unistd.h>
    37 #endif
    38 #ifdef HAVE_SYSCTLBYNAME
    39 #include <sys/types.h>
    40 #include <sys/sysctl.h>
    41 #endif
    42 #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
    43 #include <sys/sysctl.h>         /* For AltiVec check */
    44 #elif defined(__OpenBSD__) && defined(__powerpc__)
    45 #include <sys/param.h>
    46 #include <sys/sysctl.h> /* For AltiVec check */
    47 #include <machine/cpu.h>
    48 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
    49 #include <signal.h>
    50 #include <setjmp.h>
    51 #endif
    52 
    53 #define CPU_HAS_RDTSC   0x00000001
    54 #define CPU_HAS_ALTIVEC 0x00000002
    55 #define CPU_HAS_MMX     0x00000004
    56 #define CPU_HAS_3DNOW   0x00000008
    57 #define CPU_HAS_SSE     0x00000010
    58 #define CPU_HAS_SSE2    0x00000020
    59 #define CPU_HAS_SSE3    0x00000040
    60 #define CPU_HAS_SSE41   0x00000100
    61 #define CPU_HAS_SSE42   0x00000200
    62 #define CPU_HAS_AVX     0x00000400
    63 
    64 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__
    65 /* This is the brute force way of detecting instruction sets...
    66    the idea is borrowed from the libmpeg2 library - thanks!
    67  */
    68 static jmp_buf jmpbuf;
    69 static void
    70 illegal_instruction(int sig)
    71 {
    72     longjmp(jmpbuf, 1);
    73 }
    74 #endif /* HAVE_SETJMP */
    75 
    76 static SDL_INLINE int
    77 CPU_haveCPUID(void)
    78 {
    79     int has_CPUID = 0;
    80 /* *INDENT-OFF* */
    81 #if defined(__GNUC__) && defined(i386)
    82     __asm__ (
    83 "        pushfl                      # Get original EFLAGS             \n"
    84 "        popl    %%eax                                                 \n"
    85 "        movl    %%eax,%%ecx                                           \n"
    86 "        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
    87 "        pushl   %%eax               # Save new EFLAGS value on stack  \n"
    88 "        popfl                       # Replace current EFLAGS value    \n"
    89 "        pushfl                      # Get new EFLAGS                  \n"
    90 "        popl    %%eax               # Store new EFLAGS in EAX         \n"
    91 "        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
    92 "        jz      1f                  # Processor=80486                 \n"
    93 "        movl    $1,%0               # We have CPUID support           \n"
    94 "1:                                                                    \n"
    95     : "=m" (has_CPUID)
    96     :
    97     : "%eax", "%ecx"
    98     );
    99 #elif defined(__GNUC__) && defined(__x86_64__)
   100 /* Technically, if this is being compiled under __x86_64__ then it has 
   101 CPUid by definition.  But it's nice to be able to prove it.  :)      */
   102     __asm__ (
   103 "        pushfq                      # Get original EFLAGS             \n"
   104 "        popq    %%rax                                                 \n"
   105 "        movq    %%rax,%%rcx                                           \n"
   106 "        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
   107 "        pushq   %%rax               # Save new EFLAGS value on stack  \n"
   108 "        popfq                       # Replace current EFLAGS value    \n"
   109 "        pushfq                      # Get new EFLAGS                  \n"
   110 "        popq    %%rax               # Store new EFLAGS in EAX         \n"
   111 "        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
   112 "        jz      1f                  # Processor=80486                 \n"
   113 "        movl    $1,%0               # We have CPUID support           \n"
   114 "1:                                                                    \n"
   115     : "=m" (has_CPUID)
   116     :
   117     : "%rax", "%rcx"
   118     );
   119 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
   120     __asm {
   121         pushfd                      ; Get original EFLAGS
   122         pop     eax
   123         mov     ecx, eax
   124         xor     eax, 200000h        ; Flip ID bit in EFLAGS
   125         push    eax                 ; Save new EFLAGS value on stack
   126         popfd                       ; Replace current EFLAGS value
   127         pushfd                      ; Get new EFLAGS
   128         pop     eax                 ; Store new EFLAGS in EAX
   129         xor     eax, ecx            ; Can not toggle ID bit,
   130         jz      done                ; Processor=80486
   131         mov     has_CPUID,1         ; We have CPUID support
   132 done:
   133     }
   134 #elif defined(__sun) && defined(__i386)
   135     __asm (
   136 "       pushfl                 \n"
   137 "       popl    %eax           \n"
   138 "       movl    %eax,%ecx      \n"
   139 "       xorl    $0x200000,%eax \n"
   140 "       pushl   %eax           \n"
   141 "       popfl                  \n"
   142 "       pushfl                 \n"
   143 "       popl    %eax           \n"
   144 "       xorl    %ecx,%eax      \n"
   145 "       jz      1f             \n"
   146 "       movl    $1,-8(%ebp)    \n"
   147 "1:                            \n"
   148     );
   149 #elif defined(__sun) && defined(__amd64)
   150     __asm (
   151 "       pushfq                 \n"
   152 "       popq    %rax           \n"
   153 "       movq    %rax,%rcx      \n"
   154 "       xorl    $0x200000,%eax \n"
   155 "       pushq   %rax           \n"
   156 "       popfq                  \n"
   157 "       pushfq                 \n"
   158 "       popq    %rax           \n"
   159 "       xorl    %ecx,%eax      \n"
   160 "       jz      1f             \n"
   161 "       movl    $1,-8(%rbp)    \n"
   162 "1:                            \n"
   163     );
   164 #endif
   165 /* *INDENT-ON* */
   166     return has_CPUID;
   167 }
   168 
   169 #if defined(__GNUC__) && defined(i386)
   170 #define cpuid(func, a, b, c, d) \
   171     __asm__ __volatile__ ( \
   172 "        pushl %%ebx        \n" \
   173 "        cpuid              \n" \
   174 "        movl %%ebx, %%esi  \n" \
   175 "        popl %%ebx         \n" : \
   176             "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
   177 #elif defined(__GNUC__) && defined(__x86_64__)
   178 #define cpuid(func, a, b, c, d) \
   179     __asm__ __volatile__ ( \
   180 "        pushq %%rbx        \n" \
   181 "        cpuid              \n" \
   182 "        movq %%rbx, %%rsi  \n" \
   183 "        popq %%rbx         \n" : \
   184             "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
   185 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
   186 #define cpuid(func, a, b, c, d) \
   187     __asm { \
   188         __asm mov eax, func \
   189         __asm cpuid \
   190         __asm mov a, eax \
   191         __asm mov b, ebx \
   192         __asm mov c, ecx \
   193         __asm mov d, edx \
   194     }
   195 #else
   196 #define cpuid(func, a, b, c, d) \
   197     a = b = c = d = 0
   198 #endif
   199 
   200 static SDL_INLINE int
   201 CPU_getCPUIDFeatures(void)
   202 {
   203     int features = 0;
   204     int a, b, c, d;
   205 
   206     cpuid(0, a, b, c, d);
   207     if (a >= 1) {
   208         cpuid(1, a, b, c, d);
   209         features = d;
   210     }
   211     return features;
   212 }
   213 
   214 static SDL_INLINE int
   215 CPU_haveRDTSC(void)
   216 {
   217     if (CPU_haveCPUID()) {
   218         return (CPU_getCPUIDFeatures() & 0x00000010);
   219     }
   220     return 0;
   221 }
   222 
   223 static SDL_INLINE int
   224 CPU_haveAltiVec(void)
   225 {
   226     volatile int altivec = 0;
   227 #if (defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__))
   228 #ifdef __OpenBSD__
   229     int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC };
   230 #else
   231     int selectors[2] = { CTL_HW, HW_VECTORUNIT };
   232 #endif
   233     int hasVectorUnit = 0;
   234     size_t length = sizeof(hasVectorUnit);
   235     int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
   236     if (0 == error)
   237         altivec = (hasVectorUnit != 0);
   238 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
   239     void (*handler) (int sig);
   240     handler = signal(SIGILL, illegal_instruction);
   241     if (setjmp(jmpbuf) == 0) {
   242         asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1));
   243         altivec = 1;
   244     }
   245     signal(SIGILL, handler);
   246 #endif
   247     return altivec;
   248 }
   249 
   250 static SDL_INLINE int
   251 CPU_haveMMX(void)
   252 {
   253     if (CPU_haveCPUID()) {
   254         return (CPU_getCPUIDFeatures() & 0x00800000);
   255     }
   256     return 0;
   257 }
   258 
   259 static SDL_INLINE int
   260 CPU_have3DNow(void)
   261 {
   262     if (CPU_haveCPUID()) {
   263         int a, b, c, d;
   264 
   265         cpuid(0x80000000, a, b, c, d);
   266         if (a >= 0x80000001) {
   267             cpuid(0x80000001, a, b, c, d);
   268             return (d & 0x80000000);
   269         }
   270     }
   271     return 0;
   272 }
   273 
   274 static SDL_INLINE int
   275 CPU_haveSSE(void)
   276 {
   277     if (CPU_haveCPUID()) {
   278         return (CPU_getCPUIDFeatures() & 0x02000000);
   279     }
   280     return 0;
   281 }
   282 
   283 static SDL_INLINE int
   284 CPU_haveSSE2(void)
   285 {
   286     if (CPU_haveCPUID()) {
   287         return (CPU_getCPUIDFeatures() & 0x04000000);
   288     }
   289     return 0;
   290 }
   291 
   292 static SDL_INLINE int
   293 CPU_haveSSE3(void)
   294 {
   295     if (CPU_haveCPUID()) {
   296         int a, b, c, d;
   297 
   298         cpuid(0, a, b, c, d);
   299         if (a >= 1) {
   300             cpuid(1, a, b, c, d);
   301             return (c & 0x00000001);
   302         }
   303     }
   304     return 0;
   305 }
   306 
   307 static SDL_INLINE int
   308 CPU_haveSSE41(void)
   309 {
   310     if (CPU_haveCPUID()) {
   311         int a, b, c, d;
   312 
   313         cpuid(1, a, b, c, d);
   314         if (a >= 1) {
   315             cpuid(1, a, b, c, d);
   316             return (c & 0x00080000);
   317         }
   318     }
   319     return 0;
   320 }
   321 
   322 static SDL_INLINE int
   323 CPU_haveSSE42(void)
   324 {
   325     if (CPU_haveCPUID()) {
   326         int a, b, c, d;
   327 
   328         cpuid(1, a, b, c, d);
   329         if (a >= 1) {
   330             cpuid(1, a, b, c, d);
   331             return (c & 0x00100000);
   332         }
   333     }
   334     return 0;
   335 }
   336 
   337 static SDL_INLINE int
   338 CPU_haveAVX(void)
   339 {
   340     if (CPU_haveCPUID()) {
   341         int a, b, c, d;
   342 
   343         cpuid(1, a, b, c, d);
   344         if (a >= 1) {
   345             cpuid(1, a, b, c, d);
   346             return (c & 0x10000000);
   347         }
   348     }
   349     return 0;
   350 }
   351 
   352 static int SDL_CPUCount = 0;
   353 
   354 int
   355 SDL_GetCPUCount(void)
   356 {
   357     if (!SDL_CPUCount) {
   358 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
   359         if (SDL_CPUCount <= 0) {
   360             SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN);
   361         }
   362 #endif
   363 #ifdef HAVE_SYSCTLBYNAME
   364         if (SDL_CPUCount <= 0) {
   365             size_t size = sizeof(SDL_CPUCount);
   366             sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0);
   367         }
   368 #endif
   369 #ifdef __WIN32__
   370         if (SDL_CPUCount <= 0) {
   371             SYSTEM_INFO info;
   372             GetSystemInfo(&info);
   373             SDL_CPUCount = info.dwNumberOfProcessors;
   374         }
   375 #endif
   376         /* There has to be at least 1, right? :) */
   377         if (SDL_CPUCount <= 0) {
   378             SDL_CPUCount = 1;
   379         }
   380     }
   381     return SDL_CPUCount;
   382 }
   383 
   384 /* Oh, such a sweet sweet trick, just not very useful. :) */
   385 static const char *
   386 SDL_GetCPUType(void)
   387 {
   388     static char SDL_CPUType[13];
   389 
   390     if (!SDL_CPUType[0]) {
   391         int i = 0;
   392         int a, b, c, d;
   393 
   394         if (CPU_haveCPUID()) {
   395             cpuid(0x00000000, a, b, c, d);
   396             SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   397             SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   398             SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   399             SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   400             SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   401             SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   402             SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   403             SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   404             SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   405             SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   406             SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   407             SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   408         }
   409         if (!SDL_CPUType[0]) {
   410             SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
   411         }
   412     }
   413     return SDL_CPUType;
   414 }
   415 
   416 
   417 #ifdef TEST_MAIN  /* !!! FIXME: only used for test at the moment. */
   418 static const char *
   419 SDL_GetCPUName(void)
   420 {
   421     static char SDL_CPUName[48];
   422 
   423     if (!SDL_CPUName[0]) {
   424         int i = 0;
   425         int a, b, c, d;
   426 
   427         if (CPU_haveCPUID()) {
   428             cpuid(0x80000000, a, b, c, d);
   429             if (a >= 0x80000004) {
   430                 cpuid(0x80000002, a, b, c, d);
   431                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   432                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   433                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   434                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   435                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   436                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   437                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   438                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   439                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   440                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   441                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   442                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   443                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   444                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   445                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   446                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   447                 cpuid(0x80000003, a, b, c, d);
   448                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   449                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   450                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   451                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   452                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   453                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   454                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   455                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   456                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   457                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   458                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   459                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   460                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   461                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   462                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   463                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   464                 cpuid(0x80000004, a, b, c, d);
   465                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   466                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   467                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   468                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   469                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   470                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   471                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   472                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   473                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   474                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   475                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   476                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   477                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   478                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   479                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   480                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   481             }
   482         }
   483         if (!SDL_CPUName[0]) {
   484             SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName));
   485         }
   486     }
   487     return SDL_CPUName;
   488 }
   489 #endif
   490 
   491 int
   492 SDL_GetCPUCacheLineSize(void)
   493 {
   494     const char *cpuType = SDL_GetCPUType();
   495 
   496     if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
   497         int a, b, c, d;
   498 
   499         cpuid(0x00000001, a, b, c, d);
   500         return (((b >> 8) & 0xff) * 8);
   501     } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) {
   502         int a, b, c, d;
   503 
   504         cpuid(0x80000005, a, b, c, d);
   505         return (c & 0xff);
   506     } else {
   507         /* Just make a guess here... */
   508         return SDL_CACHELINE_SIZE;
   509     }
   510 }
   511 
   512 static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
   513 
   514 static Uint32
   515 SDL_GetCPUFeatures(void)
   516 {
   517     if (SDL_CPUFeatures == 0xFFFFFFFF) {
   518         SDL_CPUFeatures = 0;
   519         if (CPU_haveRDTSC()) {
   520             SDL_CPUFeatures |= CPU_HAS_RDTSC;
   521         }
   522         if (CPU_haveAltiVec()) {
   523             SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
   524         }
   525         if (CPU_haveMMX()) {
   526             SDL_CPUFeatures |= CPU_HAS_MMX;
   527         }
   528         if (CPU_have3DNow()) {
   529             SDL_CPUFeatures |= CPU_HAS_3DNOW;
   530         }
   531         if (CPU_haveSSE()) {
   532             SDL_CPUFeatures |= CPU_HAS_SSE;
   533         }
   534         if (CPU_haveSSE2()) {
   535             SDL_CPUFeatures |= CPU_HAS_SSE2;
   536         }
   537         if (CPU_haveSSE3()) {
   538             SDL_CPUFeatures |= CPU_HAS_SSE3;
   539         }
   540         if (CPU_haveSSE41()) {
   541             SDL_CPUFeatures |= CPU_HAS_SSE41;
   542         }
   543         if (CPU_haveSSE42()) {
   544             SDL_CPUFeatures |= CPU_HAS_SSE42;
   545         }
   546         if (CPU_haveAVX()) {
   547             SDL_CPUFeatures |= CPU_HAS_AVX;
   548         }
   549     }
   550     return SDL_CPUFeatures;
   551 }
   552 
   553 SDL_bool
   554 SDL_HasRDTSC(void)
   555 {
   556     if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) {
   557         return SDL_TRUE;
   558     }
   559     return SDL_FALSE;
   560 }
   561 
   562 SDL_bool
   563 SDL_HasAltiVec(void)
   564 {
   565     if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) {
   566         return SDL_TRUE;
   567     }
   568     return SDL_FALSE;
   569 }
   570 
   571 SDL_bool
   572 SDL_HasMMX(void)
   573 {
   574     if (SDL_GetCPUFeatures() & CPU_HAS_MMX) {
   575         return SDL_TRUE;
   576     }
   577     return SDL_FALSE;
   578 }
   579 
   580 SDL_bool
   581 SDL_Has3DNow(void)
   582 {
   583     if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) {
   584         return SDL_TRUE;
   585     }
   586     return SDL_FALSE;
   587 }
   588 
   589 SDL_bool
   590 SDL_HasSSE(void)
   591 {
   592     if (SDL_GetCPUFeatures() & CPU_HAS_SSE) {
   593         return SDL_TRUE;
   594     }
   595     return SDL_FALSE;
   596 }
   597 
   598 SDL_bool
   599 SDL_HasSSE2(void)
   600 {
   601     if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) {
   602         return SDL_TRUE;
   603     }
   604     return SDL_FALSE;
   605 }
   606 
   607 SDL_bool
   608 SDL_HasSSE3(void)
   609 {
   610     if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) {
   611         return SDL_TRUE;
   612     }
   613     return SDL_FALSE;
   614 }
   615 
   616 SDL_bool
   617 SDL_HasSSE41(void)
   618 {
   619     if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) {
   620         return SDL_TRUE;
   621     }
   622     return SDL_FALSE;
   623 }
   624 
   625 SDL_bool
   626 SDL_HasSSE42(void)
   627 {
   628     if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) {
   629         return SDL_TRUE;
   630     }
   631     return SDL_FALSE;
   632 }
   633 
   634 SDL_bool
   635 SDL_HasAVX(void)
   636 {
   637     if (SDL_GetCPUFeatures() & CPU_HAS_AVX) {
   638         return SDL_TRUE;
   639     }
   640     return SDL_FALSE;
   641 }
   642 
   643 static int SDL_SystemRAM = 0;
   644 
   645 int
   646 SDL_GetSystemRAM(void)
   647 {
   648     if (!SDL_SystemRAM) {
   649 #if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
   650         if (SDL_SystemRAM <= 0) {
   651             SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024));
   652         }
   653 #endif
   654 #ifdef HAVE_SYSCTLBYNAME
   655         if (SDL_SystemRAM <= 0) {
   656 #ifdef __FreeBSD__
   657 #ifdef HW_REALMEM
   658             int mib[2] = {CTL_HW, HW_REALMEM};
   659 #else
   660             /* might only report up to 2 GiB */
   661             int mib[2] = {CTL_HW, HW_PHYSMEM};
   662 #endif /* HW_REALMEM */
   663 #else
   664             int mib[2] = {CTL_HW, HW_MEMSIZE};
   665 #endif /* __FreeBSD__ */
   666             Uint64 memsize = 0;
   667             size_t len = sizeof(memsize);
   668             
   669             if (sysctl(mib, 2, &memsize, &len, NULL, 0) == 0) {
   670                 SDL_SystemRAM = (int)(memsize / (1024*1024));
   671             }
   672         }
   673 #endif
   674 #ifdef __WIN32__
   675         if (SDL_SystemRAM <= 0) {
   676             MEMORYSTATUSEX stat;
   677             stat.dwLength = sizeof(stat);
   678             if (GlobalMemoryStatusEx(&stat)) {
   679                 SDL_SystemRAM = (int)(stat.ullTotalPhys / (1024 * 1024));
   680             }
   681         }
   682 #endif
   683     }
   684     return SDL_SystemRAM;
   685 }
   686 
   687 
   688 #ifdef TEST_MAIN
   689 
   690 #include <stdio.h>
   691 
   692 int
   693 main()
   694 {
   695     printf("CPU count: %d\n", SDL_GetCPUCount());
   696     printf("CPU type: %s\n", SDL_GetCPUType());
   697     printf("CPU name: %s\n", SDL_GetCPUName());
   698     printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize());
   699     printf("RDTSC: %d\n", SDL_HasRDTSC());
   700     printf("Altivec: %d\n", SDL_HasAltiVec());
   701     printf("MMX: %d\n", SDL_HasMMX());
   702     printf("3DNow: %d\n", SDL_Has3DNow());
   703     printf("SSE: %d\n", SDL_HasSSE());
   704     printf("SSE2: %d\n", SDL_HasSSE2());
   705     printf("SSE3: %d\n", SDL_HasSSE3());
   706     printf("SSE4.1: %d\n", SDL_HasSSE41());
   707     printf("SSE4.2: %d\n", SDL_HasSSE42());
   708     printf("AVX: %d\n", SDL_HasAVX());
   709     printf("RAM: %d MB\n", SDL_GetSystemRAM());
   710     return 0;
   711 }
   712 
   713 #endif /* TEST_MAIN */
   714 
   715 /* vi: set ts=4 sw=4 expandtab: */