1 /* Get CPU type and Features for x86 processors.
2 Copyright (C) 2012-2014 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)
38 __attribute__ ((visibility("hidden")))
40 __attribute__ ((constructor CONSTRUCTOR_PRIORITY
));
42 /* Processor Vendor and Models. */
52 /* Any new types or subtypes have to be inserted at the end. */
67 enum processor_subtypes
69 INTEL_COREI7_NEHALEM
= 1,
70 INTEL_COREI7_WESTMERE
,
71 INTEL_COREI7_SANDYBRIDGE
,
79 INTEL_COREI7_IVYBRIDGE
,
84 /* ISA Features supported. */
86 enum processor_features
106 __attribute__ ((visibility("hidden")))
108 struct __processor_model
110 unsigned int __cpu_vendor
;
111 unsigned int __cpu_type
;
112 unsigned int __cpu_subtype
;
113 unsigned int __cpu_features
[1];
117 /* Get the specific type of AMD CPU. */
120 get_amd_cpu (unsigned int family
, unsigned int model
)
124 /* AMD Family 10h. */
126 __cpu_model
.__cpu_type
= AMDFAM10H
;
131 __cpu_model
.__cpu_subtype
= AMDFAM10H_BARCELONA
;
135 __cpu_model
.__cpu_subtype
= AMDFAM10H_SHANGHAI
;
139 __cpu_model
.__cpu_subtype
= AMDFAM10H_ISTANBUL
;
145 /* AMD Family 14h "btver1". */
147 __cpu_model
.__cpu_type
= AMD_BTVER1
;
149 /* AMD Family 15h "Bulldozer". */
151 __cpu_model
.__cpu_type
= AMDFAM15H
;
152 /* Bulldozer version 1. */
154 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER1
;
155 /* Bulldozer version 2 "Piledriver" */
156 if (model
>= 0x10 && model
<= 0x2f)
157 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER2
;
158 /* Bulldozer version 3 "Steamroller" */
159 if (model
>= 0x30 && model
<= 0x4f)
160 __cpu_model
.__cpu_subtype
= AMDFAM15H_BDVER3
;
162 /* AMD Family 16h "btver2" */
164 __cpu_model
.__cpu_type
= AMD_BTVER2
;
171 /* Get the specific type of Intel CPU. */
174 get_intel_cpu (unsigned int family
, unsigned int model
, unsigned int brand_id
)
176 /* Parse family and model only if brand ID is 0. */
190 __cpu_model
.__cpu_type
= INTEL_BONNELL
;
195 __cpu_model
.__cpu_type
= INTEL_SILVERMONT
;
202 __cpu_model
.__cpu_type
= INTEL_COREI7
;
203 __cpu_model
.__cpu_subtype
= INTEL_COREI7_NEHALEM
;
209 __cpu_model
.__cpu_type
= INTEL_COREI7
;
210 __cpu_model
.__cpu_subtype
= INTEL_COREI7_WESTMERE
;
215 __cpu_model
.__cpu_type
= INTEL_COREI7
;
216 __cpu_model
.__cpu_subtype
= INTEL_COREI7_SANDYBRIDGE
;
221 __cpu_model
.__cpu_type
= INTEL_COREI7
;
222 __cpu_model
.__cpu_subtype
= INTEL_COREI7_IVYBRIDGE
;
228 __cpu_model
.__cpu_type
= INTEL_COREI7
;
229 __cpu_model
.__cpu_subtype
= INTEL_COREI7_HASWELL
;
236 __cpu_model
.__cpu_type
= INTEL_CORE2
;
243 /* We have no idea. */
249 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
250 the max possible level of CPUID insn. */
252 get_available_features (unsigned int ecx
, unsigned int edx
,
255 unsigned int features
= 0;
258 features
|= (1 << FEATURE_CMOV
);
260 features
|= (1 << FEATURE_MMX
);
262 features
|= (1 << FEATURE_SSE
);
264 features
|= (1 << FEATURE_SSE2
);
265 if (ecx
& bit_POPCNT
)
266 features
|= (1 << FEATURE_POPCNT
);
268 features
|= (1 << FEATURE_SSE3
);
270 features
|= (1 << FEATURE_SSSE3
);
271 if (ecx
& bit_SSE4_1
)
272 features
|= (1 << FEATURE_SSE4_1
);
273 if (ecx
& bit_SSE4_2
)
274 features
|= (1 << FEATURE_SSE4_2
);
276 features
|= (1 << FEATURE_AVX
);
278 features
|= (1 << FEATURE_FMA
);
280 /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
281 if (max_cpuid_level
>= 7)
283 unsigned int eax
, ebx
, ecx
, edx
;
284 __cpuid_count (7, 0, eax
, ebx
, ecx
, edx
);
286 features
|= (1 << FEATURE_AVX2
);
289 unsigned int ext_level
;
290 unsigned int eax
, ebx
;
291 /* Check cpuid level of extended features. */
292 __cpuid (0x80000000, ext_level
, ebx
, ecx
, edx
);
294 if (ext_level
> 0x80000000)
296 __cpuid (0x80000001, eax
, ebx
, ecx
, edx
);
299 features
|= (1 << FEATURE_SSE4_A
);
301 features
|= (1 << FEATURE_FMA4
);
303 features
|= (1 << FEATURE_XOP
);
306 __cpu_model
.__cpu_features
[0] = features
;
309 /* A noinline function calling __get_cpuid. Having many calls to
310 cpuid in one function in 32-bit mode causes GCC to complain:
311 "can't find a register in class CLOBBERED_REGS". This is
312 related to PR rtl-optimization 44174. */
314 static int __attribute__ ((noinline
))
315 __get_cpuid_output (unsigned int __level
,
316 unsigned int *__eax
, unsigned int *__ebx
,
317 unsigned int *__ecx
, unsigned int *__edx
)
319 return __get_cpuid (__level
, __eax
, __ebx
, __ecx
, __edx
);
323 /* A constructor function that is sets __cpu_model and __cpu_features with
324 the right values. This needs to run only once. This constructor is
325 given the highest priority and it should run before constructors without
326 the priority set. However, it still runs after ifunc initializers and
327 needs to be called explicitly there. */
329 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY
))
331 __attribute__ ((visibility("hidden")))
333 __cpu_indicator_init (void)
335 unsigned int eax
, ebx
, ecx
, edx
;
339 unsigned int model
, family
, brand_id
;
340 unsigned int extended_model
, extended_family
;
342 /* This function needs to run just once. */
343 if (__cpu_model
.__cpu_vendor
)
346 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
347 if (!__get_cpuid_output (0, &eax
, &ebx
, &ecx
, &edx
))
349 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
358 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
362 if (!__get_cpuid_output (1, &eax
, &ebx
, &ecx
, &edx
))
364 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
368 model
= (eax
>> 4) & 0x0f;
369 family
= (eax
>> 8) & 0x0f;
370 brand_id
= ebx
& 0xff;
371 extended_model
= (eax
>> 12) & 0xf0;
372 extended_family
= (eax
>> 20) & 0xff;
374 if (vendor
== signature_INTEL_ebx
)
376 /* Adjust model and family for Intel CPUS. */
379 family
+= extended_family
;
380 model
+= extended_model
;
382 else if (family
== 0x06)
383 model
+= extended_model
;
386 get_intel_cpu (family
, model
, brand_id
);
387 /* Find available features. */
388 get_available_features (ecx
, edx
, max_level
);
389 __cpu_model
.__cpu_vendor
= VENDOR_INTEL
;
391 else if (vendor
== signature_AMD_ebx
)
393 /* Adjust model and family for AMD CPUS. */
396 family
+= extended_family
;
397 model
+= (extended_model
<< 4);
401 get_amd_cpu (family
, model
);
402 /* Find available features. */
403 get_available_features (ecx
, edx
, max_level
);
404 __cpu_model
.__cpu_vendor
= VENDOR_AMD
;
407 __cpu_model
.__cpu_vendor
= VENDOR_OTHER
;
409 gcc_assert (__cpu_model
.__cpu_vendor
< VENDOR_MAX
);
410 gcc_assert (__cpu_model
.__cpu_type
< CPU_TYPE_MAX
);
411 gcc_assert (__cpu_model
.__cpu_subtype
< CPU_SUBTYPE_MAX
);
416 #if defined SHARED && defined USE_ELF_SYMVER
417 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
418 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");