Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages
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 CS_PROCESSOR_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 bool HasSSE () 00071 { 00072 Initialize (); 00073 00074 return sseSupported; 00075 } 00076 00077 static inline const char* GetProcessorName () 00078 { 00079 Initialize (); 00080 00081 return processorName; 00082 } 00083 00084 private: 00085 00087 static bool isInitialized; 00088 00090 static bool mmxSupported; 00091 00093 static bool sseSupported; 00094 00096 static bool AMD3dnowSupported; 00097 00099 static char processorName[16]; 00100 00101 #if defined(CS_PROCESSOR_X86) && (CS_PROCESSOR_SIZE == 32) 00102 00106 static inline void CheckX86Processor () 00107 { 00108 int32 capFlags = 0; 00109 int CPUnum; 00110 int maxEax = 0; 00111 const char* procName = processorName; 00112 00113 bool have_cpuid; 00114 00115 #if defined(CS_COMPILER_MSVC) 00116 __asm 00117 { 00118 // save vars 00119 push eax 00120 push ebx 00121 push esi 00122 00123 //detect 386/486 00124 pushfd 00125 pop eax //get EFLAGS 00126 mov ebx, eax //save original EFLAGS 00127 xor eax, 40000h //toggle AC bit 00128 push eax //copy to stack 00129 popfd //copy to EFLAGS 00130 pushfd 00131 pop eax //get EFLAGS again 00132 xor eax, ebx //check AC bit 00133 mov CPUnum, 386 //386 00134 je end_detect //is a 386, stop detection 00135 push ebx //restore EFLAGS 00136 popfd 00137 00138 //detect 486/pentium+ 00139 pushfd //get EFLAGS 00140 pop eax 00141 mov ecx, eax 00142 xor eax, 200000h //toggle ID bit in EFLAGS 00143 push eax //save new EFLAGS value on stack 00144 popfd //replace current EFLAGS value 00145 pushfd //get new EFLAGS 00146 pop eax //store new EFLAGS in EAX 00147 xor eax, ecx //can not toggle ID bit, 00148 mov CPUnum, 486 00149 jz end_detect //processor=80486 00150 mov CPUnum, 586 //586+ 00151 00152 mov have_cpuid, 1 //we have cpuid 00153 00154 //check number of cpuid instructions 00155 mov eax, 0 00156 cpuid 00157 mov maxEax, eax //save the maximum eax for cpuid 00158 00159 //save MFT string 00160 mov esi, procName 00161 mov [esi+0], ebx 00162 mov [esi+4], edx 00163 mov [esi+8], ecx 00164 mov [esi+12], 0 00165 00166 test maxEax, 1 00167 jz end_detect 00168 00169 //get flagstring 00170 mov eax, 1 00171 cpuid 00172 mov capFlags, edx 00173 00174 end_detect: 00175 00176 pop esi 00177 pop ebx 00178 pop eax 00179 } 00180 #elif defined(CS_COMPILER_GCC) 00181 __asm__( 00182 //detect 386/486 00183 " pushfl \n" 00184 " popl %%eax \n" //get EFLAGS 00185 " movl %%eax, %%ebx \n" //save original EFLAGS 00186 " xorl $0x40000, %%eax \n" //toggle AC bit 00187 " pushl %%eax \n" //copy to stack 00188 " popfl \n" //copy to EFLAGS 00189 " pushfl \n" 00190 " popl %%eax \n" //get EFLAGS again 00191 " xorl %%ebx, %%eax \n" //check AC bit 00192 " movl $386,%0 \n" //386 00193 " je 1f \n" //is a 386, stop detection 00194 " pushl %%ebx \n" //restore EFLAGS 00195 " popfl \n" 00196 //detect 486/pentium+ 00197 " pushfl \n" //get EFLAGS 00198 " popl %%eax \n" 00199 " movl %%eax, %%ecx \n" 00200 " xorl $0x200000,%%eax \n" //toggle ID bit in EFLAGS 00201 " pushl %%eax \n" //save new EFLAGS value on stack 00202 " popfl \n" //replace current EFLAGS value 00203 " pushfl \n" //get new EFLAGS 00204 " popl %%eax \n" //store new EFLAGS in EAX 00205 " xorl %%eax, %%ecx \n" //can not toggle ID bit, 00206 " movl $486,%0 \n" 00207 " jz 1f \n" //processor=80486 00208 " movl $586,%0 \n" //586+ 00209 " movl $1,%1 \n" //we have cpuid 00210 //check number of cpuid instructions 00211 " xorl %%eax,%%eax \n" // thebolt: this was a movl $0,%eax 00212 " cpuid \n" 00213 " movl %%eax,%2 \n" //save the maximum eax for cpuid 00214 //save MFT string 00215 " movl %4,%%esi \n" 00216 " movl %%ebx,0(%%esi) \n" 00217 " movl %%edx,4(%%esi) \n" 00218 " movl %%ecx,8(%%esi) \n" 00219 " movl $0,12(%%esi) \n" 00220 " testl $1,%2 \n" 00221 " jz 1f \n" 00222 //get flagstring 00223 " movl $1,%%eax \n" 00224 " cpuid \n" 00225 " movl %%edx,%3 \n" 00226 "1: \n" 00227 : "=g" (CPUnum), "=g" (have_cpuid), "=g" (maxEax), "=g" (capFlags) 00228 : "g" (procName), "2" (maxEax) 00229 : "eax", "ebx", "ecx", "edx", "esi"); 00230 00231 #endif //CS_COMPILER_MSVC/GCC 00232 mmxSupported = capFlags & (1<<23); 00233 sseSupported = capFlags & (1<<25); 00234 //AMD3dnowSupported = capFlags & (1<<31); 00235 } 00236 #else //CS_PROCESSOR_X86 00237 static inline void CheckX86Processor() {} 00238 #endif //CS_PROCESSOR_X86 00239 }; 00240 00241 #endif //__CS_PROCESSORCAP_H__
Generated for Crystal Space by doxygen 1.3.9.1