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
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];
113 /* Get the specific type of AMD CPU. */
116 get_amd_cpu (unsigned int family
, unsigned int model
)
120 /* AMD Family 10h. */
122 __cpu_model
.__cpu_type
= AMDFAM10H
;
127 __cpu_model
.__cpu_subtype
= AMDFAM10H_BARCELONA
;
131 __cpu_model
.__cpu_subtype
= AMDFAM10H_SHANGHAI
;
135 __cpu_model
.__cpu_subtype
= AMDFAM10H_ISTANBUL
;
141 /* AMD Family 14h "btver1". */
143 __cpu_model
.__cpu_type
= AMD_BTVER1
;
145 /* AMD Family 15h "Bulldozer". */
147 __cpu_model
.__cpu_type
= AMDFAM15H
;
148 /* Bulldozer version 1. */
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
;
158 /* AMD Family 16h "btver2" */
160 __cpu_model
.__cpu_type
= AMD_BTVER2
;
167 /* Get the specific type of Intel CPU. */
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. */
186 __cpu_model
.__cpu_type
= INTEL_BONNELL
;
194 __cpu_model
.__cpu_type
= INTEL_SILVERMONT
;
201 __cpu_model
.__cpu_type
= INTEL_COREI7
;
202 __cpu_model
.__cpu_subtype
= INTEL_COREI7_NEHALEM
;
208 __cpu_model
.__cpu_type
= INTEL_COREI7
;
209 __cpu_model
.__cpu_subtype
= INTEL_COREI7_WESTMERE
;
214 __cpu_model
.__cpu_type
= INTEL_COREI7
;
215 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SANDYBRIDGE
;
220 __cpu_model
.__cpu_type
= INTEL_COREI7
;
221 __cpu_model
.__cpu_subtype
= INTEL_COREI7_IVYBRIDGE
;
228 __cpu_model
.__cpu_type
= INTEL_COREI7
;
229 __cpu_model
.__cpu_subtype
= INTEL_COREI7_HASWELL
;
235 __cpu_model
.__cpu_type
= INTEL_COREI7
;
236 __cpu_model
.__cpu_subtype
= INTEL_COREI7_BROADWELL
;
243 __cpu_model
.__cpu_type
= INTEL_CORE2
;
250 /* We have no idea. */
256 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
257 the max possible level of CPUID insn. */
259 get_available_features (unsigned int ecx
, unsigned int edx
,
262 unsigned int features
= 0;
265 features
|= (1 << FEATURE_CMOV
);
267 features
|= (1 << FEATURE_MMX
);
269 features
|= (1 << FEATURE_SSE
);
271 features
|= (1 << FEATURE_SSE2
);
272 if (ecx
& bit_POPCNT
)
273 features
|= (1 << FEATURE_POPCNT
);
275 features
|= (1 << FEATURE_SSE3
);
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
);
283 features
|= (1 << FEATURE_AVX
);
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
);
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
);
308 features
|= (1 << FEATURE_SSE4_A
);
310 features
|= (1 << FEATURE_FMA4
);
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
;
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
)
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
;
364 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
368 if (!__get_cpuid_output (1, &eax
, &ebx
, &ecx
, &edx
))
370 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
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. */
385 family
+= extended_family
;
386 model
+= extended_model
;
388 else if (family
== 0x06)
389 model
+= extended_model
;
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. */
402 family
+= extended_family
;
403 model
+= (extended_model
<< 4);
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
;
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
);