blob: 698fe887e77a6ef1a34e9de2c3d36e8cf03987e6 [file] [log] [blame]
Nicolas Capens68a82382018-10-02 13:16:55 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "CPUID.hpp"
16
17#if defined(_WIN32)
Ben Clayton595d9112019-12-17 20:37:57 +000018# ifndef WIN32_LEAN_AND_MEAN
19# define WIN32_LEAN_AND_MEAN
20# endif
21# include <windows.h>
22# include <intrin.h>
23# include <float.h>
Nicolas Capens68a82382018-10-02 13:16:55 -040024#else
Ben Clayton595d9112019-12-17 20:37:57 +000025# include <unistd.h>
26# include <sched.h>
27# include <sys/types.h>
Nicolas Capens68a82382018-10-02 13:16:55 -040028#endif
29
Nicolas Capens157ba262019-12-10 17:49:14 -050030namespace sw {
31
32bool CPUID::MMX = detectMMX();
33bool CPUID::CMOV = detectCMOV();
34bool CPUID::SSE = detectSSE();
35bool CPUID::SSE2 = detectSSE2();
36bool CPUID::SSE3 = detectSSE3();
37bool CPUID::SSSE3 = detectSSSE3();
38bool CPUID::SSE4_1 = detectSSE4_1();
39int CPUID::cores = detectCoreCount();
40int CPUID::affinity = detectAffinity();
41
42bool CPUID::enableMMX = true;
43bool CPUID::enableCMOV = true;
44bool CPUID::enableSSE = true;
45bool CPUID::enableSSE2 = true;
46bool CPUID::enableSSE3 = true;
47bool CPUID::enableSSSE3 = true;
48bool CPUID::enableSSE4_1 = true;
49
50void CPUID::setEnableMMX(bool enable)
Nicolas Capens68a82382018-10-02 13:16:55 -040051{
Nicolas Capens157ba262019-12-10 17:49:14 -050052 enableMMX = enable;
Nicolas Capens68a82382018-10-02 13:16:55 -040053
Nicolas Capens157ba262019-12-10 17:49:14 -050054 if(!enableMMX)
Nicolas Capens68a82382018-10-02 13:16:55 -040055 {
Nicolas Capens157ba262019-12-10 17:49:14 -050056 enableSSE = false;
57 enableSSE2 = false;
58 enableSSE3 = false;
59 enableSSSE3 = false;
60 enableSSE4_1 = false;
Nicolas Capens68a82382018-10-02 13:16:55 -040061 }
62}
Nicolas Capens157ba262019-12-10 17:49:14 -050063
64void CPUID::setEnableCMOV(bool enable)
65{
66 enableCMOV = enable;
67
68 if(!CMOV)
69 {
70 enableSSE = false;
71 enableSSE2 = false;
72 enableSSE3 = false;
73 enableSSSE3 = false;
74 enableSSE4_1 = false;
75 }
76}
77
78void CPUID::setEnableSSE(bool enable)
79{
80 enableSSE = enable;
81
82 if(enableSSE)
83 {
84 enableMMX = true;
85 enableCMOV = true;
86 }
87 else
88 {
89 enableSSE2 = false;
90 enableSSE3 = false;
91 enableSSSE3 = false;
92 enableSSE4_1 = false;
93 }
94}
95
96void CPUID::setEnableSSE2(bool enable)
97{
98 enableSSE2 = enable;
99
100 if(enableSSE2)
101 {
102 enableMMX = true;
103 enableCMOV = true;
104 enableSSE = true;
105 }
106 else
107 {
108 enableSSE3 = false;
109 enableSSSE3 = false;
110 enableSSE4_1 = false;
111 }
112}
113
114void CPUID::setEnableSSE3(bool enable)
115{
116 enableSSE3 = enable;
117
118 if(enableSSE3)
119 {
120 enableMMX = true;
121 enableCMOV = true;
122 enableSSE = true;
123 enableSSE2 = true;
124 }
125 else
126 {
127 enableSSSE3 = false;
128 enableSSE4_1 = false;
129 }
130}
131
132void CPUID::setEnableSSSE3(bool enable)
133{
134 enableSSSE3 = enable;
135
136 if(enableSSSE3)
137 {
138 enableMMX = true;
139 enableCMOV = true;
140 enableSSE = true;
141 enableSSE2 = true;
142 enableSSE3 = true;
143 }
144 else
145 {
146 enableSSE4_1 = false;
147 }
148}
149
150void CPUID::setEnableSSE4_1(bool enable)
151{
152 enableSSE4_1 = enable;
153
154 if(enableSSE4_1)
155 {
156 enableMMX = true;
157 enableCMOV = true;
158 enableSSE = true;
159 enableSSE2 = true;
160 enableSSE3 = true;
161 enableSSSE3 = true;
162 }
163}
164
165static void cpuid(int registers[4], int info)
166{
Ben Clayton595d9112019-12-17 20:37:57 +0000167#if defined(__i386__) || defined(__x86_64__)
168# if defined(_WIN32)
169 __cpuid(registers, info);
170# else
171 __asm volatile("cpuid"
172 : "=a"(registers[0]), "=b"(registers[1]), "=c"(registers[2]), "=d"(registers[3])
173 : "a"(info));
174# endif
175#else
176 registers[0] = 0;
177 registers[1] = 0;
178 registers[2] = 0;
179 registers[3] = 0;
180#endif
Nicolas Capens157ba262019-12-10 17:49:14 -0500181}
182
183bool CPUID::detectMMX()
184{
185 int registers[4];
186 cpuid(registers, 1);
187 return MMX = (registers[3] & 0x00800000) != 0;
188}
189
190bool CPUID::detectCMOV()
191{
192 int registers[4];
193 cpuid(registers, 1);
194 return CMOV = (registers[3] & 0x00008000) != 0;
195}
196
197bool CPUID::detectSSE()
198{
199 int registers[4];
200 cpuid(registers, 1);
201 return SSE = (registers[3] & 0x02000000) != 0;
202}
203
204bool CPUID::detectSSE2()
205{
206 int registers[4];
207 cpuid(registers, 1);
208 return SSE2 = (registers[3] & 0x04000000) != 0;
209}
210
211bool CPUID::detectSSE3()
212{
213 int registers[4];
214 cpuid(registers, 1);
215 return SSE3 = (registers[2] & 0x00000001) != 0;
216}
217
218bool CPUID::detectSSSE3()
219{
220 int registers[4];
221 cpuid(registers, 1);
222 return SSSE3 = (registers[2] & 0x00000200) != 0;
223}
224
225bool CPUID::detectSSE4_1()
226{
227 int registers[4];
228 cpuid(registers, 1);
229 return SSE4_1 = (registers[2] & 0x00080000) != 0;
230}
231
232int CPUID::detectCoreCount()
233{
234 int cores = 0;
235
Ben Clayton595d9112019-12-17 20:37:57 +0000236#if defined(_WIN32)
237 DWORD_PTR processAffinityMask = 1;
238 DWORD_PTR systemAffinityMask = 1;
Nicolas Capens157ba262019-12-10 17:49:14 -0500239
Ben Clayton595d9112019-12-17 20:37:57 +0000240 GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask);
Nicolas Capens157ba262019-12-10 17:49:14 -0500241
Ben Clayton595d9112019-12-17 20:37:57 +0000242 while(systemAffinityMask)
243 {
244 if(systemAffinityMask & 1)
Nicolas Capens157ba262019-12-10 17:49:14 -0500245 {
Ben Clayton595d9112019-12-17 20:37:57 +0000246 cores++;
Nicolas Capens157ba262019-12-10 17:49:14 -0500247 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500248
Ben Clayton595d9112019-12-17 20:37:57 +0000249 systemAffinityMask >>= 1;
250 }
251#else
252 cores = sysconf(_SC_NPROCESSORS_ONLN);
253#endif
254
255 if(cores < 1) cores = 1;
Nicolas Capens157ba262019-12-10 17:49:14 -0500256 if(cores > 16) cores = 16;
257
Ben Clayton595d9112019-12-17 20:37:57 +0000258 return cores; // FIXME: Number of physical cores
Nicolas Capens157ba262019-12-10 17:49:14 -0500259}
260
261int CPUID::detectAffinity()
262{
263 int cores = 0;
264
Ben Clayton595d9112019-12-17 20:37:57 +0000265#if defined(_WIN32)
266 DWORD_PTR processAffinityMask = 1;
267 DWORD_PTR systemAffinityMask = 1;
Nicolas Capens157ba262019-12-10 17:49:14 -0500268
Ben Clayton595d9112019-12-17 20:37:57 +0000269 GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask);
Nicolas Capens157ba262019-12-10 17:49:14 -0500270
Ben Clayton595d9112019-12-17 20:37:57 +0000271 while(processAffinityMask)
272 {
273 if(processAffinityMask & 1)
Nicolas Capens157ba262019-12-10 17:49:14 -0500274 {
Ben Clayton595d9112019-12-17 20:37:57 +0000275 cores++;
Nicolas Capens157ba262019-12-10 17:49:14 -0500276 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500277
Ben Clayton595d9112019-12-17 20:37:57 +0000278 processAffinityMask >>= 1;
279 }
280#else
281 return detectCoreCount(); // FIXME: Assumes no affinity limitation
282#endif
283
284 if(cores < 1) cores = 1;
Nicolas Capens157ba262019-12-10 17:49:14 -0500285 if(cores > 16) cores = 16;
286
287 return cores;
288}
289
290void CPUID::setFlushToZero(bool enable)
291{
Ben Clayton595d9112019-12-17 20:37:57 +0000292#if defined(_MSC_VER)
293 _controlfp(enable ? _DN_FLUSH : _DN_SAVE, _MCW_DN);
294#else
295 // Unimplemented
296#endif
Nicolas Capens157ba262019-12-10 17:49:14 -0500297}
298
299void CPUID::setDenormalsAreZero(bool enable)
300{
301 // Unimplemented
302}
303
304} // namespace sw