blob: 1302c9dff6796371d80182c736b42e74a5da0dbc [file] [log] [blame]
Alina Sbirlea36f57fb2016-07-14 22:02:35 +00001//===-- 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
30enum VendorSignatures {
31 SIG_INTEL = 0x756e6547 /* Genu */,
32 SIG_AMD = 0x68747541 /* Auth */
33};
34
35enum ProcessorVendors {
36 VENDOR_INTEL = 1,
37 VENDOR_AMD,
38 VENDOR_OTHER,
39 VENDOR_MAX
40};
41
42enum 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
69enum 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
107enum 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.
130static 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.
163static 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.
200static 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.
252static 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
269static 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
282static 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
566static 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
687static 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
729int __cpu_indicator_init(void)
730 __attribute__((constructor CONSTRUCTOR_PRIORITY));
731
732struct __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
745int __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