~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Open Mash Cross Reference
mash/misc/cpuinfo.cc

Component: ~ [ mash ] ~ [ apps ] ~ [ gsm ] ~ [ lib ] ~ [ otcl ] ~ [ srm ] ~ [ tcl8.3 ] ~ [ tclcl ] ~ [ tk8.3 ] ~ [ tutorials ] ~

  1 /*
  2  * cpuinfo.cc --
  3  *
  4  *      Provides information about the processor
  5  *
  6  * Copyright (c) 2001 The Regents of the University of California.
  7  * All rights reserved.
  8  *
  9  * Redistribution and use in source and binary forms, with or without
 10  * modification, are permitted provided that the following conditions are met:
 11  *
 12  * A. Redistributions of source code must retain the above copyright notice,
 13  *    this list of conditions and the following disclaimer.
 14  * B. Redistributions in binary form must reproduce the above copyright notice,
 15  *    this list of conditions and the following disclaimer in the documentation
 16  *    and/or other materials provided with the distribution.
 17  * C. Neither the names of the copyright holders nor the names of its
 18  *    contributors may be used to endorse or promote products derived from this
 19  *    software without specific prior written permission.
 20  *
 21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
 22  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 23  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 31  * POSSIBILITY OF SUCH DAMAGE.
 32  *
 33  *  $Header: /usr/mash/src/repository/mash/mash-1/misc/cpuinfo.cc,v 1.5 2004/05/12 21:44:18 aswan Exp $
 34  */
 35 
 36 #include <iostream>
 37 using namespace std;
 38 
 39 #include "cpuinfo.h"
 40 #ifdef WIN32
 41 #include<excpt.h>
 42 #endif
 43 
 44 // #define ALLOW_UNIX_EXCEPTIONS
 45 
 46 bool supportsMMX()// returns true if MMX supported, false otherwise
 47 {
 48     unsigned int a=CpuInfo::get();
 49     return ((a&FLAG_MMX)?true:false);
 50 }
 51 
 52 bool supportsSIMD() // returns true if SIMD can be used (hardware&OS), false otherwise
 53 {
 54     unsigned int a=CpuInfo::get();
 55     return (((a&FLAG_SIMD)&&(a&FLAG_SIMD_OS))?true:false);
 56 }
 57 
 58 #ifdef TEST_EXECUTE
 59 int textexec();
 60 #endif
 61 
 62 CpuInfo cpuinfo();
 63 bool CpuInfo::configured=false;
 64 unsigned int CpuInfo::flags=0;
 65 
 66 void getCpuInfo(unsigned int&);
 67 
 68 CpuInfo::CpuInfo() { //: TclClass( (const char *)"CpuInfo") {
 69     name("CpuInfo");
 70     if(!configured) {
 71         getCpuInfo(flags);      
 72         configured=true;
 73 #ifdef TEST_EXECUTE 
 74         textexec();
 75 #endif
 76     }
 77 }
 78 
 79 unsigned int CpuInfo::get() { 
 80     if(configured) {
 81         return flags;
 82     }
 83     else {
 84                 getCpuInfo(flags);      
 85                 configured=true;
 86 #ifdef TEST_EXECUTE 
 87                 textexec();
 88 #endif
 89                 return flags;
 90         }
 91 }
 92 
 93 int CpuInfo::command(int argc, const char*const* argv)
 94 {
 95     if (argc == 2) {
 96         Tcl& tcl = Tcl::instance();
 97         char* cp = tcl.buffer();
 98         if (strcmp(argv[1], "mmx") == 0 ) {
 99             if( (flags&FLAG_MMX) ) {
100                 strcpy(cp, "true");
101             }
102             else {
103                 strcpy(cp, "false");
104             }
105         }
106         else if( strcmp(argv[1], "simd") == 0 ) {
107             if( ((flags&FLAG_SIMD)&&(flags&FLAG_SIMD_OS)) ) {
108                 strcpy(cp, "true");
109             }
110             else {
111                 strcpy(cp, "false");
112             }               
113         }
114         else if( strcmp(argv[1], "processor") == 0 ) {
115             if( flags&FLAG_INTEL ) {
116                 strcpy(cp, "intel");
117             }
118             else {
119                 strcpy(cp, "non-intel");
120             }
121         }
122         else return (TclObject::command(argc, argv));
123         tcl.result(cp);
124         return (TCL_OK);
125     }
126     else return (TclObject::command(argc, argv));
127 }
128 
129 #ifdef X86_ASSEMBLER
130 // this function can only really detect 486 and later processors
131 void getCpuInfo(unsigned int&flags) 
132 {
133     flags=0;
134     int a=-1;
135     int line1=-1;
136     int line2=-1;
137     int line3=-1;
138 #ifdef WIN32
139     _try {
140         __asm {
141             mov eax, 0
142             cpuid
143             mov [a], eax
144             mov [line1], ebx
145             mov [line2], ecx
146             mov [line3], edx
147         }
148     }
149     _except( EXCEPTION_EXECUTE_HANDLER ) {
150         cout << "exception cpuid code is " << _exception_code() << endl;
151         return;
152     }
153 #else
154 
155 #ifdef ALLOW_UNIX_EXCEPTIONS
156     try {
157 #endif
158         a=0;
159         __asm__ __volatile__(
160             "cpuid"
161             : "=a" (a), "=b" (line1), "=c" (line2), "=d" (line3)
162             : "a" (a) );
163 #ifdef ALLOW_UNIX_EXCEPTIONS
164     }
165     catch( ... ) { // exception e // cout << e.what() << endl;
166         cout << "caught cpuid exception" << endl;
167         return;
168     }
169 #endif
170 
171 #endif
172 
173     // "GenuineIntel" ==> 0x47656e75696e65496e74656c
174     if(line1!=0x756e6547 || line2!=0x6c65746e || line3!=0x49656e69) {
175         return;
176     }
177     flags|=FLAG_INTEL; // received intel chip
178     
179     if(a<1) {
180         return;         // can't check family or MMX bit
181     }
182     
183 #ifdef WIN32
184     __asm {
185         mov eax, 1
186         cpuid
187         mov [a], eax    // processor type, family, model, stepping [res,type,fam,mod,stepping]
188         mov [line1], edx // feature flags (intel table 5)
189     }
190 #else
191     a=1;
192         __asm__ __volatile__(
193             "cpuid"
194             : "=a" (a), "=d" (line1)
195             : "a" (a) );
196 #endif
197     // highest 18 bits undefined and reserved
198     // processor type is bits 12-13
199     // family is 8-11
200     // model 4-7
201     // stepping 0-3
202     if( /*family*/ ((a>>8)&0xf)==4 /*0100*/ ) {
203         int model=((a>>4)&0xf);
204         switch(model) {
205         case 0: case 1: // 486DX
206         case 2: // 486SX 
207         case 3: // 487, 486DX2
208         case 4: // 486SL
209         case 5: // 486SX2
210         case 7: // 486DX2 write-back enhanced
211         case 8: // 486DX4
212         default: // unknown
213             flags|=FLAG_I486; 
214             break;
215         }
216     }
217     else if( /*family*/ ((a>>8)&0xf)==5 /*0101*/ ) {
218         int model=((a>>4)&0xf);
219         switch(model) {
220         case 1: // Pentium 60,66Mhz (may be overdrive 60,66)
221         case 2: // Pentium 75-200Mhz (may be overdrive 75-133)
222         case 3: // Pentium Overdrive for 486-based systems
223         case 4: // Pentium with MMX (166,200Mhz) (may be overdrive 75-133)
224         default: // unknown
225             flags|=FLAG_I586; 
226             break;
227         }
228     }
229     else if( /*family*/ ((a>>8)&0xf)==6 /*0110*/) {
230         int model=((a>>4)&0xf);
231         switch(model) {
232         case 1: // Pentium Pro
233         case 3: // Pentium II model 3 (or Pentium Pro overdrive)
234         case 5: // Pentium II model 5 or Celeron
235         default:
236             flags|=FLAG_I686; 
237             break;
238         }
239     }
240     else {
241         // unknown intel family
242         if( ((a>>8)&0xf)>6 ) { // assuming newer families have 686 capabilities
243             flags|=FLAG_I686; 
244         }
245     }
246     if( (line1>>23)&0x1 ) { // bit 23 is mmx
247         flags|=FLAG_MMX;
248     }
249     if( (line1>>25)&0x1 ) { // bit 25 is simd
250         flags|=FLAG_SIMD;
251 #ifndef OLD_ASM
252         // if assembler supports simd instructions, then try executing an operation
253 #ifdef WIN32
254         _try {
255                 __asm xorps xmm0, xmm0; Streaming SIMD Extension
256         }
257         _except( EXCEPTION_EXECUTE_HANDLER ) {
258             cout << "simd exception code is " << _exception_code() << endl;
259             return;
260         }
261 #else
262         // using 'a' just to keep the compiler happy
263 #ifdef ALLOW_UNIX_EXCEPTIONS
264         try {
265 #endif
266             __asm__ __volatile__(
267                 "xorps %%xmm0, %%xmm0"
268                 : "=a" (a)
269                 : "a" (a) );
270 #ifdef ALLOW_UNIX_EXCEPTIONS
271         }
272         catch(...) {
273             cout << "caught xorps exception" << endl;
274             return;
275         }
276 #endif
277 #endif
278         flags|=FLAG_SIMD_OS;
279 #endif
280     }
281 }
282 #else
283 void getCpuInfo(unsigned int&flags) 
284 {
285     flags=0;
286 }
287 #endif
288 
289 #if defined(TEST_MAIN) || defined(TEST_EXECUTE)
290 
291 #ifdef TEST_MAIN
292 int main(int argc, char*argv[])
293 #else
294 int textexec()
295 #endif
296 {
297     unsigned int a=CpuInfo::get();
298     cout << ((a&FLAG_INTEL)?"intel chip":"non-intel chip") << endl;
299     cout << (((a&FLAG_FAMILY_MASK)==FLAG_I086)?"086 chip":"non-086 chip") << endl;
300     cout << (((a&FLAG_FAMILY_MASK)==FLAG_I286)?"286 chip":"non-286 chip") << endl;
301     cout << (((a&FLAG_FAMILY_MASK)==FLAG_I386)?"386 chip":"non-386 chip") << endl;
302     cout << (((a&FLAG_FAMILY_MASK)==FLAG_I486)?"486 chip":"non-486 chip") << endl;
303     cout << (((a&FLAG_FAMILY_MASK)==FLAG_I586)?"586 chip":"non-586 chip") << endl;
304     cout << (((a&FLAG_FAMILY_MASK)==FLAG_I686)?"686 chip":"non-686 chip") << endl;
305     cout << ((a&FLAG_MMX)?"MMX chip":"non-MMX chip") << endl;
306     cout << ((a&FLAG_SIMD)?"SIMD chip":"non-SIMD chip") << endl;
307     cout << ((a&FLAG_SIMD_OS)?"SIMD OS":"non-SIMD OS") << endl;
308 
309     cout << "MMX supported=" << supportsMMX() << endl;
310     cout << "SIMD supported=" << supportsSIMD() << endl;
311     return 0;
312 }
313 #endif
314 
315 CpuInfoClass cic;
316 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.