csutil/csprocessorcap.h
00001 /* 00002 Copyright (C) 2002 by Marten Svanfeldt 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public 00015 License along with this library; if not, write to the Free 00016 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 */ 00018 00019 #ifndef __CS_PROCESSORCAP_H__ 00020 #define __CS_PROCESSORCAP_H__ 00021 00022 #include "csextern.h" 00023 00028 class CS_CSUTIL_EXPORT csProcessorCapability 00029 { 00030 public: 00031 00035 csProcessorCapability () 00036 { 00037 } 00038 00042 ~csProcessorCapability () 00043 { 00044 } 00045 00049 static inline void Initialize () 00050 { 00051 if (isInitialized) 00052 return; 00053 00054 #ifdef PROC_X86 00055 CheckX86Processor (); 00056 #else 00057 mmxSupported = false; 00058 sseSupported = false; 00059 processorName[0] = 0; 00060 #endif 00061 } 00062 00063 static inline bool HasMMX () 00064 { 00065 Initialize (); 00066 00067 return mmxSupported; 00068 } 00069 00070 static inline const char* GetProcessorName () 00071 { 00072 Initialize (); 00073 00074 return processorName; 00075 } 00076 00077 private: 00078 00080 static bool isInitialized; 00081 00083 static bool mmxSupported; 00084 00086 static bool sseSupported; 00087 00089 static bool AMD3dnowSupported; 00090 00092 static char processorName[16]; 00093 00094 #ifdef PROC_X86 00095 00099 static inline void CheckX86Processor () 00100 { 00101 int32 capFlags = 0; 00102 int CPUnum; 00103 int maxEax = 0; 00104 const char* procName = processorName; 00105 00106 bool have_cpuid; 00107 00108 #if defined(COMP_VC) 00109 __asm 00110 { 00111 // save vars 00112 push eax 00113 push ebx 00114 push esi 00115 00116 //detect 386/486 00117 pushfd 00118 pop eax //get EFLAGS 00119 mov ebx, eax //save original EFLAGS 00120 xor eax, 40000h //toggle AC bit 00121 push eax //copy to stack 00122 popfd //copy to EFLAGS 00123 pushfd 00124 pop eax //get EFLAGS again 00125 xor eax, ebx //check AC bit 00126 mov CPUnum, 386 //386 00127 je end_detect //is a 386, stop detection 00128 push ebx //restore EFLAGS 00129 popfd 00130 00131 //detect 486/pentium+ 00132 pushfd //get EFLAGS 00133 pop eax 00134 mov ecx, eax 00135 xor eax, 200000h //toggle ID bit in EFLAGS 00136 push eax //save new EFLAGS value on stack 00137 popfd //replace current EFLAGS value 00138 pushfd //get new EFLAGS 00139 pop eax //store new EFLAGS in EAX 00140 xor eax, ecx //can not toggle ID bit, 00141 mov CPUnum, 486 00142 jz end_detect //processor=80486 00143 mov CPUnum, 586 //586+ 00144 00145 mov have_cpuid, 1 //we have cpuid 00146 00147 //check number of cpuid instructions 00148 mov eax, 0 00149 cpuid 00150 mov maxEax, eax //save the maximum eax for cpuid 00151 00152 //save MFT string 00153 mov esi, procName 00154 mov [esi+0], ebx 00155 mov [esi+4], edx 00156 mov [esi+8], ecx 00157 mov [esi+12], 0 00158 00159 test maxEax, 1 00160 jz end_detect 00161 00162 //get flagstring 00163 mov eax, 1 00164 cpuid 00165 mov capFlags, edx 00166 00167 end_detect: 00168 00169 pop esi 00170 pop ebx 00171 pop eax 00172 } 00173 #elif defined(COMP_GCC) 00174 __asm__( 00175 //detect 386/486 00176 " pushfl \n" 00177 " popl %%eax \n" //get EFLAGS 00178 " movl %%eax, %%ebx \n" //save original EFLAGS 00179 " xorl $0x40000, %%eax \n" //toggle AC bit 00180 " pushl %%eax \n" //copy to stack 00181 " popfl \n" //copy to EFLAGS 00182 " pushfl \n" 00183 " popl %%eax \n" //get EFLAGS again 00184 " xorl %%ebx, %%eax \n" //check AC bit 00185 " movl $386,%0 \n" //386 00186 " je 1f \n" //is a 386, stop detection 00187 " pushl %%ebx \n" //restore EFLAGS 00188 " popfl \n" 00189 //detect 486/pentium+ 00190 " pushfl \n" //get EFLAGS 00191 " popl %%eax \n" 00192 " movl %%eax, %%ecx \n" 00193 " xorl $0x200000,%%eax \n" //toggle ID bit in EFLAGS 00194 " pushl %%eax \n" //save new EFLAGS value on stack 00195 " popfl \n" //replace current EFLAGS value 00196 " pushfl \n" //get new EFLAGS 00197 " popl %%eax \n" //store new EFLAGS in EAX 00198 " xorl %%eax, %%ecx \n" //can not toggle ID bit, 00199 " movl $486,%0 \n" 00200 " jz 1f \n" //processor=80486 00201 " movl $586,%0 \n" //586+ 00202 " movl $1,%1 \n" //we have cpuid 00203 //check number of cpuid instructions 00204 " xorl %%eax,%%eax \n" // thebolt: this was a movl $0,%eax 00205 " cpuid \n" 00206 " movl %%eax,%2 \n" //save the maximum eax for cpuid 00207 //save MFT string 00208 " movl %4,%%esi \n" 00209 " movl %%ebx,0(%%esi) \n" 00210 " movl %%edx,4(%%esi) \n" 00211 " movl %%ecx,8(%%esi) \n" 00212 " movl $0,12(%%esi) \n" 00213 " testl $1,%2 \n" 00214 " jz 1f \n" 00215 //get flagstring 00216 " movl $1,%%eax \n" 00217 " cpuid \n" 00218 " movl %%edx,%3 \n" 00219 "1: \n" 00220 : "=g" (CPUnum), "=g" (have_cpuid), "=g" (maxEax), "=g" (capFlags) 00221 : "g" (procName), "2" (maxEax) 00222 : "eax", "ebx", "ecx", "edx", "esi"); 00223 00224 #endif //COMP_ 00225 mmxSupported = capFlags & (1<<23); 00226 sseSupported = capFlags & (1<<25); 00227 //AMD3dnowSupported = capFlags & (1<<31); 00228 } 00229 #else //PROC_X86 00230 void csProcessorCapability::CheckX86Processor () {} 00231 #endif //PROC_X86 00232 00233 }; 00234 00235 #endif //__CS_PROCESSORCAP_H__
Generated for Crystal Space by doxygen 1.2.18