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