Add Knights Landing support to __builtin_cpu_is
[official-gcc.git] / libgcc / config / i386 / cpuinfo.c
blobb7b11de9865cba6b61c879647441b8431fe00d99
1 /* Get CPU type and Features for x86 processors.
2 Copyright (C) 2012-2015 Free Software Foundation, Inc.
3 Contributed by Sriraman Tallam (tmsriram@google.com)
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "cpuid.h"
27 #include "tsystem.h"
28 #include "auto-target.h"
30 #ifdef HAVE_INIT_PRIORITY
31 #define CONSTRUCTOR_PRIORITY (101)
32 #else
33 #define CONSTRUCTOR_PRIORITY
34 #endif
36 int __cpu_indicator_init (void)
37 __attribute__ ((constructor CONSTRUCTOR_PRIORITY));
39 /* Processor Vendor and Models. */
41 enum processor_vendor
43 VENDOR_INTEL = 1,
44 VENDOR_AMD,
45 VENDOR_OTHER,
46 VENDOR_MAX
49 /* Any new types or subtypes have to be inserted at the end. */
51 enum processor_types
53 INTEL_BONNELL = 1,
54 INTEL_CORE2,
55 INTEL_COREI7,
56 AMDFAM10H,
57 AMDFAM15H,
58 INTEL_SILVERMONT,
59 INTEL_KNL,
60 AMD_BTVER1,
61 AMD_BTVER2,
62 CPU_TYPE_MAX
65 enum processor_subtypes
67 INTEL_COREI7_NEHALEM = 1,
68 INTEL_COREI7_WESTMERE,
69 INTEL_COREI7_SANDYBRIDGE,
70 AMDFAM10H_BARCELONA,
71 AMDFAM10H_SHANGHAI,
72 AMDFAM10H_ISTANBUL,
73 AMDFAM15H_BDVER1,
74 AMDFAM15H_BDVER2,
75 AMDFAM15H_BDVER3,
76 AMDFAM15H_BDVER4,
77 INTEL_COREI7_IVYBRIDGE,
78 INTEL_COREI7_HASWELL,
79 INTEL_COREI7_BROADWELL,
80 CPU_SUBTYPE_MAX
83 /* ISA Features supported. */
85 enum processor_features
87 FEATURE_CMOV = 0,
88 FEATURE_MMX,
89 FEATURE_POPCNT,
90 FEATURE_SSE,
91 FEATURE_SSE2,
92 FEATURE_SSE3,
93 FEATURE_SSSE3,
94 FEATURE_SSE4_1,
95 FEATURE_SSE4_2,
96 FEATURE_AVX,
97 FEATURE_AVX2,
98 FEATURE_SSE4_A,
99 FEATURE_FMA4,
100 FEATURE_XOP,
101 FEATURE_FMA,
102 FEATURE_AVX512F,
103 FEATURE_BMI,
104 FEATURE_BMI2,
105 FEATURE_AES,
106 FEATURE_PCLMUL
109 struct __processor_model
111 unsigned int __cpu_vendor;
112 unsigned int __cpu_type;
113 unsigned int __cpu_subtype;
114 unsigned int __cpu_features[1];
115 } __cpu_model = { };
118 /* Get the specific type of AMD CPU. */
120 static void
121 get_amd_cpu (unsigned int family, unsigned int model)
123 switch (family)
125 /* AMD Family 10h. */
126 case 0x10:
127 __cpu_model.__cpu_type = AMDFAM10H;
128 switch (model)
130 case 0x2:
131 /* Barcelona. */
132 __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
133 break;
134 case 0x4:
135 /* Shanghai. */
136 __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
137 break;
138 case 0x8:
139 /* Istanbul. */
140 __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
141 break;
142 default:
143 break;
145 break;
146 /* AMD Family 14h "btver1". */
147 case 0x14:
148 __cpu_model.__cpu_type = AMD_BTVER1;
149 break;
150 /* AMD Family 15h "Bulldozer". */
151 case 0x15:
152 __cpu_model.__cpu_type = AMDFAM15H;
153 /* Bulldozer version 1. */
154 if ( model <= 0xf)
155 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
156 /* Bulldozer version 2 "Piledriver" */
157 if (model >= 0x10 && model <= 0x2f)
158 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
159 /* Bulldozer version 3 "Steamroller" */
160 if (model >= 0x30 && model <= 0x4f)
161 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
162 break;
163 /* AMD Family 16h "btver2" */
164 case 0x16:
165 __cpu_model.__cpu_type = AMD_BTVER2;
166 break;
167 default:
168 break;
172 /* Get the specific type of Intel CPU. */
174 static void
175 get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
177 /* Parse family and model only if brand ID is 0. */
178 if (brand_id == 0)
180 switch (family)
182 case 0x5:
183 /* Pentium. */
184 break;
185 case 0x6:
186 switch (model)
188 case 0x1c:
189 case 0x26:
190 /* Bonnell. */
191 __cpu_model.__cpu_type = INTEL_BONNELL;
192 break;
193 case 0x37:
194 case 0x4a:
195 case 0x4d:
196 case 0x5a:
197 case 0x5d:
198 /* Silvermont. */
199 __cpu_model.__cpu_type = INTEL_SILVERMONT;
200 break;
201 case 0x57:
202 /* Knights Landing. */
203 __cpu_model.__cpu_type = INTEL_KNL;
204 break;
205 case 0x1a:
206 case 0x1e:
207 case 0x1f:
208 case 0x2e:
209 /* Nehalem. */
210 __cpu_model.__cpu_type = INTEL_COREI7;
211 __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
212 break;
213 case 0x25:
214 case 0x2c:
215 case 0x2f:
216 /* Westmere. */
217 __cpu_model.__cpu_type = INTEL_COREI7;
218 __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
219 break;
220 case 0x2a:
221 case 0x2d:
222 /* Sandy Bridge. */
223 __cpu_model.__cpu_type = INTEL_COREI7;
224 __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
225 break;
226 case 0x3a:
227 case 0x3e:
228 /* Ivy Bridge. */
229 __cpu_model.__cpu_type = INTEL_COREI7;
230 __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
231 break;
232 case 0x3c:
233 case 0x3f:
234 case 0x45:
235 case 0x46:
236 /* Haswell. */
237 __cpu_model.__cpu_type = INTEL_COREI7;
238 __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
239 break;
240 case 0x3d:
241 case 0x47:
242 case 0x4f:
243 case 0x56:
244 /* Broadwell. */
245 __cpu_model.__cpu_type = INTEL_COREI7;
246 __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
247 break;
248 case 0x17:
249 case 0x1d:
250 /* Penryn. */
251 case 0x0f:
252 /* Merom. */
253 __cpu_model.__cpu_type = INTEL_CORE2;
254 break;
255 default:
256 break;
258 break;
259 default:
260 /* We have no idea. */
261 break;
266 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
267 the max possible level of CPUID insn. */
268 static void
269 get_available_features (unsigned int ecx, unsigned int edx,
270 int max_cpuid_level)
272 unsigned int features = 0;
274 if (edx & bit_CMOV)
275 features |= (1 << FEATURE_CMOV);
276 if (edx & bit_MMX)
277 features |= (1 << FEATURE_MMX);
278 if (edx & bit_SSE)
279 features |= (1 << FEATURE_SSE);
280 if (edx & bit_SSE2)
281 features |= (1 << FEATURE_SSE2);
282 if (ecx & bit_POPCNT)
283 features |= (1 << FEATURE_POPCNT);
284 if (ecx & bit_AES)
285 features |= (1 << FEATURE_AES);
286 if (ecx & bit_PCLMUL)
287 features |= (1 << FEATURE_PCLMUL);
288 if (ecx & bit_SSE3)
289 features |= (1 << FEATURE_SSE3);
290 if (ecx & bit_SSSE3)
291 features |= (1 << FEATURE_SSSE3);
292 if (ecx & bit_SSE4_1)
293 features |= (1 << FEATURE_SSE4_1);
294 if (ecx & bit_SSE4_2)
295 features |= (1 << FEATURE_SSE4_2);
296 if (ecx & bit_AVX)
297 features |= (1 << FEATURE_AVX);
298 if (ecx & bit_FMA)
299 features |= (1 << FEATURE_FMA);
301 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
302 if (max_cpuid_level >= 7)
304 unsigned int eax, ebx, ecx, edx;
305 __cpuid_count (7, 0, eax, ebx, ecx, edx);
306 if (ebx & bit_BMI)
307 features |= (1 << FEATURE_BMI);
308 if (ebx & bit_AVX2)
309 features |= (1 << FEATURE_AVX2);
310 if (ebx & bit_BMI2)
311 features |= (1 << FEATURE_BMI2);
312 if (ebx & bit_AVX512F)
313 features |= (1 << FEATURE_AVX512F);
316 unsigned int ext_level;
317 unsigned int eax, ebx;
318 /* Check cpuid level of extended features. */
319 __cpuid (0x80000000, ext_level, ebx, ecx, edx);
321 if (ext_level > 0x80000000)
323 __cpuid (0x80000001, eax, ebx, ecx, edx);
325 if (ecx & bit_SSE4a)
326 features |= (1 << FEATURE_SSE4_A);
327 if (ecx & bit_FMA4)
328 features |= (1 << FEATURE_FMA4);
329 if (ecx & bit_XOP)
330 features |= (1 << FEATURE_XOP);
333 __cpu_model.__cpu_features[0] = features;
336 /* A noinline function calling __get_cpuid. Having many calls to
337 cpuid in one function in 32-bit mode causes GCC to complain:
338 "can't find a register in class CLOBBERED_REGS". This is
339 related to PR rtl-optimization 44174. */
341 static int __attribute__ ((noinline))
342 __get_cpuid_output (unsigned int __level,
343 unsigned int *__eax, unsigned int *__ebx,
344 unsigned int *__ecx, unsigned int *__edx)
346 return __get_cpuid (__level, __eax, __ebx, __ecx, __edx);
350 /* A constructor function that is sets __cpu_model and __cpu_features with
351 the right values. This needs to run only once. This constructor is
352 given the highest priority and it should run before constructors without
353 the priority set. However, it still runs after ifunc initializers and
354 needs to be called explicitly there. */
356 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
357 __cpu_indicator_init (void)
359 unsigned int eax, ebx, ecx, edx;
361 int max_level = 5;
362 unsigned int vendor;
363 unsigned int model, family, brand_id;
364 unsigned int extended_model, extended_family;
366 /* This function needs to run just once. */
367 if (__cpu_model.__cpu_vendor)
368 return 0;
370 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
371 if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx))
373 __cpu_model.__cpu_vendor = VENDOR_OTHER;
374 return -1;
377 vendor = ebx;
378 max_level = eax;
380 if (max_level < 1)
382 __cpu_model.__cpu_vendor = VENDOR_OTHER;
383 return -1;
386 if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx))
388 __cpu_model.__cpu_vendor = VENDOR_OTHER;
389 return -1;
392 model = (eax >> 4) & 0x0f;
393 family = (eax >> 8) & 0x0f;
394 brand_id = ebx & 0xff;
395 extended_model = (eax >> 12) & 0xf0;
396 extended_family = (eax >> 20) & 0xff;
398 if (vendor == signature_INTEL_ebx)
400 /* Adjust model and family for Intel CPUS. */
401 if (family == 0x0f)
403 family += extended_family;
404 model += extended_model;
406 else if (family == 0x06)
407 model += extended_model;
409 /* Get CPU type. */
410 get_intel_cpu (family, model, brand_id);
411 /* Find available features. */
412 get_available_features (ecx, edx, max_level);
413 __cpu_model.__cpu_vendor = VENDOR_INTEL;
415 else if (vendor == signature_AMD_ebx)
417 /* Adjust model and family for AMD CPUS. */
418 if (family == 0x0f)
420 family += extended_family;
421 model += (extended_model << 4);
424 /* Get CPU type. */
425 get_amd_cpu (family, model);
426 /* Find available features. */
427 get_available_features (ecx, edx, max_level);
428 __cpu_model.__cpu_vendor = VENDOR_AMD;
430 else
431 __cpu_model.__cpu_vendor = VENDOR_OTHER;
433 gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
434 gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
435 gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
437 return 0;
440 #if defined SHARED && defined USE_ELF_SYMVER
441 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
442 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");
443 #endif