10
#include "../../zbuild.h"
11
#include "x86_features.h"
22
static inline void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) {
24
unsigned int registers[4];
25
__cpuid((int *)registers, info);
32
__cpuid(info, *eax, *ebx, *ecx, *edx);
36
static inline void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) {
38
unsigned int registers[4];
39
__cpuidex((int *)registers, info, subinfo);
46
__cpuid_count(info, subinfo, *eax, *ebx, *ecx, *edx);
50
static inline uint64_t xgetbv(unsigned int xcr) {
55
__asm__ ( ".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(xcr));
56
return (uint64_t)(edx) << 32 | eax;
60
void Z_INTERNAL x86_check_features(struct x86_cpu_features *features) {
61
unsigned eax, ebx, ecx, edx;
64
cpuid(0, &maxbasic, &ebx, &ecx, &edx);
65
cpuid(1 , &eax, &ebx, &ecx, &edx);
67
features->has_sse2 = edx & 0x4000000;
68
features->has_ssse3 = ecx & 0x200;
69
features->has_sse42 = ecx & 0x100000;
70
features->has_pclmulqdq = ecx & 0x2;
72
if (ecx & 0x08000000) {
73
uint64_t xfeature = xgetbv(0);
75
features->has_os_save_ymm = ((xfeature & 0x06) == 0x06);
76
features->has_os_save_zmm = ((xfeature & 0xe6) == 0xe6);
80
cpuidex(7, 0, &eax, &ebx, &ecx, &edx);
84
features->has_vpclmulqdq = ecx & 0x400;
87
if (features->has_os_save_ymm) {
88
features->has_avx2 = ebx & 0x20;
92
if (features->has_os_save_zmm) {
93
features->has_avx512 = ebx & 0x00010000;
94
features->has_avx512vnni = ecx & 0x800;