src/cpuinfo/SDL_cpuinfo.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 19 Mar 2014 16:55:38 -0400
changeset 8642 3506de54b829
parent 8241 b6d5a589ce3f
child 9003 446ed0fe0fc3
permissions -rw-r--r--
Static analysis fix: Value stored to '[bcd]' is never read.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 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(_MSC_VER) && defined(_M_X64)
   135     has_CPUID = 1;
   136 #elif defined(__sun) && defined(__i386)
   137     __asm (
   138 "       pushfl                 \n"
   139 "       popl    %eax           \n"
   140 "       movl    %eax,%ecx      \n"
   141 "       xorl    $0x200000,%eax \n"
   142 "       pushl   %eax           \n"
   143 "       popfl                  \n"
   144 "       pushfl                 \n"
   145 "       popl    %eax           \n"
   146 "       xorl    %ecx,%eax      \n"
   147 "       jz      1f             \n"
   148 "       movl    $1,-8(%ebp)    \n"
   149 "1:                            \n"
   150     );
   151 #elif defined(__sun) && defined(__amd64)
   152     __asm (
   153 "       pushfq                 \n"
   154 "       popq    %rax           \n"
   155 "       movq    %rax,%rcx      \n"
   156 "       xorl    $0x200000,%eax \n"
   157 "       pushq   %rax           \n"
   158 "       popfq                  \n"
   159 "       pushfq                 \n"
   160 "       popq    %rax           \n"
   161 "       xorl    %ecx,%eax      \n"
   162 "       jz      1f             \n"
   163 "       movl    $1,-8(%rbp)    \n"
   164 "1:                            \n"
   165     );
   166 #endif
   167 /* *INDENT-ON* */
   168     return has_CPUID;
   169 }
   170 
   171 #if defined(__GNUC__) && defined(i386)
   172 #define cpuid(func, a, b, c, d) \
   173     __asm__ __volatile__ ( \
   174 "        pushl %%ebx        \n" \
   175 "        cpuid              \n" \
   176 "        movl %%ebx, %%esi  \n" \
   177 "        popl %%ebx         \n" : \
   178             "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
   179 #elif defined(__GNUC__) && defined(__x86_64__)
   180 #define cpuid(func, a, b, c, d) \
   181     __asm__ __volatile__ ( \
   182 "        pushq %%rbx        \n" \
   183 "        cpuid              \n" \
   184 "        movq %%rbx, %%rsi  \n" \
   185 "        popq %%rbx         \n" : \
   186             "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
   187 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
   188 #define cpuid(func, a, b, c, d) \
   189     __asm { \
   190         __asm mov eax, func \
   191         __asm cpuid \
   192         __asm mov a, eax \
   193         __asm mov b, ebx \
   194         __asm mov c, ecx \
   195         __asm mov d, edx \
   196 }
   197 #elif defined(_MSC_VER) && defined(_M_X64)
   198 #define cpuid(func, a, b, c, d) \
   199 { \
   200     int CPUInfo[4]; \
   201     __cpuid(CPUInfo, func); \
   202     a = CPUInfo[0]; \
   203     b = CPUInfo[1]; \
   204     c = CPUInfo[2]; \
   205     d = CPUInfo[3]; \
   206 }
   207 #else
   208 #define cpuid(func, a, b, c, d) \
   209     a = b = c = d = 0
   210 #endif
   211 
   212 static SDL_INLINE int
   213 CPU_getCPUIDFeatures(void)
   214 {
   215     int features = 0;
   216     int a, b, c, d;
   217 
   218     cpuid(0, a, b, c, d);
   219     if (a >= 1) {
   220         cpuid(1, a, b, c, d);
   221         features = d;
   222     }
   223     return features;
   224 }
   225 
   226 static SDL_INLINE int
   227 CPU_haveRDTSC(void)
   228 {
   229     if (CPU_haveCPUID()) {
   230         return (CPU_getCPUIDFeatures() & 0x00000010);
   231     }
   232     return 0;
   233 }
   234 
   235 static SDL_INLINE int
   236 CPU_haveAltiVec(void)
   237 {
   238     volatile int altivec = 0;
   239 #if (defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__))
   240 #ifdef __OpenBSD__
   241     int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC };
   242 #else
   243     int selectors[2] = { CTL_HW, HW_VECTORUNIT };
   244 #endif
   245     int hasVectorUnit = 0;
   246     size_t length = sizeof(hasVectorUnit);
   247     int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
   248     if (0 == error)
   249         altivec = (hasVectorUnit != 0);
   250 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
   251     void (*handler) (int sig);
   252     handler = signal(SIGILL, illegal_instruction);
   253     if (setjmp(jmpbuf) == 0) {
   254         asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1));
   255         altivec = 1;
   256     }
   257     signal(SIGILL, handler);
   258 #endif
   259     return altivec;
   260 }
   261 
   262 static SDL_INLINE int
   263 CPU_haveMMX(void)
   264 {
   265     if (CPU_haveCPUID()) {
   266         return (CPU_getCPUIDFeatures() & 0x00800000);
   267     }
   268     return 0;
   269 }
   270 
   271 static SDL_INLINE int
   272 CPU_have3DNow(void)
   273 {
   274     if (CPU_haveCPUID()) {
   275         int a, b, c, d;
   276 
   277         cpuid(0x80000000, a, b, c, d);
   278         if (a >= 0x80000001) {
   279             cpuid(0x80000001, a, b, c, d);
   280             return (d & 0x80000000);
   281         }
   282     }
   283     return 0;
   284 }
   285 
   286 static SDL_INLINE int
   287 CPU_haveSSE(void)
   288 {
   289     if (CPU_haveCPUID()) {
   290         return (CPU_getCPUIDFeatures() & 0x02000000);
   291     }
   292     return 0;
   293 }
   294 
   295 static SDL_INLINE int
   296 CPU_haveSSE2(void)
   297 {
   298     if (CPU_haveCPUID()) {
   299         return (CPU_getCPUIDFeatures() & 0x04000000);
   300     }
   301     return 0;
   302 }
   303 
   304 static SDL_INLINE int
   305 CPU_haveSSE3(void)
   306 {
   307     if (CPU_haveCPUID()) {
   308         int a, b, c, d;
   309 
   310         cpuid(0, a, b, c, d);
   311         if (a >= 1) {
   312             cpuid(1, a, b, c, d);
   313             return (c & 0x00000001);
   314         }
   315     }
   316     return 0;
   317 }
   318 
   319 static SDL_INLINE int
   320 CPU_haveSSE41(void)
   321 {
   322     if (CPU_haveCPUID()) {
   323         int a, b, c, d;
   324 
   325         cpuid(1, a, b, c, d);
   326         if (a >= 1) {
   327             cpuid(1, a, b, c, d);
   328             return (c & 0x00080000);
   329         }
   330     }
   331     return 0;
   332 }
   333 
   334 static SDL_INLINE int
   335 CPU_haveSSE42(void)
   336 {
   337     if (CPU_haveCPUID()) {
   338         int a, b, c, d;
   339 
   340         cpuid(1, a, b, c, d);
   341         if (a >= 1) {
   342             cpuid(1, a, b, c, d);
   343             return (c & 0x00100000);
   344         }
   345     }
   346     return 0;
   347 }
   348 
   349 static SDL_INLINE int
   350 CPU_haveAVX(void)
   351 {
   352     if (CPU_haveCPUID()) {
   353         int a, b, c, d;
   354 
   355         cpuid(1, a, b, c, d);
   356         if (a >= 1) {
   357             cpuid(1, a, b, c, d);
   358             return (c & 0x10000000);
   359         }
   360     }
   361     return 0;
   362 }
   363 
   364 static int SDL_CPUCount = 0;
   365 
   366 int
   367 SDL_GetCPUCount(void)
   368 {
   369     if (!SDL_CPUCount) {
   370 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
   371         if (SDL_CPUCount <= 0) {
   372             SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN);
   373         }
   374 #endif
   375 #ifdef HAVE_SYSCTLBYNAME
   376         if (SDL_CPUCount <= 0) {
   377             size_t size = sizeof(SDL_CPUCount);
   378             sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0);
   379         }
   380 #endif
   381 #ifdef __WIN32__
   382         if (SDL_CPUCount <= 0) {
   383             SYSTEM_INFO info;
   384             GetSystemInfo(&info);
   385             SDL_CPUCount = info.dwNumberOfProcessors;
   386         }
   387 #endif
   388         /* There has to be at least 1, right? :) */
   389         if (SDL_CPUCount <= 0) {
   390             SDL_CPUCount = 1;
   391         }
   392     }
   393     return SDL_CPUCount;
   394 }
   395 
   396 /* Oh, such a sweet sweet trick, just not very useful. :) */
   397 static const char *
   398 SDL_GetCPUType(void)
   399 {
   400     static char SDL_CPUType[13];
   401 
   402     if (!SDL_CPUType[0]) {
   403         int i = 0;
   404         int a, b, c, d;
   405 
   406         if (CPU_haveCPUID()) {
   407             cpuid(0x00000000, a, b, c, d);
   408             SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   409             SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   410             SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   411             SDL_CPUType[i++] = (char)(b & 0xff);
   412 
   413             SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   414             SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   415             SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   416             SDL_CPUType[i++] = (char)(d & 0xff);
   417 
   418             SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   419             SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   420             SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   421             SDL_CPUType[i++] = (char)(c & 0xff);
   422         }
   423         if (!SDL_CPUType[0]) {
   424             SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
   425         }
   426     }
   427     return SDL_CPUType;
   428 }
   429 
   430 
   431 #ifdef TEST_MAIN  /* !!! FIXME: only used for test at the moment. */
   432 static const char *
   433 SDL_GetCPUName(void)
   434 {
   435     static char SDL_CPUName[48];
   436 
   437     if (!SDL_CPUName[0]) {
   438         int i = 0;
   439         int a, b, c, d;
   440 
   441         if (CPU_haveCPUID()) {
   442             cpuid(0x80000000, a, b, c, d);
   443             if (a >= 0x80000004) {
   444                 cpuid(0x80000002, a, b, c, d);
   445                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   446                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   447                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   448                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   449                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   450                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   451                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   452                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   453                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   454                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   455                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   456                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   457                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   458                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   459                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   460                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   461                 cpuid(0x80000003, a, b, c, d);
   462                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   463                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   464                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   465                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   466                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   467                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   468                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   469                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   470                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   471                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   472                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   473                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   474                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   475                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   476                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   477                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   478                 cpuid(0x80000004, a, b, c, d);
   479                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   480                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   481                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   482                 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   483                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   484                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   485                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   486                 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   487                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   488                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   489                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   490                 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   491                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   492                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   493                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   494                 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   495             }
   496         }
   497         if (!SDL_CPUName[0]) {
   498             SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName));
   499         }
   500     }
   501     return SDL_CPUName;
   502 }
   503 #endif
   504 
   505 int
   506 SDL_GetCPUCacheLineSize(void)
   507 {
   508     const char *cpuType = SDL_GetCPUType();
   509 
   510     if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
   511         int a, b, c, d;
   512 
   513         cpuid(0x00000001, a, b, c, d);
   514         return (((b >> 8) & 0xff) * 8);
   515     } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) {
   516         int a, b, c, d;
   517 
   518         cpuid(0x80000005, a, b, c, d);
   519         return (c & 0xff);
   520     } else {
   521         /* Just make a guess here... */
   522         return SDL_CACHELINE_SIZE;
   523     }
   524 }
   525 
   526 static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
   527 
   528 static Uint32
   529 SDL_GetCPUFeatures(void)
   530 {
   531     if (SDL_CPUFeatures == 0xFFFFFFFF) {
   532         SDL_CPUFeatures = 0;
   533         if (CPU_haveRDTSC()) {
   534             SDL_CPUFeatures |= CPU_HAS_RDTSC;
   535         }
   536         if (CPU_haveAltiVec()) {
   537             SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
   538         }
   539         if (CPU_haveMMX()) {
   540             SDL_CPUFeatures |= CPU_HAS_MMX;
   541         }
   542         if (CPU_have3DNow()) {
   543             SDL_CPUFeatures |= CPU_HAS_3DNOW;
   544         }
   545         if (CPU_haveSSE()) {
   546             SDL_CPUFeatures |= CPU_HAS_SSE;
   547         }
   548         if (CPU_haveSSE2()) {
   549             SDL_CPUFeatures |= CPU_HAS_SSE2;
   550         }
   551         if (CPU_haveSSE3()) {
   552             SDL_CPUFeatures |= CPU_HAS_SSE3;
   553         }
   554         if (CPU_haveSSE41()) {
   555             SDL_CPUFeatures |= CPU_HAS_SSE41;
   556         }
   557         if (CPU_haveSSE42()) {
   558             SDL_CPUFeatures |= CPU_HAS_SSE42;
   559         }
   560         if (CPU_haveAVX()) {
   561             SDL_CPUFeatures |= CPU_HAS_AVX;
   562         }
   563     }
   564     return SDL_CPUFeatures;
   565 }
   566 
   567 SDL_bool
   568 SDL_HasRDTSC(void)
   569 {
   570     if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) {
   571         return SDL_TRUE;
   572     }
   573     return SDL_FALSE;
   574 }
   575 
   576 SDL_bool
   577 SDL_HasAltiVec(void)
   578 {
   579     if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) {
   580         return SDL_TRUE;
   581     }
   582     return SDL_FALSE;
   583 }
   584 
   585 SDL_bool
   586 SDL_HasMMX(void)
   587 {
   588     if (SDL_GetCPUFeatures() & CPU_HAS_MMX) {
   589         return SDL_TRUE;
   590     }
   591     return SDL_FALSE;
   592 }
   593 
   594 SDL_bool
   595 SDL_Has3DNow(void)
   596 {
   597     if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) {
   598         return SDL_TRUE;
   599     }
   600     return SDL_FALSE;
   601 }
   602 
   603 SDL_bool
   604 SDL_HasSSE(void)
   605 {
   606     if (SDL_GetCPUFeatures() & CPU_HAS_SSE) {
   607         return SDL_TRUE;
   608     }
   609     return SDL_FALSE;
   610 }
   611 
   612 SDL_bool
   613 SDL_HasSSE2(void)
   614 {
   615     if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) {
   616         return SDL_TRUE;
   617     }
   618     return SDL_FALSE;
   619 }
   620 
   621 SDL_bool
   622 SDL_HasSSE3(void)
   623 {
   624     if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) {
   625         return SDL_TRUE;
   626     }
   627     return SDL_FALSE;
   628 }
   629 
   630 SDL_bool
   631 SDL_HasSSE41(void)
   632 {
   633     if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) {
   634         return SDL_TRUE;
   635     }
   636     return SDL_FALSE;
   637 }
   638 
   639 SDL_bool
   640 SDL_HasSSE42(void)
   641 {
   642     if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) {
   643         return SDL_TRUE;
   644     }
   645     return SDL_FALSE;
   646 }
   647 
   648 SDL_bool
   649 SDL_HasAVX(void)
   650 {
   651     if (SDL_GetCPUFeatures() & CPU_HAS_AVX) {
   652         return SDL_TRUE;
   653     }
   654     return SDL_FALSE;
   655 }
   656 
   657 static int SDL_SystemRAM = 0;
   658 
   659 int
   660 SDL_GetSystemRAM(void)
   661 {
   662     if (!SDL_SystemRAM) {
   663 #if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
   664         if (SDL_SystemRAM <= 0) {
   665             SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024));
   666         }
   667 #endif
   668 #ifdef HAVE_SYSCTLBYNAME
   669         if (SDL_SystemRAM <= 0) {
   670 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
   671 #ifdef HW_REALMEM
   672             int mib[2] = {CTL_HW, HW_REALMEM};
   673 #else
   674             /* might only report up to 2 GiB */
   675             int mib[2] = {CTL_HW, HW_PHYSMEM};
   676 #endif /* HW_REALMEM */
   677 #else
   678             int mib[2] = {CTL_HW, HW_MEMSIZE};
   679 #endif /* __FreeBSD__ || __FreeBSD_kernel__ */
   680             Uint64 memsize = 0;
   681             size_t len = sizeof(memsize);
   682             
   683             if (sysctl(mib, 2, &memsize, &len, NULL, 0) == 0) {
   684                 SDL_SystemRAM = (int)(memsize / (1024*1024));
   685             }
   686         }
   687 #endif
   688 #ifdef __WIN32__
   689         if (SDL_SystemRAM <= 0) {
   690             MEMORYSTATUSEX stat;
   691             stat.dwLength = sizeof(stat);
   692             if (GlobalMemoryStatusEx(&stat)) {
   693                 SDL_SystemRAM = (int)(stat.ullTotalPhys / (1024 * 1024));
   694             }
   695         }
   696 #endif
   697     }
   698     return SDL_SystemRAM;
   699 }
   700 
   701 
   702 #ifdef TEST_MAIN
   703 
   704 #include <stdio.h>
   705 
   706 int
   707 main()
   708 {
   709     printf("CPU count: %d\n", SDL_GetCPUCount());
   710     printf("CPU type: %s\n", SDL_GetCPUType());
   711     printf("CPU name: %s\n", SDL_GetCPUName());
   712     printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize());
   713     printf("RDTSC: %d\n", SDL_HasRDTSC());
   714     printf("Altivec: %d\n", SDL_HasAltiVec());
   715     printf("MMX: %d\n", SDL_HasMMX());
   716     printf("3DNow: %d\n", SDL_Has3DNow());
   717     printf("SSE: %d\n", SDL_HasSSE());
   718     printf("SSE2: %d\n", SDL_HasSSE2());
   719     printf("SSE3: %d\n", SDL_HasSSE3());
   720     printf("SSE4.1: %d\n", SDL_HasSSE41());
   721     printf("SSE4.2: %d\n", SDL_HasSSE42());
   722     printf("AVX: %d\n", SDL_HasAVX());
   723     printf("RAM: %d MB\n", SDL_GetSystemRAM());
   724     return 0;
   725 }
   726 
   727 #endif /* TEST_MAIN */
   728 
   729 /* vi: set ts=4 sw=4 expandtab: */