Some more improvements of MUtils::CPUFetaures code.

This commit is contained in:
LoRd_MuldeR 2016-12-25 22:16:04 +01:00
parent 7128c12680
commit 7c2c14bed5
2 changed files with 33 additions and 10 deletions

View File

@ -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!

View File

@ -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);
}
//Detect extended feature flags
if (max_basic_cap >= 7)
{
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 nExIds = qBound(0x80000000, cpuInfo[0], 0x80000004);
for(uint32_t i = 0x80000002; i <= nExIds; ++i)
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';
}
}
//Detect 64-Bit processors
#if (!(defined(_M_X64) || defined(_M_IA64)))