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.3.2.