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