source: trunk/src/kernel32/cpu.cpp@ 22018

Last change on this file since 22018 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 7.1 KB
Line 
1/* $Id: cpu.cpp,v 1.15 2004-02-20 10:05:39 sandervl Exp $ */
2/*
3 * Odin win32 CPU apis
4 *
5 * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 *
7 * Based on Wine Code (991031: misc\cpu.c)
8 *
9 * Copyright 1995,1997 Morten Welinder
10 * Copyright 1997-1998 Marcus Meissner
11 */
12
13#include <os2win.h>
14#include <ctype.h>
15#include <string.h>
16#include "winreg.h"
17#include "global.h"
18#include "winnt.h"
19#include "winerror.h"
20#include "winreg.h"
21#include "debugtools.h"
22#include <cpuhlp.h>
23
24#define DBG_LOCALLOG DBG_cpu
25#include "dbglocal.h"
26
27DEFAULT_DEBUG_CHANNEL(CPU)
28
29static BYTE PF[64] = {0,};
30static int nrCPUs = 1;
31static SYSTEM_INFO cachedsi = {0};
32
33//******************************************************************************
34//******************************************************************************
35void InitSystemInfo(int nrcpus)
36{
37 SYSTEM_INFO si;
38
39 nrCPUs = nrcpus;
40 GetSystemInfo(&si);
41}
42/***********************************************************************
43 * GetSystemInfo [KERNELL32.404]
44 *
45 * Gets the current system information.
46 *
47 * On the first call it reads cached values, so it doesn't have to determine
48 * them repeatedly. On Linux, the /proc/cpuinfo special file is used.
49 *
50 * It creates a registry subhierarchy, looking like:
51 * \HARDWARE\DESCRIPTION\System\CentralProcessor\<processornumber>\
52 * Identifier (CPU x86)
53 * Note that there is a hierarchy for every processor installed, so this
54 * supports multiprocessor systems. This is done like Win95 does it, I think.
55 *
56 * It also creates a cached flag array for IsProcessorFeaturePresent().
57 *
58 * RETURNS
59 * nothing, really
60 */
61VOID WINAPI GetSystemInfo(LPSYSTEM_INFO si) /* [out] system information */
62{
63 HKEY xhkey=0,hkey;
64 HKEY fpukey=0, xhfpukey;
65 char buf[20];
66 DWORD features, signature;
67 static int cache = 0;
68
69 if(!si) {
70 dprintf(("GetSystemInfo -> si == NULL!!"));
71 SetLastError(ERROR_INVALID_PARAMETER);
72 return;
73 }
74 if (cache) {
75 memcpy(si,&cachedsi,sizeof(*si));
76 return;
77 }
78 memset(PF,0,sizeof(PF));
79
80 /* choose sensible defaults ...
81 * FIXME: perhaps overrideable with precompiler flags?
82 */
83 cachedsi.u.x.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
84 cachedsi.dwPageSize = 4096;
85
86 /* FIXME: better values for the two entries below... */
87 cachedsi.lpMinimumApplicationAddress = (void *)0x00400000;
88 cachedsi.lpMaximumApplicationAddress = (void *)0x7FFFFFFF;
89 cachedsi.dwActiveProcessorMask = 1;
90 cachedsi.dwNumberOfProcessors = nrCPUs;
91 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
92 cachedsi.dwAllocationGranularity = 0x10000;
93 cachedsi.wProcessorLevel = 3; /* 386 */
94 cachedsi.wProcessorRevision = 0;
95
96 cache = 1; /* even if there is no more info, we now have a cacheentry */
97 memcpy(si,&cachedsi,sizeof(*si));
98
99 /* Hmm, reasonable processor feature defaults? */
100
101 /* Create this registry key for all systems */
102 if (RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System\\CentralProcessor",&hkey)!=ERROR_SUCCESS) {
103 dprintf(("Unable to register CPU information\n"));
104 }
105
106 if(SupportsCPUID())
107 {
108 for(int i=0;i<cachedsi.dwNumberOfProcessors;i++)
109 {
110 // Create a new processor subkey
111 sprintf(buf,"%d",i);
112 if (xhkey)
113 RegCloseKey(xhkey);
114 RegCreateKeyA(hkey,buf,&xhkey);
115
116 signature = GetCPUSignature();
117
118 switch ((signature >> 8)&0xf) {
119 case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
120 break;
121 case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
122 break;
123 case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
124 break;
125 case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
126 break;
127 default:
128 cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
129 break;
130 }
131 cachedsi.wProcessorRevision = signature & 0xff;
132 cachedsi.wProcessorLevel = (signature >> 8)&0xf;
133
134 /* set the CPU type of the current processor */
135 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
136 if (xhkey) {
137 RegSetValueExA(xhkey,"Identifier",0,REG_SZ,(LPBYTE)buf,strlen(buf));
138 memset(buf, 0, sizeof(buf));
139 GetCPUVendorString(buf);
140 RegSetValueExA(xhkey,"VendorIdentifier",0,REG_SZ,(LPBYTE)buf,strlen(buf));
141#ifdef __WIN32OS2__
142 if(i==0) {
143 DWORD mhz;
144 features = GetCPUFeatures();
145 if(features & CPUID_TIME_STAMP_COUNTER) {
146 LARGE_INTEGER tsc1, tsc2, freq, time1, time2;
147 double clockticks, millisec, frequency, tmp, tmp1, mhertz;
148
149 QueryPerformanceFrequency(&freq);
150
151 GetTSC((LONG *)&tsc1.LowPart, &tsc1.HighPart);
152 QueryPerformanceCounter(&time1);
153
154 Sleep(32); //sleep for about 32 ms
155
156 GetTSC((LONG *)&tsc2.LowPart, &tsc2.HighPart);
157 QueryPerformanceCounter(&time2);
158 tmp = (double)time2.LowPart + (double)time2.HighPart*4.0*1024.0*1024.0;
159 tmp1 = (double)time1.LowPart + (double)time1.HighPart*4.0*1024.0*1024.0;
160 millisec = tmp - tmp1;
161
162 frequency= (double)freq.LowPart;
163 frequency= frequency / 1000.0;
164 millisec = millisec / frequency;
165
166 tmp = (double)tsc2.LowPart + (double)tsc2.HighPart*4.0*1024.0*1024.0;
167 tmp1 = (double)tsc1.LowPart + (double)tsc1.HighPart*4.0*1024.0*1024.0;
168 clockticks = tmp - tmp1;
169 if(millisec > 0)
170 {//make sure we have something valid here
171 tmp = 1000 / millisec;
172 clockticks = clockticks * tmp; //ticks per second
173 mhertz = clockticks / 1000000.0;
174 mhz = (DWORD)mhertz;
175 }
176 else mhz = 500;
177 }
178 else mhz = 500;
179 RegSetValueExA(xhkey,"~Mhz",0,REG_DWORD, (LPBYTE)&mhz, sizeof(DWORD));
180 }
181#endif
182 }
183//TODO: FPU fdiv bug
184#if 0
185 if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) {
186 if (!lstrncmpiA(value,"yes",3))
187 PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
188
189 continue;
190 }
191#endif
192 features = GetCPUFeatures();
193 if (features & CPUID_CMPXCHG8B_INSTRUCTION)
194 PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
195 if (features & CPUID_MMX)
196 PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
197
198 //Create FPU key if one is present
199 if (features & CPUID_FPU_PRESENT) {
200 if (i == 0) {
201 if(RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System\\FloatingPointProcessor",&fpukey)!=ERROR_SUCCESS)
202 dprintf(("Unable to register FPU information\n"));
203 }
204 // Create a new processor subkey
205 if(fpukey) {
206 sprintf(buf,"%d",i);
207 RegCreateKeyA(fpukey,buf,&xhfpukey);
208 }
209 }
210
211 } //for each cpu
212 }
213 memcpy(si,&cachedsi,sizeof(*si));
214
215 if (xhkey)
216 RegCloseKey(xhkey);
217 if (hkey)
218 RegCloseKey(hkey);
219 if (xhfpukey)
220 RegCloseKey(xhfpukey);
221 if (fpukey)
222 RegCloseKey(fpukey);
223
224}
225
226
227/***********************************************************************
228 * IsProcessorFeaturePresent [KERNELL32.880]
229 * RETURNS:
230 * TRUE if processorfeature present
231 * FALSE otherwise
232 */
233BOOL WINAPI IsProcessorFeaturePresent (DWORD feature) /* [in] feature number, see PF_ defines */
234{
235 SYSTEM_INFO si;
236 GetSystemInfo (&si); /* To ensure the information is loaded and cached */
237
238 if (feature < 64) {
239 dprintf(("IsProcessorFeaturePresent %x -> %x", feature, PF[feature]));
240 return PF[feature];
241 }
242 else
243 return FALSE;
244}
245//******************************************************************************
246//******************************************************************************
Note: See TracBrowser for help on using the repository browser.