OSDN Git Service

Moved the CPU detection code into the MUtils library.
[mutilities/MUtilities.git] / src / CPUFeatures_Win32.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2014 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.
14 //
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
18 //
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
21
22 //Win32 API
23 #define WIN32_LEAN_AND_MEAN 1
24 #include <Windows.h>
25
26 //MUtils
27 #include <MUtils/CPUFeatures.h>
28
29 //Qt
30 #include <QLibrary>
31
32 MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(const QStringList &argv)
33 {
34         typedef BOOL (WINAPI *IsWow64ProcessFun)(__in HANDLE hProcess, __out PBOOL Wow64Process);
35
36         cpu_info_t features;
37         SYSTEM_INFO systemInfo;
38         int CPUInfo[4] = {-1};
39         char CPUIdentificationString[0x40];
40         char CPUBrandString[0x40];
41
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));
46         
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);
53
54         if(CPUInfo[0] >= 1)
55         {
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                 features.stepping = CPUInfo[0] & 0xf;
65                 features.model    = ((CPUInfo[0] >> 4) & 0xf) + (((CPUInfo[0] >> 16) & 0xf) << 4);
66                 features.family   = ((CPUInfo[0] >> 8) & 0xf) + ((CPUInfo[0] >> 20) & 0xff);
67         }
68
69         __cpuid(CPUInfo, 0x80000000);
70         int nExIds = qMax<int>(qMin<int>(CPUInfo[0], 0x80000004), 0x80000000);
71
72         for(int i = 0x80000002; i <= nExIds; ++i)
73         {
74                 __cpuid(CPUInfo, i);
75                 switch(i)
76                 {
77                 case 0x80000002:
78                         memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
79                         break;
80                 case 0x80000003:
81                         memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
82                         break;
83                 case 0x80000004:
84                         memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
85                         break;
86                 }
87         }
88
89         strncpy_s(features.brand, 0x40, CPUBrandString, _TRUNCATE);
90
91         if(strlen(features.brand)  < 1) strncpy_s(features.brand,  0x40, "Unknown", _TRUNCATE);
92         if(strlen(features.vendor) < 1) strncpy_s(features.vendor, 0x40, "Unknown", _TRUNCATE);
93
94 #if (!(defined(_M_X64) || defined(_M_IA64)))
95         QLibrary Kernel32Lib("kernel32.dll");
96         if(IsWow64ProcessFun IsWow64ProcessPtr = (IsWow64ProcessFun) Kernel32Lib.resolve("IsWow64Process"))
97         {
98                 BOOL x64flag = FALSE;
99                 if(IsWow64ProcessPtr(GetCurrentProcess(), &x64flag))
100                 {
101                         features.x64 = (x64flag == TRUE);
102                 }
103         }
104 #else
105         features.x64 = true;
106 #endif
107
108         DWORD_PTR procAffinity, sysAffinity;
109         if(GetProcessAffinityMask(GetCurrentProcess(), &procAffinity, &sysAffinity))
110         {
111                 for(DWORD_PTR mask = 1; mask; mask <<= 1)
112                 {
113                         features.count += ((sysAffinity & mask) ? (1) : (0));
114                 }
115         }
116         if(features.count < 1)
117         {
118                 GetNativeSystemInfo(&systemInfo);
119                 features.count = qBound(1UL, systemInfo.dwNumberOfProcessors, 64UL);
120         }
121
122         if(argv.count() > 0)
123         {
124                 bool flag = false;
125                 for(int i = 0; i < argv.count(); i++)
126                 {
127                         if(!argv[i].compare("--force-cpu-no-64bit", Qt::CaseInsensitive)) { flag = true; features.x64 = false; }
128                         if(!argv[i].compare("--force-cpu-no-sse",   Qt::CaseInsensitive)) { flag = true; features.features &= (~(FLAG_SSE | FLAG_SSE2 | FLAG_SSE3 | FLAG_SSSE3 | FLAG_SSE4 | FLAG_SSE42)); }
129                         if(!argv[i].compare("--force-cpu-no-intel", Qt::CaseInsensitive)) { flag = true; features.intel = false; }
130                 }
131                 if(flag) qWarning("CPU flags overwritten by user-defined parameters. Take care!\n");
132         }
133
134         return features;
135 }