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