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 #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