blob: 5ff6baf438766b221665d4f2b918e09bcd73d7f8 [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
Reid Kleckner3ae87c42017-04-07 16:54:32 +000030#ifndef __has_attribute
31#define __has_attribute(attr) 0
32#endif
33
Alina Sbirlea36f57fb2016-07-14 22:02:35 +000034enum VendorSignatures {
35 SIG_INTEL = 0x756e6547 /* Genu */,
36 SIG_AMD = 0x68747541 /* Auth */
37};
38
39enum ProcessorVendors {
40 VENDOR_INTEL = 1,
41 VENDOR_AMD,
42 VENDOR_OTHER,
43 VENDOR_MAX
44};
45
46enum 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
73enum 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
111enum 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.
134static bool isCpuIdSupported() {
135#if defined(__GNUC__) || defined(__clang__)
136#if defined(__i386__)
137 int __cpuid_supported;
Alina Sbirlea9b476732016-07-17 23:45:55 +0000138 __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");
Alina Sbirlea36f57fb2016-07-14 22:02:35 +0000154 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.
167static 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.
Alina Sbirlea9b476732016-07-17 23:45:55 +0000172 __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));
Alina Sbirlea36f57fb2016-07-14 22:02:35 +0000177#elif defined(__i386__)
Alina Sbirlea9b476732016-07-17 23:45:55 +0000178 __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));
Alina Sbirlea36f57fb2016-07-14 22:02:35 +0000183// 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.
204static 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?
Alina Sbirlea9b476732016-07-17 23:45:55 +0000211 __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));
Alina Sbirlea36f57fb2016-07-14 22:02:35 +0000216#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__)
Alina Sbirlea9b476732016-07-17 23:45:55 +0000228 __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));
Alina Sbirlea36f57fb2016-07-14 22:02:35 +0000233#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.
256static 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
273static 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
286static 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
570static 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
691static 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
Reid Kleckner3ae87c42017-04-07 16:54:32 +0000727#if defined(HAVE_INIT_PRIORITY)
728#define CONSTRUCTOR_ATTRIBUTE __attribute__((__constructor__ 101))
729#elif __has_attribute(__constructor__)
730#define CONSTRUCTOR_ATTRIBUTE __attribute__((__constructor__))
Alina Sbirlea36f57fb2016-07-14 22:02:35 +0000731#else
Reid Kleckner3ae87c42017-04-07 16:54:32 +0000732// FIXME: For MSVC, we should make a function pointer global in .CRT$X?? so that
733// this runs during initialization.
734#define CONSTRUCTOR_ATTRIBUTE
Alina Sbirlea36f57fb2016-07-14 22:02:35 +0000735#endif
736
Reid Kleckner3ae87c42017-04-07 16:54:32 +0000737int __cpu_indicator_init(void) CONSTRUCTOR_ATTRIBUTE;
Alina Sbirlea36f57fb2016-07-14 22:02:35 +0000738
739struct __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
Reid Kleckner3ae87c42017-04-07 16:54:32 +0000752int CONSTRUCTOR_ATTRIBUTE
Alina Sbirlea36f57fb2016-07-14 22:02:35 +0000753__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