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
;
146 __cpu_model
.__cpu_type
= INTEL_GOLDMONT
;
149 /* Knights Landing. */
150 __cpu_model
.__cpu_type
= INTEL_KNL
;
154 __cpu_model
.__cpu_type
= INTEL_KNM
;
161 __cpu_model
.__cpu_type
= INTEL_COREI7
;
162 __cpu_model
.__cpu_subtype
= INTEL_COREI7_NEHALEM
;
168 __cpu_model
.__cpu_type
= INTEL_COREI7
;
169 __cpu_model
.__cpu_subtype
= INTEL_COREI7_WESTMERE
;
174 __cpu_model
.__cpu_type
= INTEL_COREI7
;
175 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SANDYBRIDGE
;
180 __cpu_model
.__cpu_type
= INTEL_COREI7
;
181 __cpu_model
.__cpu_subtype
= INTEL_COREI7_IVYBRIDGE
;
188 __cpu_model
.__cpu_type
= INTEL_COREI7
;
189 __cpu_model
.__cpu_subtype
= INTEL_COREI7_HASWELL
;
196 __cpu_model
.__cpu_type
= INTEL_COREI7
;
197 __cpu_model
.__cpu_subtype
= INTEL_COREI7_BROADWELL
;
205 __cpu_model
.__cpu_type
= INTEL_COREI7
;
206 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SKYLAKE
;
209 /* Skylake with AVX-512 support. */
210 __cpu_model
.__cpu_type
= INTEL_COREI7
;
211 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SKYLAKE_AVX512
;
215 __cpu_model
.__cpu_type
= INTEL_COREI7
;
216 __cpu_model
.__cpu_subtype
= INTEL_COREI7_CANNONLAKE
;
223 __cpu_model
.__cpu_type
= INTEL_CORE2
;
230 /* We have no idea. */
236 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
237 the max possible level of CPUID insn. */
239 get_available_features (unsigned int ecx
, unsigned int edx
,
242 unsigned int eax
, ebx
;
243 unsigned int ext_level
;
245 unsigned int features
= 0;
246 unsigned int features2
= 0;
248 /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */
249 #define XCR_XFEATURE_ENABLED_MASK 0x0
250 #define XSTATE_FP 0x1
251 #define XSTATE_SSE 0x2
252 #define XSTATE_YMM 0x4
253 #define XSTATE_OPMASK 0x20
254 #define XSTATE_ZMM 0x40
255 #define XSTATE_HI_ZMM 0x80
257 #define XCR_AVX_ENABLED_MASK \
258 (XSTATE_SSE | XSTATE_YMM)
259 #define XCR_AVX512F_ENABLED_MASK \
260 (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
262 /* Check if AVX and AVX512 are usable. */
264 int avx512_usable
= 0;
265 if ((ecx
& bit_OSXSAVE
))
267 /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
268 ZMM16-ZMM31 states are supported by OSXSAVE. */
270 unsigned int xcrhigh
;
271 asm (".byte 0x0f, 0x01, 0xd0"
272 : "=a" (xcrlow
), "=d" (xcrhigh
)
273 : "c" (XCR_XFEATURE_ENABLED_MASK
));
274 if ((xcrlow
& XCR_AVX_ENABLED_MASK
) == XCR_AVX_ENABLED_MASK
)
277 avx512_usable
= ((xcrlow
& XCR_AVX512F_ENABLED_MASK
)
278 == XCR_AVX512F_ENABLED_MASK
);
282 #define set_feature(f) \
286 features |= (1U << (f & 31)); \
288 features2 |= (1U << ((f - 32) & 31)); \
293 set_feature (FEATURE_CMOV
);
295 set_feature (FEATURE_MMX
);
297 set_feature (FEATURE_SSE
);
299 set_feature (FEATURE_SSE2
);
300 if (ecx
& bit_POPCNT
)
301 set_feature (FEATURE_POPCNT
);
303 set_feature (FEATURE_AES
);
304 if (ecx
& bit_PCLMUL
)
305 set_feature (FEATURE_PCLMUL
);
307 set_feature (FEATURE_SSE3
);
309 set_feature (FEATURE_SSSE3
);
310 if (ecx
& bit_SSE4_1
)
311 set_feature (FEATURE_SSE4_1
);
312 if (ecx
& bit_SSE4_2
)
313 set_feature (FEATURE_SSE4_2
);
317 set_feature (FEATURE_AVX
);
319 set_feature (FEATURE_FMA
);
322 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
323 if (max_cpuid_level
>= 7)
325 __cpuid_count (7, 0, eax
, ebx
, ecx
, edx
);
327 set_feature (FEATURE_BMI
);
331 set_feature (FEATURE_AVX2
);
334 set_feature (FEATURE_BMI2
);
337 if (ebx
& bit_AVX512F
)
338 set_feature (FEATURE_AVX512F
);
339 if (ebx
& bit_AVX512VL
)
340 set_feature (FEATURE_AVX512VL
);
341 if (ebx
& bit_AVX512BW
)
342 set_feature (FEATURE_AVX512BW
);
343 if (ebx
& bit_AVX512DQ
)
344 set_feature (FEATURE_AVX512DQ
);
345 if (ebx
& bit_AVX512CD
)
346 set_feature (FEATURE_AVX512CD
);
347 if (ebx
& bit_AVX512PF
)
348 set_feature (FEATURE_AVX512PF
);
349 if (ebx
& bit_AVX512ER
)
350 set_feature (FEATURE_AVX512ER
);
351 if (ebx
& bit_AVX512IFMA
)
352 set_feature (FEATURE_AVX512IFMA
);
353 if (ecx
& bit_AVX512VBMI
)
354 set_feature (FEATURE_AVX512VBMI
);
355 if (ecx
& bit_AVX512VBMI2
)
356 set_feature (FEATURE_AVX512VBMI2
);
358 set_feature (FEATURE_GFNI
);
359 if (ecx
& bit_VPCLMULQDQ
)
360 set_feature (FEATURE_VPCLMULQDQ
);
361 if (ecx
& bit_AVX512VNNI
)
362 set_feature (FEATURE_AVX512VNNI
);
363 if (ecx
& bit_AVX512BITALG
)
364 set_feature (FEATURE_AVX512BITALG
);
365 if (ecx
& bit_AVX512VPOPCNTDQ
)
366 set_feature (FEATURE_AVX512VPOPCNTDQ
);
367 if (edx
& bit_AVX5124VNNIW
)
368 set_feature (FEATURE_AVX5124VNNIW
);
369 if (edx
& bit_AVX5124FMAPS
)
370 set_feature (FEATURE_AVX5124FMAPS
);
374 /* Check cpuid level of extended features. */
375 __cpuid (0x80000000, ext_level
, ebx
, ecx
, edx
);
377 if (ext_level
>= 0x80000001)
379 __cpuid (0x80000001, eax
, ebx
, ecx
, edx
);
382 set_feature (FEATURE_SSE4_A
);
386 set_feature (FEATURE_FMA4
);
388 set_feature (FEATURE_XOP
);
392 __cpu_model
.__cpu_features
[0] = features
;
394 __cpu_features2
= features2
;
400 /* A constructor function that is sets __cpu_model and __cpu_features with
401 the right values. This needs to run only once. This constructor is
402 given the highest priority and it should run before constructors without
403 the priority set. However, it still runs after ifunc initializers and
404 needs to be called explicitly there. */
406 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY
))
407 __cpu_indicator_init (void)
409 unsigned int eax
, ebx
, ecx
, edx
;
413 unsigned int model
, family
, brand_id
;
414 unsigned int extended_model
, extended_family
;
416 /* This function needs to run just once. */
417 if (__cpu_model
.__cpu_vendor
)
420 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
421 if (!__get_cpuid (0, &eax
, &ebx
, &ecx
, &edx
))
423 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
432 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
436 if (!__get_cpuid (1, &eax
, &ebx
, &ecx
, &edx
))
438 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
442 model
= (eax
>> 4) & 0x0f;
443 family
= (eax
>> 8) & 0x0f;
444 brand_id
= ebx
& 0xff;
445 extended_model
= (eax
>> 12) & 0xf0;
446 extended_family
= (eax
>> 20) & 0xff;
448 if (vendor
== signature_INTEL_ebx
)
450 /* Adjust model and family for Intel CPUS. */
453 family
+= extended_family
;
454 model
+= extended_model
;
456 else if (family
== 0x06)
457 model
+= extended_model
;
460 get_intel_cpu (family
, model
, brand_id
);
461 /* Find available features. */
462 get_available_features (ecx
, edx
, max_level
);
463 __cpu_model
.__cpu_vendor
= VENDOR_INTEL
;
465 else if (vendor
== signature_AMD_ebx
)
467 /* Adjust model and family for AMD CPUS. */
470 family
+= extended_family
;
471 model
+= extended_model
;
475 get_amd_cpu (family
, model
);
476 /* Find available features. */
477 get_available_features (ecx
, edx
, max_level
);
478 __cpu_model
.__cpu_vendor
= VENDOR_AMD
;
481 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
483 gcc_assert (__cpu_model
.__cpu_vendor
< VENDOR_MAX
);
484 gcc_assert (__cpu_model
.__cpu_type
< CPU_TYPE_MAX
);
485 gcc_assert (__cpu_model
.__cpu_subtype
< CPU_SUBTYPE_MAX
);
490 #if defined SHARED && defined USE_ELF_SYMVER
491 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
492 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");