qimageblitz
blitzcpu.cpp
Go to the documentation of this file.00001 #include "blitzcpu.h"
00002 #include <config-processor.h>
00003 #include <csignal>
00004 #include <csetjmp>
00005
00035 #if defined(__i386__) && ( defined(__GNUC__) || defined(__INTEL_COMPILER) )
00036 # if defined(HAVE_MMX)
00037 # define USE_MMX_INLINE_ASM
00038 # endif
00039 #endif
00040
00041 #ifdef USE_MMX_INLINE_ASM
00042
00043 typedef void (*blitz_sighandler_t)(int);
00044 static jmp_buf env;
00045 static void blitz_sighandler(int)
00046 {
00047 std::longjmp(env, 1);
00048 }
00049 #elif defined __PPC__ && defined HAVE_PPC_ALTIVEC
00050
00051 static sigjmp_buf jmpbuf;
00052 static sig_atomic_t canjump = 0;
00053 static void blitz_sighandler(int sig)
00054 {
00055 if(!canjump) {
00056 signal(sig, SIG_DFL);
00057 raise(sig);
00058 }
00059 canjump = 0;
00060 siglongjmp(jmpbuf, 1);
00061 }
00062 #endif
00063
00064 static unsigned int checkCPUID()
00065 {
00066 volatile unsigned int flags = 0;
00067 #ifdef USE_MMX_INLINE_ASM // Intel/AMD checks
00068 bool hasCPUID = false;
00069 unsigned int result = 0;
00070
00071 __asm__ __volatile__
00072 (
00073 "pushf \n\t"
00074 "popl %%ecx \n\t"
00075 "movl %%ecx, %%edx \n\t"
00076 "xorl $0x00200000, %%ecx \n\t"
00077 "pushl %%ecx \n\t"
00078 "popf \n\t"
00079
00080
00081 "pushf \n\t"
00082 "popl %%ecx \n\t"
00083 "xorl %%eax, %%eax \n\t"
00084 "cmpl %%ecx, %%edx \n\t"
00085 "je .Lno_cpuid_support%= \n\t"
00086 "movl $1, %%eax \n\t"
00087 ".Lno_cpuid_support%=: \n\t"
00088 : "=a"(hasCPUID) : : "%ecx", "%edx" );
00089 if(!hasCPUID)
00090 return(flags);
00091
00092
00093 __asm__ __volatile__
00094 ("pushl %%ebx \n\t"
00095 "movl $1, %%eax \n\t"
00096 "cpuid \n\t"
00097 "popl %%ebx \n\t"
00098 : "=d"(result) : : "%eax", "%ecx");
00099
00100
00101
00102
00103 if(result & 0x00800000)
00104 flags |= BlitzCPUInfo::MMX;
00105 if(result & 0x00200000)
00106 flags |= BlitzCPUInfo::SSE;
00107 if(result & 0x00400000)
00108 flags |= BlitzCPUInfo::SSE2;
00109
00110
00111 result = 0;
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 ".Lno_extended%=: \n\t"
00121 "popl %%ebx \n\t"
00122 : "=d"(result) : : "%eax", "%ecx");
00123
00124
00125
00126
00127 if(result & 0x80000000){
00128 flags |= BlitzCPUInfo::AMD3DNOW;
00129 if(result & 0x40000000)
00130 flags |= BlitzCPUInfo::AMD3DNOW2;
00131 if(result & 0x00400000)
00132 flags |= BlitzCPUInfo::IntegerSSE;
00133 }
00134 else if(flags & BlitzCPUInfo::SSE)
00135 flags |= BlitzCPUInfo::IntegerSSE;
00136
00137 if((flags & BlitzCPUInfo::SSE) || (flags & BlitzCPUInfo::SSE2)){
00138
00139
00140 blitz_sighandler_t oldhandler =
00141 std::signal(SIGILL, blitz_sighandler);
00142
00143
00144 if(setjmp(env)){
00145
00146 if(flags & BlitzCPUInfo::SSE)
00147 flags -= BlitzCPUInfo::SSE;
00148 if(flags & BlitzCPUInfo::SSE2)
00149 flags -= BlitzCPUInfo::SSE2;
00150 }
00151 else
00152 __asm__ __volatile__("xorps %xmm0, %xmm0");
00153
00154
00155 std::signal( SIGILL, oldhandler );
00156 }
00157
00158 #elif defined __PPC__ && defined HAVE_PPC_ALTIVEC
00159 signal(SIGILL, blitz_sighandler);
00160 if(sigsetjmp(jmpbuf, 1)){
00161 signal(SIGILL, SIG_DFL);
00162 }
00163 else{
00164 canjump = 1;
00165 __asm__ __volatile__( "mtspr 256, %0\n\t"
00166 "vand %%v0, %%v0, %%v0"
00167 :
00168 : "r" (-1) );
00169 signal(SIGILL, SIG_DFL);
00170 flags |= BlitzCPUInfo::AltiVec;
00171 }
00172 #endif
00173 return(flags);
00174 }
00175
00176 bool BlitzCPUInfo::haveExtension(unsigned int extension)
00177 {
00178 static bool checked = false;
00179 static unsigned int flags = 0;
00180 if(!checked){
00181 flags = checkCPUID();
00182 checked = true;
00183 qWarning("MMX: %d, SSE: %d, SSE2: %d, MMX-SSE: %d, 3dNow: %d, 3dNow+: %d",
00184 haveExtension(BlitzCPUInfo::MMX),
00185 haveExtension(BlitzCPUInfo::SSE),
00186 haveExtension(BlitzCPUInfo::SSE2),
00187 haveExtension(BlitzCPUInfo::IntegerSSE),
00188 haveExtension(BlitzCPUInfo::AMD3DNOW),
00189 haveExtension(BlitzCPUInfo::AMD3DNOW2));
00190 }
00191 return(flags & extension);
00192 }
00193