3 * Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
5 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
7 * mpeg2dec is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * mpeg2dec is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #define LOG_MODULE "cpu_accel"
37 #include "xineutils.h"
39 #if defined(ARCH_X86) || defined(ARCH_X86_64)
40 #if defined __x86_64__
41 static uint32_t arch_accel (void)
44 /* No need to test for this on AMD64, we know what the
46 caps = MM_ACCEL_X86_MMX | MM_ACCEL_X86_SSE | MM_ACCEL_X86_MMXEXT | MM_ACCEL_X86_SSE2;
51 static uint32_t arch_accel (void)
55 uint32_t eax, ebx, ecx, edx;
60 #define cpuid(op,eax,ebx,ecx,edx) \
68 #else /* PIC version : save ebx */
69 #define cpuid(op,eax,ebx,ecx,edx) \
70 __asm__ ("pushl %%ebx\n\t" \
86 "xorl $0x200000,%0\n\t"
97 if (eax == ebx) /* no cpuid */
100 cpuid (0x00000000, eax, ebx, ecx, edx);
101 if (!eax) /* vendor string only */
104 AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
106 cpuid (0x00000001, eax, ebx, ecx, edx);
107 if (! (edx & 0x00800000)) /* no MMX */
110 caps = MM_ACCEL_X86_MMX;
111 if (edx & 0x02000000) /* SSE - identical to AMD MMX extensions */
112 caps |= MM_ACCEL_X86_SSE | MM_ACCEL_X86_MMXEXT;
114 if (edx & 0x04000000) /* SSE2 */
115 caps |= MM_ACCEL_X86_SSE2;
117 cpuid (0x80000000, eax, ebx, ecx, edx);
118 if (eax < 0x80000001) /* no extended capabilities */
121 cpuid (0x80000001, eax, ebx, ecx, edx);
123 if (edx & 0x80000000)
124 caps |= MM_ACCEL_X86_3DNOW;
126 if (AMD && (edx & 0x00400000)) /* AMD MMX extensions */
127 caps |= MM_ACCEL_X86_MMXEXT;
136 static jmp_buf sigill_return;
138 static void sigill_handler (int n) {
139 longjmp(sigill_return, 1);
141 #endif /* ARCH_X86 */
143 #if defined (ARCH_PPC) && defined (ENABLE_ALTIVEC)
144 static sigjmp_buf jmpbuf;
145 static volatile sig_atomic_t canjump = 0;
147 static void sigill_handler (int sig)
150 signal (sig, SIG_DFL);
155 siglongjmp (jmpbuf, 1);
158 static uint32_t arch_accel (void)
160 signal (SIGILL, sigill_handler);
161 if (sigsetjmp (jmpbuf, 1)) {
162 signal (SIGILL, SIG_DFL);
168 __asm__ volatile ("mtspr 256, %0\n\t"
169 "vand %%v0, %%v0, %%v0"
173 signal (SIGILL, SIG_DFL);
174 return MM_ACCEL_PPC_ALTIVEC;
176 #endif /* ARCH_PPC */
178 uint32_t xine_mm_accel (void)
180 static int initialized = 0;
181 static uint32_t accel;
184 #if defined (ARCH_X86) || (defined (ARCH_PPC) && defined (ENABLE_ALTIVEC))
185 accel = arch_accel ();
186 #elif defined (HAVE_MLIB)
190 if ((hndl = dlopen("libmlib.so.2", RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE)) == NULL) {
195 accel = MM_ACCEL_MLIB;
198 accel = MM_ACCEL_MLIB;
204 #if defined(ARCH_X86) || defined(ARCH_X86_64)
206 /* test OS support for SSE */
207 if( accel & MM_ACCEL_X86_SSE ) {
208 void (*old_sigill_handler)(int);
210 old_sigill_handler = signal (SIGILL, sigill_handler);
212 if (setjmp(sigill_return)) {
213 lprintf ("OS doesn't support SSE instructions.\n");
214 accel &= ~(MM_ACCEL_X86_SSE|MM_ACCEL_X86_SSE2);
216 __asm__ volatile ("xorps %xmm0, %xmm0");
219 signal (SIGILL, old_sigill_handler);
221 #endif /* _MSC_VER */
222 #endif /* ARCH_X86 || ARCH_X86_64 */
224 if(getenv("XINE_NO_ACCEL")) {