Doxygen Source Code Documentation
Main Page Alphabetical List Data Structures File List Data Fields Globals Search
cpu_accel.c
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 #include "config.h"
00025
00026 #include <inttypes.h>
00027
00028 #include "mpeg2.h"
00029
00030 #ifdef ACCEL_DETECT
00031 #ifdef ARCH_X86
00032 static inline uint32_t arch_accel (void)
00033 {
00034 uint32_t eax, ebx, ecx, edx;
00035 int AMD;
00036 uint32_t caps;
00037
00038 #ifndef PIC
00039 #define cpuid(op,eax,ebx,ecx,edx) \
00040 __asm__ ("cpuid" \
00041 : "=a" (eax), \
00042 "=b" (ebx), \
00043 "=c" (ecx), \
00044 "=d" (edx) \
00045 : "a" (op) \
00046 : "cc")
00047 #else
00048 #define cpuid(op,eax,ebx,ecx,edx) \
00049 __asm__ ("push %%ebx\n\t" \
00050 "cpuid\n\t" \
00051 "movl %%ebx,%1\n\t" \
00052 "pop %%ebx" \
00053 : "=a" (eax), \
00054 "=r" (ebx), \
00055 "=c" (ecx), \
00056 "=d" (edx) \
00057 : "a" (op) \
00058 : "cc")
00059 #endif
00060
00061 __asm__ ("pushf\n\t"
00062 "pushf\n\t"
00063 "pop %0\n\t"
00064 "movl %0,%1\n\t"
00065 "xorl $0x200000,%0\n\t"
00066 "push %0\n\t"
00067 "popf\n\t"
00068 "pushf\n\t"
00069 "pop %0\n\t"
00070 "popf"
00071 : "=r" (eax),
00072 "=r" (ebx)
00073 :
00074 : "cc");
00075
00076 if (eax == ebx)
00077 return 0;
00078
00079 cpuid (0x00000000, eax, ebx, ecx, edx);
00080 if (!eax)
00081 return 0;
00082
00083 AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
00084
00085 cpuid (0x00000001, eax, ebx, ecx, edx);
00086 if (! (edx & 0x00800000))
00087 return 0;
00088
00089 caps = MPEG2_ACCEL_X86_MMX;
00090 if (edx & 0x02000000)
00091 caps = MPEG2_ACCEL_X86_MMX | MPEG2_ACCEL_X86_MMXEXT;
00092
00093 cpuid (0x80000000, eax, ebx, ecx, edx);
00094 if (eax < 0x80000001)
00095 return caps;
00096
00097 cpuid (0x80000001, eax, ebx, ecx, edx);
00098
00099 if (edx & 0x80000000)
00100 caps |= MPEG2_ACCEL_X86_3DNOW;
00101
00102 if (AMD && (edx & 0x00400000))
00103 caps |= MPEG2_ACCEL_X86_MMXEXT;
00104
00105 return caps;
00106 }
00107 #endif
00108
00109 #ifdef ARCH_PPC
00110 #include <signal.h>
00111 #include <setjmp.h>
00112
00113 static sigjmp_buf jmpbuf;
00114 static volatile sig_atomic_t canjump = 0;
00115
00116 static RETSIGTYPE sigill_handler (int sig)
00117 {
00118 if (!canjump) {
00119 signal (sig, SIG_DFL);
00120 raise (sig);
00121 }
00122
00123 canjump = 0;
00124 siglongjmp (jmpbuf, 1);
00125 }
00126
00127 static inline uint32_t arch_accel (void)
00128 {
00129 signal (SIGILL, sigill_handler);
00130 if (sigsetjmp (jmpbuf, 1)) {
00131 signal (SIGILL, SIG_DFL);
00132 return 0;
00133 }
00134
00135 canjump = 1;
00136
00137 asm volatile ("mtspr 256, %0\n\t"
00138 "vand %%v0, %%v0, %%v0"
00139 :
00140 : "r" (-1));
00141
00142 signal (SIGILL, SIG_DFL);
00143 return MPEG2_ACCEL_PPC_ALTIVEC;
00144 }
00145 #endif
00146
00147 #ifdef ARCH_ALPHA
00148 static inline uint32_t arch_accel (void)
00149 {
00150 uint64_t no_mvi;
00151
00152 asm volatile ("amask %1, %0"
00153 : "=r" (no_mvi)
00154 : "rI" (256));
00155 return no_mvi ? MPEG2_ACCEL_ALPHA : (MPEG2_ACCEL_ALPHA |
00156 MPEG2_ACCEL_ALPHA_MVI);
00157 }
00158 #endif
00159 #endif
00160
00161 uint32_t mpeg2_detect_accel (void)
00162 {
00163 uint32_t accel;
00164
00165 accel = 0;
00166 #ifdef ACCEL_DETECT
00167 #ifdef LIBMPEG2_MLIB
00168 accel = MPEG2_ACCEL_MLIB;
00169 #endif
00170 #if defined (ARCH_X86) || defined (ARCH_PPC) || defined (ARCH_ALPHA)
00171 accel |= arch_accel ();
00172 #endif
00173 #endif
00174 return accel;
00175 }