#include "config.h"
#include <stdint.h>
#include "x86/cpu.h"
typedef struct {
uint32_t eax, ebx, ecx, edx;
} CpuidRegisters;
void vmaf_cpu_cpuid(CpuidRegisters *regs, unsigned leaf, unsigned subleaf);
uint64_t vmaf_cpu_xgetbv(unsigned xcr);
#define X(reg, mask) (((reg) & (mask)) == (mask))
unsigned vmaf_get_cpu_flags_x86(void) {
CpuidRegisters r = { 0 };
vmaf_cpu_cpuid(&r, 0, 0);
const unsigned max_leaf = r.eax;
unsigned flags = 0;
if (max_leaf >= 1) {
vmaf_cpu_cpuid(&r, 1, 0);
if (X(r.edx, 0x06008000)) {
flags |= VMAF_X86_CPU_FLAG_SSE2;
if (X(r.ecx, 0x00000201)) {
flags |= VMAF_X86_CPU_FLAG_SSSE3;
if (X(r.ecx, 0x00080000))
flags |= VMAF_X86_CPU_FLAG_SSE41;
}
}
#if ARCH_X86_64
if (X(r.ecx, 0x18000000)) {
const uint64_t xcr0 = vmaf_cpu_xgetbv(0);
if (X(xcr0, 0x00000006)) {
if (max_leaf >= 7) {
vmaf_cpu_cpuid(&r, 7, 0);
if (X(r.ebx, 0x00000128)) {
flags |= VMAF_X86_CPU_FLAG_AVX2;
if (X(xcr0, 0x000000e0)) {
if (X(r.ebx, 0xd0030000))
flags |= VMAF_X86_CPU_FLAG_AVX512;
if (X(r.ebx, 0xd0230000) && X(r.ecx, 0x00005f42))
flags |= VMAF_X86_CPU_FLAG_AVX512ICL;
}
}
}
}
}
#endif
}
return flags;
}