]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/builtins/cpu_model.c
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304149, and update
[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 #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