xref: /netbsd-src/external/gpl3/gcc/dist/gcc/common/config/i386/cpuinfo.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 /* Get CPU type and Features for x86 processors.
2    Copyright (C) 2012-2022 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 struct __processor_model
27 {
28   unsigned int __cpu_vendor;
29   unsigned int __cpu_type;
30   unsigned int __cpu_subtype;
31   /* The first 32 features are stored as bitmasks in __cpu_features.
32      The rest of features are stored as bitmasks in a separate array
33      of unsigned int.  */
34   unsigned int __cpu_features[1];
35 };
36 
37 struct __processor_model2
38 {
39   unsigned int __cpu_family;
40   unsigned int __cpu_model;
41   unsigned int __cpu_max_level;
42   unsigned int __cpu_ext_level;
43 };
44 
45 #ifndef CHECK___builtin_cpu_is
46 # define CHECK___builtin_cpu_is(cpu)
47 #endif
48 
49 #ifndef CHECK___builtin_cpu_supports
50 # define CHECK___builtin_cpu_supports(isa)
51 #endif
52 
53 /* Return non-zero if the processor has feature F.  */
54 
55 static inline int
has_cpu_feature(struct __processor_model * cpu_model,unsigned int * cpu_features2,enum processor_features feature)56 has_cpu_feature (struct __processor_model *cpu_model,
57 		 unsigned int *cpu_features2,
58 		 enum processor_features feature)
59 {
60   unsigned index, offset;
61   unsigned f = feature;
62 
63   if (f < 32)
64     {
65       /* The first 32 features.  */
66       return cpu_model->__cpu_features[0] & (1U << f);
67     }
68   else
69     {
70       /* The rest of features.  cpu_features2[i] contains features from
71 	 (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
72       f -= 32;
73       index = f / 32;
74       offset = f % 32;
75       return cpu_features2[index] & (1U << offset);
76     }
77 }
78 
79 static inline void
set_cpu_feature(struct __processor_model * cpu_model,unsigned int * cpu_features2,enum processor_features feature)80 set_cpu_feature (struct __processor_model *cpu_model,
81 		 unsigned int *cpu_features2,
82 		 enum processor_features feature)
83 {
84   unsigned index, offset;
85   unsigned f = feature;
86 
87   if (f < 32)
88     {
89       /* The first 32 features.  */
90       cpu_model->__cpu_features[0] |= (1U << f);
91     }
92   else
93     {
94       /* The rest of features.  cpu_features2[i] contains features from
95 	 (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
96       f -= 32;
97       index = f / 32;
98       offset = f % 32;
99       cpu_features2[index] |= (1U << offset);
100     }
101 }
102 
103 /* Get the specific type of AMD CPU and return AMD CPU name.  Return
104    NULL for unknown AMD CPU.  */
105 
106 static inline const char *
get_amd_cpu(struct __processor_model * cpu_model,struct __processor_model2 * cpu_model2,unsigned int * cpu_features2)107 get_amd_cpu (struct __processor_model *cpu_model,
108 	     struct __processor_model2 *cpu_model2,
109 	     unsigned int *cpu_features2)
110 {
111   const char *cpu = NULL;
112   unsigned int family = cpu_model2->__cpu_family;
113   unsigned int model = cpu_model2->__cpu_model;
114 
115   switch (family)
116     {
117     case 0x10:
118       /* AMD Family 10h.  */
119       cpu = "amdfam10";
120       cpu_model->__cpu_type = AMDFAM10H;
121       switch (model)
122 	{
123 	case 0x2:
124 	  /* Barcelona.  */
125 	  CHECK___builtin_cpu_is ("amdfam10h");
126 	  CHECK___builtin_cpu_is ("barcelona");
127 	  cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA;
128 	  break;
129 	case 0x4:
130 	  /* Shanghai.  */
131 	  CHECK___builtin_cpu_is ("amdfam10h");
132 	  CHECK___builtin_cpu_is ("shanghai");
133 	  cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI;
134 	  break;
135 	case 0x8:
136 	  /* Istanbul.  */
137 	  CHECK___builtin_cpu_is ("amdfam10h");
138 	  CHECK___builtin_cpu_is ("istanbul");
139 	  cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL;
140 	  break;
141 	default:
142 	  break;
143 	}
144       break;
145     case 0x14:
146       /* AMD Family 14h "btver1". */
147       cpu = "btver1";
148       CHECK___builtin_cpu_is ("btver1");
149       cpu_model->__cpu_type = AMD_BTVER1;
150       break;
151     case 0x15:
152       /* AMD Family 15h "Bulldozer".  */
153       cpu_model->__cpu_type = AMDFAM15H;
154       if (model == 0x2)
155 	{
156 	  /* Bulldozer version 2 "Piledriver" */
157 	  cpu = "bdver2";
158 	  CHECK___builtin_cpu_is ("bdver2");
159 	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
160 	}
161       else if (model <= 0xf)
162 	{
163 	  /* Bulldozer version 1.  */
164 	  cpu = "bdver1";
165 	  CHECK___builtin_cpu_is ("bdver1");
166 	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
167 	}
168       else if (model <= 0x2f)
169 	{
170 	  /* Bulldozer version 2 "Piledriver" */
171 	  cpu = "bdver2";
172 	  CHECK___builtin_cpu_is ("bdver2");
173 	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
174 	}
175       else if (model <= 0x4f)
176 	{
177 	  /* Bulldozer version 3 "Steamroller"  */
178 	  cpu = "bdver3";
179 	  CHECK___builtin_cpu_is ("bdver3");
180 	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
181 	}
182       else if (model <= 0x7f)
183 	{
184 	  /* Bulldozer version 4 "Excavator"   */
185 	  cpu = "bdver4";
186 	  CHECK___builtin_cpu_is ("bdver4");
187 	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
188 	}
189       else if (has_cpu_feature (cpu_model, cpu_features2,
190 				FEATURE_AVX2))
191 	{
192 	  cpu = "bdver4";
193 	  CHECK___builtin_cpu_is ("bdver4");
194 	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
195 	}
196       else if (has_cpu_feature (cpu_model, cpu_features2,
197 				FEATURE_XSAVEOPT))
198 	{
199 	  cpu = "bdver3";
200 	  CHECK___builtin_cpu_is ("bdver3");
201 	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
202 	}
203       else if (has_cpu_feature (cpu_model, cpu_features2,
204 				FEATURE_BMI))
205 	{
206 	  cpu = "bdver2";
207 	  CHECK___builtin_cpu_is ("bdver2");
208 	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
209 	}
210       else if (has_cpu_feature (cpu_model, cpu_features2,
211 				FEATURE_XOP))
212 	{
213 	  cpu = "bdver1";
214 	  CHECK___builtin_cpu_is ("bdver1");
215 	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
216 	}
217       break;
218     case 0x16:
219       /* AMD Family 16h "btver2" */
220       cpu = "btver2";
221       CHECK___builtin_cpu_is ("btver2");
222       cpu_model->__cpu_type = AMD_BTVER2;
223       break;
224     case 0x17:
225       cpu_model->__cpu_type = AMDFAM17H;
226       if (model <= 0x1f)
227 	{
228 	  /* AMD family 17h version 1.  */
229 	  cpu = "znver1";
230 	  CHECK___builtin_cpu_is ("znver1");
231 	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
232 	}
233       else if (model >= 0x30)
234 	{
235 	  cpu = "znver2";
236 	  CHECK___builtin_cpu_is ("znver2");
237 	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
238 	}
239       else if (has_cpu_feature (cpu_model, cpu_features2,
240 				FEATURE_CLWB))
241 	{
242 	  cpu = "znver2";
243 	  CHECK___builtin_cpu_is ("znver2");
244 	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
245 	}
246       else if (has_cpu_feature (cpu_model, cpu_features2,
247 				FEATURE_CLZERO))
248 	{
249 	  cpu = "znver1";
250 	  CHECK___builtin_cpu_is ("znver1");
251 	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
252 	}
253       break;
254     case 0x19:
255       cpu_model->__cpu_type = AMDFAM19H;
256       /* AMD family 19h.  */
257       if (model <= 0x0f)
258 	{
259 	  cpu = "znver3";
260 	  CHECK___builtin_cpu_is ("znver3");
261 	  cpu_model->__cpu_subtype = AMDFAM19H_ZNVER3;
262 	}
263       else if ((model >= 0x10 && model <= 0x1f)
264 		|| (model >= 0x60 && model <= 0xaf))
265 	{
266 	  cpu = "znver4";
267 	  CHECK___builtin_cpu_is ("znver4");
268 	  cpu_model->__cpu_subtype = AMDFAM19H_ZNVER4;
269 	}
270       else if (has_cpu_feature (cpu_model, cpu_features2,
271 				FEATURE_AVX512F))
272 	{
273 	  cpu = "znver4";
274 	  CHECK___builtin_cpu_is ("znver4");
275 	  cpu_model->__cpu_subtype = AMDFAM19H_ZNVER4;
276 	}
277       else if (has_cpu_feature (cpu_model, cpu_features2,
278 				FEATURE_VAES))
279 	{
280 	  cpu = "znver3";
281 	  CHECK___builtin_cpu_is ("znver3");
282 	  cpu_model->__cpu_subtype = AMDFAM19H_ZNVER3;
283 	}
284       break;
285     default:
286       break;
287     }
288 
289   return cpu;
290 }
291 
292 /* Get the specific type of Intel CPU and return Intel CPU name.  Return
293    NULL for unknown Intel CPU.  */
294 
295 static inline const char *
get_intel_cpu(struct __processor_model * cpu_model,struct __processor_model2 * cpu_model2,unsigned int * cpu_features2)296 get_intel_cpu (struct __processor_model *cpu_model,
297 	       struct __processor_model2 *cpu_model2,
298 	       unsigned int *cpu_features2)
299 {
300   const char *cpu = NULL;
301 
302   /* Parse family and model only for model 6. */
303   if (cpu_model2->__cpu_family != 0x6)
304     return cpu;
305 
306   switch (cpu_model2->__cpu_model)
307     {
308     case 0x1c:
309     case 0x26:
310       /* Bonnell.  */
311       cpu = "bonnell";
312       CHECK___builtin_cpu_is ("atom");
313       cpu_model->__cpu_type = INTEL_BONNELL;
314       break;
315     case 0x37:
316     case 0x4a:
317     case 0x4d:
318     case 0x5d:
319       /* Silvermont.  */
320     case 0x4c:
321     case 0x5a:
322     case 0x75:
323       /* Airmont.  */
324       cpu = "silvermont";
325       CHECK___builtin_cpu_is ("silvermont");
326       cpu_model->__cpu_type = INTEL_SILVERMONT;
327       break;
328     case 0x5c:
329     case 0x5f:
330       /* Goldmont.  */
331       cpu = "goldmont";
332       CHECK___builtin_cpu_is ("goldmont");
333       cpu_model->__cpu_type = INTEL_GOLDMONT;
334       break;
335     case 0x7a:
336       /* Goldmont Plus.  */
337       cpu = "goldmont-plus";
338       CHECK___builtin_cpu_is ("goldmont-plus");
339       cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
340       break;
341     case 0x86:
342     case 0x96:
343     case 0x9c:
344       /* Tremont.  */
345       cpu = "tremont";
346       CHECK___builtin_cpu_is ("tremont");
347       cpu_model->__cpu_type = INTEL_TREMONT;
348       break;
349     case 0x57:
350       /* Knights Landing.  */
351       cpu = "knl";
352       CHECK___builtin_cpu_is ("knl");
353       cpu_model->__cpu_type = INTEL_KNL;
354       break;
355     case 0x85:
356       /* Knights Mill. */
357       cpu = "knm";
358       CHECK___builtin_cpu_is ("knm");
359       cpu_model->__cpu_type = INTEL_KNM;
360       break;
361     case 0x1a:
362     case 0x1e:
363     case 0x1f:
364     case 0x2e:
365       /* Nehalem.  */
366       cpu = "nehalem";
367       CHECK___builtin_cpu_is ("corei7");
368       CHECK___builtin_cpu_is ("nehalem");
369       cpu_model->__cpu_type = INTEL_COREI7;
370       cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
371       break;
372     case 0x25:
373     case 0x2c:
374     case 0x2f:
375       /* Westmere.  */
376       cpu = "westmere";
377       CHECK___builtin_cpu_is ("corei7");
378       CHECK___builtin_cpu_is ("westmere");
379       cpu_model->__cpu_type = INTEL_COREI7;
380       cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
381       break;
382     case 0x2a:
383     case 0x2d:
384       /* Sandy Bridge.  */
385       cpu = "sandybridge";
386       CHECK___builtin_cpu_is ("corei7");
387       CHECK___builtin_cpu_is ("sandybridge");
388       cpu_model->__cpu_type = INTEL_COREI7;
389       cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
390       break;
391     case 0x3a:
392     case 0x3e:
393       /* Ivy Bridge.  */
394       cpu = "ivybridge";
395       CHECK___builtin_cpu_is ("corei7");
396       CHECK___builtin_cpu_is ("ivybridge");
397       cpu_model->__cpu_type = INTEL_COREI7;
398       cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
399       break;
400     case 0x3c:
401     case 0x3f:
402     case 0x45:
403     case 0x46:
404       /* Haswell.  */
405       cpu = "haswell";
406       CHECK___builtin_cpu_is ("corei7");
407       CHECK___builtin_cpu_is ("haswell");
408       cpu_model->__cpu_type = INTEL_COREI7;
409       cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
410       break;
411     case 0x3d:
412     case 0x47:
413     case 0x4f:
414     case 0x56:
415       /* Broadwell.  */
416       cpu = "broadwell";
417       CHECK___builtin_cpu_is ("corei7");
418       CHECK___builtin_cpu_is ("broadwell");
419       cpu_model->__cpu_type = INTEL_COREI7;
420       cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
421       break;
422     case 0x4e:
423     case 0x5e:
424       /* Skylake.  */
425     case 0x8e:
426     case 0x9e:
427       /* Kaby Lake.  */
428     case 0xa5:
429     case 0xa6:
430       /* Comet Lake.  */
431       cpu = "skylake";
432       CHECK___builtin_cpu_is ("corei7");
433       CHECK___builtin_cpu_is ("skylake");
434       cpu_model->__cpu_type = INTEL_COREI7;
435       cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
436       break;
437     case 0xa7:
438       /* Rocket Lake.  */
439       cpu = "rocketlake";
440       CHECK___builtin_cpu_is ("corei7");
441       CHECK___builtin_cpu_is ("rocketlake");
442       cpu_model->__cpu_type = INTEL_COREI7;
443       cpu_model->__cpu_subtype = INTEL_COREI7_ROCKETLAKE;
444       break;
445     case 0x55:
446       CHECK___builtin_cpu_is ("corei7");
447       cpu_model->__cpu_type = INTEL_COREI7;
448       if (has_cpu_feature (cpu_model, cpu_features2,
449 			   FEATURE_AVX512BF16))
450 	{
451 	  /* Cooper Lake.  */
452 	  cpu = "cooperlake";
453 	  CHECK___builtin_cpu_is ("cooperlake");
454 	  cpu_model->__cpu_subtype = INTEL_COREI7_COOPERLAKE;
455 	}
456       else if (has_cpu_feature (cpu_model, cpu_features2,
457 				FEATURE_AVX512VNNI))
458 	{
459 	  /* Cascade Lake.  */
460 	  cpu = "cascadelake";
461 	  CHECK___builtin_cpu_is ("cascadelake");
462 	  cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
463 	}
464       else
465 	{
466 	  /* Skylake with AVX-512 support.  */
467 	  cpu = "skylake-avx512";
468 	  CHECK___builtin_cpu_is ("skylake-avx512");
469 	  cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
470 	}
471       break;
472     case 0x66:
473       /* Cannon Lake.  */
474       cpu = "cannonlake";
475       CHECK___builtin_cpu_is ("corei7");
476       CHECK___builtin_cpu_is ("cannonlake");
477       cpu_model->__cpu_type = INTEL_COREI7;
478       cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
479       break;
480     case 0x6a:
481     case 0x6c:
482       /* Ice Lake server.  */
483       cpu = "icelake-server";
484       CHECK___builtin_cpu_is ("corei7");
485       CHECK___builtin_cpu_is ("icelake-server");
486       cpu_model->__cpu_type = INTEL_COREI7;
487       cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
488       break;
489     case 0x7e:
490     case 0x7d:
491     case 0x9d:
492        /* Ice Lake client.  */
493       cpu = "icelake-client";
494       CHECK___builtin_cpu_is ("corei7");
495       CHECK___builtin_cpu_is ("icelake-client");
496       cpu_model->__cpu_type = INTEL_COREI7;
497       cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
498       break;
499     case 0x8c:
500     case 0x8d:
501       /* Tiger Lake.  */
502       cpu = "tigerlake";
503       CHECK___builtin_cpu_is ("corei7");
504       CHECK___builtin_cpu_is ("tigerlake");
505       cpu_model->__cpu_type = INTEL_COREI7;
506       cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
507       break;
508     case 0x97:
509     case 0x9a:
510       /* Alder Lake.  */
511       cpu = "alderlake";
512       CHECK___builtin_cpu_is ("corei7");
513       CHECK___builtin_cpu_is ("alderlake");
514       cpu_model->__cpu_type = INTEL_COREI7;
515       cpu_model->__cpu_subtype = INTEL_COREI7_ALDERLAKE;
516       break;
517     case 0x8f:
518       /* Sapphire Rapids.  */
519       cpu = "sapphirerapids";
520       CHECK___builtin_cpu_is ("corei7");
521       CHECK___builtin_cpu_is ("sapphirerapids");
522       cpu_model->__cpu_type = INTEL_COREI7;
523       cpu_model->__cpu_subtype = INTEL_COREI7_SAPPHIRERAPIDS;
524       break;
525     case 0x17:
526     case 0x1d:
527       /* Penryn.  */
528     case 0x0f:
529       /* Merom.  */
530       cpu = "core2";
531       CHECK___builtin_cpu_is ("core2");
532       cpu_model->__cpu_type = INTEL_CORE2;
533       break;
534     default:
535       break;
536     }
537 
538   return cpu;
539 }
540 
541 /* ECX and EDX are output of CPUID at level one.  */
542 static inline void
get_available_features(struct __processor_model * cpu_model,struct __processor_model2 * cpu_model2,unsigned int * cpu_features2,unsigned int ecx,unsigned int edx)543 get_available_features (struct __processor_model *cpu_model,
544 			struct __processor_model2 *cpu_model2,
545 			unsigned int *cpu_features2,
546 			unsigned int ecx, unsigned int edx)
547 {
548   unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
549   unsigned int eax, ebx;
550   unsigned int ext_level;
551 
552   /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
553 #define XCR_XFEATURE_ENABLED_MASK	0x0
554 #define XSTATE_FP			0x1
555 #define XSTATE_SSE			0x2
556 #define XSTATE_YMM			0x4
557 #define XSTATE_OPMASK			0x20
558 #define XSTATE_ZMM			0x40
559 #define XSTATE_HI_ZMM			0x80
560 #define XSTATE_TILECFG			0x20000
561 #define XSTATE_TILEDATA		0x40000
562 
563 #define XCR_AVX_ENABLED_MASK \
564   (XSTATE_SSE | XSTATE_YMM)
565 #define XCR_AVX512F_ENABLED_MASK \
566   (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
567 #define XCR_AMX_ENABLED_MASK \
568   (XSTATE_TILECFG | XSTATE_TILEDATA)
569 
570   /* Check if AVX and AVX512 are usable.  */
571   int avx_usable = 0;
572   int avx512_usable = 0;
573   int amx_usable = 0;
574   /* Check if KL is usable.  */
575   int has_kl = 0;
576   if ((ecx & bit_OSXSAVE))
577     {
578       /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
579 	 ZMM16-ZMM31 states are supported by OSXSAVE.  */
580       unsigned int xcrlow;
581       unsigned int xcrhigh;
582       __asm__ (".byte 0x0f, 0x01, 0xd0"
583 	       : "=a" (xcrlow), "=d" (xcrhigh)
584 	       : "c" (XCR_XFEATURE_ENABLED_MASK));
585       if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
586 	{
587 	  avx_usable = 1;
588 	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
589 			   == XCR_AVX512F_ENABLED_MASK);
590 	}
591       amx_usable = ((xcrlow & XCR_AMX_ENABLED_MASK)
592 		    == XCR_AMX_ENABLED_MASK);
593     }
594 
595 #define set_feature(f) \
596   set_cpu_feature (cpu_model, cpu_features2, f)
597 
598   if (edx & bit_CMOV)
599     set_feature (FEATURE_CMOV);
600   if (edx & bit_MMX)
601     set_feature (FEATURE_MMX);
602   if (edx & bit_SSE)
603     set_feature (FEATURE_SSE);
604   if (edx & bit_SSE2)
605     set_feature (FEATURE_SSE2);
606   if (edx & bit_CMPXCHG8B)
607     set_feature (FEATURE_CMPXCHG8B);
608   if (edx & bit_FXSAVE)
609     set_feature (FEATURE_FXSAVE);
610 
611   if (ecx & bit_POPCNT)
612     set_feature (FEATURE_POPCNT);
613   if (ecx & bit_AES)
614     set_feature (FEATURE_AES);
615   if (ecx & bit_PCLMUL)
616     set_feature (FEATURE_PCLMUL);
617   if (ecx & bit_SSE3)
618     set_feature (FEATURE_SSE3);
619   if (ecx & bit_SSSE3)
620     set_feature (FEATURE_SSSE3);
621   if (ecx & bit_SSE4_1)
622     set_feature (FEATURE_SSE4_1);
623   if (ecx & bit_SSE4_2)
624     set_feature (FEATURE_SSE4_2);
625   if (ecx & bit_OSXSAVE)
626     set_feature (FEATURE_OSXSAVE);
627   if (ecx & bit_CMPXCHG16B)
628     set_feature (FEATURE_CMPXCHG16B);
629   if (ecx & bit_MOVBE)
630     set_feature (FEATURE_MOVBE);
631   if (ecx & bit_AES)
632     set_feature (FEATURE_AES);
633   if (ecx & bit_RDRND)
634     set_feature (FEATURE_RDRND);
635   if (ecx & bit_XSAVE)
636     set_feature (FEATURE_XSAVE);
637   if (avx_usable)
638     {
639       if (ecx & bit_AVX)
640 	set_feature (FEATURE_AVX);
641       if (ecx & bit_FMA)
642 	set_feature (FEATURE_FMA);
643       if (ecx & bit_F16C)
644 	set_feature (FEATURE_F16C);
645     }
646 
647   /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
648   if (max_cpuid_level >= 7)
649     {
650       unsigned int max_subleaf_level;
651 
652       __cpuid_count (7, 0, max_subleaf_level, ebx, ecx, edx);
653       if (ebx & bit_BMI)
654 	set_feature (FEATURE_BMI);
655       if (ebx & bit_SGX)
656 	set_feature (FEATURE_SGX);
657       if (ebx & bit_HLE)
658 	set_feature (FEATURE_HLE);
659       if (ebx & bit_RTM)
660 	set_feature (FEATURE_RTM);
661       if (avx_usable)
662 	{
663 	  if (ebx & bit_AVX2)
664 	    set_feature (FEATURE_AVX2);
665 	  if (ecx & bit_VPCLMULQDQ)
666 	    set_feature (FEATURE_VPCLMULQDQ);
667 	  if (ecx & bit_VAES)
668 	    set_feature (FEATURE_VAES);
669 	}
670       if (ebx & bit_BMI2)
671 	set_feature (FEATURE_BMI2);
672       if (ebx & bit_FSGSBASE)
673 	set_feature (FEATURE_FSGSBASE);
674       if (ebx & bit_RDSEED)
675 	set_feature (FEATURE_RDSEED);
676       if (ebx & bit_ADX)
677 	set_feature (FEATURE_ADX);
678       if (ebx & bit_SHA)
679 	set_feature (FEATURE_SHA);
680       if (ebx & bit_CLFLUSHOPT)
681 	set_feature (FEATURE_CLFLUSHOPT);
682       if (ebx & bit_CLWB)
683 	set_feature (FEATURE_CLWB);
684       if (ecx & bit_PREFETCHWT1)
685 	set_feature (FEATURE_PREFETCHWT1);
686       /* NB: bit_OSPKE indicates that OS supports PKU.  */
687       if (ecx & bit_OSPKE)
688 	set_feature (FEATURE_PKU);
689       if (ecx & bit_RDPID)
690 	set_feature (FEATURE_RDPID);
691       if (ecx & bit_GFNI)
692 	set_feature (FEATURE_GFNI);
693       if (ecx & bit_MOVDIRI)
694 	set_feature (FEATURE_MOVDIRI);
695       if (ecx & bit_MOVDIR64B)
696 	set_feature (FEATURE_MOVDIR64B);
697       if (ecx & bit_ENQCMD)
698 	set_feature (FEATURE_ENQCMD);
699       if (ecx & bit_CLDEMOTE)
700 	set_feature (FEATURE_CLDEMOTE);
701       if (ecx & bit_WAITPKG)
702 	set_feature (FEATURE_WAITPKG);
703       if (ecx & bit_SHSTK)
704 	set_feature (FEATURE_SHSTK);
705       if (ecx & bit_KL)
706 	has_kl = 1;
707       if (edx & bit_SERIALIZE)
708 	set_feature (FEATURE_SERIALIZE);
709       if (edx & bit_TSXLDTRK)
710 	set_feature (FEATURE_TSXLDTRK);
711       if (edx & bit_PCONFIG)
712 	set_feature (FEATURE_PCONFIG);
713       if (edx & bit_IBT)
714 	set_feature (FEATURE_IBT);
715       if (edx & bit_UINTR)
716 	set_feature (FEATURE_UINTR);
717       if (amx_usable)
718 	{
719 	  if (edx & bit_AMX_TILE)
720 	    set_feature (FEATURE_AMX_TILE);
721 	  if (edx & bit_AMX_INT8)
722 	    set_feature (FEATURE_AMX_INT8);
723 	  if (edx & bit_AMX_BF16)
724 	    set_feature (FEATURE_AMX_BF16);
725 	}
726       if (avx512_usable)
727 	{
728 	  if (ebx & bit_AVX512F)
729 	    set_feature (FEATURE_AVX512F);
730 	  if (ebx & bit_AVX512VL)
731 	    set_feature (FEATURE_AVX512VL);
732 	  if (ebx & bit_AVX512BW)
733 	    set_feature (FEATURE_AVX512BW);
734 	  if (ebx & bit_AVX512DQ)
735 	    set_feature (FEATURE_AVX512DQ);
736 	  if (ebx & bit_AVX512CD)
737 	    set_feature (FEATURE_AVX512CD);
738 	  if (ebx & bit_AVX512PF)
739 	    set_feature (FEATURE_AVX512PF);
740 	  if (ebx & bit_AVX512ER)
741 	    set_feature (FEATURE_AVX512ER);
742 	  if (ebx & bit_AVX512IFMA)
743 	    set_feature (FEATURE_AVX512IFMA);
744 	  if (ecx & bit_AVX512VBMI)
745 	    set_feature (FEATURE_AVX512VBMI);
746 	  if (ecx & bit_AVX512VBMI2)
747 	    set_feature (FEATURE_AVX512VBMI2);
748 	  if (ecx & bit_AVX512VNNI)
749 	    set_feature (FEATURE_AVX512VNNI);
750 	  if (ecx & bit_AVX512BITALG)
751 	    set_feature (FEATURE_AVX512BITALG);
752 	  if (ecx & bit_AVX512VPOPCNTDQ)
753 	    set_feature (FEATURE_AVX512VPOPCNTDQ);
754 	  if (edx & bit_AVX5124VNNIW)
755 	    set_feature (FEATURE_AVX5124VNNIW);
756 	  if (edx & bit_AVX5124FMAPS)
757 	    set_feature (FEATURE_AVX5124FMAPS);
758 	  if (edx & bit_AVX512VP2INTERSECT)
759 	    set_feature (FEATURE_AVX512VP2INTERSECT);
760 	  if (edx & bit_AVX512FP16)
761 	    set_feature (FEATURE_AVX512FP16);
762 	}
763 
764       if (max_subleaf_level >= 1)
765 	{
766 	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
767 	  if (eax & bit_HRESET)
768 	    set_feature (FEATURE_HRESET);
769 	  if (avx_usable)
770 	    {
771 	      if (eax & bit_AVXVNNI)
772 		set_feature (FEATURE_AVXVNNI);
773 	    }
774 	  if (avx512_usable)
775 	    {
776 	      if (eax & bit_AVX512BF16)
777 		set_feature (FEATURE_AVX512BF16);
778 	    }
779 	}
780     }
781 
782   /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
783   if (max_cpuid_level >= 0xd)
784     {
785       __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
786       if (eax & bit_XSAVEOPT)
787 	set_feature (FEATURE_XSAVEOPT);
788       if (eax & bit_XSAVEC)
789 	set_feature (FEATURE_XSAVEC);
790       if (eax & bit_XSAVES)
791 	set_feature (FEATURE_XSAVES);
792     }
793 
794   /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */
795   if (max_cpuid_level >= 0x14)
796     {
797       __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
798       if (ebx & bit_PTWRITE)
799 	set_feature (FEATURE_PTWRITE);
800     }
801 
802   /* Get Advanced Features at level 0x19 (eax = 0x19).  */
803   if (max_cpuid_level >= 0x19)
804     {
805       __cpuid (0x19, eax, ebx, ecx, edx);
806       /* Check if OS support keylocker.  */
807       if (ebx & bit_AESKLE)
808 	{
809 	  set_feature (FEATURE_AESKLE);
810 	  if (ebx & bit_WIDEKL)
811 	    set_feature (FEATURE_WIDEKL);
812 	  if (has_kl)
813 	    set_feature (FEATURE_KL);
814 	}
815     }
816 
817   /* Check cpuid level of extended features.  */
818   __cpuid (0x80000000, ext_level, ebx, ecx, edx);
819 
820   cpu_model2->__cpu_ext_level = ext_level;
821 
822   if (ext_level >= 0x80000001)
823     {
824       __cpuid (0x80000001, eax, ebx, ecx, edx);
825 
826       if (ecx & bit_SSE4a)
827 	set_feature (FEATURE_SSE4_A);
828       if (ecx & bit_LAHF_LM)
829 	set_feature (FEATURE_LAHF_LM);
830       if (ecx & bit_ABM)
831 	set_feature (FEATURE_ABM);
832       if (ecx & bit_LWP)
833 	set_feature (FEATURE_LWP);
834       if (ecx & bit_TBM)
835 	set_feature (FEATURE_TBM);
836       if (ecx & bit_LZCNT)
837 	set_feature (FEATURE_LZCNT);
838       if (ecx & bit_PRFCHW)
839 	set_feature (FEATURE_PRFCHW);
840       if (ecx & bit_MWAITX)
841 	set_feature (FEATURE_MWAITX);
842 
843       if (edx & bit_LM)
844 	set_feature (FEATURE_LM);
845       if (edx & bit_3DNOWP)
846 	set_feature (FEATURE_3DNOWP);
847       if (edx & bit_3DNOW)
848 	set_feature (FEATURE_3DNOW);
849 
850       if (avx_usable)
851 	{
852 	  if (ecx & bit_FMA4)
853 	    set_feature (FEATURE_FMA4);
854 	  if (ecx & bit_XOP)
855 	    set_feature (FEATURE_XOP);
856 	}
857     }
858 
859   if (ext_level >= 0x80000008)
860     {
861       __cpuid (0x80000008, eax, ebx, ecx, edx);
862       if (ebx & bit_CLZERO)
863 	set_feature (FEATURE_CLZERO);
864       if (ebx & bit_WBNOINVD)
865 	set_feature (FEATURE_WBNOINVD);
866     }
867 
868 #undef set_feature
869 }
870 
871 static inline int
cpu_indicator_init(struct __processor_model * cpu_model,struct __processor_model2 * cpu_model2,unsigned int * cpu_features2)872 cpu_indicator_init (struct __processor_model *cpu_model,
873 		    struct __processor_model2 *cpu_model2,
874 		    unsigned int *cpu_features2)
875 {
876   unsigned int eax, ebx, ecx, edx;
877 
878   int max_level;
879   unsigned int vendor;
880   unsigned int model, family;
881   unsigned int extended_model, extended_family;
882 
883   /* This function needs to run just once.  */
884   if (cpu_model->__cpu_vendor)
885     return 0;
886 
887   /* Assume cpuid insn present. Run in level 0 to get vendor id. */
888   if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
889     {
890       cpu_model->__cpu_vendor = VENDOR_OTHER;
891       return -1;
892     }
893 
894   vendor = ebx;
895   max_level = eax;
896 
897   if (max_level < 1)
898     {
899       cpu_model->__cpu_vendor = VENDOR_OTHER;
900       return -1;
901     }
902 
903   if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
904     {
905       cpu_model->__cpu_vendor = VENDOR_OTHER;
906       return -1;
907     }
908 
909   cpu_model2->__cpu_max_level = max_level;
910 
911   model = (eax >> 4) & 0x0f;
912   family = (eax >> 8) & 0x0f;
913   extended_model = (eax >> 12) & 0xf0;
914   extended_family = (eax >> 20) & 0xff;
915 
916   /* Find available features. */
917   get_available_features (cpu_model, cpu_model2, cpu_features2,
918 			  ecx, edx);
919 
920   if (vendor == signature_INTEL_ebx)
921     {
922       /* Adjust model and family for Intel CPUS. */
923       if (family == 0x0f)
924 	{
925 	  family += extended_family;
926 	  model += extended_model;
927 	}
928       else if (family == 0x06)
929 	model += extended_model;
930 
931       cpu_model2->__cpu_family = family;
932       cpu_model2->__cpu_model = model;
933 
934       /* Get CPU type.  */
935       get_intel_cpu (cpu_model, cpu_model2, cpu_features2);
936       cpu_model->__cpu_vendor = VENDOR_INTEL;
937     }
938   else if (vendor == signature_AMD_ebx)
939     {
940       /* Adjust model and family for AMD CPUS. */
941       if (family == 0x0f)
942 	{
943 	  family += extended_family;
944 	  model += extended_model;
945 	}
946 
947       cpu_model2->__cpu_family = family;
948       cpu_model2->__cpu_model = model;
949 
950       /* Get CPU type.  */
951       get_amd_cpu (cpu_model, cpu_model2, cpu_features2);
952       cpu_model->__cpu_vendor = VENDOR_AMD;
953     }
954   else if (vendor == signature_CENTAUR_ebx)
955     cpu_model->__cpu_vendor = VENDOR_CENTAUR;
956   else if (vendor == signature_CYRIX_ebx)
957     cpu_model->__cpu_vendor = VENDOR_CYRIX;
958   else if (vendor == signature_NSC_ebx)
959     cpu_model->__cpu_vendor = VENDOR_NSC;
960   else
961     cpu_model->__cpu_vendor = VENDOR_OTHER;
962 
963   if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_LM)
964       && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE2))
965     {
966       CHECK___builtin_cpu_supports ("x86-64");
967       set_cpu_feature (cpu_model, cpu_features2,
968 		       FEATURE_X86_64_BASELINE);
969       if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_CMPXCHG16B)
970 	  && has_cpu_feature (cpu_model, cpu_features2, FEATURE_POPCNT)
971 	  && has_cpu_feature (cpu_model, cpu_features2, FEATURE_LAHF_LM)
972 	  && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE4_2))
973 	{
974 	  CHECK___builtin_cpu_supports ("x86-64-v2");
975 	  set_cpu_feature (cpu_model, cpu_features2,
976 			   FEATURE_X86_64_V2);
977 	  if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_AVX2)
978 	      && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI)
979 	      && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI2)
980 	      && has_cpu_feature (cpu_model, cpu_features2, FEATURE_F16C)
981 	      && has_cpu_feature (cpu_model, cpu_features2, FEATURE_FMA)
982 	      && has_cpu_feature (cpu_model, cpu_features2,
983 				  FEATURE_LZCNT)
984 	      && has_cpu_feature (cpu_model, cpu_features2,
985 				  FEATURE_MOVBE))
986 	    {
987 	      CHECK___builtin_cpu_supports ("x86-64-v3");
988 	      set_cpu_feature (cpu_model, cpu_features2,
989 			       FEATURE_X86_64_V3);
990 	      if (has_cpu_feature (cpu_model, cpu_features2,
991 				   FEATURE_AVX512BW)
992 		  && has_cpu_feature (cpu_model, cpu_features2,
993 				      FEATURE_AVX512CD)
994 		  && has_cpu_feature (cpu_model, cpu_features2,
995 				      FEATURE_AVX512DQ)
996 		  && has_cpu_feature (cpu_model, cpu_features2,
997 				      FEATURE_AVX512VL))
998 		{
999 		  CHECK___builtin_cpu_supports ("x86-64-v4");
1000 		  set_cpu_feature (cpu_model, cpu_features2,
1001 				   FEATURE_X86_64_V4);
1002 		}
1003 	    }
1004 	}
1005     }
1006 
1007   gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
1008   gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
1009   gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
1010 
1011   return 0;
1012 }
1013