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 &lt;tomas@famolsen.dk&gt;
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 }