Fix crash during early exit
[mplayer.git] / libmpeg2 / cpu_accel.c
blob66f7b7fdff4c28aaaf9cc34940893b93fbb37b79
1 /*
2 * cpu_accel.c
3 * Copyright (C) 2000-2003 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 libmpeg-0.4.1.diff for the exact changes.
24 * detailed changelog at http://svn.mplayerhq.hu/mplayer/trunk/
25 * $Id$
28 #include "config.h"
29 #include "cpudetect.h"
31 #include <inttypes.h>
33 #include "mpeg2.h"
34 #include "attributes.h"
35 #include "mpeg2_internal.h"
37 #ifdef ACCEL_DETECT
38 #if defined(ARCH_X86) || defined(ARCH_X86_64)
40 /* MPlayer imports libmpeg2 as decoder, which detects MMX / 3DNow!
41 * instructions via assembly. However, it is regarded as duplicated work
42 * in MPlayer, so that we enforce using MPlayer's implementation.
44 #define USE_MPLAYER_CPUDETECT
46 static inline uint32_t arch_accel (void)
48 #if !defined(USE_MPLAYER_CPUDETECT)
49 uint32_t eax, ebx, ecx, edx;
50 int AMD;
51 uint32_t caps;
53 #if defined(__x86_64__) || (!defined(PIC) && !defined(__PIC__))
54 #define cpuid(op,eax,ebx,ecx,edx) \
55 __asm__ ("cpuid" \
56 : "=a" (eax), \
57 "=b" (ebx), \
58 "=c" (ecx), \
59 "=d" (edx) \
60 : "a" (op) \
61 : "cc")
62 #else /* PIC version : save ebx (not needed on x86_64) */
63 #define cpuid(op,eax,ebx,ecx,edx) \
64 __asm__ ("pushl %%ebx\n\t" \
65 "cpuid\n\t" \
66 "movl %%ebx,%1\n\t" \
67 "popl %%ebx" \
68 : "=a" (eax), \
69 "=r" (ebx), \
70 "=c" (ecx), \
71 "=d" (edx) \
72 : "a" (op) \
73 : "cc")
74 #endif
76 #ifndef __x86_64__ /* x86_64 supports the cpuid op */
77 __asm__ ("pushf\n\t"
78 "pushf\n\t"
79 "pop %0\n\t"
80 "movl %0,%1\n\t"
81 "xorl $0x200000,%0\n\t"
82 "push %0\n\t"
83 "popf\n\t"
84 "pushf\n\t"
85 "pop %0\n\t"
86 "popf"
87 : "=r" (eax),
88 "=r" (ebx)
90 : "cc");
92 if (eax == ebx) /* no cpuid */
93 return 0;
94 #endif
96 cpuid (0x00000000, eax, ebx, ecx, edx);
97 if (!eax) /* vendor string only */
98 return 0;
100 AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
102 cpuid (0x00000001, eax, ebx, ecx, edx);
103 if (! (edx & 0x00800000)) /* no MMX */
104 return 0;
106 caps = MPEG2_ACCEL_X86_MMX;
107 if (edx & 0x02000000) /* SSE - identical to AMD MMX extensions */
108 caps = MPEG2_ACCEL_X86_MMX | MPEG2_ACCEL_X86_MMXEXT;
110 cpuid (0x80000000, eax, ebx, ecx, edx);
111 if (eax < 0x80000001) /* no extended capabilities */
112 return caps;
114 cpuid (0x80000001, eax, ebx, ecx, edx);
116 if (edx & 0x80000000)
117 caps |= MPEG2_ACCEL_X86_3DNOW;
119 if (AMD && (edx & 0x00400000)) /* AMD MMX extensions */
120 caps |= MPEG2_ACCEL_X86_MMXEXT;
122 return caps;
123 #else /* USE_MPLAYER_CPUDETECT: Use MPlayer's CPU capability property. */
124 caps = 0;
125 if (gCpuCaps.hasMMX)
126 caps |= MPEG2_ACCEL_X86_MMX;
127 if (gCpuCaps.hasSSE2)
128 caps |= MPEG2_ACCEL_X86_SSE2;
129 if (gCpuCaps.hasMMX2)
130 caps |= MPEG2_ACCEL_X86_MMXEXT;
131 if (gCpuCaps.has3DNow)
132 caps |= MPEG2_ACCEL_X86_3DNOW;
134 return caps;
136 #endif /* USE_MPLAYER_CPUDETECT */
138 #endif /* ARCH_X86 || ARCH_X86_64 */
140 #if defined(ARCH_PPC) || defined(ARCH_SPARC)
141 #include <signal.h>
142 #include <setjmp.h>
144 static sigjmp_buf jmpbuf;
145 static volatile sig_atomic_t canjump = 0;
147 static RETSIGTYPE sigill_handler (int sig)
149 if (!canjump) {
150 signal (sig, SIG_DFL);
151 raise (sig);
154 canjump = 0;
155 siglongjmp (jmpbuf, 1);
158 #ifdef ARCH_PPC
159 static uint32_t arch_accel (void)
161 static RETSIGTYPE (* oldsig) (int);
163 oldsig = signal (SIGILL, sigill_handler);
164 if (sigsetjmp (jmpbuf, 1)) {
165 signal (SIGILL, oldsig);
166 return 0;
169 canjump = 1;
171 #if defined(__APPLE_CC__) /* apple */
172 #define VAND(a,b,c) "vand v" #a ",v" #b ",v" #c "\n\t"
173 #else /* gnu */
174 #define VAND(a,b,c) "vand " #a "," #b "," #c "\n\t"
175 #endif
176 asm volatile ("mtspr 256, %0\n\t"
177 VAND (0, 0, 0)
179 : "r" (-1));
181 canjump = 0;
183 signal (SIGILL, oldsig);
184 return MPEG2_ACCEL_PPC_ALTIVEC;
186 #endif /* ARCH_PPC */
188 #ifdef ARCH_SPARC
189 static uint32_t arch_accel (void)
191 static RETSIGTYPE (* oldsig) (int);
193 oldsig = signal (SIGILL, sigill_handler);
194 if (sigsetjmp (jmpbuf, 1)) {
195 signal (SIGILL, oldsig);
196 return 0;
199 canjump = 1;
201 /* pdist %f0, %f0, %f0 */
202 __asm__ __volatile__(".word\t0x81b007c0");
204 canjump = 0;
206 if (sigsetjmp (jmpbuf, 1)) {
207 signal (SIGILL, oldsig);
208 return MPEG2_ACCEL_SPARC_VIS;
211 canjump = 1;
213 /* edge8n %g0, %g0, %g0 */
214 __asm__ __volatile__(".word\t0x81b00020");
216 canjump = 0;
218 signal (SIGILL, oldsig);
219 return MPEG2_ACCEL_SPARC_VIS | MPEG2_ACCEL_SPARC_VIS2;
221 #endif /* ARCH_SPARC */
222 #endif /* ARCH_PPC || ARCH_SPARC */
224 #ifdef ARCH_ALPHA
225 static uint32_t arch_accel (void)
227 uint64_t no_mvi;
229 asm volatile ("amask %1, %0"
230 : "=r" (no_mvi)
231 : "rI" (256)); /* AMASK_MVI */
232 return no_mvi ? MPEG2_ACCEL_ALPHA : (MPEG2_ACCEL_ALPHA |
233 MPEG2_ACCEL_ALPHA_MVI);
235 #endif /* ARCH_ALPHA */
236 #endif /* ACCEL_DETECT */
238 uint32_t mpeg2_detect_accel (void)
240 uint32_t accel;
242 accel = 0;
243 #ifdef ACCEL_DETECT
244 #if defined (ARCH_X86) || defined (ARCH_X86_64) || defined (ARCH_PPC) || defined (ARCH_ALPHA) || defined (ARCH_SPARC)
245 accel = arch_accel ();
246 #endif
247 #endif
248 return accel;