]> git.sesse.net Git - vlc/blob - plugins/imdct/ac3_srfft_sse.c
55f6a5bed28eaf6adc6ed83f97d65dce4a5a3cc4
[vlc] / plugins / imdct / ac3_srfft_sse.c
1 /*****************************************************************************
2  * ac3_srfft_sse.c: accelerated SSE ac3 fft functions
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: ac3_srfft_sse.c,v 1.13 2002/06/01 12:31:59 sam 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 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <math.h>
29 #include <stdio.h>
30
31 #include <vlc/vlc.h>
32
33 #include "ac3_imdct.h"
34 #include "ac3_srfft.h"
35
36
37 static float hsqrt2_sse[] ATTR_ALIGN(16) =
38     { 0.707106781188, 0.707106781188, -0.707106781188, -0.707106781188 };
39
40 static float C_1_sse[] ATTR_ALIGN(16) =
41     { -1.0, 1.0, -1.0, 1.0 };
42
43 typedef struct {
44         int k;
45         void * C1;
46     } ck_sse_t;
47
48
49 static void fft_4_sse (complex_t *x);
50 static void fft_8_sse (complex_t *x);
51 static void fft_asmb_sse (ck_sse_t * ck, int k, complex_t *x, complex_t *wTB,
52          const complex_t *d, const complex_t *d_3);
53
54 void _M( fft_64p ) ( complex_t *a )
55 {
56     ck_sse_t ck;
57     ck.C1 = C_1_sse;
58
59     fft_8_sse(&a[0]); fft_4_sse(&a[8]); fft_4_sse(&a[12]);
60     fft_asmb_sse(&ck, 2, &a[0], &a[8], &delta16[0], &delta16_3[0]);
61   
62     fft_8_sse(&a[16]), fft_8_sse(&a[24]);
63     fft_asmb_sse(&ck, 4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
64
65     fft_8_sse(&a[32]); fft_4_sse(&a[40]); fft_4_sse(&a[44]);
66     fft_asmb_sse(&ck, 2, &a[32], &a[40], &delta16[0], &delta16_3[0]);
67
68     fft_8_sse(&a[48]); fft_4_sse(&a[56]); fft_4_sse(&a[60]);
69     fft_asmb_sse(&ck, 2, &a[48], &a[56], &delta16[0], &delta16_3[0]);
70
71     fft_asmb_sse(&ck, 8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
72 }
73
74 void _M( fft_128p ) ( complex_t *a )
75 {
76     ck_sse_t ck;
77     ck.C1 = C_1_sse;
78             
79     fft_8_sse(&a[0]); fft_4_sse(&a[8]); fft_4_sse(&a[12]);
80     fft_asmb_sse(&ck, 2, &a[0], &a[8], &delta16[0], &delta16_3[0]);
81   
82     fft_8_sse(&a[16]), fft_8_sse(&a[24]);
83     fft_asmb_sse(&ck, 4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
84
85     fft_8_sse(&a[32]); fft_4_sse(&a[40]); fft_4_sse(&a[44]);
86     fft_asmb_sse(&ck, 2, &a[32], &a[40], &delta16[0], &delta16_3[0]);
87
88     fft_8_sse(&a[48]); fft_4_sse(&a[56]); fft_4_sse(&a[60]);
89     fft_asmb_sse(&ck, 2, &a[48], &a[56], &delta16[0], &delta16_3[0]);
90
91     fft_asmb_sse(&ck, 8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
92
93     fft_8_sse(&a[64]); fft_4_sse(&a[72]); fft_4_sse(&a[76]);
94     /* fft_16(&a[64]); */
95     fft_asmb_sse(&ck, 2, &a[64], &a[72], &delta16[0], &delta16_3[0]);
96
97     fft_8_sse(&a[80]); fft_8_sse(&a[88]);
98   
99     /* fft_32(&a[64]); */
100     fft_asmb_sse(&ck, 4, &a[64], &a[80],&delta32[0], &delta32_3[0]);
101
102     fft_8_sse(&a[96]); fft_4_sse(&a[104]), fft_4_sse(&a[108]);
103     /* fft_16(&a[96]); */
104     fft_asmb_sse(&ck, 2, &a[96], &a[104], &delta16[0], &delta16_3[0]);
105
106     fft_8_sse(&a[112]), fft_8_sse(&a[120]);
107     /* fft_32(&a[96]); */
108     fft_asmb_sse(&ck, 4, &a[96], &a[112], &delta32[0], &delta32_3[0]);
109   
110     /* fft_128(&a[0]); */
111     fft_asmb_sse(&ck, 16, &a[0], &a[64], &delta128[0], &delta128_3[0]);
112 }
113
114 static void fft_4_sse (complex_t *x)
115 {
116     __asm__ __volatile__ (
117     ".align 16\n"
118     "movaps   (%%eax), %%xmm0\n"    /* x[1] | x[0] */
119     "movaps 16(%%eax), %%xmm2\n"    /* x[3] | x[2] */
120     "movaps  %%xmm0, %%xmm1\n"      /* x[1] | x[0] */
121     "addps   %%xmm2, %%xmm0\n"      /* x[1] + x[3] | x[0] + x[2] */
122     "subps   %%xmm2, %%xmm1\n"      /* x[1] - x[3] | x[0] - x[2] */
123     "xorps   %%xmm6, %%xmm6\n"
124     "movhlps %%xmm1, %%xmm4\n"      /* ? | x[1] - x[3] */
125     "movhlps %%xmm0, %%xmm3\n"      /* ? | x[1] + x[3] */
126     "subss   %%xmm4, %%xmm6\n"      /* 0 | -(x[1] - x[3]).re */
127     "movlhps %%xmm1, %%xmm0\n"      /* x[0] - x[2] | x[0] + x[2] */
128     "movlhps %%xmm6, %%xmm4\n"      /* 0 | -(x[1] - x[3]).re | (x[1] - x[3]).im | (x[3]-x[1]).re */
129     "movaps  %%xmm0, %%xmm2\n"      /* x[0] - x[2] | x[0] + x[2] */
130     "shufps   $0x94, %%xmm4, %%xmm3\n" /* i*(x[1] - x[3]) | x[1] + x[3] */
131     "addps   %%xmm3, %%xmm0\n"
132     "subps   %%xmm3, %%xmm2\n"
133     "movaps  %%xmm0,   (%%eax)\n"
134     "movaps  %%xmm2, 16(%%eax)\n"
135     : "=a" (x)
136     : "a" (x) );
137 }
138
139 static void fft_8_sse (complex_t *x)
140 {
141     __asm__ __volatile__ (
142     ".align 16\n"
143     
144     "movlps   (%%eax), %%xmm0\n"    /* x[0] */
145     "movlps 32(%%eax), %%xmm1\n"    /* x[4] */
146     "movhps 16(%%eax), %%xmm0\n"    /* x[2] | x[0] */
147     "movhps 48(%%eax), %%xmm1\n"    /* x[6] | x[4] */
148     "movaps  %%xmm0, %%xmm2\n"      /* x[2] | x[0] */
149     "xorps   %%xmm3, %%xmm3\n"
150     "addps   %%xmm1, %%xmm0\n"      /* x[2] + x[6] | x[0] + x[4] */
151     "subps   %%xmm1, %%xmm2\n"      /* x[2] - x[6] | x[0] - x[4] */
152     "movhlps %%xmm0, %%xmm5\n"      /* x[2] + x[6] */
153     "movhlps %%xmm2, %%xmm4\n"      /* x[2] - x[6] */
154     "movlhps %%xmm2, %%xmm0\n"      /* x[0] - x[4] | x[0] + x[4] */
155     "subss   %%xmm4, %%xmm3\n"      /* (x[2]-x[6]).im | -(x[2]-x[6]).re */
156     "movaps  %%xmm0, %%xmm7\n"      /* x[0] - x[4] | x[0] + x[4] */
157     "movaps  %%xmm3, %%xmm4\n"      /* (x[2]-x[6]).im | -(x[2]-x[6]).re */
158     "movlps 8(%%eax), %%xmm1\n"     /* x[1] */
159     "shufps   $0x14, %%xmm4, %%xmm5\n" /* i*(x[2] - x[6]) | x[2] + x[6] */
160
161     "addps   %%xmm5, %%xmm0\n"      /* yt = i*(x2-x6)+x0-x4 | x2+x6+x0+x4 */
162     "subps   %%xmm5, %%xmm7\n"      /* yb = i*(x6-x2)+x0-x4 | -x6-x2+x0+x4 */
163
164     "movhps 24(%%eax), %%xmm1\n"    /* x[3] | x[1] */
165     "movlps 40(%%eax), %%xmm2\n"    /* x[5] */
166     "movhps 56(%%eax), %%xmm2\n"    /* x[7] | x[5] */
167     "movaps  %%xmm1, %%xmm3\n"      /* x[3] | x[1] */
168     "addps   %%xmm2, %%xmm1\n"      /* x[3] + x[7] | x[1] + x[5] */
169     "subps   %%xmm2, %%xmm3\n"      /* x[3] - x[7] | x[1] - x[5] */
170     "movaps (%%ecx), %%xmm4\n"      /* -1/sqrt2 | -1/sqrt2 | 1/sqrt2 | 1/sqrt2 */
171     "movaps  %%xmm3, %%xmm6\n"      /* x[3] - x[7] | x[1] - x[5] */
172     "mulps   %%xmm4, %%xmm3\n"      /* -1/s2*(x[3] - x[7]) | 1/s2*(x[1] - x[5]) */
173     "shufps   $0xc8, %%xmm4, %%xmm4\n" /* -1/sqrt2 | 1/sqrt2 | -1/sqrt2 | 1/sqrt2 */
174     "shufps   $0xb1, %%xmm6, %%xmm6\n" /* (x3-x7).re|(x3-x7).im|(x1-x5).re|(x1-x5).im */
175     "mulps   %%xmm4, %%xmm6\n"      /* (x7-x3).re/s2|(x3-x7).im/s2|(x5-x1).re/s2|(x1-x5).im/s2 */
176     "addps   %%xmm3, %%xmm6\n"      /* (-1-i)/sqrt2 * (x[3]-x[7]) | (1-i)/sqrt2 * (x[1] - x[5]) */
177     "movhlps %%xmm1, %%xmm5\n"      /* x[3] + x[7] */
178     "movlhps %%xmm6, %%xmm1\n"      /* (1+i)/sqrt2 * (x[1]-x[5]) | x[1]+x[5] */
179     "shufps   $0xe4, %%xmm6, %%xmm5\n" /* (-1-i)/sqrt2 * (x[3]-x[7]) | x[3]+x[7] */
180     "movaps  %%xmm1, %%xmm3\n"      /* (1-i)/sqrt2 * (x[1]-x[5]) | x[1]+x[5] */
181     "addps   %%xmm5, %%xmm1\n"      /* u */
182     "subps   %%xmm5, %%xmm3\n"      /* v */
183     "movaps  %%xmm0, %%xmm2\n"      /* yb */
184     "movaps  %%xmm7, %%xmm4\n"      /* yt */
185     "movaps (%%edx), %%xmm5\n"
186     "mulps   %%xmm5, %%xmm3\n"
187     "addps   %%xmm1, %%xmm0\n"      /* yt + u */
188     "subps   %%xmm1, %%xmm2\n"      /* yt - u */
189     "shufps   $0xb1, %%xmm3, %%xmm3\n" /* -i * v */
190     "movaps  %%xmm0, (%%eax)\n"
191     "movaps  %%xmm2, 32(%%eax)\n"
192     "addps   %%xmm3, %%xmm4\n"      /* yb - i*v */
193     "subps   %%xmm3, %%xmm7\n"      /* yb + i*v */
194     "movaps  %%xmm4, 16(%%eax)\n"
195     "movaps  %%xmm7, 48(%%eax)\n"
196
197     : "=a" (x)
198     : "a" (x), "c" (hsqrt2_sse), "d" (C_1_sse));
199 }
200
201 static void fft_asmb_sse (ck_sse_t * ck, int k, complex_t *x, complex_t *wTB,
202          const complex_t *d, const complex_t *d_3)
203 {
204     ck->k = k;
205     
206     __asm__ __volatile__ (
207     ".align 16\n"
208     "pushl %%ebp\n"
209     "movl %%esp, %%ebp\n"
210
211     "subl $8, %%esp\n"
212     
213     "pushl %%eax\n"
214     "pushl %%ebx\n"
215     "pushl %%ecx\n"
216     "pushl %%edx\n"
217     "pushl %%esi\n"
218     "pushl %%edi\n"
219
220     "movl 4(%%ecx), %%ebx\n"
221     "movl %%ebx, -4(%%ebp)\n"
222     "movl (%%ecx), %%ecx\n"
223
224     "movl %%ecx, -8(%%ebp)\n"   /* k */
225     "addl $8, %%edx\n" 
226     "addl $8, %%esi\n"
227     "shll $4, %%ecx\n"          /* 16k */
228
229     /* TRANSZERO and TRANS */
230     ".align 16\n"
231     "movaps (%%eax), %%xmm0\n"     /* x[1] | x[0] */
232     "movaps (%%edi), %%xmm1\n"     /* wT[1] | wT[0] */
233     "movaps (%%edi, %%ecx), %%xmm2\n" /* wB[1] | wB[0] */
234     "movlps (%%edx), %%xmm3\n"     /* d */
235     "movlps (%%esi), %%xmm4\n"     /* d3 */
236     "movhlps %%xmm1, %%xmm5\n"     /* wT[1] */
237     "movhlps %%xmm2, %%xmm6\n"     /* wB[1] */
238     "shufps $0x50, %%xmm3, %%xmm3\n" /* d[1].im | d[1].im | d[1].re | d[1].re */
239     "shufps $0x50, %%xmm4, %%xmm4\n" /* d3[1].im | d3[1].im | d3[i].re | d3[i].re */
240     "movlhps %%xmm5, %%xmm5\n"      /* wT[1] | wT[1] */
241     "movlhps %%xmm6, %%xmm6\n"      /* wB[1] | wB[1] */
242     "mulps   %%xmm3, %%xmm5\n"
243     "mulps   %%xmm4, %%xmm6\n"
244     "movhlps %%xmm5, %%xmm7\n"      /* wT[1].im * d[1].im | wT[1].re * d[1].im */
245     "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 */
246     "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 */
247     "movl  -4(%%ebp), %%ebx\n"
248     "movaps (%%ebx), %%xmm4\n"
249     "mulps   %%xmm4, %%xmm7\n"
250     "addps   %%xmm7, %%xmm5\n"      /* wB[1] * d3[1] | wT[1] * d[1] */
251     "movlhps %%xmm5, %%xmm1\n"      /* d[1] * wT[1] | wT[0] */
252     "shufps  $0xe4, %%xmm5, %%xmm2\n" /* d3[1] * wB[1] | wB[0] */
253     "movaps  %%xmm1, %%xmm3\n"      /* d[1] * wT[1] | wT[0] */
254     "leal   (%%eax, %%ecx, 2), %%ebx\n"
255     "addps  %%xmm2, %%xmm1\n"       /* u */
256     "subps  %%xmm2, %%xmm3\n"       /* v */
257     "mulps  %%xmm4, %%xmm3\n"
258     "movaps (%%eax, %%ecx), %%xmm5\n" /* xk[1] | xk[0] */
259     "shufps $0xb1, %%xmm3, %%xmm3\n"  /* -i * v */
260     "movaps %%xmm0, %%xmm2\n"       /* x[1] | x[0] */
261     "movaps %%xmm5, %%xmm6\n"       /* xk[1] | xk[0] */
262     "addps  %%xmm1, %%xmm0\n"
263     "subps  %%xmm1, %%xmm2\n"
264     "addps  %%xmm3, %%xmm5\n"
265     "subps  %%xmm3, %%xmm6\n"
266     "movaps %%xmm0, (%%eax)\n"
267     "movaps %%xmm2, (%%ebx)\n"
268     "movaps %%xmm5, (%%eax, %%ecx)\n"
269     "movaps %%xmm6, (%%ebx, %%ecx)\n"
270     "addl $16, %%eax\n"
271     "addl $16, %%edi\n"
272     "addl  $8, %%edx\n"
273     "addl  $8, %%esi\n"
274     "decl -8(%%ebp)\n"
275
276     ".align 16\n"
277 "0:\n"
278     "movaps (%%edi), %%xmm0\n"      /* wT[1] | wT[0] */
279     "movaps (%%edx), %%xmm1\n"      /* d[1] | d[0] */
280
281     "movaps (%%edi, %%ecx), %%xmm4\n" /* wB[1] | wB[0] */
282     "movaps (%%esi), %%xmm5\n"      /* d3[1] | d3[0] */
283
284     "movhlps %%xmm0, %%xmm2\n"      /* wT[1] */
285     "movhlps %%xmm1, %%xmm3\n"      /* d[1] */
286
287     "movhlps %%xmm4, %%xmm6\n"      /* wB[1] */
288     "movhlps %%xmm5, %%xmm7\n"      /* d3[1] */
289
290     "shufps $0x50, %%xmm1, %%xmm1\n" /* d[0].im | d[0].im | d[0].re | d[0].re */
291     "shufps $0x50, %%xmm3, %%xmm3\n" /* d[1].im | d[1].im | d[1].re | d[1].re */
292
293     "movlhps %%xmm0, %%xmm0\n"       /* wT[0] | wT[0] */
294     "shufps $0x50, %%xmm5, %%xmm5\n" /* d3[0].im | d3[0].im | d3[0].re | d3[0].re */
295     "movlhps %%xmm2, %%xmm2\n"       /* wT[1] | wT[1] */
296     "shufps $0x50, %%xmm7, %%xmm7\n" /* d3[1].im | d3[1].im | d3[1].re | d3[1].re */
297
298     "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 */
299     "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 */
300     "movlhps %%xmm4, %%xmm4\n"  /* wB[0] | wB[0] */
301     "movlhps %%xmm6, %%xmm6\n"  /* wB[1] | wB[1] */
302     
303     "movhlps %%xmm0, %%xmm1\n"  /* d[0].im * wT[0].im | d[0].im * wT[0].re */
304     "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 */
305     "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 */
306     "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 */
307     "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 */
308     "movl -4(%%ebp), %%ebx\n"
309     "movaps (%%ebx), %%xmm3\n"  /* 1.0 | -1.0 | 1.0 | -1.0 */
310
311     "movhlps %%xmm4, %%xmm5\n"  /* wB[0].im * d3[0].im | wB[0].re * d3[0].im */
312     "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 */
313     "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 */
314     "addps   %%xmm1, %%xmm0\n"  /* wT[1] * d[1] | wT[0] * d[0] */
315
316     "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 */
317     "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 */
318     "addps   %%xmm5, %%xmm4\n"  /* wB[1] * d3[1] | wB[0] * d3[0] */
319
320     "movaps %%xmm0, %%xmm1\n"   /* wT[1] * d[1] | wT[0] * d[0] */
321     "addps  %%xmm4, %%xmm0\n"   /* u */
322     "subps  %%xmm4, %%xmm1\n"   /* v */
323     "movaps (%%eax), %%xmm6\n"  /* x[1] | x[0] */
324     "leal   (%%eax, %%ecx, 2), %%ebx\n"
325     "mulps  %%xmm3, %%xmm1\n"
326     "addl $16, %%edi\n"
327     "addl $16, %%esi\n"
328     "shufps $0xb1, %%xmm1, %%xmm1\n"    /* -i * v */
329     "movaps (%%eax, %%ecx), %%xmm7\n"   /* xk[1] | xk[0] */
330     "movaps %%xmm6, %%xmm2\n"
331     "movaps %%xmm7, %%xmm4\n"
332     "addps  %%xmm0, %%xmm6\n"
333     "subps  %%xmm0, %%xmm2\n"
334     "movaps %%xmm6, (%%eax)\n"
335     "movaps %%xmm2, (%%ebx)\n"
336     "addps  %%xmm1, %%xmm7\n"
337     "subps  %%xmm1, %%xmm4\n"
338     "addl $16, %%edx\n"
339     "movaps %%xmm7, (%%eax, %%ecx)\n"
340     "movaps %%xmm4, (%%ebx, %%ecx)\n"
341
342     "addl $16, %%eax\n"
343     "decl -8(%%ebp)\n"
344     "jnz 0b\n"
345
346     ".align 16\n"
347 "1:\n"
348     "popl %%edi\n"
349     "popl %%esi\n"
350     "popl %%edx\n"
351     "popl %%ecx\n"
352     "popl %%ebx\n"
353     "popl %%eax\n"
354     
355     "addl $8, %%esp\n"
356     
357     "leave\n"
358     : "=a" (x), "=D" (wTB)
359     : "c" (ck), "a" (x), "D" (wTB), "d" (d), "S" (d_3) );
360 }