From 7c2c14bed507d4f2e02ad8aaf5e5ee05760b9615 Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Sun, 25 Dec 2016 22:16:04 +0100 Subject: [PATCH] Some more improvements of MUtils::CPUFetaures code. --- include/MUtils/CPUFeatures.h | 5 ++++- src/CPUFeatures_Win32.cpp | 38 +++++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/include/MUtils/CPUFeatures.h b/include/MUtils/CPUFeatures.h index 9b894a0..039f563 100644 --- a/include/MUtils/CPUFeatures.h +++ b/include/MUtils/CPUFeatures.h @@ -54,9 +54,12 @@ namespace MUtils static const quint32 FLAG_SSE2 = 0x008U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSE2* instruction set extension static const quint32 FLAG_SSE3 = 0x010U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSE3* instruction set extension static const quint32 FLAG_SSSE3 = 0x020U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSSE3* instruction set extension - static const quint32 FLAG_SSE4 = 0x030U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSE4.1* instruction set extension + static const quint32 FLAG_SSE41 = 0x040U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSE4.1* instruction set extension static const quint32 FLAG_SSE42 = 0x080U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSE4.2* instruction set extension static const quint32 FLAG_AVX = 0x100U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *AVX* instruction set extension + static const quint32 FLAG_AVX2 = 0x200U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *AVX2* instruction set extension + static const quint32 FLAG_FMA3 = 0x400U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *FMA3* instruction + static const quint32 FLAG_LZCNT = 0x800U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *LZCNT* instruction /** * \brief Struct to hold information about the CPU. See `_cpu_info_t` for details! diff --git a/src/CPUFeatures_Win32.cpp b/src/CPUFeatures_Win32.cpp index ce2e890..7d4ac27 100644 --- a/src/CPUFeatures_Win32.cpp +++ b/src/CPUFeatures_Win32.cpp @@ -49,6 +49,7 @@ MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(void) //Detect the CPU identifier string MY_CPUID(&cpuInfo[0], 0); + const uint32_t max_basic_cap = cpuInfo[0]; memcpy(&features.idstr[0U * sizeof(uint32_t)], &cpuInfo[1], sizeof(uint32_t)); memcpy(&features.idstr[1U * sizeof(uint32_t)], &cpuInfo[3], sizeof(uint32_t)); memcpy(&features.idstr[2U * sizeof(uint32_t)], &cpuInfo[2], sizeof(uint32_t)); @@ -57,7 +58,7 @@ MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(void) features.vendor |= CHECK_VENDOR(features.idstr, "AuthenticAMD", VENDOR_AMD); //Detect the CPU model and feature flags - if(cpuInfo[0] >= 1) + if(max_basic_cap >= 1) { MY_CPUID(&cpuInfo[0], 1); features.features |= CHECK_FLAG(cpuInfo[3], 0x00008000, FLAG_CMOV); @@ -66,7 +67,7 @@ MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(void) features.features |= CHECK_FLAG(cpuInfo[3], 0x04000000, FLAG_SSE2); features.features |= CHECK_FLAG(cpuInfo[2], 0x00000001, FLAG_SSE3); features.features |= CHECK_FLAG(cpuInfo[2], 0x00000200, FLAG_SSSE3); - features.features |= CHECK_FLAG(cpuInfo[2], 0x00080000, FLAG_SSE4); + features.features |= CHECK_FLAG(cpuInfo[2], 0x00080000, FLAG_SSE41); features.features |= CHECK_FLAG(cpuInfo[2], 0x00100000, FLAG_SSE42); //Check for AVX @@ -75,6 +76,7 @@ MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(void) if((_xgetbv(0) & 0x6ui64) == 0x6ui64) /*AVX requires OS support!*/ { features.features |= FLAG_AVX; + features.features |= CHECK_FLAG(cpuInfo[2], 0x00001000, FLAG_FMA3); } } @@ -84,15 +86,33 @@ MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(void) features.family = ((cpuInfo[0] >> 8) & 0xf) + ((cpuInfo[0] >> 20) & 0xff); } - //Read the CPU "brand" string - MY_CPUID(&cpuInfo[0], 0x80000000); - const uint32_t nExIds = qBound(0x80000000, cpuInfo[0], 0x80000004); - for(uint32_t i = 0x80000002; i <= nExIds; ++i) + //Detect extended feature flags + if (max_basic_cap >= 7) { - MY_CPUID(&cpuInfo[0], i); - memcpy(&features.brand[(i - 0x80000002) * sizeof(cpuInfo)], &cpuInfo[0], sizeof(cpuInfo)); + MY_CPUID(&cpuInfo[1], 7); + if (features.features & FLAG_AVX) + { + features.features |= CHECK_FLAG(cpuInfo[2], 0x00000020, FLAG_AVX2); + } + } + + //Read the CPU "brand" string + if (max_basic_cap > 0) + { + MY_CPUID(&cpuInfo[0], 0x80000000); + const uint32_t max_extended_cap = qBound(0x80000000, cpuInfo[0], 0x80000004); + if (max_extended_cap >= 0x80000001) + { + MY_CPUID(&cpuInfo[0], 0x80000001); + features.features |= CHECK_FLAG(cpuInfo[2], 0x00000020, FLAG_LZCNT); + for (uint32_t i = 0x80000002; i <= max_extended_cap; ++i) + { + MY_CPUID(&cpuInfo[0], i); + memcpy(&features.brand[(i - 0x80000002) * sizeof(cpuInfo)], &cpuInfo[0], sizeof(cpuInfo)); + } + features.brand[sizeof(features.brand) - 1] = '\0'; + } } - features.brand[sizeof(features.brand) - 1] = '\0'; //Detect 64-Bit processors #if (!(defined(_M_X64) || defined(_M_IA64)))