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
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
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/>. */
28 #include "auto-target.h"
30 #ifdef HAVE_INIT_PRIORITY
31 #define CONSTRUCTOR_PRIORITY (101)
33 #define CONSTRUCTOR_PRIORITY
36 int __cpu_indicator_init (void)
37 __attribute__ ((constructor CONSTRUCTOR_PRIORITY));
39 /* Processor Vendor and Models. */
49 /* Any new types or subtypes have to be inserted at the end. */
64 enum processor_subtypes
66 INTEL_COREI7_NEHALEM = 1,
67 INTEL_COREI7_WESTMERE,
68 INTEL_COREI7_SANDYBRIDGE,
76 INTEL_COREI7_IVYBRIDGE,
78 INTEL_COREI7_BROADWELL,
82 /* ISA Features supported. */
84 enum processor_features
106 struct __processor_model
108 unsigned int __cpu_vendor;
109 unsigned int __cpu_type;
110 unsigned int __cpu_subtype;
111 unsigned int __cpu_features[1];
115 /* Get the specific type of AMD CPU. */
118 get_amd_cpu (unsigned int family, unsigned int model)
122 /* AMD Family 10h. */
124 __cpu_model.__cpu_type = AMDFAM10H;
129 __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
133 __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
137 __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
143 /* AMD Family 14h "btver1". */
145 __cpu_model.__cpu_type = AMD_BTVER1;
147 /* AMD Family 15h "Bulldozer". */
149 __cpu_model.__cpu_type = AMDFAM15H;
150 /* Bulldozer version 1. */
152 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
153 /* Bulldozer version 2 "Piledriver" */
154 if (model >= 0x10 && model <= 0x2f)
155 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
156 /* Bulldozer version 3 "Steamroller" */
157 if (model >= 0x30 && model <= 0x4f)
158 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
159 /* Bulldozer version 4 "Excavator" */
160 if (model >= 0x60 && model <= 0x7f)
161 __cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
163 /* AMD Family 16h "btver2" */
165 __cpu_model.__cpu_type = AMD_BTVER2;
172 /* Get the specific type of Intel CPU. */
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. */
191 __cpu_model.__cpu_type = INTEL_BONNELL;
199 __cpu_model.__cpu_type = INTEL_SILVERMONT;
206 __cpu_model.__cpu_type = INTEL_COREI7;
207 __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
213 __cpu_model.__cpu_type = INTEL_COREI7;
214 __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
219 __cpu_model.__cpu_type = INTEL_COREI7;
220 __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
225 __cpu_model.__cpu_type = INTEL_COREI7;
226 __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
233 __cpu_model.__cpu_type = INTEL_COREI7;
234 __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
240 __cpu_model.__cpu_type = INTEL_COREI7;
241 __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
248 __cpu_model.__cpu_type = INTEL_CORE2;
255 /* We have no idea. */
261 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
262 the max possible level of CPUID insn. */
264 get_available_features (unsigned int ecx, unsigned int edx,
267 unsigned int features = 0;
270 features |= (1 << FEATURE_CMOV);
272 features |= (1 << FEATURE_MMX);
274 features |= (1 << FEATURE_SSE);
276 features |= (1 << FEATURE_SSE2);
277 if (ecx & bit_POPCNT)
278 features |= (1 << FEATURE_POPCNT);
280 features |= (1 << FEATURE_SSE3);
282 features |= (1 << FEATURE_SSSE3);
283 if (ecx & bit_SSE4_1)
284 features |= (1 << FEATURE_SSE4_1);
285 if (ecx & bit_SSE4_2)
286 features |= (1 << FEATURE_SSE4_2);
288 features |= (1 << FEATURE_AVX);
290 features |= (1 << FEATURE_FMA);
292 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
293 if (max_cpuid_level >= 7)
295 unsigned int eax, ebx, ecx, edx;
296 __cpuid_count (7, 0, eax, ebx, ecx, edx);
298 features |= (1 << FEATURE_BMI);
300 features |= (1 << FEATURE_AVX2);
302 features |= (1 << FEATURE_BMI2);
303 if (ebx & bit_AVX512F)
304 features |= (1 << FEATURE_AVX512F);
307 unsigned int ext_level;
308 unsigned int eax, ebx;
309 /* Check cpuid level of extended features. */
310 __cpuid (0x80000000, ext_level, ebx, ecx, edx);
312 if (ext_level > 0x80000000)
314 __cpuid (0x80000001, eax, ebx, ecx, edx);
317 features |= (1 << FEATURE_SSE4_A);
319 features |= (1 << FEATURE_FMA4);
321 features |= (1 << FEATURE_XOP);
324 __cpu_model.__cpu_features[0] = features;
327 /* A noinline function calling __get_cpuid. Having many calls to
328 cpuid in one function in 32-bit mode causes GCC to complain:
329 "can't find a register in class CLOBBERED_REGS". This is
330 related to PR rtl-optimization 44174. */
332 static int __attribute__ ((noinline))
333 __get_cpuid_output (unsigned int __level,
334 unsigned int *__eax, unsigned int *__ebx,
335 unsigned int *__ecx, unsigned int *__edx)
337 return __get_cpuid (__level, __eax, __ebx, __ecx, __edx);
341 /* A constructor function that is sets __cpu_model and __cpu_features with
342 the right values. This needs to run only once. This constructor is
343 given the highest priority and it should run before constructors without
344 the priority set. However, it still runs after ifunc initializers and
345 needs to be called explicitly there. */
347 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
348 __cpu_indicator_init (void)
350 unsigned int eax, ebx, ecx, edx;
354 unsigned int model, family, brand_id;
355 unsigned int extended_model, extended_family;
357 /* This function needs to run just once. */
358 if (__cpu_model.__cpu_vendor)
361 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
362 if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx))
364 __cpu_model.__cpu_vendor = VENDOR_OTHER;
373 __cpu_model.__cpu_vendor = VENDOR_OTHER;
377 if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx))
379 __cpu_model.__cpu_vendor = VENDOR_OTHER;
383 model = (eax >> 4) & 0x0f;
384 family = (eax >> 8) & 0x0f;
385 brand_id = ebx & 0xff;
386 extended_model = (eax >> 12) & 0xf0;
387 extended_family = (eax >> 20) & 0xff;
389 if (vendor == signature_INTEL_ebx)
391 /* Adjust model and family for Intel CPUS. */
394 family += extended_family;
395 model += extended_model;
397 else if (family == 0x06)
398 model += extended_model;
401 get_intel_cpu (family, model, brand_id);
402 /* Find available features. */
403 get_available_features (ecx, edx, max_level);
404 __cpu_model.__cpu_vendor = VENDOR_INTEL;
406 else if (vendor == signature_AMD_ebx)
408 /* Adjust model and family for AMD CPUS. */
411 family += extended_family;
412 model += extended_model;
416 get_amd_cpu (family, model);
417 /* Find available features. */
418 get_available_features (ecx, edx, max_level);
419 __cpu_model.__cpu_vendor = VENDOR_AMD;
422 __cpu_model.__cpu_vendor = VENDOR_OTHER;
424 gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
425 gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
426 gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);