24 #include "../SDL_internal.h" 28 #if defined(__WIN32__) 29 #include "../core/windows/SDL_windows.h" 34 #ifndef QSV_NUMPROCESSORS 35 #define QSV_NUMPROCESSORS 26 47 #ifdef HAVE_SYSCTLBYNAME 48 #include <sys/types.h> 49 #include <sys/sysctl.h> 51 #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__)) 52 #include <sys/sysctl.h> 53 #elif defined(__OpenBSD__) && defined(__powerpc__) 54 #include <sys/param.h> 55 #include <sys/sysctl.h> 56 #include <machine/cpu.h> 57 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP 62 #if defined(__QNXNTO__) 63 #include <sys/syspage.h> 66 #if (defined(__LINUX__) || defined(__ANDROID__)) && defined(__ARM_ARCH) 72 #define HWCAP_NEON (1 << 12) 74 #if defined HAVE_GETAUXVAL 81 #define CPU_HAS_RDTSC (1 << 0) 82 #define CPU_HAS_ALTIVEC (1 << 1) 83 #define CPU_HAS_MMX (1 << 2) 84 #define CPU_HAS_3DNOW (1 << 3) 85 #define CPU_HAS_SSE (1 << 4) 86 #define CPU_HAS_SSE2 (1 << 5) 87 #define CPU_HAS_SSE3 (1 << 6) 88 #define CPU_HAS_SSE41 (1 << 7) 89 #define CPU_HAS_SSE42 (1 << 8) 90 #define CPU_HAS_AVX (1 << 9) 91 #define CPU_HAS_AVX2 (1 << 10) 92 #define CPU_HAS_NEON (1 << 11) 93 #define CPU_HAS_AVX512F (1 << 12) 94 #define CPU_HAS_ARM_SIMD (1 << 13) 96 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__ 100 static jmp_buf jmpbuf;
102 illegal_instruction(
int sig)
114 #ifndef SDL_CPUINFO_DISABLED 115 #if defined(__GNUC__) && defined(i386) 117 " pushfl # Get original EFLAGS \n" 119 " movl %%eax,%%ecx \n" 120 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" 121 " pushl %%eax # Save new EFLAGS value on stack \n" 122 " popfl # Replace current EFLAGS value \n" 123 " pushfl # Get new EFLAGS \n" 124 " popl %%eax # Store new EFLAGS in EAX \n" 125 " xorl %%ecx,%%eax # Can not toggle ID bit, \n" 126 " jz 1f # Processor=80486 \n" 127 " movl $1,%0 # We have CPUID support \n" 133 #elif defined(__GNUC__) && defined(__x86_64__) 137 " pushfq # Get original EFLAGS \n" 139 " movq %%rax,%%rcx \n" 140 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" 141 " pushq %%rax # Save new EFLAGS value on stack \n" 142 " popfq # Replace current EFLAGS value \n" 143 " pushfq # Get new EFLAGS \n" 144 " popq %%rax # Store new EFLAGS in EAX \n" 145 " xorl %%ecx,%%eax # Can not toggle ID bit, \n" 146 " jz 1f # Processor=80486 \n" 147 " movl $1,%0 # We have CPUID support \n" 153 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 155 pushfd ; Get original EFLAGS
158 xor eax, 200000
h ; Flip ID bit
in EFLAGS
159 push eax ; Save
new EFLAGS
value on stack
160 popfd ; Replace current EFLAGS
value 161 pushfd ; Get
new EFLAGS
162 pop eax ; Store
new EFLAGS
in EAX
163 xor eax, ecx ; Can not toggle ID bit,
164 jz
done ; Processor=80486
165 mov has_CPUID,1 ; We have CPUID support
168 #elif defined(_MSC_VER) && defined(_M_X64) 170 #elif defined(__sun) && defined(__i386) 175 " xorl $0x200000,%eax \n" 182 " movl $1,-8(%ebp) \n" 185 #elif defined(__sun) && defined(__amd64) 190 " xorl $0x200000,%eax \n" 197 " movl $1,-8(%rbp) \n" 206 #if defined(__GNUC__) && defined(i386) 207 #define cpuid(func, a, b, c, d) \ 208 __asm__ __volatile__ ( \ 210 " xorl %%ecx,%%ecx \n" \ 212 " movl %%ebx, %%esi \n" \ 214 "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func)) 215 #elif defined(__GNUC__) && defined(__x86_64__) 216 #define cpuid(func, a, b, c, d) \ 217 __asm__ __volatile__ ( \ 219 " xorq %%rcx,%%rcx \n" \ 221 " movq %%rbx, %%rsi \n" \ 223 "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func)) 224 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 225 #define cpuid(func, a, b, c, d) \ 227 __asm mov eax, func \ 235 #elif defined(_MSC_VER) && defined(_M_X64) 236 #define cpuid(func, a, b, c, d) \ 239 __cpuid(CPUInfo, func); \ 246 #define cpuid(func, a, b, c, d) \ 247 do { a = b = c = d = 0; (void) a; (void) b; (void) c; (void) d; } while (0) 263 cpuid(0, a, b, c, d);
266 cpuid(1, a, b, c, d);
273 if (c & 0x08000000) {
275 #if defined(__GNUC__) && (defined(i386) || defined(__x86_64__)) 276 __asm__(
".byte 0x0f, 0x01, 0xd0" :
"=a" (a) :
"c" (0) :
"%edx");
277 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) 279 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 283 _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0
298 volatile int altivec = 0;
299 #ifndef SDL_CPUINFO_DISABLED 300 #if (defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__)) 302 int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC };
304 int selectors[2] = { CTL_HW, HW_VECTORUNIT };
306 int hasVectorUnit = 0;
307 size_t length =
sizeof(hasVectorUnit);
308 int error = sysctl(selectors, 2, &hasVectorUnit, &length,
NULL, 0);
310 altivec = (hasVectorUnit != 0);
311 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP 312 void (*handler) (
int sig);
313 handler = signal(SIGILL, illegal_instruction);
314 if (setjmp(jmpbuf) == 0) {
315 asm volatile (
"mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::
"r" (-1));
318 signal(SIGILL, handler);
327 #include <sys/types.h> 328 #include <sys/stat.h> 338 fd = open(
"/proc/self/auxv", O_RDONLY);
342 while (read(fd, &aux,
sizeof aux) ==
sizeof aux)
344 if (aux.a_type == AT_PLATFORM)
346 const char *plat = (
const char *) aux.a_un.a_val;
347 arm_simd = strncmp(plat,
"v6l", 3) == 0 ||
348 strncmp(plat,
"v7l", 3) == 0;
361 #warning SDL_HasARMSIMD is not implemented for this ARM platform. Write me. 367 #if (defined(__LINUX__) || defined(__ANDROID__)) && defined(__ARM_ARCH) && !defined(HAVE_GETAUXVAL) 369 readProcAuxvForNeon(
void)
373 const int fd = open(
"/proc/self/auxv", O_RDONLY);
375 while (read(fd, kv,
sizeof (kv)) ==
sizeof (kv)) {
376 if (kv[0] == AT_HWCAP) {
377 neon = ((kv[1] & HWCAP_NEON) == HWCAP_NEON);
393 #if defined(SDL_CPUINFO_DISABLED) || !defined(__ARM_ARCH) 395 #elif __ARM_ARCH >= 8 397 #elif defined(__APPLE__) && (__ARM_ARCH >= 7) 400 #elif defined(__APPLE__) 402 #elif defined(__QNXNTO__) 403 return SYSPAGE_ENTRY(cpuinfo)->flags & ARM_CPU_FLAG_NEON;
404 #elif (defined(__LINUX__) || defined(__ANDROID__)) && defined(HAVE_GETAUXVAL) 405 return ((getauxval(AT_HWCAP) & HWCAP_NEON) == HWCAP_NEON);
406 #elif (defined(__LINUX__) || defined(__ANDROID__)) 407 return readProcAuxvForNeon();
408 #elif (defined(__WINDOWS__) || defined(__WINRT__)) && defined(_M_ARM) 410 return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) != 0;
412 #warning SDL_HasNEON is not implemented for this ARM platform. Write me. 422 cpuid(0x80000000, a, b, c, d);
423 if (a >= 0x80000001) {
424 cpuid(0x80000001, a, b, c, d);
425 return (d & 0x80000000);
431 #define CPU_haveRDTSC() (CPU_CPUIDFeatures[3] & 0x00000010) 432 #define CPU_haveMMX() (CPU_CPUIDFeatures[3] & 0x00800000) 433 #define CPU_haveSSE() (CPU_CPUIDFeatures[3] & 0x02000000) 434 #define CPU_haveSSE2() (CPU_CPUIDFeatures[3] & 0x04000000) 435 #define CPU_haveSSE3() (CPU_CPUIDFeatures[2] & 0x00000001) 436 #define CPU_haveSSE41() (CPU_CPUIDFeatures[2] & 0x00080000) 437 #define CPU_haveSSE42() (CPU_CPUIDFeatures[2] & 0x00100000) 438 #define CPU_haveAVX() (CPU_OSSavesYMM && (CPU_CPUIDFeatures[2] & 0x10000000)) 446 cpuid(7, a, b, c, d);
447 return (b & 0x00000020);
458 cpuid(7, a, b, c, d);
459 return (b & 0x00010000);
470 #ifndef SDL_CPUINFO_DISABLED 471 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) 476 #ifdef HAVE_SYSCTLBYNAME 485 GetSystemInfo(&info);
491 DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS,
508 static char SDL_CPUType[13];
510 if (!SDL_CPUType[0]) {
516 cpuid(0x00000000, a, b, c, d);
518 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
519 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
520 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
521 SDL_CPUType[i++] = (char)(b & 0xff);
523 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
524 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
525 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
526 SDL_CPUType[i++] = (char)(d & 0xff);
528 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
529 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
530 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
531 SDL_CPUType[i++] = (char)(c & 0xff);
533 if (!SDL_CPUType[0]) {
534 SDL_strlcpy(SDL_CPUType,
"Unknown",
sizeof(SDL_CPUType));
545 static char SDL_CPUName[48];
547 if (!SDL_CPUName[0]) {
553 cpuid(0x80000000, a, b, c, d);
554 if (a >= 0x80000004) {
555 cpuid(0x80000002, a, b, c, d);
556 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
557 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
558 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
559 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
560 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
561 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
562 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
563 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
564 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
565 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
566 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
567 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
568 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
569 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
570 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
571 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
572 cpuid(0x80000003, a, b, c, d);
573 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
574 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
575 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
576 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
577 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
578 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
579 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
580 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
581 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
582 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
583 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
584 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
585 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
586 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
587 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
588 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
589 cpuid(0x80000004, a, b, c, d);
590 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
591 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
592 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
593 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
594 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
595 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
596 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
597 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
598 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
599 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
600 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
601 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
602 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
603 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
604 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
605 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
608 if (!SDL_CPUName[0]) {
609 SDL_strlcpy(SDL_CPUName,
"Unknown",
sizeof(SDL_CPUName));
622 if (
SDL_strcmp(cpuType,
"GenuineIntel") == 0) {
623 cpuid(0x00000001, a, b, c, d);
624 return (((b >> 8) & 0xff) * 8);
625 }
else if (
SDL_strcmp(cpuType,
"AuthenticAMD") == 0) {
626 cpuid(0x80000005, a, b, c, d);
703 #define CPU_FEATURE_AVAILABLE(f) ((SDL_GetCPUFeatures() & f) ? SDL_TRUE : SDL_FALSE) 794 #ifndef SDL_CPUINFO_DISABLED 795 #if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) 797 SDL_SystemRAM = (int)((
Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024));
800 #ifdef HAVE_SYSCTLBYNAME 802 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) 804 int mib[2] = {CTL_HW, HW_REALMEM};
807 int mib[2] = {CTL_HW, HW_PHYSMEM};
810 int mib[2] = {CTL_HW, HW_MEMSIZE};
813 size_t len =
sizeof(memsize);
815 if (sysctl(mib, 2, &memsize, &len,
NULL, 0) == 0) {
823 stat.dwLength =
sizeof(stat);
824 if (GlobalMemoryStatusEx(&stat)) {
832 DosQuerySysInfo(QSV_TOTPHYSMEM, QSV_TOTPHYSMEM, &sysram, 4);
856 const size_t padding = alignment - (len % alignment);
857 const size_t padded = (padding != alignment) ? (len + padding) :
len;
862 retval = ptr +
sizeof (
void *);
863 retval += alignment - (((
size_t) retval) % alignment);
864 *(((
void **) retval) - 1) = ptr;
873 void **realptr = (
void **) ptr;
889 printf(
"CPU name: %s\n", SDL_GetCPUName());
void SDL_SIMDFree(void *ptr)
Deallocate memory obtained from SDL_SIMDAlloc.
static SDL_bool CPU_OSSavesYMM
SDL_bool SDL_HasSSE41(void)
static void CPU_calcCPUIDFeatures(void)
int SDL_GetCPUCount(void)
static const char * SDL_GetCPUType(void)
GLfloat GLfloat GLfloat GLfloat h
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF ptr
SDL_bool SDL_HasAVX512F(void)
SDL_bool SDL_HasSSE(void)
SDL_bool SDL_HasSSE3(void)
static SDL_bool CPU_haveARMSIMD(void)
static int CPU_CPUIDMaxFunction
static int CPU_have3DNow(void)
void * SDL_SIMDAlloc(const size_t len)
Allocate memory in a SIMD-friendly way.
SDL_bool SDL_HasAltiVec(void)
static int CPU_haveCPUID(void)
SDL_bool SDL_HasSSE42(void)
SDL_bool SDL_HasARMSIMD(void)
SDL_bool SDL_HasMMX(void)
SDL_bool SDL_HasAVX2(void)
static int CPU_haveAltiVec(void)
static int CPU_haveAVX512F(void)
static SDL_bool CPU_OSSavesZMM
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF base if bpp PF set rept prefetch_distance PF set OFFSET endr endif endm macro preload_leading_step2 base if bpp ifc DST PF PF else if bpp lsl PF PF lsl PF PF lsl PF PF PF else PF mov
#define CPU_FEATURE_AVAILABLE(f)
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
SDL_bool SDL_HasNEON(void)
#define SDL_CACHELINE_SIZE
GLsizei const GLfloat * value
#define cpuid(func, a, b, c, d)
SDL_bool SDL_HasAVX(void)
static Uint32 SDL_CPUFeatures
static Uint32 SDL_GetCPUFeatures(void)
static int CPU_haveAVX2(void)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
#define SDL_assert(condition)
static int CPU_haveNEON(void)
SDL_bool SDL_HasRDTSC(void)
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
int SDL_GetSystemRAM(void)
static Uint32 SDL_SIMDAlignment
size_t SDL_SIMDGetAlignment(void)
Report the alignment this system needs for SIMD allocations.
static int CPU_CPUIDFeatures[4]
GLuint GLsizei GLsizei * length
GLboolean GLboolean GLboolean GLboolean a
SDL_bool SDL_HasSSE2(void)
GLboolean GLboolean GLboolean b
SDL_bool SDL_Has3DNow(void)
int SDL_GetCPUCacheLineSize(void)