1 //===-- cpu_model.c - Support for __cpu_model builtin ------------*- C -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is based on LLVM's lib/Support/Host.cpp. 11 // It implements the operating system Host concept and builtin 12 // __cpu_model for the compiler_rt library, for x86 only. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #if (defined(__i386__) || defined(_M_IX86) || \ 17 defined(__x86_64__) || defined(_M_X64)) && \ 18 (defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)) 19 20 #include <assert.h> 21 22 #define bool int 23 #define true 1 24 #define false 0 25 26 #ifdef _MSC_VER 27 #include <intrin.h> 28 #endif 29 30 #ifndef __has_attribute 31 #define __has_attribute(attr) 0 32 #endif 33 34 enum VendorSignatures { 35 SIG_INTEL = 0x756e6547 /* Genu */, 36 SIG_AMD = 0x68747541 /* Auth */ 37 }; 38 39 enum ProcessorVendors { 40 VENDOR_INTEL = 1, 41 VENDOR_AMD, 42 VENDOR_OTHER, 43 VENDOR_MAX 44 }; 45 46 enum ProcessorTypes { 47 INTEL_ATOM = 1, 48 INTEL_CORE2, 49 INTEL_COREI7, 50 AMDFAM10H, 51 AMDFAM15H, 52 INTEL_i386, 53 INTEL_i486, 54 INTEL_PENTIUM, 55 INTEL_PENTIUM_PRO, 56 INTEL_PENTIUM_II, 57 INTEL_PENTIUM_III, 58 INTEL_PENTIUM_IV, 59 INTEL_PENTIUM_M, 60 INTEL_CORE_DUO, 61 INTEL_XEONPHI, 62 INTEL_X86_64, 63 INTEL_NOCONA, 64 INTEL_PRESCOTT, 65 AMD_i486, 66 AMDPENTIUM, 67 AMDATHLON, 68 AMDFAM14H, 69 AMDFAM16H, 70 CPU_TYPE_MAX 71 }; 72 73 enum ProcessorSubtypes { 74 INTEL_COREI7_NEHALEM = 1, 75 INTEL_COREI7_WESTMERE, 76 INTEL_COREI7_SANDYBRIDGE, 77 AMDFAM10H_BARCELONA, 78 AMDFAM10H_SHANGHAI, 79 AMDFAM10H_ISTANBUL, 80 AMDFAM15H_BDVER1, 81 AMDFAM15H_BDVER2, 82 INTEL_PENTIUM_MMX, 83 INTEL_CORE2_65, 84 INTEL_CORE2_45, 85 INTEL_COREI7_IVYBRIDGE, 86 INTEL_COREI7_HASWELL, 87 INTEL_COREI7_BROADWELL, 88 INTEL_COREI7_SKYLAKE, 89 INTEL_COREI7_SKYLAKE_AVX512, 90 INTEL_ATOM_BONNELL, 91 INTEL_ATOM_SILVERMONT, 92 INTEL_KNIGHTS_LANDING, 93 AMDPENTIUM_K6, 94 AMDPENTIUM_K62, 95 AMDPENTIUM_K63, 96 AMDPENTIUM_GEODE, 97 AMDATHLON_TBIRD, 98 AMDATHLON_MP, 99 AMDATHLON_XP, 100 AMDATHLON_K8SSE3, 101 AMDATHLON_OPTERON, 102 AMDATHLON_FX, 103 AMDATHLON_64, 104 AMD_BTVER1, 105 AMD_BTVER2, 106 AMDFAM15H_BDVER3, 107 AMDFAM15H_BDVER4, 108 CPU_SUBTYPE_MAX 109 }; 110 111 enum ProcessorFeatures { 112 FEATURE_CMOV = 0, 113 FEATURE_MMX, 114 FEATURE_POPCNT, 115 FEATURE_SSE, 116 FEATURE_SSE2, 117 FEATURE_SSE3, 118 FEATURE_SSSE3, 119 FEATURE_SSE4_1, 120 FEATURE_SSE4_2, 121 FEATURE_AVX, 122 FEATURE_AVX2, 123 FEATURE_AVX512, 124 FEATURE_AVX512SAVE, 125 FEATURE_MOVBE, 126 FEATURE_ADX, 127 FEATURE_EM64T 128 }; 129 130 // The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max). 131 // Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID 132 // support. Consequently, for i386, the presence of CPUID is checked first 133 // via the corresponding eflags bit. 134 static bool isCpuIdSupported() { 135 #if defined(__GNUC__) || defined(__clang__) 136 #if defined(__i386__) 137 int __cpuid_supported; 138 __asm__(" pushfl\n" 139 " popl %%eax\n" 140 " movl %%eax,%%ecx\n" 141 " xorl $0x00200000,%%eax\n" 142 " pushl %%eax\n" 143 " popfl\n" 144 " pushfl\n" 145 " popl %%eax\n" 146 " movl $0,%0\n" 147 " cmpl %%eax,%%ecx\n" 148 " je 1f\n" 149 " movl $1,%0\n" 150 "1:" 151 : "=r"(__cpuid_supported) 152 : 153 : "eax", "ecx"); 154 if (!__cpuid_supported) 155 return false; 156 #endif 157 return true; 158 #endif 159 return true; 160 } 161 162 // This code is copied from lib/Support/Host.cpp. 163 // Changes to either file should be mirrored in the other. 164 165 /// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in 166 /// the specified arguments. If we can't run cpuid on the host, return true. 167 static void getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, 168 unsigned *rECX, unsigned *rEDX) { 169 #if defined(__GNUC__) || defined(__clang__) 170 #if defined(__x86_64__) 171 // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. 172 __asm__("movq\t%%rbx, %%rsi\n\t" 173 "cpuid\n\t" 174 "xchgq\t%%rbx, %%rsi\n\t" 175 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 176 : "a"(value)); 177 #elif defined(__i386__) 178 __asm__("movl\t%%ebx, %%esi\n\t" 179 "cpuid\n\t" 180 "xchgl\t%%ebx, %%esi\n\t" 181 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 182 : "a"(value)); 183 // pedantic #else returns to appease -Wunreachable-code (so we don't generate 184 // postprocessed code that looks like "return true; return false;") 185 #else 186 assert(0 && "This method is defined only for x86."); 187 #endif 188 #elif defined(_MSC_VER) 189 // The MSVC intrinsic is portable across x86 and x64. 190 int registers[4]; 191 __cpuid(registers, value); 192 *rEAX = registers[0]; 193 *rEBX = registers[1]; 194 *rECX = registers[2]; 195 *rEDX = registers[3]; 196 #else 197 assert(0 && "This method is defined only for GNUC, Clang or MSVC."); 198 #endif 199 } 200 201 /// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return 202 /// the 4 values in the specified arguments. If we can't run cpuid on the host, 203 /// return true. 204 static void getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, 205 unsigned *rEAX, unsigned *rEBX, unsigned *rECX, 206 unsigned *rEDX) { 207 #if defined(__x86_64__) || defined(_M_X64) 208 #if defined(__GNUC__) || defined(__clang__) 209 // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. 210 // FIXME: should we save this for Clang? 211 __asm__("movq\t%%rbx, %%rsi\n\t" 212 "cpuid\n\t" 213 "xchgq\t%%rbx, %%rsi\n\t" 214 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 215 : "a"(value), "c"(subleaf)); 216 #elif defined(_MSC_VER) 217 int registers[4]; 218 __cpuidex(registers, value, subleaf); 219 *rEAX = registers[0]; 220 *rEBX = registers[1]; 221 *rECX = registers[2]; 222 *rEDX = registers[3]; 223 #else 224 assert(0 && "This method is defined only for GNUC, Clang or MSVC."); 225 #endif 226 #elif defined(__i386__) || defined(_M_IX86) 227 #if defined(__GNUC__) || defined(__clang__) 228 __asm__("movl\t%%ebx, %%esi\n\t" 229 "cpuid\n\t" 230 "xchgl\t%%ebx, %%esi\n\t" 231 : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) 232 : "a"(value), "c"(subleaf)); 233 #elif defined(_MSC_VER) 234 __asm { 235 mov eax,value 236 mov ecx,subleaf 237 cpuid 238 mov esi,rEAX 239 mov dword ptr [esi],eax 240 mov esi,rEBX 241 mov dword ptr [esi],ebx 242 mov esi,rECX 243 mov dword ptr [esi],ecx 244 mov esi,rEDX 245 mov dword ptr [esi],edx 246 } 247 #else 248 assert(0 && "This method is defined only for GNUC, Clang or MSVC."); 249 #endif 250 #else 251 assert(0 && "This method is defined only for x86."); 252 #endif 253 } 254 255 // Read control register 0 (XCR0). Used to detect features such as AVX. 256 static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) { 257 #if defined(__GNUC__) || defined(__clang__) 258 // Check xgetbv; this uses a .byte sequence instead of the instruction 259 // directly because older assemblers do not include support for xgetbv and 260 // there is no easy way to conditionally compile based on the assembler used. 261 __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0)); 262 return false; 263 #elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) 264 unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); 265 *rEAX = Result; 266 *rEDX = Result >> 32; 267 return false; 268 #else 269 return true; 270 #endif 271 } 272 273 static void detectX86FamilyModel(unsigned EAX, unsigned *Family, 274 unsigned *Model) { 275 *Family = (EAX >> 8) & 0xf; // Bits 8 - 11 276 *Model = (EAX >> 4) & 0xf; // Bits 4 - 7 277 if (*Family == 6 || *Family == 0xf) { 278 if (*Family == 0xf) 279 // Examine extended family ID if family ID is F. 280 *Family += (EAX >> 20) & 0xff; // Bits 20 - 27 281 // Examine extended model ID if family ID is 6 or F. 282 *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 283 } 284 } 285 286 static void getIntelProcessorTypeAndSubtype(unsigned int Family, 287 unsigned int Model, 288 unsigned int Brand_id, 289 unsigned int Features, 290 unsigned *Type, unsigned *Subtype) { 291 if (Brand_id != 0) 292 return; 293 switch (Family) { 294 case 3: 295 *Type = INTEL_i386; 296 break; 297 case 4: 298 switch (Model) { 299 case 0: // Intel486 DX processors 300 case 1: // Intel486 DX processors 301 case 2: // Intel486 SX processors 302 case 3: // Intel487 processors, IntelDX2 OverDrive processors, 303 // IntelDX2 processors 304 case 4: // Intel486 SL processor 305 case 5: // IntelSX2 processors 306 case 7: // Write-Back Enhanced IntelDX2 processors 307 case 8: // IntelDX4 OverDrive processors, IntelDX4 processors 308 default: 309 *Type = INTEL_i486; 310 break; 311 } 312 case 5: 313 switch (Model) { 314 case 1: // Pentium OverDrive processor for Pentium processor (60, 66), 315 // Pentium processors (60, 66) 316 case 2: // Pentium OverDrive processor for Pentium processor (75, 90, 317 // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133, 318 // 150, 166, 200) 319 case 3: // Pentium OverDrive processors for Intel486 processor-based 320 // systems 321 *Type = INTEL_PENTIUM; 322 break; 323 case 4: // Pentium OverDrive processor with MMX technology for Pentium 324 // processor (75, 90, 100, 120, 133), Pentium processor with 325 // MMX technology (166, 200) 326 *Type = INTEL_PENTIUM; 327 *Subtype = INTEL_PENTIUM_MMX; 328 break; 329 default: 330 *Type = INTEL_PENTIUM; 331 break; 332 } 333 case 6: 334 switch (Model) { 335 case 0x01: // Pentium Pro processor 336 *Type = INTEL_PENTIUM_PRO; 337 break; 338 case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor, 339 // model 03 340 case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor, 341 // model 05, and Intel Celeron processor, model 05 342 case 0x06: // Celeron processor, model 06 343 *Type = INTEL_PENTIUM_II; 344 break; 345 case 0x07: // Pentium III processor, model 07, and Pentium III Xeon 346 // processor, model 07 347 case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor, 348 // model 08, and Celeron processor, model 08 349 case 0x0a: // Pentium III Xeon processor, model 0Ah 350 case 0x0b: // Pentium III processor, model 0Bh 351 *Type = INTEL_PENTIUM_III; 352 break; 353 case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09. 354 case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model 355 // 0Dh. All processors are manufactured using the 90 nm process. 356 case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579 357 // Integrated Processor with Intel QuickAssist Technology 358 *Type = INTEL_PENTIUM_M; 359 break; 360 case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model 361 // 0Eh. All processors are manufactured using the 65 nm process. 362 *Type = INTEL_CORE_DUO; 363 break; // yonah 364 case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile 365 // processor, Intel Core 2 Quad processor, Intel Core 2 Quad 366 // mobile processor, Intel Core 2 Extreme processor, Intel 367 // Pentium Dual-Core processor, Intel Xeon processor, model 368 // 0Fh. All processors are manufactured using the 65 nm process. 369 case 0x16: // Intel Celeron processor model 16h. All processors are 370 // manufactured using the 65 nm process 371 *Type = INTEL_CORE2; // "core2" 372 *Subtype = INTEL_CORE2_65; 373 break; 374 case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model 375 // 17h. All processors are manufactured using the 45 nm process. 376 // 377 // 45nm: Penryn , Wolfdale, Yorkfield (XE) 378 case 0x1d: // Intel Xeon processor MP. All processors are manufactured using 379 // the 45 nm process. 380 *Type = INTEL_CORE2; // "penryn" 381 *Subtype = INTEL_CORE2_45; 382 break; 383 case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All 384 // processors are manufactured using the 45 nm process. 385 case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. 386 // As found in a Summer 2010 model iMac. 387 case 0x1f: 388 case 0x2e: // Nehalem EX 389 *Type = INTEL_COREI7; // "nehalem" 390 *Subtype = INTEL_COREI7_NEHALEM; 391 break; 392 case 0x25: // Intel Core i7, laptop version. 393 case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All 394 // processors are manufactured using the 32 nm process. 395 case 0x2f: // Westmere EX 396 *Type = INTEL_COREI7; // "westmere" 397 *Subtype = INTEL_COREI7_WESTMERE; 398 break; 399 case 0x2a: // Intel Core i7 processor. All processors are manufactured 400 // using the 32 nm process. 401 case 0x2d: 402 *Type = INTEL_COREI7; //"sandybridge" 403 *Subtype = INTEL_COREI7_SANDYBRIDGE; 404 break; 405 case 0x3a: 406 case 0x3e: // Ivy Bridge EP 407 *Type = INTEL_COREI7; // "ivybridge" 408 *Subtype = INTEL_COREI7_IVYBRIDGE; 409 break; 410 411 // Haswell: 412 case 0x3c: 413 case 0x3f: 414 case 0x45: 415 case 0x46: 416 *Type = INTEL_COREI7; // "haswell" 417 *Subtype = INTEL_COREI7_HASWELL; 418 break; 419 420 // Broadwell: 421 case 0x3d: 422 case 0x47: 423 case 0x4f: 424 case 0x56: 425 *Type = INTEL_COREI7; // "broadwell" 426 *Subtype = INTEL_COREI7_BROADWELL; 427 break; 428 429 // Skylake: 430 case 0x4e: 431 *Type = INTEL_COREI7; // "skylake-avx512" 432 *Subtype = INTEL_COREI7_SKYLAKE_AVX512; 433 break; 434 case 0x5e: 435 *Type = INTEL_COREI7; // "skylake" 436 *Subtype = INTEL_COREI7_SKYLAKE; 437 break; 438 439 case 0x1c: // Most 45 nm Intel Atom processors 440 case 0x26: // 45 nm Atom Lincroft 441 case 0x27: // 32 nm Atom Medfield 442 case 0x35: // 32 nm Atom Midview 443 case 0x36: // 32 nm Atom Midview 444 *Type = INTEL_ATOM; 445 *Subtype = INTEL_ATOM_BONNELL; 446 break; // "bonnell" 447 448 // Atom Silvermont codes from the Intel software optimization guide. 449 case 0x37: 450 case 0x4a: 451 case 0x4d: 452 case 0x5a: 453 case 0x5d: 454 case 0x4c: // really airmont 455 *Type = INTEL_ATOM; 456 *Subtype = INTEL_ATOM_SILVERMONT; 457 break; // "silvermont" 458 459 case 0x57: 460 *Type = INTEL_XEONPHI; // knl 461 *Subtype = INTEL_KNIGHTS_LANDING; 462 break; 463 464 default: // Unknown family 6 CPU, try to guess. 465 if (Features & (1 << FEATURE_AVX512)) { 466 *Type = INTEL_XEONPHI; // knl 467 *Subtype = INTEL_KNIGHTS_LANDING; 468 break; 469 } 470 if (Features & (1 << FEATURE_ADX)) { 471 *Type = INTEL_COREI7; 472 *Subtype = INTEL_COREI7_BROADWELL; 473 break; 474 } 475 if (Features & (1 << FEATURE_AVX2)) { 476 *Type = INTEL_COREI7; 477 *Subtype = INTEL_COREI7_HASWELL; 478 break; 479 } 480 if (Features & (1 << FEATURE_AVX)) { 481 *Type = INTEL_COREI7; 482 *Subtype = INTEL_COREI7_SANDYBRIDGE; 483 break; 484 } 485 if (Features & (1 << FEATURE_SSE4_2)) { 486 if (Features & (1 << FEATURE_MOVBE)) { 487 *Type = INTEL_ATOM; 488 *Subtype = INTEL_ATOM_SILVERMONT; 489 } else { 490 *Type = INTEL_COREI7; 491 *Subtype = INTEL_COREI7_NEHALEM; 492 } 493 break; 494 } 495 if (Features & (1 << FEATURE_SSE4_1)) { 496 *Type = INTEL_CORE2; // "penryn" 497 *Subtype = INTEL_CORE2_45; 498 break; 499 } 500 if (Features & (1 << FEATURE_SSSE3)) { 501 if (Features & (1 << FEATURE_MOVBE)) { 502 *Type = INTEL_ATOM; 503 *Subtype = INTEL_ATOM_BONNELL; // "bonnell" 504 } else { 505 *Type = INTEL_CORE2; // "core2" 506 *Subtype = INTEL_CORE2_65; 507 } 508 break; 509 } 510 if (Features & (1 << FEATURE_EM64T)) { 511 *Type = INTEL_X86_64; 512 break; // x86-64 513 } 514 if (Features & (1 << FEATURE_SSE2)) { 515 *Type = INTEL_PENTIUM_M; 516 break; 517 } 518 if (Features & (1 << FEATURE_SSE)) { 519 *Type = INTEL_PENTIUM_III; 520 break; 521 } 522 if (Features & (1 << FEATURE_MMX)) { 523 *Type = INTEL_PENTIUM_II; 524 break; 525 } 526 *Type = INTEL_PENTIUM_PRO; 527 break; 528 } 529 case 15: { 530 switch (Model) { 531 case 0: // Pentium 4 processor, Intel Xeon processor. All processors are 532 // model 00h and manufactured using the 0.18 micron process. 533 case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon 534 // processor MP, and Intel Celeron processor. All processors are 535 // model 01h and manufactured using the 0.18 micron process. 536 case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M, 537 // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron 538 // processor, and Mobile Intel Celeron processor. All processors 539 // are model 02h and manufactured using the 0.13 micron process. 540 *Type = 541 ((Features & (1 << FEATURE_EM64T)) ? INTEL_X86_64 : INTEL_PENTIUM_IV); 542 break; 543 544 case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D 545 // processor. All processors are model 03h and manufactured using 546 // the 90 nm process. 547 case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition, 548 // Pentium D processor, Intel Xeon processor, Intel Xeon 549 // processor MP, Intel Celeron D processor. All processors are 550 // model 04h and manufactured using the 90 nm process. 551 case 6: // Pentium 4 processor, Pentium D processor, Pentium processor 552 // Extreme Edition, Intel Xeon processor, Intel Xeon processor 553 // MP, Intel Celeron D processor. All processors are model 06h 554 // and manufactured using the 65 nm process. 555 *Type = 556 ((Features & (1 << FEATURE_EM64T)) ? INTEL_NOCONA : INTEL_PRESCOTT); 557 break; 558 559 default: 560 *Type = 561 ((Features & (1 << FEATURE_EM64T)) ? INTEL_X86_64 : INTEL_PENTIUM_IV); 562 break; 563 } 564 } 565 default: 566 break; /*"generic"*/ 567 } 568 } 569 570 static void getAMDProcessorTypeAndSubtype(unsigned int Family, 571 unsigned int Model, 572 unsigned int Features, unsigned *Type, 573 unsigned *Subtype) { 574 // FIXME: this poorly matches the generated SubtargetFeatureKV table. There 575 // appears to be no way to generate the wide variety of AMD-specific targets 576 // from the information returned from CPUID. 577 switch (Family) { 578 case 4: 579 *Type = AMD_i486; 580 case 5: 581 *Type = AMDPENTIUM; 582 switch (Model) { 583 case 6: 584 case 7: 585 *Subtype = AMDPENTIUM_K6; 586 break; // "k6" 587 case 8: 588 *Subtype = AMDPENTIUM_K62; 589 break; // "k6-2" 590 case 9: 591 case 13: 592 *Subtype = AMDPENTIUM_K63; 593 break; // "k6-3" 594 case 10: 595 *Subtype = AMDPENTIUM_GEODE; 596 break; // "geode" 597 default: 598 break; 599 } 600 case 6: 601 *Type = AMDATHLON; 602 switch (Model) { 603 case 4: 604 *Subtype = AMDATHLON_TBIRD; 605 break; // "athlon-tbird" 606 case 6: 607 case 7: 608 case 8: 609 *Subtype = AMDATHLON_MP; 610 break; // "athlon-mp" 611 case 10: 612 *Subtype = AMDATHLON_XP; 613 break; // "athlon-xp" 614 default: 615 break; 616 } 617 case 15: 618 *Type = AMDATHLON; 619 if (Features & (1 << FEATURE_SSE3)) { 620 *Subtype = AMDATHLON_K8SSE3; 621 break; // "k8-sse3" 622 } 623 switch (Model) { 624 case 1: 625 *Subtype = AMDATHLON_OPTERON; 626 break; // "opteron" 627 case 5: 628 *Subtype = AMDATHLON_FX; 629 break; // "athlon-fx"; also opteron 630 default: 631 *Subtype = AMDATHLON_64; 632 break; // "athlon64" 633 } 634 case 16: 635 *Type = AMDFAM10H; // "amdfam10" 636 switch (Model) { 637 case 2: 638 *Subtype = AMDFAM10H_BARCELONA; 639 break; 640 case 4: 641 *Subtype = AMDFAM10H_SHANGHAI; 642 break; 643 case 8: 644 *Subtype = AMDFAM10H_ISTANBUL; 645 break; 646 default: 647 break; 648 } 649 case 20: 650 *Type = AMDFAM14H; 651 *Subtype = AMD_BTVER1; 652 break; // "btver1"; 653 case 21: 654 *Type = AMDFAM15H; 655 if (!(Features & 656 (1 << FEATURE_AVX))) { // If no AVX support, provide a sane fallback. 657 *Subtype = AMD_BTVER1; 658 break; // "btver1" 659 } 660 if (Model >= 0x50 && Model <= 0x6f) { 661 *Subtype = AMDFAM15H_BDVER4; 662 break; // "bdver4"; 50h-6Fh: Excavator 663 } 664 if (Model >= 0x30 && Model <= 0x3f) { 665 *Subtype = AMDFAM15H_BDVER3; 666 break; // "bdver3"; 30h-3Fh: Steamroller 667 } 668 if (Model >= 0x10 && Model <= 0x1f) { 669 *Subtype = AMDFAM15H_BDVER2; 670 break; // "bdver2"; 10h-1Fh: Piledriver 671 } 672 if (Model <= 0x0f) { 673 *Subtype = AMDFAM15H_BDVER1; 674 break; // "bdver1"; 00h-0Fh: Bulldozer 675 } 676 break; 677 case 22: 678 *Type = AMDFAM16H; 679 if (!(Features & 680 (1 << FEATURE_AVX))) { // If no AVX support provide a sane fallback. 681 *Subtype = AMD_BTVER1; 682 break; // "btver1"; 683 } 684 *Subtype = AMD_BTVER2; 685 break; // "btver2" 686 default: 687 break; // "generic" 688 } 689 } 690 691 static unsigned getAvailableFeatures(unsigned int ECX, unsigned int EDX, 692 unsigned MaxLeaf) { 693 unsigned Features = 0; 694 unsigned int EAX, EBX; 695 Features |= (((EDX >> 23) & 1) << FEATURE_MMX); 696 Features |= (((EDX >> 25) & 1) << FEATURE_SSE); 697 Features |= (((EDX >> 26) & 1) << FEATURE_SSE2); 698 Features |= (((ECX >> 0) & 1) << FEATURE_SSE3); 699 Features |= (((ECX >> 9) & 1) << FEATURE_SSSE3); 700 Features |= (((ECX >> 19) & 1) << FEATURE_SSE4_1); 701 Features |= (((ECX >> 20) & 1) << FEATURE_SSE4_2); 702 Features |= (((ECX >> 22) & 1) << FEATURE_MOVBE); 703 704 // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV 705 // indicates that the AVX registers will be saved and restored on context 706 // switch, then we have full AVX support. 707 const unsigned AVXBits = (1 << 27) | (1 << 28); 708 bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) && 709 ((EAX & 0x6) == 0x6); 710 bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0); 711 bool HasLeaf7 = MaxLeaf >= 0x7; 712 getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); 713 bool HasADX = HasLeaf7 && ((EBX >> 19) & 1); 714 bool HasAVX2 = HasAVX && HasLeaf7 && (EBX & 0x20); 715 bool HasAVX512 = HasLeaf7 && HasAVX512Save && ((EBX >> 16) & 1); 716 Features |= (HasAVX << FEATURE_AVX); 717 Features |= (HasAVX2 << FEATURE_AVX2); 718 Features |= (HasAVX512 << FEATURE_AVX512); 719 Features |= (HasAVX512Save << FEATURE_AVX512SAVE); 720 Features |= (HasADX << FEATURE_ADX); 721 722 getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); 723 Features |= (((EDX >> 29) & 0x1) << FEATURE_EM64T); 724 return Features; 725 } 726 727 #if defined(HAVE_INIT_PRIORITY) 728 #define CONSTRUCTOR_ATTRIBUTE __attribute__((__constructor__ 101)) 729 #elif __has_attribute(__constructor__) 730 #define CONSTRUCTOR_ATTRIBUTE __attribute__((__constructor__)) 731 #else 732 // FIXME: For MSVC, we should make a function pointer global in .CRT$X?? so that 733 // this runs during initialization. 734 #define CONSTRUCTOR_ATTRIBUTE 735 #endif 736 737 int __cpu_indicator_init(void) CONSTRUCTOR_ATTRIBUTE; 738 739 struct __processor_model { 740 unsigned int __cpu_vendor; 741 unsigned int __cpu_type; 742 unsigned int __cpu_subtype; 743 unsigned int __cpu_features[1]; 744 } __cpu_model = {0, 0, 0, {0}}; 745 746 /* A constructor function that is sets __cpu_model and __cpu_features with 747 the right values. This needs to run only once. This constructor is 748 given the highest priority and it should run before constructors without 749 the priority set. However, it still runs after ifunc initializers and 750 needs to be called explicitly there. */ 751 752 int CONSTRUCTOR_ATTRIBUTE 753 __cpu_indicator_init(void) { 754 unsigned int EAX, EBX, ECX, EDX; 755 unsigned int MaxLeaf = 5; 756 unsigned int Vendor; 757 unsigned int Model, Family, Brand_id; 758 unsigned int Features = 0; 759 760 /* This function needs to run just once. */ 761 if (__cpu_model.__cpu_vendor) 762 return 0; 763 764 if (!isCpuIdSupported()) 765 return -1; 766 767 /* Assume cpuid insn present. Run in level 0 to get vendor id. */ 768 getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX); 769 770 if (MaxLeaf < 1) { 771 __cpu_model.__cpu_vendor = VENDOR_OTHER; 772 return -1; 773 } 774 getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX); 775 detectX86FamilyModel(EAX, &Family, &Model); 776 Brand_id = EBX & 0xff; 777 778 /* Find available features. */ 779 Features = getAvailableFeatures(ECX, EDX, MaxLeaf); 780 __cpu_model.__cpu_features[0] = Features; 781 782 if (Vendor == SIG_INTEL) { 783 /* Get CPU type. */ 784 getIntelProcessorTypeAndSubtype(Family, Model, Brand_id, Features, 785 &(__cpu_model.__cpu_type), 786 &(__cpu_model.__cpu_subtype)); 787 __cpu_model.__cpu_vendor = VENDOR_INTEL; 788 } else if (Vendor == SIG_AMD) { 789 /* Get CPU type. */ 790 getAMDProcessorTypeAndSubtype(Family, Model, Features, 791 &(__cpu_model.__cpu_type), 792 &(__cpu_model.__cpu_subtype)); 793 __cpu_model.__cpu_vendor = VENDOR_AMD; 794 } else 795 __cpu_model.__cpu_vendor = VENDOR_OTHER; 796 797 assert(__cpu_model.__cpu_vendor < VENDOR_MAX); 798 assert(__cpu_model.__cpu_type < CPU_TYPE_MAX); 799 assert(__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX); 800 801 return 0; 802 } 803 804 #endif 805