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