]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/builtins/cpu_model.c
Update our device tree files to a Linux 4.10
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / builtins / cpu_model.c
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