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