slouken@739: /* slouken@5535: Simple DirectMedia Layer slouken@8149: Copyright (C) 1997-2014 Sam Lantinga slouken@739: slouken@5535: This software is provided 'as-is', without any express or implied slouken@5535: warranty. In no event will the authors be held liable for any damages slouken@5535: arising from the use of this software. slouken@739: slouken@5535: Permission is granted to anyone to use this software for any purpose, slouken@5535: including commercial applications, and to alter it and redistribute it slouken@5535: freely, subject to the following restrictions: slouken@739: slouken@5535: 1. The origin of this software must not be misrepresented; you must not slouken@5535: claim that you wrote the original software. If you use this software slouken@5535: in a product, an acknowledgment in the product documentation would be slouken@5535: appreciated but is not required. slouken@5535: 2. Altered source versions must be plainly marked as such, and must not be slouken@5535: misrepresented as being the original software. slouken@5535: 3. This notice may not be removed or altered from any source distribution. slouken@739: */ slouken@8148: #ifdef TEST_MAIN slouken@8148: #include "SDL_config.h" slouken@8148: #else icculus@8093: #include "../SDL_internal.h" slouken@8148: #endif slouken@739: slouken@7828: #if defined(__WIN32__) slouken@7828: #include "../core/windows/SDL_windows.h" slouken@7828: #endif slouken@7828: slouken@739: /* CPU feature detection for SDL */ slouken@739: slouken@1361: #include "SDL_cpuinfo.h" slouken@1361: slouken@3586: #ifdef HAVE_SYSCONF slouken@3586: #include slouken@3586: #endif slouken@3579: #ifdef HAVE_SYSCTLBYNAME slouken@3579: #include slouken@3579: #include slouken@3579: #endif slouken@5389: #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__)) slouken@5389: #include /* For AltiVec check */ slouken@6363: #elif defined(__OpenBSD__) && defined(__powerpc__) slouken@6363: #include slouken@6363: #include /* For AltiVec check */ slouken@6363: #include slouken@5389: #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP slouken@5389: #include slouken@5389: #include slouken@5389: #endif slouken@793: slouken@3579: #define CPU_HAS_RDTSC 0x00000001 slouken@5389: #define CPU_HAS_ALTIVEC 0x00000002 slouken@5389: #define CPU_HAS_MMX 0x00000004 slouken@5389: #define CPU_HAS_3DNOW 0x00000008 slouken@5259: #define CPU_HAS_SSE 0x00000010 slouken@5259: #define CPU_HAS_SSE2 0x00000020 slouken@5259: #define CPU_HAS_SSE3 0x00000040 slouken@5389: #define CPU_HAS_SSE41 0x00000100 slouken@5389: #define CPU_HAS_SSE42 0x00000200 slouken@8148: #define CPU_HAS_AVX 0x00000400 slouken@739: slouken@6363: #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__ slouken@5389: /* This is the brute force way of detecting instruction sets... slouken@5389: the idea is borrowed from the libmpeg2 library - thanks! slouken@5389: */ slouken@5389: static jmp_buf jmpbuf; slouken@5389: static void slouken@5389: illegal_instruction(int sig) slouken@5389: { slouken@5389: longjmp(jmpbuf, 1); slouken@5389: } slouken@5389: #endif /* HAVE_SETJMP */ slouken@793: slouken@7860: static SDL_INLINE int slouken@1895: CPU_haveCPUID(void) slouken@745: { slouken@1895: int has_CPUID = 0; slouken@1895: /* *INDENT-OFF* */ slouken@745: #if defined(__GNUC__) && defined(i386) slouken@3579: __asm__ ( slouken@745: " pushfl # Get original EFLAGS \n" slouken@745: " popl %%eax \n" slouken@745: " movl %%eax,%%ecx \n" slouken@745: " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" slouken@745: " pushl %%eax # Save new EFLAGS value on stack \n" slouken@745: " popfl # Replace current EFLAGS value \n" slouken@745: " pushfl # Get new EFLAGS \n" slouken@745: " popl %%eax # Store new EFLAGS in EAX \n" slouken@745: " xorl %%ecx,%%eax # Can not toggle ID bit, \n" slouken@745: " jz 1f # Processor=80486 \n" slouken@745: " movl $1,%0 # We have CPUID support \n" slouken@745: "1: \n" slouken@3579: : "=m" (has_CPUID) slouken@3579: : slouken@3579: : "%eax", "%ecx" slouken@3579: ); slouken@881: #elif defined(__GNUC__) && defined(__x86_64__) slouken@881: /* Technically, if this is being compiled under __x86_64__ then it has slouken@8241: CPUid by definition. But it's nice to be able to prove it. :) */ slouken@3579: __asm__ ( slouken@881: " pushfq # Get original EFLAGS \n" slouken@881: " popq %%rax \n" slouken@881: " movq %%rax,%%rcx \n" slouken@881: " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" slouken@881: " pushq %%rax # Save new EFLAGS value on stack \n" slouken@881: " popfq # Replace current EFLAGS value \n" slouken@881: " pushfq # Get new EFLAGS \n" slouken@881: " popq %%rax # Store new EFLAGS in EAX \n" slouken@881: " xorl %%ecx,%%eax # Can not toggle ID bit, \n" slouken@881: " jz 1f # Processor=80486 \n" slouken@881: " movl $1,%0 # We have CPUID support \n" slouken@881: "1: \n" slouken@3579: : "=m" (has_CPUID) slouken@3579: : slouken@3579: : "%rax", "%rcx" slouken@3579: ); slouken@1442: #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) slouken@3579: __asm { slouken@745: pushfd ; Get original EFLAGS slouken@745: pop eax slouken@745: mov ecx, eax slouken@745: xor eax, 200000h ; Flip ID bit in EFLAGS slouken@745: push eax ; Save new EFLAGS value on stack slouken@745: popfd ; Replace current EFLAGS value slouken@745: pushfd ; Get new EFLAGS slouken@745: pop eax ; Store new EFLAGS in EAX slouken@745: xor eax, ecx ; Can not toggle ID bit, slouken@745: jz done ; Processor=80486 slouken@745: mov has_CPUID,1 ; We have CPUID support slouken@745: done: slouken@3579: } slouken@8241: #elif defined(_MSC_VER) && defined(_M_X64) slouken@8241: has_CPUID = 1; slouken@1864: #elif defined(__sun) && defined(__i386) slouken@3579: __asm ( icculus@1229: " pushfl \n" slouken@3584: " popl %eax \n" slouken@3584: " movl %eax,%ecx \n" slouken@3584: " xorl $0x200000,%eax \n" slouken@3584: " pushl %eax \n" slouken@3584: " popfl \n" slouken@3584: " pushfl \n" slouken@3584: " popl %eax \n" slouken@3584: " xorl %ecx,%eax \n" slouken@3584: " jz 1f \n" slouken@3584: " movl $1,-8(%ebp) \n" icculus@1229: "1: \n" slouken@3579: ); icculus@1229: #elif defined(__sun) && defined(__amd64) slouken@3579: __asm ( icculus@1229: " pushfq \n" icculus@1229: " popq %rax \n" icculus@1229: " movq %rax,%rcx \n" icculus@1229: " xorl $0x200000,%eax \n" icculus@1229: " pushq %rax \n" icculus@1229: " popfq \n" icculus@1229: " pushfq \n" icculus@1229: " popq %rax \n" icculus@1229: " xorl %ecx,%eax \n" icculus@1229: " jz 1f \n" icculus@1229: " movl $1,-8(%rbp) \n" icculus@1229: "1: \n" slouken@3579: ); slouken@745: #endif slouken@1895: /* *INDENT-ON* */ slouken@1895: return has_CPUID; slouken@745: } slouken@745: slouken@3587: #if defined(__GNUC__) && defined(i386) slouken@3580: #define cpuid(func, a, b, c, d) \ slouken@3584: __asm__ __volatile__ ( \ slouken@3584: " pushl %%ebx \n" \ slouken@3584: " cpuid \n" \ slouken@3584: " movl %%ebx, %%esi \n" \ slouken@3584: " popl %%ebx \n" : \ slouken@3584: "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func)) slouken@3587: #elif defined(__GNUC__) && defined(__x86_64__) slouken@3587: #define cpuid(func, a, b, c, d) \ slouken@3587: __asm__ __volatile__ ( \ slouken@3587: " pushq %%rbx \n" \ slouken@3587: " cpuid \n" \ slouken@3587: " movq %%rbx, %%rsi \n" \ slouken@3587: " popq %%rbx \n" : \ slouken@3587: "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func)) slouken@3579: #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) slouken@3580: #define cpuid(func, a, b, c, d) \ slouken@3580: __asm { \ slouken@3580: __asm mov eax, func \ slouken@3580: __asm cpuid \ slouken@3580: __asm mov a, eax \ slouken@3580: __asm mov b, ebx \ slouken@3580: __asm mov c, ecx \ slouken@3580: __asm mov d, edx \ slouken@8241: } slouken@8241: #elif defined(_MSC_VER) && defined(_M_X64) slouken@8241: #define cpuid(func, a, b, c, d) \ slouken@8241: { \ slouken@8241: int CPUInfo[4]; \ slouken@8241: __cpuid(CPUInfo, func); \ slouken@8241: a = CPUInfo[0]; \ slouken@8241: b = CPUInfo[1]; \ slouken@8241: c = CPUInfo[2]; \ slouken@8241: d = CPUInfo[3]; \ slouken@8241: } slouken@3579: #else slouken@3580: #define cpuid(func, a, b, c, d) \ slouken@3580: a = b = c = d = 0 slouken@3579: #endif slouken@3579: slouken@7860: static SDL_INLINE int slouken@1895: CPU_getCPUIDFeatures(void) slouken@745: { slouken@1895: int features = 0; slouken@3580: int a, b, c, d; slouken@3579: slouken@3580: cpuid(0, a, b, c, d); slouken@3580: if (a >= 1) { slouken@3580: cpuid(1, a, b, c, d); slouken@3580: features = d; slouken@3579: } slouken@1895: return features; slouken@745: } slouken@745: slouken@7860: static SDL_INLINE int slouken@1895: CPU_haveRDTSC(void) slouken@745: { slouken@1895: if (CPU_haveCPUID()) { slouken@1895: return (CPU_getCPUIDFeatures() & 0x00000010); slouken@1895: } slouken@1895: return 0; slouken@745: } slouken@745: slouken@7860: static SDL_INLINE int slouken@5389: CPU_haveAltiVec(void) slouken@5389: { slouken@5389: volatile int altivec = 0; slouken@6363: #if (defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__)) slouken@6363: #ifdef __OpenBSD__ slouken@6363: int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC }; slouken@6363: #else slouken@5389: int selectors[2] = { CTL_HW, HW_VECTORUNIT }; slouken@6363: #endif slouken@5389: int hasVectorUnit = 0; slouken@5389: size_t length = sizeof(hasVectorUnit); slouken@5389: int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0); slouken@5389: if (0 == error) slouken@5389: altivec = (hasVectorUnit != 0); slouken@5389: #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP slouken@5389: void (*handler) (int sig); slouken@5389: handler = signal(SIGILL, illegal_instruction); slouken@5389: if (setjmp(jmpbuf) == 0) { slouken@5389: asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1)); slouken@5389: altivec = 1; slouken@5389: } slouken@5389: signal(SIGILL, handler); slouken@5389: #endif slouken@5389: return altivec; slouken@5389: } slouken@5389: slouken@7860: static SDL_INLINE int slouken@1895: CPU_haveMMX(void) slouken@745: { slouken@1895: if (CPU_haveCPUID()) { slouken@1895: return (CPU_getCPUIDFeatures() & 0x00800000); slouken@1895: } slouken@1895: return 0; slouken@745: } slouken@745: slouken@7860: static SDL_INLINE int slouken@5389: CPU_have3DNow(void) slouken@5389: { slouken@5389: if (CPU_haveCPUID()) { slouken@5389: int a, b, c, d; slouken@5389: slouken@5389: cpuid(0x80000000, a, b, c, d); slouken@5389: if (a >= 0x80000001) { slouken@5389: cpuid(0x80000001, a, b, c, d); slouken@5389: return (d & 0x80000000); slouken@5389: } slouken@5389: } slouken@5389: return 0; slouken@5389: } slouken@5389: slouken@7860: static SDL_INLINE int slouken@1895: CPU_haveSSE(void) slouken@745: { slouken@1895: if (CPU_haveCPUID()) { slouken@1895: return (CPU_getCPUIDFeatures() & 0x02000000); slouken@1895: } slouken@1895: return 0; slouken@745: } slouken@739: slouken@7860: static SDL_INLINE int slouken@1895: CPU_haveSSE2(void) slouken@785: { slouken@1895: if (CPU_haveCPUID()) { slouken@1895: return (CPU_getCPUIDFeatures() & 0x04000000); slouken@1895: } slouken@1895: return 0; slouken@785: } slouken@785: slouken@7860: static SDL_INLINE int slouken@5259: CPU_haveSSE3(void) slouken@778: { slouken@5259: if (CPU_haveCPUID()) { slouken@5259: int a, b, c, d; slouken@5259: slouken@5259: cpuid(0, a, b, c, d); slouken@5259: if (a >= 1) { slouken@5259: cpuid(1, a, b, c, d); slouken@5259: return (c & 0x00000001); slouken@5259: } slouken@1895: } slouken@5259: return 0; slouken@5259: } slouken@5259: slouken@7860: static SDL_INLINE int slouken@5263: CPU_haveSSE41(void) slouken@5259: { slouken@5259: if (CPU_haveCPUID()) { slouken@5259: int a, b, c, d; slouken@5259: slouken@5263: cpuid(1, a, b, c, d); slouken@5259: if (a >= 1) { slouken@5259: cpuid(1, a, b, c, d); slouken@5263: return (c & 0x00080000); slouken@5263: } slouken@5263: } slouken@5263: return 0; slouken@5263: } slouken@5263: slouken@7860: static SDL_INLINE int slouken@5263: CPU_haveSSE42(void) slouken@5263: { slouken@5263: if (CPU_haveCPUID()) { slouken@5263: int a, b, c, d; slouken@5263: slouken@5263: cpuid(1, a, b, c, d); slouken@5263: if (a >= 1) { slouken@5263: cpuid(1, a, b, c, d); slouken@5263: return (c & 0x00100000); slouken@5259: } slouken@5259: } slouken@5259: return 0; slouken@778: } slouken@778: slouken@8148: static SDL_INLINE int slouken@8148: CPU_haveAVX(void) slouken@8148: { slouken@8148: if (CPU_haveCPUID()) { slouken@8148: int a, b, c, d; slouken@8148: slouken@8148: cpuid(1, a, b, c, d); slouken@8148: if (a >= 1) { slouken@8148: cpuid(1, a, b, c, d); slouken@8148: return (c & 0x10000000); slouken@8148: } slouken@8148: } slouken@8148: return 0; slouken@8148: } slouken@8148: slouken@3579: static int SDL_CPUCount = 0; slouken@3579: slouken@3579: int slouken@5120: SDL_GetCPUCount(void) slouken@3579: { slouken@3579: if (!SDL_CPUCount) { slouken@3606: #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) slouken@3586: if (SDL_CPUCount <= 0) { slouken@3586: SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN); slouken@3586: } slouken@3586: #endif slouken@3579: #ifdef HAVE_SYSCTLBYNAME slouken@3586: if (SDL_CPUCount <= 0) { slouken@3580: size_t size = sizeof(SDL_CPUCount); slouken@3580: sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0); slouken@3580: } slouken@3580: #endif slouken@5086: #ifdef __WIN32__ slouken@3586: if (SDL_CPUCount <= 0) { slouken@3580: SYSTEM_INFO info; slouken@3580: GetSystemInfo(&info); slouken@3580: SDL_CPUCount = info.dwNumberOfProcessors; slouken@3580: } slouken@3579: #endif slouken@3579: /* There has to be at least 1, right? :) */ slouken@3586: if (SDL_CPUCount <= 0) { slouken@3579: SDL_CPUCount = 1; slouken@3579: } slouken@3579: } slouken@3579: return SDL_CPUCount; slouken@3579: } slouken@3579: slouken@3579: /* Oh, such a sweet sweet trick, just not very useful. :) */ slouken@4472: static const char * slouken@5120: SDL_GetCPUType(void) slouken@3579: { slouken@5115: static char SDL_CPUType[13]; slouken@3579: slouken@3579: if (!SDL_CPUType[0]) { slouken@3579: int i = 0; slouken@3580: int a, b, c, d; slouken@3579: slouken@3579: if (CPU_haveCPUID()) { slouken@5115: cpuid(0x00000000, a, b, c, d); slouken@5115: SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; icculus@8642: SDL_CPUType[i++] = (char)(b & 0xff); icculus@8642: slouken@5115: SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; slouken@5115: SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; slouken@5115: SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; icculus@8642: SDL_CPUType[i++] = (char)(d & 0xff); icculus@8642: slouken@5115: SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; icculus@8642: SDL_CPUType[i++] = (char)(c & 0xff); slouken@5115: } slouken@5115: if (!SDL_CPUType[0]) { slouken@5115: SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType)); slouken@5115: } slouken@5115: } slouken@5115: return SDL_CPUType; slouken@5115: } slouken@5115: icculus@5981: icculus@5981: #ifdef TEST_MAIN /* !!! FIXME: only used for test at the moment. */ slouken@5115: static const char * slouken@5120: SDL_GetCPUName(void) slouken@5115: { slouken@5115: static char SDL_CPUName[48]; slouken@5115: slouken@5115: if (!SDL_CPUName[0]) { slouken@5115: int i = 0; slouken@5115: int a, b, c, d; slouken@5115: slouken@5115: if (CPU_haveCPUID()) { slouken@3580: cpuid(0x80000000, a, b, c, d); slouken@3580: if (a >= 0x80000004) { slouken@3580: cpuid(0x80000002, a, b, c, d); slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@3580: cpuid(0x80000003, a, b, c, d); slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@3580: cpuid(0x80000004, a, b, c, d); slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@5115: SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; slouken@3579: } slouken@3579: } slouken@5115: if (!SDL_CPUName[0]) { slouken@5115: SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName)); slouken@3579: } slouken@3579: } slouken@5115: return SDL_CPUName; slouken@5115: } icculus@5981: #endif slouken@5115: slouken@5120: int slouken@5120: SDL_GetCPUCacheLineSize(void) slouken@5115: { slouken@5115: const char *cpuType = SDL_GetCPUType(); slouken@5115: slouken@5115: if (SDL_strcmp(cpuType, "GenuineIntel") == 0) { slouken@5115: int a, b, c, d; slouken@5115: slouken@5115: cpuid(0x00000001, a, b, c, d); slouken@5115: return (((b >> 8) & 0xff) * 8); slouken@5115: } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) { slouken@5115: int a, b, c, d; slouken@5115: slouken@5115: cpuid(0x80000005, a, b, c, d); slouken@5115: return (c & 0xff); slouken@5115: } else { slouken@5115: /* Just make a guess here... */ slouken@5115: return SDL_CACHELINE_SIZE; slouken@5115: } slouken@3579: } slouken@3579: slouken@739: static Uint32 SDL_CPUFeatures = 0xFFFFFFFF; slouken@739: slouken@1895: static Uint32 slouken@1895: SDL_GetCPUFeatures(void) slouken@739: { slouken@1895: if (SDL_CPUFeatures == 0xFFFFFFFF) { slouken@1895: SDL_CPUFeatures = 0; slouken@1895: if (CPU_haveRDTSC()) { slouken@1895: SDL_CPUFeatures |= CPU_HAS_RDTSC; slouken@1895: } slouken@5389: if (CPU_haveAltiVec()) { slouken@5389: SDL_CPUFeatures |= CPU_HAS_ALTIVEC; slouken@5389: } slouken@1895: if (CPU_haveMMX()) { slouken@1895: SDL_CPUFeatures |= CPU_HAS_MMX; slouken@1895: } slouken@5389: if (CPU_have3DNow()) { slouken@5389: SDL_CPUFeatures |= CPU_HAS_3DNOW; slouken@5389: } slouken@1895: if (CPU_haveSSE()) { slouken@1895: SDL_CPUFeatures |= CPU_HAS_SSE; slouken@1895: } slouken@1895: if (CPU_haveSSE2()) { slouken@1895: SDL_CPUFeatures |= CPU_HAS_SSE2; slouken@1895: } slouken@5259: if (CPU_haveSSE3()) { slouken@5259: SDL_CPUFeatures |= CPU_HAS_SSE3; slouken@5259: } slouken@5263: if (CPU_haveSSE41()) { slouken@5263: SDL_CPUFeatures |= CPU_HAS_SSE41; slouken@5263: } slouken@5263: if (CPU_haveSSE42()) { slouken@5263: SDL_CPUFeatures |= CPU_HAS_SSE42; slouken@1895: } slouken@8148: if (CPU_haveAVX()) { slouken@8148: SDL_CPUFeatures |= CPU_HAS_AVX; slouken@8148: } slouken@1895: } slouken@1895: return SDL_CPUFeatures; slouken@739: } slouken@739: slouken@1895: SDL_bool slouken@1895: SDL_HasRDTSC(void) slouken@745: { slouken@1895: if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) { slouken@1895: return SDL_TRUE; slouken@1895: } slouken@1895: return SDL_FALSE; slouken@745: } slouken@745: slouken@1895: SDL_bool slouken@5389: SDL_HasAltiVec(void) slouken@5389: { slouken@5389: if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) { slouken@5389: return SDL_TRUE; slouken@5389: } slouken@5389: return SDL_FALSE; slouken@5389: } slouken@5389: slouken@5389: SDL_bool slouken@1895: SDL_HasMMX(void) slouken@739: { slouken@1895: if (SDL_GetCPUFeatures() & CPU_HAS_MMX) { slouken@1895: return SDL_TRUE; slouken@1895: } slouken@1895: return SDL_FALSE; slouken@739: } slouken@739: slouken@1895: SDL_bool slouken@5389: SDL_Has3DNow(void) slouken@5389: { slouken@5389: if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) { slouken@5389: return SDL_TRUE; slouken@5389: } slouken@5389: return SDL_FALSE; slouken@5389: } slouken@5389: slouken@5389: SDL_bool slouken@1895: SDL_HasSSE(void) slouken@739: { slouken@1895: if (SDL_GetCPUFeatures() & CPU_HAS_SSE) { slouken@1895: return SDL_TRUE; slouken@1895: } slouken@1895: return SDL_FALSE; slouken@739: } slouken@739: slouken@1895: SDL_bool slouken@1895: SDL_HasSSE2(void) slouken@804: { slouken@1895: if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) { slouken@1895: return SDL_TRUE; slouken@1895: } slouken@1895: return SDL_FALSE; slouken@804: } slouken@804: slouken@1895: SDL_bool slouken@5259: SDL_HasSSE3(void) slouken@778: { slouken@5259: if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) { slouken@5259: return SDL_TRUE; slouken@5259: } slouken@5259: return SDL_FALSE; slouken@5259: } slouken@5259: slouken@5259: SDL_bool slouken@5263: SDL_HasSSE41(void) slouken@5259: { slouken@5263: if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) { slouken@5263: return SDL_TRUE; slouken@5263: } slouken@5263: return SDL_FALSE; slouken@5263: } slouken@5263: slouken@5263: SDL_bool slouken@5263: SDL_HasSSE42(void) slouken@5263: { slouken@5263: if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) { slouken@1895: return SDL_TRUE; slouken@1895: } slouken@1895: return SDL_FALSE; slouken@778: } slouken@778: slouken@8148: SDL_bool slouken@8148: SDL_HasAVX(void) slouken@8148: { slouken@8148: if (SDL_GetCPUFeatures() & CPU_HAS_AVX) { slouken@8148: return SDL_TRUE; slouken@8148: } slouken@8148: return SDL_FALSE; slouken@8148: } slouken@8148: slouken@7821: static int SDL_SystemRAM = 0; slouken@7821: slouken@7821: int slouken@7821: SDL_GetSystemRAM(void) slouken@7821: { slouken@7821: if (!SDL_SystemRAM) { slouken@7821: #if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) slouken@7821: if (SDL_SystemRAM <= 0) { slouken@7821: SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024)); slouken@7821: } slouken@7821: #endif slouken@7821: #ifdef HAVE_SYSCTLBYNAME slouken@7821: if (SDL_SystemRAM <= 0) { slouken@8240: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) slouken@7826: #ifdef HW_REALMEM slouken@7826: int mib[2] = {CTL_HW, HW_REALMEM}; slouken@7826: #else slouken@7826: /* might only report up to 2 GiB */ slouken@7826: int mib[2] = {CTL_HW, HW_PHYSMEM}; slouken@7826: #endif /* HW_REALMEM */ slouken@7826: #else slouken@7821: int mib[2] = {CTL_HW, HW_MEMSIZE}; slouken@8240: #endif /* __FreeBSD__ || __FreeBSD_kernel__ */ slouken@7823: Uint64 memsize = 0; slouken@7821: size_t len = sizeof(memsize); slouken@7821: slouken@7821: if (sysctl(mib, 2, &memsize, &len, NULL, 0) == 0) { slouken@7821: SDL_SystemRAM = (int)(memsize / (1024*1024)); slouken@7821: } slouken@7821: } slouken@7821: #endif slouken@7821: #ifdef __WIN32__ slouken@7821: if (SDL_SystemRAM <= 0) { slouken@7821: MEMORYSTATUSEX stat; icculus@7889: stat.dwLength = sizeof(stat); slouken@7821: if (GlobalMemoryStatusEx(&stat)) { slouken@7821: SDL_SystemRAM = (int)(stat.ullTotalPhys / (1024 * 1024)); slouken@7821: } slouken@7821: } slouken@7821: #endif slouken@7821: } slouken@7821: return SDL_SystemRAM; slouken@7821: } slouken@7821: slouken@7821: slouken@739: #ifdef TEST_MAIN slouken@739: slouken@739: #include slouken@739: slouken@1895: int slouken@1895: main() slouken@739: { slouken@3579: printf("CPU count: %d\n", SDL_GetCPUCount()); slouken@5115: printf("CPU type: %s\n", SDL_GetCPUType()); slouken@5115: printf("CPU name: %s\n", SDL_GetCPUName()); slouken@5115: printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize()); slouken@1895: printf("RDTSC: %d\n", SDL_HasRDTSC()); slouken@5389: printf("Altivec: %d\n", SDL_HasAltiVec()); slouken@1895: printf("MMX: %d\n", SDL_HasMMX()); slouken@5389: printf("3DNow: %d\n", SDL_Has3DNow()); slouken@1895: printf("SSE: %d\n", SDL_HasSSE()); slouken@1895: printf("SSE2: %d\n", SDL_HasSSE2()); slouken@5259: printf("SSE3: %d\n", SDL_HasSSE3()); slouken@5263: printf("SSE4.1: %d\n", SDL_HasSSE41()); slouken@5263: printf("SSE4.2: %d\n", SDL_HasSSE42()); slouken@8148: printf("AVX: %d\n", SDL_HasAVX()); slouken@7821: printf("RAM: %d MB\n", SDL_GetSystemRAM()); slouken@1895: return 0; slouken@739: } slouken@739: slouken@739: #endif /* TEST_MAIN */ slouken@1895: slouken@1895: /* vi: set ts=4 sw=4 expandtab: */