Documentation updates.
[MUtilities.git] / src / CPUFeatures_Win32.cpp
blob12207442b1f8cf1132d9d8719e8f32d556cdff36
1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2016 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
22 //Win32 API
23 #define WIN32_LEAN_AND_MEAN 1
24 #include <Windows.h>
26 //MUtils
27 #include <MUtils/CPUFeatures.h>
28 #include <MUtils/OSSupport.h>
29 #include "Utils_Win32.h"
31 MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(void)
33 const OS::ArgumentMap &args = OS::arguments();
34 typedef BOOL (WINAPI *IsWow64ProcessFun)(__in HANDLE hProcess, __out PBOOL Wow64Process);
36 cpu_info_t features;
37 SYSTEM_INFO systemInfo;
38 int CPUInfo[4] = {-1};
39 char CPUIdentificationString[0x40];
40 char CPUBrandString[0x40];
42 memset(&features, 0, sizeof(cpu_info_t));
43 memset(&systemInfo, 0, sizeof(SYSTEM_INFO));
44 memset(CPUIdentificationString, 0, sizeof(CPUIdentificationString));
45 memset(CPUBrandString, 0, sizeof(CPUBrandString));
47 __cpuid(CPUInfo, 0);
48 memcpy(CPUIdentificationString, &CPUInfo[1], sizeof(int));
49 memcpy(CPUIdentificationString + 4, &CPUInfo[3], sizeof(int));
50 memcpy(CPUIdentificationString + 8, &CPUInfo[2], sizeof(int));
51 features.intel = (_stricmp(CPUIdentificationString, "GenuineIntel") == 0);
52 strncpy_s(features.vendor, 0x40, CPUIdentificationString, _TRUNCATE);
54 if(CPUInfo[0] >= 1)
56 __cpuid(CPUInfo, 1);
57 if(CPUInfo[3] & 0x00800000) features.features |= FLAG_MMX;
58 if(CPUInfo[3] & 0x02000000) features.features |= FLAG_SSE;
59 if(CPUInfo[3] & 0x04000000) features.features |= FLAG_SSE2;
60 if(CPUInfo[2] & 0x00000001) features.features |= FLAG_SSE3;
61 if(CPUInfo[2] & 0x00000200) features.features |= FLAG_SSSE3;
62 if(CPUInfo[2] & 0x00080000) features.features |= FLAG_SSE4;
63 if(CPUInfo[2] & 0x00100000) features.features |= FLAG_SSE42;
64 if ((CPUInfo[2] & 0x18000000) == 0x18000000)
66 if((_xgetbv(0) & 0x6ui64) == 0x6ui64) /*AVX requires OS support!*/
68 features.features |= FLAG_AVX;
71 features.stepping = CPUInfo[0] & 0xf;
72 features.model = ((CPUInfo[0] >> 4) & 0xf) + (((CPUInfo[0] >> 16) & 0xf) << 4);
73 features.family = ((CPUInfo[0] >> 8) & 0xf) + ((CPUInfo[0] >> 20) & 0xff);
76 __cpuid(CPUInfo, 0x80000000);
77 int nExIds = qMax<int>(qMin<int>(CPUInfo[0], 0x80000004), 0x80000000);
79 for(int i = 0x80000002; i <= nExIds; ++i)
81 __cpuid(CPUInfo, i);
82 switch(i)
84 case 0x80000002:
85 memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
86 break;
87 case 0x80000003:
88 memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
89 break;
90 case 0x80000004:
91 memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
92 break;
96 strncpy_s(features.brand, 0x40, CPUBrandString, _TRUNCATE);
98 if(strlen(features.brand) < 1) strncpy_s(features.brand, 0x40, "Unknown", _TRUNCATE);
99 if(strlen(features.vendor) < 1) strncpy_s(features.vendor, 0x40, "Unknown", _TRUNCATE);
101 #if (!(defined(_M_X64) || defined(_M_IA64)))
102 const IsWow64ProcessFun isWow64ProcessPtr = MUtils::Win32Utils::resolve<IsWow64ProcessFun>(QLatin1String("kernel32"), QLatin1String("IsWow64Process"));
103 if(isWow64ProcessPtr)
105 BOOL x64flag = FALSE;
106 if(isWow64ProcessPtr(GetCurrentProcess(), &x64flag))
108 if(x64flag) features.x64 = true;
111 #else
112 features.x64 = true;
113 #endif
115 if (features.x64)
117 features.features |= (FLAG_MMX | FLAG_SSE | FLAG_SSE2); /*x86_64 implies SSE2*/
120 if (!(features.features & FLAG_MMX))
122 qWarning("Warning: CPU does not seem to support MMX. Take care!\n");
123 features.features = 0;
126 DWORD_PTR procAffinity, sysAffinity;
127 if(GetProcessAffinityMask(GetCurrentProcess(), &procAffinity, &sysAffinity))
129 for(DWORD_PTR mask = 1; mask; mask <<= 1)
131 features.count += ((sysAffinity & mask) ? (1) : (0));
134 if(features.count < 1)
136 GetNativeSystemInfo(&systemInfo);
137 features.count = qBound(1UL, systemInfo.dwNumberOfProcessors, 64UL);
140 bool userFlag = false;
141 if(args.contains("force-cpu-no-64bit")) { userFlag = true; features.x64 = false; }
142 if(args.contains("force-cpu-no-sse" )) { userFlag = true; features.features &= (~(FLAG_SSE | FLAG_SSE2 | FLAG_SSE3 | FLAG_SSSE3 | FLAG_SSE4 | FLAG_SSE42)); }
143 if(args.contains("force-cpu-no-intel")) { userFlag = true; features.intel = false; }
145 if(userFlag)
147 qWarning("CPU flags overwritten by user-defined parameters. Take care!\n");
150 return features;