From 9c992c6e7daebcaab03e58635a36e7e6a1eeb111 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 1 Feb 2022 20:05:13 +0000 Subject: [PATCH] checking xsave/oxsave and AVX with xgetbv instruction --- Sources/Core/CpuID.cpp | 29 +++++++++++++++++++++++------ Sources/Core/CpuID.h | 2 ++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Sources/Core/CpuID.cpp b/Sources/Core/CpuID.cpp index 23f7d3b79..43fe96991 100644 --- a/Sources/Core/CpuID.cpp +++ b/Sources/Core/CpuID.cpp @@ -28,6 +28,16 @@ namespace spades { return regs; } + static uint32_t xcr0() { +#ifdef WIN32 + return static_cast(_xgetbv(0)); +#else + uint32_t a; + asm volatile("xgetbv" : "=a"(a) : "c"(0) : "%edx"); + return a; +#endif + } + CpuID::CpuID() { uint32_t maxStdLevel; { @@ -42,6 +52,13 @@ namespace spades { auto ar = cpuid(1); featureEcx = ar[2]; featureEdx = ar[3]; + + // xsave/osxsave + if ((featureEcx & 26) && (featureEcx & 27)) { + auto x = xcr0(); + featureXcr0Avx = ((x & 6) == 6); + featureXcr0Avx512 = ((x & 224) == 224); + } } { @@ -72,12 +89,12 @@ namespace spades { case CpuFeature::SSE3: return featureEcx & (1U << 0); case CpuFeature::SSSE3: return featureEcx & (1U << 9); case CpuFeature::FMA: return featureEcx & (1U << 12); - case CpuFeature::AVX: return ((featureEcx & (1U << 28)) && (featureEcx & (1U << 27))); - case CpuFeature::AVX2: return subfeature & (1U << 5); - case CpuFeature::AVX512CD: return subfeature & (1U << 28); - case CpuFeature::AVX512ER: return subfeature & (1U << 27); - case CpuFeature::AVX512PF: return subfeature & (1U << 26); - case CpuFeature::AVX512F: return subfeature & (1U << 16); + case CpuFeature::AVX: return (featureXcr0Avx && (featureEcx & (1U << 28))); + case CpuFeature::AVX2: return (featureXcr0Avx && subfeature & (1U << 5)); + case CpuFeature::AVX512CD: return (featureXcr0Avx512 && subfeature & (1U << 28)); + case CpuFeature::AVX512ER: return (featureXcr0Avx512 && subfeature & (1U << 27)); + case CpuFeature::AVX512PF: return (featureXcr0Avx512 && subfeature & (1U << 26)); + case CpuFeature::AVX512F: return (featureXcr0Avx512 && subfeature & (1U << 16)); case CpuFeature::SimultaneousMT: return featureEdx & (1U << 28); } } diff --git a/Sources/Core/CpuID.h b/Sources/Core/CpuID.h index 9a2648c75..22b185751 100644 --- a/Sources/Core/CpuID.h +++ b/Sources/Core/CpuID.h @@ -36,6 +36,8 @@ namespace spades { uint32_t featureEdx; uint32_t subfeature; std::string info; + bool featureXcr0Avx; + bool featureXcr0Avx512; public: CpuID();