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_MSA (1 << 13) 95 #define CPU_HAS_LSX (1 << 14) 96 #define CPU_HAS_LASX (1 << 15) 99 #define CPU_CFG2_LSX (1 << 6) 100 #define CPU_CFG2_LASX (1 << 7) 102 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__ 106 static jmp_buf jmpbuf;
108 illegal_instruction(
int sig)
120 #ifndef SDL_CPUINFO_DISABLED 121 #if defined(__GNUC__) && defined(i386) 123 " pushfl # Get original EFLAGS \n" 125 " movl %%eax,%%ecx \n" 126 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" 127 " pushl %%eax # Save new EFLAGS value on stack \n" 128 " popfl # Replace current EFLAGS value \n" 129 " pushfl # Get new EFLAGS \n" 130 " popl %%eax # Store new EFLAGS in EAX \n" 131 " xorl %%ecx,%%eax # Can not toggle ID bit, \n" 132 " jz 1f # Processor=80486 \n" 133 " movl $1,%0 # We have CPUID support \n" 139 #elif defined(__GNUC__) && defined(__x86_64__) 143 " pushfq # Get original EFLAGS \n" 145 " movq %%rax,%%rcx \n" 146 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" 147 " pushq %%rax # Save new EFLAGS value on stack \n" 148 " popfq # Replace current EFLAGS value \n" 149 " pushfq # Get new EFLAGS \n" 150 " popq %%rax # Store new EFLAGS in EAX \n" 151 " xorl %%ecx,%%eax # Can not toggle ID bit, \n" 152 " jz 1f # Processor=80486 \n" 153 " movl $1,%0 # We have CPUID support \n" 159 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 161 pushfd ; Get original EFLAGS
164 xor eax, 200000
h ; Flip ID bit
in EFLAGS
165 push eax ; Save
new EFLAGS
value on stack
166 popfd ; Replace current EFLAGS
value 167 pushfd ; Get
new EFLAGS
168 pop eax ; Store
new EFLAGS
in EAX
169 xor eax, ecx ; Can not toggle ID bit,
170 jz
done ; Processor=80486
171 mov has_CPUID,1 ; We have CPUID support
174 #elif defined(_MSC_VER) && defined(_M_X64) 176 #elif defined(__sun) && defined(__i386) 181 " xorl $0x200000,%eax \n" 188 " movl $1,-8(%ebp) \n" 191 #elif defined(__sun) && defined(__amd64) 196 " xorl $0x200000,%eax \n" 203 " movl $1,-8(%rbp) \n" 212 #if defined(__GNUC__) && defined(i386) 213 #define cpuid(func, a, b, c, d) \ 214 __asm__ __volatile__ ( \ 216 " xorl %%ecx,%%ecx \n" \ 218 " movl %%ebx, %%esi \n" \ 220 "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func)) 221 #elif defined(__GNUC__) && defined(__x86_64__) 222 #define cpuid(func, a, b, c, d) \ 223 __asm__ __volatile__ ( \ 225 " xorq %%rcx,%%rcx \n" \ 227 " movq %%rbx, %%rsi \n" \ 229 "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func)) 230 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 231 #define cpuid(func, a, b, c, d) \ 233 __asm mov eax, func \ 241 #elif defined(_MSC_VER) && defined(_M_X64) 242 #define cpuid(func, a, b, c, d) \ 245 __cpuid(CPUInfo, func); \ 252 #define cpuid(func, a, b, c, d) \ 253 do { a = b = c = d = 0; (void) a; (void) b; (void) c; (void) d; } while (0) 269 cpuid(0, a, b, c, d);
272 cpuid(1, a, b, c, d);
279 if (c & 0x08000000) {
281 #if defined(__GNUC__) && (defined(i386) || defined(__x86_64__)) 282 __asm__(
".byte 0x0f, 0x01, 0xd0" :
"=a" (a) :
"c" (0) :
"%edx");
283 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) 285 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 289 _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0
304 volatile int altivec = 0;
305 #ifndef SDL_CPUINFO_DISABLED 306 #if (defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__)) 308 int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC };
310 int selectors[2] = { CTL_HW, HW_VECTORUNIT };
312 int hasVectorUnit = 0;
313 size_t length =
sizeof(hasVectorUnit);
314 int error = sysctl(selectors, 2, &hasVectorUnit, &length,
NULL, 0);
316 altivec = (hasVectorUnit != 0);
317 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP 318 void (*handler) (
int sig);
319 handler = signal(SIGILL, illegal_instruction);
320 if (setjmp(jmpbuf) == 0) {
321 asm volatile (
"mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::
"r" (-1));
324 signal(SIGILL, handler);
330 #if (defined(__LINUX__) || defined(__ANDROID__)) && defined(__ARM_ARCH) && !defined(HAVE_GETAUXVAL) 332 readProcAuxvForNeon(
void)
336 const int fd = open(
"/proc/self/auxv", O_RDONLY);
338 while (read(fd, kv,
sizeof (kv)) ==
sizeof (kv)) {
339 if (kv[0] == AT_HWCAP) {
340 neon = ((kv[1] & HWCAP_NEON) == HWCAP_NEON);
356 #if defined(SDL_CPUINFO_DISABLED) || !defined(__ARM_ARCH) 358 #elif __ARM_ARCH >= 8 360 #elif defined(__APPLE__) && (__ARM_ARCH >= 7) 363 #elif defined(__APPLE__) 365 #elif defined(__QNXNTO__) 366 return SYSPAGE_ENTRY(cpuinfo)->flags & ARM_CPU_FLAG_NEON;
367 #elif (defined(__LINUX__) || defined(__ANDROID__)) && defined(HAVE_GETAUXVAL) 368 return ((getauxval(AT_HWCAP) & HWCAP_NEON) == HWCAP_NEON);
369 #elif (defined(__LINUX__) || defined(__ANDROID__)) 370 return readProcAuxvForNeon();
371 #elif (defined(__WINDOWS__) || defined(__WINRT__)) && defined(_M_ARM) 373 return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) != 0;
375 #warning SDL_HasNEON is not implemented for this ARM platform. Write me. 387 FILE* fp = fopen(
"/proc/cpuinfo",
"r");
391 memset(buf, 0,
sizeof(buf));
392 while (fgets(buf,
sizeof(buf), fp)) {
393 if (!strncmp(buf,
"cpu model", strlen(
"cpu model"))) {
397 if (strstr(buf,
"Loongson-2K")) {
402 if (!strncmp(buf,
"ASEs implemented", strlen(
"ASEs implemented"))) {
403 if (strstr(buf,
"msa")) {
420 #if defined __loongarch__ 430 #define CPU_haveLSX() (CPU_readCPUCFG() & CPU_CFG2_LSX) 431 #define CPU_haveLASX() (CPU_readCPUCFG() & CPU_CFG2_LASX) 438 cpuid(0x80000000, a, b, c, d);
439 if (a >= 0x80000001) {
440 cpuid(0x80000001, a, b, c, d);
441 return (d & 0x80000000);
447 #define CPU_haveRDTSC() (CPU_CPUIDFeatures[3] & 0x00000010) 448 #define CPU_haveMMX() (CPU_CPUIDFeatures[3] & 0x00800000) 449 #define CPU_haveSSE() (CPU_CPUIDFeatures[3] & 0x02000000) 450 #define CPU_haveSSE2() (CPU_CPUIDFeatures[3] & 0x04000000) 451 #define CPU_haveSSE3() (CPU_CPUIDFeatures[2] & 0x00000001) 452 #define CPU_haveSSE41() (CPU_CPUIDFeatures[2] & 0x00080000) 453 #define CPU_haveSSE42() (CPU_CPUIDFeatures[2] & 0x00100000) 454 #define CPU_haveAVX() (CPU_OSSavesYMM && (CPU_CPUIDFeatures[2] & 0x10000000)) 462 cpuid(7, a, b, c, d);
463 return (b & 0x00000020);
474 cpuid(7, a, b, c, d);
475 return (b & 0x00010000);
486 #ifndef SDL_CPUINFO_DISABLED 487 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) 492 #ifdef HAVE_SYSCTLBYNAME 501 GetSystemInfo(&info);
507 DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS,
524 static char SDL_CPUType[13];
526 if (!SDL_CPUType[0]) {
532 cpuid(0x00000000, a, b, c, d);
534 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
535 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
536 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
537 SDL_CPUType[i++] = (char)(b & 0xff);
539 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
540 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
541 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
542 SDL_CPUType[i++] = (char)(d & 0xff);
544 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
545 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
546 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
547 SDL_CPUType[i++] = (char)(c & 0xff);
549 if (!SDL_CPUType[0]) {
550 SDL_strlcpy(SDL_CPUType,
"Unknown",
sizeof(SDL_CPUType));
561 static char SDL_CPUName[48];
563 if (!SDL_CPUName[0]) {
569 cpuid(0x80000000, a, b, c, d);
570 if (a >= 0x80000004) {
571 cpuid(0x80000002, a, b, c, d);
572 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
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)(b & 0xff); b >>= 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)(c & 0xff); c >>= 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)(d & 0xff); d >>= 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 cpuid(0x80000003, a, b, c, d);
589 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
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)(b & 0xff); b >>= 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)(c & 0xff); c >>= 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)(d & 0xff); d >>= 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 cpuid(0x80000004, a, b, c, d);
606 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
607 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
608 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
609 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
610 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
611 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
612 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
613 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
614 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
615 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
616 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
617 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
618 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
619 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
620 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
621 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
624 if (!SDL_CPUName[0]) {
625 SDL_strlcpy(SDL_CPUName,
"Unknown",
sizeof(SDL_CPUName));
638 if (
SDL_strcmp(cpuType,
"GenuineIntel") == 0) {
639 cpuid(0x00000001, a, b, c, d);
640 return (((b >> 8) & 0xff) * 8);
641 }
else if (
SDL_strcmp(cpuType,
"AuthenticAMD") == 0) {
642 cpuid(0x80000005, a, b, c, d);
727 #define CPU_FEATURE_AVAILABLE(f) ((SDL_GetCPUFeatures() & f) ? SDL_TRUE : SDL_FALSE) 830 #ifndef SDL_CPUINFO_DISABLED 831 #if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) 833 SDL_SystemRAM = (int)((
Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024));
836 #ifdef HAVE_SYSCTLBYNAME 838 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) 840 int mib[2] = {CTL_HW, HW_REALMEM};
843 int mib[2] = {CTL_HW, HW_PHYSMEM};
846 int mib[2] = {CTL_HW, HW_MEMSIZE};
849 size_t len =
sizeof(memsize);
851 if (sysctl(mib, 2, &memsize, &len,
NULL, 0) == 0) {
859 stat.dwLength =
sizeof(stat);
860 if (GlobalMemoryStatusEx(&stat)) {
868 DosQuerySysInfo(QSV_TOTPHYSMEM, QSV_TOTPHYSMEM, &sysram, 4);
892 const size_t padding = alignment - (len % alignment);
893 const size_t padded = (padding != alignment) ? (len + padding) :
len;
898 retval = ptr +
sizeof (
void *);
899 retval += alignment - (((
size_t) retval) % alignment);
900 *(((
void **) retval) - 1) = ptr;
909 void **realptr = (
void **) ptr;
925 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
SDL_bool SDL_HasAVX512F(void)
SDL_bool SDL_HasSSE(void)
SDL_bool SDL_HasLASX(void)
SDL_bool SDL_HasSSE3(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_haveMSA(void)
static int CPU_haveCPUID(void)
SDL_bool SDL_HasSSE42(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
static int CPU_readCPUCFG(void)
#define CPU_FEATURE_AVAILABLE(f)
SDL_bool SDL_HasLSX(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 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)
GLenum GLuint GLenum GLsizei const GLchar * buf
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)
SDL_bool SDL_HasMSA(void)
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)