kcpuinfo.cpp
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 
00039 
00040 #if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 > 2)
00041 #  define KDE_NO_EXPORT __attribute__ ((visibility("hidden")))
00042 #else
00043 #  define KDE_NO_EXPORT
00044 #endif
00045 
00046 typedef void (*kde_sighandler_t) (int);
00047 
00048 #ifdef __i386__
00049 static jmp_buf KDE_NO_EXPORT env;
00050 
00051 
00052 static void KDE_NO_EXPORT sighandler( int )
00053 {
00054     std::longjmp( env, 1 );
00055 }
00056 #endif
00057 
00058 #ifdef __PPC__
00059 static sigjmp_buf KDE_NO_EXPORT jmpbuf;
00060 static sig_atomic_t KDE_NO_EXPORT canjump = 0;
00061 
00062 static void KDE_NO_EXPORT sigill_handler( int sig )
00063 {
00064     if ( !canjump ) {
00065         signal( sig, SIG_DFL );
00066         raise( sig );
00067     }
00068     canjump = 0;
00069     siglongjmp( jmpbuf, 1 );
00070 }
00071 #endif
00072 
00073 static int KDE_NO_EXPORT getCpuFeatures()
00074 {
00075     int features = 0;
00076 
00077 #if defined( HAVE_GNU_INLINE_ASM )
00078 #if defined( __i386__ )
00079     bool haveCPUID = false;
00080     bool have3DNOW = false;
00081     int result = 0;
00082 
00083     
00084     __asm__ __volatile__(
00085     
00086     "pushf                      \n\t"   
00087     "popl   %%ecx               \n\t"   
00088     "movl   %%ecx, %%edx        \n\t"   
00089     "xorl   $0x00200000, %%ecx  \n\t"   
00090     "pushl  %%ecx               \n\t"   
00091     "popf                       \n\t"   
00092 
00093     
00094     "pushf                      \n\t"   
00095     "popl   %%ecx               \n\t"   
00096     "xorl   %%eax, %%eax        \n\t"   
00097     "cmpl   %%ecx, %%edx        \n\t"   
00098     "je    .Lno_cpuid_support%= \n\t"   
00099     "movl      $1, %%eax        \n\t"   
00100     ".Lno_cpuid_support%=:      \n\t"
00101     : "=a"(haveCPUID) : : "%ecx", "%edx" );
00102 
00103     
00104     if ( ! haveCPUID )
00105         return 0L;
00106 
00107     
00108     __asm__ __volatile__(
00109     "pushl  %%ebx               \n\t"   
00110     "movl      $1, %%eax        \n\t"   
00111     "cpuid                      \n\t"   
00112     "popl   %%ebx               \n\t"   
00113     : "=d"(result) : : "%eax", "%ecx" );
00114 
00115     
00116     if ( result & 0x00800000 )
00117         features |= KCPUInfo::IntelMMX;
00118 
00119     __asm__ __volatile__(
00120       "pushl %%ebx             \n\t"
00121       "movl $0x80000000, %%eax \n\t"
00122       "cpuid                   \n\t"
00123       "cmpl $0x80000000, %%eax \n\t"
00124       "jbe .Lno_extended%=     \n\t"
00125       "movl $0x80000001, %%eax \n\t"
00126       "cpuid                   \n\t"
00127       "test $0x80000000, %%edx \n\t"
00128       "jz .Lno_extended%=      \n\t"
00129       "movl      $1, %%eax     \n\t"   
00130       ".Lno_extended%=:        \n\t"
00131       "popl   %%ebx            \n\t"   
00132       : "=a"(have3DNOW) : );
00133 
00134     if ( have3DNOW )
00135         features |= KCPUInfo::AMD3DNOW;
00136 
00137 #ifdef HAVE_X86_SSE
00138     
00139     if ( result & 0x00200000 ) {
00140         features |= KCPUInfo::IntelSSE;
00141 
00142         
00143         
00144         kde_sighandler_t oldhandler = std::signal( SIGILL, sighandler );
00145 
00146         
00147         if ( setjmp( env ) )
00148             features ^= KCPUInfo::IntelSSE; 
00149         else
00150             __asm__ __volatile__("xorps %xmm0, %xmm0");
00151 
00152         
00153         std::signal( SIGILL, oldhandler );
00154 
00155         
00156         if ( (result & 0x00400000) && (features & KCPUInfo::IntelSSE) )
00157             features |= KCPUInfo::IntelSSE2;
00158 
00159         
00160         
00161     }
00162 #endif // HAVE_X86_SSE
00163 #elif defined __PPC__ && defined HAVE_PPC_ALTIVEC
00164     signal( SIGILL, sigill_handler );
00165     if ( sigsetjmp( jmpbuf, 1 ) ) {
00166         signal( SIGILL, SIG_DFL );
00167     } else {
00168         canjump = 1;
00169         __asm__ __volatile__( "mtspr 256, %0\n\t"
00170                               "vand %%v0, %%v0, %%v0"
00171                               : 
00172                               : "r" (-1) );
00173         signal( SIGILL, SIG_DFL );
00174         features |= KCPUInfo::AltiVec;
00175     }
00176 #endif // __i386__
00177 #endif //HAVE_GNU_INLINE_ASM
00178 
00179     return features;
00180 }
00181 
00182 unsigned int KCPUInfo::s_features = getCpuFeatures();
00183 
00184 
 
This file is part of the documentation for kdefx Library Version 3.2.0.