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
;
206 __cpu_model
.__cpu_type
= INTEL_CORE2
;
213 /* We have no idea. */
219 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
220 the max possible level of CPUID insn. */
222 get_available_features (unsigned int ecx
, unsigned int edx
,
225 unsigned int eax
, ebx
;
226 unsigned int ext_level
;
228 unsigned int features
= 0;
231 features
|= (1 << FEATURE_CMOV
);
233 features
|= (1 << FEATURE_MMX
);
235 features
|= (1 << FEATURE_SSE
);
237 features
|= (1 << FEATURE_SSE2
);
238 if (ecx
& bit_POPCNT
)
239 features
|= (1 << FEATURE_POPCNT
);
241 features
|= (1 << FEATURE_AES
);
242 if (ecx
& bit_PCLMUL
)
243 features
|= (1 << FEATURE_PCLMUL
);
245 features
|= (1 << FEATURE_SSE3
);
247 features
|= (1 << FEATURE_SSSE3
);
248 if (ecx
& bit_SSE4_1
)
249 features
|= (1 << FEATURE_SSE4_1
);
250 if (ecx
& bit_SSE4_2
)
251 features
|= (1 << FEATURE_SSE4_2
);
253 features
|= (1 << FEATURE_AVX
);
255 features
|= (1 << FEATURE_FMA
);
257 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
258 if (max_cpuid_level
>= 7)
260 __cpuid_count (7, 0, eax
, ebx
, ecx
, edx
);
262 features
|= (1 << FEATURE_BMI
);
264 features
|= (1 << FEATURE_AVX2
);
266 features
|= (1 << FEATURE_BMI2
);
267 if (ebx
& bit_AVX512F
)
268 features
|= (1 << FEATURE_AVX512F
);
269 if (ebx
& bit_AVX512VL
)
270 features
|= (1 << FEATURE_AVX512VL
);
271 if (ebx
& bit_AVX512BW
)
272 features
|= (1 << FEATURE_AVX512BW
);
273 if (ebx
& bit_AVX512DQ
)
274 features
|= (1 << FEATURE_AVX512DQ
);
275 if (ebx
& bit_AVX512CD
)
276 features
|= (1 << FEATURE_AVX512CD
);
277 if (ebx
& bit_AVX512PF
)
278 features
|= (1 << FEATURE_AVX512PF
);
279 if (ebx
& bit_AVX512ER
)
280 features
|= (1 << FEATURE_AVX512ER
);
281 if (ebx
& bit_AVX512IFMA
)
282 features
|= (1 << FEATURE_AVX512IFMA
);
283 if (ecx
& bit_AVX512VBMI
)
284 features
|= (1 << FEATURE_AVX512VBMI
);
285 if (ecx
& bit_AVX512VPOPCNTDQ
)
286 features
|= (1 << FEATURE_AVX512VPOPCNTDQ
);
287 if (edx
& bit_AVX5124VNNIW
)
288 features
|= (1 << FEATURE_AVX5124VNNIW
);
289 if (edx
& bit_AVX5124FMAPS
)
290 features
|= (1 << FEATURE_AVX5124FMAPS
);
293 /* Check cpuid level of extended features. */
294 __cpuid (0x80000000, ext_level
, ebx
, ecx
, edx
);
296 if (ext_level
>= 0x80000001)
298 __cpuid (0x80000001, eax
, ebx
, ecx
, edx
);
301 features
|= (1 << FEATURE_SSE4_A
);
303 features
|= (1 << FEATURE_FMA4
);
305 features
|= (1 << FEATURE_XOP
);
308 __cpu_model
.__cpu_features
[0] = features
;
311 /* A constructor function that is sets __cpu_model and __cpu_features with
312 the right values. This needs to run only once. This constructor is
313 given the highest priority and it should run before constructors without
314 the priority set. However, it still runs after ifunc initializers and
315 needs to be called explicitly there. */
317 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY
))
318 __cpu_indicator_init (void)
320 unsigned int eax
, ebx
, ecx
, edx
;
324 unsigned int model
, family
, brand_id
;
325 unsigned int extended_model
, extended_family
;
327 /* This function needs to run just once. */
328 if (__cpu_model
.__cpu_vendor
)
331 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
332 if (!__get_cpuid (0, &eax
, &ebx
, &ecx
, &edx
))
334 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
343 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
347 if (!__get_cpuid (1, &eax
, &ebx
, &ecx
, &edx
))
349 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
353 model
= (eax
>> 4) & 0x0f;
354 family
= (eax
>> 8) & 0x0f;
355 brand_id
= ebx
& 0xff;
356 extended_model
= (eax
>> 12) & 0xf0;
357 extended_family
= (eax
>> 20) & 0xff;
359 if (vendor
== signature_INTEL_ebx
)
361 /* Adjust model and family for Intel CPUS. */
364 family
+= extended_family
;
365 model
+= extended_model
;
367 else if (family
== 0x06)
368 model
+= extended_model
;
371 get_intel_cpu (family
, model
, brand_id
);
372 /* Find available features. */
373 get_available_features (ecx
, edx
, max_level
);
374 __cpu_model
.__cpu_vendor
= VENDOR_INTEL
;
376 else if (vendor
== signature_AMD_ebx
)
378 /* Adjust model and family for AMD CPUS. */
381 family
+= extended_family
;
382 model
+= extended_model
;
386 get_amd_cpu (family
, model
);
387 /* Find available features. */
388 get_available_features (ecx
, edx
, max_level
);
389 __cpu_model
.__cpu_vendor
= VENDOR_AMD
;
392 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
394 gcc_assert (__cpu_model
.__cpu_vendor
< VENDOR_MAX
);
395 gcc_assert (__cpu_model
.__cpu_type
< CPU_TYPE_MAX
);
396 gcc_assert (__cpu_model
.__cpu_subtype
< CPU_SUBTYPE_MAX
);
401 #if defined SHARED && defined USE_ELF_SYMVER
402 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
403 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");