00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025
00026 #include <inttypes.h>
00027
00028 #include "mpeg2.h"
00029 #include "attributes.h"
00030 #include "mpeg2_internal.h"
00031
00032 #ifdef ARCH_X86
00033 static inline uint32_t arch_accel (uint32_t accel)
00034 {
00035 if (accel & (MPEG2_ACCEL_X86_3DNOW | MPEG2_ACCEL_X86_MMXEXT))
00036 accel |= MPEG2_ACCEL_X86_MMX;
00037
00038 if (accel & (MPEG2_ACCEL_X86_SSE2 | MPEG2_ACCEL_X86_SSE3))
00039 accel |= MPEG2_ACCEL_X86_MMXEXT;
00040
00041 if (accel & (MPEG2_ACCEL_X86_SSE3))
00042 accel |= MPEG2_ACCEL_X86_SSE2;
00043
00044 #ifdef ACCEL_DETECT
00045 if (accel & MPEG2_ACCEL_DETECT) {
00046 uint32_t eax, ebx, ecx, edx;
00047 int AMD;
00048
00049 #if defined(__x86_64__) || (!defined(PIC) && !defined(__PIC__))
00050 #define cpuid(op,eax,ebx,ecx,edx) \
00051 __asm__ ("cpuid" \
00052 : "=a" (eax), \
00053 "=b" (ebx), \
00054 "=c" (ecx), \
00055 "=d" (edx) \
00056 : "a" (op) \
00057 : "cc")
00058 #else
00059 #define cpuid(op,eax,ebx,ecx,edx) \
00060 __asm__ ("pushl %%ebx\n\t" \
00061 "cpuid\n\t" \
00062 "movl %%ebx,%1\n\t" \
00063 "popl %%ebx" \
00064 : "=a" (eax), \
00065 "=r" (ebx), \
00066 "=c" (ecx), \
00067 "=d" (edx) \
00068 : "a" (op) \
00069 : "cc")
00070 #endif
00071
00072 #ifndef __x86_64__
00073 __asm__ ("pushf\n\t"
00074 "pushf\n\t"
00075 "pop %0\n\t"
00076 "movl %0,%1\n\t"
00077 "xorl $0x200000,%0\n\t"
00078 "push %0\n\t"
00079 "popf\n\t"
00080 "pushf\n\t"
00081 "pop %0\n\t"
00082 "popf"
00083 : "=r" (eax),
00084 "=r" (ebx)
00085 :
00086 : "cc");
00087
00088 if (eax == ebx)
00089 return accel;
00090 #endif
00091
00092 cpuid (0x00000000, eax, ebx, ecx, edx);
00093 if (!eax)
00094 return accel;
00095
00096 AMD = (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65);
00097
00098 cpuid (0x00000001, eax, ebx, ecx, edx);
00099 if (! (edx & 0x00800000))
00100 return accel;
00101
00102 accel |= MPEG2_ACCEL_X86_MMX;
00103 if (edx & 0x02000000)
00104 accel |= MPEG2_ACCEL_X86_MMXEXT;
00105
00106 if (edx & 0x04000000)
00107 accel |= MPEG2_ACCEL_X86_SSE2;
00108
00109 if (ecx & 0x00000001)
00110 accel |= MPEG2_ACCEL_X86_SSE3;
00111
00112 cpuid (0x80000000, eax, ebx, ecx, edx);
00113 if (eax < 0x80000001)
00114 return accel;
00115
00116 cpuid (0x80000001, eax, ebx, ecx, edx);
00117
00118 if (edx & 0x80000000)
00119 accel |= MPEG2_ACCEL_X86_3DNOW;
00120
00121 if (AMD && (edx & 0x00400000))
00122 accel |= MPEG2_ACCEL_X86_MMXEXT;
00123 }
00124 #endif
00125
00126 return accel;
00127 }
00128 #endif
00129
00130 #if defined(ACCEL_DETECT) && (defined(ARCH_PPC) || defined(ARCH_SPARC))
00131 #include <signal.h>
00132 #include <setjmp.h>
00133
00134 static sigjmp_buf jmpbuf;
00135 static volatile sig_atomic_t canjump = 0;
00136
00137 static RETSIGTYPE sigill_handler (int sig)
00138 {
00139 if (!canjump) {
00140 signal (sig, SIG_DFL);
00141 raise (sig);
00142 }
00143
00144 canjump = 0;
00145 siglongjmp (jmpbuf, 1);
00146 }
00147 #endif
00148
00149 #ifdef ARCH_PPC
00150 static uint32_t arch_accel (uint32_t accel)
00151 {
00152 #if defined(ACCEL_DETECT) && defined(HAVE_ALTIVEC)
00153 if ((accel & (MPEG2_ACCEL_PPC_ALTIVEC | MPEG2_ACCEL_DETECT)) ==
00154 MPEG2_ACCEL_DETECT) {
00155 static RETSIGTYPE (* oldsig) (int);
00156
00157 oldsig = signal (SIGILL, sigill_handler);
00158 if (sigsetjmp (jmpbuf, 1)) {
00159 signal (SIGILL, oldsig);
00160 return accel;
00161 }
00162
00163 canjump = 1;
00164
00165 #if defined(HAVE_ALTIVEC_H) && !defined(__APPLE__)
00166 #define VAND(a,b,c) "vand " #a "," #b "," #c "\n\t"
00167 #else
00168 #define VAND(a,b,c) "vand v" #a ",v" #b ",v" #c "\n\t"
00169 #endif
00170 asm volatile ("mtspr 256, %0\n\t"
00171 VAND (0, 0, 0)
00172 :
00173 : "r" (-1));
00174
00175 canjump = 0;
00176 accel |= MPEG2_ACCEL_PPC_ALTIVEC;
00177
00178 signal (SIGILL, oldsig);
00179 }
00180 #endif
00181
00182 return accel;
00183 }
00184 #endif
00185
00186 #ifdef ARCH_SPARC
00187 static uint32_t arch_accel (uint32_t accel)
00188 {
00189 if (accel & MPEG2_ACCEL_SPARC_VIS2)
00190 accel |= MPEG2_ACCEL_SPARC_VIS;
00191
00192 #ifdef ACCEL_DETECT
00193 if ((accel & (MPEG2_ACCEL_SPARC_VIS2 | MPEG2_ACCEL_DETECT)) ==
00194 MPEG2_ACCEL_DETECT) {
00195 static RETSIGTYPE (* oldsig) (int);
00196
00197 oldsig = signal (SIGILL, sigill_handler);
00198 if (sigsetjmp (jmpbuf, 1)) {
00199 signal (SIGILL, oldsig);
00200 return accel;
00201 }
00202
00203 canjump = 1;
00204
00205
00206 __asm__ __volatile__(".word\t0x81b007c0");
00207
00208 canjump = 0;
00209 accel |= MPEG2_ACCEL_SPARC_VIS;
00210
00211 if (sigsetjmp (jmpbuf, 1)) {
00212 signal (SIGILL, oldsig);
00213 return accel;
00214 }
00215
00216 canjump = 1;
00217
00218
00219 __asm__ __volatile__(".word\t0x81b00020");
00220
00221 canjump = 0;
00222 accel |= MPEG2_ACCEL_SPARC_VIS2;
00223
00224 signal (SIGILL, oldsig);
00225 }
00226 #endif
00227
00228 return accel;
00229 }
00230 #endif
00231
00232 #ifdef ARCH_ALPHA
00233 static inline uint32_t arch_accel (uint32_t accel)
00234 {
00235 if (accel & MPEG2_ACCEL_ALPHA_MVI)
00236 accel |= MPEG2_ACCEL_ALPHA;
00237
00238 #ifdef ACCEL_DETECT
00239 if (accel & MPEG2_ACCEL_DETECT) {
00240 uint64_t no_mvi;
00241
00242 asm volatile ("amask %1, %0"
00243 : "=r" (no_mvi)
00244 : "rI" (256));
00245 accel |= no_mvi ? MPEG2_ACCEL_ALPHA : (MPEG2_ACCEL_ALPHA |
00246 MPEG2_ACCEL_ALPHA_MVI);
00247 }
00248 #endif
00249
00250 return accel;
00251 }
00252 #endif
00253
00254 uint32_t mpeg2_detect_accel (uint32_t accel)
00255 {
00256 #if defined (ARCH_X86) || defined (ARCH_PPC) || defined (ARCH_ALPHA) || defined (ARCH_SPARC)
00257 accel = arch_accel (accel);
00258 #endif
00259 return accel;
00260 }