1d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
3d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Licensed under the Apache License, Version 2.0 (the "License");
4d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// you may not use this file except in compliance with the License.
5d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// You may obtain a copy of the License at
6894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
7d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//    http://www.apache.org/licenses/LICENSE-2.0
8894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
9d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Unless required by applicable law or agreed to in writing, software
10d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// distributed under the License is distributed on an "AS IS" BASIS,
11d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// See the License for the specific language governing permissions and
13d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// limitations under the License.
14894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
15894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "CPUID.hpp"
16894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
17894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#if defined(_WIN32)
18894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#ifndef WIN32_LEAN_AND_MEAN
19894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#define WIN32_LEAN_AND_MEAN
20894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#endif
21894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#include <windows.h>
22894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#include <intrin.h>
2366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	#include <float.h>
2466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#else
2566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	#include <unistd.h>
26894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#include <sched.h>
27894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#include <sys/types.h>
28894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
29894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
30894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumannamespace sw
31894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
32894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::MMX = detectMMX();
33894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::CMOV = detectCMOV();
34894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::SSE = detectSSE();
35894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::SSE2 = detectSSE2();
36894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::SSE3 = detectSSE3();
37894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::SSSE3 = detectSSSE3();
38894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::SSE4_1 = detectSSE4_1();
39894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	int CPUID::cores = detectCoreCount();
40894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	int CPUID::affinity = detectAffinity();
41894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
42894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::enableMMX = true;
43894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::enableCMOV = true;
44894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::enableSSE = true;
45894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::enableSSE2 = true;
46894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::enableSSE3 = true;
47894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::enableSSSE3 = true;
48894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::enableSSE4_1 = true;
49894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
50894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void CPUID::setEnableMMX(bool enable)
51894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
52894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		enableMMX = enable;
53894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
54894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!enableMMX)
55894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
56894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE = false;
57894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE2 = false;
58894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE3 = false;
59894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSSE3 = false;
60894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE4_1 = false;
61894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
62894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
63894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
64894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void CPUID::setEnableCMOV(bool enable)
65894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
66894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		enableCMOV = enable;
67894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
68894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!CMOV)
69894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
70894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE = false;
71894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE2 = false;
72894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE3 = false;
73894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSSE3 = false;
74894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE4_1 = false;
75894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
76894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
77894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
78894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void CPUID::setEnableSSE(bool enable)
79894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
8066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		enableSSE = enable;
81894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
82894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(enableSSE)
83894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
84894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableMMX = true;
85894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableCMOV = true;
86894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
87894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
88894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
89894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE2 = false;
90894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE3 = false;
91894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSSE3 = false;
92894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE4_1 = false;
93894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
94894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
95894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
96894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void CPUID::setEnableSSE2(bool enable)
97894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
98894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		enableSSE2 = enable;
99894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(enableSSE2)
101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableMMX = true;
103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableCMOV = true;
104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE = true;
105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE3 = false;
109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSSE3 = false;
110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE4_1 = false;
111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void CPUID::setEnableSSE3(bool enable)
115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
11666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		enableSSE3 = enable;
117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(enableSSE3)
119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableMMX = true;
121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableCMOV = true;
122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE = true;
123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE2 = true;
124894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSSE3 = false;
128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE4_1 = false;
129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void CPUID::setEnableSSSE3(bool enable)
133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		enableSSSE3 = enable;
135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(enableSSSE3)
137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableMMX = true;
139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableCMOV = true;
140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE = true;
141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE2 = true;
142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE3 = true;
143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE4_1 = false;
147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void CPUID::setEnableSSE4_1(bool enable)
151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		enableSSE4_1 = enable;
153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(enableSSE4_1)
155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableMMX = true;
157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableCMOV = true;
158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE = true;
159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE2 = true;
160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSE3 = true;
161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			enableSSSE3 = true;
162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
16566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	static void cpuid(int registers[4], int info)
16666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	{
1679ef5b6a8a59e7f6cafaa7eb98e30796e292bbe3bNicolas Capens		#if defined(__i386__) || defined(__x86_64__)
1689ef5b6a8a59e7f6cafaa7eb98e30796e292bbe3bNicolas Capens			#if defined(_WIN32)
1699ef5b6a8a59e7f6cafaa7eb98e30796e292bbe3bNicolas Capens				__cpuid(registers, info);
1709ef5b6a8a59e7f6cafaa7eb98e30796e292bbe3bNicolas Capens			#else
1719ef5b6a8a59e7f6cafaa7eb98e30796e292bbe3bNicolas Capens				__asm volatile("cpuid": "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]): "a" (info));
1729ef5b6a8a59e7f6cafaa7eb98e30796e292bbe3bNicolas Capens			#endif
17366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		#else
1749ef5b6a8a59e7f6cafaa7eb98e30796e292bbe3bNicolas Capens			registers[0] = 0;
1759ef5b6a8a59e7f6cafaa7eb98e30796e292bbe3bNicolas Capens			registers[1] = 0;
1769ef5b6a8a59e7f6cafaa7eb98e30796e292bbe3bNicolas Capens			registers[2] = 0;
1779ef5b6a8a59e7f6cafaa7eb98e30796e292bbe3bNicolas Capens			registers[3] = 0;
17866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		#endif
17966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	}
18066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::detectMMX()
182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
183c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		int registers[4];
184c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		cpuid(registers, 1);
185c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		return MMX = (registers[3] & 0x00800000) != 0;
186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::detectCMOV()
189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
190c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		int registers[4];
191c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		cpuid(registers, 1);
192c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		return CMOV = (registers[3] & 0x00008000) != 0;
193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
195894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::detectSSE()
196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
197c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		int registers[4];
198c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		cpuid(registers, 1);
199c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		return SSE = (registers[3] & 0x02000000) != 0;
200894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
201894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::detectSSE2()
203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
204c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		int registers[4];
205c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		cpuid(registers, 1);
206c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		return SSE2 = (registers[3] & 0x04000000) != 0;
207894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
209894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::detectSSE3()
210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
211c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		int registers[4];
212c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		cpuid(registers, 1);
213c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		return SSE3 = (registers[2] & 0x00000001) != 0;
214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
215894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::detectSSSE3()
217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
218c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		int registers[4];
219c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		cpuid(registers, 1);
220c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		return SSSE3 = (registers[2] & 0x00000200) != 0;
221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
222894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
223894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool CPUID::detectSSE4_1()
224894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
225c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		int registers[4];
226c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		cpuid(registers, 1);
227c71c4506fefbd3479d0e3ca0ea1a30c17c480701Nicolas Capens		return SSE4_1 = (registers[2] & 0x00080000) != 0;
228894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	int CPUID::detectCoreCount()
231894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
232894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int cores = 0;
233894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#if defined(_WIN32)
235894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			DWORD_PTR processAffinityMask = 1;
236894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			DWORD_PTR systemAffinityMask = 1;
23766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
238894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask);
239894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
240894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			while(systemAffinityMask)
241894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
242894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(systemAffinityMask & 1)
243894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
244894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					cores++;
245894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
246894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
247894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				systemAffinityMask >>= 1;
248894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
249894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#else
25066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			cores = sysconf(_SC_NPROCESSORS_ONLN);
251894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#endif
252894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(cores < 1)  cores = 1;
254894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(cores > 16) cores = 16;
255894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
256894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return cores;   // FIXME: Number of physical cores
257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
258894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	int CPUID::detectAffinity()
260894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
261894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int cores = 0;
262894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
263894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#if defined(_WIN32)
264894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			DWORD_PTR processAffinityMask = 1;
265894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			DWORD_PTR systemAffinityMask = 1;
26666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
267894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask);
268894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			while(processAffinityMask)
270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
271894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(processAffinityMask & 1)
272894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
273894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					cores++;
274894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
275894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
276894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				processAffinityMask >>= 1;
277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
278894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#else
27966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			return detectCoreCount();   // FIXME: Assumes no affinity limitation
280894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#endif
281894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(cores < 1)  cores = 1;
283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(cores > 16) cores = 16;
284894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
285894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return cores;
286894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
28766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
28866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	void CPUID::setFlushToZero(bool enable)
28966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	{
29066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		#if defined(_MSC_VER)
29166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			_controlfp(enable ? _DN_FLUSH : _DN_SAVE, _MCW_DN);
29266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		#else
29366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			// Unimplemented
29466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		#endif
29566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	}
29666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
29766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	void CPUID::setDenormalsAreZero(bool enable)
29866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	{
29966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		// Unimplemented
30066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	}
301894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
302