cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_cpuinfo.c (22326B)


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