Crystal Space: csutil/csprocessorcap.h Source File (Crystal Space Public API Reference)

| ## Public API Reference

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

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