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