Update gcc-50 to SVN version 231263 (gcc-5-branch)
[dragonfly.git] / contrib / gcc-5.0 / libgcc / config / i386 / cpuinfo.c
1 /* Get CPU type and Features for x86 processors.
2    Copyright (C) 2012-2015 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
30 #ifdef HAVE_INIT_PRIORITY
31 #define CONSTRUCTOR_PRIORITY (101)
32 #else
33 #define CONSTRUCTOR_PRIORITY
34 #endif
35
36 int __cpu_indicator_init (void)
37   __attribute__ ((constructor CONSTRUCTOR_PRIORITY));
38
39 /* Processor Vendor and Models. */
40
41 enum processor_vendor
42 {
43   VENDOR_INTEL = 1,
44   VENDOR_AMD,
45   VENDOR_OTHER,
46   VENDOR_MAX
47 };
48
49 /* Any new types or subtypes have to be inserted at the end. */
50
51 enum processor_types
52 {
53   INTEL_BONNELL = 1,
54   INTEL_CORE2,
55   INTEL_COREI7,
56   AMDFAM10H,
57   AMDFAM15H,
58   INTEL_SILVERMONT,
59   AMD_BTVER1,
60   AMD_BTVER2,  
61   CPU_TYPE_MAX
62 };
63
64 enum processor_subtypes
65 {
66   INTEL_COREI7_NEHALEM = 1,
67   INTEL_COREI7_WESTMERE,
68   INTEL_COREI7_SANDYBRIDGE,
69   AMDFAM10H_BARCELONA,
70   AMDFAM10H_SHANGHAI,
71   AMDFAM10H_ISTANBUL,
72   AMDFAM15H_BDVER1,
73   AMDFAM15H_BDVER2,
74   AMDFAM15H_BDVER3,
75   AMDFAM15H_BDVER4,
76   INTEL_COREI7_IVYBRIDGE,
77   INTEL_COREI7_HASWELL,
78   INTEL_COREI7_BROADWELL,
79   CPU_SUBTYPE_MAX
80 };
81
82 /* ISA Features supported. */
83
84 enum processor_features
85 {
86   FEATURE_CMOV = 0,
87   FEATURE_MMX,
88   FEATURE_POPCNT,
89   FEATURE_SSE,
90   FEATURE_SSE2,
91   FEATURE_SSE3,
92   FEATURE_SSSE3,
93   FEATURE_SSE4_1,
94   FEATURE_SSE4_2,
95   FEATURE_AVX,
96   FEATURE_AVX2,
97   FEATURE_SSE4_A,
98   FEATURE_FMA4,
99   FEATURE_XOP,
100   FEATURE_FMA,
101   FEATURE_AVX512F,
102   FEATURE_BMI,
103   FEATURE_BMI2
104 };
105
106 struct __processor_model
107 {
108   unsigned int __cpu_vendor;
109   unsigned int __cpu_type;
110   unsigned int __cpu_subtype;
111   unsigned int __cpu_features[1];
112 } __cpu_model;
113
114
115 /* Get the specific type of AMD CPU.  */
116
117 static void
118 get_amd_cpu (unsigned int family, unsigned int model)
119 {
120   switch (family)
121     {
122     /* AMD Family 10h.  */
123     case 0x10:
124       __cpu_model.__cpu_type = AMDFAM10H;
125       switch (model)
126         {
127         case 0x2:
128           /* Barcelona.  */
129           __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
130           break;
131         case 0x4:
132           /* Shanghai.  */
133           __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
134           break;
135         case 0x8:
136           /* Istanbul.  */
137           __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
138           break;
139         default:
140           break;
141         }
142       break;
143     /* AMD Family 14h "btver1". */
144     case 0x14:
145       __cpu_model.__cpu_type = AMD_BTVER1;
146       break;
147     /* AMD Family 15h "Bulldozer".  */
148     case 0x15:
149       __cpu_model.__cpu_type = AMDFAM15H;
150       /* Bulldozer version 1.  */
151       if ( model <= 0xf)
152         __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
153       /* Bulldozer version 2 "Piledriver" */
154       if (model >= 0x10 && model <= 0x2f)
155         __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
156       /* Bulldozer version 3 "Steamroller"  */
157       if (model >= 0x30 && model <= 0x4f)
158         __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
159       /* Bulldozer version 4 "Excavator"   */
160       if (model >= 0x60 && model <= 0x7f)
161         __cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
162       break;
163     /* AMD Family 16h "btver2" */
164     case 0x16:
165       __cpu_model.__cpu_type = AMD_BTVER2;
166       break;
167     default:
168       break;
169     }
170 }
171
172 /* Get the specific type of Intel CPU.  */
173
174 static void
175 get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
176 {
177   /* Parse family and model only if brand ID is 0. */
178   if (brand_id == 0)
179     {
180       switch (family)
181         {
182         case 0x5:
183           /* Pentium.  */
184           break;
185         case 0x6:
186           switch (model)
187             {
188             case 0x1c:
189             case 0x26:
190               /* Bonnell.  */
191               __cpu_model.__cpu_type = INTEL_BONNELL;
192               break;
193             case 0x37:
194             case 0x4a:
195             case 0x4d:
196             case 0x5a:
197             case 0x5d:
198               /* Silvermont.  */
199               __cpu_model.__cpu_type = INTEL_SILVERMONT;
200               break;
201             case 0x1a:
202             case 0x1e:
203             case 0x1f:
204             case 0x2e:
205               /* Nehalem.  */
206               __cpu_model.__cpu_type = INTEL_COREI7;
207               __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
208               break;
209             case 0x25:
210             case 0x2c:
211             case 0x2f:
212               /* Westmere.  */
213               __cpu_model.__cpu_type = INTEL_COREI7;
214               __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
215               break;
216             case 0x2a:
217             case 0x2d:
218               /* Sandy Bridge.  */
219               __cpu_model.__cpu_type = INTEL_COREI7;
220               __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
221               break;
222             case 0x3a:
223             case 0x3e:
224               /* Ivy Bridge.  */
225               __cpu_model.__cpu_type = INTEL_COREI7;
226               __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
227               break;
228             case 0x3c:
229             case 0x3f:
230             case 0x45:
231             case 0x46:
232               /* Haswell.  */
233               __cpu_model.__cpu_type = INTEL_COREI7;
234               __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
235               break;
236             case 0x3d:
237             case 0x4f:
238             case 0x56:
239               /* Broadwell.  */
240               __cpu_model.__cpu_type = INTEL_COREI7;
241               __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
242               break;
243             case 0x17:
244             case 0x1d:
245               /* Penryn.  */
246             case 0x0f:
247               /* Merom.  */
248               __cpu_model.__cpu_type = INTEL_CORE2;
249               break;
250             default:
251               break;
252             }
253           break;
254         default:
255           /* We have no idea.  */
256           break;
257         }
258     }
259 }                       
260
261 /* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
262    the max possible level of CPUID insn.  */
263 static void
264 get_available_features (unsigned int ecx, unsigned int edx,
265                         int max_cpuid_level)
266 {
267   unsigned int features = 0;
268
269   if (edx & bit_CMOV)
270     features |= (1 << FEATURE_CMOV);
271   if (edx & bit_MMX)
272     features |= (1 << FEATURE_MMX);
273   if (edx & bit_SSE)
274     features |= (1 << FEATURE_SSE);
275   if (edx & bit_SSE2)
276     features |= (1 << FEATURE_SSE2);
277   if (ecx & bit_POPCNT)
278     features |= (1 << FEATURE_POPCNT);
279   if (ecx & bit_SSE3)
280     features |= (1 << FEATURE_SSE3);
281   if (ecx & bit_SSSE3)
282     features |= (1 << FEATURE_SSSE3);
283   if (ecx & bit_SSE4_1)
284     features |= (1 << FEATURE_SSE4_1);
285   if (ecx & bit_SSE4_2)
286     features |= (1 << FEATURE_SSE4_2);
287   if (ecx & bit_AVX)
288     features |= (1 << FEATURE_AVX);
289   if (ecx & bit_FMA)
290     features |= (1 << FEATURE_FMA);
291
292   /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
293   if (max_cpuid_level >= 7)
294     {
295       unsigned int eax, ebx, ecx, edx;
296       __cpuid_count (7, 0, eax, ebx, ecx, edx);
297       if (ebx & bit_BMI)
298         features |= (1 << FEATURE_BMI);
299       if (ebx & bit_AVX2)
300         features |= (1 << FEATURE_AVX2);
301       if (ebx & bit_BMI2)
302         features |= (1 << FEATURE_BMI2);
303       if (ebx & bit_AVX512F)
304         features |= (1 << FEATURE_AVX512F);
305     }
306
307   unsigned int ext_level;
308   unsigned int eax, ebx;
309   /* Check cpuid level of extended features.  */
310   __cpuid (0x80000000, ext_level, ebx, ecx, edx);
311
312   if (ext_level > 0x80000000)
313     {
314       __cpuid (0x80000001, eax, ebx, ecx, edx);
315
316       if (ecx & bit_SSE4a)
317         features |= (1 << FEATURE_SSE4_A);
318       if (ecx & bit_FMA4)
319         features |= (1 << FEATURE_FMA4);
320       if (ecx & bit_XOP)
321         features |= (1 << FEATURE_XOP);
322     }
323     
324   __cpu_model.__cpu_features[0] = features;
325 }
326
327 /* A noinline function calling __get_cpuid. Having many calls to
328    cpuid in one function in 32-bit mode causes GCC to complain:
329    "can't find a register in class CLOBBERED_REGS".  This is
330    related to PR rtl-optimization 44174. */
331
332 static int __attribute__ ((noinline))
333 __get_cpuid_output (unsigned int __level,
334                     unsigned int *__eax, unsigned int *__ebx,
335                     unsigned int *__ecx, unsigned int *__edx)
336 {
337   return __get_cpuid (__level, __eax, __ebx, __ecx, __edx);
338 }
339
340
341 /* A constructor function that is sets __cpu_model and __cpu_features with
342    the right values.  This needs to run only once.  This constructor is
343    given the highest priority and it should run before constructors without
344    the priority set.  However, it still runs after ifunc initializers and
345    needs to be called explicitly there.  */
346
347 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
348 __cpu_indicator_init (void)
349 {
350   unsigned int eax, ebx, ecx, edx;
351
352   int max_level = 5;
353   unsigned int vendor;
354   unsigned int model, family, brand_id;
355   unsigned int extended_model, extended_family;
356
357   /* This function needs to run just once.  */
358   if (__cpu_model.__cpu_vendor)
359     return 0;
360
361   /* Assume cpuid insn present. Run in level 0 to get vendor id. */
362   if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx))
363     {
364       __cpu_model.__cpu_vendor = VENDOR_OTHER;
365       return -1;
366     }
367
368   vendor = ebx;
369   max_level = eax;
370
371   if (max_level < 1)
372     {
373       __cpu_model.__cpu_vendor = VENDOR_OTHER;
374       return -1;
375     }
376
377   if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx))
378     {
379       __cpu_model.__cpu_vendor = VENDOR_OTHER;
380       return -1;
381     }
382
383   model = (eax >> 4) & 0x0f;
384   family = (eax >> 8) & 0x0f;
385   brand_id = ebx & 0xff;
386   extended_model = (eax >> 12) & 0xf0;
387   extended_family = (eax >> 20) & 0xff;
388
389   if (vendor == signature_INTEL_ebx)
390     {
391       /* Adjust model and family for Intel CPUS. */
392       if (family == 0x0f)
393         {
394           family += extended_family;
395           model += extended_model;
396         }
397       else if (family == 0x06)
398         model += extended_model;
399
400       /* Get CPU type.  */
401       get_intel_cpu (family, model, brand_id);
402       /* Find available features. */
403       get_available_features (ecx, edx, max_level);
404       __cpu_model.__cpu_vendor = VENDOR_INTEL;
405     }
406   else if (vendor == signature_AMD_ebx)
407     {
408       /* Adjust model and family for AMD CPUS. */
409       if (family == 0x0f)
410         {
411           family += extended_family;
412           model += extended_model;
413         }
414
415       /* Get CPU type.  */
416       get_amd_cpu (family, model);
417       /* Find available features. */
418       get_available_features (ecx, edx, max_level);
419       __cpu_model.__cpu_vendor = VENDOR_AMD;
420     }
421   else
422     __cpu_model.__cpu_vendor = VENDOR_OTHER;
423
424   gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
425   gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
426   gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
427
428   return 0;
429 }