1 #include <stdbool.h>
2 #include <stdint.h>
3 #include <stddef.h>
4 
5 #include <x86/cpuid.h>
6 #include <cpuinfo.h>
7 
8 #ifdef __GNUC__
9     #pragma GCC diagnostic push
10     #pragma GCC diagnostic ignored "-Wunused-parameter"
11 #endif
12 
13 #if CPUINFO_ARCH_X86
14     #ifdef _MSC_VER
15         #pragma pack(push, 2)
16     #endif
17     struct fxsave_region {
18         uint16_t fpu_control_word;
19         uint16_t fpu_status_word;
20         uint16_t fpu_tag_word;
21         uint16_t fpu_opcode;
22         uint32_t fpu_instruction_pointer_offset;
23         uint32_t fpu_instruction_pointer_selector;
24         uint32_t fpu_operand_pointer_offset;
25         uint32_t fpu_operand_pointer_selector;
26         uint32_t mxcsr_state;
27         uint32_t mxcsr_mask;
28         uint64_t fpu_registers[8 * 2];
29         uint64_t xmm_registers[8 * 2];
30         uint64_t padding[28];
31     }
32     #ifndef _MSC_VER
33         __attribute__((__aligned__(16), __packed__))
34     #endif
35     ; /* end of fxsave_region structure */
36     #ifdef _MSC_VER
37         #pragma pack(pop, 2)
38     #endif
39 #endif
40 
41 
cpuinfo_x86_detect_isa(const struct cpuid_regs basic_info,const struct cpuid_regs extended_info,uint32_t max_base_index,uint32_t max_extended_index,enum cpuinfo_vendor vendor)42 struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
43     const struct cpuid_regs basic_info, const struct cpuid_regs extended_info,
44     uint32_t max_base_index, uint32_t max_extended_index,
45     enum cpuinfo_vendor vendor)
46 {
47     struct cpuinfo_x86_isa isa = { 0 };
48 
49     const struct cpuid_regs structured_feature_info0 =
50         (max_base_index >= 7) ? cpuidex(7, 0) : (struct cpuid_regs) { 0, 0, 0, 0};
51     const struct cpuid_regs structured_feature_info1 =
52         (max_base_index >= 7) ? cpuidex(7, 1) : (struct cpuid_regs) { 0, 0, 0, 0};
53 
54     const uint32_t processor_capacity_info_index = UINT32_C(0x80000008);
55     const struct cpuid_regs processor_capacity_info =
56         (max_extended_index >= processor_capacity_info_index) ?
57             cpuid(processor_capacity_info_index) : (struct cpuid_regs) { 0, 0, 0, 0 };
58 
59     bool avx_regs = false, avx512_regs = false, mpx_regs = false;
60     /*
61      * OSXSAVE: Operating system enabled XSAVE instructions for application use:
62      * - Intel, AMD: ecx[bit 26] in basic info = XSAVE/XRSTOR instructions supported by a chip.
63      * - Intel, AMD: ecx[bit 27] in basic info = XSAVE/XRSTOR instructions enabled by OS.
64      */
65     const uint32_t osxsave_mask = UINT32_C(0x0C000000);
66     if ((basic_info.ecx & osxsave_mask) == osxsave_mask) {
67         uint64_t xcr0_valid_bits = 0;
68         if (max_base_index >= 0xD) {
69             const struct cpuid_regs regs = cpuidex(0xD, 0);
70             xcr0_valid_bits = ((uint64_t) regs.edx << 32) | regs.eax;
71         }
72 
73         const uint64_t xfeature_enabled_mask = xgetbv(0);
74 
75         /*
76          * AVX registers:
77          * - Intel, AMD: XFEATURE_ENABLED_MASK[bit 1] for low 128 bits of ymm registers
78          * - Intel, AMD: XFEATURE_ENABLED_MASK[bit 2] for high 128 bits of ymm registers
79          */
80         const uint64_t avx_regs_mask = UINT64_C(0x0000000000000006);
81         if ((xcr0_valid_bits & avx_regs_mask) == avx_regs_mask) {
82             avx_regs = (xfeature_enabled_mask & avx_regs_mask) == avx_regs_mask;
83         }
84 
85         /*
86          * AVX512 registers:
87          * - Intel, AMD: XFEATURE_ENABLED_MASK[bit 1] for low 128 bits of zmm registers
88          * - Intel, AMD: XFEATURE_ENABLED_MASK[bit 2] for bits 128-255 of zmm registers
89          * - Intel: XFEATURE_ENABLED_MASK[bit 5] for 8 64-bit OpMask registers (k0-k7)
90          * - Intel: XFEATURE_ENABLED_MASK[bit 6] for the high 256 bits of the zmm registers zmm0-zmm15
91          * - Intel: XFEATURE_ENABLED_MASK[bit 7] for the 512-bit zmm registers zmm16-zmm31
92          */
93         const uint64_t avx512_regs_mask = UINT64_C(0x00000000000000E6);
94         if ((xcr0_valid_bits & avx512_regs_mask) == avx512_regs_mask) {
95             avx512_regs = (xfeature_enabled_mask & avx512_regs_mask) == avx512_regs_mask;
96         }
97 
98         /*
99          * MPX registers:
100          * - Intel: XFEATURE_ENABLED_MASK[bit 3] for BNDREGS
101          * - Intel: XFEATURE_ENABLED_MASK[bit 4] for BNDCSR
102          */
103         const uint64_t mpx_regs_mask = UINT64_C(0x0000000000000018);
104         if ((xcr0_valid_bits & mpx_regs_mask) == mpx_regs_mask) {
105             mpx_regs = (xfeature_enabled_mask & mpx_regs_mask) == mpx_regs_mask;
106         }
107     }
108 
109 #if CPUINFO_ARCH_X86
110     /*
111      * RDTSC instruction:
112      * - Intel, AMD: edx[bit 4] in basic info.
113      * - AMD: edx[bit 4] in extended info (reserved bit on Intel CPUs).
114      */
115     isa.rdtsc = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00000010));
116 #endif
117 
118     /*
119      * SYSENTER/SYSEXIT instructions:
120      * - Intel, AMD: edx[bit 11] in basic info.
121      */
122     isa.sysenter = !!(basic_info.edx & UINT32_C(0x00000800));
123 
124 #if CPUINFO_ARCH_X86
125     /*
126      * SYSCALL/SYSRET instructions:
127      * - Intel, AMD: edx[bit 11] in extended info.
128      */
129     isa.syscall = !!(extended_info.edx & UINT32_C(0x00000800));
130 #endif
131 
132     /*
133      * RDMSR/WRMSR instructions:
134      * - Intel, AMD: edx[bit 5] in basic info.
135      * - AMD: edx[bit 5] in extended info (reserved bit on Intel CPUs).
136      */
137     isa.msr = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00000020));
138 
139     /*
140      * CLZERO instruction:
141      * - AMD: ebx[bit 0] in processor capacity info (reserved bit on Intel CPUs).
142      */
143     isa.clzero = !!(processor_capacity_info.ebx & UINT32_C(0x00000001));
144 
145     /*
146      * CLFLUSH instruction:
147      * - Intel, AMD: edx[bit 19] in basic info.
148      */
149     isa.clflush = !!(basic_info.edx & UINT32_C(0x00080000));
150 
151     /*
152      * CLFLUSHOPT instruction:
153      * - Intel: ebx[bit 23] in structured feature info (ecx = 0).
154      */
155     isa.clflushopt = !!(structured_feature_info0.ebx & UINT32_C(0x00800000));
156 
157     /*
158      * MWAIT/MONITOR instructions:
159      * - Intel, AMD: ecx[bit 3] in basic info.
160      */
161     isa.mwait = !!(basic_info.ecx & UINT32_C(0x00000008));
162 
163     /*
164      * MWAITX/MONITORX instructions:
165      * - AMD: ecx[bit 29] in extended info.
166      */
167     isa.mwaitx = !!(extended_info.ecx & UINT32_C(0x20000000));
168 
169     /*
170      * FXSAVE/FXRSTOR instructions:
171      * - Intel, AMD: edx[bit 24] in basic info.
172      * - AMD: edx[bit 24] in extended info (zero bit on Intel CPUs, EMMX bit on Cyrix CPUs).
173      */
174     switch (vendor) {
175 #if CPUINFO_ARCH_X86
176         case cpuinfo_vendor_cyrix:
177         case cpuinfo_vendor_nsc:
178             isa.emmx = !!(extended_info.edx & UINT32_C(0x01000000));
179             break;
180 #endif
181         default:
182             isa.fxsave = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x01000000));
183             break;
184     }
185 
186     /*
187      * XSAVE/XRSTOR instructions:
188      * - Intel, AMD: ecx[bit 26] in basic info.
189      */
190     isa.xsave = !!(basic_info.ecx & UINT32_C(0x04000000));
191 
192 #if CPUINFO_ARCH_X86
193     /*
194      * x87 FPU instructions:
195      * - Intel, AMD: edx[bit 0] in basic info.
196      * - AMD: edx[bit 0] in extended info (reserved bit on Intel CPUs).
197      */
198     isa.fpu = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00000001));
199 
200     /*
201      * MMX instructions:
202      * - Intel, AMD: edx[bit 23] in basic info.
203      * - AMD: edx[bit 23] in extended info (zero bit on Intel CPUs).
204      */
205     isa.mmx = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00800000));
206 
207     /*
208      * MMX+/Integer SSE instructions:
209      * - Intel, AMD: edx[bit 25] in basic info (SSE feature flag).
210      * - Pre-SSE AMD: edx[bit 22] in extended info (zero bit on Intel CPUs).
211      */
212     isa.mmx_plus = !!((basic_info.edx & UINT32_C(0x02000000)) | (extended_info.edx & UINT32_C(0x00400000)));
213 #endif
214 
215     /*
216      * 3dnow! instructions:
217      * - AMD: edx[bit 31] of extended info (zero bit on Intel CPUs).
218      */
219     isa.three_d_now = !!(extended_info.edx & UINT32_C(0x80000000));
220 
221     /*
222      * 3dnow!+ instructions:
223      * - AMD: edx[bit 30] of extended info (zero bit on Intel CPUs).
224      */
225     isa.three_d_now_plus = !!(extended_info.edx & UINT32_C(0x40000000));
226 
227 #if CPUINFO_ARCH_X86
228     /*
229      * 3dnow! Geode instructions:
230      * - Removed support
231      */
232     isa.three_d_now_geode = false;
233 #endif
234 
235     /*
236      * PREFETCH instruction:
237      * - AMD: ecx[bit 8] of extended info (one of 3dnow! prefetch instructions).
238      *        On Intel this bit indicates PREFETCHW, but not PREFETCH support.
239      * - AMD: edx[bit 31] of extended info (implied by 3dnow! support). Reserved bit on Intel CPUs.
240      * - AMD: edx[bit 30] of extended info (implied by 3dnow!+ support). Reserved bit on Intel CPUs.
241      * - AMD: edx[bit 29] of extended info (x86-64 support). Does not imply PREFETCH support on non-AMD CPUs!!!
242      */
243     switch (vendor) {
244         case cpuinfo_vendor_intel:
245             /*
246              * Instruction is not documented in the manual,
247              * and the 3dnow! prefetch CPUID bit indicates PREFETCHW instruction.
248              */
249             break;
250         case cpuinfo_vendor_amd:
251         case cpuinfo_vendor_hygon:
252             isa.prefetch = !!((extended_info.ecx & UINT32_C(0x00000100)) | (extended_info.edx & UINT32_C(0xE0000000)));
253             break;
254         default:
255             /*
256              * Conservatively assume, that 3dnow!/3dnow!+ support implies PREFETCH support, but
257              * 3dnow! prefetch CPUID bit follows Intel spec (PREFETCHW, but not PREFETCH).
258              */
259             isa.prefetch = !!(extended_info.edx & UINT32_C(0xC0000000));
260             break;
261     }
262 
263     /*
264      * PREFETCHW instruction:
265      * - AMD: ecx[bit 8] of extended info (one of 3dnow! prefetch instructions).
266      * - Intel: ecx[bit 8] of extended info (PREFETCHW instruction only).
267      * - AMD: edx[bit 31] of extended info (implied by 3dnow! support). Reserved bit on Intel CPUs.
268      * - AMD: edx[bit 30] of extended info (implied by 3dnow!+ support). Reserved bit on Intel CPUs.
269      * - AMD: edx[bit 29] of extended info (x86-64 support). Does not imply PREFETCHW support on non-AMD CPUs!!!
270      */
271     switch (vendor) {
272         case cpuinfo_vendor_amd:
273         case cpuinfo_vendor_hygon:
274             isa.prefetchw = !!((extended_info.ecx & UINT32_C(0x00000100)) | (extended_info.edx & UINT32_C(0xE0000000)));
275             break;
276         default:
277             /* Assume, that 3dnow!/3dnow!+ support implies PREFETCHW support, not implications from x86-64 support */
278             isa.prefetchw = !!((extended_info.ecx & UINT32_C(0x00000100)) | (extended_info.edx & UINT32_C(0xC0000000)));
279             break;
280     }
281 
282     /*
283      * PREFETCHWT1 instruction:
284      * - Intel: ecx[bit 0] of structured feature info (ecx = 0). Reserved bit on AMD.
285      */
286     isa.prefetchwt1 = !!(structured_feature_info0.ecx & UINT32_C(0x00000001));
287 
288 #if CPUINFO_ARCH_X86
289     /*
290      * SSE instructions:
291      * - Intel, AMD: edx[bit 25] in basic info.
292      */
293     isa.sse = !!(basic_info.edx & UINT32_C(0x02000000));
294 
295     /*
296      * SSE2 instructions:
297      * - Intel, AMD: edx[bit 26] in basic info.
298      */
299     isa.sse2 = !!(basic_info.edx & UINT32_C(0x04000000));
300 #endif
301 
302     /*
303      * SSE3 instructions:
304      * - Intel, AMD: ecx[bit 0] in basic info.
305      */
306     isa.sse3 = !!(basic_info.ecx & UINT32_C(0x00000001));
307 
308 #if CPUINFO_ARCH_X86
309     /*
310      * CPUs with x86-64 or SSE3 always support DAZ (denormals-as-zero) mode.
311      * Only early Pentium 4 models may not support it.
312      */
313     if (isa.sse3) {
314         isa.daz = true;
315     } else {
316         /* Detect DAZ support from masked MXCSR bits */
317         if (isa.sse && isa.fxsave) {
318             struct fxsave_region region = { 0 };
319             #ifdef _MSC_VER
320                 _fxsave(&region);
321             #else
322                 __asm__ __volatile__ ("fxsave %[region];" : [region] "+m" (region));
323             #endif
324 
325             /*
326              * Denormals-as-zero (DAZ) flag:
327              * - Intel, AMD: MXCSR[bit 6]
328              */
329             isa.daz = !!(region.mxcsr_mask & UINT32_C(0x00000040));
330         }
331     }
332 #endif
333 
334     /*
335      * SSSE3 instructions:
336      * - Intel, AMD: ecx[bit 9] in basic info.
337      */
338     isa.ssse3 = !!(basic_info.ecx & UINT32_C(0x0000200));
339 
340 
341     /*
342      * SSE4.1 instructions:
343      * - Intel, AMD: ecx[bit 19] in basic info.
344      */
345     isa.sse4_1 = !!(basic_info.ecx & UINT32_C(0x00080000));
346 
347     /*
348      * SSE4.2 instructions:
349      * - Intel: ecx[bit 20] in basic info (reserved bit on AMD CPUs).
350      */
351     isa.sse4_2 = !!(basic_info.ecx & UINT32_C(0x00100000));
352 
353     /*
354      * SSE4A instructions:
355      * - AMD: ecx[bit 6] in extended info (reserved bit on Intel CPUs).
356      */
357     isa.sse4a = !!(extended_info.ecx & UINT32_C(0x00000040));
358 
359     /*
360      * Misaligned memory operands in SSE instructions:
361      * - AMD: ecx[bit 7] in extended info (reserved bit on Intel CPUs).
362      */
363     isa.misaligned_sse = !!(extended_info.ecx & UINT32_C(0x00000080));
364 
365     /*
366      * AVX instructions:
367      * - Intel, AMD: ecx[bit 28] in basic info.
368      */
369     isa.avx = avx_regs && !!(basic_info.ecx & UINT32_C(0x10000000));
370 
371     /*
372      * FMA3 instructions:
373      * - Intel: ecx[bit 12] in basic info (reserved bit on AMD CPUs).
374      */
375     isa.fma3 = avx_regs && !!(basic_info.ecx & UINT32_C(0x00001000));
376 
377     /*
378      * FMA4 instructions:
379      * - AMD: ecx[bit 16] in extended info (reserved bit on Intel CPUs).
380      */
381     isa.fma4 = avx_regs && !!(extended_info.ecx & UINT32_C(0x00010000));
382 
383     /*
384      * XOP instructions:
385      * - AMD: ecx[bit 11] in extended info (reserved bit on Intel CPUs).
386      */
387     isa.xop = avx_regs && !!(extended_info.ecx & UINT32_C(0x00000800));
388 
389     /*
390      * F16C instructions:
391      * - Intel, AMD: ecx[bit 29] in basic info.
392      */
393     isa.f16c = avx_regs && !!(basic_info.ecx & UINT32_C(0x20000000));
394 
395     /*
396      * AVX2 instructions:
397      * - Intel: ebx[bit 5] in structured feature info (ecx = 0).
398      */
399     isa.avx2 = avx_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00000020));
400 
401     /*
402      * AVX512F instructions:
403      * - Intel: ebx[bit 16] in structured feature info (ecx = 0).
404      */
405     isa.avx512f = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00010000));
406 
407     /*
408      * AVX512PF instructions:
409      * - Intel: ebx[bit 26] in structured feature info (ecx = 0).
410      */
411     isa.avx512pf = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x04000000));
412 
413     /*
414      * AVX512ER instructions:
415      * - Intel: ebx[bit 27] in structured feature info (ecx = 0).
416      */
417     isa.avx512er = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x08000000));
418 
419     /*
420      * AVX512CD instructions:
421      * - Intel: ebx[bit 28] in structured feature info (ecx = 0).
422      */
423     isa.avx512cd = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x10000000));
424 
425     /*
426      * AVX512DQ instructions:
427      * - Intel: ebx[bit 17] in structured feature info (ecx = 0).
428      */
429     isa.avx512dq = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00020000));
430 
431     /*
432      * AVX512BW instructions:
433      * - Intel: ebx[bit 30] in structured feature info (ecx = 0).
434      */
435     isa.avx512bw = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x40000000));
436 
437     /*
438      * AVX512VL instructions:
439      * - Intel: ebx[bit 31] in structured feature info (ecx = 0).
440      */
441     isa.avx512vl = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x80000000));
442 
443     /*
444      * AVX512IFMA instructions:
445      * - Intel: ebx[bit 21] in structured feature info (ecx = 0).
446      */
447     isa.avx512ifma = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00200000));
448 
449     /*
450      * AVX512VBMI instructions:
451      * - Intel: ecx[bit 1] in structured feature info (ecx = 0).
452      */
453     isa.avx512vbmi = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00000002));
454 
455     /*
456      * AVX512VBMI2 instructions:
457      * - Intel: ecx[bit 6] in structured feature info (ecx = 0).
458      */
459     isa.avx512vbmi2 = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00000040));
460 
461     /*
462      * AVX512BITALG instructions:
463      * - Intel: ecx[bit 12] in structured feature info (ecx = 0).
464      */
465     isa.avx512bitalg = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00001000));
466 
467     /*
468      * AVX512VPOPCNTDQ instructions:
469      * - Intel: ecx[bit 14] in structured feature info (ecx = 0).
470      */
471     isa.avx512vpopcntdq = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00004000));
472 
473     /*
474      * AVX512VNNI instructions:
475      * - Intel: ecx[bit 11] in structured feature info (ecx = 0).
476      */
477     isa.avx512vnni = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00000800));
478 
479     /*
480      * AVX512_4VNNIW instructions:
481      * - Intel: edx[bit 2] in structured feature info (ecx = 0).
482      */
483     isa.avx512_4vnniw = avx512_regs && !!(structured_feature_info0.edx & UINT32_C(0x00000004));
484 
485     /*
486      * AVX512_4FMAPS instructions:
487      * - Intel: edx[bit 3] in structured feature info (ecx = 0).
488      */
489     isa.avx512_4fmaps = avx512_regs && !!(structured_feature_info0.edx & UINT32_C(0x00000008));
490 
491     /*
492      * AVX512_VP2INTERSECT instructions:
493      * - Intel: edx[bit 8] in structured feature info (ecx = 0).
494      */
495     isa.avx512vp2intersect = avx512_regs && !!(structured_feature_info0.edx & UINT32_C(0x00000100));
496 
497     /*
498      * AVX512_BF16 instructions:
499      * - Intel: eax[bit 5] in structured feature info (ecx = 1).
500      */
501     isa.avx512bf16 = avx512_regs && !!(structured_feature_info1.eax & UINT32_C(0x00000020));
502 
503     /*
504      * HLE instructions:
505      * - Intel: ebx[bit 4] in structured feature info (ecx = 0).
506      */
507     isa.hle = !!(structured_feature_info0.ebx & UINT32_C(0x00000010));
508 
509     /*
510      * RTM instructions:
511      * - Intel: ebx[bit 11] in structured feature info (ecx = 0).
512      */
513     isa.rtm = !!(structured_feature_info0.ebx & UINT32_C(0x00000800));
514 
515     /*
516      * XTEST instruction:
517      * - Intel: either HLE or RTM is supported
518      */
519     isa.xtest = isa.hle || isa.rtm;
520 
521     /*
522      * MPX registers and instructions:
523      * - Intel: ebx[bit 14] in structured feature info (ecx = 0).
524      */
525     isa.mpx = mpx_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00004000));
526 
527 #if CPUINFO_ARCH_X86
528     /*
529      * CMOV instructions:
530      * - Intel, AMD: edx[bit 15] in basic info.
531      * - AMD: edx[bit 15] in extended info (zero bit on Intel CPUs).
532      */
533     isa.cmov = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00008000));
534 
535     /*
536      * CMPXCHG8B instruction:
537      * - Intel, AMD: edx[bit 8] in basic info.
538      * - AMD: edx[bit 8] in extended info (reserved bit on Intel CPUs).
539      */
540     isa.cmpxchg8b = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00000100));
541 #endif
542 
543     /*
544      * CMPXCHG16B instruction:
545      * - Intel, AMD: ecx[bit 13] in basic info.
546      */
547     isa.cmpxchg16b = !!(basic_info.ecx & UINT32_C(0x00002000));
548 
549     /*
550      * CLWB instruction:
551      * - Intel: ebx[bit 24] in structured feature info (ecx = 0).
552      */
553     isa.clwb = !!(structured_feature_info0.ebx & UINT32_C(0x01000000));
554 
555     /*
556      * MOVBE instruction:
557      * - Intel: ecx[bit 22] in basic info.
558      */
559     isa.movbe = !!(basic_info.ecx & UINT32_C(0x00400000));
560 
561 #if CPUINFO_ARCH_X86_64
562     /*
563      * Some early x86-64 CPUs lack LAHF & SAHF instructions.
564      * A special CPU feature bit must be checked to ensure their availability:
565      * - Intel, AMD: ecx[bit 0] in extended info.
566      */
567     isa.lahf_sahf = !!(extended_info.ecx & UINT32_C(0x00000001));
568 #endif
569 
570     /*
571      * RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE instructions.
572      * - Intel: ebx[bit 0] in structured feature info (ecx = 0).
573      */
574     isa.fs_gs_base = !!(structured_feature_info0.ebx & UINT32_C(0x00000001));
575 
576     /*
577      * LZCNT instruction:
578      * - Intel, AMD: ecx[bit 5] in extended info.
579      */
580     isa.lzcnt = !!(extended_info.ecx & UINT32_C(0x00000020));
581 
582     /*
583      * POPCNT instruction:
584      * - Intel, AMD: ecx[bit 23] in basic info.
585      */
586     isa.popcnt = !!(basic_info.ecx & UINT32_C(0x00800000));
587 
588     /*
589      * TBM instructions:
590      * - AMD: ecx[bit 21] in extended info (reserved bit on Intel CPUs).
591      */
592     isa.tbm = !!(extended_info.ecx & UINT32_C(0x00200000));
593 
594     /*
595      * BMI instructions:
596      * - Intel, AMD: ebx[bit 3] in structured feature info (ecx = 0).
597      */
598     isa.bmi = !!(structured_feature_info0.ebx & UINT32_C(0x00000008));
599 
600     /*
601      * BMI2 instructions:
602      * - Intel: ebx[bit 8] in structured feature info (ecx = 0).
603      */
604     isa.bmi2 = !!(structured_feature_info0.ebx & UINT32_C(0x00000100));
605 
606     /*
607      * ADCX/ADOX instructions:
608      * - Intel: ebx[bit 19] in structured feature info (ecx = 0).
609      */
610     isa.adx = !!(structured_feature_info0.ebx & UINT32_C(0x00080000));
611 
612     /*
613      * AES instructions:
614      * - Intel: ecx[bit 25] in basic info (reserved bit on AMD CPUs).
615      */
616     isa.aes = !!(basic_info.ecx & UINT32_C(0x02000000));
617 
618     /*
619      * VAES instructions:
620      * - Intel: ecx[bit 9] in structured feature info (ecx = 0).
621      */
622     isa.vaes = !!(structured_feature_info0.ecx & UINT32_C(0x00000200));
623 
624     /*
625      * PCLMULQDQ instruction:
626      * - Intel: ecx[bit 1] in basic info (reserved bit on AMD CPUs).
627      */
628     isa.pclmulqdq = !!(basic_info.ecx & UINT32_C(0x00000002));
629 
630     /*
631      * VPCLMULQDQ instruction:
632      * - Intel: ecx[bit 10] in structured feature info (ecx = 0).
633      */
634     isa.vpclmulqdq = !!(structured_feature_info0.ecx & UINT32_C(0x00000400));
635 
636     /*
637      * GFNI instructions:
638      * - Intel: ecx[bit 8] in structured feature info (ecx = 0).
639      */
640     isa.gfni = !!(structured_feature_info0.ecx & UINT32_C(0x00000100));
641 
642     /*
643      * RDRAND instruction:
644      * - Intel: ecx[bit 30] in basic info (reserved bit on AMD CPUs).
645      */
646     isa.rdrand = !!(basic_info.ecx & UINT32_C(0x40000000));
647 
648     /*
649      * RDSEED instruction:
650      * - Intel: ebx[bit 18] in structured feature info (ecx = 0).
651      */
652     isa.rdseed = !!(structured_feature_info0.ebx & UINT32_C(0x00040000));
653 
654     /*
655      * SHA instructions:
656      * - Intel: ebx[bit 29] in structured feature info (ecx = 0).
657      */
658     isa.sha = !!(structured_feature_info0.ebx & UINT32_C(0x20000000));
659 
660     if (vendor == cpuinfo_vendor_via) {
661         const struct cpuid_regs padlock_meta_info = cpuid(UINT32_C(0xC0000000));
662         const uint32_t max_padlock_index = padlock_meta_info.eax;
663         const uint32_t padlock_info_index = UINT32_C(0xC0000001);
664         if (max_padlock_index >= padlock_info_index) {
665             const struct cpuid_regs padlock_info = cpuid(padlock_info_index);
666 
667             /*
668              * Padlock RNG extension:
669              * - VIA: edx[bit 2] in padlock info = RNG exists on chip flag.
670              * - VIA: edx[bit 3] in padlock info = RNG enabled by OS.
671              */
672             const uint32_t padlock_rng_mask = UINT32_C(0x0000000C);
673             isa.rng = (padlock_info.edx & padlock_rng_mask) == padlock_rng_mask;
674 
675             /*
676              * Padlock ACE extension:
677              * - VIA: edx[bit 6] in padlock info = ACE exists on chip flag.
678              * - VIA: edx[bit 7] in padlock info = ACE enabled by OS.
679              */
680             const uint32_t padlock_ace_mask = UINT32_C(0x000000C0);
681             isa.ace = (padlock_info.edx & padlock_ace_mask) == padlock_ace_mask;
682 
683             /*
684              * Padlock ACE 2 extension:
685              * - VIA: edx[bit 8] in padlock info = ACE2 exists on chip flag.
686              * - VIA: edx[bit 9] in padlock info = ACE 2 enabled by OS.
687              */
688             const uint32_t padlock_ace2_mask = UINT32_C(0x00000300);
689             isa.ace2 = (padlock_info.edx & padlock_ace2_mask) == padlock_ace2_mask;
690 
691             /*
692              * Padlock PHE extension:
693              * - VIA: edx[bit 10] in padlock info = PHE exists on chip flag.
694              * - VIA: edx[bit 11] in padlock info = PHE enabled by OS.
695              */
696             const uint32_t padlock_phe_mask = UINT32_C(0x00000C00);
697             isa.phe = (padlock_info.edx & padlock_phe_mask) == padlock_phe_mask;
698 
699             /*
700              * Padlock PMM extension:
701              * - VIA: edx[bit 12] in padlock info = PMM exists on chip flag.
702              * - VIA: edx[bit 13] in padlock info = PMM enabled by OS.
703              */
704             const uint32_t padlock_pmm_mask = UINT32_C(0x00003000);
705             isa.pmm = (padlock_info.edx & padlock_pmm_mask) == padlock_pmm_mask;
706         }
707     }
708 
709     /*
710      * LWP instructions:
711      * - AMD: ecx[bit 15] in extended info (reserved bit on Intel CPUs).
712      */
713     isa.lwp = !!(extended_info.ecx & UINT32_C(0x00008000));
714 
715     /*
716      * RDTSCP instruction:
717      * - Intel, AMD: edx[bit 27] in extended info.
718      */
719     isa.rdtscp = !!(extended_info.edx & UINT32_C(0x08000000));
720 
721     /*
722      * RDPID instruction:
723      * - Intel: ecx[bit 22] in structured feature info (ecx = 0).
724      */
725     isa.rdpid = !!(structured_feature_info0.ecx & UINT32_C(0x00400000));
726 
727     return isa;
728 }
729 
730 #ifdef __GNUC__
731     #pragma GCC diagnostic pop
732 #endif
733