csutil/csprocessorcap.h
Go to the documentation of this file.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 00026 #include "csextern.h" 00027 00032 class CS_CRYSTALSPACE_EXPORT csProcessorCapability 00033 { 00034 public: 00035 00039 csProcessorCapability () 00040 { 00041 } 00042 00046 ~csProcessorCapability () 00047 { 00048 } 00049 00053 static inline void Initialize () 00054 { 00055 if (isInitialized) 00056 return; 00057 00058 #ifdef CS_PROCESSOR_X86 00059 CheckX86Processor (); 00060 #else 00061 mmxSupported = false; 00062 sseSupported = false; 00063 processorName[0] = 0; 00064 #endif 00065 } 00066 00067 static inline bool HasMMX () 00068 { 00069 Initialize (); 00070 00071 return mmxSupported; 00072 } 00073 00074 static inline bool HasSSE () 00075 { 00076 Initialize (); 00077 00078 return sseSupported; 00079 } 00080 00081 static inline const char* GetProcessorName () 00082 { 00083 Initialize (); 00084 00085 return processorName; 00086 } 00087 00088 private: 00089 00091 static bool isInitialized; 00092 00094 static bool mmxSupported; 00095 00097 static bool sseSupported; 00098 00100 static bool AMD3dnowSupported; 00101 00103 static char processorName[16]; 00104 00105 #if defined(CS_PROCESSOR_X86) && (CS_PROCESSOR_SIZE == 32) 00106 00110 static inline void CheckX86Processor () 00111 { 00112 int32 capFlags = 0; 00113 int CPUnum; 00114 int maxEax = 0; 00115 const char* procName = processorName; 00116 00117 bool have_cpuid; 00118 00119 #if defined(CS_COMPILER_MSVC) 00120 __asm 00121 { 00122 // save vars 00123 push eax 00124 push ebx 00125 push esi 00126 00127 //detect 386/486 00128 pushfd 00129 pop eax //get EFLAGS 00130 mov ebx, eax //save original EFLAGS 00131 xor eax, 40000h //toggle AC bit 00132 push eax //copy to stack 00133 popfd //copy to EFLAGS 00134 pushfd 00135 pop eax //get EFLAGS again 00136 xor eax, ebx //check AC bit 00137 mov CPUnum, 386 //386 00138 je end_detect //is a 386, stop detection 00139 push ebx //restore EFLAGS 00140 popfd 00141 00142 //detect 486/pentium+ 00143 pushfd //get EFLAGS 00144 pop eax 00145 mov ecx, eax 00146 xor eax, 200000h //toggle ID bit in EFLAGS 00147 push eax //save new EFLAGS value on stack 00148 popfd //replace current EFLAGS value 00149 pushfd //get new EFLAGS 00150 pop eax //store new EFLAGS in EAX 00151 xor eax, ecx //can not toggle ID bit, 00152 mov CPUnum, 486 00153 jz end_detect //processor=80486 00154 mov CPUnum, 586 //586+ 00155 00156 mov have_cpuid, 1 //we have cpuid 00157 00158 //check number of cpuid instructions 00159 mov eax, 0 00160 cpuid 00161 mov maxEax, eax //save the maximum eax for cpuid 00162 00163 //save MFT string 00164 mov esi, procName 00165 mov [esi+0], ebx 00166 mov [esi+4], edx 00167 mov [esi+8], ecx 00168 mov [esi+12], 0 00169 00170 test maxEax, 1 00171 jz end_detect 00172 00173 //get flagstring 00174 mov eax, 1 00175 cpuid 00176 mov capFlags, edx 00177 00178 end_detect: 00179 00180 pop esi 00181 pop ebx 00182 pop eax 00183 } 00184 #elif defined(CS_COMPILER_GCC) 00185 __asm__( 00186 //detect 386/486 00187 " pushfl \n" 00188 " popl %%eax \n" //get EFLAGS 00189 " movl %%eax, %%ebx \n" //save original EFLAGS 00190 " xorl $0x40000, %%eax \n" //toggle AC bit 00191 " pushl %%eax \n" //copy to stack 00192 " popfl \n" //copy to EFLAGS 00193 " pushfl \n" 00194 " popl %%eax \n" //get EFLAGS again 00195 " xorl %%ebx, %%eax \n" //check AC bit 00196 " movl $386,%0 \n" //386 00197 " je 1f \n" //is a 386, stop detection 00198 " pushl %%ebx \n" //restore EFLAGS 00199 " popfl \n" 00200 //detect 486/pentium+ 00201 " pushfl \n" //get EFLAGS 00202 " popl %%eax \n" 00203 " movl %%eax, %%ecx \n" 00204 " xorl $0x200000,%%eax \n" //toggle ID bit in EFLAGS 00205 " pushl %%eax \n" //save new EFLAGS value on stack 00206 " popfl \n" //replace current EFLAGS value 00207 " pushfl \n" //get new EFLAGS 00208 " popl %%eax \n" //store new EFLAGS in EAX 00209 " xorl %%eax, %%ecx \n" //can not toggle ID bit, 00210 " movl $486,%0 \n" 00211 " jz 1f \n" //processor=80486 00212 " movl $586,%0 \n" //586+ 00213 " movl $1,%1 \n" //we have cpuid 00214 //check number of cpuid instructions 00215 " xorl %%eax,%%eax \n" // thebolt: this was a movl $0,%eax 00216 " cpuid \n" 00217 " movl %%eax,%2 \n" //save the maximum eax for cpuid 00218 //save MFT string 00219 " movl %4,%%esi \n" 00220 " movl %%ebx,0(%%esi) \n" 00221 " movl %%edx,4(%%esi) \n" 00222 " movl %%ecx,8(%%esi) \n" 00223 " movl $0,12(%%esi) \n" 00224 " testl $1,%2 \n" 00225 " jz 1f \n" 00226 //get flagstring 00227 " movl $1,%%eax \n" 00228 " cpuid \n" 00229 " movl %%edx,%3 \n" 00230 "1: \n" 00231 : "=g" (CPUnum), "=g" (have_cpuid), "=g" (maxEax), "=g" (capFlags) 00232 : "g" (procName), "2" (maxEax) 00233 : "eax", "ebx", "ecx", "edx", "esi"); 00234 00235 #endif //CS_COMPILER_MSVC/GCC 00236 mmxSupported = (capFlags & (1<<23)) != 0; 00237 sseSupported = (capFlags & (1<<25)) != 0; 00238 //AMD3dnowSupported = capFlags & (1<<31); 00239 } 00240 #else //CS_PROCESSOR_X86 00241 static inline void CheckX86Processor() {} 00242 #endif //CS_PROCESSOR_X86 00243 }; 00244 00245 #endif //__CS_PROCESSORCAP_H__
Generated for Crystal Space by doxygen 1.4.7