CrystalSpace

Public API Reference

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