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
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"
31 #ifdef HAVE_INIT_PRIORITY
32 #define CONSTRUCTOR_PRIORITY (101)
34 #define CONSTRUCTOR_PRIORITY
37 int __cpu_indicator_init (void)
38 __attribute__ ((constructor CONSTRUCTOR_PRIORITY
));
41 struct __processor_model __cpu_model
= { };
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
;
51 /* Get the specific type of AMD CPU. */
54 get_amd_cpu (unsigned int family
, unsigned int model
)
60 __cpu_model
.__cpu_type
= AMDFAM10H
;
65 __cpu_model
.__cpu_subtype
= AMDFAM10H_BARCELONA
;
69 __cpu_model
.__cpu_subtype
= AMDFAM10H_SHANGHAI
;
73 __cpu_model
.__cpu_subtype
= AMDFAM10H_ISTANBUL
;
79 /* AMD Family 14h "btver1". */
81 __cpu_model
.__cpu_type
= AMD_BTVER1
;
83 /* AMD Family 15h "Bulldozer". */
85 __cpu_model
.__cpu_type
= AMDFAM15H
;
86 /* Bulldozer version 1. */
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
;
99 /* AMD Family 16h "btver2" */
101 __cpu_model
.__cpu_type
= AMD_BTVER2
;
104 __cpu_model
.__cpu_type
= AMDFAM17H
;
105 /* AMD family 17h version 1. */
107 __cpu_model
.__cpu_subtype
= AMDFAM17H_ZNVER1
;
114 /* Get the specific type of Intel CPU. */
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. */
133 __cpu_model
.__cpu_type
= INTEL_BONNELL
;
141 __cpu_model
.__cpu_type
= INTEL_SILVERMONT
;
144 /* Knights Landing. */
145 __cpu_model
.__cpu_type
= INTEL_KNL
;
149 __cpu_model
.__cpu_type
= INTEL_KNM
;
156 __cpu_model
.__cpu_type
= INTEL_COREI7
;
157 __cpu_model
.__cpu_subtype
= INTEL_COREI7_NEHALEM
;
163 __cpu_model
.__cpu_type
= INTEL_COREI7
;
164 __cpu_model
.__cpu_subtype
= INTEL_COREI7_WESTMERE
;
169 __cpu_model
.__cpu_type
= INTEL_COREI7
;
170 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SANDYBRIDGE
;
175 __cpu_model
.__cpu_type
= INTEL_COREI7
;
176 __cpu_model
.__cpu_subtype
= INTEL_COREI7_IVYBRIDGE
;
183 __cpu_model
.__cpu_type
= INTEL_COREI7
;
184 __cpu_model
.__cpu_subtype
= INTEL_COREI7_HASWELL
;
191 __cpu_model
.__cpu_type
= INTEL_COREI7
;
192 __cpu_model
.__cpu_subtype
= INTEL_COREI7_BROADWELL
;
200 __cpu_model
.__cpu_type
= INTEL_COREI7
;
201 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SKYLAKE
;
204 /* Skylake with AVX-512 support. */
205 __cpu_model
.__cpu_type
= INTEL_COREI7
;
206 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SKYLAKE_AVX512
;
210 __cpu_model
.__cpu_type
= INTEL_COREI7
;
211 __cpu_model
.__cpu_subtype
= INTEL_COREI7_CANNONLAKE
;
218 __cpu_model
.__cpu_type
= INTEL_CORE2
;
225 /* We have no idea. */
231 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
232 the max possible level of CPUID insn. */
234 get_available_features (unsigned int ecx
, unsigned int edx
,
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))
247 set_feature (FEATURE_CMOV
);
249 set_feature (FEATURE_MMX
);
251 set_feature (FEATURE_SSE
);
253 set_feature (FEATURE_SSE2
);
254 if (ecx
& bit_POPCNT
)
255 set_feature (FEATURE_POPCNT
);
257 set_feature (FEATURE_AES
);
258 if (ecx
& bit_PCLMUL
)
259 set_feature (FEATURE_PCLMUL
);
261 set_feature (FEATURE_SSE3
);
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
);
269 set_feature (FEATURE_AVX
);
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
);
278 set_feature (FEATURE_BMI
);
280 set_feature (FEATURE_AVX2
);
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
);
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
);
327 set_feature (FEATURE_SSE4_A
);
329 set_feature (FEATURE_FMA4
);
331 set_feature (FEATURE_XOP
);
334 __cpu_model
.__cpu_features
[0] = features
;
336 __cpu_features2
= features2
;
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
;
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
)
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
;
374 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
378 if (!__get_cpuid (1, &eax
, &ebx
, &ecx
, &edx
))
380 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
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. */
395 family
+= extended_family
;
396 model
+= extended_model
;
398 else if (family
== 0x06)
399 model
+= extended_model
;
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. */
412 family
+= extended_family
;
413 model
+= extended_model
;
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
;
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
);
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");