9e9156b9a14b430c4ed36084293e708ab4f4055f
[platform/upstream/gcc.git] / libgcc / config / i386 / cpuinfo.c
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)
4
5 This file is part of GCC.
6
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.
11
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.
16
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.
20
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/>.  */
25
26 #include "cpuid.h"
27 #include "tsystem.h"
28 #include "auto-target.h"
29 #include "cpuinfo.h"
30
31 #ifdef HAVE_INIT_PRIORITY
32 #define CONSTRUCTOR_PRIORITY (101)
33 #else
34 #define CONSTRUCTOR_PRIORITY
35 #endif
36
37 int __cpu_indicator_init (void)
38   __attribute__ ((constructor CONSTRUCTOR_PRIORITY));
39
40
41 struct __processor_model __cpu_model = { };
42
43
44 /* Get the specific type of AMD CPU.  */
45
46 static void
47 get_amd_cpu (unsigned int family, unsigned int model)
48 {
49   switch (family)
50     {
51     /* AMD Family 10h.  */
52     case 0x10:
53       __cpu_model.__cpu_type = AMDFAM10H;
54       switch (model)
55         {
56         case 0x2:
57           /* Barcelona.  */
58           __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
59           break;
60         case 0x4:
61           /* Shanghai.  */
62           __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
63           break;
64         case 0x8:
65           /* Istanbul.  */
66           __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
67           break;
68         default:
69           break;
70         }
71       break;
72     /* AMD Family 14h "btver1". */
73     case 0x14:
74       __cpu_model.__cpu_type = AMD_BTVER1;
75       break;
76     /* AMD Family 15h "Bulldozer".  */
77     case 0x15:
78       __cpu_model.__cpu_type = AMDFAM15H;
79       /* Bulldozer version 1.  */
80       if ( model <= 0xf)
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;
91       break;
92     /* AMD Family 16h "btver2" */
93     case 0x16:
94       __cpu_model.__cpu_type = AMD_BTVER2;
95       break;
96     case 0x17:
97       __cpu_model.__cpu_type = AMDFAM17H;
98       /* AMD family 17h version 1.  */
99       if (model <= 0x1f)
100         __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
101       break;
102     default:
103       break;
104     }
105 }
106
107 /* Get the specific type of Intel CPU.  */
108
109 static void
110 get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
111 {
112   /* Parse family and model only if brand ID is 0. */
113   if (brand_id == 0)
114     {
115       switch (family)
116         {
117         case 0x5:
118           /* Pentium.  */
119           break;
120         case 0x6:
121           switch (model)
122             {
123             case 0x1c:
124             case 0x26:
125               /* Bonnell.  */
126               __cpu_model.__cpu_type = INTEL_BONNELL;
127               break;
128             case 0x37:
129             case 0x4a:
130             case 0x4d:
131             case 0x5a:
132             case 0x5d:
133               /* Silvermont.  */
134               __cpu_model.__cpu_type = INTEL_SILVERMONT;
135               break;
136             case 0x57:
137               /* Knights Landing.  */
138               __cpu_model.__cpu_type = INTEL_KNL;
139               break;
140             case 0x1a:
141             case 0x1e:
142             case 0x1f:
143             case 0x2e:
144               /* Nehalem.  */
145               __cpu_model.__cpu_type = INTEL_COREI7;
146               __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
147               break;
148             case 0x25:
149             case 0x2c:
150             case 0x2f:
151               /* Westmere.  */
152               __cpu_model.__cpu_type = INTEL_COREI7;
153               __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
154               break;
155             case 0x2a:
156             case 0x2d:
157               /* Sandy Bridge.  */
158               __cpu_model.__cpu_type = INTEL_COREI7;
159               __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
160               break;
161             case 0x3a:
162             case 0x3e:
163               /* Ivy Bridge.  */
164               __cpu_model.__cpu_type = INTEL_COREI7;
165               __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
166               break;
167             case 0x3c:
168             case 0x3f:
169             case 0x45:
170             case 0x46:
171               /* Haswell.  */
172               __cpu_model.__cpu_type = INTEL_COREI7;
173               __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
174               break;
175             case 0x3d:
176             case 0x47:
177             case 0x4f:
178             case 0x56:
179               /* Broadwell.  */
180               __cpu_model.__cpu_type = INTEL_COREI7;
181               __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
182               break;
183             case 0x4e:
184             case 0x5e:
185               /* Skylake.  */
186               __cpu_model.__cpu_type = INTEL_COREI7;
187               __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
188               break;
189             case 0x55:
190               /* Skylake with AVX-512 support.  */
191               __cpu_model.__cpu_type = INTEL_COREI7;
192               __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
193               break;
194             case 0x17:
195             case 0x1d:
196               /* Penryn.  */
197             case 0x0f:
198               /* Merom.  */
199               __cpu_model.__cpu_type = INTEL_CORE2;
200               break;
201             default:
202               break;
203             }
204           break;
205         default:
206           /* We have no idea.  */
207           break;
208         }
209     }
210 }                       
211
212 /* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
213    the max possible level of CPUID insn.  */
214 static void
215 get_available_features (unsigned int ecx, unsigned int edx,
216                         int max_cpuid_level)
217 {
218   unsigned int features = 0;
219
220   if (edx & bit_CMOV)
221     features |= (1 << FEATURE_CMOV);
222   if (edx & bit_MMX)
223     features |= (1 << FEATURE_MMX);
224   if (edx & bit_SSE)
225     features |= (1 << FEATURE_SSE);
226   if (edx & bit_SSE2)
227     features |= (1 << FEATURE_SSE2);
228   if (ecx & bit_POPCNT)
229     features |= (1 << FEATURE_POPCNT);
230   if (ecx & bit_AES)
231     features |= (1 << FEATURE_AES);
232   if (ecx & bit_PCLMUL)
233     features |= (1 << FEATURE_PCLMUL);
234   if (ecx & bit_SSE3)
235     features |= (1 << FEATURE_SSE3);
236   if (ecx & bit_SSSE3)
237     features |= (1 << FEATURE_SSSE3);
238   if (ecx & bit_SSE4_1)
239     features |= (1 << FEATURE_SSE4_1);
240   if (ecx & bit_SSE4_2)
241     features |= (1 << FEATURE_SSE4_2);
242   if (ecx & bit_AVX)
243     features |= (1 << FEATURE_AVX);
244   if (ecx & bit_FMA)
245     features |= (1 << FEATURE_FMA);
246
247   /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
248   if (max_cpuid_level >= 7)
249     {
250       unsigned int eax, ebx, ecx, edx;
251       __cpuid_count (7, 0, eax, ebx, ecx, edx);
252       if (ebx & bit_BMI)
253         features |= (1 << FEATURE_BMI);
254       if (ebx & bit_AVX2)
255         features |= (1 << FEATURE_AVX2);
256       if (ebx & bit_BMI2)
257         features |= (1 << FEATURE_BMI2);
258       if (ebx & bit_AVX512F)
259         features |= (1 << FEATURE_AVX512F);
260       if (ebx & bit_AVX512VL)
261         features |= (1 << FEATURE_AVX512VL);
262       if (ebx & bit_AVX512BW)
263         features |= (1 << FEATURE_AVX512BW);
264       if (ebx & bit_AVX512DQ)
265         features |= (1 << FEATURE_AVX512DQ);
266       if (ebx & bit_AVX512CD)
267         features |= (1 << FEATURE_AVX512CD);
268       if (ebx & bit_AVX512PF)
269         features |= (1 << FEATURE_AVX512PF);
270       if (ebx & bit_AVX512ER)
271         features |= (1 << FEATURE_AVX512ER);
272       if (ebx & bit_AVX512IFMA)
273         features |= (1 << FEATURE_AVX512IFMA);
274       if (ecx & bit_AVX512VBMI)
275         features |= (1 << FEATURE_AVX512VBMI);
276       if (edx & bit_AVX5124VNNIW)
277         features |= (1 << FEATURE_AVX5124VNNIW);
278       if (edx & bit_AVX5124FMAPS)
279         features |= (1 << FEATURE_AVX5124FMAPS);
280     }
281
282   unsigned int ext_level;
283   unsigned int eax, ebx;
284   /* Check cpuid level of extended features.  */
285   __cpuid (0x80000000, ext_level, ebx, ecx, edx);
286
287   if (ext_level > 0x80000000)
288     {
289       __cpuid (0x80000001, eax, ebx, ecx, edx);
290
291       if (ecx & bit_SSE4a)
292         features |= (1 << FEATURE_SSE4_A);
293       if (ecx & bit_FMA4)
294         features |= (1 << FEATURE_FMA4);
295       if (ecx & bit_XOP)
296         features |= (1 << FEATURE_XOP);
297     }
298     
299   __cpu_model.__cpu_features[0] = features;
300 }
301
302 /* A constructor function that is sets __cpu_model and __cpu_features with
303    the right values.  This needs to run only once.  This constructor is
304    given the highest priority and it should run before constructors without
305    the priority set.  However, it still runs after ifunc initializers and
306    needs to be called explicitly there.  */
307
308 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
309 __cpu_indicator_init (void)
310 {
311   unsigned int eax, ebx, ecx, edx;
312
313   int max_level;
314   unsigned int vendor;
315   unsigned int model, family, brand_id;
316   unsigned int extended_model, extended_family;
317
318   /* This function needs to run just once.  */
319   if (__cpu_model.__cpu_vendor)
320     return 0;
321
322   /* Assume cpuid insn present. Run in level 0 to get vendor id. */
323   if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
324     {
325       __cpu_model.__cpu_vendor = VENDOR_OTHER;
326       return -1;
327     }
328
329   vendor = ebx;
330   max_level = eax;
331
332   if (max_level < 1)
333     {
334       __cpu_model.__cpu_vendor = VENDOR_OTHER;
335       return -1;
336     }
337
338   if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
339     {
340       __cpu_model.__cpu_vendor = VENDOR_OTHER;
341       return -1;
342     }
343
344   model = (eax >> 4) & 0x0f;
345   family = (eax >> 8) & 0x0f;
346   brand_id = ebx & 0xff;
347   extended_model = (eax >> 12) & 0xf0;
348   extended_family = (eax >> 20) & 0xff;
349
350   if (vendor == signature_INTEL_ebx)
351     {
352       /* Adjust model and family for Intel CPUS. */
353       if (family == 0x0f)
354         {
355           family += extended_family;
356           model += extended_model;
357         }
358       else if (family == 0x06)
359         model += extended_model;
360
361       /* Get CPU type.  */
362       get_intel_cpu (family, model, brand_id);
363       /* Find available features. */
364       get_available_features (ecx, edx, max_level);
365       __cpu_model.__cpu_vendor = VENDOR_INTEL;
366     }
367   else if (vendor == signature_AMD_ebx)
368     {
369       /* Adjust model and family for AMD CPUS. */
370       if (family == 0x0f)
371         {
372           family += extended_family;
373           model += extended_model;
374         }
375
376       /* Get CPU type.  */
377       get_amd_cpu (family, model);
378       /* Find available features. */
379       get_available_features (ecx, edx, max_level);
380       __cpu_model.__cpu_vendor = VENDOR_AMD;
381     }
382   else
383     __cpu_model.__cpu_vendor = VENDOR_OTHER;
384
385   gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
386   gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
387   gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
388
389   return 0;
390 }
391
392 #if defined SHARED && defined USE_ELF_SYMVER
393 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
394 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");
395 #endif