Mercurial > sdl-ios-xcode
comparison src/cpuinfo/gcpuinfo.c @ 739:22dbf364c017
Added SDL_HasMMX(), SDL_Has3DNow(), SDL_HasSSE() in SDL_cpuinfo.h
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 18 Nov 2003 01:27:06 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
738:82b85b731fe3 | 739:22dbf364c017 |
---|---|
1 /**************************************************************************** | |
2 * | |
3 * SciTech OS Portability Manager Library | |
4 * | |
5 * ======================================================================== | |
6 * | |
7 * Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved. | |
8 * | |
9 * This file may be distributed and/or modified under the terms of the | |
10 * GNU Lesser General Public License version 2.1 as published by the Free | |
11 * Software Foundation and appearing in the file LICENSE.LGPL included | |
12 * in the packaging of this file. | |
13 * | |
14 * Licensees holding a valid Commercial License for this product from | |
15 * SciTech Software, Inc. may use this file in accordance with the | |
16 * Commercial License Agreement provided with the Software. | |
17 * | |
18 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING | |
19 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
20 * PURPOSE. | |
21 * | |
22 * See http://www.scitechsoft.com/license/ for information about | |
23 * the licensing options available and how to purchase a Commercial | |
24 * License Agreement. | |
25 * | |
26 * Contact license@scitechsoft.com if any conditions of this licensing | |
27 * are not clear to you, or you have questions about licensing options. | |
28 * | |
29 * ======================================================================== | |
30 * | |
31 * Language: ANSI C | |
32 * Environment: Any | |
33 * | |
34 * Description: Main module to implement the Zen Timer support functions. | |
35 * | |
36 ****************************************************************************/ | |
37 | |
38 #include "cpuinfo.h" | |
39 //#include "pmapi.h" | |
40 //#include "oshdr.h" | |
41 | |
42 /*----------------------------- Implementation ----------------------------*/ | |
43 | |
44 /* External Intel assembler functions */ | |
45 #ifdef __INTEL__ | |
46 /* {secret} */ | |
47 ibool _ASMAPI _CPU_haveCPUID(void); | |
48 /* {secret} */ | |
49 ibool _ASMAPI _CPU_check80386(void); | |
50 /* {secret} */ | |
51 ibool _ASMAPI _CPU_check80486(void); | |
52 /* {secret} */ | |
53 uint _ASMAPI _CPU_checkCPUID(void); | |
54 /* {secret} */ | |
55 uint _ASMAPI _CPU_getCPUIDModel(void); | |
56 /* {secret} */ | |
57 uint _ASMAPI _CPU_getCPUIDStepping(void); | |
58 /* {secret} */ | |
59 uint _ASMAPI _CPU_getCPUIDFeatures(void); | |
60 /* {secret} */ | |
61 uint _ASMAPI _CPU_getCacheSize(void); | |
62 /* {secret} */ | |
63 uint _ASMAPI _CPU_have3DNow(void); | |
64 /* {secret} */ | |
65 ibool _ASMAPI _CPU_checkClone(void); | |
66 /* {secret} */ | |
67 void _ASMAPI _CPU_readTimeStamp(CPU_largeInteger *time); | |
68 /* {secret} */ | |
69 void _ASMAPI _CPU_runBSFLoop(ulong iterations); | |
70 /* {secret} */ | |
71 ulong _ASMAPI _CPU_mulDiv(ulong a,ulong b,ulong c); | |
72 /* {secret} */ | |
73 #define CPU_HaveMMX 0x00800000 | |
74 #define CPU_HaveRDTSC 0x00000010 | |
75 #define CPU_HaveSSE 0x02000000 | |
76 #endif | |
77 | |
78 /*------------------------ Public interface routines ----------------------*/ | |
79 | |
80 #ifdef __INTEL__ | |
81 extern Uint8 PM_inpb(int port); | |
82 extern void PM_outpb(int port,Uint8 val); | |
83 | |
84 /**************************************************************************** | |
85 REMARKS: | |
86 Read an I/O port location. | |
87 ****************************************************************************/ | |
88 static uchar rdinx( | |
89 int port, | |
90 int index) | |
91 { | |
92 PM_outpb(port,(uchar)index); | |
93 return PM_inpb(port+1); | |
94 } | |
95 | |
96 /**************************************************************************** | |
97 REMARKS: | |
98 Write an I/O port location. | |
99 ****************************************************************************/ | |
100 static void wrinx( | |
101 ushort port, | |
102 ushort index, | |
103 ushort value) | |
104 { | |
105 PM_outpb(port,(uchar)index); | |
106 PM_outpb(port+1,(uchar)value); | |
107 } | |
108 | |
109 /**************************************************************************** | |
110 REMARKS: | |
111 Enables the Cyrix CPUID instruction to properly detect MediaGX and 6x86 | |
112 processors. | |
113 ****************************************************************************/ | |
114 static void _CPU_enableCyrixCPUID(void) | |
115 { | |
116 uchar ccr3; | |
117 | |
118 //PM_init(); | |
119 ccr3 = rdinx(0x22,0xC3); | |
120 wrinx(0x22,0xC3,(uchar)(ccr3 | 0x10)); | |
121 wrinx(0x22,0xE8,(uchar)(rdinx(0x22,0xE8) | 0x80)); | |
122 wrinx(0x22,0xC3,ccr3); | |
123 } | |
124 #endif | |
125 | |
126 /**************************************************************************** | |
127 DESCRIPTION: | |
128 Returns the type of processor in the system. | |
129 | |
130 HEADER: | |
131 cpuinfo.h | |
132 | |
133 RETURNS: | |
134 Numerical identifier for the installed processor | |
135 | |
136 REMARKS: | |
137 Returns the type of processor in the system. Note that if the CPU is an | |
138 unknown Pentium family processor that we don't have an enumeration for, | |
139 the return value will be greater than or equal to the value of CPU_UnkPentium | |
140 (depending on the value returned by the CPUID instruction). | |
141 | |
142 SEE ALSO: | |
143 CPU_getProcessorSpeed, CPU_haveMMX, CPU_getProcessorName | |
144 ****************************************************************************/ | |
145 uint ZAPI CPU_getProcessorType(void) | |
146 { | |
147 #if defined(__INTEL__) | |
148 uint cpu,vendor,model,cacheSize; | |
149 static ibool firstTime = true; | |
150 | |
151 if (_CPU_haveCPUID()) { | |
152 cpu = _CPU_checkCPUID(); | |
153 vendor = cpu & ~CPU_mask; | |
154 if (vendor == CPU_Intel) { | |
155 /* Check for Intel processors */ | |
156 switch (cpu & CPU_mask) { | |
157 case 4: cpu = CPU_i486; break; | |
158 case 5: cpu = CPU_Pentium; break; | |
159 case 6: | |
160 if ((model = _CPU_getCPUIDModel()) == 1) | |
161 cpu = CPU_PentiumPro; | |
162 else if (model <= 6) { | |
163 cacheSize = _CPU_getCacheSize(); | |
164 if ((model == 5 && cacheSize == 0) || | |
165 (model == 5 && cacheSize == 256) || | |
166 (model == 6 && cacheSize == 128)) | |
167 cpu = CPU_Celeron; | |
168 else | |
169 cpu = CPU_PentiumII; | |
170 } | |
171 else if (model >= 7) { | |
172 /* Model 7 == Pentium III */ | |
173 /* Model 8 == Celeron/Pentium III Coppermine */ | |
174 cacheSize = _CPU_getCacheSize(); | |
175 if ((model == 8 && cacheSize == 128)) | |
176 cpu = CPU_Celeron; | |
177 else | |
178 cpu = CPU_PentiumIII; | |
179 } | |
180 break; | |
181 case 7: | |
182 cpu = CPU_Pentium4; | |
183 break; | |
184 default: | |
185 cpu = CPU_UnkIntel; | |
186 break; | |
187 } | |
188 } | |
189 else if (vendor == CPU_Cyrix) { | |
190 /* Check for Cyrix processors */ | |
191 switch (cpu & CPU_mask) { | |
192 case 4: | |
193 if ((model = _CPU_getCPUIDModel()) == 4) | |
194 cpu = CPU_CyrixMediaGX; | |
195 else | |
196 cpu = CPU_UnkCyrix; | |
197 break; | |
198 case 5: | |
199 if ((model = _CPU_getCPUIDModel()) == 2) | |
200 cpu = CPU_Cyrix6x86; | |
201 else if (model == 4) | |
202 cpu = CPU_CyrixMediaGXm; | |
203 else | |
204 cpu = CPU_UnkCyrix; | |
205 break; | |
206 case 6: | |
207 if ((model = _CPU_getCPUIDModel()) <= 1) | |
208 cpu = CPU_Cyrix6x86MX; | |
209 else | |
210 cpu = CPU_UnkCyrix; | |
211 break; | |
212 default: | |
213 cpu = CPU_UnkCyrix; | |
214 break; | |
215 } | |
216 } | |
217 else if (vendor == CPU_AMD) { | |
218 /* Check for AMD processors */ | |
219 switch (cpu & CPU_mask) { | |
220 case 4: | |
221 if ((model = _CPU_getCPUIDModel()) == 0) | |
222 cpu = CPU_AMDAm5x86; | |
223 else | |
224 cpu = CPU_AMDAm486; | |
225 break; | |
226 case 5: | |
227 if ((model = _CPU_getCPUIDModel()) <= 3) | |
228 cpu = CPU_AMDK5; | |
229 else if (model <= 7) | |
230 cpu = CPU_AMDK6; | |
231 else if (model == 8) | |
232 cpu = CPU_AMDK6_2; | |
233 else if (model == 9) | |
234 cpu = CPU_AMDK6_III; | |
235 else if (model == 13) { | |
236 if (_CPU_getCPUIDStepping() <= 3) | |
237 cpu = CPU_AMDK6_IIIplus; | |
238 else | |
239 cpu = CPU_AMDK6_2plus; | |
240 } | |
241 else | |
242 cpu = CPU_UnkAMD; | |
243 break; | |
244 case 6: | |
245 if ((model = _CPU_getCPUIDModel()) == 3) | |
246 cpu = CPU_AMDDuron; | |
247 else | |
248 cpu = CPU_AMDAthlon; | |
249 break; | |
250 default: | |
251 cpu = CPU_UnkAMD; | |
252 break; | |
253 } | |
254 } | |
255 else if (vendor == CPU_IDT) { | |
256 /* Check for IDT WinChip processors */ | |
257 switch (cpu & CPU_mask) { | |
258 case 5: | |
259 if ((model = _CPU_getCPUIDModel()) <= 4) | |
260 cpu = CPU_WinChipC6; | |
261 else if (model == 8) | |
262 cpu = CPU_WinChip2; | |
263 else | |
264 cpu = CPU_UnkIDT; | |
265 break; | |
266 case 6: | |
267 vendor = CPU_VIA; | |
268 if ((model = _CPU_getCPUIDModel()) <= 6) | |
269 cpu = CPU_ViaCyrixIII; | |
270 else | |
271 cpu = CPU_UnkVIA; | |
272 break; | |
273 default: | |
274 vendor = CPU_VIA; | |
275 cpu = CPU_UnkVIA; | |
276 break; | |
277 } | |
278 } | |
279 else { | |
280 /* Assume a Pentium compatible Intel clone */ | |
281 cpu = CPU_Pentium; | |
282 } | |
283 return cpu | vendor | (_CPU_getCPUIDStepping() << CPU_steppingShift); | |
284 } | |
285 else { | |
286 if (_CPU_check80386()) | |
287 cpu = CPU_i386; | |
288 else if (_CPU_check80486()) { | |
289 /* If we get here we may have a Cyrix processor so we can try | |
290 * enabling the CPUID instruction and trying again. | |
291 */ | |
292 if (firstTime) { | |
293 firstTime = false; | |
294 _CPU_enableCyrixCPUID(); | |
295 return CPU_getProcessorType(); | |
296 } | |
297 cpu = CPU_i486; | |
298 } | |
299 else | |
300 cpu = CPU_Pentium; | |
301 if (!_CPU_checkClone()) | |
302 return cpu | CPU_Intel; | |
303 return cpu; | |
304 } | |
305 #elif defined(__ALPHA__) | |
306 return CPU_Alpha; | |
307 #elif defined(__MIPS__) | |
308 return CPU_Mips; | |
309 #elif defined(__PPC__) | |
310 return CPU_PowerPC; | |
311 #endif | |
312 } | |
313 | |
314 /**************************************************************************** | |
315 DESCRIPTION: | |
316 Returns true if the processor supports Intel MMX extensions. | |
317 | |
318 HEADER: | |
319 cpuinfo.h | |
320 | |
321 RETURNS: | |
322 True if MMX is available, false if not. | |
323 | |
324 REMARKS: | |
325 This function determines if the processor supports the Intel MMX extended | |
326 instruction set. | |
327 | |
328 SEE ALSO: | |
329 CPU_getProcessorType, CPU_getProcessorSpeed, CPU_have3DNow, CPU_haveSSE, | |
330 CPU_getProcessorName | |
331 ****************************************************************************/ | |
332 ibool ZAPI CPU_haveMMX(void) | |
333 { | |
334 #ifdef __INTEL__ | |
335 if (_CPU_haveCPUID()) | |
336 return (_CPU_getCPUIDFeatures() & CPU_HaveMMX) != 0; | |
337 return false; | |
338 #else | |
339 return false; | |
340 #endif | |
341 } | |
342 | |
343 /**************************************************************************** | |
344 DESCRIPTION: | |
345 Returns true if the processor supports AMD 3DNow! extensions. | |
346 | |
347 HEADER: | |
348 cpuinfo.h | |
349 | |
350 RETURNS: | |
351 True if 3DNow! is available, false if not. | |
352 | |
353 REMARKS: | |
354 This function determines if the processor supports the AMD 3DNow! extended | |
355 instruction set. | |
356 | |
357 SEE ALSO: | |
358 CPU_getProcessorType, CPU_getProcessorSpeed, CPU_haveMMX, CPU_haveSSE, | |
359 CPU_getProcessorName | |
360 ****************************************************************************/ | |
361 ibool ZAPI CPU_have3DNow(void) | |
362 { | |
363 #ifdef __INTEL__ | |
364 if (_CPU_haveCPUID()) | |
365 return _CPU_have3DNow(); | |
366 return false; | |
367 #else | |
368 return false; | |
369 #endif | |
370 } | |
371 | |
372 /**************************************************************************** | |
373 DESCRIPTION: | |
374 Returns true if the processor supports Intel SSE extensions. | |
375 | |
376 HEADER: | |
377 cpuinfo.h | |
378 | |
379 RETURNS: | |
380 True if Intel SSE is available, false if not. | |
381 | |
382 REMARKS: | |
383 This function determines if the processor supports the Intel SSE extended | |
384 instruction set. | |
385 | |
386 SEE ALSO: | |
387 CPU_getProcessorType, CPU_getProcessorSpeed, CPU_haveMMX, CPU_have3DNow, | |
388 CPU_getProcessorName | |
389 ****************************************************************************/ | |
390 ibool ZAPI CPU_haveSSE(void) | |
391 { | |
392 #ifdef __INTEL__ | |
393 if (_CPU_haveCPUID()) | |
394 return (_CPU_getCPUIDFeatures() & CPU_HaveSSE) != 0; | |
395 return false; | |
396 #else | |
397 return false; | |
398 #endif | |
399 } | |
400 | |
401 /**************************************************************************** | |
402 RETURNS: | |
403 True if the RTSC instruction is available, false if not. | |
404 | |
405 REMARKS: | |
406 This function determines if the processor supports the Intel RDTSC | |
407 instruction, for high precision timing. If the processor is not an Intel or | |
408 Intel clone CPU, this function will always return false. | |
409 | |
410 DESCRIPTION: | |
411 Returns true if the processor supports RDTSC extensions. | |
412 | |
413 HEADER: | |
414 cpuinfo.h | |
415 | |
416 RETURNS: | |
417 True if RTSC is available, false if not. | |
418 | |
419 REMARKS: | |
420 This function determines if the processor supports the RDTSC instruction | |
421 for reading the processor time stamp counter. | |
422 | |
423 SEE ALSO: | |
424 CPU_getProcessorType, CPU_getProcessorSpeed, CPU_haveMMX, CPU_have3DNow, | |
425 CPU_getProcessorName | |
426 ****************************************************************************/ | |
427 ibool ZAPI CPU_haveRDTSC(void) | |
428 { | |
429 #ifdef __INTEL__ | |
430 if (_CPU_haveCPUID()) | |
431 return (_CPU_getCPUIDFeatures() & CPU_HaveRDTSC) != 0; | |
432 return false; | |
433 #else | |
434 return false; | |
435 #endif | |
436 } |