1 /* Get CPU type and Features for x86 processors.
2 Copyright (C) 2012-2016 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. */
66 enum processor_subtypes
68 INTEL_COREI7_NEHALEM
= 1,
69 INTEL_COREI7_WESTMERE
,
70 INTEL_COREI7_SANDYBRIDGE
,
79 INTEL_COREI7_IVYBRIDGE
,
81 INTEL_COREI7_BROADWELL
,
83 INTEL_COREI7_SKYLAKE_AVX512
,
87 /* ISA Features supported. New features have to be inserted at the end. */
89 enum processor_features
119 FEATURE_AVX5124VNNIW
,
123 struct __processor_model
125 unsigned int __cpu_vendor
;
126 unsigned int __cpu_type
;
127 unsigned int __cpu_subtype
;
128 unsigned int __cpu_features
[1];
132 /* Get the specific type of AMD CPU. */
135 get_amd_cpu (unsigned int family
, unsigned int model
)
139 /* AMD Family 10h. */
141 __cpu_model
.__cpu_type
= AMDFAM10H
;
146 __cpu_model
.__cpu_subtype
= AMDFAM10H_BARCELONA
;
150 __cpu_model
.__cpu_subtype
= AMDFAM10H_SHANGHAI
;
154 __cpu_model
.__cpu_subtype
= AMDFAM10H_ISTANBUL
;
160 /* AMD Family 14h "btver1". */
162 __cpu_model
.__cpu_type
= AMD_BTVER1
;
164 /* AMD Family 15h "Bulldozer". */
166 __cpu_model
.__cpu_type
= AMDFAM15H
;
167 /* Bulldozer version 1. */
169 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER1
;
170 /* Bulldozer version 2 "Piledriver" */
171 if (model
>= 0x10 && model
<= 0x2f)
172 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER2
;
173 /* Bulldozer version 3 "Steamroller" */
174 if (model
>= 0x30 && model
<= 0x4f)
175 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER3
;
176 /* Bulldozer version 4 "Excavator" */
177 if (model
>= 0x60 && model
<= 0x7f)
178 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER4
;
180 /* AMD Family 16h "btver2" */
182 __cpu_model
.__cpu_type
= AMD_BTVER2
;
185 __cpu_model
.__cpu_type
= AMDFAM17H
;
186 /* AMD family 17h version 1. */
188 __cpu_model
.__cpu_subtype
= AMDFAM17H_ZNVER1
;
195 /* Get the specific type of Intel CPU. */
198 get_intel_cpu (unsigned int family
, unsigned int model
, unsigned int brand_id
)
200 /* Parse family and model only if brand ID is 0. */
214 __cpu_model
.__cpu_type
= INTEL_BONNELL
;
222 __cpu_model
.__cpu_type
= INTEL_SILVERMONT
;
225 /* Knights Landing. */
226 __cpu_model
.__cpu_type
= INTEL_KNL
;
233 __cpu_model
.__cpu_type
= INTEL_COREI7
;
234 __cpu_model
.__cpu_subtype
= INTEL_COREI7_NEHALEM
;
240 __cpu_model
.__cpu_type
= INTEL_COREI7
;
241 __cpu_model
.__cpu_subtype
= INTEL_COREI7_WESTMERE
;
246 __cpu_model
.__cpu_type
= INTEL_COREI7
;
247 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SANDYBRIDGE
;
252 __cpu_model
.__cpu_type
= INTEL_COREI7
;
253 __cpu_model
.__cpu_subtype
= INTEL_COREI7_IVYBRIDGE
;
260 __cpu_model
.__cpu_type
= INTEL_COREI7
;
261 __cpu_model
.__cpu_subtype
= INTEL_COREI7_HASWELL
;
268 __cpu_model
.__cpu_type
= INTEL_COREI7
;
269 __cpu_model
.__cpu_subtype
= INTEL_COREI7_BROADWELL
;
274 __cpu_model
.__cpu_type
= INTEL_COREI7
;
275 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SKYLAKE
;
278 /* Skylake with AVX-512 support. */
279 __cpu_model
.__cpu_type
= INTEL_COREI7
;
280 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SKYLAKE_AVX512
;
287 __cpu_model
.__cpu_type
= INTEL_CORE2
;
294 /* We have no idea. */
300 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
301 the max possible level of CPUID insn. */
303 get_available_features (unsigned int ecx
, unsigned int edx
,
306 unsigned int features
= 0;
309 features
|= (1 << FEATURE_CMOV
);
311 features
|= (1 << FEATURE_MMX
);
313 features
|= (1 << FEATURE_SSE
);
315 features
|= (1 << FEATURE_SSE2
);
316 if (ecx
& bit_POPCNT
)
317 features
|= (1 << FEATURE_POPCNT
);
319 features
|= (1 << FEATURE_AES
);
320 if (ecx
& bit_PCLMUL
)
321 features
|= (1 << FEATURE_PCLMUL
);
323 features
|= (1 << FEATURE_SSE3
);
325 features
|= (1 << FEATURE_SSSE3
);
326 if (ecx
& bit_SSE4_1
)
327 features
|= (1 << FEATURE_SSE4_1
);
328 if (ecx
& bit_SSE4_2
)
329 features
|= (1 << FEATURE_SSE4_2
);
331 features
|= (1 << FEATURE_AVX
);
333 features
|= (1 << FEATURE_FMA
);
335 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
336 if (max_cpuid_level
>= 7)
338 unsigned int eax
, ebx
, ecx
, edx
;
339 __cpuid_count (7, 0, eax
, ebx
, ecx
, edx
);
341 features
|= (1 << FEATURE_BMI
);
343 features
|= (1 << FEATURE_AVX2
);
345 features
|= (1 << FEATURE_BMI2
);
346 if (ebx
& bit_AVX512F
)
347 features
|= (1 << FEATURE_AVX512F
);
348 if (ebx
& bit_AVX512VL
)
349 features
|= (1 << FEATURE_AVX512VL
);
350 if (ebx
& bit_AVX512BW
)
351 features
|= (1 << FEATURE_AVX512BW
);
352 if (ebx
& bit_AVX512DQ
)
353 features
|= (1 << FEATURE_AVX512DQ
);
354 if (ebx
& bit_AVX512CD
)
355 features
|= (1 << FEATURE_AVX512CD
);
356 if (ebx
& bit_AVX512PF
)
357 features
|= (1 << FEATURE_AVX512PF
);
358 if (ebx
& bit_AVX512ER
)
359 features
|= (1 << FEATURE_AVX512ER
);
360 if (ebx
& bit_AVX512IFMA
)
361 features
|= (1 << FEATURE_AVX512IFMA
);
362 if (ecx
& bit_AVX512VBMI
)
363 features
|= (1 << FEATURE_AVX512VBMI
);
364 if (edx
& bit_AVX5124VNNIW
)
365 features
|= (1 << FEATURE_AVX5124VNNIW
);
366 if (edx
& bit_AVX5124FMAPS
)
367 features
|= (1 << FEATURE_AVX5124FMAPS
);
370 unsigned int ext_level
;
371 unsigned int eax
, ebx
;
372 /* Check cpuid level of extended features. */
373 __cpuid (0x80000000, ext_level
, ebx
, ecx
, edx
);
375 if (ext_level
> 0x80000000)
377 __cpuid (0x80000001, eax
, ebx
, ecx
, edx
);
380 features
|= (1 << FEATURE_SSE4_A
);
382 features
|= (1 << FEATURE_FMA4
);
384 features
|= (1 << FEATURE_XOP
);
387 __cpu_model
.__cpu_features
[0] = features
;
390 /* A constructor function that is sets __cpu_model and __cpu_features with
391 the right values. This needs to run only once. This constructor is
392 given the highest priority and it should run before constructors without
393 the priority set. However, it still runs after ifunc initializers and
394 needs to be called explicitly there. */
396 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY
))
397 __cpu_indicator_init (void)
399 unsigned int eax
, ebx
, ecx
, edx
;
403 unsigned int model
, family
, brand_id
;
404 unsigned int extended_model
, extended_family
;
406 /* This function needs to run just once. */
407 if (__cpu_model
.__cpu_vendor
)
410 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
411 if (!__get_cpuid (0, &eax
, &ebx
, &ecx
, &edx
))
413 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
422 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
426 if (!__get_cpuid (1, &eax
, &ebx
, &ecx
, &edx
))
428 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
432 model
= (eax
>> 4) & 0x0f;
433 family
= (eax
>> 8) & 0x0f;
434 brand_id
= ebx
& 0xff;
435 extended_model
= (eax
>> 12) & 0xf0;
436 extended_family
= (eax
>> 20) & 0xff;
438 if (vendor
== signature_INTEL_ebx
)
440 /* Adjust model and family for Intel CPUS. */
443 family
+= extended_family
;
444 model
+= extended_model
;
446 else if (family
== 0x06)
447 model
+= extended_model
;
450 get_intel_cpu (family
, model
, brand_id
);
451 /* Find available features. */
452 get_available_features (ecx
, edx
, max_level
);
453 __cpu_model
.__cpu_vendor
= VENDOR_INTEL
;
455 else if (vendor
== signature_AMD_ebx
)
457 /* Adjust model and family for AMD CPUS. */
460 family
+= extended_family
;
461 model
+= extended_model
;
465 get_amd_cpu (family
, model
);
466 /* Find available features. */
467 get_available_features (ecx
, edx
, max_level
);
468 __cpu_model
.__cpu_vendor
= VENDOR_AMD
;
471 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
473 gcc_assert (__cpu_model
.__cpu_vendor
< VENDOR_MAX
);
474 gcc_assert (__cpu_model
.__cpu_type
< CPU_TYPE_MAX
);
475 gcc_assert (__cpu_model
.__cpu_subtype
< CPU_SUBTYPE_MAX
);
480 #if defined SHARED && defined USE_ELF_SYMVER
481 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
482 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");