PR target/84945
[official-gcc.git] / libgcc / config / i386 / cpuinfo.c
blob4eb3f5cd9441e55668b3f2b1ce10902bc9cf8e6b
1 /* Get CPU type and Features for x86 processors.
2 Copyright (C) 2012-2018 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"
29 #include "cpuinfo.h"
31 #ifdef HAVE_INIT_PRIORITY
32 #define CONSTRUCTOR_PRIORITY (101)
33 #else
34 #define CONSTRUCTOR_PRIORITY
35 #endif
37 int __cpu_indicator_init (void)
38 __attribute__ ((constructor CONSTRUCTOR_PRIORITY));
41 struct __processor_model __cpu_model = { };
42 #ifndef SHARED
43 /* We want to move away from __cpu_model in libgcc_s.so.1 and the
44 size of __cpu_model is part of ABI. So, new features that don't
45 fit into __cpu_model.__cpu_features[0] go into extra variables
46 in libgcc.a only, preferrably hidden. */
47 unsigned int __cpu_features2;
48 #endif
51 /* Get the specific type of AMD CPU. */
53 static void
54 get_amd_cpu (unsigned int family, unsigned int model)
56 switch (family)
58 /* AMD Family 10h. */
59 case 0x10:
60 __cpu_model.__cpu_type = AMDFAM10H;
61 switch (model)
63 case 0x2:
64 /* Barcelona. */
65 __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
66 break;
67 case 0x4:
68 /* Shanghai. */
69 __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
70 break;
71 case 0x8:
72 /* Istanbul. */
73 __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
74 break;
75 default:
76 break;
78 break;
79 /* AMD Family 14h "btver1". */
80 case 0x14:
81 __cpu_model.__cpu_type = AMD_BTVER1;
82 break;
83 /* AMD Family 15h "Bulldozer". */
84 case 0x15:
85 __cpu_model.__cpu_type = AMDFAM15H;
86 /* Bulldozer version 1. */
87 if ( model <= 0xf)
88 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
89 /* Bulldozer version 2 "Piledriver" */
90 if (model >= 0x10 && model <= 0x2f)
91 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
92 /* Bulldozer version 3 "Steamroller" */
93 if (model >= 0x30 && model <= 0x4f)
94 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
95 /* Bulldozer version 4 "Excavator" */
96 if (model >= 0x60 && model <= 0x7f)
97 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
98 break;
99 /* AMD Family 16h "btver2" */
100 case 0x16:
101 __cpu_model.__cpu_type = AMD_BTVER2;
102 break;
103 case 0x17:
104 __cpu_model.__cpu_type = AMDFAM17H;
105 /* AMD family 17h version 1. */
106 if (model <= 0x1f)
107 __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
108 break;
109 default:
110 break;
114 /* Get the specific type of Intel CPU. */
116 static void
117 get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
119 /* Parse family and model only if brand ID is 0. */
120 if (brand_id == 0)
122 switch (family)
124 case 0x5:
125 /* Pentium. */
126 break;
127 case 0x6:
128 switch (model)
130 case 0x1c:
131 case 0x26:
132 /* Bonnell. */
133 __cpu_model.__cpu_type = INTEL_BONNELL;
134 break;
135 case 0x37:
136 case 0x4a:
137 case 0x4d:
138 case 0x5a:
139 case 0x5d:
140 /* Silvermont. */
141 __cpu_model.__cpu_type = INTEL_SILVERMONT;
142 break;
143 case 0x57:
144 /* Knights Landing. */
145 __cpu_model.__cpu_type = INTEL_KNL;
146 break;
147 case 0x85:
148 /* Knights Mill. */
149 __cpu_model.__cpu_type = INTEL_KNM;
150 break;
151 case 0x1a:
152 case 0x1e:
153 case 0x1f:
154 case 0x2e:
155 /* Nehalem. */
156 __cpu_model.__cpu_type = INTEL_COREI7;
157 __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
158 break;
159 case 0x25:
160 case 0x2c:
161 case 0x2f:
162 /* Westmere. */
163 __cpu_model.__cpu_type = INTEL_COREI7;
164 __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
165 break;
166 case 0x2a:
167 case 0x2d:
168 /* Sandy Bridge. */
169 __cpu_model.__cpu_type = INTEL_COREI7;
170 __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
171 break;
172 case 0x3a:
173 case 0x3e:
174 /* Ivy Bridge. */
175 __cpu_model.__cpu_type = INTEL_COREI7;
176 __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
177 break;
178 case 0x3c:
179 case 0x3f:
180 case 0x45:
181 case 0x46:
182 /* Haswell. */
183 __cpu_model.__cpu_type = INTEL_COREI7;
184 __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
185 break;
186 case 0x3d:
187 case 0x47:
188 case 0x4f:
189 case 0x56:
190 /* Broadwell. */
191 __cpu_model.__cpu_type = INTEL_COREI7;
192 __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
193 break;
194 case 0x4e:
195 case 0x5e:
196 /* Skylake. */
197 case 0x8e:
198 case 0x9e:
199 /* Kaby Lake. */
200 __cpu_model.__cpu_type = INTEL_COREI7;
201 __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
202 break;
203 case 0x55:
204 /* Skylake with AVX-512 support. */
205 __cpu_model.__cpu_type = INTEL_COREI7;
206 __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
207 break;
208 case 0x66:
209 /* Cannon Lake. */
210 __cpu_model.__cpu_type = INTEL_COREI7;
211 __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
212 break;
213 case 0x17:
214 case 0x1d:
215 /* Penryn. */
216 case 0x0f:
217 /* Merom. */
218 __cpu_model.__cpu_type = INTEL_CORE2;
219 break;
220 default:
221 break;
223 break;
224 default:
225 /* We have no idea. */
226 break;
231 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
232 the max possible level of CPUID insn. */
233 static void
234 get_available_features (unsigned int ecx, unsigned int edx,
235 int max_cpuid_level)
237 unsigned int eax, ebx;
238 unsigned int ext_level;
240 unsigned int features = 0;
241 unsigned int features2 = 0;
243 #define set_feature(f) \
244 if (f < 32) features |= (1U << f); else features2 |= (1U << (f - 32))
246 if (edx & bit_CMOV)
247 set_feature (FEATURE_CMOV);
248 if (edx & bit_MMX)
249 set_feature (FEATURE_MMX);
250 if (edx & bit_SSE)
251 set_feature (FEATURE_SSE);
252 if (edx & bit_SSE2)
253 set_feature (FEATURE_SSE2);
254 if (ecx & bit_POPCNT)
255 set_feature (FEATURE_POPCNT);
256 if (ecx & bit_AES)
257 set_feature (FEATURE_AES);
258 if (ecx & bit_PCLMUL)
259 set_feature (FEATURE_PCLMUL);
260 if (ecx & bit_SSE3)
261 set_feature (FEATURE_SSE3);
262 if (ecx & bit_SSSE3)
263 set_feature (FEATURE_SSSE3);
264 if (ecx & bit_SSE4_1)
265 set_feature (FEATURE_SSE4_1);
266 if (ecx & bit_SSE4_2)
267 set_feature (FEATURE_SSE4_2);
268 if (ecx & bit_AVX)
269 set_feature (FEATURE_AVX);
270 if (ecx & bit_FMA)
271 set_feature (FEATURE_FMA);
273 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
274 if (max_cpuid_level >= 7)
276 __cpuid_count (7, 0, eax, ebx, ecx, edx);
277 if (ebx & bit_BMI)
278 set_feature (FEATURE_BMI);
279 if (ebx & bit_AVX2)
280 set_feature (FEATURE_AVX2);
281 if (ebx & bit_BMI2)
282 set_feature (FEATURE_BMI2);
283 if (ebx & bit_AVX512F)
284 set_feature (FEATURE_AVX512F);
285 if (ebx & bit_AVX512VL)
286 set_feature (FEATURE_AVX512VL);
287 if (ebx & bit_AVX512BW)
288 set_feature (FEATURE_AVX512BW);
289 if (ebx & bit_AVX512DQ)
290 set_feature (FEATURE_AVX512DQ);
291 if (ebx & bit_AVX512CD)
292 set_feature (FEATURE_AVX512CD);
293 if (ebx & bit_AVX512PF)
294 set_feature (FEATURE_AVX512PF);
295 if (ebx & bit_AVX512ER)
296 set_feature (FEATURE_AVX512ER);
297 if (ebx & bit_AVX512IFMA)
298 set_feature (FEATURE_AVX512IFMA);
299 if (ecx & bit_AVX512VBMI)
300 set_feature (FEATURE_AVX512VBMI);
301 if (ecx & bit_AVX512VBMI2)
302 set_feature (FEATURE_AVX512VBMI2);
303 if (ecx & bit_GFNI)
304 set_feature (FEATURE_GFNI);
305 if (ecx & bit_VPCLMULQDQ)
306 set_feature (FEATURE_VPCLMULQDQ);
307 if (ecx & bit_AVX512VNNI)
308 set_feature (FEATURE_AVX512VNNI);
309 if (ecx & bit_AVX512BITALG)
310 set_feature (FEATURE_AVX512BITALG);
311 if (ecx & bit_AVX512VPOPCNTDQ)
312 set_feature (FEATURE_AVX512VPOPCNTDQ);
313 if (edx & bit_AVX5124VNNIW)
314 set_feature (FEATURE_AVX5124VNNIW);
315 if (edx & bit_AVX5124FMAPS)
316 set_feature (FEATURE_AVX5124FMAPS);
319 /* Check cpuid level of extended features. */
320 __cpuid (0x80000000, ext_level, ebx, ecx, edx);
322 if (ext_level >= 0x80000001)
324 __cpuid (0x80000001, eax, ebx, ecx, edx);
326 if (ecx & bit_SSE4a)
327 set_feature (FEATURE_SSE4_A);
328 if (ecx & bit_FMA4)
329 set_feature (FEATURE_FMA4);
330 if (ecx & bit_XOP)
331 set_feature (FEATURE_XOP);
334 __cpu_model.__cpu_features[0] = features;
335 #ifndef SHARED
336 __cpu_features2 = features2;
337 #else
338 (void) features2;
339 #endif
342 /* A constructor function that is sets __cpu_model and __cpu_features with
343 the right values. This needs to run only once. This constructor is
344 given the highest priority and it should run before constructors without
345 the priority set. However, it still runs after ifunc initializers and
346 needs to be called explicitly there. */
348 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
349 __cpu_indicator_init (void)
351 unsigned int eax, ebx, ecx, edx;
353 int max_level;
354 unsigned int vendor;
355 unsigned int model, family, brand_id;
356 unsigned int extended_model, extended_family;
358 /* This function needs to run just once. */
359 if (__cpu_model.__cpu_vendor)
360 return 0;
362 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
363 if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
365 __cpu_model.__cpu_vendor = VENDOR_OTHER;
366 return -1;
369 vendor = ebx;
370 max_level = eax;
372 if (max_level < 1)
374 __cpu_model.__cpu_vendor = VENDOR_OTHER;
375 return -1;
378 if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
380 __cpu_model.__cpu_vendor = VENDOR_OTHER;
381 return -1;
384 model = (eax >> 4) & 0x0f;
385 family = (eax >> 8) & 0x0f;
386 brand_id = ebx & 0xff;
387 extended_model = (eax >> 12) & 0xf0;
388 extended_family = (eax >> 20) & 0xff;
390 if (vendor == signature_INTEL_ebx)
392 /* Adjust model and family for Intel CPUS. */
393 if (family == 0x0f)
395 family += extended_family;
396 model += extended_model;
398 else if (family == 0x06)
399 model += extended_model;
401 /* Get CPU type. */
402 get_intel_cpu (family, model, brand_id);
403 /* Find available features. */
404 get_available_features (ecx, edx, max_level);
405 __cpu_model.__cpu_vendor = VENDOR_INTEL;
407 else if (vendor == signature_AMD_ebx)
409 /* Adjust model and family for AMD CPUS. */
410 if (family == 0x0f)
412 family += extended_family;
413 model += extended_model;
416 /* Get CPU type. */
417 get_amd_cpu (family, model);
418 /* Find available features. */
419 get_available_features (ecx, edx, max_level);
420 __cpu_model.__cpu_vendor = VENDOR_AMD;
422 else
423 __cpu_model.__cpu_vendor = VENDOR_OTHER;
425 gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
426 gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
427 gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
429 return 0;
432 #if defined SHARED && defined USE_ELF_SYMVER
433 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
434 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");
435 #endif