cpuinfo.c revision 1.1.1.3
1/* Get CPU type and Features for x86 processors.
2   Copyright (C) 2012-2016 Free Software Foundation, Inc.
3   Contributed by Sriraman Tallam (tmsriram@google.com)
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see 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
36int __cpu_indicator_init (void)
37  __attribute__ ((constructor CONSTRUCTOR_PRIORITY));
38
39/* Processor Vendor and Models. */
40
41enum 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
51enum processor_types
52{
53  INTEL_BONNELL = 1,
54  INTEL_CORE2,
55  INTEL_COREI7,
56  AMDFAM10H,
57  AMDFAM15H,
58  INTEL_SILVERMONT,
59  INTEL_KNL,
60  AMD_BTVER1,
61  AMD_BTVER2,
62  AMDFAM17H,
63  CPU_TYPE_MAX
64};
65
66enum processor_subtypes
67{
68  INTEL_COREI7_NEHALEM = 1,
69  INTEL_COREI7_WESTMERE,
70  INTEL_COREI7_SANDYBRIDGE,
71  AMDFAM10H_BARCELONA,
72  AMDFAM10H_SHANGHAI,
73  AMDFAM10H_ISTANBUL,
74  AMDFAM15H_BDVER1,
75  AMDFAM15H_BDVER2,
76  AMDFAM15H_BDVER3,
77  AMDFAM15H_BDVER4,
78  AMDFAM17H_ZNVER1,
79  INTEL_COREI7_IVYBRIDGE,
80  INTEL_COREI7_HASWELL,
81  INTEL_COREI7_BROADWELL,
82  INTEL_COREI7_SKYLAKE,
83  INTEL_COREI7_SKYLAKE_AVX512,
84  CPU_SUBTYPE_MAX
85};
86
87/* ISA Features supported. New features have to be inserted at the end.  */
88
89enum processor_features
90{
91  FEATURE_CMOV = 0,
92  FEATURE_MMX,
93  FEATURE_POPCNT,
94  FEATURE_SSE,
95  FEATURE_SSE2,
96  FEATURE_SSE3,
97  FEATURE_SSSE3,
98  FEATURE_SSE4_1,
99  FEATURE_SSE4_2,
100  FEATURE_AVX,
101  FEATURE_AVX2,
102  FEATURE_SSE4_A,
103  FEATURE_FMA4,
104  FEATURE_XOP,
105  FEATURE_FMA,
106  FEATURE_AVX512F,
107  FEATURE_BMI,
108  FEATURE_BMI2,
109  FEATURE_AES,
110  FEATURE_PCLMUL,
111  FEATURE_AVX512VL,
112  FEATURE_AVX512BW,
113  FEATURE_AVX512DQ,
114  FEATURE_AVX512CD,
115  FEATURE_AVX512ER,
116  FEATURE_AVX512PF,
117  FEATURE_AVX512VBMI,
118  FEATURE_AVX512IFMA
119};
120
121struct __processor_model
122{
123  unsigned int __cpu_vendor;
124  unsigned int __cpu_type;
125  unsigned int __cpu_subtype;
126  unsigned int __cpu_features[1];
127} __cpu_model = { };
128
129
130/* Get the specific type of AMD CPU.  */
131
132static void
133get_amd_cpu (unsigned int family, unsigned int model)
134{
135  switch (family)
136    {
137    /* AMD Family 10h.  */
138    case 0x10:
139      __cpu_model.__cpu_type = AMDFAM10H;
140      switch (model)
141	{
142	case 0x2:
143	  /* Barcelona.  */
144	  __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
145	  break;
146	case 0x4:
147	  /* Shanghai.  */
148	  __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
149	  break;
150	case 0x8:
151	  /* Istanbul.  */
152	  __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
153	  break;
154	default:
155	  break;
156	}
157      break;
158    /* AMD Family 14h "btver1". */
159    case 0x14:
160      __cpu_model.__cpu_type = AMD_BTVER1;
161      break;
162    /* AMD Family 15h "Bulldozer".  */
163    case 0x15:
164      __cpu_model.__cpu_type = AMDFAM15H;
165      /* Bulldozer version 1.  */
166      if ( model <= 0xf)
167	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
168      /* Bulldozer version 2 "Piledriver" */
169      if (model >= 0x10 && model <= 0x2f)
170	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
171      /* Bulldozer version 3 "Steamroller"  */
172      if (model >= 0x30 && model <= 0x4f)
173	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
174      /* Bulldozer version 4 "Excavator"   */
175      if (model >= 0x60 && model <= 0x7f)
176	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
177      break;
178    /* AMD Family 16h "btver2" */
179    case 0x16:
180      __cpu_model.__cpu_type = AMD_BTVER2;
181      break;
182    case 0x17:
183      __cpu_model.__cpu_type = AMDFAM17H;
184      /* AMD family 17h version 1.  */
185      if (model <= 0x1f)
186	__cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
187      break;
188    default:
189      break;
190    }
191}
192
193/* Get the specific type of Intel CPU.  */
194
195static void
196get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
197{
198  /* Parse family and model only if brand ID is 0. */
199  if (brand_id == 0)
200    {
201      switch (family)
202	{
203	case 0x5:
204	  /* Pentium.  */
205	  break;
206	case 0x6:
207	  switch (model)
208	    {
209	    case 0x1c:
210	    case 0x26:
211	      /* Bonnell.  */
212	      __cpu_model.__cpu_type = INTEL_BONNELL;
213	      break;
214	    case 0x37:
215	    case 0x4a:
216	    case 0x4d:
217	    case 0x5a:
218	    case 0x5d:
219	      /* Silvermont.  */
220	      __cpu_model.__cpu_type = INTEL_SILVERMONT;
221	      break;
222	    case 0x57:
223	      /* Knights Landing.  */
224	      __cpu_model.__cpu_type = INTEL_KNL;
225	      break;
226	    case 0x1a:
227	    case 0x1e:
228	    case 0x1f:
229	    case 0x2e:
230	      /* Nehalem.  */
231	      __cpu_model.__cpu_type = INTEL_COREI7;
232	      __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
233	      break;
234	    case 0x25:
235	    case 0x2c:
236	    case 0x2f:
237	      /* Westmere.  */
238	      __cpu_model.__cpu_type = INTEL_COREI7;
239	      __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
240	      break;
241	    case 0x2a:
242	    case 0x2d:
243	      /* Sandy Bridge.  */
244	      __cpu_model.__cpu_type = INTEL_COREI7;
245	      __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
246	      break;
247	    case 0x3a:
248	    case 0x3e:
249	      /* Ivy Bridge.  */
250	      __cpu_model.__cpu_type = INTEL_COREI7;
251	      __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
252	      break;
253	    case 0x3c:
254	    case 0x3f:
255	    case 0x45:
256	    case 0x46:
257	      /* Haswell.  */
258	      __cpu_model.__cpu_type = INTEL_COREI7;
259	      __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
260	      break;
261	    case 0x3d:
262	    case 0x47:
263	    case 0x4f:
264	    case 0x56:
265	      /* Broadwell.  */
266	      __cpu_model.__cpu_type = INTEL_COREI7;
267	      __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
268	      break;
269	    case 0x4e:
270	    case 0x5e:
271	      /* Skylake.  */
272	      __cpu_model.__cpu_type = INTEL_COREI7;
273	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
274	      break;
275	    case 0x55:
276	      /* Skylake with AVX-512 support.  */
277	      __cpu_model.__cpu_type = INTEL_COREI7;
278	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
279	      break;
280	    case 0x17:
281	    case 0x1d:
282	      /* Penryn.  */
283	    case 0x0f:
284	      /* Merom.  */
285	      __cpu_model.__cpu_type = INTEL_CORE2;
286	      break;
287	    default:
288	      break;
289	    }
290	  break;
291	default:
292	  /* We have no idea.  */
293	  break;
294	}
295    }
296}
297
298/* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
299   the max possible level of CPUID insn.  */
300static void
301get_available_features (unsigned int ecx, unsigned int edx,
302			int max_cpuid_level)
303{
304  unsigned int features = 0;
305
306  if (edx & bit_CMOV)
307    features |= (1 << FEATURE_CMOV);
308  if (edx & bit_MMX)
309    features |= (1 << FEATURE_MMX);
310  if (edx & bit_SSE)
311    features |= (1 << FEATURE_SSE);
312  if (edx & bit_SSE2)
313    features |= (1 << FEATURE_SSE2);
314  if (ecx & bit_POPCNT)
315    features |= (1 << FEATURE_POPCNT);
316  if (ecx & bit_AES)
317    features |= (1 << FEATURE_AES);
318  if (ecx & bit_PCLMUL)
319    features |= (1 << FEATURE_PCLMUL);
320  if (ecx & bit_SSE3)
321    features |= (1 << FEATURE_SSE3);
322  if (ecx & bit_SSSE3)
323    features |= (1 << FEATURE_SSSE3);
324  if (ecx & bit_SSE4_1)
325    features |= (1 << FEATURE_SSE4_1);
326  if (ecx & bit_SSE4_2)
327    features |= (1 << FEATURE_SSE4_2);
328  if (ecx & bit_AVX)
329    features |= (1 << FEATURE_AVX);
330  if (ecx & bit_FMA)
331    features |= (1 << FEATURE_FMA);
332
333  /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
334  if (max_cpuid_level >= 7)
335    {
336      unsigned int eax, ebx, ecx, edx;
337      __cpuid_count (7, 0, eax, ebx, ecx, edx);
338      if (ebx & bit_BMI)
339        features |= (1 << FEATURE_BMI);
340      if (ebx & bit_AVX2)
341	features |= (1 << FEATURE_AVX2);
342      if (ebx & bit_BMI2)
343        features |= (1 << FEATURE_BMI2);
344      if (ebx & bit_AVX512F)
345	features |= (1 << FEATURE_AVX512F);
346      if (ebx & bit_AVX512VL)
347	features |= (1 << FEATURE_AVX512VL);
348      if (ebx & bit_AVX512BW)
349	features |= (1 << FEATURE_AVX512BW);
350      if (ebx & bit_AVX512DQ)
351	features |= (1 << FEATURE_AVX512DQ);
352      if (ebx & bit_AVX512CD)
353	features |= (1 << FEATURE_AVX512CD);
354      if (ebx & bit_AVX512PF)
355	features |= (1 << FEATURE_AVX512PF);
356      if (ebx & bit_AVX512ER)
357	features |= (1 << FEATURE_AVX512ER);
358      if (ebx & bit_AVX512IFMA)
359	features |= (1 << FEATURE_AVX512IFMA);
360      if (ecx & bit_AVX512VBMI)
361	features |= (1 << FEATURE_AVX512VBMI);
362    }
363
364  unsigned int ext_level;
365  unsigned int eax, ebx;
366  /* Check cpuid level of extended features.  */
367  __cpuid (0x80000000, ext_level, ebx, ecx, edx);
368
369  if (ext_level > 0x80000000)
370    {
371      __cpuid (0x80000001, eax, ebx, ecx, edx);
372
373      if (ecx & bit_SSE4a)
374	features |= (1 << FEATURE_SSE4_A);
375      if (ecx & bit_FMA4)
376	features |= (1 << FEATURE_FMA4);
377      if (ecx & bit_XOP)
378	features |= (1 << FEATURE_XOP);
379    }
380
381  __cpu_model.__cpu_features[0] = features;
382}
383
384/* A noinline function calling __get_cpuid. Having many calls to
385   cpuid in one function in 32-bit mode causes GCC to complain:
386   "can't find a register in class CLOBBERED_REGS".  This is
387   related to PR rtl-optimization 44174. */
388
389static int __attribute__ ((noinline))
390__get_cpuid_output (unsigned int __level,
391		    unsigned int *__eax, unsigned int *__ebx,
392		    unsigned int *__ecx, unsigned int *__edx)
393{
394  return __get_cpuid (__level, __eax, __ebx, __ecx, __edx);
395}
396
397
398/* A constructor function that is sets __cpu_model and __cpu_features with
399   the right values.  This needs to run only once.  This constructor is
400   given the highest priority and it should run before constructors without
401   the priority set.  However, it still runs after ifunc initializers and
402   needs to be called explicitly there.  */
403
404int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
405__cpu_indicator_init (void)
406{
407  unsigned int eax, ebx, ecx, edx;
408
409  int max_level = 5;
410  unsigned int vendor;
411  unsigned int model, family, brand_id;
412  unsigned int extended_model, extended_family;
413
414  /* This function needs to run just once.  */
415  if (__cpu_model.__cpu_vendor)
416    return 0;
417
418  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
419  if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx))
420    {
421      __cpu_model.__cpu_vendor = VENDOR_OTHER;
422      return -1;
423    }
424
425  vendor = ebx;
426  max_level = eax;
427
428  if (max_level < 1)
429    {
430      __cpu_model.__cpu_vendor = VENDOR_OTHER;
431      return -1;
432    }
433
434  if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx))
435    {
436      __cpu_model.__cpu_vendor = VENDOR_OTHER;
437      return -1;
438    }
439
440  model = (eax >> 4) & 0x0f;
441  family = (eax >> 8) & 0x0f;
442  brand_id = ebx & 0xff;
443  extended_model = (eax >> 12) & 0xf0;
444  extended_family = (eax >> 20) & 0xff;
445
446  if (vendor == signature_INTEL_ebx)
447    {
448      /* Adjust model and family for Intel CPUS. */
449      if (family == 0x0f)
450	{
451	  family += extended_family;
452	  model += extended_model;
453	}
454      else if (family == 0x06)
455	model += extended_model;
456
457      /* Get CPU type.  */
458      get_intel_cpu (family, model, brand_id);
459      /* Find available features. */
460      get_available_features (ecx, edx, max_level);
461      __cpu_model.__cpu_vendor = VENDOR_INTEL;
462    }
463  else if (vendor == signature_AMD_ebx)
464    {
465      /* Adjust model and family for AMD CPUS. */
466      if (family == 0x0f)
467	{
468	  family += extended_family;
469	  model += extended_model;
470	}
471
472      /* Get CPU type.  */
473      get_amd_cpu (family, model);
474      /* Find available features. */
475      get_available_features (ecx, edx, max_level);
476      __cpu_model.__cpu_vendor = VENDOR_AMD;
477    }
478  else
479    __cpu_model.__cpu_vendor = VENDOR_OTHER;
480
481  gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
482  gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
483  gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
484
485  return 0;
486}
487
488#if defined SHARED && defined USE_ELF_SYMVER
489__asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
490__asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");
491#endif
492