xref: /netbsd-src/external/gpl3/gcc/dist/libgcc/config/i386/cpuinfo.c (revision eceb233b9bd0dfebb902ed73b531ae6964fa3f9b)
1 /* Get CPU type and Features for x86 processors.
2    Copyright (C) 2012-2019 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 #ifndef SHARED
43 /* We want to move away from __cpu_model in libgcc_s.so.1 and the
44    size of __cpu_model is part of ABI.  So, new features that don't
45    fit into __cpu_model.__cpu_features[0] go into extra variables
46    in libgcc.a only, preferrably hidden.  */
47 unsigned int __cpu_features2;
48 #endif
49 
50 
51 /* Get the specific type of AMD CPU.  */
52 
53 static void
54 get_amd_cpu (unsigned int family, unsigned int model)
55 {
56   switch (family)
57     {
58     /* AMD Family 10h.  */
59     case 0x10:
60       __cpu_model.__cpu_type = AMDFAM10H;
61       switch (model)
62 	{
63 	case 0x2:
64 	  /* Barcelona.  */
65 	  __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
66 	  break;
67 	case 0x4:
68 	  /* Shanghai.  */
69 	  __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
70 	  break;
71 	case 0x8:
72 	  /* Istanbul.  */
73 	  __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
74 	  break;
75 	default:
76 	  break;
77 	}
78       break;
79     /* AMD Family 14h "btver1". */
80     case 0x14:
81       __cpu_model.__cpu_type = AMD_BTVER1;
82       break;
83     /* AMD Family 15h "Bulldozer".  */
84     case 0x15:
85       __cpu_model.__cpu_type = AMDFAM15H;
86 
87       if (model == 0x2)
88 	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
89       /* Bulldozer version 1.  */
90       else if (model <= 0xf)
91 	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
92       /* Bulldozer version 2 "Piledriver" */
93       else if (model <= 0x2f)
94 	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
95       /* Bulldozer version 3 "Steamroller"  */
96       else if (model <= 0x4f)
97 	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
98       /* Bulldozer version 4 "Excavator"   */
99       else if (model <= 0x7f)
100 	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
101       break;
102     /* AMD Family 16h "btver2" */
103     case 0x16:
104       __cpu_model.__cpu_type = AMD_BTVER2;
105       break;
106     case 0x17:
107       __cpu_model.__cpu_type = AMDFAM17H;
108       /* AMD family 17h version 1.  */
109       if (model <= 0x1f)
110 	__cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
111       if (model >= 0x30)
112 	 __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER2;
113       break;
114     default:
115       break;
116     }
117 }
118 
119 /* Get the specific type of Intel CPU.  */
120 
121 static void
122 get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
123 {
124   /* Parse family and model only if brand ID is 0. */
125   if (brand_id == 0)
126     {
127       switch (family)
128 	{
129 	case 0x5:
130 	  /* Pentium.  */
131 	  break;
132 	case 0x6:
133 	  switch (model)
134 	    {
135 	    case 0x1c:
136 	    case 0x26:
137 	      /* Bonnell.  */
138 	      __cpu_model.__cpu_type = INTEL_BONNELL;
139 	      break;
140 	    case 0x37:
141 	    case 0x4a:
142 	    case 0x4d:
143 	    case 0x5a:
144 	    case 0x5d:
145 	      /* Silvermont.  */
146 	      __cpu_model.__cpu_type = INTEL_SILVERMONT;
147 	      break;
148 	    case 0x5c:
149 	    case 0x5f:
150 	      /* Goldmont.  */
151 	      __cpu_model.__cpu_type = INTEL_GOLDMONT;
152 	      break;
153 	    case 0x7a:
154 	      /* Goldmont Plus.  */
155 	      __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS;
156 	      break;
157 	    case 0x57:
158 	      /* Knights Landing.  */
159 	      __cpu_model.__cpu_type = INTEL_KNL;
160 	      break;
161 	    case 0x85:
162 	      /* Knights Mill. */
163 	      __cpu_model.__cpu_type = INTEL_KNM;
164 	      break;
165 	    case 0x1a:
166 	    case 0x1e:
167 	    case 0x1f:
168 	    case 0x2e:
169 	      /* Nehalem.  */
170 	      __cpu_model.__cpu_type = INTEL_COREI7;
171 	      __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
172 	      break;
173 	    case 0x25:
174 	    case 0x2c:
175 	    case 0x2f:
176 	      /* Westmere.  */
177 	      __cpu_model.__cpu_type = INTEL_COREI7;
178 	      __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
179 	      break;
180 	    case 0x2a:
181 	    case 0x2d:
182 	      /* Sandy Bridge.  */
183 	      __cpu_model.__cpu_type = INTEL_COREI7;
184 	      __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
185 	      break;
186 	    case 0x3a:
187 	    case 0x3e:
188 	      /* Ivy Bridge.  */
189 	      __cpu_model.__cpu_type = INTEL_COREI7;
190 	      __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
191 	      break;
192 	    case 0x3c:
193 	    case 0x3f:
194 	    case 0x45:
195 	    case 0x46:
196 	      /* Haswell.  */
197 	      __cpu_model.__cpu_type = INTEL_COREI7;
198 	      __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
199 	      break;
200 	    case 0x3d:
201 	    case 0x47:
202 	    case 0x4f:
203 	    case 0x56:
204 	      /* Broadwell.  */
205 	      __cpu_model.__cpu_type = INTEL_COREI7;
206 	      __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
207 	      break;
208 	    case 0x4e:
209 	    case 0x5e:
210 	      /* Skylake.  */
211 	    case 0x8e:
212 	    case 0x9e:
213 	      /* Kaby Lake.  */
214 	      __cpu_model.__cpu_type = INTEL_COREI7;
215 	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
216 	      break;
217 	    case 0x55:
218 	      {
219 	        unsigned int eax, ebx, ecx, edx;
220 	        __cpu_model.__cpu_type = INTEL_COREI7;
221 	        __cpuid_count (7, 0, eax, ebx, ecx, edx);
222 	        if (ecx & bit_AVX512VNNI)
223 	          /* Cascade Lake.  */
224 	          __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE;
225 	        else
226 	          /* Skylake with AVX-512 support.  */
227 	          __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
228 	      }
229 	      break;
230 	    case 0x66:
231 	      /* Cannon Lake.  */
232 	      __cpu_model.__cpu_type = INTEL_COREI7;
233 	      __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
234 	      break;
235 	    case 0x17:
236 	    case 0x1d:
237 	      /* Penryn.  */
238 	    case 0x0f:
239 	      /* Merom.  */
240 	      __cpu_model.__cpu_type = INTEL_CORE2;
241 	      break;
242 	    default:
243 	      break;
244 	    }
245 	  break;
246 	default:
247 	  /* We have no idea.  */
248 	  break;
249 	}
250     }
251 }
252 
253 /* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
254    the max possible level of CPUID insn.  */
255 static void
256 get_available_features (unsigned int ecx, unsigned int edx,
257 			int max_cpuid_level)
258 {
259   unsigned int eax, ebx;
260   unsigned int ext_level;
261 
262   unsigned int features = 0;
263   unsigned int features2 = 0;
264 
265   /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
266 #define XCR_XFEATURE_ENABLED_MASK	0x0
267 #define XSTATE_FP			0x1
268 #define XSTATE_SSE			0x2
269 #define XSTATE_YMM			0x4
270 #define XSTATE_OPMASK			0x20
271 #define XSTATE_ZMM			0x40
272 #define XSTATE_HI_ZMM			0x80
273 
274 #define XCR_AVX_ENABLED_MASK \
275   (XSTATE_SSE | XSTATE_YMM)
276 #define XCR_AVX512F_ENABLED_MASK \
277   (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
278 
279   /* Check if AVX and AVX512 are usable.  */
280   int avx_usable = 0;
281   int avx512_usable = 0;
282   if ((ecx & bit_OSXSAVE))
283     {
284       /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
285          ZMM16-ZMM31 states are supported by OSXSAVE.  */
286       unsigned int xcrlow;
287       unsigned int xcrhigh;
288       asm (".byte 0x0f, 0x01, 0xd0"
289 	   : "=a" (xcrlow), "=d" (xcrhigh)
290 	   : "c" (XCR_XFEATURE_ENABLED_MASK));
291       if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
292 	{
293 	  avx_usable = 1;
294 	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
295 			   == XCR_AVX512F_ENABLED_MASK);
296 	}
297     }
298 
299 #define set_feature(f) \
300   do						\
301     {						\
302       if (f < 32)				\
303 	features |= (1U << (f & 31));		\
304       else					\
305 	features2 |= (1U << ((f - 32) & 31));	\
306     }						\
307   while (0)
308 
309   if (edx & bit_CMOV)
310     set_feature (FEATURE_CMOV);
311   if (edx & bit_MMX)
312     set_feature (FEATURE_MMX);
313   if (edx & bit_SSE)
314     set_feature (FEATURE_SSE);
315   if (edx & bit_SSE2)
316     set_feature (FEATURE_SSE2);
317   if (ecx & bit_POPCNT)
318     set_feature (FEATURE_POPCNT);
319   if (ecx & bit_AES)
320     set_feature (FEATURE_AES);
321   if (ecx & bit_PCLMUL)
322     set_feature (FEATURE_PCLMUL);
323   if (ecx & bit_SSE3)
324     set_feature (FEATURE_SSE3);
325   if (ecx & bit_SSSE3)
326     set_feature (FEATURE_SSSE3);
327   if (ecx & bit_SSE4_1)
328     set_feature (FEATURE_SSE4_1);
329   if (ecx & bit_SSE4_2)
330     set_feature (FEATURE_SSE4_2);
331   if (avx_usable)
332     {
333       if (ecx & bit_AVX)
334 	set_feature (FEATURE_AVX);
335       if (ecx & bit_FMA)
336 	set_feature (FEATURE_FMA);
337     }
338 
339   /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
340   if (max_cpuid_level >= 7)
341     {
342       __cpuid_count (7, 0, eax, ebx, ecx, edx);
343       if (ebx & bit_BMI)
344 	set_feature (FEATURE_BMI);
345       if (avx_usable)
346 	{
347 	  if (ebx & bit_AVX2)
348 	    set_feature (FEATURE_AVX2);
349 	}
350       if (ebx & bit_BMI2)
351 	set_feature (FEATURE_BMI2);
352       if (avx512_usable)
353 	{
354 	  if (ebx & bit_AVX512F)
355 	    set_feature (FEATURE_AVX512F);
356 	  if (ebx & bit_AVX512VL)
357 	    set_feature (FEATURE_AVX512VL);
358 	  if (ebx & bit_AVX512BW)
359 	    set_feature (FEATURE_AVX512BW);
360 	  if (ebx & bit_AVX512DQ)
361 	    set_feature (FEATURE_AVX512DQ);
362 	  if (ebx & bit_AVX512CD)
363 	    set_feature (FEATURE_AVX512CD);
364 	  if (ebx & bit_AVX512PF)
365 	    set_feature (FEATURE_AVX512PF);
366 	  if (ebx & bit_AVX512ER)
367 	    set_feature (FEATURE_AVX512ER);
368 	  if (ebx & bit_AVX512IFMA)
369 	    set_feature (FEATURE_AVX512IFMA);
370 	  if (ecx & bit_AVX512VBMI)
371 	    set_feature (FEATURE_AVX512VBMI);
372 	  if (ecx & bit_AVX512VBMI2)
373 	    set_feature (FEATURE_AVX512VBMI2);
374 	  if (ecx & bit_GFNI)
375 	    set_feature (FEATURE_GFNI);
376 	  if (ecx & bit_VPCLMULQDQ)
377 	    set_feature (FEATURE_VPCLMULQDQ);
378 	  if (ecx & bit_AVX512VNNI)
379 	    set_feature (FEATURE_AVX512VNNI);
380 	  if (ecx & bit_AVX512BITALG)
381 	    set_feature (FEATURE_AVX512BITALG);
382 	  if (ecx & bit_AVX512VPOPCNTDQ)
383 	    set_feature (FEATURE_AVX512VPOPCNTDQ);
384 	  if (edx & bit_AVX5124VNNIW)
385 	    set_feature (FEATURE_AVX5124VNNIW);
386 	  if (edx & bit_AVX5124FMAPS)
387 	    set_feature (FEATURE_AVX5124FMAPS);
388 	}
389     }
390 
391   /* Check cpuid level of extended features.  */
392   __cpuid (0x80000000, ext_level, ebx, ecx, edx);
393 
394   if (ext_level >= 0x80000001)
395     {
396       __cpuid (0x80000001, eax, ebx, ecx, edx);
397 
398       if (ecx & bit_SSE4a)
399 	set_feature (FEATURE_SSE4_A);
400       if (avx_usable)
401 	{
402 	  if (ecx & bit_FMA4)
403 	    set_feature (FEATURE_FMA4);
404 	  if (ecx & bit_XOP)
405 	    set_feature (FEATURE_XOP);
406 	}
407     }
408 
409   __cpu_model.__cpu_features[0] = features;
410 #ifndef SHARED
411   __cpu_features2 = features2;
412 #else
413   (void) features2;
414 #endif
415 }
416 
417 /* A constructor function that is sets __cpu_model and __cpu_features with
418    the right values.  This needs to run only once.  This constructor is
419    given the highest priority and it should run before constructors without
420    the priority set.  However, it still runs after ifunc initializers and
421    needs to be called explicitly there.  */
422 
423 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
424 __cpu_indicator_init (void)
425 {
426   unsigned int eax, ebx, ecx, edx;
427 
428   int max_level;
429   unsigned int vendor;
430   unsigned int model, family, brand_id;
431   unsigned int extended_model, extended_family;
432 
433   /* This function needs to run just once.  */
434   if (__cpu_model.__cpu_vendor)
435     return 0;
436 
437   /* Assume cpuid insn present. Run in level 0 to get vendor id. */
438   if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
439     {
440       __cpu_model.__cpu_vendor = VENDOR_OTHER;
441       return -1;
442     }
443 
444   vendor = ebx;
445   max_level = eax;
446 
447   if (max_level < 1)
448     {
449       __cpu_model.__cpu_vendor = VENDOR_OTHER;
450       return -1;
451     }
452 
453   if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
454     {
455       __cpu_model.__cpu_vendor = VENDOR_OTHER;
456       return -1;
457     }
458 
459   model = (eax >> 4) & 0x0f;
460   family = (eax >> 8) & 0x0f;
461   brand_id = ebx & 0xff;
462   extended_model = (eax >> 12) & 0xf0;
463   extended_family = (eax >> 20) & 0xff;
464 
465   if (vendor == signature_INTEL_ebx)
466     {
467       /* Adjust model and family for Intel CPUS. */
468       if (family == 0x0f)
469 	{
470 	  family += extended_family;
471 	  model += extended_model;
472 	}
473       else if (family == 0x06)
474 	model += extended_model;
475 
476       /* Get CPU type.  */
477       get_intel_cpu (family, model, brand_id);
478       /* Find available features. */
479       get_available_features (ecx, edx, max_level);
480       __cpu_model.__cpu_vendor = VENDOR_INTEL;
481     }
482   else if (vendor == signature_AMD_ebx)
483     {
484       /* Adjust model and family for AMD CPUS. */
485       if (family == 0x0f)
486 	{
487 	  family += extended_family;
488 	  model += extended_model;
489 	}
490 
491       /* Get CPU type.  */
492       get_amd_cpu (family, model);
493       /* Find available features. */
494       get_available_features (ecx, edx, max_level);
495       __cpu_model.__cpu_vendor = VENDOR_AMD;
496     }
497   else
498     __cpu_model.__cpu_vendor = VENDOR_OTHER;
499 
500   gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
501   gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
502   gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
503 
504   return 0;
505 }
506 
507 #if defined SHARED && defined USE_ELF_SYMVER
508 __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
509 __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");
510 #endif
511