3 * Copyright (C) 2000-2004 Michel Lespinasse <walken@zoy.org>
4 * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
6 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
7 * See http://libmpeg2.sourceforge.net/ for updates.
9 * mpeg2dec is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * mpeg2dec is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Modified for use with MPlayer, see libmpeg2_changes.diff for the exact changes.
24 * detailed changelog at http://svn.mplayerhq.hu/mplayer/trunk/
33 #include "attributes.h"
34 #include "mpeg2_internal.h"
36 #include "cpudetect.h"
38 #if ARCH_X86 || ARCH_X86_64
39 static inline uint32_t arch_accel (uint32_t accel
)
41 /* Use MPlayer CPU detection instead of libmpeg2 variant. */
43 if (accel
& (MPEG2_ACCEL_X86_3DNOW
| MPEG2_ACCEL_X86_MMXEXT
))
44 accel
|= MPEG2_ACCEL_X86_MMX
;
46 if (accel
& (MPEG2_ACCEL_X86_SSE2
| MPEG2_ACCEL_X86_SSE3
))
47 accel
|= MPEG2_ACCEL_X86_MMXEXT
;
49 if (accel
& (MPEG2_ACCEL_X86_SSE3
))
50 accel
|= MPEG2_ACCEL_X86_SSE2
;
53 if (accel
& MPEG2_ACCEL_DETECT
) {
54 uint32_t eax
, ebx
, ecx
, edx
;
57 #if defined(__x86_64__) || (!defined(PIC) && !defined(__PIC__))
58 #define cpuid(op,eax,ebx,ecx,edx) \
66 #else /* PIC version : save ebx (not needed on x86_64) */
67 #define cpuid(op,eax,ebx,ecx,edx) \
68 __asm__ ("pushl %%ebx\n\t" \
80 #ifndef __x86_64__ /* x86_64 supports the cpuid op */
85 "xorl $0x200000,%0\n\t"
96 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 accel
|= MPEG2_ACCEL_X86_MMX
;
111 if (edx
& 0x02000000) /* SSE - identical to AMD MMX ext. */
112 accel
|= MPEG2_ACCEL_X86_MMXEXT
;
114 if (edx
& 0x04000000) /* SSE2 */
115 accel
|= MPEG2_ACCEL_X86_SSE2
;
117 if (ecx
& 0x00000001) /* SSE3 */
118 accel
|= MPEG2_ACCEL_X86_SSE3
;
120 cpuid (0x80000000, eax
, ebx
, ecx
, edx
);
121 if (eax
< 0x80000001) /* no extended capabilities */
124 cpuid (0x80000001, eax
, ebx
, ecx
, edx
);
126 if (edx
& 0x80000000)
127 accel
|= MPEG2_ACCEL_X86_3DNOW
;
129 if (AMD
&& (edx
& 0x00400000)) /* AMD MMX extensions */
130 accel
|= MPEG2_ACCEL_X86_MMXEXT
;
132 #endif /* ACCEL_DETECT */
139 accel
|= MPEG2_ACCEL_X86_MMX
;
140 if (gCpuCaps
.hasSSE2
)
141 accel
|= MPEG2_ACCEL_X86_SSE2
;
142 if (gCpuCaps
.hasMMX2
)
143 accel
|= MPEG2_ACCEL_X86_MMXEXT
;
144 if (gCpuCaps
.has3DNow
)
145 accel
|= MPEG2_ACCEL_X86_3DNOW
;
151 #endif /* ARCH_X86 || ARCH_X86_64 */
153 #if defined(ACCEL_DETECT) && (ARCH_PPC || ARCH_SPARC)
157 static sigjmp_buf jmpbuf
;
158 static volatile sig_atomic_t canjump
= 0;
160 static RETSIGTYPE
sigill_handler (int sig
)
163 signal (sig
, SIG_DFL
);
168 siglongjmp (jmpbuf
, 1);
170 #endif /* ACCEL_DETECT && (ARCH_PPC || ARCH_SPARC) */
173 static uint32_t arch_accel (uint32_t accel
)
176 if ((accel
& (MPEG2_ACCEL_PPC_ALTIVEC
| MPEG2_ACCEL_DETECT
)) ==
177 MPEG2_ACCEL_DETECT
) {
178 static RETSIGTYPE (* oldsig
) (int);
180 oldsig
= signal (SIGILL
, sigill_handler
);
181 if (sigsetjmp (jmpbuf
, 1)) {
182 signal (SIGILL
, oldsig
);
188 #if defined(__APPLE_CC__) /* apple */
189 #define VAND(a,b,c) "vand v" #a ",v" #b ",v" #c "\n\t"
191 #define VAND(a,b,c) "vand " #a "," #b "," #c "\n\t"
193 asm volatile ("mtspr 256, %0\n\t"
199 accel
|= MPEG2_ACCEL_PPC_ALTIVEC
;
201 signal (SIGILL
, oldsig
);
203 #endif /* ACCEL_DETECT */
207 #endif /* ARCH_PPC */
210 static uint32_t arch_accel (uint32_t accel
)
212 if (accel
& MPEG2_ACCEL_SPARC_VIS2
)
213 accel
|= MPEG2_ACCEL_SPARC_VIS
;
216 if ((accel
& (MPEG2_ACCEL_SPARC_VIS2
| MPEG2_ACCEL_DETECT
)) ==
217 MPEG2_ACCEL_DETECT
) {
218 static RETSIGTYPE (* oldsig
) (int);
220 oldsig
= signal (SIGILL
, sigill_handler
);
221 if (sigsetjmp (jmpbuf
, 1)) {
222 signal (SIGILL
, oldsig
);
228 /* pdist %f0, %f0, %f0 */
229 __asm__
__volatile__(".word\t0x81b007c0");
232 accel
|= MPEG2_ACCEL_SPARC_VIS
;
234 if (sigsetjmp (jmpbuf
, 1)) {
235 signal (SIGILL
, oldsig
);
241 /* edge8n %g0, %g0, %g0 */
242 __asm__
__volatile__(".word\t0x81b00020");
245 accel
|= MPEG2_ACCEL_SPARC_VIS2
;
247 signal (SIGILL
, oldsig
);
249 #endif /* ACCEL_DETECT */
253 #endif /* ARCH_SPARC */
256 static inline uint32_t arch_accel (uint32_t accel
)
258 if (accel
& MPEG2_ACCEL_ALPHA_MVI
)
259 accel
|= MPEG2_ACCEL_ALPHA
;
262 if (accel
& MPEG2_ACCEL_DETECT
) {
265 asm volatile ("amask %1, %0"
267 : "rI" (256)); /* AMASK_MVI */
268 accel
|= no_mvi
? MPEG2_ACCEL_ALPHA
: (MPEG2_ACCEL_ALPHA
|
269 MPEG2_ACCEL_ALPHA_MVI
);
271 #endif /* ACCEL_DETECT */
275 #endif /* ARCH_ALPHA */
277 uint32_t mpeg2_detect_accel (uint32_t accel
)
279 #if ARCH_X86 || ARCH_X86_64 || ARCH_PPC || ARCH_ALPHA || ARCH_SPARC
280 accel
= arch_accel (accel
);