Line data Source code
1 : /* Get CPU type and Features for x86 processors.
2 : Copyright (C) 2012-2026 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
56 174014 : has_cpu_feature (struct __processor_model *cpu_model,
57 : unsigned int *cpu_features2,
58 : enum processor_features feature)
59 : {
60 174014 : unsigned index, offset;
61 0 : unsigned f = feature;
62 :
63 146174 : if (f < 32)
64 : {
65 : /* The first 32 features. */
66 38625 : 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 124253 : f -= 32;
73 124253 : index = f / 32;
74 124253 : offset = f % 32;
75 113117 : return cpu_features2[index] & (1U << offset);
76 : }
77 : }
78 :
79 : /* Save FEATURE to either CPU_MODEL or CPU_FEATURES2. */
80 :
81 : static inline void
82 65424 : set_cpu_feature (struct __processor_model *cpu_model,
83 : unsigned int *cpu_features2,
84 : enum processor_features feature)
85 : {
86 65424 : unsigned index, offset;
87 65424 : unsigned f = feature;
88 :
89 65424 : if (f < 32)
90 : {
91 : /* The first 32 features. */
92 25056 : cpu_model->__cpu_features[0] |= (1U << f);
93 : }
94 : else
95 : {
96 : /* The rest of features. cpu_features2[i] contains features from
97 : (32 + i * 32) to (31 + 32 + i * 32), inclusively. */
98 40368 : f -= 32;
99 40368 : index = f / 32;
100 40368 : offset = f % 32;
101 40368 : cpu_features2[index] |= (1U << offset);
102 : }
103 : }
104 :
105 : /* Drop FEATURE from either CPU_MODEL or CPU_FEATURES2. */
106 :
107 : static inline void
108 0 : reset_cpu_feature (struct __processor_model *cpu_model,
109 : unsigned int *cpu_features2,
110 : enum processor_features feature)
111 : {
112 0 : unsigned index, offset;
113 0 : unsigned f = feature;
114 :
115 0 : if (f < 32)
116 : {
117 : /* The first 32 features. */
118 0 : cpu_model->__cpu_features[0] &= ~(1U << f);
119 : }
120 : else
121 : {
122 : /* The rest of features. cpu_features2[i] contains features from
123 : (32 + i * 32) to (31 + 32 + i * 32), inclusively. */
124 0 : f -= 32;
125 0 : index = f / 32;
126 0 : offset = f % 32;
127 0 : cpu_features2[index] &= ~(1U << offset);
128 : }
129 : }
130 :
131 : /* Get the specific type of AMD CPU and return AMD CPU name. Return
132 : NULL for unknown AMD CPU. */
133 :
134 : static inline const char *
135 1392 : get_amd_cpu (struct __processor_model *cpu_model,
136 : struct __processor_model2 *cpu_model2,
137 : unsigned int *cpu_features2)
138 : {
139 1392 : const char *cpu = NULL;
140 1392 : unsigned int family = cpu_model2->__cpu_family;
141 1392 : unsigned int model = cpu_model2->__cpu_model;
142 :
143 1392 : switch (family)
144 : {
145 0 : case 0x10:
146 : /* AMD Family 10h. */
147 0 : cpu = "amdfam10";
148 0 : cpu_model->__cpu_type = AMDFAM10H;
149 0 : switch (model)
150 : {
151 0 : case 0x2:
152 : /* Barcelona. */
153 0 : CHECK___builtin_cpu_is ("amdfam10h");
154 0 : CHECK___builtin_cpu_is ("barcelona");
155 0 : cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA;
156 0 : break;
157 0 : case 0x4:
158 : /* Shanghai. */
159 0 : CHECK___builtin_cpu_is ("amdfam10h");
160 0 : CHECK___builtin_cpu_is ("shanghai");
161 0 : cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI;
162 0 : break;
163 0 : case 0x8:
164 : /* Istanbul. */
165 0 : CHECK___builtin_cpu_is ("amdfam10h");
166 0 : CHECK___builtin_cpu_is ("istanbul");
167 0 : cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL;
168 0 : break;
169 : default:
170 : break;
171 : }
172 : break;
173 0 : case 0x14:
174 : /* AMD Family 14h "btver1". */
175 0 : cpu = "btver1";
176 0 : CHECK___builtin_cpu_is ("btver1");
177 0 : cpu_model->__cpu_type = AMD_BTVER1;
178 0 : break;
179 0 : case 0x15:
180 : /* AMD Family 15h "Bulldozer". */
181 0 : cpu_model->__cpu_type = AMDFAM15H;
182 0 : if (model == 0x2)
183 : {
184 : /* Bulldozer version 2 "Piledriver" */
185 0 : cpu = "bdver2";
186 0 : CHECK___builtin_cpu_is ("bdver2");
187 0 : cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
188 : }
189 0 : else if (model <= 0xf)
190 : {
191 : /* Bulldozer version 1. */
192 0 : cpu = "bdver1";
193 0 : CHECK___builtin_cpu_is ("bdver1");
194 0 : cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
195 : }
196 0 : else if (model <= 0x2f)
197 : {
198 : /* Bulldozer version 2 "Piledriver" */
199 0 : cpu = "bdver2";
200 0 : CHECK___builtin_cpu_is ("bdver2");
201 0 : cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
202 : }
203 0 : else if (model <= 0x4f)
204 : {
205 : /* Bulldozer version 3 "Steamroller" */
206 0 : cpu = "bdver3";
207 0 : CHECK___builtin_cpu_is ("bdver3");
208 0 : cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
209 : }
210 0 : else if (model <= 0x7f)
211 : {
212 : /* Bulldozer version 4 "Excavator" */
213 0 : cpu = "bdver4";
214 0 : CHECK___builtin_cpu_is ("bdver4");
215 0 : cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
216 : }
217 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
218 : FEATURE_AVX2))
219 : {
220 0 : cpu = "bdver4";
221 0 : CHECK___builtin_cpu_is ("bdver4");
222 0 : cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
223 : }
224 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
225 : FEATURE_XSAVEOPT))
226 : {
227 0 : cpu = "bdver3";
228 0 : CHECK___builtin_cpu_is ("bdver3");
229 0 : cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
230 : }
231 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
232 : FEATURE_BMI))
233 : {
234 0 : cpu = "bdver2";
235 0 : CHECK___builtin_cpu_is ("bdver2");
236 0 : cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
237 : }
238 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
239 : FEATURE_XOP))
240 : {
241 0 : cpu = "bdver1";
242 0 : CHECK___builtin_cpu_is ("bdver1");
243 0 : cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
244 : }
245 : break;
246 0 : case 0x16:
247 : /* AMD Family 16h "btver2" */
248 0 : cpu = "btver2";
249 0 : CHECK___builtin_cpu_is ("btver2");
250 0 : cpu_model->__cpu_type = AMD_BTVER2;
251 0 : break;
252 1392 : case 0x17:
253 1392 : cpu_model->__cpu_type = AMDFAM17H;
254 1392 : if (model <= 0x1f)
255 : {
256 : /* AMD family 17h version 1. */
257 0 : cpu = "znver1";
258 0 : CHECK___builtin_cpu_is ("znver1");
259 0 : cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
260 : }
261 1392 : else if (model >= 0x30)
262 : {
263 1392 : cpu = "znver2";
264 1392 : CHECK___builtin_cpu_is ("znver2");
265 1392 : cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
266 : }
267 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
268 : FEATURE_CLWB))
269 : {
270 0 : cpu = "znver2";
271 0 : CHECK___builtin_cpu_is ("znver2");
272 0 : cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
273 : }
274 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
275 : FEATURE_CLZERO))
276 : {
277 0 : cpu = "znver1";
278 0 : CHECK___builtin_cpu_is ("znver1");
279 0 : cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
280 : }
281 : break;
282 0 : case 0x19:
283 0 : cpu_model->__cpu_type = AMDFAM19H;
284 : /* AMD family 19h. */
285 0 : if (model <= 0x0f)
286 : {
287 0 : cpu = "znver3";
288 0 : CHECK___builtin_cpu_is ("znver3");
289 0 : cpu_model->__cpu_subtype = AMDFAM19H_ZNVER3;
290 : }
291 0 : else if ((model >= 0x10 && model <= 0x1f)
292 0 : || (model >= 0x60 && model <= 0xaf))
293 : {
294 0 : cpu = "znver4";
295 0 : CHECK___builtin_cpu_is ("znver4");
296 0 : cpu_model->__cpu_subtype = AMDFAM19H_ZNVER4;
297 : }
298 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
299 : FEATURE_AVX512F))
300 : {
301 0 : cpu = "znver4";
302 0 : CHECK___builtin_cpu_is ("znver4");
303 0 : cpu_model->__cpu_subtype = AMDFAM19H_ZNVER4;
304 : }
305 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
306 : FEATURE_VAES))
307 : {
308 0 : cpu = "znver3";
309 0 : CHECK___builtin_cpu_is ("znver3");
310 0 : cpu_model->__cpu_subtype = AMDFAM19H_ZNVER3;
311 : }
312 : break;
313 0 : case 0x1a:
314 0 : cpu_model->__cpu_type = AMDFAM1AH;
315 0 : if (model <= 0x4f || (model >= 0x60 && model <= 0x77) ||
316 0 : (model >= 0xd0 && model <= 0xd7))
317 : {
318 0 : cpu = "znver5";
319 0 : CHECK___builtin_cpu_is ("znver5");
320 0 : cpu_model->__cpu_subtype = AMDFAM1AH_ZNVER5;
321 : }
322 0 : else if ((model >= 0x50 && model <= 0x5f) ||
323 0 : (model >= 0x80 && model <= 0xcf) ||
324 0 : (model >= 0xd8 && model <= 0xe7))
325 : {
326 0 : cpu = "znver6";
327 0 : CHECK___builtin_cpu_is ("znver6");
328 0 : cpu_model->__cpu_subtype = AMDFAM1AH_ZNVER6;
329 : }
330 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
331 : FEATURE_AVX512VP2INTERSECT))
332 : {
333 0 : cpu = "znver5";
334 0 : CHECK___builtin_cpu_is ("znver5");
335 0 : cpu_model->__cpu_subtype = AMDFAM1AH_ZNVER5;
336 : }
337 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
338 : FEATURE_AVX512BMM))
339 : {
340 0 : cpu = "znver6";
341 0 : CHECK___builtin_cpu_is ("znver6");
342 0 : cpu_model->__cpu_subtype = AMDFAM1AH_ZNVER6;
343 : }
344 : break;
345 : default:
346 : break;
347 : }
348 :
349 1392 : return cpu;
350 : }
351 :
352 : /* Get the specific type of HYGON CPU and return HYGON CPU name. Return
353 : NULL for unknown HYGON CPU. */
354 :
355 : static inline const char *
356 0 : get_hygon_cpu (struct __processor_model *cpu_model,
357 : struct __processor_model2 *cpu_model2,
358 : unsigned int *cpu_features2 __attribute__((unused)))
359 : {
360 0 : const char *cpu = NULL;
361 0 : unsigned int family = cpu_model2->__cpu_family;
362 0 : unsigned int model = cpu_model2->__cpu_model;
363 :
364 0 : switch (family)
365 : {
366 0 : case 0x18:
367 0 : cpu_model->__cpu_type = HYGONFAM18H;
368 0 : if (model == 0x4)
369 : {
370 0 : cpu = "c86-4g-m4";
371 0 : CHECK___builtin_cpu_is ("c86-4g-m4");
372 0 : cpu_model->__cpu_subtype = HYGONFAM18H_C86_4G_M4;
373 : }
374 0 : else if (model == 0x6)
375 : {
376 0 : cpu = "c86-4g-m6";
377 0 : CHECK___builtin_cpu_is ("c86-4g-m6");
378 0 : cpu_model->__cpu_subtype = HYGONFAM18H_C86_4G_M6;
379 : }
380 0 : else if (model == 0x7)
381 : {
382 0 : cpu = "c86-4g-m7";
383 0 : CHECK___builtin_cpu_is ("c86-4g-m7");
384 0 : cpu_model->__cpu_subtype = HYGONFAM18H_C86_4G_M7;
385 : }
386 0 : else if (model == 0x8)
387 : {
388 0 : cpu = "c86-4g-m8";
389 0 : CHECK___builtin_cpu_is ("c86-4g-m8");
390 0 : cpu_model->__cpu_subtype = HYGONFAM18H_C86_4G_M8;
391 : }
392 : break;
393 : default:
394 : break;
395 : }
396 :
397 0 : return cpu;
398 : }
399 :
400 : /* Get the specific type of Intel CPU and return Intel CPU name. Return
401 : NULL for unknown Intel CPU. */
402 :
403 : static inline const char *
404 0 : get_intel_cpu (struct __processor_model *cpu_model,
405 : struct __processor_model2 *cpu_model2,
406 : unsigned int *cpu_features2)
407 : {
408 0 : const char *cpu = NULL;
409 :
410 : /* Parse family and model for family 0x6. */
411 0 : if (cpu_model2->__cpu_family == 0x6)
412 0 : switch (cpu_model2->__cpu_model)
413 : {
414 0 : case 0x1c:
415 0 : case 0x26:
416 : /* Bonnell. */
417 0 : cpu = "bonnell";
418 0 : CHECK___builtin_cpu_is ("atom");
419 0 : cpu_model->__cpu_type = INTEL_BONNELL;
420 0 : break;
421 0 : case 0x37:
422 0 : case 0x4a:
423 0 : case 0x4d:
424 0 : case 0x5d:
425 : /* Silvermont. */
426 0 : case 0x4c:
427 0 : case 0x5a:
428 0 : case 0x75:
429 : /* Airmont. */
430 0 : cpu = "silvermont";
431 0 : CHECK___builtin_cpu_is ("silvermont");
432 0 : cpu_model->__cpu_type = INTEL_SILVERMONT;
433 0 : break;
434 0 : case 0x5c:
435 0 : case 0x5f:
436 : /* Goldmont. */
437 0 : cpu = "goldmont";
438 0 : CHECK___builtin_cpu_is ("goldmont");
439 0 : cpu_model->__cpu_type = INTEL_GOLDMONT;
440 0 : break;
441 0 : case 0x7a:
442 : /* Goldmont Plus. */
443 0 : cpu = "goldmont-plus";
444 0 : CHECK___builtin_cpu_is ("goldmont-plus");
445 0 : cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
446 0 : break;
447 0 : case 0x86:
448 0 : case 0x96:
449 0 : case 0x9c:
450 : /* Tremont. */
451 0 : cpu = "tremont";
452 0 : CHECK___builtin_cpu_is ("tremont");
453 0 : cpu_model->__cpu_type = INTEL_TREMONT;
454 0 : break;
455 0 : case 0x17:
456 0 : case 0x1d:
457 : /* Penryn. */
458 0 : case 0x0f:
459 : /* Merom. */
460 0 : cpu = "core2";
461 0 : CHECK___builtin_cpu_is ("core2");
462 0 : cpu_model->__cpu_type = INTEL_CORE2;
463 0 : break;
464 0 : case 0x1a:
465 0 : case 0x1e:
466 0 : case 0x1f:
467 0 : case 0x2e:
468 : /* Nehalem. */
469 0 : cpu = "nehalem";
470 0 : CHECK___builtin_cpu_is ("corei7");
471 0 : CHECK___builtin_cpu_is ("nehalem");
472 0 : cpu_model->__cpu_type = INTEL_COREI7;
473 0 : cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
474 0 : break;
475 0 : case 0x25:
476 0 : case 0x2c:
477 0 : case 0x2f:
478 : /* Westmere. */
479 0 : cpu = "westmere";
480 0 : CHECK___builtin_cpu_is ("corei7");
481 0 : CHECK___builtin_cpu_is ("westmere");
482 0 : cpu_model->__cpu_type = INTEL_COREI7;
483 0 : cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
484 0 : break;
485 0 : case 0x2a:
486 0 : case 0x2d:
487 : /* Sandy Bridge. */
488 0 : cpu = "sandybridge";
489 0 : CHECK___builtin_cpu_is ("corei7");
490 0 : CHECK___builtin_cpu_is ("sandybridge");
491 0 : cpu_model->__cpu_type = INTEL_COREI7;
492 0 : cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
493 0 : break;
494 0 : case 0x3a:
495 0 : case 0x3e:
496 : /* Ivy Bridge. */
497 0 : cpu = "ivybridge";
498 0 : CHECK___builtin_cpu_is ("corei7");
499 0 : CHECK___builtin_cpu_is ("ivybridge");
500 0 : cpu_model->__cpu_type = INTEL_COREI7;
501 0 : cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
502 0 : break;
503 0 : case 0x3c:
504 0 : case 0x3f:
505 0 : case 0x45:
506 0 : case 0x46:
507 : /* Haswell. */
508 0 : cpu = "haswell";
509 0 : CHECK___builtin_cpu_is ("corei7");
510 0 : CHECK___builtin_cpu_is ("haswell");
511 0 : cpu_model->__cpu_type = INTEL_COREI7;
512 0 : cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
513 0 : break;
514 0 : case 0x3d:
515 0 : case 0x47:
516 0 : case 0x4f:
517 0 : case 0x56:
518 : /* Broadwell. */
519 0 : cpu = "broadwell";
520 0 : CHECK___builtin_cpu_is ("corei7");
521 0 : CHECK___builtin_cpu_is ("broadwell");
522 0 : cpu_model->__cpu_type = INTEL_COREI7;
523 0 : cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
524 0 : break;
525 0 : case 0x4e:
526 0 : case 0x5e:
527 : /* Skylake. */
528 0 : case 0x8e:
529 0 : case 0x9e:
530 : /* Kaby Lake. */
531 0 : case 0xa5:
532 0 : case 0xa6:
533 : /* Comet Lake. */
534 0 : cpu = "skylake";
535 0 : CHECK___builtin_cpu_is ("corei7");
536 0 : CHECK___builtin_cpu_is ("skylake");
537 0 : cpu_model->__cpu_type = INTEL_COREI7;
538 0 : cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
539 0 : break;
540 0 : case 0x55:
541 0 : CHECK___builtin_cpu_is ("corei7");
542 0 : cpu_model->__cpu_type = INTEL_COREI7;
543 0 : if (has_cpu_feature (cpu_model, cpu_features2,
544 : FEATURE_AVX512BF16))
545 : {
546 : /* Cooper Lake. */
547 0 : cpu = "cooperlake";
548 0 : CHECK___builtin_cpu_is ("cooperlake");
549 0 : cpu_model->__cpu_subtype = INTEL_COREI7_COOPERLAKE;
550 : }
551 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
552 : FEATURE_AVX512VNNI))
553 : {
554 : /* Cascade Lake. */
555 0 : cpu = "cascadelake";
556 0 : CHECK___builtin_cpu_is ("cascadelake");
557 0 : cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
558 : }
559 : else
560 : {
561 : /* Skylake with AVX-512 support. */
562 0 : cpu = "skylake-avx512";
563 0 : CHECK___builtin_cpu_is ("skylake-avx512");
564 0 : cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
565 : }
566 : break;
567 0 : case 0x66:
568 : /* Cannon Lake. */
569 0 : cpu = "cannonlake";
570 0 : CHECK___builtin_cpu_is ("corei7");
571 0 : CHECK___builtin_cpu_is ("cannonlake");
572 0 : cpu_model->__cpu_type = INTEL_COREI7;
573 0 : cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
574 0 : break;
575 0 : case 0x7e:
576 0 : case 0x7d:
577 0 : case 0x9d:
578 : /* Ice Lake client. */
579 0 : cpu = "icelake-client";
580 0 : CHECK___builtin_cpu_is ("corei7");
581 0 : CHECK___builtin_cpu_is ("icelake-client");
582 0 : cpu_model->__cpu_type = INTEL_COREI7;
583 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
584 0 : break;
585 0 : case 0x6a:
586 0 : case 0x6c:
587 : /* Ice Lake server. */
588 0 : cpu = "icelake-server";
589 0 : CHECK___builtin_cpu_is ("corei7");
590 0 : CHECK___builtin_cpu_is ("icelake-server");
591 0 : cpu_model->__cpu_type = INTEL_COREI7;
592 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
593 0 : break;
594 0 : case 0xa7:
595 : /* Rocket Lake. */
596 0 : cpu = "rocketlake";
597 0 : CHECK___builtin_cpu_is ("corei7");
598 0 : CHECK___builtin_cpu_is ("rocketlake");
599 0 : cpu_model->__cpu_type = INTEL_COREI7;
600 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ROCKETLAKE;
601 0 : break;
602 0 : case 0x8c:
603 0 : case 0x8d:
604 : /* Tiger Lake. */
605 0 : cpu = "tigerlake";
606 0 : CHECK___builtin_cpu_is ("corei7");
607 0 : CHECK___builtin_cpu_is ("tigerlake");
608 0 : cpu_model->__cpu_type = INTEL_COREI7;
609 0 : cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
610 0 : break;
611 0 : case 0xbe:
612 : /* Alder Lake N, E-core only. */
613 0 : case 0x97:
614 0 : case 0x9a:
615 : /* Alder Lake. */
616 0 : case 0xb7:
617 0 : case 0xba:
618 0 : case 0xbf:
619 : /* Raptor Lake. */
620 0 : case 0xaa:
621 0 : case 0xac:
622 : /* Meteor Lake. */
623 0 : cpu = "alderlake";
624 0 : CHECK___builtin_cpu_is ("corei7");
625 0 : CHECK___builtin_cpu_is ("alderlake");
626 0 : cpu_model->__cpu_type = INTEL_COREI7;
627 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ALDERLAKE;
628 0 : break;
629 0 : case 0x8f:
630 : /* Sapphire Rapids. */
631 0 : case 0xcf:
632 : /* Emerald Rapids. */
633 0 : cpu = "sapphirerapids";
634 0 : CHECK___builtin_cpu_is ("corei7");
635 0 : CHECK___builtin_cpu_is ("sapphirerapids");
636 0 : cpu_model->__cpu_type = INTEL_COREI7;
637 0 : cpu_model->__cpu_subtype = INTEL_COREI7_SAPPHIRERAPIDS;
638 0 : break;
639 0 : case 0xaf:
640 : /* Sierra Forest. */
641 0 : cpu = "sierraforest";
642 0 : CHECK___builtin_cpu_is ("sierraforest");
643 0 : cpu_model->__cpu_type = INTEL_SIERRAFOREST;
644 0 : break;
645 0 : case 0xad:
646 : /* Granite Rapids. */
647 0 : cpu = "graniterapids";
648 0 : CHECK___builtin_cpu_is ("corei7");
649 0 : CHECK___builtin_cpu_is ("graniterapids");
650 0 : cpu_model->__cpu_type = INTEL_COREI7;
651 0 : cpu_model->__cpu_subtype = INTEL_COREI7_GRANITERAPIDS;
652 0 : break;
653 0 : case 0xae:
654 : /* Granite Rapids D. */
655 0 : cpu = "graniterapids-d";
656 0 : CHECK___builtin_cpu_is ("corei7");
657 0 : CHECK___builtin_cpu_is ("graniterapids-d");
658 0 : cpu_model->__cpu_type = INTEL_COREI7;
659 0 : cpu_model->__cpu_subtype = INTEL_COREI7_GRANITERAPIDS_D;
660 0 : break;
661 0 : case 0xb6:
662 : /* Grand Ridge. */
663 0 : cpu = "grandridge";
664 0 : CHECK___builtin_cpu_is ("grandridge");
665 0 : cpu_model->__cpu_type = INTEL_GRANDRIDGE;
666 0 : break;
667 0 : case 0xb5:
668 0 : case 0xc5:
669 : /* Arrow Lake. */
670 0 : cpu = "arrowlake";
671 0 : CHECK___builtin_cpu_is ("corei7");
672 0 : CHECK___builtin_cpu_is ("arrowlake");
673 0 : cpu_model->__cpu_type = INTEL_COREI7;
674 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ARROWLAKE;
675 0 : break;
676 0 : case 0xc6:
677 : /* Arrow Lake S. */
678 0 : case 0xbd:
679 : /* Lunar Lake. */
680 0 : cpu = "arrowlake-s";
681 0 : CHECK___builtin_cpu_is ("corei7");
682 0 : CHECK___builtin_cpu_is ("arrowlake-s");
683 0 : cpu_model->__cpu_type = INTEL_COREI7;
684 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ARROWLAKE_S;
685 0 : break;
686 0 : case 0xdd:
687 : /* Clearwater Forest. */
688 0 : cpu = "clearwaterforest";
689 0 : CHECK___builtin_cpu_is ("clearwaterforest");
690 0 : cpu_model->__cpu_type = INTEL_CLEARWATERFOREST;
691 0 : break;
692 0 : case 0xcc:
693 : /* Panther Lake. */
694 0 : case 0xd5:
695 : /* Wildcat Lake. */
696 0 : cpu = "pantherlake";
697 0 : CHECK___builtin_cpu_is ("corei7");
698 0 : CHECK___builtin_cpu_is ("pantherlake");
699 0 : cpu_model->__cpu_type = INTEL_COREI7;
700 0 : cpu_model->__cpu_subtype = INTEL_COREI7_PANTHERLAKE;
701 0 : break;
702 : default:
703 : break;
704 : }
705 : /* Parse family and model for family 0x12. */
706 0 : else if (cpu_model2->__cpu_family == 0x12)
707 0 : switch (cpu_model2->__cpu_model)
708 : {
709 0 : case 0x01:
710 0 : case 0x03:
711 : /* Nova Lake. */
712 0 : cpu = "novalake";
713 0 : CHECK___builtin_cpu_is ("corei7");
714 0 : CHECK___builtin_cpu_is ("novalake");
715 0 : cpu_model->__cpu_type = INTEL_COREI7;
716 0 : cpu_model->__cpu_subtype = INTEL_COREI7_NOVALAKE;
717 0 : break;
718 : default:
719 : break;
720 : }
721 : /* Parse family and model for family 0x13. */
722 0 : else if (cpu_model2->__cpu_family == 0x13)
723 0 : switch (cpu_model2->__cpu_model)
724 : {
725 0 : case 0x01:
726 : /* Diamond Rapids. */
727 0 : cpu = "diamondrapids";
728 0 : CHECK___builtin_cpu_is ("corei7");
729 0 : CHECK___builtin_cpu_is ("diamondrapids");
730 0 : cpu_model->__cpu_type = INTEL_COREI7;
731 0 : cpu_model->__cpu_subtype = INTEL_COREI7_DIAMONDRAPIDS;
732 0 : break;
733 : default:
734 : break;
735 : }
736 :
737 0 : return cpu;
738 : }
739 :
740 : /* Get the specific type of ZHAOXIN CPU and return ZHAOXIN CPU name.
741 : Return NULL for unknown ZHAOXIN CPU. */
742 :
743 : static inline const char *
744 0 : get_zhaoxin_cpu (struct __processor_model *cpu_model,
745 : struct __processor_model2 *cpu_model2,
746 : unsigned int *cpu_features2)
747 : {
748 0 : const char *cpu = NULL;
749 0 : unsigned int family = cpu_model2->__cpu_family;
750 0 : unsigned int model = cpu_model2->__cpu_model;
751 :
752 0 : switch (family)
753 : {
754 : /* ZHAOXIN family 7h. */
755 0 : case 0x07:
756 0 : cpu_model->__cpu_type = ZHAOXIN_FAM7H;
757 0 : if (model == 0x3b)
758 : {
759 0 : cpu = "lujiazui";
760 0 : CHECK___builtin_cpu_is ("lujiazui");
761 0 : reset_cpu_feature (cpu_model, cpu_features2, FEATURE_AVX);
762 0 : reset_cpu_feature (cpu_model, cpu_features2, FEATURE_F16C);
763 0 : cpu_model->__cpu_subtype = ZHAOXIN_FAM7H_LUJIAZUI;
764 : }
765 0 : else if (model == 0x5b)
766 : {
767 0 : cpu = "yongfeng";
768 0 : CHECK___builtin_cpu_is ("yongfeng");
769 0 : cpu_model->__cpu_subtype = ZHAOXIN_FAM7H_YONGFENG;
770 : }
771 0 : else if (model >= 0x6b)
772 : {
773 0 : cpu = "shijidadao";
774 0 : CHECK___builtin_cpu_is ("shijidadao");
775 0 : cpu_model->__cpu_subtype = ZHAOXIN_FAM7H_SHIJIDADAO;
776 : }
777 : break;
778 : default:
779 : break;
780 : }
781 :
782 0 : return cpu;
783 : }
784 :
785 : /* ECX and EDX are output of CPUID at level one. */
786 : static inline void
787 1392 : get_available_features (struct __processor_model *cpu_model,
788 : struct __processor_model2 *cpu_model2,
789 : unsigned int *cpu_features2,
790 : unsigned int ecx, unsigned int edx)
791 : {
792 1392 : unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
793 1392 : unsigned int eax, ebx;
794 1392 : unsigned int ext_level;
795 :
796 : /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */
797 : #define XCR_XFEATURE_ENABLED_MASK 0x0
798 : #define XSTATE_FP 0x1
799 : #define XSTATE_SSE 0x2
800 : #define XSTATE_YMM 0x4
801 : #define XSTATE_OPMASK 0x20
802 : #define XSTATE_ZMM 0x40
803 : #define XSTATE_HI_ZMM 0x80
804 : #define XSTATE_TILECFG 0x20000
805 : #define XSTATE_TILEDATA 0x40000
806 : #define XSTATE_APX_F 0x80000
807 : #define XSTATE_BSR 0x100000
808 :
809 : #define XCR_AVX_ENABLED_MASK \
810 : (XSTATE_SSE | XSTATE_YMM)
811 : #define XCR_AVX512F_ENABLED_MASK \
812 : (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
813 : #define XCR_AMX_ENABLED_MASK \
814 : (XSTATE_TILECFG | XSTATE_TILEDATA)
815 : #define XCR_ACE_ENABLED_MASK \
816 : (XSTATE_TILECFG | XSTATE_TILEDATA | XSTATE_BSR)
817 : #define XCR_APX_F_ENABLED_MASK XSTATE_APX_F
818 :
819 : /* Check if AVX, AVX512, AMX, APX and ACE are usable. */
820 1392 : int avx_usable = 0;
821 1392 : int avx512_usable = 0;
822 1392 : int amx_usable = 0;
823 1392 : int apx_usable = 0;
824 1392 : int ace_usable = 0;
825 : /* Check if KL is usable. */
826 1392 : int has_kl = 0;
827 : /* Record AVX10 version. */
828 1392 : int avx10_set = 0;
829 1392 : int ace_set = 0, avx10v2aux_set = 0;
830 1392 : int version = 0;
831 1392 : if ((ecx & bit_OSXSAVE))
832 : {
833 : /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
834 : ZMM16-ZMM31 states are supported by OSXSAVE. */
835 1392 : unsigned int xcrlow;
836 1392 : unsigned int xcrhigh;
837 1392 : __asm__ (".byte 0x0f, 0x01, 0xd0"
838 : : "=a" (xcrlow), "=d" (xcrhigh)
839 : : "c" (XCR_XFEATURE_ENABLED_MASK));
840 1392 : if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
841 : {
842 1392 : avx_usable = 1;
843 1392 : avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
844 1392 : == XCR_AVX512F_ENABLED_MASK);
845 : }
846 1392 : amx_usable = ((xcrlow & XCR_AMX_ENABLED_MASK)
847 1392 : == XCR_AMX_ENABLED_MASK);
848 1392 : apx_usable = ((xcrlow & XCR_APX_F_ENABLED_MASK)
849 1392 : == XCR_APX_F_ENABLED_MASK);
850 1392 : ace_usable = ((xcrlow & XCR_ACE_ENABLED_MASK)
851 1392 : == XCR_ACE_ENABLED_MASK);
852 : }
853 :
854 : #define set_feature(f) \
855 : set_cpu_feature (cpu_model, cpu_features2, f)
856 :
857 1392 : if (edx & bit_CMOV)
858 1392 : set_feature (FEATURE_CMOV);
859 1392 : if (edx & bit_MMX)
860 1392 : set_feature (FEATURE_MMX);
861 1392 : if (edx & bit_SSE)
862 1392 : set_feature (FEATURE_SSE);
863 1392 : if (edx & bit_SSE2)
864 1392 : set_feature (FEATURE_SSE2);
865 1392 : if (edx & bit_CMPXCHG8B)
866 1392 : set_feature (FEATURE_CMPXCHG8B);
867 1392 : if (edx & bit_FXSAVE)
868 1392 : set_feature (FEATURE_FXSAVE);
869 :
870 1392 : if (ecx & bit_POPCNT)
871 1392 : set_feature (FEATURE_POPCNT);
872 1392 : if (ecx & bit_AES)
873 1392 : set_feature (FEATURE_AES);
874 1392 : if (ecx & bit_PCLMUL)
875 1392 : set_feature (FEATURE_PCLMUL);
876 1392 : if (ecx & bit_SSE3)
877 1392 : set_feature (FEATURE_SSE3);
878 1392 : if (ecx & bit_SSSE3)
879 1392 : set_feature (FEATURE_SSSE3);
880 1392 : if (ecx & bit_SSE4_1)
881 1392 : set_feature (FEATURE_SSE4_1);
882 1392 : if (ecx & bit_SSE4_2)
883 1392 : set_feature (FEATURE_SSE4_2);
884 1392 : if (ecx & bit_OSXSAVE)
885 1392 : set_feature (FEATURE_OSXSAVE);
886 1392 : if (ecx & bit_CMPXCHG16B)
887 1392 : set_feature (FEATURE_CMPXCHG16B);
888 1392 : if (ecx & bit_MOVBE)
889 1392 : set_feature (FEATURE_MOVBE);
890 1392 : if (ecx & bit_AES)
891 1392 : set_feature (FEATURE_AES);
892 1392 : if (ecx & bit_RDRND)
893 1392 : set_feature (FEATURE_RDRND);
894 1392 : if (ecx & bit_XSAVE)
895 1392 : set_feature (FEATURE_XSAVE);
896 1392 : if (avx_usable)
897 : {
898 1392 : if (ecx & bit_AVX)
899 1392 : set_feature (FEATURE_AVX);
900 1392 : if (ecx & bit_FMA)
901 1392 : set_feature (FEATURE_FMA);
902 1392 : if (ecx & bit_F16C)
903 1392 : set_feature (FEATURE_F16C);
904 : }
905 :
906 : /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
907 1392 : if (max_cpuid_level >= 7)
908 : {
909 1392 : unsigned int max_subleaf_level;
910 :
911 1392 : __cpuid_count (7, 0, max_subleaf_level, ebx, ecx, edx);
912 1392 : if (ebx & bit_BMI)
913 1392 : set_feature (FEATURE_BMI);
914 1392 : if (ebx & bit_SGX)
915 0 : set_feature (FEATURE_SGX);
916 1392 : if (ebx & bit_HLE)
917 0 : set_feature (FEATURE_HLE);
918 1392 : if (ebx & bit_RTM)
919 0 : set_feature (FEATURE_RTM);
920 1392 : if (avx_usable)
921 : {
922 1392 : if (ebx & bit_AVX2)
923 1392 : set_feature (FEATURE_AVX2);
924 1392 : if (ecx & bit_VPCLMULQDQ)
925 0 : set_feature (FEATURE_VPCLMULQDQ);
926 1392 : if (ecx & bit_VAES)
927 0 : set_feature (FEATURE_VAES);
928 : }
929 1392 : if (ebx & bit_BMI2)
930 1392 : set_feature (FEATURE_BMI2);
931 1392 : if (ebx & bit_FSGSBASE)
932 1392 : set_feature (FEATURE_FSGSBASE);
933 1392 : if (ebx & bit_RDSEED)
934 1392 : set_feature (FEATURE_RDSEED);
935 1392 : if (ebx & bit_ADX)
936 1392 : set_feature (FEATURE_ADX);
937 1392 : if (ebx & bit_SHA)
938 1392 : set_feature (FEATURE_SHA);
939 1392 : if (ebx & bit_CLFLUSHOPT)
940 1392 : set_feature (FEATURE_CLFLUSHOPT);
941 1392 : if (ebx & bit_CLWB)
942 1392 : set_feature (FEATURE_CLWB);
943 : /* NB: bit_OSPKE indicates that OS supports PKU. */
944 1392 : if (ecx & bit_OSPKE)
945 0 : set_feature (FEATURE_PKU);
946 1392 : if (ecx & bit_RDPID)
947 1392 : set_feature (FEATURE_RDPID);
948 1392 : if (ecx & bit_GFNI)
949 0 : set_feature (FEATURE_GFNI);
950 1392 : if (ecx & bit_MOVDIRI)
951 0 : set_feature (FEATURE_MOVDIRI);
952 1392 : if (ecx & bit_MOVDIR64B)
953 0 : set_feature (FEATURE_MOVDIR64B);
954 1392 : if (ecx & bit_ENQCMD)
955 0 : set_feature (FEATURE_ENQCMD);
956 1392 : if (ecx & bit_CLDEMOTE)
957 0 : set_feature (FEATURE_CLDEMOTE);
958 1392 : if (ecx & bit_WAITPKG)
959 0 : set_feature (FEATURE_WAITPKG);
960 1392 : if (ecx & bit_SHSTK)
961 0 : set_feature (FEATURE_SHSTK);
962 1392 : if (ecx & bit_KL)
963 0 : has_kl = 1;
964 1392 : if (edx & bit_SERIALIZE)
965 0 : set_feature (FEATURE_SERIALIZE);
966 1392 : if (edx & bit_TSXLDTRK)
967 0 : set_feature (FEATURE_TSXLDTRK);
968 1392 : if (edx & bit_PCONFIG)
969 0 : set_feature (FEATURE_PCONFIG);
970 1392 : if (edx & bit_IBT)
971 0 : set_feature (FEATURE_IBT);
972 1392 : if (edx & bit_UINTR)
973 0 : set_feature (FEATURE_UINTR);
974 1392 : if (amx_usable)
975 : {
976 0 : if (edx & bit_AMX_TILE)
977 0 : set_feature (FEATURE_AMX_TILE);
978 0 : if (edx & bit_AMX_INT8)
979 0 : set_feature (FEATURE_AMX_INT8);
980 0 : if (edx & bit_AMX_BF16)
981 0 : set_feature (FEATURE_AMX_BF16);
982 : }
983 1392 : if (avx512_usable)
984 : {
985 0 : if (ebx & bit_AVX512F)
986 0 : set_feature (FEATURE_AVX512F);
987 0 : if (ebx & bit_AVX512VL)
988 0 : set_feature (FEATURE_AVX512VL);
989 0 : if (ebx & bit_AVX512BW)
990 0 : set_feature (FEATURE_AVX512BW);
991 0 : if (ebx & bit_AVX512DQ)
992 0 : set_feature (FEATURE_AVX512DQ);
993 0 : if (ebx & bit_AVX512CD)
994 0 : set_feature (FEATURE_AVX512CD);
995 0 : if (ebx & bit_AVX512IFMA)
996 0 : set_feature (FEATURE_AVX512IFMA);
997 0 : if (ecx & bit_AVX512VBMI)
998 0 : set_feature (FEATURE_AVX512VBMI);
999 0 : if (ecx & bit_AVX512VBMI2)
1000 0 : set_feature (FEATURE_AVX512VBMI2);
1001 0 : if (ecx & bit_AVX512VNNI)
1002 0 : set_feature (FEATURE_AVX512VNNI);
1003 0 : if (ecx & bit_AVX512BITALG)
1004 0 : set_feature (FEATURE_AVX512BITALG);
1005 0 : if (ecx & bit_AVX512VPOPCNTDQ)
1006 0 : set_feature (FEATURE_AVX512VPOPCNTDQ);
1007 0 : if (edx & bit_AVX512VP2INTERSECT)
1008 0 : set_feature (FEATURE_AVX512VP2INTERSECT);
1009 0 : if (edx & bit_AVX512FP16)
1010 0 : set_feature (FEATURE_AVX512FP16);
1011 : }
1012 :
1013 1392 : if (max_subleaf_level >= 1)
1014 : {
1015 0 : __cpuid_count (7, 1, eax, ebx, ecx, edx);
1016 0 : if (eax & bit_HRESET)
1017 0 : set_feature (FEATURE_HRESET);
1018 0 : if (eax & bit_CMPCCXADD)
1019 0 : set_feature(FEATURE_CMPCCXADD);
1020 0 : if (edx & bit_PREFETCHI)
1021 0 : set_feature (FEATURE_PREFETCHI);
1022 0 : if (eax & bit_RAOINT)
1023 0 : set_feature (FEATURE_RAOINT);
1024 0 : if (edx & bit_USER_MSR)
1025 0 : set_feature (FEATURE_USER_MSR);
1026 0 : if (eax & bit_MOVRS)
1027 0 : set_feature (FEATURE_MOVRS);
1028 0 : if (avx_usable)
1029 : {
1030 0 : if (eax & bit_AVXVNNI)
1031 0 : set_feature (FEATURE_AVXVNNI);
1032 0 : if (eax & bit_AVXIFMA)
1033 0 : set_feature (FEATURE_AVXIFMA);
1034 0 : if (edx & bit_AVXVNNIINT8)
1035 0 : set_feature (FEATURE_AVXVNNIINT8);
1036 0 : if (edx & bit_AVXNECONVERT)
1037 0 : set_feature (FEATURE_AVXNECONVERT);
1038 0 : if (edx & bit_AVXVNNIINT16)
1039 0 : set_feature (FEATURE_AVXVNNIINT16);
1040 0 : if (eax & bit_SM3)
1041 0 : set_feature (FEATURE_SM3);
1042 0 : if (eax & bit_SHA512)
1043 0 : set_feature (FEATURE_SHA512);
1044 0 : if (eax & bit_SM4)
1045 0 : set_feature (FEATURE_SM4);
1046 : }
1047 0 : if (avx512_usable)
1048 : {
1049 0 : if (eax & bit_AVX512BF16)
1050 0 : set_feature (FEATURE_AVX512BF16);
1051 : /* AVX10 has the same XSTATE with AVX512. */
1052 0 : if (edx & bit_AVX10)
1053 0 : avx10_set = 1;
1054 : }
1055 0 : if (avx10_set)
1056 : {
1057 : /* The XSTATE for vector registers has been checked
1058 : when setting avx10_set. */
1059 0 : if (ace_usable)
1060 0 : if (ecx & bit_ACE)
1061 0 : ace_set = 1;
1062 : }
1063 0 : if (amx_usable)
1064 : {
1065 0 : if (eax & bit_AMX_FP16)
1066 0 : set_feature (FEATURE_AMX_FP16);
1067 0 : if (edx & bit_AMX_COMPLEX)
1068 0 : set_feature (FEATURE_AMX_COMPLEX);
1069 : }
1070 0 : if (apx_usable)
1071 : {
1072 0 : if (edx & bit_APX_F)
1073 0 : set_feature (FEATURE_APX_F);
1074 : }
1075 : }
1076 : }
1077 :
1078 : /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
1079 1392 : if (max_cpuid_level >= 0xd)
1080 : {
1081 1392 : __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
1082 1392 : if (eax & bit_XSAVEOPT)
1083 1392 : set_feature (FEATURE_XSAVEOPT);
1084 1392 : if (eax & bit_XSAVEC)
1085 1392 : set_feature (FEATURE_XSAVEC);
1086 1392 : if (eax & bit_XSAVES)
1087 1392 : set_feature (FEATURE_XSAVES);
1088 : }
1089 :
1090 : /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */
1091 1392 : if (max_cpuid_level >= 0x14)
1092 : {
1093 0 : __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
1094 0 : if (ebx & bit_PTWRITE)
1095 0 : set_feature (FEATURE_PTWRITE);
1096 : }
1097 :
1098 : /* Get Advanced Features at level 0x19 (eax = 0x19). */
1099 0 : if (max_cpuid_level >= 0x19)
1100 : {
1101 0 : __cpuid (0x19, eax, ebx, ecx, edx);
1102 : /* Check if OS support keylocker. */
1103 0 : if (ebx & bit_AESKLE)
1104 : {
1105 0 : set_feature (FEATURE_AESKLE);
1106 0 : if (ebx & bit_WIDEKL)
1107 0 : set_feature (FEATURE_WIDEKL);
1108 0 : if (has_kl)
1109 0 : set_feature (FEATURE_KL);
1110 : }
1111 : }
1112 :
1113 : /* Get Advanced Features at level 0x1e (eax = 0x1e, ecx = 1). */
1114 0 : if (max_cpuid_level >= 0x1e)
1115 : {
1116 0 : __cpuid_count (0x1e, 1, eax, ebx, ecx, edx);
1117 0 : if (amx_usable)
1118 : {
1119 0 : if (eax & bit_AMX_AVX512)
1120 0 : set_feature (FEATURE_AMX_AVX512);
1121 0 : if (eax & bit_AMX_FP8)
1122 0 : set_feature (FEATURE_AMX_FP8);
1123 0 : if (eax & bit_AMX_MOVRS)
1124 0 : set_feature (FEATURE_AMX_MOVRS);
1125 : }
1126 : }
1127 :
1128 : /* Get Advanced Features at level 0x24 (eax = 0x24, ecx = 0). */
1129 1392 : if (avx10_set && max_cpuid_level >= 0x24)
1130 : {
1131 0 : unsigned int max_subleaf_level;
1132 :
1133 0 : __cpuid_count (0x24, 0, max_subleaf_level, ebx, ecx, edx);
1134 0 : version = ebx & 0xff;
1135 0 : switch (version)
1136 : {
1137 0 : case 2:
1138 0 : set_feature (FEATURE_AVX10_2);
1139 : /* Fall through. */
1140 0 : case 1:
1141 0 : set_feature (FEATURE_AVX10_1);
1142 0 : break;
1143 0 : default:
1144 0 : set_feature (FEATURE_AVX10_1);
1145 0 : break;
1146 : }
1147 0 : if (max_subleaf_level >= 1)
1148 : {
1149 0 : __cpuid_count (0x24, 1, eax, ebx, ecx, edx);
1150 0 : if (ecx & bit_AVX10V2AUX)
1151 : {
1152 0 : set_feature (FEATURE_AVX10V2AUX);
1153 0 : avx10v2aux_set = 1;
1154 : }
1155 : }
1156 : }
1157 :
1158 : /* Get Advanced Features at level 0x1d (eax = 0x1d).
1159 : ACE check must be put after AVX10 check to get AVX10 features.
1160 : TODO: Change the condition after AVX10V1AUX is added. */
1161 1392 : if (version >= 2 && avx10v2aux_set && ace_set && max_cpuid_level >= 0x1d)
1162 : {
1163 0 : __cpuid_count (0x1d, 0, eax, ebx, ecx, edx);
1164 0 : if (eax == 2)
1165 : {
1166 0 : __cpuid_count (0x1d, 2, eax, ebx, ecx, edx);
1167 0 : version = eax & 0xff;
1168 0 : switch (version)
1169 : {
1170 0 : case 1:
1171 0 : set_feature (FEATURE_ACEV1);
1172 0 : break;
1173 0 : default:
1174 0 : set_feature (FEATURE_ACEV1);
1175 0 : break;
1176 : }
1177 : }
1178 : }
1179 :
1180 : /* Check cpuid level of extended features. */
1181 1392 : __cpuid (0x80000000, ext_level, ebx, ecx, edx);
1182 :
1183 1392 : cpu_model2->__cpu_ext_level = ext_level;
1184 :
1185 1392 : if (ext_level >= 0x80000001)
1186 : {
1187 1392 : __cpuid (0x80000001, eax, ebx, ecx, edx);
1188 :
1189 1392 : if (ecx & bit_SSE4a)
1190 1392 : set_feature (FEATURE_SSE4_A);
1191 1392 : if (ecx & bit_LAHF_LM)
1192 1392 : set_feature (FEATURE_LAHF_LM);
1193 1392 : if (ecx & bit_ABM)
1194 1392 : set_feature (FEATURE_ABM);
1195 1392 : if (ecx & bit_LWP)
1196 0 : set_feature (FEATURE_LWP);
1197 1392 : if (ecx & bit_TBM)
1198 0 : set_feature (FEATURE_TBM);
1199 1392 : if (ecx & bit_LZCNT)
1200 1392 : set_feature (FEATURE_LZCNT);
1201 1392 : if (ecx & bit_PRFCHW)
1202 1392 : set_feature (FEATURE_PRFCHW);
1203 1392 : if (ecx & bit_MWAITX)
1204 1392 : set_feature (FEATURE_MWAITX);
1205 :
1206 1392 : if (edx & bit_LM)
1207 1392 : set_feature (FEATURE_LM);
1208 1392 : if (edx & bit_3DNOWP)
1209 0 : set_feature (FEATURE_3DNOWP);
1210 1392 : if (edx & bit_3DNOW)
1211 0 : set_feature (FEATURE_3DNOW);
1212 :
1213 1392 : if (avx_usable)
1214 : {
1215 1392 : if (ecx & bit_FMA4)
1216 0 : set_feature (FEATURE_FMA4);
1217 1392 : if (ecx & bit_XOP)
1218 0 : set_feature (FEATURE_XOP);
1219 : }
1220 : }
1221 :
1222 1392 : if (ext_level >= 0x80000008)
1223 : {
1224 1392 : __cpuid (0x80000008, eax, ebx, ecx, edx);
1225 1392 : if (ebx & bit_CLZERO)
1226 1392 : set_feature (FEATURE_CLZERO);
1227 1392 : if (ebx & bit_WBNOINVD)
1228 1392 : set_feature (FEATURE_WBNOINVD);
1229 : }
1230 :
1231 1392 : if (ext_level >= 0x80000021)
1232 : {
1233 0 : __cpuid (0x80000021, eax, ebx, ecx, edx);
1234 0 : if (eax & bit_AMD_PREFETCHI)
1235 0 : set_feature (FEATURE_PREFETCHI);
1236 0 : if (eax & bit_AVX512BMM)
1237 0 : set_feature (FEATURE_AVX512BMM);
1238 : }
1239 :
1240 : #undef set_feature
1241 1392 : }
1242 :
1243 : static inline int
1244 1392 : cpu_indicator_init (struct __processor_model *cpu_model,
1245 : struct __processor_model2 *cpu_model2,
1246 : unsigned int *cpu_features2)
1247 : {
1248 1392 : unsigned int eax, ebx, ecx, edx;
1249 :
1250 1392 : int max_level;
1251 1392 : unsigned int vendor;
1252 1392 : unsigned int model, family;
1253 1392 : unsigned int extended_model, extended_family;
1254 :
1255 : /* This function needs to run just once. */
1256 1392 : if (cpu_model->__cpu_vendor)
1257 : return 0;
1258 :
1259 : /* Assume cpuid insn present. Run in level 0 to get vendor id. */
1260 1392 : if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
1261 : {
1262 0 : cpu_model->__cpu_vendor = VENDOR_OTHER;
1263 0 : return -1;
1264 : }
1265 :
1266 1392 : vendor = ebx;
1267 1392 : max_level = eax;
1268 :
1269 1392 : if (max_level < 1)
1270 : {
1271 0 : cpu_model->__cpu_vendor = VENDOR_OTHER;
1272 0 : return -1;
1273 : }
1274 :
1275 1392 : if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
1276 : {
1277 0 : cpu_model->__cpu_vendor = VENDOR_OTHER;
1278 0 : return -1;
1279 : }
1280 :
1281 1392 : cpu_model2->__cpu_max_level = max_level;
1282 :
1283 1392 : model = (eax >> 4) & 0x0f;
1284 1392 : family = (eax >> 8) & 0x0f;
1285 1392 : extended_model = (eax >> 12) & 0xf0;
1286 1392 : extended_family = (eax >> 20) & 0xff;
1287 :
1288 : /* Find available features. */
1289 1392 : get_available_features (cpu_model, cpu_model2, cpu_features2,
1290 : ecx, edx);
1291 :
1292 1392 : if (vendor == signature_INTEL_ebx)
1293 : {
1294 : /* Adjust model and family for Intel CPUS. */
1295 0 : if (family == 0x0f)
1296 : {
1297 0 : family += extended_family;
1298 0 : model += extended_model;
1299 : }
1300 0 : else if (family == 0x06)
1301 0 : model += extended_model;
1302 :
1303 0 : cpu_model2->__cpu_family = family;
1304 0 : cpu_model2->__cpu_model = model;
1305 :
1306 : /* Get CPU type. */
1307 0 : get_intel_cpu (cpu_model, cpu_model2, cpu_features2);
1308 0 : cpu_model->__cpu_vendor = VENDOR_INTEL;
1309 : }
1310 1392 : else if (vendor == signature_AMD_ebx)
1311 : {
1312 : /* Adjust model and family for AMD CPUS. */
1313 1392 : if (family == 0x0f)
1314 : {
1315 1392 : family += extended_family;
1316 1392 : model += extended_model;
1317 : }
1318 :
1319 1392 : cpu_model2->__cpu_family = family;
1320 1392 : cpu_model2->__cpu_model = model;
1321 :
1322 : /* Get CPU type. */
1323 1392 : get_amd_cpu (cpu_model, cpu_model2, cpu_features2);
1324 1392 : cpu_model->__cpu_vendor = VENDOR_AMD;
1325 : }
1326 0 : else if (vendor == signature_CENTAUR_ebx && family < 0x07)
1327 0 : cpu_model->__cpu_vendor = VENDOR_CENTAUR;
1328 0 : else if (vendor == signature_SHANGHAI_ebx
1329 0 : || vendor == signature_CENTAUR_ebx)
1330 : {
1331 : /* Adjust model and family for ZHAOXIN CPUS. */
1332 0 : if (family == 0x07)
1333 0 : model += extended_model;
1334 :
1335 0 : cpu_model2->__cpu_family = family;
1336 0 : cpu_model2->__cpu_model = model;
1337 :
1338 : /* Get CPU type. */
1339 0 : get_zhaoxin_cpu (cpu_model, cpu_model2, cpu_features2);
1340 0 : cpu_model->__cpu_vendor = VENDOR_ZHAOXIN;
1341 : }
1342 0 : else if (vendor == signature_CYRIX_ebx)
1343 0 : cpu_model->__cpu_vendor = VENDOR_CYRIX;
1344 0 : else if (vendor == signature_NSC_ebx)
1345 0 : cpu_model->__cpu_vendor = VENDOR_NSC;
1346 0 : else if (vendor == signature_HYGON_ebx)
1347 : {
1348 : /* Adjust model and family for HYGON CPUS. */
1349 0 : if (family == 0x0f)
1350 : {
1351 0 : family += extended_family;
1352 0 : model += extended_model;
1353 : }
1354 0 : cpu_model2->__cpu_family = family;
1355 0 : cpu_model2->__cpu_model = model;
1356 :
1357 : /* Get CPU type. */
1358 0 : get_hygon_cpu (cpu_model, cpu_model2, cpu_features2);
1359 0 : cpu_model->__cpu_vendor = VENDOR_HYGON;
1360 : }
1361 : else
1362 0 : cpu_model->__cpu_vendor = VENDOR_OTHER;
1363 :
1364 1392 : if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_LM)
1365 1392 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE2))
1366 : {
1367 1392 : CHECK___builtin_cpu_supports ("x86-64");
1368 1392 : set_cpu_feature (cpu_model, cpu_features2,
1369 : FEATURE_X86_64_BASELINE);
1370 1392 : if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_CMPXCHG16B)
1371 1392 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_POPCNT)
1372 1392 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_LAHF_LM)
1373 2784 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE4_2))
1374 : {
1375 1392 : CHECK___builtin_cpu_supports ("x86-64-v2");
1376 1392 : set_cpu_feature (cpu_model, cpu_features2,
1377 : FEATURE_X86_64_V2);
1378 1392 : if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_AVX2)
1379 1392 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI)
1380 1392 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI2)
1381 1392 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_F16C)
1382 1392 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_FMA)
1383 1392 : && has_cpu_feature (cpu_model, cpu_features2,
1384 : FEATURE_LZCNT)
1385 2784 : && has_cpu_feature (cpu_model, cpu_features2,
1386 : FEATURE_MOVBE))
1387 : {
1388 1392 : CHECK___builtin_cpu_supports ("x86-64-v3");
1389 1392 : set_cpu_feature (cpu_model, cpu_features2,
1390 : FEATURE_X86_64_V3);
1391 1392 : if (has_cpu_feature (cpu_model, cpu_features2,
1392 : FEATURE_AVX512BW)
1393 0 : && has_cpu_feature (cpu_model, cpu_features2,
1394 : FEATURE_AVX512CD)
1395 0 : && has_cpu_feature (cpu_model, cpu_features2,
1396 : FEATURE_AVX512DQ)
1397 1392 : && has_cpu_feature (cpu_model, cpu_features2,
1398 : FEATURE_AVX512VL))
1399 : {
1400 0 : CHECK___builtin_cpu_supports ("x86-64-v4");
1401 0 : set_cpu_feature (cpu_model, cpu_features2,
1402 : FEATURE_X86_64_V4);
1403 : }
1404 : }
1405 : }
1406 : }
1407 :
1408 1392 : gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
1409 1392 : gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
1410 1392 : gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
1411 :
1412 : return 0;
1413 : }
|