CrystalSpace

Public API Reference

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

csprocessorcap.h

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

Generated for Crystal Space by doxygen 1.2.14