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