MUtilities development repository
修订版 | 7c2c14bed507d4f2e02ad8aaf5e5ee05760b9615 (tree) |
---|---|
时间 | 2016-12-26 06:16:04 |
作者 | ![]() |
Commiter | LoRd_MuldeR |
Some more improvements of MUtils::CPUFetaures code.
@@ -54,9 +54,12 @@ namespace MUtils | ||
54 | 54 | static const quint32 FLAG_SSE2 = 0x008U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSE2* instruction set extension |
55 | 55 | static const quint32 FLAG_SSE3 = 0x010U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSE3* instruction set extension |
56 | 56 | static const quint32 FLAG_SSSE3 = 0x020U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSSE3* instruction set extension |
57 | - static const quint32 FLAG_SSE4 = 0x030U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSE4.1* instruction set extension | |
57 | + static const quint32 FLAG_SSE41 = 0x040U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSE4.1* instruction set extension | |
58 | 58 | static const quint32 FLAG_SSE42 = 0x080U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *SSE4.2* instruction set extension |
59 | 59 | static const quint32 FLAG_AVX = 0x100U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *AVX* instruction set extension |
60 | + static const quint32 FLAG_AVX2 = 0x200U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *AVX2* instruction set extension | |
61 | + static const quint32 FLAG_FMA3 = 0x400U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *FMA3* instruction | |
62 | + static const quint32 FLAG_LZCNT = 0x800U; ///< \brief CPU feature flag \details Indicates that the CPU supports the *LZCNT* instruction | |
60 | 63 | |
61 | 64 | /** |
62 | 65 | * \brief Struct to hold information about the CPU. See `_cpu_info_t` for details! |
@@ -49,6 +49,7 @@ MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(void) | ||
49 | 49 | |
50 | 50 | //Detect the CPU identifier string |
51 | 51 | MY_CPUID(&cpuInfo[0], 0); |
52 | + const uint32_t max_basic_cap = cpuInfo[0]; | |
52 | 53 | memcpy(&features.idstr[0U * sizeof(uint32_t)], &cpuInfo[1], sizeof(uint32_t)); |
53 | 54 | memcpy(&features.idstr[1U * sizeof(uint32_t)], &cpuInfo[3], sizeof(uint32_t)); |
54 | 55 | 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) | ||
57 | 58 | features.vendor |= CHECK_VENDOR(features.idstr, "AuthenticAMD", VENDOR_AMD); |
58 | 59 | |
59 | 60 | //Detect the CPU model and feature flags |
60 | - if(cpuInfo[0] >= 1) | |
61 | + if(max_basic_cap >= 1) | |
61 | 62 | { |
62 | 63 | MY_CPUID(&cpuInfo[0], 1); |
63 | 64 | features.features |= CHECK_FLAG(cpuInfo[3], 0x00008000, FLAG_CMOV); |
@@ -66,7 +67,7 @@ MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(void) | ||
66 | 67 | features.features |= CHECK_FLAG(cpuInfo[3], 0x04000000, FLAG_SSE2); |
67 | 68 | features.features |= CHECK_FLAG(cpuInfo[2], 0x00000001, FLAG_SSE3); |
68 | 69 | features.features |= CHECK_FLAG(cpuInfo[2], 0x00000200, FLAG_SSSE3); |
69 | - features.features |= CHECK_FLAG(cpuInfo[2], 0x00080000, FLAG_SSE4); | |
70 | + features.features |= CHECK_FLAG(cpuInfo[2], 0x00080000, FLAG_SSE41); | |
70 | 71 | features.features |= CHECK_FLAG(cpuInfo[2], 0x00100000, FLAG_SSE42); |
71 | 72 | |
72 | 73 | //Check for AVX |
@@ -75,6 +76,7 @@ MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(void) | ||
75 | 76 | if((_xgetbv(0) & 0x6ui64) == 0x6ui64) /*AVX requires OS support!*/ |
76 | 77 | { |
77 | 78 | features.features |= FLAG_AVX; |
79 | + features.features |= CHECK_FLAG(cpuInfo[2], 0x00001000, FLAG_FMA3); | |
78 | 80 | } |
79 | 81 | } |
80 | 82 |
@@ -84,15 +86,33 @@ MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(void) | ||
84 | 86 | features.family = ((cpuInfo[0] >> 8) & 0xf) + ((cpuInfo[0] >> 20) & 0xff); |
85 | 87 | } |
86 | 88 | |
89 | + //Detect extended feature flags | |
90 | + if (max_basic_cap >= 7) | |
91 | + { | |
92 | + MY_CPUID(&cpuInfo[1], 7); | |
93 | + if (features.features & FLAG_AVX) | |
94 | + { | |
95 | + features.features |= CHECK_FLAG(cpuInfo[2], 0x00000020, FLAG_AVX2); | |
96 | + } | |
97 | + } | |
98 | + | |
87 | 99 | //Read the CPU "brand" string |
88 | - MY_CPUID(&cpuInfo[0], 0x80000000); | |
89 | - const uint32_t nExIds = qBound(0x80000000, cpuInfo[0], 0x80000004); | |
90 | - for(uint32_t i = 0x80000002; i <= nExIds; ++i) | |
100 | + if (max_basic_cap > 0) | |
91 | 101 | { |
92 | - MY_CPUID(&cpuInfo[0], i); | |
93 | - memcpy(&features.brand[(i - 0x80000002) * sizeof(cpuInfo)], &cpuInfo[0], sizeof(cpuInfo)); | |
102 | + MY_CPUID(&cpuInfo[0], 0x80000000); | |
103 | + const uint32_t max_extended_cap = qBound(0x80000000, cpuInfo[0], 0x80000004); | |
104 | + if (max_extended_cap >= 0x80000001) | |
105 | + { | |
106 | + MY_CPUID(&cpuInfo[0], 0x80000001); | |
107 | + features.features |= CHECK_FLAG(cpuInfo[2], 0x00000020, FLAG_LZCNT); | |
108 | + for (uint32_t i = 0x80000002; i <= max_extended_cap; ++i) | |
109 | + { | |
110 | + MY_CPUID(&cpuInfo[0], i); | |
111 | + memcpy(&features.brand[(i - 0x80000002) * sizeof(cpuInfo)], &cpuInfo[0], sizeof(cpuInfo)); | |
112 | + } | |
113 | + features.brand[sizeof(features.brand) - 1] = '\0'; | |
114 | + } | |
94 | 115 | } |
95 | - features.brand[sizeof(features.brand) - 1] = '\0'; | |
96 | 116 | |
97 | 117 | //Detect 64-Bit processors |
98 | 118 | #if (!(defined(_M_X64) || defined(_M_IA64))) |