kdefx
kcpuinfo.cpp
Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 #include <csignal>
00028 #include <csetjmp>
00029 
00030 #include <config.h>
00031 #include "kcpuinfo.h"
00032 
00033 
00034 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
00035 #  define HAVE_GNU_INLINE_ASM
00036 #endif
00037 
00038 typedef void (*kde_sighandler_t) (int);
00039 
00040 #ifdef __i386__
00041 static jmp_buf env;
00042 
00043 
00044 static void sighandler( int )
00045 {
00046     std::longjmp( env, 1 );
00047 }
00048 #endif
00049 
00050 #ifdef __PPC__
00051 static sigjmp_buf KDE_NO_EXPORT jmpbuf;
00052 static sig_atomic_t KDE_NO_EXPORT canjump = 0;
00053 
00054 static void KDE_NO_EXPORT sigill_handler( int sig )
00055 {
00056     if ( !canjump ) {
00057         signal( sig, SIG_DFL );
00058         raise( sig );
00059     }
00060     canjump = 0;
00061     siglongjmp( jmpbuf, 1 );
00062 }
00063 #endif
00064 
00065 static int getCpuFeatures()
00066 {
00067     volatile int features = 0;
00068 
00069 #if defined( HAVE_GNU_INLINE_ASM )
00070 #if defined( __i386__ )
00071     bool haveCPUID = false;
00072     bool have3DNOW = false;
00073     int result = 0;
00074 
00075     
00076     __asm__ __volatile__(
00077     
00078     "pushf                      \n\t"   
00079     "popl   %%ecx               \n\t"   
00080     "movl   %%ecx, %%edx        \n\t"   
00081     "xorl   $0x00200000, %%ecx  \n\t"   
00082     "pushl  %%ecx               \n\t"   
00083     "popf                       \n\t"   
00084 
00085     
00086     "pushf                      \n\t"   
00087     "popl   %%ecx               \n\t"   
00088     "xorl   %%eax, %%eax        \n\t"   
00089     "cmpl   %%ecx, %%edx        \n\t"   
00090     "je    .Lno_cpuid_support%= \n\t"   
00091     "movl      $1, %%eax        \n\t"   
00092     ".Lno_cpuid_support%=:      \n\t"
00093     : "=a"(haveCPUID) : : "%ecx", "%edx" );
00094 
00095     
00096     if ( ! haveCPUID )
00097         return 0L;
00098 
00099     
00100     __asm__ __volatile__(
00101     "pushl  %%ebx               \n\t"   
00102     "movl      $1, %%eax        \n\t"   
00103     "cpuid                      \n\t"   
00104     "popl   %%ebx               \n\t"   
00105     : "=d"(result) : : "%eax", "%ecx" );
00106 
00107     
00108     if ( result & 0x00800000 )
00109         features |= KCPUInfo::IntelMMX;
00110 
00111     __asm__ __volatile__(
00112       "pushl %%ebx             \n\t"
00113       "movl $0x80000000, %%eax \n\t"
00114       "cpuid                   \n\t"
00115       "cmpl $0x80000000, %%eax \n\t"
00116       "jbe .Lno_extended%=     \n\t"
00117       "movl $0x80000001, %%eax \n\t"
00118       "cpuid                   \n\t"
00119       "test $0x80000000, %%edx \n\t"
00120       "jz .Lno_extended%=      \n\t"
00121       "movl      $1, %%eax     \n\t"   
00122       ".Lno_extended%=:        \n\t"
00123       "popl   %%ebx            \n\t"   
00124       : "=a"(have3DNOW) : );
00125 
00126     if ( have3DNOW )
00127         features |= KCPUInfo::AMD3DNOW;
00128 
00129 #ifdef HAVE_X86_SSE
00130     
00131     if ( result & 0x00200000 ) {
00132         features |= KCPUInfo::IntelSSE;
00133 
00134         
00135         
00136         kde_sighandler_t oldhandler = std::signal( SIGILL, sighandler );
00137 
00138         
00139         if ( setjmp( env ) )
00140             features ^= KCPUInfo::IntelSSE; 
00141         else
00142             __asm__ __volatile__("xorps %xmm0, %xmm0");
00143 
00144         
00145         std::signal( SIGILL, oldhandler );
00146 
00147         
00148         if ( (result & 0x00400000) && (features & KCPUInfo::IntelSSE) )
00149             features |= KCPUInfo::IntelSSE2;
00150 
00151         
00152         
00153     }
00154 #endif // HAVE_X86_SSE
00155 #elif defined __PPC__ && defined HAVE_PPC_ALTIVEC
00156     signal( SIGILL, sigill_handler );
00157     if ( sigsetjmp( jmpbuf, 1 ) ) {
00158         signal( SIGILL, SIG_DFL );
00159     } else {
00160         canjump = 1;
00161         __asm__ __volatile__( "mtspr 256, %0\n\t"
00162                               "vand %%v0, %%v0, %%v0"
00163                               : 
00164                               : "r" (-1) );
00165         signal( SIGILL, SIG_DFL );
00166         features |= KCPUInfo::AltiVec;
00167     }
00168 #endif // __i386__
00169 #endif //HAVE_GNU_INLINE_ASM
00170 
00171     return features;
00172 }
00173 
00174 unsigned int KCPUInfo::s_features = getCpuFeatures();
00175 
00176