src/cpuinfo/SDL_cpuinfo.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 11 Feb 2011 23:02:35 -0800
changeset 5263 e1122f31fec5
parent 5262 b530ef003506
child 5389 24903690f48a
permissions -rw-r--r--
Fixed SSE4 detection, and split it into SSE 4.1 and 4.2
slouken@739
     1
/*
slouken@739
     2
    SDL - Simple DirectMedia Layer
slouken@5262
     3
    Copyright (C) 1997-2011 Sam Lantinga
slouken@739
     4
slouken@739
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@739
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@739
     9
slouken@739
    10
    This library is distributed in the hope that it will be useful,
slouken@739
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@739
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@739
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@739
    18
slouken@739
    19
    Sam Lantinga
slouken@739
    20
    slouken@libsdl.org
slouken@739
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@739
    23
slouken@739
    24
/* CPU feature detection for SDL */
slouken@739
    25
slouken@1361
    26
#include "SDL_cpuinfo.h"
slouken@1361
    27
slouken@3586
    28
#ifdef HAVE_SYSCONF
slouken@3586
    29
#include <unistd.h>
slouken@3586
    30
#endif
slouken@3579
    31
#ifdef HAVE_SYSCTLBYNAME
slouken@3579
    32
#include <sys/types.h>
slouken@3579
    33
#include <sys/sysctl.h>
slouken@3579
    34
#endif
slouken@5086
    35
#ifdef __WIN32__
slouken@5090
    36
#include "../core/windows/SDL_windows.h"
slouken@3580
    37
#endif
slouken@793
    38
slouken@3579
    39
#define CPU_HAS_RDTSC   0x00000001
slouken@3579
    40
#define CPU_HAS_MMX     0x00000002
slouken@5259
    41
#define CPU_HAS_SSE     0x00000010
slouken@5259
    42
#define CPU_HAS_SSE2    0x00000020
slouken@5259
    43
#define CPU_HAS_SSE3    0x00000040
slouken@5263
    44
#define CPU_HAS_SSE41   0x00000080
slouken@5263
    45
#define CPU_HAS_SSE42   0x00000100
slouken@739
    46
slouken@793
    47
slouken@1895
    48
static __inline__ int
slouken@1895
    49
CPU_haveCPUID(void)
slouken@745
    50
{
slouken@1895
    51
    int has_CPUID = 0;
slouken@1895
    52
/* *INDENT-OFF* */
slouken@745
    53
#if defined(__GNUC__) && defined(i386)
slouken@3579
    54
    __asm__ (
slouken@745
    55
"        pushfl                      # Get original EFLAGS             \n"
slouken@745
    56
"        popl    %%eax                                                 \n"
slouken@745
    57
"        movl    %%eax,%%ecx                                           \n"
slouken@745
    58
"        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
slouken@745
    59
"        pushl   %%eax               # Save new EFLAGS value on stack  \n"
slouken@745
    60
"        popfl                       # Replace current EFLAGS value    \n"
slouken@745
    61
"        pushfl                      # Get new EFLAGS                  \n"
slouken@745
    62
"        popl    %%eax               # Store new EFLAGS in EAX         \n"
slouken@745
    63
"        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
slouken@745
    64
"        jz      1f                  # Processor=80486                 \n"
slouken@745
    65
"        movl    $1,%0               # We have CPUID support           \n"
slouken@745
    66
"1:                                                                    \n"
slouken@3579
    67
    : "=m" (has_CPUID)
slouken@3579
    68
    :
slouken@3579
    69
    : "%eax", "%ecx"
slouken@3579
    70
    );
slouken@881
    71
#elif defined(__GNUC__) && defined(__x86_64__)
slouken@881
    72
/* Technically, if this is being compiled under __x86_64__ then it has 
slouken@881
    73
CPUid by definition.  But it's nice to be able to prove it.  :)      */
slouken@3579
    74
    __asm__ (
slouken@881
    75
"        pushfq                      # Get original EFLAGS             \n"
slouken@881
    76
"        popq    %%rax                                                 \n"
slouken@881
    77
"        movq    %%rax,%%rcx                                           \n"
slouken@881
    78
"        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
slouken@881
    79
"        pushq   %%rax               # Save new EFLAGS value on stack  \n"
slouken@881
    80
"        popfq                       # Replace current EFLAGS value    \n"
slouken@881
    81
"        pushfq                      # Get new EFLAGS                  \n"
slouken@881
    82
"        popq    %%rax               # Store new EFLAGS in EAX         \n"
slouken@881
    83
"        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
slouken@881
    84
"        jz      1f                  # Processor=80486                 \n"
slouken@881
    85
"        movl    $1,%0               # We have CPUID support           \n"
slouken@881
    86
"1:                                                                    \n"
slouken@3579
    87
    : "=m" (has_CPUID)
slouken@3579
    88
    :
slouken@3579
    89
    : "%rax", "%rcx"
slouken@3579
    90
    );
slouken@1442
    91
#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
slouken@3579
    92
    __asm {
slouken@745
    93
        pushfd                      ; Get original EFLAGS
slouken@745
    94
        pop     eax
slouken@745
    95
        mov     ecx, eax
slouken@745
    96
        xor     eax, 200000h        ; Flip ID bit in EFLAGS
slouken@745
    97
        push    eax                 ; Save new EFLAGS value on stack
slouken@745
    98
        popfd                       ; Replace current EFLAGS value
slouken@745
    99
        pushfd                      ; Get new EFLAGS
slouken@745
   100
        pop     eax                 ; Store new EFLAGS in EAX
slouken@745
   101
        xor     eax, ecx            ; Can not toggle ID bit,
slouken@745
   102
        jz      done                ; Processor=80486
slouken@745
   103
        mov     has_CPUID,1         ; We have CPUID support
slouken@745
   104
done:
slouken@3579
   105
    }
slouken@1864
   106
#elif defined(__sun) && defined(__i386)
slouken@3579
   107
    __asm (
icculus@1229
   108
"       pushfl                 \n"
slouken@3584
   109
"       popl    %eax           \n"
slouken@3584
   110
"       movl    %eax,%ecx      \n"
slouken@3584
   111
"       xorl    $0x200000,%eax \n"
slouken@3584
   112
"       pushl   %eax           \n"
slouken@3584
   113
"       popfl                  \n"
slouken@3584
   114
"       pushfl                 \n"
slouken@3584
   115
"       popl    %eax           \n"
slouken@3584
   116
"       xorl    %ecx,%eax      \n"
slouken@3584
   117
"       jz      1f             \n"
slouken@3584
   118
"       movl    $1,-8(%ebp)    \n"
icculus@1229
   119
"1:                            \n"
slouken@3579
   120
    );
icculus@1229
   121
#elif defined(__sun) && defined(__amd64)
slouken@3579
   122
    __asm (
icculus@1229
   123
"       pushfq                 \n"
icculus@1229
   124
"       popq    %rax           \n"
icculus@1229
   125
"       movq    %rax,%rcx      \n"
icculus@1229
   126
"       xorl    $0x200000,%eax \n"
icculus@1229
   127
"       pushq   %rax           \n"
icculus@1229
   128
"       popfq                  \n"
icculus@1229
   129
"       pushfq                 \n"
icculus@1229
   130
"       popq    %rax           \n"
icculus@1229
   131
"       xorl    %ecx,%eax      \n"
icculus@1229
   132
"       jz      1f             \n"
icculus@1229
   133
"       movl    $1,-8(%rbp)    \n"
icculus@1229
   134
"1:                            \n"
slouken@3579
   135
    );
slouken@745
   136
#endif
slouken@1895
   137
/* *INDENT-ON* */
slouken@1895
   138
    return has_CPUID;
slouken@745
   139
}
slouken@745
   140
slouken@3587
   141
#if defined(__GNUC__) && defined(i386)
slouken@3580
   142
#define cpuid(func, a, b, c, d) \
slouken@3584
   143
    __asm__ __volatile__ ( \
slouken@3584
   144
"        pushl %%ebx        \n" \
slouken@3584
   145
"        cpuid              \n" \
slouken@3584
   146
"        movl %%ebx, %%esi  \n" \
slouken@3584
   147
"        popl %%ebx         \n" : \
slouken@3584
   148
            "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
slouken@3587
   149
#elif defined(__GNUC__) && defined(__x86_64__)
slouken@3587
   150
#define cpuid(func, a, b, c, d) \
slouken@3587
   151
    __asm__ __volatile__ ( \
slouken@3587
   152
"        pushq %%rbx        \n" \
slouken@3587
   153
"        cpuid              \n" \
slouken@3587
   154
"        movq %%rbx, %%rsi  \n" \
slouken@3587
   155
"        popq %%rbx         \n" : \
slouken@3587
   156
            "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
slouken@3579
   157
#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
slouken@3580
   158
#define cpuid(func, a, b, c, d) \
slouken@3580
   159
    __asm { \
slouken@3580
   160
        __asm mov eax, func \
slouken@3580
   161
        __asm cpuid \
slouken@3580
   162
        __asm mov a, eax \
slouken@3580
   163
        __asm mov b, ebx \
slouken@3580
   164
        __asm mov c, ecx \
slouken@3580
   165
        __asm mov d, edx \
slouken@3579
   166
    }
slouken@3579
   167
#else
slouken@3580
   168
#define cpuid(func, a, b, c, d) \
slouken@3580
   169
    a = b = c = d = 0
slouken@3579
   170
#endif
slouken@3579
   171
slouken@1895
   172
static __inline__ int
slouken@1895
   173
CPU_getCPUIDFeatures(void)
slouken@745
   174
{
slouken@1895
   175
    int features = 0;
slouken@3580
   176
    int a, b, c, d;
slouken@3579
   177
slouken@3580
   178
    cpuid(0, a, b, c, d);
slouken@3580
   179
    if (a >= 1) {
slouken@3580
   180
        cpuid(1, a, b, c, d);
slouken@3580
   181
        features = d;
slouken@3579
   182
    }
slouken@1895
   183
    return features;
slouken@745
   184
}
slouken@745
   185
slouken@1895
   186
static __inline__ int
slouken@1895
   187
CPU_haveRDTSC(void)
slouken@745
   188
{
slouken@1895
   189
    if (CPU_haveCPUID()) {
slouken@1895
   190
        return (CPU_getCPUIDFeatures() & 0x00000010);
slouken@1895
   191
    }
slouken@1895
   192
    return 0;
slouken@745
   193
}
slouken@745
   194
slouken@1895
   195
static __inline__ int
slouken@1895
   196
CPU_haveMMX(void)
slouken@745
   197
{
slouken@1895
   198
    if (CPU_haveCPUID()) {
slouken@1895
   199
        return (CPU_getCPUIDFeatures() & 0x00800000);
slouken@1895
   200
    }
slouken@1895
   201
    return 0;
slouken@745
   202
}
slouken@745
   203
slouken@1895
   204
static __inline__ int
slouken@1895
   205
CPU_haveSSE(void)
slouken@745
   206
{
slouken@1895
   207
    if (CPU_haveCPUID()) {
slouken@1895
   208
        return (CPU_getCPUIDFeatures() & 0x02000000);
slouken@1895
   209
    }
slouken@1895
   210
    return 0;
slouken@745
   211
}
slouken@739
   212
slouken@1895
   213
static __inline__ int
slouken@1895
   214
CPU_haveSSE2(void)
slouken@785
   215
{
slouken@1895
   216
    if (CPU_haveCPUID()) {
slouken@1895
   217
        return (CPU_getCPUIDFeatures() & 0x04000000);
slouken@1895
   218
    }
slouken@1895
   219
    return 0;
slouken@785
   220
}
slouken@785
   221
slouken@1895
   222
static __inline__ int
slouken@5259
   223
CPU_haveSSE3(void)
slouken@778
   224
{
slouken@5259
   225
    if (CPU_haveCPUID()) {
slouken@5259
   226
        int a, b, c, d;
slouken@5259
   227
slouken@5259
   228
        cpuid(0, a, b, c, d);
slouken@5259
   229
        if (a >= 1) {
slouken@5259
   230
            cpuid(1, a, b, c, d);
slouken@5259
   231
            return (c & 0x00000001);
slouken@5259
   232
        }
slouken@1895
   233
    }
slouken@5259
   234
    return 0;
slouken@5259
   235
}
slouken@5259
   236
slouken@5259
   237
static __inline__ int
slouken@5263
   238
CPU_haveSSE41(void)
slouken@5259
   239
{
slouken@5259
   240
    if (CPU_haveCPUID()) {
slouken@5259
   241
        int a, b, c, d;
slouken@5259
   242
slouken@5263
   243
        cpuid(1, a, b, c, d);
slouken@5259
   244
        if (a >= 1) {
slouken@5259
   245
            cpuid(1, a, b, c, d);
slouken@5263
   246
            return (c & 0x00080000);
slouken@5263
   247
        }
slouken@5263
   248
    }
slouken@5263
   249
    return 0;
slouken@5263
   250
}
slouken@5263
   251
slouken@5263
   252
static __inline__ int
slouken@5263
   253
CPU_haveSSE42(void)
slouken@5263
   254
{
slouken@5263
   255
    if (CPU_haveCPUID()) {
slouken@5263
   256
        int a, b, c, d;
slouken@5263
   257
slouken@5263
   258
        cpuid(1, a, b, c, d);
slouken@5263
   259
        if (a >= 1) {
slouken@5263
   260
            cpuid(1, a, b, c, d);
slouken@5263
   261
            return (c & 0x00100000);
slouken@5259
   262
        }
slouken@5259
   263
    }
slouken@5259
   264
    return 0;
slouken@778
   265
}
slouken@778
   266
slouken@3579
   267
static int SDL_CPUCount = 0;
slouken@3579
   268
slouken@3579
   269
int
slouken@5120
   270
SDL_GetCPUCount(void)
slouken@3579
   271
{
slouken@3579
   272
    if (!SDL_CPUCount) {
slouken@3606
   273
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
slouken@3586
   274
        if (SDL_CPUCount <= 0) {
slouken@3586
   275
            SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN);
slouken@3586
   276
        }
slouken@3586
   277
#endif
slouken@3579
   278
#ifdef HAVE_SYSCTLBYNAME
slouken@3586
   279
        if (SDL_CPUCount <= 0) {
slouken@3580
   280
            size_t size = sizeof(SDL_CPUCount);
slouken@3580
   281
            sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0);
slouken@3580
   282
        }
slouken@3580
   283
#endif
slouken@5086
   284
#ifdef __WIN32__
slouken@3586
   285
        if (SDL_CPUCount <= 0) {
slouken@3580
   286
            SYSTEM_INFO info;
slouken@3580
   287
            GetSystemInfo(&info);
slouken@3580
   288
            SDL_CPUCount = info.dwNumberOfProcessors;
slouken@3580
   289
        }
slouken@3579
   290
#endif
slouken@3579
   291
        /* There has to be at least 1, right? :) */
slouken@3586
   292
        if (SDL_CPUCount <= 0) {
slouken@3579
   293
            SDL_CPUCount = 1;
slouken@3579
   294
        }
slouken@3579
   295
    }
slouken@3579
   296
    return SDL_CPUCount;
slouken@3579
   297
}
slouken@3579
   298
slouken@3579
   299
/* Oh, such a sweet sweet trick, just not very useful. :) */
slouken@4472
   300
static const char *
slouken@5120
   301
SDL_GetCPUType(void)
slouken@3579
   302
{
slouken@5115
   303
    static char SDL_CPUType[13];
slouken@3579
   304
slouken@3579
   305
    if (!SDL_CPUType[0]) {
slouken@3579
   306
        int i = 0;
slouken@3580
   307
        int a, b, c, d;
slouken@3579
   308
slouken@3579
   309
        if (CPU_haveCPUID()) {
slouken@5115
   310
            cpuid(0x00000000, a, b, c, d);
slouken@5115
   311
            SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   312
            SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   313
            SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   314
            SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   315
            SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   316
            SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   317
            SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   318
            SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   319
            SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   320
            SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   321
            SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   322
            SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   323
        }
slouken@5115
   324
        if (!SDL_CPUType[0]) {
slouken@5115
   325
            SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
slouken@5115
   326
        }
slouken@5115
   327
    }
slouken@5115
   328
    return SDL_CPUType;
slouken@5115
   329
}
slouken@5115
   330
slouken@5115
   331
static const char *
slouken@5120
   332
SDL_GetCPUName(void)
slouken@5115
   333
{
slouken@5115
   334
    static char SDL_CPUName[48];
slouken@5115
   335
slouken@5115
   336
    if (!SDL_CPUName[0]) {
slouken@5115
   337
        int i = 0;
slouken@5115
   338
        int a, b, c, d;
slouken@5115
   339
slouken@5115
   340
        if (CPU_haveCPUID()) {
slouken@3580
   341
            cpuid(0x80000000, a, b, c, d);
slouken@3580
   342
            if (a >= 0x80000004) {
slouken@3580
   343
                cpuid(0x80000002, a, b, c, d);
slouken@5115
   344
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   345
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   346
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   347
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   348
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   349
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   350
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   351
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   352
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   353
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   354
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   355
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   356
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   357
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   358
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   359
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@3580
   360
                cpuid(0x80000003, a, b, c, d);
slouken@5115
   361
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   362
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   363
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   364
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   365
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   366
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   367
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   368
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   369
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   370
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   371
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   372
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   373
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   374
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   375
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   376
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@3580
   377
                cpuid(0x80000004, a, b, c, d);
slouken@5115
   378
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   379
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   380
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   381
                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
slouken@5115
   382
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   383
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   384
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   385
                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
slouken@5115
   386
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   387
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   388
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   389
                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
slouken@5115
   390
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   391
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   392
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@5115
   393
                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
slouken@3579
   394
            }
slouken@3579
   395
        }
slouken@5115
   396
        if (!SDL_CPUName[0]) {
slouken@5115
   397
            SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName));
slouken@3579
   398
        }
slouken@3579
   399
    }
slouken@5115
   400
    return SDL_CPUName;
slouken@5115
   401
}
slouken@5115
   402
slouken@5120
   403
int
slouken@5120
   404
SDL_GetCPUCacheLineSize(void)
slouken@5115
   405
{
slouken@5115
   406
    const char *cpuType = SDL_GetCPUType();
slouken@5115
   407
slouken@5115
   408
    if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
slouken@5115
   409
        int a, b, c, d;
slouken@5115
   410
slouken@5115
   411
        cpuid(0x00000001, a, b, c, d);
slouken@5115
   412
        return (((b >> 8) & 0xff) * 8);
slouken@5115
   413
    } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) {
slouken@5115
   414
        int a, b, c, d;
slouken@5115
   415
slouken@5115
   416
        cpuid(0x80000005, a, b, c, d);
slouken@5115
   417
        return (c & 0xff);
slouken@5115
   418
    } else {
slouken@5115
   419
        /* Just make a guess here... */
slouken@5115
   420
        return SDL_CACHELINE_SIZE;
slouken@5115
   421
    }
slouken@3579
   422
}
slouken@3579
   423
slouken@739
   424
static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
slouken@739
   425
slouken@1895
   426
static Uint32
slouken@1895
   427
SDL_GetCPUFeatures(void)
slouken@739
   428
{
slouken@1895
   429
    if (SDL_CPUFeatures == 0xFFFFFFFF) {
slouken@1895
   430
        SDL_CPUFeatures = 0;
slouken@1895
   431
        if (CPU_haveRDTSC()) {
slouken@1895
   432
            SDL_CPUFeatures |= CPU_HAS_RDTSC;
slouken@1895
   433
        }
slouken@1895
   434
        if (CPU_haveMMX()) {
slouken@1895
   435
            SDL_CPUFeatures |= CPU_HAS_MMX;
slouken@1895
   436
        }
slouken@1895
   437
        if (CPU_haveSSE()) {
slouken@1895
   438
            SDL_CPUFeatures |= CPU_HAS_SSE;
slouken@1895
   439
        }
slouken@1895
   440
        if (CPU_haveSSE2()) {
slouken@1895
   441
            SDL_CPUFeatures |= CPU_HAS_SSE2;
slouken@1895
   442
        }
slouken@5259
   443
        if (CPU_haveSSE3()) {
slouken@5259
   444
            SDL_CPUFeatures |= CPU_HAS_SSE3;
slouken@5259
   445
        }
slouken@5263
   446
        if (CPU_haveSSE41()) {
slouken@5263
   447
            SDL_CPUFeatures |= CPU_HAS_SSE41;
slouken@5263
   448
        }
slouken@5263
   449
        if (CPU_haveSSE42()) {
slouken@5263
   450
            SDL_CPUFeatures |= CPU_HAS_SSE42;
slouken@1895
   451
        }
slouken@1895
   452
    }
slouken@1895
   453
    return SDL_CPUFeatures;
slouken@739
   454
}
slouken@739
   455
slouken@1895
   456
SDL_bool
slouken@1895
   457
SDL_HasRDTSC(void)
slouken@745
   458
{
slouken@1895
   459
    if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) {
slouken@1895
   460
        return SDL_TRUE;
slouken@1895
   461
    }
slouken@1895
   462
    return SDL_FALSE;
slouken@745
   463
}
slouken@745
   464
slouken@1895
   465
SDL_bool
slouken@1895
   466
SDL_HasMMX(void)
slouken@739
   467
{
slouken@1895
   468
    if (SDL_GetCPUFeatures() & CPU_HAS_MMX) {
slouken@1895
   469
        return SDL_TRUE;
slouken@1895
   470
    }
slouken@1895
   471
    return SDL_FALSE;
slouken@739
   472
}
slouken@739
   473
slouken@1895
   474
SDL_bool
slouken@1895
   475
SDL_HasSSE(void)
slouken@739
   476
{
slouken@1895
   477
    if (SDL_GetCPUFeatures() & CPU_HAS_SSE) {
slouken@1895
   478
        return SDL_TRUE;
slouken@1895
   479
    }
slouken@1895
   480
    return SDL_FALSE;
slouken@739
   481
}
slouken@739
   482
slouken@1895
   483
SDL_bool
slouken@1895
   484
SDL_HasSSE2(void)
slouken@804
   485
{
slouken@1895
   486
    if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) {
slouken@1895
   487
        return SDL_TRUE;
slouken@1895
   488
    }
slouken@1895
   489
    return SDL_FALSE;
slouken@804
   490
}
slouken@804
   491
slouken@1895
   492
SDL_bool
slouken@5259
   493
SDL_HasSSE3(void)
slouken@778
   494
{
slouken@5259
   495
    if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) {
slouken@5259
   496
        return SDL_TRUE;
slouken@5259
   497
    }
slouken@5259
   498
    return SDL_FALSE;
slouken@5259
   499
}
slouken@5259
   500
slouken@5259
   501
SDL_bool
slouken@5263
   502
SDL_HasSSE41(void)
slouken@5259
   503
{
slouken@5263
   504
    if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) {
slouken@5263
   505
        return SDL_TRUE;
slouken@5263
   506
    }
slouken@5263
   507
    return SDL_FALSE;
slouken@5263
   508
}
slouken@5263
   509
slouken@5263
   510
SDL_bool
slouken@5263
   511
SDL_HasSSE42(void)
slouken@5263
   512
{
slouken@5263
   513
    if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) {
slouken@1895
   514
        return SDL_TRUE;
slouken@1895
   515
    }
slouken@1895
   516
    return SDL_FALSE;
slouken@778
   517
}
slouken@778
   518
slouken@739
   519
#ifdef TEST_MAIN
slouken@739
   520
slouken@739
   521
#include <stdio.h>
slouken@739
   522
slouken@1895
   523
int
slouken@1895
   524
main()
slouken@739
   525
{
slouken@3579
   526
    printf("CPU count: %d\n", SDL_GetCPUCount());
slouken@5115
   527
    printf("CPU type: %s\n", SDL_GetCPUType());
slouken@5115
   528
    printf("CPU name: %s\n", SDL_GetCPUName());
slouken@5115
   529
    printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize());
slouken@1895
   530
    printf("RDTSC: %d\n", SDL_HasRDTSC());
slouken@1895
   531
    printf("MMX: %d\n", SDL_HasMMX());
slouken@1895
   532
    printf("SSE: %d\n", SDL_HasSSE());
slouken@1895
   533
    printf("SSE2: %d\n", SDL_HasSSE2());
slouken@5259
   534
    printf("SSE3: %d\n", SDL_HasSSE3());
slouken@5263
   535
    printf("SSE4.1: %d\n", SDL_HasSSE41());
slouken@5263
   536
    printf("SSE4.2: %d\n", SDL_HasSSE42());
slouken@1895
   537
    return 0;
slouken@739
   538
}
slouken@739
   539
slouken@739
   540
#endif /* TEST_MAIN */
slouken@1895
   541
slouken@1895
   542
/* vi: set ts=4 sw=4 expandtab: */