]> git.sesse.net Git - vlc/blob - src/ac3_decoder/ac3_srfft_sse.c
8f5294631c2834328815ab8beae8ad04f8774248
[vlc] / src / ac3_decoder / ac3_srfft_sse.c
1 /*****************************************************************************
2  * ac3_srfft_sse.c: ac3 fft functions
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  * $Id: ac3_srfft_sse.c,v 1.1 2001/05/14 15:58:04 reno Exp $
6  *
7  * Authors: Renaud Dartus <reno@videolan.org>
8  *          Aaron Holtzman <aholtzma@engr.uvic.ca>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 #include <stdio.h>
26
27 #include "defs.h"
28
29 #include <math.h>
30 #include <stdio.h>
31
32 #include "config.h"
33 #include "common.h"
34 #include "threads.h"
35 #include "mtime.h"
36
37 #include "stream_control.h"
38 #include "input_ext-dec.h"
39
40 #include "ac3_decoder.h"
41 #include "ac3_srfft.h"
42
43 void hsqrt2 (void);
44 void C_1 (void);
45 static void fft_4_sse (complex_t *x);
46 static void fft_8_sse (complex_t *x);
47 static void fft_asmb_sse (int k, complex_t *x, complex_t *wTB,
48              const complex_t *d, const complex_t *d_3);
49
50 void fft_64p_sse(complex_t *a)
51 {
52         fft_8_sse(&a[0]); fft_4_sse(&a[8]); fft_4_sse(&a[12]);
53         fft_asmb_sse(2, &a[0], &a[8], &delta16[0], &delta16_3[0]);
54   
55         fft_8_sse(&a[16]), fft_8_sse(&a[24]);
56         fft_asmb_sse(4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
57
58         fft_8_sse(&a[32]); fft_4_sse(&a[40]); fft_4_sse(&a[44]);
59         fft_asmb_sse(2, &a[32], &a[40], &delta16[0], &delta16_3[0]);
60
61         fft_8_sse(&a[48]); fft_4_sse(&a[56]); fft_4_sse(&a[60]);
62         fft_asmb_sse(2, &a[48], &a[56], &delta16[0], &delta16_3[0]);
63
64         fft_asmb_sse(8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
65 }
66
67
68 void fft_128p_sse(complex_t *a)
69 {
70         fft_8_sse(&a[0]); fft_4_sse(&a[8]); fft_4_sse(&a[12]);
71         fft_asmb_sse(2, &a[0], &a[8], &delta16[0], &delta16_3[0]);
72   
73         fft_8_sse(&a[16]), fft_8_sse(&a[24]);
74         fft_asmb_sse(4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
75
76         fft_8_sse(&a[32]); fft_4_sse(&a[40]); fft_4_sse(&a[44]);
77         fft_asmb_sse(2, &a[32], &a[40], &delta16[0], &delta16_3[0]);
78
79         fft_8_sse(&a[48]); fft_4_sse(&a[56]); fft_4_sse(&a[60]);
80         fft_asmb_sse(2, &a[48], &a[56], &delta16[0], &delta16_3[0]);
81
82         fft_asmb_sse(8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
83
84         fft_8_sse(&a[64]); fft_4_sse(&a[72]); fft_4_sse(&a[76]);
85         /* fft_16(&a[64]); */
86         fft_asmb_sse(2, &a[64], &a[72], &delta16[0], &delta16_3[0]);
87
88         fft_8_sse(&a[80]); fft_8_sse(&a[88]);
89   
90         /* fft_32(&a[64]); */
91         fft_asmb_sse(4, &a[64], &a[80],&delta32[0], &delta32_3[0]);
92
93         fft_8_sse(&a[96]); fft_4_sse(&a[104]), fft_4_sse(&a[108]);
94         /* fft_16(&a[96]); */
95         fft_asmb_sse(2, &a[96], &a[104], &delta16[0], &delta16_3[0]);
96
97         fft_8_sse(&a[112]), fft_8_sse(&a[120]);
98         /* fft_32(&a[96]); */
99         fft_asmb_sse(4, &a[96], &a[112], &delta32[0], &delta32_3[0]);
100   
101         /* fft_128(&a[0]); */
102         fft_asmb_sse(16, &a[0], &a[64], &delta128[0], &delta128_3[0]);
103 }
104
105 void hsqrt2 (void)
106 {
107     __asm__ (
108      ".float 0f0.707106781188\n"
109          ".float 0f0.707106781188\n"
110          ".float 0f-0.707106781188\n"
111          ".float 0f-0.707106781188\n"
112      );
113 }
114
115 void C_1 (void)
116 {
117     __asm__ (
118      ".float 0f-1.0\n"
119          ".float 0f1.0\n"
120          ".float 0f-1.0\n"
121          ".float 0f1.0\n"
122      );
123 }
124
125 static void fft_4_sse (complex_t *x)
126 {
127     __asm__ __volatile__ (
128         "movups   (%%eax), %%xmm0\n"    /* x[1] | x[0] */
129         "movups 16(%%eax), %%xmm2\n"    /* x[3] | x[2] */
130         "movups  %%xmm0, %%xmm1\n"              /* x[1] | x[0] */
131         "addps   %%xmm2, %%xmm0\n"              /* x[1] + x[3] | x[0] + x[2] */
132         "subps   %%xmm2, %%xmm1\n"              /* x[1] - x[3] | x[0] - x[2] */
133         "xorps   %%xmm6, %%xmm6\n"
134         "movhlps %%xmm1, %%xmm4\n"              /* ? | x[1] - x[3] */
135         "movhlps %%xmm0, %%xmm3\n"              /* ? | x[1] + x[3] */
136         "subss   %%xmm4, %%xmm6\n"              /* 0 | -(x[1] - x[3]).re */
137         "movlhps %%xmm1, %%xmm0\n"              /* x[0] - x[2] | x[0] + x[2] */
138     "movlhps %%xmm6, %%xmm4\n"          /* 0 | -(x[1] - x[3]).re | (x[1] - x[3]).im | (x[3]-x[1]).re */
139         "movups  %%xmm0, %%xmm2\n"              /* x[0] - x[2] | x[0] + x[2] */
140         "shufps   $0x94, %%xmm4, %%xmm3\n" /* i*(x[1] - x[3]) | x[1] + x[3] */
141     "addps   %%xmm3, %%xmm0\n"
142         "subps   %%xmm3, %%xmm2\n"
143         "movups  %%xmm0,   (%%eax)\n"
144         "movups  %%xmm2, 16(%%eax)\n"
145     : "=a" (x)
146     : "a" (x) );
147 }
148
149 static void fft_8_sse (complex_t *x)
150 {
151     __asm__ __volatile__ (
152         "pushl   %%ebx\n"
153     
154         "movlps   (%%eax), %%xmm0\n"    /* x[0] */
155         "movlps 32(%%eax), %%xmm1\n"    /* x[4] */
156         "movhps 16(%%eax), %%xmm0\n"    /* x[2] | x[0] */
157         "movhps 48(%%eax), %%xmm1\n"    /* x[6] | x[4] */
158         "movups  %%xmm0, %%xmm2\n"          /* x[2] | x[0] */
159         "xorps   %%xmm3, %%xmm3\n"
160     "addps   %%xmm1, %%xmm0\n"      /* x[2] + x[6] | x[0] + x[4] */
161         "subps   %%xmm1, %%xmm2\n"      /* x[2] - x[6] | x[0] - x[4] */
162         "movhlps %%xmm0, %%xmm5\n"              /* x[2] + x[6] */
163         "movhlps %%xmm2, %%xmm4\n"      /* x[2] - x[6] */
164     "movlhps %%xmm2, %%xmm0\n"      /* x[0] - x[4] | x[0] + x[4] */
165         "subss   %%xmm4, %%xmm3\n"          /* (x[2]-x[6]).im | -(x[2]-x[6]).re */
166         "movups  %%xmm0, %%xmm7\n"          /* x[0] - x[4] | x[0] + x[4] */
167         "movups  %%xmm3, %%xmm4\n"          /* (x[2]-x[6]).im | -(x[2]-x[6]).re */
168         "movlps 8(%%eax), %%xmm1\n"         /* x[1] */
169         "shufps   $0x14, %%xmm4, %%xmm5\n" /* i*(x[2] - x[6]) | x[2] + x[6] */
170
171         "addps   %%xmm5, %%xmm0\n"              /* yt = i*(x2-x6)+x0-x4 | x2+x6+x0+x4 */
172         "subps   %%xmm5, %%xmm7\n"              /* yb = i*(x6-x2)+x0-x4 | -x6-x2+x0+x4 */
173
174         "movhps 24(%%eax), %%xmm1\n"    /* x[3] | x[1] */
175     "movl   $hsqrt2, %%ebx\n"
176         "movlps 40(%%eax), %%xmm2\n"    /* x[5] */
177         "movhps 56(%%eax), %%xmm2\n"    /* x[7] | x[5] */
178         "movups  %%xmm1, %%xmm3\n"              /* x[3] | x[1] */
179         "addps   %%xmm2, %%xmm1\n"              /* x[3] + x[7] | x[1] + x[5] */
180         "subps   %%xmm2, %%xmm3\n"              /* x[3] - x[7] | x[1] - x[5] */
181         "movups (%%ebx), %%xmm4\n"              /* -1/sqrt2 | -1/sqrt2 | 1/sqrt2 | 1/sqrt2 */
182         "movups  %%xmm3, %%xmm6\n"              /* x[3] - x[7] | x[1] - x[5] */
183         "mulps   %%xmm4, %%xmm3\n"      /* -1/s2*(x[3] - x[7]) | 1/s2*(x[1] - x[5]) */
184         "shufps   $0xc8, %%xmm4, %%xmm4\n" /* -1/sqrt2 | 1/sqrt2 | -1/sqrt2 | 1/sqrt2 */
185         "shufps   $0xb1, %%xmm6, %%xmm6\n" /* (x3-x7).re|(x3-x7).im|(x1-x5).re|(x1-x5).im */
186         "mulps   %%xmm4, %%xmm6\n"      /* (x7-x3).re/s2|(x3-x7).im/s2|(x5-x1).re/s2|(x1-x5).im/s2 */
187         "addps   %%xmm3, %%xmm6\n"              /* (-1-i)/sqrt2 * (x[3]-x[7]) | (1-i)/sqrt2 * (x[1] - x[5]) */
188         "movhlps %%xmm1, %%xmm5\n"              /* x[3] + x[7] */
189         "movlhps %%xmm6, %%xmm1\n"              /* (1+i)/sqrt2 * (x[1]-x[5]) | x[1]+x[5] */
190         "shufps   $0xe4, %%xmm6, %%xmm5\n"      /* (-1-i)/sqrt2 * (x[3]-x[7]) | x[3]+x[7] */
191         "movups  %%xmm1, %%xmm3\n"              /* (1-i)/sqrt2 * (x[1]-x[5]) | x[1]+x[5] */
192         "movl      $C_1, %%ebx\n"
193         "addps   %%xmm5, %%xmm1\n"              /* u */
194         "subps   %%xmm5, %%xmm3\n"              /* v */
195         "movups  %%xmm0, %%xmm2\n"              /* yb */
196         "movups  %%xmm7, %%xmm4\n"              /* yt */
197         "movups (%%ebx), %%xmm5\n"
198         "mulps   %%xmm5, %%xmm3\n"
199         "addps   %%xmm1, %%xmm0\n"              /* yt + u */
200         "subps   %%xmm1, %%xmm2\n"              /* yt - u */
201         "shufps   $0xb1, %%xmm3, %%xmm3\n" /* -i * v */
202         "movups  %%xmm0, (%%eax)\n"
203         "movups  %%xmm2, 32(%%eax)\n"
204         "addps   %%xmm3, %%xmm4\n"              /* yb - i*v */
205         "subps   %%xmm3, %%xmm7\n"              /* yb + i*v */
206         "movups  %%xmm4, 16(%%eax)\n"
207         "movups  %%xmm7, 48(%%eax)\n"
208
209         "popl    %%ebx\n"
210     : "=a" (x)
211     : "a" (x));
212 }
213
214     
215 static void fft_asmb_sse (int k, complex_t *x, complex_t *wTB,
216              const complex_t *d, const complex_t *d_3)
217 {
218     __asm__ __volatile__ (
219         "pushl %%ebp\n"
220         "movl %%esp, %%ebp\n"
221
222         "subl $4, %%esp\n"
223         
224         "pushl %%eax\n"
225         "pushl %%ebx\n"
226         "pushl %%ecx\n"
227         "pushl %%edx\n"
228         "pushl %%esi\n"
229         "pushl %%edi\n"
230
231         "movl  8(%%ebp), %%ecx\n"   /* k */
232         "movl 12(%%ebp), %%eax\n"   /* x */
233         "movl %%ecx, -4(%%ebp)\n"   /* k */
234         "movl 16(%%ebp), %%ebx\n"   /* wT */
235         "movl 20(%%ebp), %%edx\n"   /* d */
236         "movl 24(%%ebp), %%esi\n"   /* d3 */
237         "shll $4, %%ecx\n"          /* 16k */
238         "addl $8, %%edx\n"
239         "leal (%%eax, %%ecx, 2), %%edi\n"
240         "addl $8, %%esi\n"
241         
242         /* TRANSZERO and TRANS */
243         "movups (%%eax), %%xmm0\n"      /* x[1] | x[0] */
244         "movups (%%ebx), %%xmm1\n"      /* wT[1] | wT[0] */
245         "movups (%%ebx, %%ecx), %%xmm2\n" /* wB[1] | wB[0] */
246         "movlps (%%edx), %%xmm3\n"      /* d */
247         "movlps (%%esi), %%xmm4\n"      /* d3 */
248         "movhlps %%xmm1, %%xmm5\n"      /* wT[1] */
249         "movhlps %%xmm2, %%xmm6\n"      /* wB[1] */
250         "shufps $0x50, %%xmm3, %%xmm3\n" /* d[1].im | d[1].im | d[1].re | d[1].re */
251         "shufps $0x50, %%xmm4, %%xmm4\n" /* d3[1].im | d3[1].im | d3[i].re | d3[i].re */
252         "movlhps %%xmm5, %%xmm5\n"      /* wT[1] | wT[1] */
253         "movlhps %%xmm6, %%xmm6\n"      /* wB[1] | wB[1] */
254         "mulps   %%xmm3, %%xmm5\n"
255         "mulps   %%xmm4, %%xmm6\n"
256         "movhlps %%xmm5, %%xmm7\n"      /* wT[1].im * d[1].im | wT[1].re * d[1].im */
257         "movlhps %%xmm6, %%xmm5\n"      /* wB[1].im * d3[1].re | wB[1].re * d3[1].re | wT[1].im * d[1].re | wT[1].re * d[1].re */
258         "shufps $0xb1, %%xmm6, %%xmm7\n" /* wB[1].re * d3[1].im | wB[i].im * d3[1].im | wT[1].re * d[1].im | wT[1].im * d[1].im */
259         "movl $C_1, %%edi\n"
260         "movups (%%edi), %%xmm4\n"
261         "mulps   %%xmm4, %%xmm7\n"
262         "addps   %%xmm7, %%xmm5\n"      /* wB[1] * d3[1] | wT[1] * d[1] */
263         "movlhps %%xmm5, %%xmm1\n"      /* d[1] * wT[1] | wT[0] */
264         "shufps  $0xe4, %%xmm5, %%xmm2\n" /* d3[1] * wB[1] | wB[0] */
265         "movups  %%xmm1, %%xmm3\n"      /* d[1] * wT[1] | wT[0] */
266         "leal   (%%eax, %%ecx, 2), %%edi\n"
267         "addps  %%xmm2, %%xmm1\n"       /* u */
268         "subps  %%xmm2, %%xmm3\n"       /* v */
269         "mulps  %%xmm4, %%xmm3\n"
270         "movups (%%eax, %%ecx), %%xmm5\n" /* xk[1] | xk[0] */
271         "shufps $0xb1, %%xmm3, %%xmm3\n"  /* -i * v */
272         "movups %%xmm0, %%xmm2\n"         /* x[1] | x[0] */
273         "movups %%xmm5, %%xmm6\n"         /* xk[1] | xk[0] */
274         "addps  %%xmm1, %%xmm0\n"
275         "subps  %%xmm1, %%xmm2\n"
276         "addps  %%xmm3, %%xmm5\n"
277         "subps  %%xmm3, %%xmm6\n"
278         "movups %%xmm0, (%%eax)\n"
279         "movups %%xmm2, (%%edi)\n"
280         "movups %%xmm5, (%%eax, %%ecx)\n"
281         "movups %%xmm6, (%%edi, %%ecx)\n"
282         "addl $16, %%eax\n"
283         "addl $16, %%ebx\n"
284         "addl  $8, %%edx\n"
285         "addl  $8, %%esi\n"
286         "decl -4(%%ebp)\n"
287
288 ".loop:\n"
289         "movups (%%ebx), %%xmm0\n"      /* wT[1] | wT[0] */
290         "movups (%%edx), %%xmm1\n"      /* d[1] | d[0] */
291
292         "movups (%%ebx, %%ecx), %%xmm4\n" /* wB[1] | wB[0] */
293         "movups (%%esi), %%xmm5\n"      /* d3[1] | d3[0] */
294
295         "movhlps %%xmm0, %%xmm2\n"      /* wT[1] */
296         "movhlps %%xmm1, %%xmm3\n"      /* d[1] */
297
298         "movhlps %%xmm4, %%xmm6\n"      /* wB[1] */
299         "movhlps %%xmm5, %%xmm7\n"      /* d3[1] */
300
301         "shufps $0x50, %%xmm1, %%xmm1\n" /* d[0].im | d[0].im | d[0].re | d[0].re */
302         "shufps $0x50, %%xmm3, %%xmm3\n" /* d[1].im | d[1].im | d[1].re | d[1].re */
303
304         "movlhps %%xmm0, %%xmm0\n"       /* wT[0] | wT[0] */
305         "shufps $0x50, %%xmm5, %%xmm5\n" /* d3[0].im | d3[0].im | d3[0].re | d3[0].re */
306         "movlhps %%xmm2, %%xmm2\n"       /* wT[1] | wT[1] */
307         "shufps $0x50, %%xmm7, %%xmm7\n" /* d3[1].im | d3[1].im | d3[1].re | d3[1].re */
308
309         "mulps   %%xmm1, %%xmm0\n"  /* d[0].im * wT[0].im | d[0].im * wT[0].re | d[0].re * wT[0].im | d[0].re * wT[0].re */
310         "mulps   %%xmm3, %%xmm2\n"  /* d[1].im * wT[1].im | d[1].im * wT[1].re | d[1].re * wT[1].im | d[1].re * wT[1].re */
311         "movlhps %%xmm4, %%xmm4\n"  /* wB[0] | wB[0] */
312         "movlhps %%xmm6, %%xmm6\n"  /* wB[1] | wB[1] */
313     
314         "movhlps %%xmm0, %%xmm1\n"  /* d[0].im * wT[0].im | d[0].im * wT[0].re */
315         "movlhps %%xmm2, %%xmm0\n"  /* d[1].re * wT[1].im | d[1].re * wT[1].re | d[0].re * wT[0].im | d[0].re * wT[0].re */
316         "mulps   %%xmm5, %%xmm4\n"  /* wB[0].im * d3[0].im | wB[0].re * d3[0].im | wB[0].im * d3[0].re | wB[0].re * d3[0].re */
317         "mulps   %%xmm7, %%xmm6\n"  /* wB[1].im * d3[1].im | wB[1].re * d3[1].im | wB[1].im * d3[1].re | wB[1].re * d3[1].re */
318         "shufps $0xb1, %%xmm2, %%xmm1\n"    /* d[1].im * wT[1].re | d[1].im * wT[1].im | d[0].im * wT[0].re | d[0].im * wT[0].im */
319         "movl $C_1, %%edi\n"
320         "movups (%%edi), %%xmm3\n"  /* 1.0 | -1.0 | 1.0 | -1.0 */
321
322         "movhlps %%xmm4, %%xmm5\n"  /* wB[0].im * d3[0].im | wB[0].re * d3[0].im */
323         "mulps   %%xmm3, %%xmm1\n"  /* d[1].im * wT[1].re | -d[1].im * wT[1].im | d[0].im * wT[0].re | -d[0].im * wT[0].im */
324         "movlhps %%xmm6, %%xmm4\n"  /* wB[1].im * d3[1].re | wB[1].re * d3[1].re | wB[0].im * d3[0].re | wB[0].im * d3[0].re */
325         "addps   %%xmm1, %%xmm0\n"  /* wT[1] * d[1] | wT[0] * d[0] */
326
327         "shufps $0xb1, %%xmm6, %%xmm5\n"    /* wB[1].re * d3[1].im | wB[1].im * d3[1].im | wB[0].re * d3[0].im | wB[0].im * d3[0].im */
328         "mulps   %%xmm3, %%xmm5\n"  /* wB[1].re * d3[1].im | -wB[1].im * d3[1].im | wB[0].re * d3[0].im | -wB[0].im * d3[0].im */
329         "addps   %%xmm5, %%xmm4\n"  /* wB[1] * d3[1] | wB[0] * d3[0] */
330
331         "movups %%xmm0, %%xmm1\n"   /* wT[1] * d[1] | wT[0] * d[0] */
332         "addps  %%xmm4, %%xmm0\n"   /* u */
333         "subps  %%xmm4, %%xmm1\n"   /* v */
334         "movups (%%eax), %%xmm6\n"  /* x[1] | x[0] */
335         "leal   (%%eax, %%ecx, 2), %%edi\n"
336         "mulps  %%xmm3, %%xmm1\n"
337         "addl $16, %%ebx\n"
338         "addl $16, %%esi\n"
339         "shufps $0xb1, %%xmm1, %%xmm1\n"    /* -i * v */
340         "movups (%%eax, %%ecx), %%xmm7\n"   /* xk[1] | xk[0] */
341         "movups %%xmm6, %%xmm2\n"
342         "movups %%xmm7, %%xmm4\n"
343         "addps  %%xmm0, %%xmm6\n"
344         "subps  %%xmm0, %%xmm2\n"
345         "movups %%xmm6, (%%eax)\n"
346         "movups %%xmm2, (%%edi)\n"
347         "addps  %%xmm1, %%xmm7\n"
348         "subps  %%xmm1, %%xmm4\n"
349         "addl $16, %%edx\n"
350         "movups %%xmm7, (%%eax, %%ecx)\n"
351         "movups %%xmm4, (%%edi, %%ecx)\n"
352
353         "addl $16, %%eax\n"
354         "decl -4(%%ebp)\n"
355         "jnz .loop\n"
356
357 ".end:\n"
358         "popl %%edi\n"
359         "popl %%esi\n"
360         "popl %%edx\n"
361         "popl %%ecx\n"
362         "popl %%ebx\n"
363         "popl %%eax\n"
364         
365         "addl $4, %%esp\n"
366
367     "leave\n"
368     ::);
369 }