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")) {