Cleaned up some compiler warnings.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
22 #include "SDL_config.h"
24 #include "../SDL_internal.h"
27 #if defined(__WIN32__)
28 #include "../core/windows/SDL_windows.h"
31 /* CPU feature detection for SDL */
33 #include "SDL_cpuinfo.h"
38 #ifdef HAVE_SYSCTLBYNAME
39 #include <sys/types.h>
40 #include <sys/sysctl.h>
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
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
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!
69 static jmp_buf jmpbuf;
71 illegal_instruction(int sig)
75 #endif /* HAVE_SETJMP */
82 #ifndef SDL_CPUINFO_DISABLED
83 #if defined(__GNUC__) && defined(i386)
85 " pushfl # Get original EFLAGS \n"
87 " movl %%eax,%%ecx \n"
88 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n"
89 " pushl %%eax # Save new EFLAGS value on stack \n"
90 " popfl # Replace current EFLAGS value \n"
91 " pushfl # Get new EFLAGS \n"
92 " popl %%eax # Store new EFLAGS in EAX \n"
93 " xorl %%ecx,%%eax # Can not toggle ID bit, \n"
94 " jz 1f # Processor=80486 \n"
95 " movl $1,%0 # We have CPUID support \n"
101 #elif defined(__GNUC__) && defined(__x86_64__)
102 /* Technically, if this is being compiled under __x86_64__ then it has
103 CPUid by definition. But it's nice to be able to prove it. :) */
105 " pushfq # Get original EFLAGS \n"
107 " movq %%rax,%%rcx \n"
108 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n"
109 " pushq %%rax # Save new EFLAGS value on stack \n"
110 " popfq # Replace current EFLAGS value \n"
111 " pushfq # Get new EFLAGS \n"
112 " popq %%rax # Store new EFLAGS in EAX \n"
113 " xorl %%ecx,%%eax # Can not toggle ID bit, \n"
114 " jz 1f # Processor=80486 \n"
115 " movl $1,%0 # We have CPUID support \n"
121 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
123 pushfd ; Get original EFLAGS
126 xor eax, 200000h ; Flip ID bit in EFLAGS
127 push eax ; Save new EFLAGS value on stack
128 popfd ; Replace current EFLAGS value
129 pushfd ; Get new EFLAGS
130 pop eax ; Store new EFLAGS in EAX
131 xor eax, ecx ; Can not toggle ID bit,
132 jz done ; Processor=80486
133 mov has_CPUID,1 ; We have CPUID support
136 #elif defined(_MSC_VER) && defined(_M_X64)
138 #elif defined(__sun) && defined(__i386)
143 " xorl $0x200000,%eax \n"
150 " movl $1,-8(%ebp) \n"
153 #elif defined(__sun) && defined(__amd64)
158 " xorl $0x200000,%eax \n"
165 " movl $1,-8(%rbp) \n"
174 #if defined(__GNUC__) && defined(i386)
175 #define cpuid(func, a, b, c, d) \
176 __asm__ __volatile__ ( \
178 " xorl %%ecx,%%ecx \n" \
180 " movl %%ebx, %%esi \n" \
182 "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
183 #elif defined(__GNUC__) && defined(__x86_64__)
184 #define cpuid(func, a, b, c, d) \
185 __asm__ __volatile__ ( \
187 " xorq %%rcx,%%rcx \n" \
189 " movq %%rbx, %%rsi \n" \
191 "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
192 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
193 #define cpuid(func, a, b, c, d) \
195 __asm mov eax, func \
203 #elif defined(_MSC_VER) && defined(_M_X64)
204 #define cpuid(func, a, b, c, d) \
207 __cpuid(CPUInfo, func); \
214 #define cpuid(func, a, b, c, d) \
219 CPU_getCPUIDFeatures(void)
224 cpuid(0, a, b, c, d);
226 cpuid(1, a, b, c, d);
237 /* Check to make sure we can call xgetbv */
238 cpuid(0, a, b, c, d);
242 cpuid(1, a, b, c, d);
243 if (!(c & 0x08000000)) {
247 /* Call xgetbv to see if YMM register state is saved */
249 #if defined(__GNUC__) && (defined(i386) || defined(__x86_64__))
250 asm(".byte 0x0f, 0x01, 0xd0" : "=a" (a) : "c" (0) : "%edx");
251 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) /* VS2010 SP1 */
253 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
257 _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0
261 return ((a & 6) == 6) ? SDL_TRUE : SDL_FALSE;
267 if (CPU_haveCPUID()) {
268 return (CPU_getCPUIDFeatures() & 0x00000010);
274 CPU_haveAltiVec(void)
276 volatile int altivec = 0;
277 #ifndef SDL_CPUINFO_DISABLED
278 #if (defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__))
280 int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC };
282 int selectors[2] = { CTL_HW, HW_VECTORUNIT };
284 int hasVectorUnit = 0;
285 size_t length = sizeof(hasVectorUnit);
286 int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
288 altivec = (hasVectorUnit != 0);
289 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
290 void (*handler) (int sig);
291 handler = signal(SIGILL, illegal_instruction);
292 if (setjmp(jmpbuf) == 0) {
293 asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1));
296 signal(SIGILL, handler);
305 if (CPU_haveCPUID()) {
306 return (CPU_getCPUIDFeatures() & 0x00800000);
314 if (CPU_haveCPUID()) {
317 cpuid(0x80000000, a, b, c, d);
318 if (a >= 0x80000001) {
319 cpuid(0x80000001, a, b, c, d);
320 return (d & 0x80000000);
329 if (CPU_haveCPUID()) {
330 return (CPU_getCPUIDFeatures() & 0x02000000);
338 if (CPU_haveCPUID()) {
339 return (CPU_getCPUIDFeatures() & 0x04000000);
347 if (CPU_haveCPUID()) {
350 cpuid(0, a, b, c, d);
352 cpuid(1, a, b, c, d);
353 return (c & 0x00000001);
362 if (CPU_haveCPUID()) {
365 cpuid(0, a, b, c, d);
367 cpuid(1, a, b, c, d);
368 return (c & 0x00080000);
377 if (CPU_haveCPUID()) {
380 cpuid(0, a, b, c, d);
382 cpuid(1, a, b, c, d);
383 return (c & 0x00100000);
392 if (CPU_haveCPUID() && CPU_OSSavesYMM()) {
395 cpuid(0, a, b, c, d);
397 cpuid(1, a, b, c, d);
398 return (c & 0x10000000);
407 if (CPU_haveCPUID() && CPU_OSSavesYMM()) {
410 cpuid(0, a, b, c, d);
412 cpuid(7, a, b, c, d);
413 return (b & 0x00000020);
419 static int SDL_CPUCount = 0;
422 SDL_GetCPUCount(void)
425 #ifndef SDL_CPUINFO_DISABLED
426 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
427 if (SDL_CPUCount <= 0) {
428 SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN);
431 #ifdef HAVE_SYSCTLBYNAME
432 if (SDL_CPUCount <= 0) {
433 size_t size = sizeof(SDL_CPUCount);
434 sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0);
438 if (SDL_CPUCount <= 0) {
440 GetSystemInfo(&info);
441 SDL_CPUCount = info.dwNumberOfProcessors;
445 /* There has to be at least 1, right? :) */
446 if (SDL_CPUCount <= 0) {
453 /* Oh, such a sweet sweet trick, just not very useful. :) */
457 static char SDL_CPUType[13];
459 if (!SDL_CPUType[0]) {
462 if (CPU_haveCPUID()) {
464 cpuid(0x00000000, a, b, c, d);
466 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
467 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
468 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
469 SDL_CPUType[i++] = (char)(b & 0xff);
471 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
472 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
473 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
474 SDL_CPUType[i++] = (char)(d & 0xff);
476 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
477 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
478 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
479 SDL_CPUType[i++] = (char)(c & 0xff);
481 if (!SDL_CPUType[0]) {
482 SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
489 #ifdef TEST_MAIN /* !!! FIXME: only used for test at the moment. */
493 static char SDL_CPUName[48];
495 if (!SDL_CPUName[0]) {
499 if (CPU_haveCPUID()) {
500 cpuid(0x80000000, a, b, c, d);
501 if (a >= 0x80000004) {
502 cpuid(0x80000002, a, b, c, d);
503 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
504 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
505 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
506 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
507 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
508 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
509 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
510 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
511 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
512 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
513 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
514 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
515 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
516 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
517 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
518 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
519 cpuid(0x80000003, a, b, c, d);
520 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
521 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
522 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
523 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
524 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
525 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
526 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
527 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
528 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
529 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
530 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
531 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
532 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
533 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
534 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
535 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
536 cpuid(0x80000004, a, b, c, d);
537 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
538 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
539 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
540 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
541 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
542 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
543 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
544 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
545 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
546 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
547 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
548 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
549 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
550 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
551 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
552 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
555 if (!SDL_CPUName[0]) {
556 SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName));
564 SDL_GetCPUCacheLineSize(void)
566 const char *cpuType = SDL_GetCPUType();
568 (void) a; (void) b; (void) c; (void) d;
569 if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
570 cpuid(0x00000001, a, b, c, d);
571 return (((b >> 8) & 0xff) * 8);
572 } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) {
573 cpuid(0x80000005, a, b, c, d);
576 /* Just make a guess here... */
577 return SDL_CACHELINE_SIZE;
581 static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
584 SDL_GetCPUFeatures(void)
586 if (SDL_CPUFeatures == 0xFFFFFFFF) {
588 if (CPU_haveRDTSC()) {
589 SDL_CPUFeatures |= CPU_HAS_RDTSC;
591 if (CPU_haveAltiVec()) {
592 SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
595 SDL_CPUFeatures |= CPU_HAS_MMX;
597 if (CPU_have3DNow()) {
598 SDL_CPUFeatures |= CPU_HAS_3DNOW;
601 SDL_CPUFeatures |= CPU_HAS_SSE;
603 if (CPU_haveSSE2()) {
604 SDL_CPUFeatures |= CPU_HAS_SSE2;
606 if (CPU_haveSSE3()) {
607 SDL_CPUFeatures |= CPU_HAS_SSE3;
609 if (CPU_haveSSE41()) {
610 SDL_CPUFeatures |= CPU_HAS_SSE41;
612 if (CPU_haveSSE42()) {
613 SDL_CPUFeatures |= CPU_HAS_SSE42;
616 SDL_CPUFeatures |= CPU_HAS_AVX;
618 if (CPU_haveAVX2()) {
619 SDL_CPUFeatures |= CPU_HAS_AVX2;
622 return SDL_CPUFeatures;
628 if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) {
637 if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) {
646 if (SDL_GetCPUFeatures() & CPU_HAS_MMX) {
655 if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) {
664 if (SDL_GetCPUFeatures() & CPU_HAS_SSE) {
673 if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) {
682 if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) {
691 if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) {
700 if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) {
709 if (SDL_GetCPUFeatures() & CPU_HAS_AVX) {
718 if (SDL_GetCPUFeatures() & CPU_HAS_AVX2) {
724 static int SDL_SystemRAM = 0;
727 SDL_GetSystemRAM(void)
729 if (!SDL_SystemRAM) {
730 #ifndef SDL_CPUINFO_DISABLED
731 #if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
732 if (SDL_SystemRAM <= 0) {
733 SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024));
736 #ifdef HAVE_SYSCTLBYNAME
737 if (SDL_SystemRAM <= 0) {
738 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
740 int mib[2] = {CTL_HW, HW_REALMEM};
742 /* might only report up to 2 GiB */
743 int mib[2] = {CTL_HW, HW_PHYSMEM};
744 #endif /* HW_REALMEM */
746 int mib[2] = {CTL_HW, HW_MEMSIZE};
747 #endif /* __FreeBSD__ || __FreeBSD_kernel__ */
749 size_t len = sizeof(memsize);
751 if (sysctl(mib, 2, &memsize, &len, NULL, 0) == 0) {
752 SDL_SystemRAM = (int)(memsize / (1024*1024));
757 if (SDL_SystemRAM <= 0) {
759 stat.dwLength = sizeof(stat);
760 if (GlobalMemoryStatusEx(&stat)) {
761 SDL_SystemRAM = (int)(stat.ullTotalPhys / (1024 * 1024));
767 return SDL_SystemRAM;
778 printf("CPU count: %d\n", SDL_GetCPUCount());
779 printf("CPU type: %s\n", SDL_GetCPUType());
780 printf("CPU name: %s\n", SDL_GetCPUName());
781 printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize());
782 printf("RDTSC: %d\n", SDL_HasRDTSC());
783 printf("Altivec: %d\n", SDL_HasAltiVec());
784 printf("MMX: %d\n", SDL_HasMMX());
785 printf("3DNow: %d\n", SDL_Has3DNow());
786 printf("SSE: %d\n", SDL_HasSSE());
787 printf("SSE2: %d\n", SDL_HasSSE2());
788 printf("SSE3: %d\n", SDL_HasSSE3());
789 printf("SSE4.1: %d\n", SDL_HasSSE41());
790 printf("SSE4.2: %d\n", SDL_HasSSE42());
791 printf("AVX: %d\n", SDL_HasAVX());
792 printf("AVX2: %d\n", SDL_HasAVX2());
793 printf("RAM: %d MB\n", SDL_GetSystemRAM());
797 #endif /* TEST_MAIN */
799 /* vi: set ts=4 sw=4 expandtab: */