* Force symbol __cpu_model to be hidden in libgcc.a. Trunk
[official-gcc.git] / gcc-4_9 / libgcc / config / i386 / cpuinfo.c
blob3cfda02709757a95ee2b8421529a7ae543d0af56
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
10 version.
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
15 for more details.
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/>. */
26 #include "cpuid.h"
27 #include "tsystem.h"
28 #include "auto-target.h"
30 #ifdef HAVE_INIT_PRIORITY
31 #define CONSTRUCTOR_PRIORITY (101)
32 #else
33 #define CONSTRUCTOR_PRIORITY
34 #endif
36 int __cpu_indicator_init (void)
37 #if !defined(SHARED)
38 __attribute__ ((visibility("hidden")))
39 #endif
40 __attribute__ ((constructor CONSTRUCTOR_PRIORITY));
42 /* Processor Vendor and Models. */
44 enum processor_vendor
46 VENDOR_INTEL = 1,
47 VENDOR_AMD,
48 VENDOR_OTHER,
49 VENDOR_MAX
52 /* Any new types or subtypes have to be inserted at the end. */
54 enum processor_types
56 INTEL_BONNELL = 1,
57 INTEL_CORE2,
58 INTEL_COREI7,
59 AMDFAM10H,
60 AMDFAM15H,
61 INTEL_SILVERMONT,
62 AMD_BTVER1,
63 AMD_BTVER2,
64 CPU_TYPE_MAX
67 enum processor_subtypes
69 INTEL_COREI7_NEHALEM = 1,
70 INTEL_COREI7_WESTMERE,
71 INTEL_COREI7_SANDYBRIDGE,
72 AMDFAM10H_BARCELONA,
73 AMDFAM10H_SHANGHAI,
74 AMDFAM10H_ISTANBUL,
75 AMDFAM15H_BDVER1,
76 AMDFAM15H_BDVER2,
77 AMDFAM15H_BDVER3,
78 AMDFAM15H_BDVER4,
79 INTEL_COREI7_IVYBRIDGE,
80 INTEL_COREI7_HASWELL,
81 CPU_SUBTYPE_MAX
84 /* ISA Features supported. */
86 enum processor_features
88 FEATURE_CMOV = 0,
89 FEATURE_MMX,
90 FEATURE_POPCNT,
91 FEATURE_SSE,
92 FEATURE_SSE2,
93 FEATURE_SSE3,
94 FEATURE_SSSE3,
95 FEATURE_SSE4_1,
96 FEATURE_SSE4_2,
97 FEATURE_AVX,
98 FEATURE_AVX2,
99 FEATURE_SSE4_A,
100 FEATURE_FMA4,
101 FEATURE_XOP,
102 FEATURE_FMA
105 #if !defined(SHARED)
106 __attribute__ ((visibility("hidden")))
107 #endif
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];
114 } __cpu_model = { };
117 /* Get the specific type of AMD CPU. */
119 static void
120 get_amd_cpu (unsigned int family, unsigned int model)
122 switch (family)
124 /* AMD Family 10h. */
125 case 0x10:
126 __cpu_model.__cpu_type = AMDFAM10H;
127 switch (model)
129 case 0x2:
130 /* Barcelona. */
131 __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
132 break;
133 case 0x4:
134 /* Shanghai. */
135 __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
136 break;
137 case 0x8:
138 /* Istanbul. */
139 __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
140 break;
141 default:
142 break;
144 break;
145 /* AMD Family 14h "btver1". */
146 case 0x14:
147 __cpu_model.__cpu_type = AMD_BTVER1;
148 break;
149 /* AMD Family 15h "Bulldozer". */
150 case 0x15:
151 __cpu_model.__cpu_type = AMDFAM15H;
152 /* Bulldozer version 1. */
153 if ( model <= 0xf)
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;
161 break;
162 /* AMD Family 16h "btver2" */
163 case 0x16:
164 __cpu_model.__cpu_type = AMD_BTVER2;
165 break;
166 default:
167 break;
171 /* Get the specific type of Intel CPU. */
173 static void
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. */
177 if (brand_id == 0)
179 switch (family)
181 case 0x5:
182 /* Pentium. */
183 break;
184 case 0x6:
185 switch (model)
187 case 0x1c:
188 case 0x26:
189 /* Bonnell. */
190 __cpu_model.__cpu_type = INTEL_BONNELL;
191 break;
192 case 0x37:
193 case 0x4d:
194 /* Silvermont. */
195 __cpu_model.__cpu_type = INTEL_SILVERMONT;
196 break;
197 case 0x1a:
198 case 0x1e:
199 case 0x1f:
200 case 0x2e:
201 /* Nehalem. */
202 __cpu_model.__cpu_type = INTEL_COREI7;
203 __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
204 break;
205 case 0x25:
206 case 0x2c:
207 case 0x2f:
208 /* Westmere. */
209 __cpu_model.__cpu_type = INTEL_COREI7;
210 __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
211 break;
212 case 0x2a:
213 case 0x2d:
214 /* Sandy Bridge. */
215 __cpu_model.__cpu_type = INTEL_COREI7;
216 __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
217 break;
218 case 0x3a:
219 case 0x3e:
220 /* Ivy Bridge. */
221 __cpu_model.__cpu_type = INTEL_COREI7;
222 __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
223 break;
224 case 0x3c:
225 case 0x45:
226 case 0x46:
227 /* Haswell. */
228 __cpu_model.__cpu_type = INTEL_COREI7;
229 __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
230 break;
231 case 0x17:
232 case 0x1d:
233 /* Penryn. */
234 case 0x0f:
235 /* Merom. */
236 __cpu_model.__cpu_type = INTEL_CORE2;
237 break;
238 default:
239 break;
241 break;
242 default:
243 /* We have no idea. */
244 break;
249 /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
250 the max possible level of CPUID insn. */
251 static void
252 get_available_features (unsigned int ecx, unsigned int edx,
253 int max_cpuid_level)
255 unsigned int features = 0;
257 if (edx & bit_CMOV)
258 features |= (1 << FEATURE_CMOV);
259 if (edx & bit_MMX)
260 features |= (1 << FEATURE_MMX);
261 if (edx & bit_SSE)
262 features |= (1 << FEATURE_SSE);
263 if (edx & bit_SSE2)
264 features |= (1 << FEATURE_SSE2);
265 if (ecx & bit_POPCNT)
266 features |= (1 << FEATURE_POPCNT);
267 if (ecx & bit_SSE3)
268 features |= (1 << FEATURE_SSE3);
269 if (ecx & bit_SSSE3)
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);
275 if (ecx & bit_AVX)
276 features |= (1 << FEATURE_AVX);
277 if (ecx & bit_FMA)
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);
285 if (ebx & bit_AVX2)
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);
298 if (ecx & bit_SSE4a)
299 features |= (1 << FEATURE_SSE4_A);
300 if (ecx & bit_FMA4)
301 features |= (1 << FEATURE_FMA4);
302 if (ecx & bit_XOP)
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))
330 #if !defined(SHARED)
331 __attribute__ ((visibility("hidden")))
332 #endif
333 __cpu_indicator_init (void)
335 unsigned int eax, ebx, ecx, edx;
337 int max_level = 5;
338 unsigned int vendor;
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)
344 return 0;
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;
350 return -1;
353 vendor = ebx;
354 max_level = eax;
356 if (max_level < 1)
358 __cpu_model.__cpu_vendor = VENDOR_OTHER;
359 return -1;
362 if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx))
364 __cpu_model.__cpu_vendor = VENDOR_OTHER;
365 return -1;
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. */
377 if (family == 0x0f)
379 family += extended_family;
380 model += extended_model;
382 else if (family == 0x06)
383 model += extended_model;
385 /* Get CPU type. */
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. */
394 if (family == 0x0f)
396 family += extended_family;
397 model += (extended_model << 4);
400 /* Get CPU type. */
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;
406 else
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);
413 return 0;
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");
419 #endif