Branch data Line data Source code
1 : : /* Get CPU type and Features for x86 processors.
2 : : Copyright (C) 2012-2025 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 : 164660 : has_cpu_feature (struct __processor_model *cpu_model,
57 : : unsigned int *cpu_features2,
58 : : enum processor_features feature)
59 : : {
60 : 164660 : unsigned index, offset;
61 : 164660 : unsigned f = feature;
62 : :
63 : 139048 : if (f < 32)
64 : : {
65 : : /* The first 32 features. */
66 : 37447 : 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 : 116429 : f -= 32;
73 : 116429 : index = f / 32;
74 : 116429 : offset = f % 32;
75 : 106993 : 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 : 63356 : set_cpu_feature (struct __processor_model *cpu_model,
83 : : unsigned int *cpu_features2,
84 : : enum processor_features feature)
85 : : {
86 : 63356 : unsigned index, offset;
87 : 63356 : unsigned f = feature;
88 : :
89 : 63356 : if (f < 32)
90 : : {
91 : : /* The first 32 features. */
92 : 24264 : 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 : 39092 : f -= 32;
99 : 39092 : index = f / 32;
100 : 39092 : offset = f % 32;
101 : 39092 : cpu_features2[index] |= (1U << offset);
102 : : }
103 : 59312 : }
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 : 1348 : get_amd_cpu (struct __processor_model *cpu_model,
136 : : struct __processor_model2 *cpu_model2,
137 : : unsigned int *cpu_features2)
138 : : {
139 : 1348 : const char *cpu = NULL;
140 : 1348 : unsigned int family = cpu_model2->__cpu_family;
141 : 1348 : unsigned int model = cpu_model2->__cpu_model;
142 : :
143 : 1348 : 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 : 1348 : case 0x17:
253 : 1348 : cpu_model->__cpu_type = AMDFAM17H;
254 : 1348 : 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 : 1348 : else if (model >= 0x30)
262 : : {
263 : 1348 : cpu = "znver2";
264 : 1348 : CHECK___builtin_cpu_is ("znver2");
265 : 1348 : 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 (has_cpu_feature (cpu_model, cpu_features2,
323 : : FEATURE_AVX512VP2INTERSECT))
324 : : {
325 : 0 : cpu = "znver5";
326 : 0 : CHECK___builtin_cpu_is ("znver5");
327 : 0 : cpu_model->__cpu_subtype = AMDFAM1AH_ZNVER5;
328 : : }
329 : : break;
330 : : default:
331 : : break;
332 : : }
333 : :
334 : 1348 : return cpu;
335 : : }
336 : :
337 : : /* Get the specific type of Intel CPU and return Intel CPU name. Return
338 : : NULL for unknown Intel CPU. */
339 : :
340 : : static inline const char *
341 : 0 : get_intel_cpu (struct __processor_model *cpu_model,
342 : : struct __processor_model2 *cpu_model2,
343 : : unsigned int *cpu_features2)
344 : : {
345 : 0 : const char *cpu = NULL;
346 : :
347 : : /* Parse family and model for family 0x6. */
348 : 0 : if (cpu_model2->__cpu_family == 0x6)
349 : 0 : switch (cpu_model2->__cpu_model)
350 : : {
351 : 0 : case 0x1c:
352 : 0 : case 0x26:
353 : : /* Bonnell. */
354 : 0 : cpu = "bonnell";
355 : 0 : CHECK___builtin_cpu_is ("atom");
356 : 0 : cpu_model->__cpu_type = INTEL_BONNELL;
357 : 0 : break;
358 : 0 : case 0x37:
359 : 0 : case 0x4a:
360 : 0 : case 0x4d:
361 : 0 : case 0x5d:
362 : : /* Silvermont. */
363 : 0 : case 0x4c:
364 : 0 : case 0x5a:
365 : 0 : case 0x75:
366 : : /* Airmont. */
367 : 0 : cpu = "silvermont";
368 : 0 : CHECK___builtin_cpu_is ("silvermont");
369 : 0 : cpu_model->__cpu_type = INTEL_SILVERMONT;
370 : 0 : break;
371 : 0 : case 0x5c:
372 : 0 : case 0x5f:
373 : : /* Goldmont. */
374 : 0 : cpu = "goldmont";
375 : 0 : CHECK___builtin_cpu_is ("goldmont");
376 : 0 : cpu_model->__cpu_type = INTEL_GOLDMONT;
377 : 0 : break;
378 : 0 : case 0x7a:
379 : : /* Goldmont Plus. */
380 : 0 : cpu = "goldmont-plus";
381 : 0 : CHECK___builtin_cpu_is ("goldmont-plus");
382 : 0 : cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
383 : 0 : break;
384 : 0 : case 0x86:
385 : 0 : case 0x96:
386 : 0 : case 0x9c:
387 : : /* Tremont. */
388 : 0 : cpu = "tremont";
389 : 0 : CHECK___builtin_cpu_is ("tremont");
390 : 0 : cpu_model->__cpu_type = INTEL_TREMONT;
391 : 0 : break;
392 : 0 : case 0x17:
393 : 0 : case 0x1d:
394 : : /* Penryn. */
395 : 0 : case 0x0f:
396 : : /* Merom. */
397 : 0 : cpu = "core2";
398 : 0 : CHECK___builtin_cpu_is ("core2");
399 : 0 : cpu_model->__cpu_type = INTEL_CORE2;
400 : 0 : break;
401 : 0 : case 0x1a:
402 : 0 : case 0x1e:
403 : 0 : case 0x1f:
404 : 0 : case 0x2e:
405 : : /* Nehalem. */
406 : 0 : cpu = "nehalem";
407 : 0 : CHECK___builtin_cpu_is ("corei7");
408 : 0 : CHECK___builtin_cpu_is ("nehalem");
409 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
410 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
411 : 0 : break;
412 : 0 : case 0x25:
413 : 0 : case 0x2c:
414 : 0 : case 0x2f:
415 : : /* Westmere. */
416 : 0 : cpu = "westmere";
417 : 0 : CHECK___builtin_cpu_is ("corei7");
418 : 0 : CHECK___builtin_cpu_is ("westmere");
419 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
420 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
421 : 0 : break;
422 : 0 : case 0x2a:
423 : 0 : case 0x2d:
424 : : /* Sandy Bridge. */
425 : 0 : cpu = "sandybridge";
426 : 0 : CHECK___builtin_cpu_is ("corei7");
427 : 0 : CHECK___builtin_cpu_is ("sandybridge");
428 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
429 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
430 : 0 : break;
431 : 0 : case 0x3a:
432 : 0 : case 0x3e:
433 : : /* Ivy Bridge. */
434 : 0 : cpu = "ivybridge";
435 : 0 : CHECK___builtin_cpu_is ("corei7");
436 : 0 : CHECK___builtin_cpu_is ("ivybridge");
437 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
438 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
439 : 0 : break;
440 : 0 : case 0x3c:
441 : 0 : case 0x3f:
442 : 0 : case 0x45:
443 : 0 : case 0x46:
444 : : /* Haswell. */
445 : 0 : cpu = "haswell";
446 : 0 : CHECK___builtin_cpu_is ("corei7");
447 : 0 : CHECK___builtin_cpu_is ("haswell");
448 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
449 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
450 : 0 : break;
451 : 0 : case 0x3d:
452 : 0 : case 0x47:
453 : 0 : case 0x4f:
454 : 0 : case 0x56:
455 : : /* Broadwell. */
456 : 0 : cpu = "broadwell";
457 : 0 : CHECK___builtin_cpu_is ("corei7");
458 : 0 : CHECK___builtin_cpu_is ("broadwell");
459 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
460 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
461 : 0 : break;
462 : 0 : case 0x4e:
463 : 0 : case 0x5e:
464 : : /* Skylake. */
465 : 0 : case 0x8e:
466 : 0 : case 0x9e:
467 : : /* Kaby Lake. */
468 : 0 : case 0xa5:
469 : 0 : case 0xa6:
470 : : /* Comet Lake. */
471 : 0 : cpu = "skylake";
472 : 0 : CHECK___builtin_cpu_is ("corei7");
473 : 0 : CHECK___builtin_cpu_is ("skylake");
474 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
475 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
476 : 0 : break;
477 : 0 : case 0x55:
478 : 0 : CHECK___builtin_cpu_is ("corei7");
479 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
480 : 0 : if (has_cpu_feature (cpu_model, cpu_features2,
481 : : FEATURE_AVX512BF16))
482 : : {
483 : : /* Cooper Lake. */
484 : 0 : cpu = "cooperlake";
485 : 0 : CHECK___builtin_cpu_is ("cooperlake");
486 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_COOPERLAKE;
487 : : }
488 : 0 : else if (has_cpu_feature (cpu_model, cpu_features2,
489 : : FEATURE_AVX512VNNI))
490 : : {
491 : : /* Cascade Lake. */
492 : 0 : cpu = "cascadelake";
493 : 0 : CHECK___builtin_cpu_is ("cascadelake");
494 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
495 : : }
496 : : else
497 : : {
498 : : /* Skylake with AVX-512 support. */
499 : 0 : cpu = "skylake-avx512";
500 : 0 : CHECK___builtin_cpu_is ("skylake-avx512");
501 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
502 : : }
503 : : break;
504 : 0 : case 0x66:
505 : : /* Cannon Lake. */
506 : 0 : cpu = "cannonlake";
507 : 0 : CHECK___builtin_cpu_is ("corei7");
508 : 0 : CHECK___builtin_cpu_is ("cannonlake");
509 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
510 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
511 : 0 : break;
512 : 0 : case 0x7e:
513 : 0 : case 0x7d:
514 : 0 : case 0x9d:
515 : : /* Ice Lake client. */
516 : 0 : cpu = "icelake-client";
517 : 0 : CHECK___builtin_cpu_is ("corei7");
518 : 0 : CHECK___builtin_cpu_is ("icelake-client");
519 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
520 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
521 : 0 : break;
522 : 0 : case 0x6a:
523 : 0 : case 0x6c:
524 : : /* Ice Lake server. */
525 : 0 : cpu = "icelake-server";
526 : 0 : CHECK___builtin_cpu_is ("corei7");
527 : 0 : CHECK___builtin_cpu_is ("icelake-server");
528 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
529 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
530 : 0 : break;
531 : 0 : case 0xa7:
532 : : /* Rocket Lake. */
533 : 0 : cpu = "rocketlake";
534 : 0 : CHECK___builtin_cpu_is ("corei7");
535 : 0 : CHECK___builtin_cpu_is ("rocketlake");
536 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
537 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ROCKETLAKE;
538 : 0 : break;
539 : 0 : case 0x8c:
540 : 0 : case 0x8d:
541 : : /* Tiger Lake. */
542 : 0 : cpu = "tigerlake";
543 : 0 : CHECK___builtin_cpu_is ("corei7");
544 : 0 : CHECK___builtin_cpu_is ("tigerlake");
545 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
546 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
547 : 0 : break;
548 : 0 : case 0xbe:
549 : : /* Alder Lake N, E-core only. */
550 : 0 : case 0x97:
551 : 0 : case 0x9a:
552 : : /* Alder Lake. */
553 : 0 : case 0xb7:
554 : 0 : case 0xba:
555 : 0 : case 0xbf:
556 : : /* Raptor Lake. */
557 : 0 : case 0xaa:
558 : 0 : case 0xac:
559 : : /* Meteor Lake. */
560 : 0 : cpu = "alderlake";
561 : 0 : CHECK___builtin_cpu_is ("corei7");
562 : 0 : CHECK___builtin_cpu_is ("alderlake");
563 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
564 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ALDERLAKE;
565 : 0 : break;
566 : 0 : case 0x8f:
567 : : /* Sapphire Rapids. */
568 : 0 : case 0xcf:
569 : : /* Emerald Rapids. */
570 : 0 : cpu = "sapphirerapids";
571 : 0 : CHECK___builtin_cpu_is ("corei7");
572 : 0 : CHECK___builtin_cpu_is ("sapphirerapids");
573 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
574 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_SAPPHIRERAPIDS;
575 : 0 : break;
576 : 0 : case 0xaf:
577 : : /* Sierra Forest. */
578 : 0 : cpu = "sierraforest";
579 : 0 : CHECK___builtin_cpu_is ("sierraforest");
580 : 0 : cpu_model->__cpu_type = INTEL_SIERRAFOREST;
581 : 0 : break;
582 : 0 : case 0xad:
583 : : /* Granite Rapids. */
584 : 0 : cpu = "graniterapids";
585 : 0 : CHECK___builtin_cpu_is ("corei7");
586 : 0 : CHECK___builtin_cpu_is ("graniterapids");
587 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
588 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_GRANITERAPIDS;
589 : 0 : break;
590 : 0 : case 0xae:
591 : : /* Granite Rapids D. */
592 : 0 : cpu = "graniterapids-d";
593 : 0 : CHECK___builtin_cpu_is ("corei7");
594 : 0 : CHECK___builtin_cpu_is ("graniterapids-d");
595 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
596 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_GRANITERAPIDS_D;
597 : 0 : break;
598 : 0 : case 0xb6:
599 : : /* Grand Ridge. */
600 : 0 : cpu = "grandridge";
601 : 0 : CHECK___builtin_cpu_is ("grandridge");
602 : 0 : cpu_model->__cpu_type = INTEL_GRANDRIDGE;
603 : 0 : break;
604 : 0 : case 0xb5:
605 : 0 : case 0xc5:
606 : : /* Arrow Lake. */
607 : 0 : cpu = "arrowlake";
608 : 0 : CHECK___builtin_cpu_is ("corei7");
609 : 0 : CHECK___builtin_cpu_is ("arrowlake");
610 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
611 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ARROWLAKE;
612 : 0 : break;
613 : 0 : case 0xc6:
614 : : /* Arrow Lake S. */
615 : 0 : case 0xbd:
616 : : /* Lunar Lake. */
617 : 0 : cpu = "arrowlake-s";
618 : 0 : CHECK___builtin_cpu_is ("corei7");
619 : 0 : CHECK___builtin_cpu_is ("arrowlake-s");
620 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
621 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_ARROWLAKE_S;
622 : 0 : break;
623 : 0 : case 0xdd:
624 : : /* Clearwater Forest. */
625 : 0 : cpu = "clearwaterforest";
626 : 0 : CHECK___builtin_cpu_is ("clearwaterforest");
627 : 0 : cpu_model->__cpu_type = INTEL_CLEARWATERFOREST;
628 : 0 : break;
629 : 0 : case 0xcc:
630 : : /* Panther Lake. */
631 : 0 : case 0xd5:
632 : : /* Wildcat Lake. */
633 : 0 : cpu = "pantherlake";
634 : 0 : CHECK___builtin_cpu_is ("corei7");
635 : 0 : CHECK___builtin_cpu_is ("pantherlake");
636 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
637 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_PANTHERLAKE;
638 : 0 : break;
639 : : default:
640 : : break;
641 : : }
642 : : /* Parse family and model for family 0x12. */
643 : 0 : else if (cpu_model2->__cpu_family == 0x12)
644 : 0 : switch (cpu_model2->__cpu_model)
645 : : {
646 : 0 : case 0x01:
647 : 0 : case 0x03:
648 : : /* Nova Lake. */
649 : 0 : cpu = "novalake";
650 : 0 : CHECK___builtin_cpu_is ("corei7");
651 : 0 : CHECK___builtin_cpu_is ("novalake");
652 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
653 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_NOVALAKE;
654 : 0 : break;
655 : : default:
656 : : break;
657 : : }
658 : : /* Parse family and model for family 0x13. */
659 : 0 : else if (cpu_model2->__cpu_family == 0x13)
660 : 0 : switch (cpu_model2->__cpu_model)
661 : : {
662 : 0 : case 0x01:
663 : : /* Diamond Rapids. */
664 : 0 : cpu = "diamondrapids";
665 : 0 : CHECK___builtin_cpu_is ("corei7");
666 : 0 : CHECK___builtin_cpu_is ("diamondrapids");
667 : 0 : cpu_model->__cpu_type = INTEL_COREI7;
668 : 0 : cpu_model->__cpu_subtype = INTEL_COREI7_DIAMONDRAPIDS;
669 : 0 : break;
670 : : default:
671 : : break;
672 : : }
673 : :
674 : 0 : return cpu;
675 : : }
676 : :
677 : : /* Get the specific type of ZHAOXIN CPU and return ZHAOXIN CPU name.
678 : : Return NULL for unknown ZHAOXIN CPU. */
679 : :
680 : : static inline const char *
681 : 0 : get_zhaoxin_cpu (struct __processor_model *cpu_model,
682 : : struct __processor_model2 *cpu_model2,
683 : : unsigned int *cpu_features2)
684 : : {
685 : 0 : const char *cpu = NULL;
686 : 0 : unsigned int family = cpu_model2->__cpu_family;
687 : 0 : unsigned int model = cpu_model2->__cpu_model;
688 : :
689 : 0 : switch (family)
690 : : {
691 : : /* ZHAOXIN family 7h. */
692 : 0 : case 0x07:
693 : 0 : cpu_model->__cpu_type = ZHAOXIN_FAM7H;
694 : 0 : if (model == 0x3b)
695 : : {
696 : 0 : cpu = "lujiazui";
697 : 0 : CHECK___builtin_cpu_is ("lujiazui");
698 : 0 : reset_cpu_feature (cpu_model, cpu_features2, FEATURE_AVX);
699 : 0 : reset_cpu_feature (cpu_model, cpu_features2, FEATURE_F16C);
700 : 0 : cpu_model->__cpu_subtype = ZHAOXIN_FAM7H_LUJIAZUI;
701 : : }
702 : 0 : else if (model == 0x5b)
703 : : {
704 : 0 : cpu = "yongfeng";
705 : 0 : CHECK___builtin_cpu_is ("yongfeng");
706 : 0 : cpu_model->__cpu_subtype = ZHAOXIN_FAM7H_YONGFENG;
707 : : }
708 : 0 : else if (model >= 0x6b)
709 : : {
710 : 0 : cpu = "shijidadao";
711 : 0 : CHECK___builtin_cpu_is ("shijidadao");
712 : 0 : cpu_model->__cpu_subtype = ZHAOXIN_FAM7H_SHIJIDADAO;
713 : : }
714 : : break;
715 : : default:
716 : : break;
717 : : }
718 : :
719 : 0 : return cpu;
720 : : }
721 : :
722 : : /* ECX and EDX are output of CPUID at level one. */
723 : : static inline void
724 : 1348 : get_available_features (struct __processor_model *cpu_model,
725 : : struct __processor_model2 *cpu_model2,
726 : : unsigned int *cpu_features2,
727 : : unsigned int ecx, unsigned int edx)
728 : : {
729 : 1348 : unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
730 : 1348 : unsigned int eax, ebx;
731 : 1348 : unsigned int ext_level;
732 : :
733 : : /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */
734 : : #define XCR_XFEATURE_ENABLED_MASK 0x0
735 : : #define XSTATE_FP 0x1
736 : : #define XSTATE_SSE 0x2
737 : : #define XSTATE_YMM 0x4
738 : : #define XSTATE_OPMASK 0x20
739 : : #define XSTATE_ZMM 0x40
740 : : #define XSTATE_HI_ZMM 0x80
741 : : #define XSTATE_TILECFG 0x20000
742 : : #define XSTATE_TILEDATA 0x40000
743 : : #define XSTATE_APX_F 0x80000
744 : :
745 : : #define XCR_AVX_ENABLED_MASK \
746 : : (XSTATE_SSE | XSTATE_YMM)
747 : : #define XCR_AVX512F_ENABLED_MASK \
748 : : (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
749 : : #define XCR_AMX_ENABLED_MASK \
750 : : (XSTATE_TILECFG | XSTATE_TILEDATA)
751 : : #define XCR_APX_F_ENABLED_MASK XSTATE_APX_F
752 : :
753 : : /* Check if AVX, AVX512 and APX are usable. */
754 : 1348 : int avx_usable = 0;
755 : 1348 : int avx512_usable = 0;
756 : 1348 : int amx_usable = 0;
757 : 1348 : int apx_usable = 0;
758 : : /* Check if KL is usable. */
759 : 1348 : int has_kl = 0;
760 : : /* Record AVX10 version. */
761 : 1348 : int avx10_set = 0;
762 : 1348 : int version = 0;
763 : 1348 : if ((ecx & bit_OSXSAVE))
764 : : {
765 : : /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
766 : : ZMM16-ZMM31 states are supported by OSXSAVE. */
767 : 1348 : unsigned int xcrlow;
768 : 1348 : unsigned int xcrhigh;
769 : 1348 : __asm__ (".byte 0x0f, 0x01, 0xd0"
770 : : : "=a" (xcrlow), "=d" (xcrhigh)
771 : : : "c" (XCR_XFEATURE_ENABLED_MASK));
772 : 1348 : if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
773 : : {
774 : 1348 : avx_usable = 1;
775 : 1348 : avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
776 : 1348 : == XCR_AVX512F_ENABLED_MASK);
777 : : }
778 : 1348 : amx_usable = ((xcrlow & XCR_AMX_ENABLED_MASK)
779 : 1348 : == XCR_AMX_ENABLED_MASK);
780 : 1348 : apx_usable = ((xcrlow & XCR_APX_F_ENABLED_MASK)
781 : 1348 : == XCR_APX_F_ENABLED_MASK);
782 : : }
783 : :
784 : : #define set_feature(f) \
785 : : set_cpu_feature (cpu_model, cpu_features2, f)
786 : :
787 : 1348 : if (edx & bit_CMOV)
788 : 1348 : set_feature (FEATURE_CMOV);
789 : 1348 : if (edx & bit_MMX)
790 : 1348 : set_feature (FEATURE_MMX);
791 : 1348 : if (edx & bit_SSE)
792 : 1348 : set_feature (FEATURE_SSE);
793 : 1348 : if (edx & bit_SSE2)
794 : 1348 : set_feature (FEATURE_SSE2);
795 : 1348 : if (edx & bit_CMPXCHG8B)
796 : 1348 : set_feature (FEATURE_CMPXCHG8B);
797 : 1348 : if (edx & bit_FXSAVE)
798 : 1348 : set_feature (FEATURE_FXSAVE);
799 : :
800 : 1348 : if (ecx & bit_POPCNT)
801 : 1348 : set_feature (FEATURE_POPCNT);
802 : 1348 : if (ecx & bit_AES)
803 : 1348 : set_feature (FEATURE_AES);
804 : 1348 : if (ecx & bit_PCLMUL)
805 : 1348 : set_feature (FEATURE_PCLMUL);
806 : 1348 : if (ecx & bit_SSE3)
807 : 1348 : set_feature (FEATURE_SSE3);
808 : 1348 : if (ecx & bit_SSSE3)
809 : 1348 : set_feature (FEATURE_SSSE3);
810 : 1348 : if (ecx & bit_SSE4_1)
811 : 1348 : set_feature (FEATURE_SSE4_1);
812 : 1348 : if (ecx & bit_SSE4_2)
813 : 1348 : set_feature (FEATURE_SSE4_2);
814 : 1348 : if (ecx & bit_OSXSAVE)
815 : 1348 : set_feature (FEATURE_OSXSAVE);
816 : 1348 : if (ecx & bit_CMPXCHG16B)
817 : 1348 : set_feature (FEATURE_CMPXCHG16B);
818 : 1348 : if (ecx & bit_MOVBE)
819 : 1348 : set_feature (FEATURE_MOVBE);
820 : 1348 : if (ecx & bit_AES)
821 : 1348 : set_feature (FEATURE_AES);
822 : 1348 : if (ecx & bit_RDRND)
823 : 1348 : set_feature (FEATURE_RDRND);
824 : 1348 : if (ecx & bit_XSAVE)
825 : 1348 : set_feature (FEATURE_XSAVE);
826 : 1348 : if (avx_usable)
827 : : {
828 : 1348 : if (ecx & bit_AVX)
829 : 1348 : set_feature (FEATURE_AVX);
830 : 1348 : if (ecx & bit_FMA)
831 : 1348 : set_feature (FEATURE_FMA);
832 : 1348 : if (ecx & bit_F16C)
833 : 1348 : set_feature (FEATURE_F16C);
834 : : }
835 : :
836 : : /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
837 : 1348 : if (max_cpuid_level >= 7)
838 : : {
839 : 1348 : unsigned int max_subleaf_level;
840 : :
841 : 1348 : __cpuid_count (7, 0, max_subleaf_level, ebx, ecx, edx);
842 : 1348 : if (ebx & bit_BMI)
843 : 1348 : set_feature (FEATURE_BMI);
844 : 1348 : if (ebx & bit_SGX)
845 : 0 : set_feature (FEATURE_SGX);
846 : 1348 : if (ebx & bit_HLE)
847 : 0 : set_feature (FEATURE_HLE);
848 : 1348 : if (ebx & bit_RTM)
849 : 0 : set_feature (FEATURE_RTM);
850 : 1348 : if (avx_usable)
851 : : {
852 : 1348 : if (ebx & bit_AVX2)
853 : 1348 : set_feature (FEATURE_AVX2);
854 : 1348 : if (ecx & bit_VPCLMULQDQ)
855 : 0 : set_feature (FEATURE_VPCLMULQDQ);
856 : 1348 : if (ecx & bit_VAES)
857 : 0 : set_feature (FEATURE_VAES);
858 : : }
859 : 1348 : if (ebx & bit_BMI2)
860 : 1348 : set_feature (FEATURE_BMI2);
861 : 1348 : if (ebx & bit_FSGSBASE)
862 : 1348 : set_feature (FEATURE_FSGSBASE);
863 : 1348 : if (ebx & bit_RDSEED)
864 : 1348 : set_feature (FEATURE_RDSEED);
865 : 1348 : if (ebx & bit_ADX)
866 : 1348 : set_feature (FEATURE_ADX);
867 : 1348 : if (ebx & bit_SHA)
868 : 1348 : set_feature (FEATURE_SHA);
869 : 1348 : if (ebx & bit_CLFLUSHOPT)
870 : 1348 : set_feature (FEATURE_CLFLUSHOPT);
871 : 1348 : if (ebx & bit_CLWB)
872 : 1348 : set_feature (FEATURE_CLWB);
873 : : /* NB: bit_OSPKE indicates that OS supports PKU. */
874 : 1348 : if (ecx & bit_OSPKE)
875 : 0 : set_feature (FEATURE_PKU);
876 : 1348 : if (ecx & bit_RDPID)
877 : 1348 : set_feature (FEATURE_RDPID);
878 : 1348 : if (ecx & bit_GFNI)
879 : 0 : set_feature (FEATURE_GFNI);
880 : 1348 : if (ecx & bit_MOVDIRI)
881 : 0 : set_feature (FEATURE_MOVDIRI);
882 : 1348 : if (ecx & bit_MOVDIR64B)
883 : 0 : set_feature (FEATURE_MOVDIR64B);
884 : 1348 : if (ecx & bit_ENQCMD)
885 : 0 : set_feature (FEATURE_ENQCMD);
886 : 1348 : if (ecx & bit_CLDEMOTE)
887 : 0 : set_feature (FEATURE_CLDEMOTE);
888 : 1348 : if (ecx & bit_WAITPKG)
889 : 0 : set_feature (FEATURE_WAITPKG);
890 : 1348 : if (ecx & bit_SHSTK)
891 : 0 : set_feature (FEATURE_SHSTK);
892 : 1348 : if (ecx & bit_KL)
893 : 0 : has_kl = 1;
894 : 1348 : if (edx & bit_SERIALIZE)
895 : 0 : set_feature (FEATURE_SERIALIZE);
896 : 1348 : if (edx & bit_TSXLDTRK)
897 : 0 : set_feature (FEATURE_TSXLDTRK);
898 : 1348 : if (edx & bit_PCONFIG)
899 : 0 : set_feature (FEATURE_PCONFIG);
900 : 1348 : if (edx & bit_IBT)
901 : 0 : set_feature (FEATURE_IBT);
902 : 1348 : if (edx & bit_UINTR)
903 : 0 : set_feature (FEATURE_UINTR);
904 : 1348 : if (amx_usable)
905 : : {
906 : 0 : if (edx & bit_AMX_TILE)
907 : 0 : set_feature (FEATURE_AMX_TILE);
908 : 0 : if (edx & bit_AMX_INT8)
909 : 0 : set_feature (FEATURE_AMX_INT8);
910 : 0 : if (edx & bit_AMX_BF16)
911 : 0 : set_feature (FEATURE_AMX_BF16);
912 : : }
913 : 1348 : if (avx512_usable)
914 : : {
915 : 0 : if (ebx & bit_AVX512F)
916 : 0 : set_feature (FEATURE_AVX512F);
917 : 0 : if (ebx & bit_AVX512VL)
918 : 0 : set_feature (FEATURE_AVX512VL);
919 : 0 : if (ebx & bit_AVX512BW)
920 : 0 : set_feature (FEATURE_AVX512BW);
921 : 0 : if (ebx & bit_AVX512DQ)
922 : 0 : set_feature (FEATURE_AVX512DQ);
923 : 0 : if (ebx & bit_AVX512CD)
924 : 0 : set_feature (FEATURE_AVX512CD);
925 : 0 : if (ebx & bit_AVX512IFMA)
926 : 0 : set_feature (FEATURE_AVX512IFMA);
927 : 0 : if (ecx & bit_AVX512VBMI)
928 : 0 : set_feature (FEATURE_AVX512VBMI);
929 : 0 : if (ecx & bit_AVX512VBMI2)
930 : 0 : set_feature (FEATURE_AVX512VBMI2);
931 : 0 : if (ecx & bit_AVX512VNNI)
932 : 0 : set_feature (FEATURE_AVX512VNNI);
933 : 0 : if (ecx & bit_AVX512BITALG)
934 : 0 : set_feature (FEATURE_AVX512BITALG);
935 : 0 : if (ecx & bit_AVX512VPOPCNTDQ)
936 : 0 : set_feature (FEATURE_AVX512VPOPCNTDQ);
937 : 0 : if (edx & bit_AVX512VP2INTERSECT)
938 : 0 : set_feature (FEATURE_AVX512VP2INTERSECT);
939 : 0 : if (edx & bit_AVX512FP16)
940 : 0 : set_feature (FEATURE_AVX512FP16);
941 : : }
942 : :
943 : 1348 : if (max_subleaf_level >= 1)
944 : : {
945 : 0 : __cpuid_count (7, 1, eax, ebx, ecx, edx);
946 : 0 : if (eax & bit_HRESET)
947 : 0 : set_feature (FEATURE_HRESET);
948 : 0 : if (eax & bit_CMPCCXADD)
949 : 0 : set_feature(FEATURE_CMPCCXADD);
950 : 0 : if (edx & bit_PREFETCHI)
951 : 0 : set_feature (FEATURE_PREFETCHI);
952 : 0 : if (eax & bit_RAOINT)
953 : 0 : set_feature (FEATURE_RAOINT);
954 : 0 : if (edx & bit_USER_MSR)
955 : 0 : set_feature (FEATURE_USER_MSR);
956 : 0 : if (eax & bit_MOVRS)
957 : 0 : set_feature (FEATURE_MOVRS);
958 : 0 : if (avx_usable)
959 : : {
960 : 0 : if (eax & bit_AVXVNNI)
961 : 0 : set_feature (FEATURE_AVXVNNI);
962 : 0 : if (eax & bit_AVXIFMA)
963 : 0 : set_feature (FEATURE_AVXIFMA);
964 : 0 : if (edx & bit_AVXVNNIINT8)
965 : 0 : set_feature (FEATURE_AVXVNNIINT8);
966 : 0 : if (edx & bit_AVXNECONVERT)
967 : 0 : set_feature (FEATURE_AVXNECONVERT);
968 : 0 : if (edx & bit_AVXVNNIINT16)
969 : 0 : set_feature (FEATURE_AVXVNNIINT16);
970 : 0 : if (eax & bit_SM3)
971 : 0 : set_feature (FEATURE_SM3);
972 : 0 : if (eax & bit_SHA512)
973 : 0 : set_feature (FEATURE_SHA512);
974 : 0 : if (eax & bit_SM4)
975 : 0 : set_feature (FEATURE_SM4);
976 : : }
977 : 0 : if (avx512_usable)
978 : : {
979 : 0 : if (eax & bit_AVX512BF16)
980 : 0 : set_feature (FEATURE_AVX512BF16);
981 : : /* AVX10 has the same XSTATE with AVX512. */
982 : 0 : if (edx & bit_AVX10)
983 : 0 : avx10_set = 1;
984 : : }
985 : 0 : if (amx_usable)
986 : : {
987 : 0 : if (eax & bit_AMX_FP16)
988 : 0 : set_feature (FEATURE_AMX_FP16);
989 : 0 : if (edx & bit_AMX_COMPLEX)
990 : 0 : set_feature (FEATURE_AMX_COMPLEX);
991 : : }
992 : 0 : if (apx_usable)
993 : : {
994 : 0 : if (edx & bit_APX_F)
995 : 0 : set_feature (FEATURE_APX_F);
996 : : }
997 : : }
998 : : }
999 : :
1000 : : /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
1001 : 1348 : if (max_cpuid_level >= 0xd)
1002 : : {
1003 : 1348 : __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
1004 : 1348 : if (eax & bit_XSAVEOPT)
1005 : 1348 : set_feature (FEATURE_XSAVEOPT);
1006 : 1348 : if (eax & bit_XSAVEC)
1007 : 1348 : set_feature (FEATURE_XSAVEC);
1008 : 1348 : if (eax & bit_XSAVES)
1009 : 1348 : set_feature (FEATURE_XSAVES);
1010 : : }
1011 : :
1012 : : /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */
1013 : 1348 : if (max_cpuid_level >= 0x14)
1014 : : {
1015 : 0 : __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
1016 : 0 : if (ebx & bit_PTWRITE)
1017 : 0 : set_feature (FEATURE_PTWRITE);
1018 : : }
1019 : :
1020 : : /* Get Advanced Features at level 0x19 (eax = 0x19). */
1021 : 0 : if (max_cpuid_level >= 0x19)
1022 : : {
1023 : 0 : __cpuid (0x19, eax, ebx, ecx, edx);
1024 : : /* Check if OS support keylocker. */
1025 : 0 : if (ebx & bit_AESKLE)
1026 : : {
1027 : 0 : set_feature (FEATURE_AESKLE);
1028 : 0 : if (ebx & bit_WIDEKL)
1029 : 0 : set_feature (FEATURE_WIDEKL);
1030 : 0 : if (has_kl)
1031 : 0 : set_feature (FEATURE_KL);
1032 : : }
1033 : : }
1034 : :
1035 : : /* Get Advanced Features at level 0x1e (eax = 0x1e, ecx = 1). */
1036 : 0 : if (max_cpuid_level >= 0x1e)
1037 : : {
1038 : 0 : __cpuid_count (0x1e, 1, eax, ebx, ecx, edx);
1039 : 0 : if (amx_usable)
1040 : : {
1041 : 0 : if (eax & bit_AMX_AVX512)
1042 : 0 : set_feature (FEATURE_AMX_AVX512);
1043 : 0 : if (eax & bit_AMX_TF32)
1044 : 0 : set_feature (FEATURE_AMX_TF32);
1045 : 0 : if (eax & bit_AMX_FP8)
1046 : 0 : set_feature (FEATURE_AMX_FP8);
1047 : 0 : if (eax & bit_AMX_MOVRS)
1048 : 0 : set_feature (FEATURE_AMX_MOVRS);
1049 : : }
1050 : : }
1051 : :
1052 : : /* Get Advanced Features at level 0x24 (eax = 0x24, ecx = 0). */
1053 : 1348 : if (avx10_set && max_cpuid_level >= 0x24)
1054 : : {
1055 : 0 : __cpuid_count (0x24, 0, eax, ebx, ecx, edx);
1056 : 0 : version = ebx & 0xff;
1057 : 0 : switch (version)
1058 : : {
1059 : 0 : case 2:
1060 : 0 : set_feature (FEATURE_AVX10_2);
1061 : : /* Fall through. */
1062 : 0 : case 1:
1063 : 0 : set_feature (FEATURE_AVX10_1);
1064 : 0 : break;
1065 : 0 : default:
1066 : 0 : set_feature (FEATURE_AVX10_1);
1067 : 0 : break;
1068 : : }
1069 : : }
1070 : :
1071 : : /* Check cpuid level of extended features. */
1072 : 1348 : __cpuid (0x80000000, ext_level, ebx, ecx, edx);
1073 : :
1074 : 1348 : cpu_model2->__cpu_ext_level = ext_level;
1075 : :
1076 : 1348 : if (ext_level >= 0x80000001)
1077 : : {
1078 : 1348 : __cpuid (0x80000001, eax, ebx, ecx, edx);
1079 : :
1080 : 1348 : if (ecx & bit_SSE4a)
1081 : 1348 : set_feature (FEATURE_SSE4_A);
1082 : 1348 : if (ecx & bit_LAHF_LM)
1083 : 1348 : set_feature (FEATURE_LAHF_LM);
1084 : 1348 : if (ecx & bit_ABM)
1085 : 1348 : set_feature (FEATURE_ABM);
1086 : 1348 : if (ecx & bit_LWP)
1087 : 0 : set_feature (FEATURE_LWP);
1088 : 1348 : if (ecx & bit_TBM)
1089 : 0 : set_feature (FEATURE_TBM);
1090 : 1348 : if (ecx & bit_LZCNT)
1091 : 1348 : set_feature (FEATURE_LZCNT);
1092 : 1348 : if (ecx & bit_PRFCHW)
1093 : 1348 : set_feature (FEATURE_PRFCHW);
1094 : 1348 : if (ecx & bit_MWAITX)
1095 : 1348 : set_feature (FEATURE_MWAITX);
1096 : :
1097 : 1348 : if (edx & bit_LM)
1098 : 1348 : set_feature (FEATURE_LM);
1099 : 1348 : if (edx & bit_3DNOWP)
1100 : 0 : set_feature (FEATURE_3DNOWP);
1101 : 1348 : if (edx & bit_3DNOW)
1102 : 0 : set_feature (FEATURE_3DNOW);
1103 : :
1104 : 1348 : if (avx_usable)
1105 : : {
1106 : 1348 : if (ecx & bit_FMA4)
1107 : 0 : set_feature (FEATURE_FMA4);
1108 : 1348 : if (ecx & bit_XOP)
1109 : 0 : set_feature (FEATURE_XOP);
1110 : : }
1111 : : }
1112 : :
1113 : 1348 : if (ext_level >= 0x80000008)
1114 : : {
1115 : 1348 : __cpuid (0x80000008, eax, ebx, ecx, edx);
1116 : 1348 : if (ebx & bit_CLZERO)
1117 : 1348 : set_feature (FEATURE_CLZERO);
1118 : 1348 : if (ebx & bit_WBNOINVD)
1119 : 1348 : set_feature (FEATURE_WBNOINVD);
1120 : : }
1121 : :
1122 : 1348 : if (ext_level >= 0x80000021)
1123 : : {
1124 : 0 : __cpuid (0x80000021, eax, ebx, ecx, edx);
1125 : 0 : if (eax & bit_AMD_PREFETCHI)
1126 : : {
1127 : 0 : set_feature (FEATURE_PREFETCHI);
1128 : : }
1129 : : }
1130 : :
1131 : : #undef set_feature
1132 : 1348 : }
1133 : :
1134 : : static inline int
1135 : 1348 : cpu_indicator_init (struct __processor_model *cpu_model,
1136 : : struct __processor_model2 *cpu_model2,
1137 : : unsigned int *cpu_features2)
1138 : : {
1139 : 1348 : unsigned int eax, ebx, ecx, edx;
1140 : :
1141 : 1348 : int max_level;
1142 : 1348 : unsigned int vendor;
1143 : 1348 : unsigned int model, family;
1144 : 1348 : unsigned int extended_model, extended_family;
1145 : :
1146 : : /* This function needs to run just once. */
1147 : 1348 : if (cpu_model->__cpu_vendor)
1148 : : return 0;
1149 : :
1150 : : /* Assume cpuid insn present. Run in level 0 to get vendor id. */
1151 : 1348 : if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
1152 : : {
1153 : 0 : cpu_model->__cpu_vendor = VENDOR_OTHER;
1154 : 0 : return -1;
1155 : : }
1156 : :
1157 : 1348 : vendor = ebx;
1158 : 1348 : max_level = eax;
1159 : :
1160 : 1348 : if (max_level < 1)
1161 : : {
1162 : 0 : cpu_model->__cpu_vendor = VENDOR_OTHER;
1163 : 0 : return -1;
1164 : : }
1165 : :
1166 : 1348 : if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
1167 : : {
1168 : 0 : cpu_model->__cpu_vendor = VENDOR_OTHER;
1169 : 0 : return -1;
1170 : : }
1171 : :
1172 : 1348 : cpu_model2->__cpu_max_level = max_level;
1173 : :
1174 : 1348 : model = (eax >> 4) & 0x0f;
1175 : 1348 : family = (eax >> 8) & 0x0f;
1176 : 1348 : extended_model = (eax >> 12) & 0xf0;
1177 : 1348 : extended_family = (eax >> 20) & 0xff;
1178 : :
1179 : : /* Find available features. */
1180 : 1348 : get_available_features (cpu_model, cpu_model2, cpu_features2,
1181 : : ecx, edx);
1182 : :
1183 : 1348 : if (vendor == signature_INTEL_ebx)
1184 : : {
1185 : : /* Adjust model and family for Intel CPUS. */
1186 : 0 : if (family == 0x0f)
1187 : : {
1188 : 0 : family += extended_family;
1189 : 0 : model += extended_model;
1190 : : }
1191 : 0 : else if (family == 0x06)
1192 : 0 : model += extended_model;
1193 : :
1194 : 0 : cpu_model2->__cpu_family = family;
1195 : 0 : cpu_model2->__cpu_model = model;
1196 : :
1197 : : /* Get CPU type. */
1198 : 0 : get_intel_cpu (cpu_model, cpu_model2, cpu_features2);
1199 : 0 : cpu_model->__cpu_vendor = VENDOR_INTEL;
1200 : : }
1201 : 1348 : else if (vendor == signature_AMD_ebx)
1202 : : {
1203 : : /* Adjust model and family for AMD CPUS. */
1204 : 1348 : if (family == 0x0f)
1205 : : {
1206 : 1348 : family += extended_family;
1207 : 1348 : model += extended_model;
1208 : : }
1209 : :
1210 : 1348 : cpu_model2->__cpu_family = family;
1211 : 1348 : cpu_model2->__cpu_model = model;
1212 : :
1213 : : /* Get CPU type. */
1214 : 1348 : get_amd_cpu (cpu_model, cpu_model2, cpu_features2);
1215 : 1348 : cpu_model->__cpu_vendor = VENDOR_AMD;
1216 : : }
1217 : 0 : else if (vendor == signature_CENTAUR_ebx && family < 0x07)
1218 : 0 : cpu_model->__cpu_vendor = VENDOR_CENTAUR;
1219 : 0 : else if (vendor == signature_SHANGHAI_ebx
1220 : 0 : || vendor == signature_CENTAUR_ebx)
1221 : : {
1222 : : /* Adjust model and family for ZHAOXIN CPUS. */
1223 : 0 : if (family == 0x07)
1224 : 0 : model += extended_model;
1225 : :
1226 : 0 : cpu_model2->__cpu_family = family;
1227 : 0 : cpu_model2->__cpu_model = model;
1228 : :
1229 : : /* Get CPU type. */
1230 : 0 : get_zhaoxin_cpu (cpu_model, cpu_model2, cpu_features2);
1231 : 0 : cpu_model->__cpu_vendor = VENDOR_ZHAOXIN;
1232 : : }
1233 : 0 : else if (vendor == signature_CYRIX_ebx)
1234 : 0 : cpu_model->__cpu_vendor = VENDOR_CYRIX;
1235 : 0 : else if (vendor == signature_NSC_ebx)
1236 : 0 : cpu_model->__cpu_vendor = VENDOR_NSC;
1237 : : else
1238 : 0 : cpu_model->__cpu_vendor = VENDOR_OTHER;
1239 : :
1240 : 1348 : if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_LM)
1241 : 1348 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE2))
1242 : : {
1243 : 1348 : CHECK___builtin_cpu_supports ("x86-64");
1244 : 1348 : set_cpu_feature (cpu_model, cpu_features2,
1245 : : FEATURE_X86_64_BASELINE);
1246 : 1348 : if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_CMPXCHG16B)
1247 : 1348 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_POPCNT)
1248 : 1348 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_LAHF_LM)
1249 : 2696 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE4_2))
1250 : : {
1251 : 1348 : CHECK___builtin_cpu_supports ("x86-64-v2");
1252 : 1348 : set_cpu_feature (cpu_model, cpu_features2,
1253 : : FEATURE_X86_64_V2);
1254 : 1348 : if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_AVX2)
1255 : 1348 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI)
1256 : 1348 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI2)
1257 : 1348 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_F16C)
1258 : 1348 : && has_cpu_feature (cpu_model, cpu_features2, FEATURE_FMA)
1259 : 1348 : && has_cpu_feature (cpu_model, cpu_features2,
1260 : : FEATURE_LZCNT)
1261 : 2696 : && has_cpu_feature (cpu_model, cpu_features2,
1262 : : FEATURE_MOVBE))
1263 : : {
1264 : 1348 : CHECK___builtin_cpu_supports ("x86-64-v3");
1265 : 1348 : set_cpu_feature (cpu_model, cpu_features2,
1266 : : FEATURE_X86_64_V3);
1267 : 1348 : if (has_cpu_feature (cpu_model, cpu_features2,
1268 : : FEATURE_AVX512BW)
1269 : 0 : && has_cpu_feature (cpu_model, cpu_features2,
1270 : : FEATURE_AVX512CD)
1271 : 0 : && has_cpu_feature (cpu_model, cpu_features2,
1272 : : FEATURE_AVX512DQ)
1273 : 1348 : && has_cpu_feature (cpu_model, cpu_features2,
1274 : : FEATURE_AVX512VL))
1275 : : {
1276 : 0 : CHECK___builtin_cpu_supports ("x86-64-v4");
1277 : 0 : set_cpu_feature (cpu_model, cpu_features2,
1278 : : FEATURE_X86_64_V4);
1279 : : }
1280 : : }
1281 : : }
1282 : : }
1283 : :
1284 : 1348 : gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
1285 : 1348 : gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
1286 : 1348 : gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
1287 : :
1288 : : return 0;
1289 : : }
|