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