CrystalSpace

Public API Reference

Main Page   Modules   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

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