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
121 struct __processor_model
123 unsigned int __cpu_vendor
;
124 unsigned int __cpu_type
;
125 unsigned int __cpu_subtype
;
126 unsigned int __cpu_features
[1];
130 /* Get the specific type of AMD CPU. */
133 get_amd_cpu (unsigned int family
, unsigned int model
)
137 /* AMD Family 10h. */
139 __cpu_model
.__cpu_type
= AMDFAM10H
;
144 __cpu_model
.__cpu_subtype
= AMDFAM10H_BARCELONA
;
148 __cpu_model
.__cpu_subtype
= AMDFAM10H_SHANGHAI
;
152 __cpu_model
.__cpu_subtype
= AMDFAM10H_ISTANBUL
;
158 /* AMD Family 14h "btver1". */
160 __cpu_model
.__cpu_type
= AMD_BTVER1
;
162 /* AMD Family 15h "Bulldozer". */
164 __cpu_model
.__cpu_type
= AMDFAM15H
;
165 /* Bulldozer version 1. */
167 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER1
;
168 /* Bulldozer version 2 "Piledriver" */
169 if (model
>= 0x10 && model
<= 0x2f)
170 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER2
;
171 /* Bulldozer version 3 "Steamroller" */
172 if (model
>= 0x30 && model
<= 0x4f)
173 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER3
;
174 /* Bulldozer version 4 "Excavator" */
175 if (model
>= 0x60 && model
<= 0x7f)
176 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER4
;
178 /* AMD Family 16h "btver2" */
180 __cpu_model
.__cpu_type
= AMD_BTVER2
;
183 __cpu_model
.__cpu_type
= AMDFAM17H
;
184 /* AMD family 17h version 1. */
186 __cpu_model
.__cpu_subtype
= AMDFAM17H_ZNVER1
;
193 /* Get the specific type of Intel CPU. */
196 get_intel_cpu (unsigned int family
, unsigned int model
, unsigned int brand_id
)
198 /* Parse family and model only if brand ID is 0. */
212 __cpu_model
.__cpu_type
= INTEL_BONNELL
;
220 __cpu_model
.__cpu_type
= INTEL_SILVERMONT
;
223 /* Knights Landing. */
224 __cpu_model
.__cpu_type
= INTEL_KNL
;
231 __cpu_model
.__cpu_type
= INTEL_COREI7
;
232 __cpu_model
.__cpu_subtype
= INTEL_COREI7_NEHALEM
;
238 __cpu_model
.__cpu_type
= INTEL_COREI7
;
239 __cpu_model
.__cpu_subtype
= INTEL_COREI7_WESTMERE
;
244 __cpu_model
.__cpu_type
= INTEL_COREI7
;
245 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SANDYBRIDGE
;
250 __cpu_model
.__cpu_type
= INTEL_COREI7
;
251 __cpu_model
.__cpu_subtype
= INTEL_COREI7_IVYBRIDGE
;
258 __cpu_model
.__cpu_type
= INTEL_COREI7
;
259 __cpu_model
.__cpu_subtype
= INTEL_COREI7_HASWELL
;
266 __cpu_model
.__cpu_type
= INTEL_COREI7
;
267 __cpu_model
.__cpu_subtype
= INTEL_COREI7_BROADWELL
;
272 __cpu_model
.__cpu_type
= INTEL_COREI7
;
273 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SKYLAKE
;
276 /* Skylake with AVX-512 support. */
277 __cpu_model
.__cpu_type
= INTEL_COREI7
;
278 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SKYLAKE_AVX512
;
285 __cpu_model
.__cpu_type
= INTEL_CORE2
;
292 /* We have no idea. */
298 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
299 the max possible level of CPUID insn. */
301 get_available_features (unsigned int ecx
, unsigned int edx
,
304 unsigned int features
= 0;
307 features
|= (1 << FEATURE_CMOV
);
309 features
|= (1 << FEATURE_MMX
);
311 features
|= (1 << FEATURE_SSE
);
313 features
|= (1 << FEATURE_SSE2
);
314 if (ecx
& bit_POPCNT
)
315 features
|= (1 << FEATURE_POPCNT
);
317 features
|= (1 << FEATURE_AES
);
318 if (ecx
& bit_PCLMUL
)
319 features
|= (1 << FEATURE_PCLMUL
);
321 features
|= (1 << FEATURE_SSE3
);
323 features
|= (1 << FEATURE_SSSE3
);
324 if (ecx
& bit_SSE4_1
)
325 features
|= (1 << FEATURE_SSE4_1
);
326 if (ecx
& bit_SSE4_2
)
327 features
|= (1 << FEATURE_SSE4_2
);
329 features
|= (1 << FEATURE_AVX
);
331 features
|= (1 << FEATURE_FMA
);
333 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
334 if (max_cpuid_level
>= 7)
336 unsigned int eax
, ebx
, ecx
, edx
;
337 __cpuid_count (7, 0, eax
, ebx
, ecx
, edx
);
339 features
|= (1 << FEATURE_BMI
);
341 features
|= (1 << FEATURE_AVX2
);
343 features
|= (1 << FEATURE_BMI2
);
344 if (ebx
& bit_AVX512F
)
345 features
|= (1 << FEATURE_AVX512F
);
346 if (ebx
& bit_AVX512VL
)
347 features
|= (1 << FEATURE_AVX512VL
);
348 if (ebx
& bit_AVX512BW
)
349 features
|= (1 << FEATURE_AVX512BW
);
350 if (ebx
& bit_AVX512DQ
)
351 features
|= (1 << FEATURE_AVX512DQ
);
352 if (ebx
& bit_AVX512CD
)
353 features
|= (1 << FEATURE_AVX512CD
);
354 if (ebx
& bit_AVX512PF
)
355 features
|= (1 << FEATURE_AVX512PF
);
356 if (ebx
& bit_AVX512ER
)
357 features
|= (1 << FEATURE_AVX512ER
);
358 if (ebx
& bit_AVX512IFMA
)
359 features
|= (1 << FEATURE_AVX512IFMA
);
360 if (ecx
& bit_AVX512VBMI
)
361 features
|= (1 << FEATURE_AVX512VBMI
);
364 unsigned int ext_level
;
365 unsigned int eax
, ebx
;
366 /* Check cpuid level of extended features. */
367 __cpuid (0x80000000, ext_level
, ebx
, ecx
, edx
);
369 if (ext_level
> 0x80000000)
371 __cpuid (0x80000001, eax
, ebx
, ecx
, edx
);
374 features
|= (1 << FEATURE_SSE4_A
);
376 features
|= (1 << FEATURE_FMA4
);
378 features
|= (1 << FEATURE_XOP
);
381 __cpu_model
.__cpu_features
[0] = features
;
384 /* A noinline function calling __get_cpuid. Having many calls to
385 cpuid in one function in 32-bit mode causes GCC to complain:
386 "can't find a register in class CLOBBERED_REGS". This is
387 related to PR rtl-optimization 44174. */
389 static int __attribute__ ((noinline
))
390 __get_cpuid_output (unsigned int __level
,
391 unsigned int *__eax
, unsigned int *__ebx
,
392 unsigned int *__ecx
, unsigned int *__edx
)
394 return __get_cpuid (__level
, __eax
, __ebx
, __ecx
, __edx
);
398 /* A constructor function that is sets __cpu_model and __cpu_features with
399 the right values. This needs to run only once. This constructor is
400 given the highest priority and it should run before constructors without
401 the priority set. However, it still runs after ifunc initializers and
402 needs to be called explicitly there. */
404 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY
))
405 __cpu_indicator_init (void)
407 unsigned int eax
, ebx
, ecx
, edx
;
411 unsigned int model
, family
, brand_id
;
412 unsigned int extended_model
, extended_family
;
414 /* This function needs to run just once. */
415 if (__cpu_model
.__cpu_vendor
)
418 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
419 if (!__get_cpuid_output (0, &eax
, &ebx
, &ecx
, &edx
))
421 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
430 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
434 if (!__get_cpuid_output (1, &eax
, &ebx
, &ecx
, &edx
))
436 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
440 model
= (eax
>> 4) & 0x0f;
441 family
= (eax
>> 8) & 0x0f;
442 brand_id
= ebx
& 0xff;
443 extended_model
= (eax
>> 12) & 0xf0;
444 extended_family
= (eax
>> 20) & 0xff;
446 if (vendor
== signature_INTEL_ebx
)
448 /* Adjust model and family for Intel CPUS. */
451 family
+= extended_family
;
452 model
+= extended_model
;
454 else if (family
== 0x06)
455 model
+= extended_model
;
458 get_intel_cpu (family
, model
, brand_id
);
459 /* Find available features. */
460 get_available_features (ecx
, edx
, max_level
);
461 __cpu_model
.__cpu_vendor
= VENDOR_INTEL
;
463 else if (vendor
== signature_AMD_ebx
)
465 /* Adjust model and family for AMD CPUS. */
468 family
+= extended_family
;
469 model
+= extended_model
;
473 get_amd_cpu (family
, model
);
474 /* Find available features. */
475 get_available_features (ecx
, edx
, max_level
);
476 __cpu_model
.__cpu_vendor
= VENDOR_AMD
;
479 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
481 gcc_assert (__cpu_model
.__cpu_vendor
< VENDOR_MAX
);
482 gcc_assert (__cpu_model
.__cpu_type
< CPU_TYPE_MAX
);
483 gcc_assert (__cpu_model
.__cpu_subtype
< CPU_SUBTYPE_MAX
);
488 #if defined SHARED && defined USE_ELF_SYMVER
489 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
490 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");