Mercurial > projects > ldc
comparison druntime/src/compiler/dmd/util/cpuid.d @ 759:d3eb054172f9
Added copy of druntime from DMD 2.020 modified for LDC.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 11 Nov 2008 01:52:37 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
758:f04dde6e882c | 759:d3eb054172f9 |
---|---|
1 /** | |
2 * Identify the characteristics of the host CPU. | |
3 * | |
4 * Implemented according to: | |
5 | |
6 - AP-485 Intel(C) Processor Identification and the CPUID Instruction | |
7 $(LINK http://www.intel.com/design/xeon/applnots/241618.htm) | |
8 | |
9 - Intel(R) 64 and IA-32 Architectures Software Developer's Manual, Volume 2A: Instruction Set Reference, A-M | |
10 $(LINK http://developer.intel.com/design/pentium4/manuals/index_new.htm) | |
11 | |
12 - AMD CPUID Specification Publication # 25481 | |
13 $(LINK http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf) | |
14 | |
15 Example: | |
16 --- | |
17 import std.cpuid; | |
18 import std.stdio; | |
19 | |
20 void main() | |
21 { | |
22 writefln(std.cpuid.toString()); | |
23 } | |
24 --- | |
25 | |
26 AUTHORS: Tomas Lindquist Olsen <tomas@famolsen.dk> | |
27 (slightly altered by Walter Bright) | |
28 COPYRIGHT: Public Domain | |
29 | |
30 * BUGS: Only works on x86 CPUs | |
31 * | |
32 * Macros: | |
33 * WIKI = Phobos/StdCpuid | |
34 * COPYRIGHT = Public Domain | |
35 */ | |
36 | |
37 /* | |
38 * Modified by Sean Kelly for use with the D Runtime Project | |
39 */ | |
40 | |
41 module rt.util.cpuid; | |
42 | |
43 private import stdc.string; | |
44 | |
45 version(D_InlineAsm_X86) | |
46 { | |
47 /// Returns vendor string | |
48 char[] vendor() {return vendorStr;} | |
49 /// Returns processor string | |
50 string processor() {return processorStr;} | |
51 | |
52 /// Is MMX supported? | |
53 bool mmx() {return (flags&MMX_BIT)!=0;} | |
54 /// Is FXSR supported? | |
55 bool fxsr() {return (flags&FXSR_BIT)!=0;} | |
56 /// Is SSE supported? | |
57 bool sse() {return (flags&SSE_BIT)!=0;} | |
58 /// Is SSE2 supported? | |
59 bool sse2() {return (flags&SSE2_BIT)!=0;} | |
60 /// Is SSE3 supported? | |
61 bool sse3() {return (misc&SSE3_BIT)!=0;} | |
62 /// Is SSSE3 supported? | |
63 bool ssse3() {return (misc&SSSE3_BIT)!=0;} | |
64 | |
65 /// Is AMD 3DNOW supported? | |
66 bool amd3dnow() {return (exflags&AMD_3DNOW_BIT)!=0;} | |
67 /// Is AMD 3DNOW Ext supported? | |
68 bool amd3dnowExt() {return (exflags&AMD_3DNOW_EXT_BIT)!=0;} | |
69 /// Is AMD MMX supported? | |
70 bool amdMmx() {return (exflags&AMD_MMX_BIT)!=0;} | |
71 | |
72 /// Is this an Intel Architecture IA64? | |
73 bool ia64() {return (flags&IA64_BIT)!=0;} | |
74 /// Is this an AMD 64? | |
75 bool amd64() {return (exflags&AMD64_BIT)!=0;} | |
76 | |
77 /// Is hyperthreading supported? | |
78 bool hyperThreading() {return (flags&HTT_BIT)!=0;} | |
79 /// Returns number of threads per CPU | |
80 uint threadsPerCPU() {return maxThreads;} | |
81 /// Returns number of cores in CPU | |
82 uint coresPerCPU() {return maxCores;} | |
83 | |
84 /// Is this an Intel processor? | |
85 bool intel() {return manufac==INTEL;} | |
86 /// Is this an AMD processor? | |
87 bool amd() {return manufac==AMD;} | |
88 | |
89 /// Returns stepping | |
90 uint stepping() {return _stepping;} | |
91 /// Returns model | |
92 uint model() {return _model;} | |
93 /// Returns family | |
94 uint family() {return _family;} | |
95 //uint processorType() {return (signature>>>12)&0x3;} | |
96 | |
97 static this() | |
98 { | |
99 getVendorString(); | |
100 getProcessorString(); | |
101 getFeatureFlags(); | |
102 | |
103 // stepping / family / model | |
104 _stepping = signature&0xF; | |
105 uint fbase = (signature>>>8)&0xF; | |
106 uint fex = (signature>>>20)&0xFF; | |
107 uint mbase = (signature>>>4)&0xF; | |
108 uint mex = (signature>>>16)&0xF; | |
109 | |
110 // vendor specific | |
111 void function() threadFn; | |
112 switch(vendorStr) | |
113 { | |
114 case "GenuineIntel": | |
115 manufac = INTEL; | |
116 threadFn = &getThreadingIntel; | |
117 if (fbase == 0xF) | |
118 _family = fbase+fex; | |
119 else | |
120 _family = fbase; | |
121 if (_family == 0x6 || _family == 0xF) | |
122 _model = mbase+(mex<<4); | |
123 else | |
124 _model = mbase; | |
125 break; | |
126 | |
127 case "AuthenticAMD": | |
128 manufac = AMD; | |
129 threadFn = &getThreadingAMD; | |
130 if (fbase < 0xF) | |
131 { | |
132 _family = fbase; | |
133 _model = mbase; | |
134 } | |
135 else | |
136 { | |
137 _family = fbase+fex; | |
138 _model = mbase+(mex<<4); | |
139 } | |
140 break; | |
141 | |
142 default: | |
143 manufac = OTHER; | |
144 } | |
145 | |
146 // threading details | |
147 if (hyperThreading && threadFn !is null) | |
148 { | |
149 threadFn(); | |
150 } | |
151 } | |
152 | |
153 private: | |
154 // feature flags | |
155 enum : uint | |
156 { | |
157 MMX_BIT = 1<<23, | |
158 FXSR_BIT = 1<<24, | |
159 SSE_BIT = 1<<25, | |
160 SSE2_BIT = 1<<26, | |
161 HTT_BIT = 1<<28, | |
162 IA64_BIT = 1<<30 | |
163 } | |
164 // feature flags misc | |
165 enum : uint | |
166 { | |
167 SSE3_BIT = 1, | |
168 SSSE3_BIT = 1<<9 | |
169 } | |
170 // extended feature flags | |
171 enum : uint | |
172 { | |
173 AMD_MMX_BIT = 1<<22, | |
174 AMD64_BIT = 1<<29, | |
175 AMD_3DNOW_EXT_BIT = 1<<30, | |
176 AMD_3DNOW_BIT = 1<<31 | |
177 } | |
178 // manufacturer | |
179 enum | |
180 { | |
181 OTHER, | |
182 INTEL, | |
183 AMD | |
184 } | |
185 | |
186 uint flags, misc, exflags, apic, signature; | |
187 uint _stepping, _model, _family; | |
188 | |
189 char[12] vendorStr = 0; | |
190 string processorStr = ""; | |
191 | |
192 uint maxThreads=1; | |
193 uint maxCores=1; | |
194 uint manufac=OTHER; | |
195 | |
196 /* ** | |
197 * fetches the cpu vendor string | |
198 */ | |
199 private void getVendorString() | |
200 { | |
201 char* dst = vendorStr.ptr; | |
202 // puts the vendor string into dst | |
203 asm | |
204 { | |
205 mov EAX, 0 ; | |
206 cpuid ; | |
207 mov EAX, dst ; | |
208 mov [EAX], EBX ; | |
209 mov [EAX+4], EDX ; | |
210 mov [EAX+8], ECX ; | |
211 } | |
212 } | |
213 | |
214 private void getProcessorString() | |
215 { | |
216 char[48] buffer; | |
217 char* dst = buffer.ptr; | |
218 // puts the processor string into dst | |
219 asm | |
220 { | |
221 mov EAX, 0x8000_0000 ; | |
222 cpuid ; | |
223 cmp EAX, 0x8000_0004 ; | |
224 jb PSLabel ; // no support | |
225 push EDI ; | |
226 mov EDI, dst ; | |
227 mov EAX, 0x8000_0002 ; | |
228 cpuid ; | |
229 mov [EDI], EAX ; | |
230 mov [EDI+4], EBX ; | |
231 mov [EDI+8], ECX ; | |
232 mov [EDI+12], EDX ; | |
233 mov EAX, 0x8000_0003 ; | |
234 cpuid ; | |
235 mov [EDI+16], EAX ; | |
236 mov [EDI+20], EBX ; | |
237 mov [EDI+24], ECX ; | |
238 mov [EDI+28], EDX ; | |
239 mov EAX, 0x8000_0004 ; | |
240 cpuid ; | |
241 mov [EDI+32], EAX ; | |
242 mov [EDI+36], EBX ; | |
243 mov [EDI+40], ECX ; | |
244 mov [EDI+44], EDX ; | |
245 pop EDI ; | |
246 PSLabel: ; | |
247 } | |
248 | |
249 if (buffer[0] == char.init) // no support | |
250 return; | |
251 | |
252 // seems many intel processors prepend whitespace | |
253 processorStr = cast(string)strip(toString(dst)).dup; | |
254 } | |
255 | |
256 private void getFeatureFlags() | |
257 { | |
258 uint f,m,e,a,s; | |
259 asm | |
260 { | |
261 mov EAX, 0 ; | |
262 cpuid ; | |
263 cmp EAX, 1 ; | |
264 jb FeatLabel ; // no support | |
265 mov EAX, 1 ; | |
266 cpuid ; | |
267 mov f, EDX ; | |
268 mov m, ECX ; | |
269 mov a, EBX ; | |
270 mov s, EAX ; | |
271 | |
272 FeatLabel: ; | |
273 mov EAX, 0x8000_0000 ; | |
274 cpuid ; | |
275 cmp EAX, 0x8000_0001 ; | |
276 jb FeatLabel2 ; // no support | |
277 mov EAX, 0x8000_0001 ; | |
278 cpuid ; | |
279 mov e, EDX ; | |
280 | |
281 FeatLabel2: | |
282 ; | |
283 } | |
284 flags = f; | |
285 misc = m; | |
286 exflags = e; | |
287 apic = a; | |
288 signature = s; | |
289 } | |
290 | |
291 private void getThreadingIntel() | |
292 { | |
293 uint n; | |
294 ubyte b = 0; | |
295 asm | |
296 { | |
297 mov EAX, 0 ; | |
298 cpuid ; | |
299 cmp EAX, 4 ; | |
300 jb IntelSingle ; | |
301 mov EAX, 4 ; | |
302 mov ECX, 0 ; | |
303 cpuid ; | |
304 mov n, EAX ; | |
305 mov b, 1 ; | |
306 IntelSingle: ; | |
307 } | |
308 if (b != 0) | |
309 { | |
310 maxCores = ((n>>>26)&0x3F)+1; | |
311 maxThreads = (apic>>>16)&0xFF; | |
312 } | |
313 else | |
314 { | |
315 maxCores = maxThreads = 1; | |
316 } | |
317 } | |
318 | |
319 private void getThreadingAMD() | |
320 { | |
321 ubyte n; | |
322 ubyte b = 0; | |
323 asm | |
324 { | |
325 mov EAX, 0x8000_0000 ; | |
326 cpuid ; | |
327 cmp EAX, 0x8000_0008 ; | |
328 jb AMDSingle ; | |
329 mov EAX, 0x8000_0008 ; | |
330 cpuid ; | |
331 mov n, CL ; | |
332 mov b, 1 ; | |
333 AMDSingle: ; | |
334 } | |
335 if (b != 0) | |
336 { | |
337 maxCores = n+1; | |
338 maxThreads = (apic>>>16)&0xFF; | |
339 } | |
340 else | |
341 { | |
342 maxCores = maxThreads = 1; | |
343 } | |
344 } | |
345 | |
346 /*************************************************************************** | |
347 * Support code for above, from std.string and std.ctype | |
348 ***************************************************************************/ | |
349 | |
350 private | |
351 { | |
352 enum | |
353 { | |
354 _SPC = 8, | |
355 _CTL = 0x20, | |
356 _BLK = 0x40, | |
357 _HEX = 0x80, | |
358 _UC = 1, | |
359 _LC = 2, | |
360 _PNC = 0x10, | |
361 _DIG = 4, | |
362 _ALP = _UC|_LC, | |
363 } | |
364 | |
365 ubyte _ctype[128] = | |
366 [ | |
367 _CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL, | |
368 _CTL,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL,_CTL, | |
369 _CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL, | |
370 _CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL, | |
371 _SPC|_BLK,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC, | |
372 _PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC, | |
373 _DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX, | |
374 _DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX, | |
375 _PNC,_PNC,_PNC,_PNC,_PNC,_PNC, | |
376 _PNC,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC, | |
377 _UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC, | |
378 _UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC, | |
379 _UC,_UC,_UC,_PNC,_PNC,_PNC,_PNC,_PNC, | |
380 _PNC,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC, | |
381 _LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC, | |
382 _LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC, | |
383 _LC,_LC,_LC,_PNC,_PNC,_PNC,_PNC,_CTL | |
384 ]; | |
385 | |
386 /** | |
387 * Returns !=0 if c is a space, tab, vertical tab, form feed, | |
388 * carriage return, or linefeed. | |
389 */ | |
390 int isspace(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_SPC) : 0; } | |
391 | |
392 /***************************************** | |
393 * Strips leading or trailing whitespace, or both. | |
394 */ | |
395 char[] stripl(char[] s) | |
396 { | |
397 uint i; | |
398 | |
399 for (i = 0; i < s.length; i++) | |
400 { | |
401 if (!isspace(s[i])) | |
402 break; | |
403 } | |
404 return s[i .. s.length]; | |
405 } | |
406 | |
407 char[] stripr(char[] s) /// ditto | |
408 { | |
409 uint i; | |
410 | |
411 for (i = s.length; i > 0; i--) | |
412 { | |
413 if (!isspace(s[i - 1])) | |
414 break; | |
415 } | |
416 return s[0 .. i]; | |
417 } | |
418 | |
419 char[] strip(char[] s) /// ditto | |
420 { | |
421 return stripr(stripl(s)); | |
422 } | |
423 | |
424 char[] toString(char* s) | |
425 { | |
426 return s ? s[0 .. strlen(s)] : null; | |
427 } | |
428 | |
429 string toString(invariant(char)* s) | |
430 { | |
431 return s ? s[0 .. strlen(s)] : null; | |
432 } | |
433 } | |
434 } | |
435 else | |
436 { | |
437 char[] vendor() {return "unknown vendor"; } | |
438 char[] processor() {return "unknown processor"; } | |
439 | |
440 bool mmx() {return false; } | |
441 bool fxsr() {return false; } | |
442 bool sse() {return false; } | |
443 bool sse2() {return false; } | |
444 bool sse3() {return false; } | |
445 bool ssse3() {return false; } | |
446 | |
447 bool amd3dnow() {return false; } | |
448 bool amd3dnowExt() {return false; } | |
449 bool amdMmx() {return false; } | |
450 | |
451 bool ia64() {return false; } | |
452 bool amd64() {return false; } | |
453 | |
454 bool hyperThreading() {return false; } | |
455 uint threadsPerCPU() {return 0; } | |
456 uint coresPerCPU() {return 0; } | |
457 | |
458 bool intel() {return false; } | |
459 bool amd() {return false; } | |
460 | |
461 uint stepping() {return 0; } | |
462 uint model() {return 0; } | |
463 uint family() {return 0; } | |
464 } |