Mercurial > mplayer.hg
annotate libmpeg2/cpu_accel.c @ 19564:797ee556b564
sync with r19561
patch by Savchenko Andrew % Bircoph A list.ru %
author | gpoirier |
---|---|
date | Mon, 28 Aug 2006 15:39:32 +0000 |
parents | 0783dd397f74 |
children | 60a39d71e247 |
rev | line source |
---|---|
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 | |
14732
1385ec491ffb
Mark locally modified files as such to comply more closely with GPL 2a.
diego
parents:
13864
diff
changeset
|
22 * |
1385ec491ffb
Mark locally modified files as such to comply more closely with GPL 2a.
diego
parents:
13864
diff
changeset
|
23 * Modified for use with MPlayer, see libmpeg-0.4.0.diff for the exact changes. |
18783 | 24 * detailed changelog at http://svn.mplayerhq.hu/mplayer/trunk/ |
14732
1385ec491ffb
Mark locally modified files as such to comply more closely with GPL 2a.
diego
parents:
13864
diff
changeset
|
25 * $Id$ |
9857 | 26 */ |
27 | |
28 #include "config.h" | |
18727
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
29 #include "cpudetect.h" |
9857 | 30 |
31 #include <inttypes.h> | |
32 | |
33 #include "mpeg2.h" | |
12932 | 34 #include "attributes.h" |
35 #include "mpeg2_internal.h" | |
9857 | 36 |
37 #ifdef ACCEL_DETECT | |
13864 | 38 #if defined(ARCH_X86) || defined(ARCH_X86_64) |
18727
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
39 |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
40 /* MPlayer imports libmpeg2 as decoder, which detects MMX / 3DNow! |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
41 * instructions via assembly. However, it is regarded as duplicaed work |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
42 * in MPlayer, so that we enforce to use MPlayer's implementation. |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
43 */ |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
44 #define USE_MPLAYER_CPUDETECT |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
45 |
9857 | 46 static inline uint32_t arch_accel (void) |
47 { | |
18727
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
48 #if !defined(USE_MPLAYER_CPUDETECT) |
9857 | 49 uint32_t eax, ebx, ecx, edx; |
50 int AMD; | |
51 uint32_t caps; | |
52 | |
12932 | 53 #if !defined(PIC) && !defined(__PIC__) |
9857 | 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 */ | |
63 #define cpuid(op,eax,ebx,ecx,edx) \ | |
64 __asm__ ("push %%ebx\n\t" \ | |
65 "cpuid\n\t" \ | |
66 "movl %%ebx,%1\n\t" \ | |
67 "pop %%ebx" \ | |
68 : "=a" (eax), \ | |
69 "=r" (ebx), \ | |
70 "=c" (ecx), \ | |
71 "=d" (edx) \ | |
72 : "a" (op) \ | |
73 : "cc") | |
74 #endif | |
75 | |
76 __asm__ ("pushf\n\t" | |
77 "pushf\n\t" | |
78 "pop %0\n\t" | |
79 "movl %0,%1\n\t" | |
80 "xorl $0x200000,%0\n\t" | |
81 "push %0\n\t" | |
82 "popf\n\t" | |
83 "pushf\n\t" | |
84 "pop %0\n\t" | |
85 "popf" | |
86 : "=r" (eax), | |
87 "=r" (ebx) | |
88 : | |
89 : "cc"); | |
90 | |
91 if (eax == ebx) /* no cpuid */ | |
92 return 0; | |
93 | |
94 cpuid (0x00000000, eax, ebx, ecx, edx); | |
95 if (!eax) /* vendor string only */ | |
96 return 0; | |
97 | |
98 AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65); | |
99 | |
100 cpuid (0x00000001, eax, ebx, ecx, edx); | |
101 if (! (edx & 0x00800000)) /* no MMX */ | |
102 return 0; | |
103 | |
104 caps = MPEG2_ACCEL_X86_MMX; | |
105 if (edx & 0x02000000) /* SSE - identical to AMD MMX extensions */ | |
106 caps = MPEG2_ACCEL_X86_MMX | MPEG2_ACCEL_X86_MMXEXT; | |
107 | |
108 cpuid (0x80000000, eax, ebx, ecx, edx); | |
109 if (eax < 0x80000001) /* no extended capabilities */ | |
110 return caps; | |
111 | |
112 cpuid (0x80000001, eax, ebx, ecx, edx); | |
113 | |
114 if (edx & 0x80000000) | |
115 caps |= MPEG2_ACCEL_X86_3DNOW; | |
116 | |
117 if (AMD && (edx & 0x00400000)) /* AMD MMX extensions */ | |
118 caps |= MPEG2_ACCEL_X86_MMXEXT; | |
119 | |
120 return caps; | |
18727
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
121 #else /* USE_MPLAYER_CPUDETECT: Use MPlayer's cpu capability property */ |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
122 caps = 0; |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
123 if (gCpuCaps.hasMMX) |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
124 caps |= MPEG2_ACCEL_X86_MMX; |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
125 if (gCpuCaps.hasSSE2) |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
126 caps |= MPEG2_ACCEL_X86_SSE2; |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
127 if (gCpuCaps.hasMMX2) |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
128 caps |= MPEG2_ACCEL_X86_MMXEXT; |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
129 if (gCpuCaps.has3DNow) |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
130 caps |= MPEG2_ACCEL_X86_3DNOW; |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
131 |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
132 return caps; |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
133 |
24b2d27f2407
Use MPlayer's CPU detection module instead of libmpeg2's,
gpoirier
parents:
15483
diff
changeset
|
134 #endif /* USE_MPLAYER_CPUDETECT */ |
9857 | 135 } |
13864 | 136 #endif /* ARCH_X86 || ARCH_X86_64 */ |
9857 | 137 |
13018
adb93ef6b07f
Improved SPARC CPU detection and SPARC compilation fixes.
diego
parents:
12932
diff
changeset
|
138 #if defined(ARCH_PPC) || (defined(ARCH_SPARC) && defined(HAVE_VIS)) |
9857 | 139 #include <signal.h> |
140 #include <setjmp.h> | |
141 | |
142 static sigjmp_buf jmpbuf; | |
143 static volatile sig_atomic_t canjump = 0; | |
144 | |
145 static RETSIGTYPE sigill_handler (int sig) | |
146 { | |
147 if (!canjump) { | |
148 signal (sig, SIG_DFL); | |
149 raise (sig); | |
150 } | |
151 | |
152 canjump = 0; | |
153 siglongjmp (jmpbuf, 1); | |
154 } | |
155 | |
12932 | 156 #ifdef ARCH_PPC |
9857 | 157 static inline uint32_t arch_accel (void) |
158 { | |
10303 | 159 static RETSIGTYPE (* oldsig) (int); |
160 | |
161 oldsig = signal (SIGILL, sigill_handler); | |
9857 | 162 if (sigsetjmp (jmpbuf, 1)) { |
10303 | 163 signal (SIGILL, oldsig); |
9857 | 164 return 0; |
165 } | |
166 | |
167 canjump = 1; | |
168 | |
15483 | 169 #if defined( __APPLE_CC__ ) && defined( __APPLE_ALTIVEC__ ) /* apple */ |
170 #define VAND(a,b,c) "vand v" #a ",v" #b ",v" #c "\n\t" | |
171 #else /* gnu */ | |
10303 | 172 #define VAND(a,b,c) "vand " #a "," #b "," #c "\n\t" |
173 #endif | |
9857 | 174 asm volatile ("mtspr 256, %0\n\t" |
10303 | 175 VAND (0, 0, 0) |
9857 | 176 : |
177 : "r" (-1)); | |
178 | |
12932 | 179 canjump = 0; |
180 | |
10303 | 181 signal (SIGILL, oldsig); |
9857 | 182 return MPEG2_ACCEL_PPC_ALTIVEC; |
183 } | |
184 #endif /* ARCH_PPC */ | |
185 | |
12932 | 186 #ifdef ARCH_SPARC |
187 static inline uint32_t arch_accel (void) | |
188 { | |
189 static RETSIGTYPE (* oldsig) (int); | |
190 | |
191 oldsig = signal (SIGILL, sigill_handler); | |
192 if (sigsetjmp (jmpbuf, 1)) { | |
193 signal (SIGILL, oldsig); | |
194 return 0; | |
195 } | |
196 | |
197 canjump = 1; | |
198 | |
199 /* pdist %f0, %f0, %f0 */ | |
200 __asm__ __volatile__(".word\t0x81b007c0"); | |
201 | |
202 canjump = 0; | |
203 | |
204 if (sigsetjmp (jmpbuf, 1)) { | |
205 signal (SIGILL, oldsig); | |
206 return MPEG2_ACCEL_SPARC_VIS; | |
207 } | |
208 | |
209 canjump = 1; | |
210 | |
211 /* edge8n %g0, %g0, %g0 */ | |
212 __asm__ __volatile__(".word\t0x81b00020"); | |
213 | |
214 canjump = 0; | |
215 | |
216 signal (SIGILL, oldsig); | |
217 return MPEG2_ACCEL_SPARC_VIS | MPEG2_ACCEL_SPARC_VIS2; | |
218 } | |
219 #endif /* ARCH_SPARC */ | |
220 #endif /* ARCH_PPC || ARCH_SPARC */ | |
221 | |
9857 | 222 #ifdef ARCH_ALPHA |
223 static inline uint32_t arch_accel (void) | |
224 { | |
10488 | 225 #ifdef CAN_COMPILE_ALPHA_MVI |
9857 | 226 uint64_t no_mvi; |
227 | |
228 asm volatile ("amask %1, %0" | |
229 : "=r" (no_mvi) | |
230 : "rI" (256)); /* AMASK_MVI */ | |
231 return no_mvi ? MPEG2_ACCEL_ALPHA : (MPEG2_ACCEL_ALPHA | | |
232 MPEG2_ACCEL_ALPHA_MVI); | |
10488 | 233 #else |
234 return MPEG2_ACCEL_ALPHA; | |
235 #endif | |
9857 | 236 } |
237 #endif /* ARCH_ALPHA */ | |
12932 | 238 #endif /* ACCEL_DETECT */ |
9857 | 239 |
240 uint32_t mpeg2_detect_accel (void) | |
241 { | |
242 uint32_t accel; | |
243 | |
244 accel = 0; | |
245 #ifdef ACCEL_DETECT | |
13864 | 246 #if defined (ARCH_X86) || defined (ARCH_X86_64) || defined (ARCH_PPC) || defined (ARCH_ALPHA) || defined (ARCH_SPARC) |
12932 | 247 accel = arch_accel (); |
9857 | 248 #endif |
249 #endif | |
250 return accel; | |
251 } |