Atlas - SDL_cpuinfo.c

Home / ext / SDL / src / cpuinfo Lines: 61 | Size: 40541 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 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. 8 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: 12 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. 20*/ 21 22#include "SDL_internal.h" 23 24#include "SDL_cpuinfo_c.h" 25 26#if defined(SDL_PLATFORM_WINDOWS) 27#include "../core/windows/SDL_windows.h" 28#endif 29 30// CPU feature detection for SDL 31 32#if defined(HAVE_GETPAGESIZE) && !defined(SDL_PLATFORM_WINDOWS) 33#define USE_GETPAGESIZE 34#endif 35 36#if defined(HAVE_SYSCONF) || defined(USE_GETPAGESIZE) 37#include <unistd.h> 38#endif 39#ifdef HAVE_SYSCTLBYNAME 40#include <sys/types.h> 41#include <sys/sysctl.h> 42#endif 43#if defined(SDL_PLATFORM_MACOS) && (defined(__ppc__) || defined(__ppc64__)) 44#include <sys/sysctl.h> // For AltiVec check 45#elif defined(SDL_PLATFORM_OPENBSD) && defined(__powerpc__) && !defined(HAVE_ELF_AUX_INFO) 46#include <sys/types.h> 47#include <sys/sysctl.h> // For AltiVec check 48#include <machine/cpu.h> 49#elif defined(SDL_PLATFORM_FREEBSD) && defined(__powerpc__) && defined(HAVE_ELF_AUX_INFO) 50#include <machine/cpu.h> 51#elif defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP) 52#include <signal.h> 53#include <setjmp.h> 54#endif 55 56#if (defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_ANDROID)) && defined(__arm__) 57#include <unistd.h> 58#include <sys/types.h> 59#include <sys/stat.h> 60#include <fcntl.h> 61#include <elf.h> 62 63// #include <asm/hwcap.h> 64#ifndef AT_HWCAP 65#define AT_HWCAP 16 66#endif 67#ifndef AT_PLATFORM 68#define AT_PLATFORM 15 69#endif 70#ifndef HWCAP_NEON 71#define HWCAP_NEON (1 << 12) 72#endif 73#endif 74 75#if defined (SDL_PLATFORM_FREEBSD) 76#include <sys/param.h> 77#endif 78 79#if defined(HAVE_GETAUXVAL) || defined(HAVE_ELF_AUX_INFO) || defined(SDL_PLATFORM_ANDROID) 80#include <sys/auxv.h> 81#endif 82 83#ifdef SDL_PLATFORM_RISCOS 84#include <kernel.h> 85#include <swis.h> 86#endif 87#ifdef SDL_PLATFORM_3DS 88#include <3ds.h> 89#endif 90#ifdef SDL_PLATFORM_PS2 91#include <kernel.h> 92#endif 93 94#ifdef SDL_PLATFORM_HAIKU 95#include <kernel/OS.h> 96#endif 97 98#define CPU_HAS_ALTIVEC (1 << 0) 99#define CPU_HAS_MMX (1 << 1) 100#define CPU_HAS_SSE (1 << 2) 101#define CPU_HAS_SSE2 (1 << 3) 102#define CPU_HAS_SSE3 (1 << 4) 103#define CPU_HAS_SSE41 (1 << 5) 104#define CPU_HAS_SSE42 (1 << 6) 105#define CPU_HAS_AVX (1 << 7) 106#define CPU_HAS_AVX2 (1 << 8) 107#define CPU_HAS_NEON (1 << 9) 108#define CPU_HAS_AVX512F (1 << 10) 109#define CPU_HAS_ARM_SIMD (1 << 11) 110#define CPU_HAS_LSX (1 << 12) 111#define CPU_HAS_LASX (1 << 13) 112 113#define CPU_CFG2 0x2 114#define CPU_CFG2_LSX (1 << 6) 115#define CPU_CFG2_LASX (1 << 7) 116 117#if !defined(SDL_CPUINFO_DISABLED) && \ 118 !((defined(SDL_PLATFORM_MACOS) && (defined(__ppc__) || defined(__ppc64__))) || (defined(SDL_PLATFORM_OPENBSD) && defined(__powerpc__))) && \ 119 !(defined(SDL_PLATFORM_FREEBSD) && defined(__powerpc__)) && \ 120 !(defined(SDL_PLATFORM_LINUX) && defined(__powerpc__) && defined(HAVE_GETAUXVAL)) && \ 121 defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP) 122/* This is the brute force way of detecting instruction sets... 123 the idea is borrowed from the libmpeg2 library - thanks! 124 */ 125static jmp_buf jmpbuf; 126static void illegal_instruction(int sig) 127{ 128 longjmp(jmpbuf, 1); 129} 130#endif // HAVE_SETJMP 131 132static int CPU_haveCPUID(void) 133{ 134 int has_CPUID = 0; 135 136/* *INDENT-OFF* */ // clang-format off 137#ifndef SDL_PLATFORM_EMSCRIPTEN 138#if (defined(__GNUC__) || defined(__llvm__)) && defined(__i386__) 139 __asm__ ( 140" pushfl # Get original EFLAGS \n" 141" popl %%eax \n" 142" movl %%eax,%%ecx \n" 143" xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" 144" pushl %%eax # Save new EFLAGS value on stack \n" 145" popfl # Replace current EFLAGS value \n" 146" pushfl # Get new EFLAGS \n" 147" popl %%eax # Store new EFLAGS in EAX \n" 148" xorl %%ecx,%%eax # Can not toggle ID bit, \n" 149" jz 1f # Processor=80486 \n" 150" movl $1,%0 # We have CPUID support \n" 151"1: \n" 152 : "=m" (has_CPUID) 153 : 154 : "%eax", "%ecx" 155 ); 156#elif (defined(__GNUC__) || defined(__llvm__)) && defined(__x86_64__) 157/* Technically, if this is being compiled under __x86_64__ then it has 158 CPUid by definition. But it's nice to be able to prove it. :) */ 159 __asm__ ( 160" pushfq # Get original EFLAGS \n" 161" popq %%rax \n" 162" movq %%rax,%%rcx \n" 163" xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" 164" pushq %%rax # Save new EFLAGS value on stack \n" 165" popfq # Replace current EFLAGS value \n" 166" pushfq # Get new EFLAGS \n" 167" popq %%rax # Store new EFLAGS in EAX \n" 168" xorl %%ecx,%%eax # Can not toggle ID bit, \n" 169" jz 1f # Processor=80486 \n" 170" movl $1,%0 # We have CPUID support \n" 171"1: \n" 172 : "=m" (has_CPUID) 173 : 174 : "%rax", "%rcx" 175 ); 176#elif defined(_MSC_VER) && defined(_M_IX86) 177 __asm { 178 pushfd ; Get original EFLAGS 179 pop eax 180 mov ecx, eax 181 xor eax, 200000h ; Flip ID bit in EFLAGS 182 push eax ; Save new EFLAGS value on stack 183 popfd ; Replace current EFLAGS value 184 pushfd ; Get new EFLAGS 185 pop eax ; Store new EFLAGS in EAX 186 xor eax, ecx ; Can not toggle ID bit, 187 jz done ; Processor=80486 188 mov has_CPUID,1 ; We have CPUID support 189done: 190 } 191#elif defined(_MSC_VER) && defined(_M_X64) 192 has_CPUID = 1; 193#elif defined(__sun) && defined(__i386) 194 __asm ( 195" pushfl \n" 196" popl %eax \n" 197" movl %eax,%ecx \n" 198" xorl $0x200000,%eax \n" 199" pushl %eax \n" 200" popfl \n" 201" pushfl \n" 202" popl %eax \n" 203" xorl %ecx,%eax \n" 204" jz 1f \n" 205" movl $1,-8(%ebp) \n" 206"1: \n" 207 ); 208#elif defined(__sun) && defined(__amd64) 209 __asm ( 210" pushfq \n" 211" popq %rax \n" 212" movq %rax,%rcx \n" 213" xorl $0x200000,%eax \n" 214" pushq %rax \n" 215" popfq \n" 216" pushfq \n" 217" popq %rax \n" 218" xorl %ecx,%eax \n" 219" jz 1f \n" 220" movl $1,-8(%rbp) \n" 221"1: \n" 222 ); 223#endif 224#endif // !SDL_PLATFORM_EMSCRIPTEN 225/* *INDENT-ON* */ // clang-format on 226 return has_CPUID; 227} 228 229#if (defined(__GNUC__) || defined(__llvm__)) && defined(__i386__) 230#define cpuid(func, a, b, c, d) \ 231 __asm__ __volatile__( \ 232 " pushl %%ebx \n" \ 233 " xorl %%ecx,%%ecx \n" \ 234 " cpuid \n" \ 235 " movl %%ebx, %%esi \n" \ 236 " popl %%ebx \n" \ 237 : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \ 238 : "a"(func)) 239#elif (defined(__GNUC__) || defined(__llvm__)) && defined(__x86_64__) 240#define cpuid(func, a, b, c, d) \ 241 __asm__ __volatile__( \ 242 " pushq %%rbx \n" \ 243 " xorq %%rcx,%%rcx \n" \ 244 " cpuid \n" \ 245 " movq %%rbx, %%rsi \n" \ 246 " popq %%rbx \n" \ 247 : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \ 248 : "a"(func)) 249#elif defined(_MSC_VER) && defined(_M_IX86) 250#define cpuid(func, a, b, c, d) \ 251 __asm { \ 252 __asm mov eax, func \ 253 __asm xor ecx, ecx \ 254 __asm cpuid \ 255 __asm mov a, eax \ 256 __asm mov b, ebx \ 257 __asm mov c, ecx \ 258 __asm mov d, edx \ 259 } 260#elif (defined(_MSC_VER) && defined(_M_X64)) 261// Use __cpuidex instead of __cpuid because ICL does not clear ecx register 262#define cpuid(func, a, b, c, d) \ 263 { \ 264 int CPUInfo[4]; \ 265 __cpuidex(CPUInfo, func, 0); \ 266 a = CPUInfo[0]; \ 267 b = CPUInfo[1]; \ 268 c = CPUInfo[2]; \ 269 d = CPUInfo[3]; \ 270 } 271#else 272#define cpuid(func, a, b, c, d) \ 273 do { \ 274 a = b = c = d = 0; \ 275 (void)a; \ 276 (void)b; \ 277 (void)c; \ 278 (void)d; \ 279 } while (0) 280#endif 281 282static int CPU_CPUIDFeatures[4]; 283static int CPU_CPUIDMaxFunction = 0; 284static bool CPU_OSSavesYMM = false; 285static bool CPU_OSSavesZMM = false; 286 287static void CPU_calcCPUIDFeatures(void) 288{ 289 static bool checked = false; 290 if (!checked) { 291 checked = true; 292 if (CPU_haveCPUID()) { 293 int a, b, c, d; 294 cpuid(0, a, b, c, d); 295 CPU_CPUIDMaxFunction = a; 296 if (CPU_CPUIDMaxFunction >= 1) { 297 cpuid(1, a, b, c, d); 298 CPU_CPUIDFeatures[0] = a; 299 CPU_CPUIDFeatures[1] = b; 300 CPU_CPUIDFeatures[2] = c; 301 CPU_CPUIDFeatures[3] = d; 302 303 // Check to make sure we can call xgetbv 304 if (c & 0x08000000) { 305 // Call xgetbv to see if YMM (etc) register state is saved 306#if (defined(__GNUC__) || defined(__llvm__)) && (defined(__i386__) || defined(__x86_64__)) 307 __asm__(".byte 0x0f, 0x01, 0xd0" 308 : "=a"(a) 309 : "c"(0) 310 : "%edx"); 311#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) // VS2010 SP1 312 a = (int)_xgetbv(0); 313#elif defined(_MSC_VER) && defined(_M_IX86) 314 __asm 315 { 316 xor ecx, ecx 317 _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0 318 mov a, eax 319 } 320#endif 321 CPU_OSSavesYMM = ((a & 6) == 6) ? true : false; 322 CPU_OSSavesZMM = (CPU_OSSavesYMM && ((a & 0xe0) == 0xe0)) ? true : false; 323 } 324 } 325 } 326 } 327} 328 329static int CPU_haveAltiVec(void) 330{ 331 volatile int altivec = 0; 332#ifndef SDL_CPUINFO_DISABLED 333#if (defined(SDL_PLATFORM_FREEBSD) || defined(SDL_PLATFORM_OPENBSD)) && defined(__powerpc__) && defined(HAVE_ELF_AUX_INFO) 334 unsigned long cpufeatures = 0; 335 elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures)); 336 altivec = cpufeatures & PPC_FEATURE_HAS_ALTIVEC; 337 return altivec; 338#elif (defined(SDL_PLATFORM_MACOS) && (defined(__ppc__) || defined(__ppc64__))) || (defined(SDL_PLATFORM_OPENBSD) && defined(__powerpc__)) 339#ifdef SDL_PLATFORM_OPENBSD 340 int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC }; 341#else 342 int selectors[2] = { CTL_HW, HW_VECTORUNIT }; 343#endif 344 int hasVectorUnit = 0; 345 size_t length = sizeof(hasVectorUnit); 346 int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0); 347 if (0 == error) { 348 altivec = (hasVectorUnit != 0); 349 } 350#elif defined(SDL_PLATFORM_LINUX) && defined(__powerpc__) && defined(HAVE_GETAUXVAL) 351 altivec = getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC; 352#elif defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP) 353 void (*handler)(int sig); 354 handler = signal(SIGILL, illegal_instruction); 355 if (setjmp(jmpbuf) == 0) { 356 asm volatile("mtspr 256, %0\n\t" 357 "vand %%v0, %%v0, %%v0" ::"r"(-1)); 358 altivec = 1; 359 } 360 signal(SIGILL, handler); 361#endif 362#endif 363 return altivec; 364} 365 366#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 6)) || defined(__aarch64__) 367static int CPU_haveARMSIMD(void) 368{ 369 return 1; 370} 371 372#elif !defined(__arm__) 373static int CPU_haveARMSIMD(void) 374{ 375 return 0; 376} 377 378#elif defined(SDL_PLATFORM_LINUX) 379static int CPU_haveARMSIMD(void) 380{ 381 int arm_simd = 0; 382 int fd; 383 384 fd = open("/proc/self/auxv", O_RDONLY | O_CLOEXEC); 385 if (fd >= 0) { 386 Elf32_auxv_t aux; 387 while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) { 388 if (aux.a_type == AT_PLATFORM) { 389 const char *plat = (const char *)aux.a_un.a_val; 390 if (plat) { 391 arm_simd = SDL_strncmp(plat, "v6l", 3) == 0 || 392 SDL_strncmp(plat, "v7l", 3) == 0; 393 } 394 } 395 } 396 close(fd); 397 } 398 return arm_simd; 399} 400 401#elif defined(SDL_PLATFORM_RISCOS) 402static int CPU_haveARMSIMD(void) 403{ 404 _kernel_swi_regs regs; 405 regs.r[0] = 0; 406 if (_kernel_swi(OS_PlatformFeatures, &regs, &regs) != NULL) { 407 return 0; 408 } 409 410 if (!(regs.r[0] & (1 << 31))) { 411 return 0; 412 } 413 414 regs.r[0] = 34; 415 regs.r[1] = 29; 416 if (_kernel_swi(OS_PlatformFeatures, &regs, &regs) != NULL) { 417 return 0; 418 } 419 420 return regs.r[0]; 421} 422 423#elif defined(SDL_PLATFORM_NGAGE) 424static int CPU_haveARMSIMD(void) 425{ 426 // The RM920T is based on the ARMv4T architecture and doesn't have SIMD. 427 return 0; 428} 429#else 430static int CPU_haveARMSIMD(void) 431{ 432#warning SDL_HasARMSIMD is not implemented for this ARM platform. Write me. 433 return 0; 434} 435#endif 436 437#if defined(SDL_PLATFORM_LINUX) && defined(__arm__) && !defined(HAVE_GETAUXVAL) 438static int readProcAuxvForNeon(void) 439{ 440 int neon = 0; 441 int fd; 442 443 fd = open("/proc/self/auxv", O_RDONLY | O_CLOEXEC); 444 if (fd >= 0) { 445 Elf32_auxv_t aux; 446 while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) { 447 if (aux.a_type == AT_HWCAP) { 448 neon = (aux.a_un.a_val & HWCAP_NEON) == HWCAP_NEON; 449 break; 450 } 451 } 452 close(fd); 453 } 454 return neon; 455} 456#endif 457 458static int CPU_haveNEON(void) 459{ 460/* The way you detect NEON is a privileged instruction on ARM, so you have 461 query the OS kernel in a platform-specific way. :/ */ 462#if defined(SDL_PLATFORM_WINDOWS) && (defined(_M_ARM) || defined(_M_ARM64)) 463// Visual Studio, for ARM, doesn't define __ARM_ARCH. Handle this first. 464// Seems to have been removed 465#ifndef PF_ARM_NEON_INSTRUCTIONS_AVAILABLE 466#define PF_ARM_NEON_INSTRUCTIONS_AVAILABLE 19 467#endif 468 // All WinRT ARM devices are required to support NEON, but just in case. 469 return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) != 0; 470#elif (defined(__ARM_ARCH) && (__ARM_ARCH >= 8)) || defined(__aarch64__) 471 return 1; // ARMv8 always has non-optional NEON support. 472#elif defined(SDL_PLATFORM_VITA) 473 return 1; 474#elif defined(SDL_PLATFORM_3DS) 475 return 0; 476#elif defined(SDL_PLATFORM_NGAGE) 477 return 0; // The ARM920T is based on the ARMv4T architecture and doesn't have NEON. 478#elif defined(SDL_PLATFORM_APPLE) && defined(__ARM_ARCH) && (__ARM_ARCH >= 7) 479 // (note that sysctlbyname("hw.optional.neon") doesn't work!) 480 return 1; // all Apple ARMv7 chips and later have NEON. 481#elif defined(SDL_PLATFORM_APPLE) 482 return 0; // assume anything else from Apple doesn't have NEON. 483#elif !defined(__arm__) 484 return 0; // not an ARM CPU at all. 485#elif defined(HAVE_ELF_AUX_INFO) 486 unsigned long hasneon = 0; 487 if (elf_aux_info(AT_HWCAP, (void *)&hasneon, (int)sizeof(hasneon)) != 0) { 488 return 0; 489 } 490 return (hasneon & HWCAP_NEON) == HWCAP_NEON; 491#elif (defined(SDL_PLATFORM_LINUX) && defined(HAVE_GETAUXVAL)) || defined(SDL_PLATFORM_ANDROID) 492 return (getauxval(AT_HWCAP) & HWCAP_NEON) == HWCAP_NEON; 493#elif defined(SDL_PLATFORM_LINUX) 494 return readProcAuxvForNeon(); 495#elif defined(SDL_PLATFORM_RISCOS) 496 // Use the VFPSupport_Features SWI to access the MVFR registers 497 { 498 _kernel_swi_regs regs; 499 regs.r[0] = 0; 500 if (_kernel_swi(VFPSupport_Features, &regs, &regs) == NULL) { 501 if ((regs.r[2] & 0xFFF000) == 0x111000) { 502 return 1; 503 } 504 } 505 return 0; 506 } 507#elif defined(SDL_PLATFORM_OPENBSD) 508 return 1; // OpenBSD only supports ARMv7 CPUs that have NEON. 509#elif defined(SDL_PLATFORM_EMSCRIPTEN) 510 return 0; 511#else 512#warning SDL_HasNEON is not implemented for this ARM platform. Write me. 513 return 0; 514#endif 515} 516 517static int CPU_readCPUCFG(void) 518{ 519 uint32_t cfg2 = 0; 520#if defined __loongarch__ 521 __asm__ volatile( 522 "cpucfg %0, %1 \n\t" 523 : "+&r"(cfg2) 524 : "r"(CPU_CFG2)); 525#endif 526 return cfg2; 527} 528 529#define CPU_haveLSX() (CPU_readCPUCFG() & CPU_CFG2_LSX) 530#define CPU_haveLASX() (CPU_readCPUCFG() & CPU_CFG2_LASX) 531 532#ifdef __e2k__ 533#ifdef __MMX__ 534#define CPU_haveMMX() (1) 535#else 536#define CPU_haveMMX() (0) 537#endif 538#ifdef __SSE__ 539#define CPU_haveSSE() (1) 540#else 541#define CPU_haveSSE() (0) 542#endif 543#ifdef __SSE2__ 544#define CPU_haveSSE2() (1) 545#else 546#define CPU_haveSSE2() (0) 547#endif 548#ifdef __SSE3__ 549#define CPU_haveSSE3() (1) 550#else 551#define CPU_haveSSE3() (0) 552#endif 553#ifdef __SSE4_1__ 554#define CPU_haveSSE41() (1) 555#else 556#define CPU_haveSSE41() (0) 557#endif 558#ifdef __SSE4_2__ 559#define CPU_haveSSE42() (1) 560#else 561#define CPU_haveSSE42() (0) 562#endif 563#ifdef __AVX__ 564#define CPU_haveAVX() (1) 565#else 566#define CPU_haveAVX() (0) 567#endif 568#else 569#define CPU_haveMMX() (CPU_CPUIDFeatures[3] & 0x00800000) 570#define CPU_haveSSE() (CPU_CPUIDFeatures[3] & 0x02000000) 571#define CPU_haveSSE2() (CPU_CPUIDFeatures[3] & 0x04000000) 572#define CPU_haveSSE3() (CPU_CPUIDFeatures[2] & 0x00000001) 573#define CPU_haveSSE41() (CPU_CPUIDFeatures[2] & 0x00080000) 574#define CPU_haveSSE42() (CPU_CPUIDFeatures[2] & 0x00100000) 575#define CPU_haveAVX() (CPU_OSSavesYMM && (CPU_CPUIDFeatures[2] & 0x10000000)) 576#endif 577 578#ifdef __e2k__ 579inline int 580CPU_haveAVX2(void) 581{ 582#ifdef __AVX2__ 583 return 1; 584#else 585 return 0; 586#endif 587} 588#else 589static int CPU_haveAVX2(void) 590{ 591 if (CPU_OSSavesYMM && (CPU_CPUIDMaxFunction >= 7)) { 592 int a, b, c, d; 593 (void)a; 594 (void)b; 595 (void)c; 596 (void)d; // compiler warnings... 597 cpuid(7, a, b, c, d); 598 return b & 0x00000020; 599 } 600 return 0; 601} 602#endif 603 604#ifdef __e2k__ 605inline int 606CPU_haveAVX512F(void) 607{ 608 return 0; 609} 610#else 611static int CPU_haveAVX512F(void) 612{ 613 if (CPU_OSSavesZMM && (CPU_CPUIDMaxFunction >= 7)) { 614 int a, b, c, d; 615 (void)a; 616 (void)b; 617 (void)c; 618 (void)d; // compiler warnings... 619 cpuid(7, a, b, c, d); 620 return b & 0x00010000; 621 } 622 return 0; 623} 624#endif 625 626static int SDL_NumLogicalCPUCores = 0; 627 628int SDL_GetNumLogicalCPUCores(void) 629{ 630 if (!SDL_NumLogicalCPUCores) { 631#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) 632 if (SDL_NumLogicalCPUCores <= 0) { 633 SDL_NumLogicalCPUCores = (int)sysconf(_SC_NPROCESSORS_ONLN); 634 } 635#endif 636#ifdef HAVE_SYSCTLBYNAME 637 if (SDL_NumLogicalCPUCores <= 0) { 638 size_t size = sizeof(SDL_NumLogicalCPUCores); 639 sysctlbyname("hw.ncpu", &SDL_NumLogicalCPUCores, &size, NULL, 0); 640 } 641#endif 642#if defined(SDL_PLATFORM_WINDOWS) 643 if (SDL_NumLogicalCPUCores <= 0) { 644 SYSTEM_INFO info; 645 GetSystemInfo(&info); 646 SDL_NumLogicalCPUCores = info.dwNumberOfProcessors; 647 } 648#endif 649#ifdef SDL_PLATFORM_3DS 650 if (SDL_NumLogicalCPUCores <= 0) { 651 bool isNew3DS = false; 652 APT_CheckNew3DS(&isNew3DS); 653 // 1 core is always dedicated to the OS 654 // Meaning that the New3DS has 3 available core, and the Old3DS only one. 655 SDL_NumLogicalCPUCores = isNew3DS ? 4 : 2; 656 } 657#endif 658 // There has to be at least 1, right? :) 659 if (SDL_NumLogicalCPUCores <= 0) { 660 SDL_NumLogicalCPUCores = 1; 661 } 662 } 663 return SDL_NumLogicalCPUCores; 664} 665 666#ifdef __e2k__ 667inline const char * 668SDL_GetCPUType(void) 669{ 670 static char SDL_CPUType[13]; 671 672 SDL_strlcpy(SDL_CPUType, "E2K MACHINE", sizeof(SDL_CPUType)); 673 674 return SDL_CPUType; 675} 676#else 677// Oh, such a sweet sweet trick, just not very useful. :) 678static const char *SDL_GetCPUType(void) 679{ 680 static char SDL_CPUType[13]; 681 682 if (!SDL_CPUType[0]) { 683 int i = 0; 684 685 CPU_calcCPUIDFeatures(); 686 if (CPU_CPUIDMaxFunction > 0) { // do we have CPUID at all? 687 int a, b, c, d; 688 cpuid(0x00000000, a, b, c, d); 689 (void)a; 690 SDL_CPUType[i++] = (char)(b & 0xff); 691 b >>= 8; 692 SDL_CPUType[i++] = (char)(b & 0xff); 693 b >>= 8; 694 SDL_CPUType[i++] = (char)(b & 0xff); 695 b >>= 8; 696 SDL_CPUType[i++] = (char)(b & 0xff); 697 698 SDL_CPUType[i++] = (char)(d & 0xff); 699 d >>= 8; 700 SDL_CPUType[i++] = (char)(d & 0xff); 701 d >>= 8; 702 SDL_CPUType[i++] = (char)(d & 0xff); 703 d >>= 8; 704 SDL_CPUType[i++] = (char)(d & 0xff); 705 706 SDL_CPUType[i++] = (char)(c & 0xff); 707 c >>= 8; 708 SDL_CPUType[i++] = (char)(c & 0xff); 709 c >>= 8; 710 SDL_CPUType[i++] = (char)(c & 0xff); 711 c >>= 8; 712 SDL_CPUType[i++] = (char)(c & 0xff); 713 } 714 if (!SDL_CPUType[0]) { 715 SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType)); 716 } 717 } 718 return SDL_CPUType; 719} 720#endif 721 722#if 0 723!!! FIXME: Not used at the moment. */ 724#ifdef __e2k__ 725inline const char * 726SDL_GetCPUName(void) 727{ 728 static char SDL_CPUName[48]; 729 730 SDL_strlcpy(SDL_CPUName, __builtin_cpu_name(), sizeof(SDL_CPUName)); 731 732 return SDL_CPUName; 733} 734#else 735static const char *SDL_GetCPUName(void) 736{ 737 static char SDL_CPUName[48]; 738 739 if (!SDL_CPUName[0]) { 740 int i = 0; 741 int a, b, c, d; 742 743 CPU_calcCPUIDFeatures(); 744 if (CPU_CPUIDMaxFunction > 0) { // do we have CPUID at all? 745 cpuid(0x80000000, a, b, c, d); 746 if (a >= 0x80000004) { 747 cpuid(0x80000002, a, b, c, d); 748 SDL_CPUName[i++] = (char)(a & 0xff); 749 a >>= 8; 750 SDL_CPUName[i++] = (char)(a & 0xff); 751 a >>= 8; 752 SDL_CPUName[i++] = (char)(a & 0xff); 753 a >>= 8; 754 SDL_CPUName[i++] = (char)(a & 0xff); 755 a >>= 8; 756 SDL_CPUName[i++] = (char)(b & 0xff); 757 b >>= 8; 758 SDL_CPUName[i++] = (char)(b & 0xff); 759 b >>= 8; 760 SDL_CPUName[i++] = (char)(b & 0xff); 761 b >>= 8; 762 SDL_CPUName[i++] = (char)(b & 0xff); 763 b >>= 8; 764 SDL_CPUName[i++] = (char)(c & 0xff); 765 c >>= 8; 766 SDL_CPUName[i++] = (char)(c & 0xff); 767 c >>= 8; 768 SDL_CPUName[i++] = (char)(c & 0xff); 769 c >>= 8; 770 SDL_CPUName[i++] = (char)(c & 0xff); 771 c >>= 8; 772 SDL_CPUName[i++] = (char)(d & 0xff); 773 d >>= 8; 774 SDL_CPUName[i++] = (char)(d & 0xff); 775 d >>= 8; 776 SDL_CPUName[i++] = (char)(d & 0xff); 777 d >>= 8; 778 SDL_CPUName[i++] = (char)(d & 0xff); 779 d >>= 8; 780 cpuid(0x80000003, a, b, c, d); 781 SDL_CPUName[i++] = (char)(a & 0xff); 782 a >>= 8; 783 SDL_CPUName[i++] = (char)(a & 0xff); 784 a >>= 8; 785 SDL_CPUName[i++] = (char)(a & 0xff); 786 a >>= 8; 787 SDL_CPUName[i++] = (char)(a & 0xff); 788 a >>= 8; 789 SDL_CPUName[i++] = (char)(b & 0xff); 790 b >>= 8; 791 SDL_CPUName[i++] = (char)(b & 0xff); 792 b >>= 8; 793 SDL_CPUName[i++] = (char)(b & 0xff); 794 b >>= 8; 795 SDL_CPUName[i++] = (char)(b & 0xff); 796 b >>= 8; 797 SDL_CPUName[i++] = (char)(c & 0xff); 798 c >>= 8; 799 SDL_CPUName[i++] = (char)(c & 0xff); 800 c >>= 8; 801 SDL_CPUName[i++] = (char)(c & 0xff); 802 c >>= 8; 803 SDL_CPUName[i++] = (char)(c & 0xff); 804 c >>= 8; 805 SDL_CPUName[i++] = (char)(d & 0xff); 806 d >>= 8; 807 SDL_CPUName[i++] = (char)(d & 0xff); 808 d >>= 8; 809 SDL_CPUName[i++] = (char)(d & 0xff); 810 d >>= 8; 811 SDL_CPUName[i++] = (char)(d & 0xff); 812 d >>= 8; 813 cpuid(0x80000004, a, b, c, d); 814 SDL_CPUName[i++] = (char)(a & 0xff); 815 a >>= 8; 816 SDL_CPUName[i++] = (char)(a & 0xff); 817 a >>= 8; 818 SDL_CPUName[i++] = (char)(a & 0xff); 819 a >>= 8; 820 SDL_CPUName[i++] = (char)(a & 0xff); 821 a >>= 8; 822 SDL_CPUName[i++] = (char)(b & 0xff); 823 b >>= 8; 824 SDL_CPUName[i++] = (char)(b & 0xff); 825 b >>= 8; 826 SDL_CPUName[i++] = (char)(b & 0xff); 827 b >>= 8; 828 SDL_CPUName[i++] = (char)(b & 0xff); 829 b >>= 8; 830 SDL_CPUName[i++] = (char)(c & 0xff); 831 c >>= 8; 832 SDL_CPUName[i++] = (char)(c & 0xff); 833 c >>= 8; 834 SDL_CPUName[i++] = (char)(c & 0xff); 835 c >>= 8; 836 SDL_CPUName[i++] = (char)(c & 0xff); 837 c >>= 8; 838 SDL_CPUName[i++] = (char)(d & 0xff); 839 d >>= 8; 840 SDL_CPUName[i++] = (char)(d & 0xff); 841 d >>= 8; 842 SDL_CPUName[i++] = (char)(d & 0xff); 843 d >>= 8; 844 SDL_CPUName[i++] = (char)(d & 0xff); 845 d >>= 8; 846 } 847 } 848 if (!SDL_CPUName[0]) { 849 SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName)); 850 } 851 } 852 return SDL_CPUName; 853} 854#endif 855#endif 856 857int SDL_GetCPUCacheLineSize(void) 858{ 859 const char *cpuType = SDL_GetCPUType(); 860 int cacheline_size = SDL_CACHELINE_SIZE; // initial guess 861 int a, b, c, d; 862 (void)a; 863 (void)b; 864 (void)c; 865 (void)d; 866 if (SDL_strcmp(cpuType, "GenuineIntel") == 0 || SDL_strcmp(cpuType, "CentaurHauls") == 0 || SDL_strcmp(cpuType, " Shanghai ") == 0) { 867 cpuid(0x00000001, a, b, c, d); 868 cacheline_size = ((b >> 8) & 0xff) * 8; 869 } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0 || SDL_strcmp(cpuType, "HygonGenuine") == 0) { 870 cpuid(0x80000005, a, b, c, d); 871 cacheline_size = c & 0xff; 872 } else { 873#if defined(HAVE_SYSCONF) && defined(_SC_LEVEL1_DCACHE_LINESIZE) 874 if ((cacheline_size = (int)sysconf(_SC_LEVEL1_DCACHE_LINESIZE)) > 0) { 875 return cacheline_size; 876 } else { 877 cacheline_size = SDL_CACHELINE_SIZE; 878 } 879#endif 880#if defined(SDL_PLATFORM_LINUX) 881 { 882 FILE *f = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r"); 883 if (f) { 884 int size; 885 if (fscanf(f, "%d", &size) == 1) { 886 cacheline_size = size; 887 } 888 fclose(f); 889 } 890 } 891#elif defined(__FREEBSD__) && defined(CACHE_LINE_SIZE) 892 cacheline_size = CACHE_LINE_SIZE; 893#endif 894 } 895 return cacheline_size; 896} 897 898#define SDL_CPUFEATURES_RESET_VALUE 0xFFFFFFFF 899 900static Uint32 SDL_CPUFeatures = SDL_CPUFEATURES_RESET_VALUE; 901static Uint32 SDL_SIMDAlignment = 0xFFFFFFFF; 902 903static bool ref_string_equals(const char *ref, const char *test, const char *end_test) { 904 size_t len_test = end_test - test; 905 return SDL_strncmp(ref, test, len_test) == 0 && ref[len_test] == '\0' && (test[len_test] == '\0' || test[len_test] == ','); 906} 907 908static Uint32 SDLCALL SDL_CPUFeatureMaskFromHint(void) 909{ 910 Uint32 result_mask = SDL_CPUFEATURES_RESET_VALUE; 911 912 const char *hint = SDL_GetHint(SDL_HINT_CPU_FEATURE_MASK); 913 914 if (hint) { 915 for (const char *spot = hint, *next; *spot; spot = next) { 916 const char *end = SDL_strchr(spot, ','); 917 Uint32 spot_mask; 918 bool add_spot_mask = true; 919 if (end) { 920 next = end + 1; 921 } else { 922 size_t len = SDL_strlen(spot); 923 end = spot + len; 924 next = end; 925 } 926 if (spot[0] == '+') { 927 add_spot_mask = true; 928 spot += 1; 929 } else if (spot[0] == '-') { 930 add_spot_mask = false; 931 spot += 1; 932 } 933 if (ref_string_equals("all", spot, end)) { 934 spot_mask = SDL_CPUFEATURES_RESET_VALUE; 935 } else if (ref_string_equals("altivec", spot, end)) { 936 spot_mask= CPU_HAS_ALTIVEC; 937 } else if (ref_string_equals("mmx", spot, end)) { 938 spot_mask = CPU_HAS_MMX; 939 } else if (ref_string_equals("sse", spot, end)) { 940 spot_mask = CPU_HAS_SSE; 941 } else if (ref_string_equals("sse2", spot, end)) { 942 spot_mask = CPU_HAS_SSE2; 943 } else if (ref_string_equals("sse3", spot, end)) { 944 spot_mask = CPU_HAS_SSE3; 945 } else if (ref_string_equals("sse41", spot, end)) { 946 spot_mask = CPU_HAS_SSE41; 947 } else if (ref_string_equals("sse42", spot, end)) { 948 spot_mask = CPU_HAS_SSE42; 949 } else if (ref_string_equals("avx", spot, end)) { 950 spot_mask = CPU_HAS_AVX; 951 } else if (ref_string_equals("avx2", spot, end)) { 952 spot_mask = CPU_HAS_AVX2; 953 } else if (ref_string_equals("avx512f", spot, end)) { 954 spot_mask = CPU_HAS_AVX512F; 955 } else if (ref_string_equals("arm-simd", spot, end)) { 956 spot_mask = CPU_HAS_ARM_SIMD; 957 } else if (ref_string_equals("neon", spot, end)) { 958 spot_mask = CPU_HAS_NEON; 959 } else if (ref_string_equals("lsx", spot, end)) { 960 spot_mask = CPU_HAS_LSX; 961 } else if (ref_string_equals("lasx", spot, end)) { 962 spot_mask = CPU_HAS_LASX; 963 } else { 964 // Ignore unknown/incorrect cpu feature(s) 965 continue; 966 } 967 if (add_spot_mask) { 968 result_mask |= spot_mask; 969 } else { 970 result_mask &= ~spot_mask; 971 } 972 } 973 } 974 return result_mask; 975} 976 977static Uint32 SDL_GetCPUFeatures(void) 978{ 979 if (SDL_CPUFeatures == SDL_CPUFEATURES_RESET_VALUE) { 980 CPU_calcCPUIDFeatures(); 981 SDL_CPUFeatures = 0; 982 SDL_SIMDAlignment = sizeof(void *); // a good safe base value 983 if (CPU_haveAltiVec()) { 984 SDL_CPUFeatures |= CPU_HAS_ALTIVEC; 985 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); 986 } 987 if (CPU_haveMMX()) { 988 SDL_CPUFeatures |= CPU_HAS_MMX; 989 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 8); 990 } 991 if (CPU_haveSSE()) { 992 SDL_CPUFeatures |= CPU_HAS_SSE; 993 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); 994 } 995 if (CPU_haveSSE2()) { 996 SDL_CPUFeatures |= CPU_HAS_SSE2; 997 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); 998 } 999 if (CPU_haveSSE3()) { 1000 SDL_CPUFeatures |= CPU_HAS_SSE3; 1001 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); 1002 } 1003 if (CPU_haveSSE41()) { 1004 SDL_CPUFeatures |= CPU_HAS_SSE41; 1005 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); 1006 } 1007 if (CPU_haveSSE42()) { 1008 SDL_CPUFeatures |= CPU_HAS_SSE42; 1009 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); 1010 } 1011 if (CPU_haveAVX()) { 1012 SDL_CPUFeatures |= CPU_HAS_AVX; 1013 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 32); 1014 } 1015 if (CPU_haveAVX2()) { 1016 SDL_CPUFeatures |= CPU_HAS_AVX2; 1017 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 32); 1018 } 1019 if (CPU_haveAVX512F()) { 1020 SDL_CPUFeatures |= CPU_HAS_AVX512F; 1021 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 64); 1022 } 1023 if (CPU_haveARMSIMD()) { 1024 SDL_CPUFeatures |= CPU_HAS_ARM_SIMD; 1025 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); 1026 } 1027 if (CPU_haveNEON()) { 1028 SDL_CPUFeatures |= CPU_HAS_NEON; 1029 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); 1030 } 1031 if (CPU_haveLSX()) { 1032 SDL_CPUFeatures |= CPU_HAS_LSX; 1033 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); 1034 } 1035 if (CPU_haveLASX()) { 1036 SDL_CPUFeatures |= CPU_HAS_LASX; 1037 SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 32); 1038 } 1039 SDL_CPUFeatures &= SDL_CPUFeatureMaskFromHint(); 1040 } 1041 return SDL_CPUFeatures; 1042} 1043 1044void SDL_QuitCPUInfo(void) { 1045 SDL_CPUFeatures = SDL_CPUFEATURES_RESET_VALUE; 1046} 1047 1048#define CPU_FEATURE_AVAILABLE(f) ((SDL_GetCPUFeatures() & (f)) ? true : false) 1049 1050bool SDL_HasAltiVec(void) 1051{ 1052 return CPU_FEATURE_AVAILABLE(CPU_HAS_ALTIVEC); 1053} 1054 1055bool SDL_HasMMX(void) 1056{ 1057 return CPU_FEATURE_AVAILABLE(CPU_HAS_MMX); 1058} 1059 1060bool SDL_HasSSE(void) 1061{ 1062 return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE); 1063} 1064 1065bool SDL_HasSSE2(void) 1066{ 1067 return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE2); 1068} 1069 1070bool SDL_HasSSE3(void) 1071{ 1072 return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE3); 1073} 1074 1075bool SDL_HasSSE41(void) 1076{ 1077 return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE41); 1078} 1079 1080bool SDL_HasSSE42(void) 1081{ 1082 return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE42); 1083} 1084 1085bool SDL_HasAVX(void) 1086{ 1087 return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX); 1088} 1089 1090bool SDL_HasAVX2(void) 1091{ 1092 return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX2); 1093} 1094 1095bool SDL_HasAVX512F(void) 1096{ 1097 return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX512F); 1098} 1099 1100bool SDL_HasARMSIMD(void) 1101{ 1102 return CPU_FEATURE_AVAILABLE(CPU_HAS_ARM_SIMD); 1103} 1104 1105bool SDL_HasNEON(void) 1106{ 1107 return CPU_FEATURE_AVAILABLE(CPU_HAS_NEON); 1108} 1109 1110bool SDL_HasLSX(void) 1111{ 1112 return CPU_FEATURE_AVAILABLE(CPU_HAS_LSX); 1113} 1114 1115bool SDL_HasLASX(void) 1116{ 1117 return CPU_FEATURE_AVAILABLE(CPU_HAS_LASX); 1118} 1119 1120static int SDL_SystemRAM = 0; 1121 1122int SDL_GetSystemRAM(void) 1123{ 1124 if (!SDL_SystemRAM) { 1125#if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) 1126 if (SDL_SystemRAM <= 0) { 1127 SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024 * 1024)); 1128 } 1129#endif 1130#ifdef HAVE_SYSCTLBYNAME 1131 if (SDL_SystemRAM <= 0) { 1132#ifdef HW_PHYSMEM64 1133 // (64-bit): NetBSD since 2003, OpenBSD 1134 int mib[2] = { CTL_HW, HW_PHYSMEM64 }; 1135#elif defined(HW_REALMEM) 1136 // (64-bit): FreeBSD since 2005, DragonFly 1137 int mib[2] = { CTL_HW, HW_REALMEM }; 1138#elif defined(HW_MEMSIZE) 1139 // (64-bit): Darwin 1140 int mib[2] = { CTL_HW, HW_MEMSIZE }; 1141#else 1142 // (32-bit): very old BSD, might only report up to 2 GiB 1143 int mib[2] = { CTL_HW, HW_PHYSMEM }; 1144#endif // HW_PHYSMEM64 1145 Uint64 memsize = 0; 1146 size_t len = sizeof(memsize); 1147 1148 if (sysctl(mib, 2, &memsize, &len, NULL, 0) == 0) { 1149 SDL_SystemRAM = (int)(memsize / (1024 * 1024)); 1150 } 1151 } 1152#endif 1153#if defined(SDL_PLATFORM_WINDOWS) 1154 if (SDL_SystemRAM <= 0) { 1155 MEMORYSTATUSEX stat; 1156 stat.dwLength = sizeof(stat); 1157 if (GlobalMemoryStatusEx(&stat)) { 1158 SDL_SystemRAM = (int)(stat.ullTotalPhys / (1024 * 1024)); 1159 } 1160 } 1161#endif 1162#ifdef SDL_PLATFORM_RISCOS 1163 if (SDL_SystemRAM <= 0) { 1164 _kernel_swi_regs regs; 1165 regs.r[0] = 0x108; 1166 if (_kernel_swi(OS_Memory, &regs, &regs) == NULL) { 1167 SDL_SystemRAM = (int)(regs.r[1] * regs.r[2] / (1024 * 1024)); 1168 } 1169 } 1170#endif 1171#ifdef SDL_PLATFORM_3DS 1172 if (SDL_SystemRAM <= 0) { 1173 // The New3DS has 255MiB, the Old3DS 127MiB 1174 SDL_SystemRAM = (int)(osGetMemRegionSize(MEMREGION_ALL) / (1024 * 1024)); 1175 } 1176#endif 1177#ifdef SDL_PLATFORM_VITA 1178 if (SDL_SystemRAM <= 0) { 1179 /* Vita has 512MiB on SoC, that's split into 256MiB(+109MiB in extended memory mode) for app 1180 +26MiB of physically continuous memory, +112MiB of CDRAM(VRAM) + system reserved memory. */ 1181 SDL_SystemRAM = 536870912; 1182 } 1183#endif 1184#ifdef SDL_PLATFORM_PS2 1185 if (SDL_SystemRAM <= 0) { 1186 // PlayStation 2 has 32MiB however there are some special models with 64 and 128 1187 SDL_SystemRAM = GetMemorySize(); 1188 } 1189#endif 1190#ifdef SDL_PLATFORM_HAIKU 1191 if (SDL_SystemRAM <= 0) { 1192 system_info info; 1193 if (get_system_info(&info) == B_OK) { 1194 /* To have an accurate amount, we also take in account the inaccessible pages (aka ignored) 1195 which is a bit handier compared to the legacy system's api (i.e. used_pages).*/ 1196 SDL_SystemRAM = (int)SDL_round((info.max_pages + info.ignored_pages > 0 ? info.ignored_pages : 0) * B_PAGE_SIZE / 1048576.0); 1197 } 1198 } 1199#endif 1200 } 1201 return SDL_SystemRAM; 1202} 1203 1204 1205static int SDL_SystemPageSize = -1; 1206 1207int SDL_GetSystemPageSize(void) 1208{ 1209 if (SDL_SystemPageSize == -1) { 1210#ifdef SDL_PLATFORM_SYSTEM_PAGE_SIZE_PRIVATE // consoles will define this in a platform-specific internal header. 1211 SDL_SystemPageSize = SDL_PLATFORM_SYSTEM_PAGE_SIZE_PRIVATE; 1212#endif 1213#ifdef SDL_PLATFORM_3DS 1214 SDL_SystemPageSize = 4096; // It's an ARM11 CPU; I assume this is 4K. 1215#endif 1216#ifdef SDL_PLATFORM_VITA 1217 SDL_SystemPageSize = 4096; // It's an ARMv7 CPU; I assume this is 4K. 1218#endif 1219#ifdef SDL_PLATFORM_PS2 1220 SDL_SystemPageSize = 4096; // It's a MIPS R5900 CPU; I assume this is 4K. 1221#endif 1222#if defined(HAVE_SYSCONF) && (defined(_SC_PAGESIZE) || defined(_SC_PAGE_SIZE)) 1223 if (SDL_SystemPageSize <= 0) { 1224 #if defined(_SC_PAGE_SIZE) 1225 SDL_SystemPageSize = (int)sysconf(_SC_PAGE_SIZE); 1226 #else 1227 SDL_SystemPageSize = (int)sysconf(_SC_PAGESIZE); 1228 #endif 1229 } 1230#endif 1231#if defined(HAVE_SYSCTLBYNAME) && defined(HW_PAGESIZE) 1232 if (SDL_SystemPageSize <= 0) { 1233 // NetBSD, OpenBSD, FreeBSD, Darwin...everything agrees to use HW_PAGESIZE. 1234 int mib[2] = { CTL_HW, HW_PAGESIZE }; 1235 int pagesize = 0; 1236 size_t len = sizeof(pagesize); 1237 1238 if (sysctl(mib, 2, &pagesize, &len, NULL, 0) == 0) { 1239 SDL_SystemPageSize = pagesize; 1240 } 1241 } 1242#endif 1243#ifdef USE_GETPAGESIZE 1244 if (SDL_SystemPageSize <= 0) { 1245 SDL_SystemPageSize = getpagesize(); 1246 } 1247#endif 1248#if defined(SDL_PLATFORM_WINDOWS) 1249 if (SDL_SystemPageSize <= 0) { 1250 SYSTEM_INFO sysinfo; 1251 GetSystemInfo(&sysinfo); 1252 SDL_SystemPageSize = (int) sysinfo.dwPageSize; 1253 } 1254#endif 1255 if (SDL_SystemPageSize < 0) { // in case we got a weird result somewhere, or no better information, force it to 0. 1256 SDL_SystemPageSize = 0; // unknown page size, sorry. 1257 } 1258 } 1259 return SDL_SystemPageSize; 1260} 1261 1262 1263size_t SDL_GetSIMDAlignment(void) 1264{ 1265 if (SDL_SIMDAlignment == 0xFFFFFFFF) { 1266 SDL_GetCPUFeatures(); // make sure this has been calculated 1267 } 1268 SDL_assert(SDL_SIMDAlignment != 0); 1269 return SDL_SIMDAlignment; 1270} 1271
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.