Support new Intel processor model numbers
[official-gcc.git] / libgcc / config / i386 / cpuinfo.c
blobc80083eec5053323aad4842da71e28395ed6f7c1
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 AMD_BTVER1,
60 AMD_BTVER2,
61 CPU_TYPE_MAX
64 enum processor_subtypes
66 INTEL_COREI7_NEHALEM = 1,
67 INTEL_COREI7_WESTMERE,
68 INTEL_COREI7_SANDYBRIDGE,
69 AMDFAM10H_BARCELONA,
70 AMDFAM10H_SHANGHAI,
71 AMDFAM10H_ISTANBUL,
72 AMDFAM15H_BDVER1,
73 AMDFAM15H_BDVER2,
74 AMDFAM15H_BDVER3,
75 AMDFAM15H_BDVER4,
76 INTEL_COREI7_IVYBRIDGE,
77 INTEL_COREI7_HASWELL,
78 INTEL_COREI7_BROADWELL,
79 CPU_SUBTYPE_MAX
82 /* ISA Features supported. */
84 enum processor_features
86 FEATURE_CMOV = 0,
87 FEATURE_MMX,
88 FEATURE_POPCNT,
89 FEATURE_SSE,
90 FEATURE_SSE2,
91 FEATURE_SSE3,
92 FEATURE_SSSE3,
93 FEATURE_SSE4_1,
94 FEATURE_SSE4_2,
95 FEATURE_AVX,
96 FEATURE_AVX2,
97 FEATURE_SSE4_A,
98 FEATURE_FMA4,
99 FEATURE_XOP,
100 FEATURE_FMA,
101 FEATURE_AVX512F
104 struct __processor_model
106 unsigned int __cpu_vendor;
107 unsigned int __cpu_type;
108 unsigned int __cpu_subtype;
109 unsigned int __cpu_features[1];
110 } __cpu_model;
113 /* Get the specific type of AMD CPU. */
115 static void
116 get_amd_cpu (unsigned int family, unsigned int model)
118 switch (family)
120 /* AMD Family 10h. */
121 case 0x10:
122 __cpu_model.__cpu_type = AMDFAM10H;
123 switch (model)
125 case 0x2:
126 /* Barcelona. */
127 __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
128 break;
129 case 0x4:
130 /* Shanghai. */
131 __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
132 break;
133 case 0x8:
134 /* Istanbul. */
135 __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
136 break;
137 default:
138 break;
140 break;
141 /* AMD Family 14h "btver1". */
142 case 0x14:
143 __cpu_model.__cpu_type = AMD_BTVER1;
144 break;
145 /* AMD Family 15h "Bulldozer". */
146 case 0x15:
147 __cpu_model.__cpu_type = AMDFAM15H;
148 /* Bulldozer version 1. */
149 if ( model <= 0xf)
150 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
151 /* Bulldozer version 2 "Piledriver" */
152 if (model >= 0x10 && model <= 0x2f)
153 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
154 /* Bulldozer version 3 "Steamroller" */
155 if (model >= 0x30 && model <= 0x4f)
156 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
157 break;
158 /* AMD Family 16h "btver2" */
159 case 0x16:
160 __cpu_model.__cpu_type = AMD_BTVER2;
161 break;
162 default:
163 break;
167 /* Get the specific type of Intel CPU. */
169 static void
170 get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
172 /* Parse family and model only if brand ID is 0. */
173 if (brand_id == 0)
175 switch (family)
177 case 0x5:
178 /* Pentium. */
179 break;
180 case 0x6:
181 switch (model)
183 case 0x1c:
184 case 0x26:
185 /* Bonnell. */
186 __cpu_model.__cpu_type = INTEL_BONNELL;
187 break;
188 case 0x37:
189 case 0x4a:
190 case 0x4d:
191 case 0x5a:
192 case 0x5d:
193 /* Silvermont. */
194 __cpu_model.__cpu_type = INTEL_SILVERMONT;
195 break;
196 case 0x1a:
197 case 0x1e:
198 case 0x1f:
199 case 0x2e:
200 /* Nehalem. */
201 __cpu_model.__cpu_type = INTEL_COREI7;
202 __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
203 break;
204 case 0x25:
205 case 0x2c:
206 case 0x2f:
207 /* Westmere. */
208 __cpu_model.__cpu_type = INTEL_COREI7;
209 __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
210 break;
211 case 0x2a:
212 case 0x2d:
213 /* Sandy Bridge. */
214 __cpu_model.__cpu_type = INTEL_COREI7;
215 __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
216 break;
217 case 0x3a:
218 case 0x3e:
219 /* Ivy Bridge. */
220 __cpu_model.__cpu_type = INTEL_COREI7;
221 __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
222 break;
223 case 0x3c:
224 case 0x3f:
225 case 0x45:
226 case 0x46:
227 /* Haswell. */
228 __cpu_model.__cpu_type = INTEL_COREI7;
229 __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
230 break;
231 case 0x3d:
232 case 0x4f:
233 case 0x56:
234 /* Broadwell. */
235 __cpu_model.__cpu_type = INTEL_COREI7;
236 __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
237 break;
238 case 0x17:
239 case 0x1d:
240 /* Penryn. */
241 case 0x0f:
242 /* Merom. */
243 __cpu_model.__cpu_type = INTEL_CORE2;
244 break;
245 default:
246 break;
248 break;
249 default:
250 /* We have no idea. */
251 break;
256 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
257 the max possible level of CPUID insn. */
258 static void
259 get_available_features (unsigned int ecx, unsigned int edx,
260 int max_cpuid_level)
262 unsigned int features = 0;
264 if (edx & bit_CMOV)
265 features |= (1 << FEATURE_CMOV);
266 if (edx & bit_MMX)
267 features |= (1 << FEATURE_MMX);
268 if (edx & bit_SSE)
269 features |= (1 << FEATURE_SSE);
270 if (edx & bit_SSE2)
271 features |= (1 << FEATURE_SSE2);
272 if (ecx & bit_POPCNT)
273 features |= (1 << FEATURE_POPCNT);
274 if (ecx & bit_SSE3)
275 features |= (1 << FEATURE_SSE3);
276 if (ecx & bit_SSSE3)
277 features |= (1 << FEATURE_SSSE3);
278 if (ecx & bit_SSE4_1)
279 features |= (1 << FEATURE_SSE4_1);
280 if (ecx & bit_SSE4_2)
281 features |= (1 << FEATURE_SSE4_2);
282 if (ecx & bit_AVX)
283 features |= (1 << FEATURE_AVX);
284 if (ecx & bit_FMA)
285 features |= (1 << FEATURE_FMA);
287 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
288 if (max_cpuid_level >= 7)
290 unsigned int eax, ebx, ecx, edx;
291 __cpuid_count (7, 0, eax, ebx, ecx, edx);
292 if (ebx & bit_AVX2)
293 features |= (1 << FEATURE_AVX2);
294 if (ebx & bit_AVX512F)
295 features |= (1 << FEATURE_AVX512F);
298 unsigned int ext_level;
299 unsigned int eax, ebx;
300 /* Check cpuid level of extended features. */
301 __cpuid (0x80000000, ext_level, ebx, ecx, edx);
303 if (ext_level > 0x80000000)
305 __cpuid (0x80000001, eax, ebx, ecx, edx);
307 if (ecx & bit_SSE4a)
308 features |= (1 << FEATURE_SSE4_A);
309 if (ecx & bit_FMA4)
310 features |= (1 << FEATURE_FMA4);
311 if (ecx & bit_XOP)
312 features |= (1 << FEATURE_XOP);
315 __cpu_model.__cpu_features[0] = features;
318 /* A noinline function calling __get_cpuid. Having many calls to
319 cpuid in one function in 32-bit mode causes GCC to complain:
320 "can't find a register in class CLOBBERED_REGS". This is
321 related to PR rtl-optimization 44174. */
323 static int __attribute__ ((noinline))
324 __get_cpuid_output (unsigned int __level,
325 unsigned int *__eax, unsigned int *__ebx,
326 unsigned int *__ecx, unsigned int *__edx)
328 return __get_cpuid (__level, __eax, __ebx, __ecx, __edx);
332 /* A constructor function that is sets __cpu_model and __cpu_features with
333 the right values. This needs to run only once. This constructor is
334 given the highest priority and it should run before constructors without
335 the priority set. However, it still runs after ifunc initializers and
336 needs to be called explicitly there. */
338 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
339 __cpu_indicator_init (void)
341 unsigned int eax, ebx, ecx, edx;
343 int max_level = 5;
344 unsigned int vendor;
345 unsigned int model, family, brand_id;
346 unsigned int extended_model, extended_family;
348 /* This function needs to run just once. */
349 if (__cpu_model.__cpu_vendor)
350 return 0;
352 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
353 if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx))
355 __cpu_model.__cpu_vendor = VENDOR_OTHER;
356 return -1;
359 vendor = ebx;
360 max_level = eax;
362 if (max_level < 1)
364 __cpu_model.__cpu_vendor = VENDOR_OTHER;
365 return -1;
368 if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx))
370 __cpu_model.__cpu_vendor = VENDOR_OTHER;
371 return -1;
374 model = (eax >> 4) & 0x0f;
375 family = (eax >> 8) & 0x0f;
376 brand_id = ebx & 0xff;
377 extended_model = (eax >> 12) & 0xf0;
378 extended_family = (eax >> 20) & 0xff;
380 if (vendor == signature_INTEL_ebx)
382 /* Adjust model and family for Intel CPUS. */
383 if (family == 0x0f)
385 family += extended_family;
386 model += extended_model;
388 else if (family == 0x06)
389 model += extended_model;
391 /* Get CPU type. */
392 get_intel_cpu (family, model, brand_id);
393 /* Find available features. */
394 get_available_features (ecx, edx, max_level);
395 __cpu_model.__cpu_vendor = VENDOR_INTEL;
397 else if (vendor == signature_AMD_ebx)
399 /* Adjust model and family for AMD CPUS. */
400 if (family == 0x0f)
402 family += extended_family;
403 model += (extended_model << 4);
406 /* Get CPU type. */
407 get_amd_cpu (family, model);
408 /* Find available features. */
409 get_available_features (ecx, edx, max_level);
410 __cpu_model.__cpu_vendor = VENDOR_AMD;
412 else
413 __cpu_model.__cpu_vendor = VENDOR_OTHER;
415 gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
416 gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
417 gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
419 return 0;