9857
|
1 /*
|
|
2 * cpu_accel.c
|
10303
|
3 * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
9857
|
4 * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
|
5 *
|
|
6 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
|
|
7 * See http://libmpeg2.sourceforge.net/ for updates.
|
|
8 *
|
|
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.
|
|
13 *
|
|
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.
|
|
18 *
|
|
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
|
|
22 */
|
|
23
|
|
24 #include "config.h"
|
|
25
|
|
26 #include <inttypes.h>
|
|
27
|
|
28 #include "mpeg2.h"
|
12932
|
29 #include "attributes.h"
|
|
30 #include "mpeg2_internal.h"
|
9857
|
31
|
|
32 #ifdef ACCEL_DETECT
|
|
33 #ifdef ARCH_X86
|
|
34 static inline uint32_t arch_accel (void)
|
|
35 {
|
|
36 uint32_t eax, ebx, ecx, edx;
|
|
37 int AMD;
|
|
38 uint32_t caps;
|
|
39
|
12932
|
40 #if !defined(PIC) && !defined(__PIC__)
|
9857
|
41 #define cpuid(op,eax,ebx,ecx,edx) \
|
|
42 __asm__ ("cpuid" \
|
|
43 : "=a" (eax), \
|
|
44 "=b" (ebx), \
|
|
45 "=c" (ecx), \
|
|
46 "=d" (edx) \
|
|
47 : "a" (op) \
|
|
48 : "cc")
|
|
49 #else /* PIC version : save ebx */
|
|
50 #define cpuid(op,eax,ebx,ecx,edx) \
|
|
51 __asm__ ("push %%ebx\n\t" \
|
|
52 "cpuid\n\t" \
|
|
53 "movl %%ebx,%1\n\t" \
|
|
54 "pop %%ebx" \
|
|
55 : "=a" (eax), \
|
|
56 "=r" (ebx), \
|
|
57 "=c" (ecx), \
|
|
58 "=d" (edx) \
|
|
59 : "a" (op) \
|
|
60 : "cc")
|
|
61 #endif
|
|
62
|
|
63 __asm__ ("pushf\n\t"
|
|
64 "pushf\n\t"
|
|
65 "pop %0\n\t"
|
|
66 "movl %0,%1\n\t"
|
|
67 "xorl $0x200000,%0\n\t"
|
|
68 "push %0\n\t"
|
|
69 "popf\n\t"
|
|
70 "pushf\n\t"
|
|
71 "pop %0\n\t"
|
|
72 "popf"
|
|
73 : "=r" (eax),
|
|
74 "=r" (ebx)
|
|
75 :
|
|
76 : "cc");
|
|
77
|
|
78 if (eax == ebx) /* no cpuid */
|
|
79 return 0;
|
|
80
|
|
81 cpuid (0x00000000, eax, ebx, ecx, edx);
|
|
82 if (!eax) /* vendor string only */
|
|
83 return 0;
|
|
84
|
|
85 AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
|
|
86
|
|
87 cpuid (0x00000001, eax, ebx, ecx, edx);
|
|
88 if (! (edx & 0x00800000)) /* no MMX */
|
|
89 return 0;
|
|
90
|
|
91 caps = MPEG2_ACCEL_X86_MMX;
|
|
92 if (edx & 0x02000000) /* SSE - identical to AMD MMX extensions */
|
|
93 caps = MPEG2_ACCEL_X86_MMX | MPEG2_ACCEL_X86_MMXEXT;
|
|
94
|
|
95 cpuid (0x80000000, eax, ebx, ecx, edx);
|
|
96 if (eax < 0x80000001) /* no extended capabilities */
|
|
97 return caps;
|
|
98
|
|
99 cpuid (0x80000001, eax, ebx, ecx, edx);
|
|
100
|
|
101 if (edx & 0x80000000)
|
|
102 caps |= MPEG2_ACCEL_X86_3DNOW;
|
|
103
|
|
104 if (AMD && (edx & 0x00400000)) /* AMD MMX extensions */
|
|
105 caps |= MPEG2_ACCEL_X86_MMXEXT;
|
|
106
|
|
107 return caps;
|
|
108 }
|
|
109 #endif /* ARCH_X86 */
|
|
110
|
12932
|
111 #if defined(ARCH_PPC) || defined(ARCH_SPARC)
|
9857
|
112 #include <signal.h>
|
|
113 #include <setjmp.h>
|
|
114
|
|
115 static sigjmp_buf jmpbuf;
|
|
116 static volatile sig_atomic_t canjump = 0;
|
|
117
|
|
118 static RETSIGTYPE sigill_handler (int sig)
|
|
119 {
|
|
120 if (!canjump) {
|
|
121 signal (sig, SIG_DFL);
|
|
122 raise (sig);
|
|
123 }
|
|
124
|
|
125 canjump = 0;
|
|
126 siglongjmp (jmpbuf, 1);
|
|
127 }
|
|
128
|
12932
|
129 #ifdef ARCH_PPC
|
9857
|
130 static inline uint32_t arch_accel (void)
|
|
131 {
|
10303
|
132 static RETSIGTYPE (* oldsig) (int);
|
|
133
|
|
134 oldsig = signal (SIGILL, sigill_handler);
|
9857
|
135 if (sigsetjmp (jmpbuf, 1)) {
|
10303
|
136 signal (SIGILL, oldsig);
|
9857
|
137 return 0;
|
|
138 }
|
|
139
|
|
140 canjump = 1;
|
|
141
|
10303
|
142 #ifdef HAVE_ALTIVEC_H /* gnu */
|
|
143 #define VAND(a,b,c) "vand " #a "," #b "," #c "\n\t"
|
|
144 #else /* apple */
|
|
145 #define VAND(a,b,c) "vand v" #a ",v" #b ",v" #c "\n\t"
|
|
146 #endif
|
9857
|
147 asm volatile ("mtspr 256, %0\n\t"
|
10303
|
148 VAND (0, 0, 0)
|
9857
|
149 :
|
|
150 : "r" (-1));
|
|
151
|
12932
|
152 canjump = 0;
|
|
153
|
10303
|
154 signal (SIGILL, oldsig);
|
9857
|
155 return MPEG2_ACCEL_PPC_ALTIVEC;
|
|
156 }
|
|
157 #endif /* ARCH_PPC */
|
|
158
|
12932
|
159 #ifdef ARCH_SPARC
|
|
160 static inline uint32_t arch_accel (void)
|
|
161 {
|
|
162 static RETSIGTYPE (* oldsig) (int);
|
|
163
|
|
164 oldsig = signal (SIGILL, sigill_handler);
|
|
165 if (sigsetjmp (jmpbuf, 1)) {
|
|
166 signal (SIGILL, oldsig);
|
|
167 return 0;
|
|
168 }
|
|
169
|
|
170 canjump = 1;
|
|
171
|
|
172 /* pdist %f0, %f0, %f0 */
|
|
173 __asm__ __volatile__(".word\t0x81b007c0");
|
|
174
|
|
175 canjump = 0;
|
|
176
|
|
177 if (sigsetjmp (jmpbuf, 1)) {
|
|
178 signal (SIGILL, oldsig);
|
|
179 return MPEG2_ACCEL_SPARC_VIS;
|
|
180 }
|
|
181
|
|
182 canjump = 1;
|
|
183
|
|
184 /* edge8n %g0, %g0, %g0 */
|
|
185 __asm__ __volatile__(".word\t0x81b00020");
|
|
186
|
|
187 canjump = 0;
|
|
188
|
|
189 signal (SIGILL, oldsig);
|
|
190 return MPEG2_ACCEL_SPARC_VIS | MPEG2_ACCEL_SPARC_VIS2;
|
|
191 }
|
|
192 #endif /* ARCH_SPARC */
|
|
193 #endif /* ARCH_PPC || ARCH_SPARC */
|
|
194
|
9857
|
195 #ifdef ARCH_ALPHA
|
|
196 static inline uint32_t arch_accel (void)
|
|
197 {
|
10488
|
198 #ifdef CAN_COMPILE_ALPHA_MVI
|
9857
|
199 uint64_t no_mvi;
|
|
200
|
|
201 asm volatile ("amask %1, %0"
|
|
202 : "=r" (no_mvi)
|
|
203 : "rI" (256)); /* AMASK_MVI */
|
|
204 return no_mvi ? MPEG2_ACCEL_ALPHA : (MPEG2_ACCEL_ALPHA |
|
|
205 MPEG2_ACCEL_ALPHA_MVI);
|
10488
|
206 #else
|
|
207 return MPEG2_ACCEL_ALPHA;
|
|
208 #endif
|
9857
|
209 }
|
|
210 #endif /* ARCH_ALPHA */
|
12932
|
211 #endif /* ACCEL_DETECT */
|
9857
|
212
|
|
213 uint32_t mpeg2_detect_accel (void)
|
|
214 {
|
|
215 uint32_t accel;
|
|
216
|
|
217 accel = 0;
|
|
218 #ifdef ACCEL_DETECT
|
12932
|
219 #if defined (ARCH_X86) || defined (ARCH_PPC) || defined (ARCH_ALPHA) || defined (ARCH_SPARC)
|
|
220 accel = arch_accel ();
|
9857
|
221 #endif
|
|
222 #endif
|
|
223 return accel;
|
|
224 }
|