Static analysis fix: Value stored to '[bcd]' is never read.
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
64 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__
65 /* This is the brute force way of detecting instruction sets...
66 the idea is borrowed from the libmpeg2 library - thanks!
68 static jmp_buf jmpbuf;
70 illegal_instruction(int sig)
74 #endif /* HAVE_SETJMP */
81 #if defined(__GNUC__) && defined(i386)
83 " pushfl # Get original EFLAGS \n"
85 " movl %%eax,%%ecx \n"
86 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n"
87 " pushl %%eax # Save new EFLAGS value on stack \n"
88 " popfl # Replace current EFLAGS value \n"
89 " pushfl # Get new EFLAGS \n"
90 " popl %%eax # Store new EFLAGS in EAX \n"
91 " xorl %%ecx,%%eax # Can not toggle ID bit, \n"
92 " jz 1f # Processor=80486 \n"
93 " movl $1,%0 # We have CPUID support \n"
99 #elif defined(__GNUC__) && defined(__x86_64__)
100 /* Technically, if this is being compiled under __x86_64__ then it has
101 CPUid by definition. But it's nice to be able to prove it. :) */
103 " pushfq # Get original EFLAGS \n"
105 " movq %%rax,%%rcx \n"
106 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n"
107 " pushq %%rax # Save new EFLAGS value on stack \n"
108 " popfq # Replace current EFLAGS value \n"
109 " pushfq # Get new EFLAGS \n"
110 " popq %%rax # Store new EFLAGS in EAX \n"
111 " xorl %%ecx,%%eax # Can not toggle ID bit, \n"
112 " jz 1f # Processor=80486 \n"
113 " movl $1,%0 # We have CPUID support \n"
119 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
121 pushfd ; Get original EFLAGS
124 xor eax, 200000h ; Flip ID bit in EFLAGS
125 push eax ; Save new EFLAGS value on stack
126 popfd ; Replace current EFLAGS value
127 pushfd ; Get new EFLAGS
128 pop eax ; Store new EFLAGS in EAX
129 xor eax, ecx ; Can not toggle ID bit,
130 jz done ; Processor=80486
131 mov has_CPUID,1 ; We have CPUID support
134 #elif defined(_MSC_VER) && defined(_M_X64)
136 #elif defined(__sun) && defined(__i386)
141 " xorl $0x200000,%eax \n"
148 " movl $1,-8(%ebp) \n"
151 #elif defined(__sun) && defined(__amd64)
156 " xorl $0x200000,%eax \n"
163 " movl $1,-8(%rbp) \n"
171 #if defined(__GNUC__) && defined(i386)
172 #define cpuid(func, a, b, c, d) \
173 __asm__ __volatile__ ( \
176 " movl %%ebx, %%esi \n" \
178 "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
179 #elif defined(__GNUC__) && defined(__x86_64__)
180 #define cpuid(func, a, b, c, d) \
181 __asm__ __volatile__ ( \
184 " movq %%rbx, %%rsi \n" \
186 "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
187 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
188 #define cpuid(func, a, b, c, d) \
190 __asm mov eax, func \
197 #elif defined(_MSC_VER) && defined(_M_X64)
198 #define cpuid(func, a, b, c, d) \
201 __cpuid(CPUInfo, func); \
208 #define cpuid(func, a, b, c, d) \
212 static SDL_INLINE int
213 CPU_getCPUIDFeatures(void)
218 cpuid(0, a, b, c, d);
220 cpuid(1, a, b, c, d);
226 static SDL_INLINE int
229 if (CPU_haveCPUID()) {
230 return (CPU_getCPUIDFeatures() & 0x00000010);
235 static SDL_INLINE int
236 CPU_haveAltiVec(void)
238 volatile int altivec = 0;
239 #if (defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__))
241 int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC };
243 int selectors[2] = { CTL_HW, HW_VECTORUNIT };
245 int hasVectorUnit = 0;
246 size_t length = sizeof(hasVectorUnit);
247 int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
249 altivec = (hasVectorUnit != 0);
250 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
251 void (*handler) (int sig);
252 handler = signal(SIGILL, illegal_instruction);
253 if (setjmp(jmpbuf) == 0) {
254 asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1));
257 signal(SIGILL, handler);
262 static SDL_INLINE int
265 if (CPU_haveCPUID()) {
266 return (CPU_getCPUIDFeatures() & 0x00800000);
271 static SDL_INLINE int
274 if (CPU_haveCPUID()) {
277 cpuid(0x80000000, a, b, c, d);
278 if (a >= 0x80000001) {
279 cpuid(0x80000001, a, b, c, d);
280 return (d & 0x80000000);
286 static SDL_INLINE int
289 if (CPU_haveCPUID()) {
290 return (CPU_getCPUIDFeatures() & 0x02000000);
295 static SDL_INLINE int
298 if (CPU_haveCPUID()) {
299 return (CPU_getCPUIDFeatures() & 0x04000000);
304 static SDL_INLINE int
307 if (CPU_haveCPUID()) {
310 cpuid(0, a, b, c, d);
312 cpuid(1, a, b, c, d);
313 return (c & 0x00000001);
319 static SDL_INLINE int
322 if (CPU_haveCPUID()) {
325 cpuid(1, a, b, c, d);
327 cpuid(1, a, b, c, d);
328 return (c & 0x00080000);
334 static SDL_INLINE int
337 if (CPU_haveCPUID()) {
340 cpuid(1, a, b, c, d);
342 cpuid(1, a, b, c, d);
343 return (c & 0x00100000);
349 static SDL_INLINE int
352 if (CPU_haveCPUID()) {
355 cpuid(1, a, b, c, d);
357 cpuid(1, a, b, c, d);
358 return (c & 0x10000000);
364 static int SDL_CPUCount = 0;
367 SDL_GetCPUCount(void)
370 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
371 if (SDL_CPUCount <= 0) {
372 SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN);
375 #ifdef HAVE_SYSCTLBYNAME
376 if (SDL_CPUCount <= 0) {
377 size_t size = sizeof(SDL_CPUCount);
378 sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0);
382 if (SDL_CPUCount <= 0) {
384 GetSystemInfo(&info);
385 SDL_CPUCount = info.dwNumberOfProcessors;
388 /* There has to be at least 1, right? :) */
389 if (SDL_CPUCount <= 0) {
396 /* Oh, such a sweet sweet trick, just not very useful. :) */
400 static char SDL_CPUType[13];
402 if (!SDL_CPUType[0]) {
406 if (CPU_haveCPUID()) {
407 cpuid(0x00000000, a, b, c, d);
408 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
409 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
410 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
411 SDL_CPUType[i++] = (char)(b & 0xff);
413 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
414 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
415 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
416 SDL_CPUType[i++] = (char)(d & 0xff);
418 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
419 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
420 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
421 SDL_CPUType[i++] = (char)(c & 0xff);
423 if (!SDL_CPUType[0]) {
424 SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
431 #ifdef TEST_MAIN /* !!! FIXME: only used for test at the moment. */
435 static char SDL_CPUName[48];
437 if (!SDL_CPUName[0]) {
441 if (CPU_haveCPUID()) {
442 cpuid(0x80000000, a, b, c, d);
443 if (a >= 0x80000004) {
444 cpuid(0x80000002, a, b, c, d);
445 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
446 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
447 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
448 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
449 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
450 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
451 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
452 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
453 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
454 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
455 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
456 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
457 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
458 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
459 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
460 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
461 cpuid(0x80000003, a, b, c, d);
462 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
463 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
464 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
465 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
466 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
467 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
468 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
469 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
470 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
471 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
472 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
473 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
474 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
475 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
476 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
477 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
478 cpuid(0x80000004, a, b, c, d);
479 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
480 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
481 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
482 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
483 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
484 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
485 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
486 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
487 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
488 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
489 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
490 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
491 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
492 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
493 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
494 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
497 if (!SDL_CPUName[0]) {
498 SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName));
506 SDL_GetCPUCacheLineSize(void)
508 const char *cpuType = SDL_GetCPUType();
510 if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
513 cpuid(0x00000001, a, b, c, d);
514 return (((b >> 8) & 0xff) * 8);
515 } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) {
518 cpuid(0x80000005, a, b, c, d);
521 /* Just make a guess here... */
522 return SDL_CACHELINE_SIZE;
526 static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
529 SDL_GetCPUFeatures(void)
531 if (SDL_CPUFeatures == 0xFFFFFFFF) {
533 if (CPU_haveRDTSC()) {
534 SDL_CPUFeatures |= CPU_HAS_RDTSC;
536 if (CPU_haveAltiVec()) {
537 SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
540 SDL_CPUFeatures |= CPU_HAS_MMX;
542 if (CPU_have3DNow()) {
543 SDL_CPUFeatures |= CPU_HAS_3DNOW;
546 SDL_CPUFeatures |= CPU_HAS_SSE;
548 if (CPU_haveSSE2()) {
549 SDL_CPUFeatures |= CPU_HAS_SSE2;
551 if (CPU_haveSSE3()) {
552 SDL_CPUFeatures |= CPU_HAS_SSE3;
554 if (CPU_haveSSE41()) {
555 SDL_CPUFeatures |= CPU_HAS_SSE41;
557 if (CPU_haveSSE42()) {
558 SDL_CPUFeatures |= CPU_HAS_SSE42;
561 SDL_CPUFeatures |= CPU_HAS_AVX;
564 return SDL_CPUFeatures;
570 if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) {
579 if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) {
588 if (SDL_GetCPUFeatures() & CPU_HAS_MMX) {
597 if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) {
606 if (SDL_GetCPUFeatures() & CPU_HAS_SSE) {
615 if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) {
624 if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) {
633 if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) {
642 if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) {
651 if (SDL_GetCPUFeatures() & CPU_HAS_AVX) {
657 static int SDL_SystemRAM = 0;
660 SDL_GetSystemRAM(void)
662 if (!SDL_SystemRAM) {
663 #if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
664 if (SDL_SystemRAM <= 0) {
665 SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024));
668 #ifdef HAVE_SYSCTLBYNAME
669 if (SDL_SystemRAM <= 0) {
670 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
672 int mib[2] = {CTL_HW, HW_REALMEM};
674 /* might only report up to 2 GiB */
675 int mib[2] = {CTL_HW, HW_PHYSMEM};
676 #endif /* HW_REALMEM */
678 int mib[2] = {CTL_HW, HW_MEMSIZE};
679 #endif /* __FreeBSD__ || __FreeBSD_kernel__ */
681 size_t len = sizeof(memsize);
683 if (sysctl(mib, 2, &memsize, &len, NULL, 0) == 0) {
684 SDL_SystemRAM = (int)(memsize / (1024*1024));
689 if (SDL_SystemRAM <= 0) {
691 stat.dwLength = sizeof(stat);
692 if (GlobalMemoryStatusEx(&stat)) {
693 SDL_SystemRAM = (int)(stat.ullTotalPhys / (1024 * 1024));
698 return SDL_SystemRAM;
709 printf("CPU count: %d\n", SDL_GetCPUCount());
710 printf("CPU type: %s\n", SDL_GetCPUType());
711 printf("CPU name: %s\n", SDL_GetCPUName());
712 printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize());
713 printf("RDTSC: %d\n", SDL_HasRDTSC());
714 printf("Altivec: %d\n", SDL_HasAltiVec());
715 printf("MMX: %d\n", SDL_HasMMX());
716 printf("3DNow: %d\n", SDL_Has3DNow());
717 printf("SSE: %d\n", SDL_HasSSE());
718 printf("SSE2: %d\n", SDL_HasSSE2());
719 printf("SSE3: %d\n", SDL_HasSSE3());
720 printf("SSE4.1: %d\n", SDL_HasSSE41());
721 printf("SSE4.2: %d\n", SDL_HasSSE42());
722 printf("AVX: %d\n", SDL_HasAVX());
723 printf("RAM: %d MB\n", SDL_GetSystemRAM());
727 #endif /* TEST_MAIN */
729 /* vi: set ts=4 sw=4 expandtab: */