SDL_cpuinfo.c (22326B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 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#ifdef TEST_MAIN 22#include "SDL_config.h" 23#else 24#include "../SDL_internal.h" 25#endif 26 27#if defined(__WIN32__) 28#include "../core/windows/SDL_windows.h" 29#endif 30 31/* CPU feature detection for SDL */ 32 33#include "SDL_cpuinfo.h" 34 35#ifdef HAVE_SYSCONF 36#include <unistd.h> 37#endif 38#ifdef HAVE_SYSCTLBYNAME 39#include <sys/types.h> 40#include <sys/sysctl.h> 41#endif 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 49#include <signal.h> 50#include <setjmp.h> 51#endif 52 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 64 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! 68 */ 69static jmp_buf jmpbuf; 70static void 71illegal_instruction(int sig) 72{ 73 longjmp(jmpbuf, 1); 74} 75#endif /* HAVE_SETJMP */ 76 77static int 78CPU_haveCPUID(void) 79{ 80 int has_CPUID = 0; 81/* *INDENT-OFF* */ 82#if defined(__GNUC__) && defined(i386) 83 __asm__ ( 84" pushfl # Get original EFLAGS \n" 85" popl %%eax \n" 86" movl %%eax,%%ecx \n" 87" xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" 88" pushl %%eax # Save new EFLAGS value on stack \n" 89" popfl # Replace current EFLAGS value \n" 90" pushfl # Get new EFLAGS \n" 91" popl %%eax # Store new EFLAGS in EAX \n" 92" xorl %%ecx,%%eax # Can not toggle ID bit, \n" 93" jz 1f # Processor=80486 \n" 94" movl $1,%0 # We have CPUID support \n" 95"1: \n" 96 : "=m" (has_CPUID) 97 : 98 : "%eax", "%ecx" 99 ); 100#elif defined(__GNUC__) && defined(__x86_64__) 101/* Technically, if this is being compiled under __x86_64__ then it has 102 CPUid by definition. But it's nice to be able to prove it. :) */ 103 __asm__ ( 104" pushfq # Get original EFLAGS \n" 105" popq %%rax \n" 106" movq %%rax,%%rcx \n" 107" xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" 108" pushq %%rax # Save new EFLAGS value on stack \n" 109" popfq # Replace current EFLAGS value \n" 110" pushfq # Get new EFLAGS \n" 111" popq %%rax # Store new EFLAGS in EAX \n" 112" xorl %%ecx,%%eax # Can not toggle ID bit, \n" 113" jz 1f # Processor=80486 \n" 114" movl $1,%0 # We have CPUID support \n" 115"1: \n" 116 : "=m" (has_CPUID) 117 : 118 : "%rax", "%rcx" 119 ); 120#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 121 __asm { 122 pushfd ; Get original EFLAGS 123 pop eax 124 mov ecx, eax 125 xor eax, 200000h ; Flip ID bit in EFLAGS 126 push eax ; Save new EFLAGS value on stack 127 popfd ; Replace current EFLAGS value 128 pushfd ; Get new EFLAGS 129 pop eax ; Store new EFLAGS in EAX 130 xor eax, ecx ; Can not toggle ID bit, 131 jz done ; Processor=80486 132 mov has_CPUID,1 ; We have CPUID support 133done: 134 } 135#elif defined(_MSC_VER) && defined(_M_X64) 136 has_CPUID = 1; 137#elif defined(__sun) && defined(__i386) 138 __asm ( 139" pushfl \n" 140" popl %eax \n" 141" movl %eax,%ecx \n" 142" xorl $0x200000,%eax \n" 143" pushl %eax \n" 144" popfl \n" 145" pushfl \n" 146" popl %eax \n" 147" xorl %ecx,%eax \n" 148" jz 1f \n" 149" movl $1,-8(%ebp) \n" 150"1: \n" 151 ); 152#elif defined(__sun) && defined(__amd64) 153 __asm ( 154" pushfq \n" 155" popq %rax \n" 156" movq %rax,%rcx \n" 157" xorl $0x200000,%eax \n" 158" pushq %rax \n" 159" popfq \n" 160" pushfq \n" 161" popq %rax \n" 162" xorl %ecx,%eax \n" 163" jz 1f \n" 164" movl $1,-8(%rbp) \n" 165"1: \n" 166 ); 167#endif 168/* *INDENT-ON* */ 169 return has_CPUID; 170} 171 172#if defined(__GNUC__) && defined(i386) 173#define cpuid(func, a, b, c, d) \ 174 __asm__ __volatile__ ( \ 175" pushl %%ebx \n" \ 176" xorl %%ecx,%%ecx \n" \ 177" cpuid \n" \ 178" movl %%ebx, %%esi \n" \ 179" popl %%ebx \n" : \ 180 "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func)) 181#elif defined(__GNUC__) && defined(__x86_64__) 182#define cpuid(func, a, b, c, d) \ 183 __asm__ __volatile__ ( \ 184" pushq %%rbx \n" \ 185" xorq %%rcx,%%rcx \n" \ 186" cpuid \n" \ 187" movq %%rbx, %%rsi \n" \ 188" popq %%rbx \n" : \ 189 "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func)) 190#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 191#define cpuid(func, a, b, c, d) \ 192 __asm { \ 193 __asm mov eax, func \ 194 __asm xor ecx, ecx \ 195 __asm cpuid \ 196 __asm mov a, eax \ 197 __asm mov b, ebx \ 198 __asm mov c, ecx \ 199 __asm mov d, edx \ 200} 201#elif defined(_MSC_VER) && defined(_M_X64) 202#define cpuid(func, a, b, c, d) \ 203{ \ 204 int CPUInfo[4]; \ 205 __cpuid(CPUInfo, func); \ 206 a = CPUInfo[0]; \ 207 b = CPUInfo[1]; \ 208 c = CPUInfo[2]; \ 209 d = CPUInfo[3]; \ 210} 211#else 212#define cpuid(func, a, b, c, d) \ 213 a = b = c = d = 0 214#endif 215 216static int 217CPU_getCPUIDFeatures(void) 218{ 219 int features = 0; 220 int a, b, c, d; 221 222 cpuid(0, a, b, c, d); 223 if (a >= 1) { 224 cpuid(1, a, b, c, d); 225 features = d; 226 } 227 return features; 228} 229 230static SDL_bool 231CPU_OSSavesYMM(void) 232{ 233 int a, b, c, d; 234 235 /* Check to make sure we can call xgetbv */ 236 cpuid(0, a, b, c, d); 237 if (a < 1) { 238 return SDL_FALSE; 239 } 240 cpuid(1, a, b, c, d); 241 if (!(c & 0x08000000)) { 242 return SDL_FALSE; 243 } 244 245 /* Call xgetbv to see if YMM register state is saved */ 246 a = 0; 247#if defined(__GNUC__) && (defined(i386) || defined(__x86_64__)) 248 asm(".byte 0x0f, 0x01, 0xd0" : "=a" (a) : "c" (0) : "%edx"); 249#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) /* VS2010 SP1 */ 250 a = (int)_xgetbv(0); 251#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 252 __asm 253 { 254 xor ecx, ecx 255 _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0 256 mov a, eax 257 } 258#endif 259 return ((a & 6) == 6) ? SDL_TRUE : SDL_FALSE; 260} 261 262static int 263CPU_haveRDTSC(void) 264{ 265 if (CPU_haveCPUID()) { 266 return (CPU_getCPUIDFeatures() & 0x00000010); 267 } 268 return 0; 269} 270 271static int 272CPU_haveAltiVec(void) 273{ 274 volatile int altivec = 0; 275#if (defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__)) 276#ifdef __OpenBSD__ 277 int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC }; 278#else 279 int selectors[2] = { CTL_HW, HW_VECTORUNIT }; 280#endif 281 int hasVectorUnit = 0; 282 size_t length = sizeof(hasVectorUnit); 283 int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0); 284 if (0 == error) 285 altivec = (hasVectorUnit != 0); 286#elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP 287 void (*handler) (int sig); 288 handler = signal(SIGILL, illegal_instruction); 289 if (setjmp(jmpbuf) == 0) { 290 asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1)); 291 altivec = 1; 292 } 293 signal(SIGILL, handler); 294#endif 295 return altivec; 296} 297 298static int 299CPU_haveMMX(void) 300{ 301 if (CPU_haveCPUID()) { 302 return (CPU_getCPUIDFeatures() & 0x00800000); 303 } 304 return 0; 305} 306 307static int 308CPU_have3DNow(void) 309{ 310 if (CPU_haveCPUID()) { 311 int a, b, c, d; 312 313 cpuid(0x80000000, a, b, c, d); 314 if (a >= 0x80000001) { 315 cpuid(0x80000001, a, b, c, d); 316 return (d & 0x80000000); 317 } 318 } 319 return 0; 320} 321 322static int 323CPU_haveSSE(void) 324{ 325 if (CPU_haveCPUID()) { 326 return (CPU_getCPUIDFeatures() & 0x02000000); 327 } 328 return 0; 329} 330 331static int 332CPU_haveSSE2(void) 333{ 334 if (CPU_haveCPUID()) { 335 return (CPU_getCPUIDFeatures() & 0x04000000); 336 } 337 return 0; 338} 339 340static int 341CPU_haveSSE3(void) 342{ 343 if (CPU_haveCPUID()) { 344 int a, b, c, d; 345 346 cpuid(0, a, b, c, d); 347 if (a >= 1) { 348 cpuid(1, a, b, c, d); 349 return (c & 0x00000001); 350 } 351 } 352 return 0; 353} 354 355static int 356CPU_haveSSE41(void) 357{ 358 if (CPU_haveCPUID()) { 359 int a, b, c, d; 360 361 cpuid(0, a, b, c, d); 362 if (a >= 1) { 363 cpuid(1, a, b, c, d); 364 return (c & 0x00080000); 365 } 366 } 367 return 0; 368} 369 370static int 371CPU_haveSSE42(void) 372{ 373 if (CPU_haveCPUID()) { 374 int a, b, c, d; 375 376 cpuid(0, a, b, c, d); 377 if (a >= 1) { 378 cpuid(1, a, b, c, d); 379 return (c & 0x00100000); 380 } 381 } 382 return 0; 383} 384 385static int 386CPU_haveAVX(void) 387{ 388 if (CPU_haveCPUID() && CPU_OSSavesYMM()) { 389 int a, b, c, d; 390 391 cpuid(0, a, b, c, d); 392 if (a >= 1) { 393 cpuid(1, a, b, c, d); 394 return (c & 0x10000000); 395 } 396 } 397 return 0; 398} 399 400static int 401CPU_haveAVX2(void) 402{ 403 if (CPU_haveCPUID() && CPU_OSSavesYMM()) { 404 int a, b, c, d; 405 406 cpuid(0, a, b, c, d); 407 if (a >= 7) { 408 cpuid(7, a, b, c, d); 409 return (b & 0x00000020); 410 } 411 } 412 return 0; 413} 414 415static int SDL_CPUCount = 0; 416 417int 418SDL_GetCPUCount(void) 419{ 420 if (!SDL_CPUCount) { 421#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) 422 if (SDL_CPUCount <= 0) { 423 SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN); 424 } 425#endif 426#ifdef HAVE_SYSCTLBYNAME 427 if (SDL_CPUCount <= 0) { 428 size_t size = sizeof(SDL_CPUCount); 429 sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0); 430 } 431#endif 432#ifdef __WIN32__ 433 if (SDL_CPUCount <= 0) { 434 SYSTEM_INFO info; 435 GetSystemInfo(&info); 436 SDL_CPUCount = info.dwNumberOfProcessors; 437 } 438#endif 439 /* There has to be at least 1, right? :) */ 440 if (SDL_CPUCount <= 0) { 441 SDL_CPUCount = 1; 442 } 443 } 444 return SDL_CPUCount; 445} 446 447/* Oh, such a sweet sweet trick, just not very useful. :) */ 448static const char * 449SDL_GetCPUType(void) 450{ 451 static char SDL_CPUType[13]; 452 453 if (!SDL_CPUType[0]) { 454 int i = 0; 455 int a, b, c, d; 456 457 if (CPU_haveCPUID()) { 458 cpuid(0x00000000, a, b, c, d); 459 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; 460 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; 461 SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; 462 SDL_CPUType[i++] = (char)(b & 0xff); 463 464 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; 465 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; 466 SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; 467 SDL_CPUType[i++] = (char)(d & 0xff); 468 469 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; 470 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; 471 SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; 472 SDL_CPUType[i++] = (char)(c & 0xff); 473 } 474 if (!SDL_CPUType[0]) { 475 SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType)); 476 } 477 } 478 return SDL_CPUType; 479} 480 481 482#ifdef TEST_MAIN /* !!! FIXME: only used for test at the moment. */ 483static const char * 484SDL_GetCPUName(void) 485{ 486 static char SDL_CPUName[48]; 487 488 if (!SDL_CPUName[0]) { 489 int i = 0; 490 int a, b, c, d; 491 492 if (CPU_haveCPUID()) { 493 cpuid(0x80000000, a, b, c, d); 494 if (a >= 0x80000004) { 495 cpuid(0x80000002, a, b, c, d); 496 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 497 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 498 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 499 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 500 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 501 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 502 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 503 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 504 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 505 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 506 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 507 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 508 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 509 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 510 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 511 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 512 cpuid(0x80000003, a, b, c, d); 513 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 514 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 515 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 516 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 517 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 518 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 519 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 520 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 521 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 522 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 523 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 524 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 525 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 526 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 527 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 528 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 529 cpuid(0x80000004, a, b, c, d); 530 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 531 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 532 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 533 SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; 534 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 535 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 536 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 537 SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; 538 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 539 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 540 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 541 SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; 542 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 543 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 544 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 545 SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; 546 } 547 } 548 if (!SDL_CPUName[0]) { 549 SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName)); 550 } 551 } 552 return SDL_CPUName; 553} 554#endif 555 556int 557SDL_GetCPUCacheLineSize(void) 558{ 559 const char *cpuType = SDL_GetCPUType(); 560 561 if (SDL_strcmp(cpuType, "GenuineIntel") == 0) { 562 int a, b, c, d; 563 564 cpuid(0x00000001, a, b, c, d); 565 return (((b >> 8) & 0xff) * 8); 566 } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) { 567 int a, b, c, d; 568 569 cpuid(0x80000005, a, b, c, d); 570 return (c & 0xff); 571 } else { 572 /* Just make a guess here... */ 573 return SDL_CACHELINE_SIZE; 574 } 575} 576 577static Uint32 SDL_CPUFeatures = 0xFFFFFFFF; 578 579static Uint32 580SDL_GetCPUFeatures(void) 581{ 582 if (SDL_CPUFeatures == 0xFFFFFFFF) { 583 SDL_CPUFeatures = 0; 584 if (CPU_haveRDTSC()) { 585 SDL_CPUFeatures |= CPU_HAS_RDTSC; 586 } 587 if (CPU_haveAltiVec()) { 588 SDL_CPUFeatures |= CPU_HAS_ALTIVEC; 589 } 590 if (CPU_haveMMX()) { 591 SDL_CPUFeatures |= CPU_HAS_MMX; 592 } 593 if (CPU_have3DNow()) { 594 SDL_CPUFeatures |= CPU_HAS_3DNOW; 595 } 596 if (CPU_haveSSE()) { 597 SDL_CPUFeatures |= CPU_HAS_SSE; 598 } 599 if (CPU_haveSSE2()) { 600 SDL_CPUFeatures |= CPU_HAS_SSE2; 601 } 602 if (CPU_haveSSE3()) { 603 SDL_CPUFeatures |= CPU_HAS_SSE3; 604 } 605 if (CPU_haveSSE41()) { 606 SDL_CPUFeatures |= CPU_HAS_SSE41; 607 } 608 if (CPU_haveSSE42()) { 609 SDL_CPUFeatures |= CPU_HAS_SSE42; 610 } 611 if (CPU_haveAVX()) { 612 SDL_CPUFeatures |= CPU_HAS_AVX; 613 } 614 if (CPU_haveAVX2()) { 615 SDL_CPUFeatures |= CPU_HAS_AVX2; 616 } 617 } 618 return SDL_CPUFeatures; 619} 620 621SDL_bool 622SDL_HasRDTSC(void) 623{ 624 if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) { 625 return SDL_TRUE; 626 } 627 return SDL_FALSE; 628} 629 630SDL_bool 631SDL_HasAltiVec(void) 632{ 633 if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) { 634 return SDL_TRUE; 635 } 636 return SDL_FALSE; 637} 638 639SDL_bool 640SDL_HasMMX(void) 641{ 642 if (SDL_GetCPUFeatures() & CPU_HAS_MMX) { 643 return SDL_TRUE; 644 } 645 return SDL_FALSE; 646} 647 648SDL_bool 649SDL_Has3DNow(void) 650{ 651 if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) { 652 return SDL_TRUE; 653 } 654 return SDL_FALSE; 655} 656 657SDL_bool 658SDL_HasSSE(void) 659{ 660 if (SDL_GetCPUFeatures() & CPU_HAS_SSE) { 661 return SDL_TRUE; 662 } 663 return SDL_FALSE; 664} 665 666SDL_bool 667SDL_HasSSE2(void) 668{ 669 if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) { 670 return SDL_TRUE; 671 } 672 return SDL_FALSE; 673} 674 675SDL_bool 676SDL_HasSSE3(void) 677{ 678 if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) { 679 return SDL_TRUE; 680 } 681 return SDL_FALSE; 682} 683 684SDL_bool 685SDL_HasSSE41(void) 686{ 687 if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) { 688 return SDL_TRUE; 689 } 690 return SDL_FALSE; 691} 692 693SDL_bool 694SDL_HasSSE42(void) 695{ 696 if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) { 697 return SDL_TRUE; 698 } 699 return SDL_FALSE; 700} 701 702SDL_bool 703SDL_HasAVX(void) 704{ 705 if (SDL_GetCPUFeatures() & CPU_HAS_AVX) { 706 return SDL_TRUE; 707 } 708 return SDL_FALSE; 709} 710 711SDL_bool 712SDL_HasAVX2(void) 713{ 714 if (SDL_GetCPUFeatures() & CPU_HAS_AVX2) { 715 return SDL_TRUE; 716 } 717 return SDL_FALSE; 718} 719 720static int SDL_SystemRAM = 0; 721 722int 723SDL_GetSystemRAM(void) 724{ 725 if (!SDL_SystemRAM) { 726#if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) 727 if (SDL_SystemRAM <= 0) { 728 SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024)); 729 } 730#endif 731#ifdef HAVE_SYSCTLBYNAME 732 if (SDL_SystemRAM <= 0) { 733#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 734#ifdef HW_REALMEM 735 int mib[2] = {CTL_HW, HW_REALMEM}; 736#else 737 /* might only report up to 2 GiB */ 738 int mib[2] = {CTL_HW, HW_PHYSMEM}; 739#endif /* HW_REALMEM */ 740#else 741 int mib[2] = {CTL_HW, HW_MEMSIZE}; 742#endif /* __FreeBSD__ || __FreeBSD_kernel__ */ 743 Uint64 memsize = 0; 744 size_t len = sizeof(memsize); 745 746 if (sysctl(mib, 2, &memsize, &len, NULL, 0) == 0) { 747 SDL_SystemRAM = (int)(memsize / (1024*1024)); 748 } 749 } 750#endif 751#ifdef __WIN32__ 752 if (SDL_SystemRAM <= 0) { 753 MEMORYSTATUSEX stat; 754 stat.dwLength = sizeof(stat); 755 if (GlobalMemoryStatusEx(&stat)) { 756 SDL_SystemRAM = (int)(stat.ullTotalPhys / (1024 * 1024)); 757 } 758 } 759#endif 760 } 761 return SDL_SystemRAM; 762} 763 764 765#ifdef TEST_MAIN 766 767#include <stdio.h> 768 769int 770main() 771{ 772 printf("CPU count: %d\n", SDL_GetCPUCount()); 773 printf("CPU type: %s\n", SDL_GetCPUType()); 774 printf("CPU name: %s\n", SDL_GetCPUName()); 775 printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize()); 776 printf("RDTSC: %d\n", SDL_HasRDTSC()); 777 printf("Altivec: %d\n", SDL_HasAltiVec()); 778 printf("MMX: %d\n", SDL_HasMMX()); 779 printf("3DNow: %d\n", SDL_Has3DNow()); 780 printf("SSE: %d\n", SDL_HasSSE()); 781 printf("SSE2: %d\n", SDL_HasSSE2()); 782 printf("SSE3: %d\n", SDL_HasSSE3()); 783 printf("SSE4.1: %d\n", SDL_HasSSE41()); 784 printf("SSE4.2: %d\n", SDL_HasSSE42()); 785 printf("AVX: %d\n", SDL_HasAVX()); 786 printf("AVX2: %d\n", SDL_HasAVX2()); 787 printf("RAM: %d MB\n", SDL_GetSystemRAM()); 788 return 0; 789} 790 791#endif /* TEST_MAIN */ 792 793/* vi: set ts=4 sw=4 expandtab: */