PR target/82524
[official-gcc.git] / libgcc / config / i386 / cpuinfo.c
blobc2ab8bed88eec5d6261bc67107fbfd8648cf6f38
1 /* Get CPU type and Features for x86 processors.
2 Copyright (C) 2012-2017 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 = { };
44 /* Get the specific type of AMD CPU. */
46 static void
47 get_amd_cpu (unsigned int family, unsigned int model)
49 switch (family)
51 /* AMD Family 10h. */
52 case 0x10:
53 __cpu_model.__cpu_type = AMDFAM10H;
54 switch (model)
56 case 0x2:
57 /* Barcelona. */
58 __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
59 break;
60 case 0x4:
61 /* Shanghai. */
62 __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
63 break;
64 case 0x8:
65 /* Istanbul. */
66 __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
67 break;
68 default:
69 break;
71 break;
72 /* AMD Family 14h "btver1". */
73 case 0x14:
74 __cpu_model.__cpu_type = AMD_BTVER1;
75 break;
76 /* AMD Family 15h "Bulldozer". */
77 case 0x15:
78 __cpu_model.__cpu_type = AMDFAM15H;
79 /* Bulldozer version 1. */
80 if ( model <= 0xf)
81 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
82 /* Bulldozer version 2 "Piledriver" */
83 if (model >= 0x10 && model <= 0x2f)
84 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
85 /* Bulldozer version 3 "Steamroller" */
86 if (model >= 0x30 && model <= 0x4f)
87 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
88 /* Bulldozer version 4 "Excavator" */
89 if (model >= 0x60 && model <= 0x7f)
90 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
91 break;
92 /* AMD Family 16h "btver2" */
93 case 0x16:
94 __cpu_model.__cpu_type = AMD_BTVER2;
95 break;
96 case 0x17:
97 __cpu_model.__cpu_type = AMDFAM17H;
98 /* AMD family 17h version 1. */
99 if (model <= 0x1f)
100 __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
101 break;
102 default:
103 break;
107 /* Get the specific type of Intel CPU. */
109 static void
110 get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
112 /* Parse family and model only if brand ID is 0. */
113 if (brand_id == 0)
115 switch (family)
117 case 0x5:
118 /* Pentium. */
119 break;
120 case 0x6:
121 switch (model)
123 case 0x1c:
124 case 0x26:
125 /* Bonnell. */
126 __cpu_model.__cpu_type = INTEL_BONNELL;
127 break;
128 case 0x37:
129 case 0x4a:
130 case 0x4d:
131 case 0x5a:
132 case 0x5d:
133 /* Silvermont. */
134 __cpu_model.__cpu_type = INTEL_SILVERMONT;
135 break;
136 case 0x57:
137 /* Knights Landing. */
138 __cpu_model.__cpu_type = INTEL_KNL;
139 break;
140 case 0x85:
141 /* Knights Mill. */
142 __cpu_model.__cpu_type = INTEL_KNM;
143 break;
144 case 0x1a:
145 case 0x1e:
146 case 0x1f:
147 case 0x2e:
148 /* Nehalem. */
149 __cpu_model.__cpu_type = INTEL_COREI7;
150 __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
151 break;
152 case 0x25:
153 case 0x2c:
154 case 0x2f:
155 /* Westmere. */
156 __cpu_model.__cpu_type = INTEL_COREI7;
157 __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
158 break;
159 case 0x2a:
160 case 0x2d:
161 /* Sandy Bridge. */
162 __cpu_model.__cpu_type = INTEL_COREI7;
163 __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
164 break;
165 case 0x3a:
166 case 0x3e:
167 /* Ivy Bridge. */
168 __cpu_model.__cpu_type = INTEL_COREI7;
169 __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
170 break;
171 case 0x3c:
172 case 0x3f:
173 case 0x45:
174 case 0x46:
175 /* Haswell. */
176 __cpu_model.__cpu_type = INTEL_COREI7;
177 __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
178 break;
179 case 0x3d:
180 case 0x47:
181 case 0x4f:
182 case 0x56:
183 /* Broadwell. */
184 __cpu_model.__cpu_type = INTEL_COREI7;
185 __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
186 break;
187 case 0x4e:
188 case 0x5e:
189 /* Skylake. */
190 case 0x8e:
191 case 0x9e:
192 /* Kaby Lake. */
193 __cpu_model.__cpu_type = INTEL_COREI7;
194 __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
195 break;
196 case 0x55:
197 /* Skylake with AVX-512 support. */
198 __cpu_model.__cpu_type = INTEL_COREI7;
199 __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
200 break;
201 case 0x17:
202 case 0x1d:
203 /* Penryn. */
204 case 0x0f:
205 /* Merom. */
206 __cpu_model.__cpu_type = INTEL_CORE2;
207 break;
208 default:
209 break;
211 break;
212 default:
213 /* We have no idea. */
214 break;
219 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
220 the max possible level of CPUID insn. */
221 static void
222 get_available_features (unsigned int ecx, unsigned int edx,
223 int max_cpuid_level)
225 unsigned int eax, ebx;
226 unsigned int ext_level;
228 unsigned int features = 0;
230 if (edx & bit_CMOV)
231 features |= (1 << FEATURE_CMOV);
232 if (edx & bit_MMX)
233 features |= (1 << FEATURE_MMX);
234 if (edx & bit_SSE)
235 features |= (1 << FEATURE_SSE);
236 if (edx & bit_SSE2)
237 features |= (1 << FEATURE_SSE2);
238 if (ecx & bit_POPCNT)
239 features |= (1 << FEATURE_POPCNT);
240 if (ecx & bit_AES)
241 features |= (1 << FEATURE_AES);
242 if (ecx & bit_PCLMUL)
243 features |= (1 << FEATURE_PCLMUL);
244 if (ecx & bit_SSE3)
245 features |= (1 << FEATURE_SSE3);
246 if (ecx & bit_SSSE3)
247 features |= (1 << FEATURE_SSSE3);
248 if (ecx & bit_SSE4_1)
249 features |= (1 << FEATURE_SSE4_1);
250 if (ecx & bit_SSE4_2)
251 features |= (1 << FEATURE_SSE4_2);
252 if (ecx & bit_AVX)
253 features |= (1 << FEATURE_AVX);
254 if (ecx & bit_FMA)
255 features |= (1 << FEATURE_FMA);
257 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
258 if (max_cpuid_level >= 7)
260 __cpuid_count (7, 0, eax, ebx, ecx, edx);
261 if (ebx & bit_BMI)
262 features |= (1 << FEATURE_BMI);
263 if (ebx & bit_AVX2)
264 features |= (1 << FEATURE_AVX2);
265 if (ebx & bit_BMI2)
266 features |= (1 << FEATURE_BMI2);
267 if (ebx & bit_AVX512F)
268 features |= (1 << FEATURE_AVX512F);
269 if (ebx & bit_AVX512VL)
270 features |= (1 << FEATURE_AVX512VL);
271 if (ebx & bit_AVX512BW)
272 features |= (1 << FEATURE_AVX512BW);
273 if (ebx & bit_AVX512DQ)
274 features |= (1 << FEATURE_AVX512DQ);
275 if (ebx & bit_AVX512CD)
276 features |= (1 << FEATURE_AVX512CD);
277 if (ebx & bit_AVX512PF)
278 features |= (1 << FEATURE_AVX512PF);
279 if (ebx & bit_AVX512ER)
280 features |= (1 << FEATURE_AVX512ER);
281 if (ebx & bit_AVX512IFMA)
282 features |= (1 << FEATURE_AVX512IFMA);
283 if (ecx & bit_AVX512VBMI)
284 features |= (1 << FEATURE_AVX512VBMI);
285 if (ecx & bit_AVX512VPOPCNTDQ)
286 features |= (1 << FEATURE_AVX512VPOPCNTDQ);
287 if (edx & bit_AVX5124VNNIW)
288 features |= (1 << FEATURE_AVX5124VNNIW);
289 if (edx & bit_AVX5124FMAPS)
290 features |= (1 << FEATURE_AVX5124FMAPS);
293 /* Check cpuid level of extended features. */
294 __cpuid (0x80000000, ext_level, ebx, ecx, edx);
296 if (ext_level >= 0x80000001)
298 __cpuid (0x80000001, eax, ebx, ecx, edx);
300 if (ecx & bit_SSE4a)
301 features |= (1 << FEATURE_SSE4_A);
302 if (ecx & bit_FMA4)
303 features |= (1 << FEATURE_FMA4);
304 if (ecx & bit_XOP)
305 features |= (1 << FEATURE_XOP);
308 __cpu_model.__cpu_features[0] = features;
311 /* A constructor function that is sets __cpu_model and __cpu_features with
312 the right values. This needs to run only once. This constructor is
313 given the highest priority and it should run before constructors without
314 the priority set. However, it still runs after ifunc initializers and
315 needs to be called explicitly there. */
317 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
318 __cpu_indicator_init (void)
320 unsigned int eax, ebx, ecx, edx;
322 int max_level;
323 unsigned int vendor;
324 unsigned int model, family, brand_id;
325 unsigned int extended_model, extended_family;
327 /* This function needs to run just once. */
328 if (__cpu_model.__cpu_vendor)
329 return 0;
331 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
332 if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
334 __cpu_model.__cpu_vendor = VENDOR_OTHER;
335 return -1;
338 vendor = ebx;
339 max_level = eax;
341 if (max_level < 1)
343 __cpu_model.__cpu_vendor = VENDOR_OTHER;
344 return -1;
347 if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
349 __cpu_model.__cpu_vendor = VENDOR_OTHER;
350 return -1;
353 model = (eax >> 4) & 0x0f;
354 family = (eax >> 8) & 0x0f;
355 brand_id = ebx & 0xff;
356 extended_model = (eax >> 12) & 0xf0;
357 extended_family = (eax >> 20) & 0xff;
359 if (vendor == signature_INTEL_ebx)
361 /* Adjust model and family for Intel CPUS. */
362 if (family == 0x0f)
364 family += extended_family;
365 model += extended_model;
367 else if (family == 0x06)
368 model += extended_model;
370 /* Get CPU type. */
371 get_intel_cpu (family, model, brand_id);
372 /* Find available features. */
373 get_available_features (ecx, edx, max_level);
374 __cpu_model.__cpu_vendor = VENDOR_INTEL;
376 else if (vendor == signature_AMD_ebx)
378 /* Adjust model and family for AMD CPUS. */
379 if (family == 0x0f)
381 family += extended_family;
382 model += extended_model;
385 /* Get CPU type. */
386 get_amd_cpu (family, model);
387 /* Find available features. */
388 get_available_features (ecx, edx, max_level);
389 __cpu_model.__cpu_vendor = VENDOR_AMD;
391 else
392 __cpu_model.__cpu_vendor = VENDOR_OTHER;
394 gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
395 gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
396 gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
398 return 0;
401 #if defined SHARED && defined USE_ELF_SYMVER
402 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
403 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");
404 #endif