CrystalSpace

Public API Reference

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