• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE Support
  • Sitemap
  • Contact Us
 

qimageblitz

blitzcpu.cpp

Go to the documentation of this file.
00001 #include "blitzcpu.h"
00002 #include <config-processor.h>
00003 #include <csignal>
00004 #include <csetjmp>
00005 
00035 #if defined(__i386__) && ( defined(__GNUC__) || defined(__INTEL_COMPILER) )
00036 #  if defined(HAVE_MMX)
00037 #    define USE_MMX_INLINE_ASM
00038 #  endif
00039 #endif
00040 
00041 #ifdef USE_MMX_INLINE_ASM
00042 // Sighandler for the SSE OS support check
00043 typedef void (*blitz_sighandler_t)(int);
00044 static jmp_buf env;
00045 static void blitz_sighandler(int)
00046 {
00047     std::longjmp(env, 1);
00048 }
00049 #elif defined __PPC__ && defined HAVE_PPC_ALTIVEC
00050 // Sighandler for PPC AltiVec check
00051 static sigjmp_buf jmpbuf;
00052 static sig_atomic_t canjump = 0;
00053 static void blitz_sighandler(int sig)
00054 {
00055     if(!canjump) {
00056         signal(sig, SIG_DFL);
00057         raise(sig);
00058     }
00059     canjump = 0;
00060     siglongjmp(jmpbuf, 1);
00061 }
00062 #endif
00063 
00064 static unsigned int checkCPUID()
00065 {
00066     volatile unsigned int flags = 0;
00067 #ifdef USE_MMX_INLINE_ASM // Intel/AMD checks
00068     bool hasCPUID = false;
00069     unsigned int result = 0;
00070 
00071     __asm__ __volatile__
00072         (// Try to toggle the CPUID bit in the EFLAGS register
00073          "pushf                      \n\t"   // Push the EFLAGS register onto the stack
00074          "popl   %%ecx               \n\t"   // Pop the value into ECX
00075          "movl   %%ecx, %%edx        \n\t"   // Copy ECX to EDX
00076          "xorl   $0x00200000, %%ecx  \n\t"   // Toggle bit 21 (CPUID) in ECX
00077          "pushl  %%ecx               \n\t"   // Push the modified value onto the stack
00078          "popf                       \n\t"   // Pop it back into EFLAGS
00079 
00080          // Check if the CPUID bit was successfully toggled
00081          "pushf                      \n\t"   // Push EFLAGS back onto the stack
00082          "popl   %%ecx               \n\t"   // Pop the value into ECX
00083          "xorl   %%eax, %%eax        \n\t"   // Zero out the EAX register
00084          "cmpl   %%ecx, %%edx        \n\t"   // Compare ECX with EDX
00085          "je    .Lno_cpuid_support%= \n\t"   // Jump if they're identical
00086          "movl      $1, %%eax        \n\t"   // Set EAX to true
00087          ".Lno_cpuid_support%=:      \n\t"
00088          : "=a"(hasCPUID) : : "%ecx", "%edx" );
00089     if(!hasCPUID)
00090         return(flags);
00091 
00092     // Execute CPUID with the feature request bit set
00093     __asm__ __volatile__
00094         ("pushl  %%ebx               \n\t"   // Save EBX
00095          "movl      $1, %%eax        \n\t"   // Set EAX to 1 (features request)
00096          "cpuid                      \n\t"   // Call CPUID
00097          "popl   %%ebx               \n\t"   // Restore EBX
00098          : "=d"(result) : : "%eax", "%ecx");
00099 
00100     // Test bit 23 (MMX support)
00101     // 25: SSE
00102     // 26: SSE2
00103     if(result & 0x00800000)
00104         flags |= BlitzCPUInfo::MMX;
00105     if(result & 0x00200000)
00106         flags |= BlitzCPUInfo::SSE;
00107     if(result & 0x00400000)
00108         flags |= BlitzCPUInfo::SSE2;
00109 
00110     // Now try extended feature request
00111     result = 0;
00112     __asm__ __volatile__
00113         ("pushl %%ebx             \n\t"
00114          "movl $0x80000000, %%eax \n\t"
00115          "cpuid                   \n\t"
00116          "cmpl $0x80000000, %%eax \n\t"
00117          "jbe .Lno_extended%=     \n\t"
00118          "movl $0x80000001, %%eax \n\t"
00119          "cpuid                   \n\t"
00120          ".Lno_extended%=:        \n\t"
00121          "popl   %%ebx            \n\t"   // Restore EBX
00122          : "=d"(result) : : "%eax", "%ecx");
00123 
00124     // Bit 31: 3dNow
00125     // Bit 30: 3dNow+
00126     // Bit 22: MMX SSE (Integer SSE) - AMD Only
00127     if(result & 0x80000000){
00128         flags |= BlitzCPUInfo::AMD3DNOW;
00129         if(result & 0x40000000)
00130             flags |= BlitzCPUInfo::AMD3DNOW2;
00131         if(result & 0x00400000) // This is only valid on AMD cpu's w/ 3dnow
00132             flags |= BlitzCPUInfo::IntegerSSE;
00133     }
00134     else if(flags & BlitzCPUInfo::SSE)
00135         flags |= BlitzCPUInfo::IntegerSSE;
00136 
00137     if((flags & BlitzCPUInfo::SSE) || (flags & BlitzCPUInfo::SSE2)){
00138         // SSE OS support check
00139         // Install our own sighandler for SIGILL.
00140         blitz_sighandler_t oldhandler =
00141             std::signal(SIGILL, blitz_sighandler);
00142 
00143         // Try executing an SSE insn to see if we get a SIGILL
00144         if(setjmp(env)){
00145             // No go. MMX-SSE should still be okay, tho.
00146             if(flags & BlitzCPUInfo::SSE)
00147                 flags -= BlitzCPUInfo::SSE;
00148             if(flags & BlitzCPUInfo::SSE2)
00149                 flags -= BlitzCPUInfo::SSE2;
00150         }
00151         else
00152             __asm__ __volatile__("xorps %xmm0, %xmm0");
00153 
00154         // Restore the default sighandler
00155         std::signal( SIGILL, oldhandler );
00156     }
00157 
00158 #elif defined __PPC__ && defined HAVE_PPC_ALTIVEC
00159     signal(SIGILL, blitz_sighandler);
00160     if(sigsetjmp(jmpbuf, 1)){
00161         signal(SIGILL, SIG_DFL);
00162     }
00163     else{
00164         canjump = 1;
00165         __asm__ __volatile__( "mtspr 256, %0\n\t"
00166                              "vand %%v0, %%v0, %%v0"
00167                              : /* none */
00168                              : "r" (-1) );
00169         signal(SIGILL, SIG_DFL);
00170         flags |= BlitzCPUInfo::AltiVec;
00171     }
00172 #endif
00173     return(flags);
00174 }
00175 
00176 bool BlitzCPUInfo::haveExtension(unsigned int extension)
00177 {
00178     static bool checked = false;
00179     static unsigned int flags = 0;
00180     if(!checked){
00181         flags = checkCPUID();
00182         checked = true;
00183         qWarning("MMX: %d, SSE: %d, SSE2: %d, MMX-SSE: %d, 3dNow: %d, 3dNow+: %d",
00184                  haveExtension(BlitzCPUInfo::MMX),
00185                  haveExtension(BlitzCPUInfo::SSE),
00186                  haveExtension(BlitzCPUInfo::SSE2),
00187                  haveExtension(BlitzCPUInfo::IntegerSSE),
00188                  haveExtension(BlitzCPUInfo::AMD3DNOW),
00189                  haveExtension(BlitzCPUInfo::AMD3DNOW2));
00190     }
00191     return(flags & extension);
00192 }
00193 

qimageblitz

Skip menu "qimageblitz"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

KDE Support

Skip menu "KDE Support"
  • akonadi
  • Decibel
  • grantlee
  • kdewin
  • phonon
  •     Backend
  • polkit-qt
  • qca
  • qimageblitz
  • soprano
  • strigi
  •     searchclient
  •     streamanalyzer
  •     streams
Generated for KDE Support by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal