1 /* Get CPU type and Features for x86 processors.
2 Copyright (C) 2012-2017 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
= { };
44 /* Get the specific type of AMD CPU. */
47 get_amd_cpu (unsigned int family
, unsigned int model
)
53 __cpu_model
.__cpu_type
= AMDFAM10H
;
58 __cpu_model
.__cpu_subtype
= AMDFAM10H_BARCELONA
;
62 __cpu_model
.__cpu_subtype
= AMDFAM10H_SHANGHAI
;
66 __cpu_model
.__cpu_subtype
= AMDFAM10H_ISTANBUL
;
72 /* AMD Family 14h "btver1". */
74 __cpu_model
.__cpu_type
= AMD_BTVER1
;
76 /* AMD Family 15h "Bulldozer". */
78 __cpu_model
.__cpu_type
= AMDFAM15H
;
79 /* Bulldozer version 1. */
81 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER1
;
82 /* Bulldozer version 2 "Piledriver" */
83 if (model
>= 0x10 && model
<= 0x2f)
84 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER2
;
85 /* Bulldozer version 3 "Steamroller" */
86 if (model
>= 0x30 && model
<= 0x4f)
87 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER3
;
88 /* Bulldozer version 4 "Excavator" */
89 if (model
>= 0x60 && model
<= 0x7f)
90 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER4
;
92 /* AMD Family 16h "btver2" */
94 __cpu_model
.__cpu_type
= AMD_BTVER2
;
97 __cpu_model
.__cpu_type
= AMDFAM17H
;
98 /* AMD family 17h version 1. */
100 __cpu_model
.__cpu_subtype
= AMDFAM17H_ZNVER1
;
107 /* Get the specific type of Intel CPU. */
110 get_intel_cpu (unsigned int family
, unsigned int model
, unsigned int brand_id
)
112 /* Parse family and model only if brand ID is 0. */
126 __cpu_model
.__cpu_type
= INTEL_BONNELL
;
134 __cpu_model
.__cpu_type
= INTEL_SILVERMONT
;
137 /* Knights Landing. */
138 __cpu_model
.__cpu_type
= INTEL_KNL
;
142 __cpu_model
.__cpu_type
= INTEL_KNM
;
149 __cpu_model
.__cpu_type
= INTEL_COREI7
;
150 __cpu_model
.__cpu_subtype
= INTEL_COREI7_NEHALEM
;
156 __cpu_model
.__cpu_type
= INTEL_COREI7
;
157 __cpu_model
.__cpu_subtype
= INTEL_COREI7_WESTMERE
;
162 __cpu_model
.__cpu_type
= INTEL_COREI7
;
163 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SANDYBRIDGE
;
168 __cpu_model
.__cpu_type
= INTEL_COREI7
;
169 __cpu_model
.__cpu_subtype
= INTEL_COREI7_IVYBRIDGE
;
176 __cpu_model
.__cpu_type
= INTEL_COREI7
;
177 __cpu_model
.__cpu_subtype
= INTEL_COREI7_HASWELL
;
184 __cpu_model
.__cpu_type
= INTEL_COREI7
;
185 __cpu_model
.__cpu_subtype
= INTEL_COREI7_BROADWELL
;
193 __cpu_model
.__cpu_type
= INTEL_COREI7
;
194 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SKYLAKE
;
197 /* Skylake with AVX-512 support. */
198 __cpu_model
.__cpu_type
= INTEL_COREI7
;
199 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SKYLAKE_AVX512
;
203 __cpu_model
.__cpu_type
= INTEL_COREI7
;
204 __cpu_model
.__cpu_subtype
= INTEL_COREI7_CANNONLAKE
;
211 __cpu_model
.__cpu_type
= INTEL_CORE2
;
218 /* We have no idea. */
224 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
225 the max possible level of CPUID insn. */
227 get_available_features (unsigned int ecx
, unsigned int edx
,
230 unsigned int eax
, ebx
;
231 unsigned int ext_level
;
233 unsigned int features
= 0;
236 features
|= (1 << FEATURE_CMOV
);
238 features
|= (1 << FEATURE_MMX
);
240 features
|= (1 << FEATURE_SSE
);
242 features
|= (1 << FEATURE_SSE2
);
243 if (ecx
& bit_POPCNT
)
244 features
|= (1 << FEATURE_POPCNT
);
246 features
|= (1 << FEATURE_AES
);
247 if (ecx
& bit_PCLMUL
)
248 features
|= (1 << FEATURE_PCLMUL
);
250 features
|= (1 << FEATURE_SSE3
);
252 features
|= (1 << FEATURE_SSSE3
);
253 if (ecx
& bit_SSE4_1
)
254 features
|= (1 << FEATURE_SSE4_1
);
255 if (ecx
& bit_SSE4_2
)
256 features
|= (1 << FEATURE_SSE4_2
);
258 features
|= (1 << FEATURE_AVX
);
260 features
|= (1 << FEATURE_FMA
);
262 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
263 if (max_cpuid_level
>= 7)
265 __cpuid_count (7, 0, eax
, ebx
, ecx
, edx
);
267 features
|= (1 << FEATURE_BMI
);
269 features
|= (1 << FEATURE_AVX2
);
271 features
|= (1 << FEATURE_BMI2
);
272 if (ebx
& bit_AVX512F
)
273 features
|= (1 << FEATURE_AVX512F
);
274 if (ebx
& bit_AVX512VL
)
275 features
|= (1 << FEATURE_AVX512VL
);
276 if (ebx
& bit_AVX512BW
)
277 features
|= (1 << FEATURE_AVX512BW
);
278 if (ebx
& bit_AVX512DQ
)
279 features
|= (1 << FEATURE_AVX512DQ
);
280 if (ebx
& bit_AVX512CD
)
281 features
|= (1 << FEATURE_AVX512CD
);
282 if (ebx
& bit_AVX512PF
)
283 features
|= (1 << FEATURE_AVX512PF
);
284 if (ebx
& bit_AVX512ER
)
285 features
|= (1 << FEATURE_AVX512ER
);
286 if (ebx
& bit_AVX512IFMA
)
287 features
|= (1 << FEATURE_AVX512IFMA
);
288 if (ecx
& bit_AVX512VBMI
)
289 features
|= (1 << FEATURE_AVX512VBMI
);
290 if (ecx
& bit_AVX512VPOPCNTDQ
)
291 features
|= (1 << FEATURE_AVX512VPOPCNTDQ
);
292 if (edx
& bit_AVX5124VNNIW
)
293 features
|= (1 << FEATURE_AVX5124VNNIW
);
294 if (edx
& bit_AVX5124FMAPS
)
295 features
|= (1 << FEATURE_AVX5124FMAPS
);
298 /* Check cpuid level of extended features. */
299 __cpuid (0x80000000, ext_level
, ebx
, ecx
, edx
);
301 if (ext_level
>= 0x80000001)
303 __cpuid (0x80000001, eax
, ebx
, ecx
, edx
);
306 features
|= (1 << FEATURE_SSE4_A
);
308 features
|= (1 << FEATURE_FMA4
);
310 features
|= (1 << FEATURE_XOP
);
313 __cpu_model
.__cpu_features
[0] = features
;
316 /* A constructor function that is sets __cpu_model and __cpu_features with
317 the right values. This needs to run only once. This constructor is
318 given the highest priority and it should run before constructors without
319 the priority set. However, it still runs after ifunc initializers and
320 needs to be called explicitly there. */
322 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY
))
323 __cpu_indicator_init (void)
325 unsigned int eax
, ebx
, ecx
, edx
;
329 unsigned int model
, family
, brand_id
;
330 unsigned int extended_model
, extended_family
;
332 /* This function needs to run just once. */
333 if (__cpu_model
.__cpu_vendor
)
336 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
337 if (!__get_cpuid (0, &eax
, &ebx
, &ecx
, &edx
))
339 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
348 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
352 if (!__get_cpuid (1, &eax
, &ebx
, &ecx
, &edx
))
354 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
358 model
= (eax
>> 4) & 0x0f;
359 family
= (eax
>> 8) & 0x0f;
360 brand_id
= ebx
& 0xff;
361 extended_model
= (eax
>> 12) & 0xf0;
362 extended_family
= (eax
>> 20) & 0xff;
364 if (vendor
== signature_INTEL_ebx
)
366 /* Adjust model and family for Intel CPUS. */
369 family
+= extended_family
;
370 model
+= extended_model
;
372 else if (family
== 0x06)
373 model
+= extended_model
;
376 get_intel_cpu (family
, model
, brand_id
);
377 /* Find available features. */
378 get_available_features (ecx
, edx
, max_level
);
379 __cpu_model
.__cpu_vendor
= VENDOR_INTEL
;
381 else if (vendor
== signature_AMD_ebx
)
383 /* Adjust model and family for AMD CPUS. */
386 family
+= extended_family
;
387 model
+= extended_model
;
391 get_amd_cpu (family
, model
);
392 /* Find available features. */
393 get_available_features (ecx
, edx
, max_level
);
394 __cpu_model
.__cpu_vendor
= VENDOR_AMD
;
397 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
399 gcc_assert (__cpu_model
.__cpu_vendor
< VENDOR_MAX
);
400 gcc_assert (__cpu_model
.__cpu_type
< CPU_TYPE_MAX
);
401 gcc_assert (__cpu_model
.__cpu_subtype
< CPU_SUBTYPE_MAX
);
406 #if defined SHARED && defined USE_ELF_SYMVER
407 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
408 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");