e1b485b697a9c65ffdb98b0562a8ca62a688735e
[ffmpeg.git] / libavcodec / x86 / fft_mmx.asm
1 ;******************************************************************************
2 ;* FFT transform with SSE/3DNow optimizations
3 ;* Copyright (c) 2008 Loren Merritt
4 ;* Copyright (c) 2011 Vitor Sessak
5 ;*
6 ;* This algorithm (though not any of the implementation details) is
7 ;* based on libdjbfft by D. J. Bernstein.
8 ;*
9 ;* This file is part of FFmpeg.
10 ;*
11 ;* FFmpeg is free software; you can redistribute it and/or
12 ;* modify it under the terms of the GNU Lesser General Public
13 ;* License as published by the Free Software Foundation; either
14 ;* version 2.1 of the License, or (at your option) any later version.
15 ;*
16 ;* FFmpeg is distributed in the hope that it will be useful,
17 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 ;* Lesser General Public License for more details.
20 ;*
21 ;* You should have received a copy of the GNU Lesser General Public
22 ;* License along with FFmpeg; if not, write to the Free Software
23 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 ;******************************************************************************
25
26 ; These functions are not individually interchangeable with the C versions.
27 ; While C takes arrays of FFTComplex, SSE/3DNow leave intermediate results
28 ; in blocks as conventient to the vector size.
29 ; i.e. {4x real, 4x imaginary, 4x real, ...} (or 2x respectively)
30
31 %include "libavutil/x86/x86inc.asm"
32
33 %if ARCH_X86_64
34 %define pointer resq
35 %else
36 %define pointer resd
37 %endif
38
39 SECTION_RODATA
40
41 struc FFTContext
42     .nbits:    resd 1
43     .reverse:  resd 1
44     .revtab:   pointer 1
45     .tmpbuf:   pointer 1
46     .mdctsize: resd 1
47     .mdctbits: resd 1
48     .tcos:     pointer 1
49     .tsin:     pointer 1
50 endstruc
51
52 %define M_SQRT1_2 0.70710678118654752440
53 %define M_COS_PI_1_8 0.923879532511287
54 %define M_COS_PI_3_8 0.38268343236509
55
56 align 32
57 ps_cos16_1: dd 1.0, M_COS_PI_1_8, M_SQRT1_2, M_COS_PI_3_8, 1.0, M_COS_PI_1_8, M_SQRT1_2, M_COS_PI_3_8
58 ps_cos16_2: dd 0, M_COS_PI_3_8, M_SQRT1_2, M_COS_PI_1_8, 0, -M_COS_PI_3_8, -M_SQRT1_2, -M_COS_PI_1_8
59
60 ps_root2: times 8 dd M_SQRT1_2
61 ps_root2mppm: dd -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2
62 ps_p1p1m1p1: dd 0, 0, 1<<31, 0, 0, 0, 1<<31, 0
63
64 perm1: dd 0x00, 0x02, 0x03, 0x01, 0x03, 0x00, 0x02, 0x01
65 perm2: dd 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x02, 0x03
66 ps_p1p1m1p1root2: dd 1.0, 1.0, -1.0, 1.0, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2
67 ps_m1m1p1m1p1m1m1m1: dd 1<<31, 1<<31, 0, 1<<31, 0, 1<<31, 1<<31, 1<<31
68 ps_m1p1: dd 1<<31, 0
69
70 %assign i 16
71 %rep 13
72 cextern cos_ %+ i
73 %assign i i<<1
74 %endrep
75
76 %if ARCH_X86_64
77     %define pointer dq
78 %else
79     %define pointer dd
80 %endif
81
82 %macro IF0 1+
83 %endmacro
84 %macro IF1 1+
85     %1
86 %endmacro
87
88 SECTION_TEXT
89
90 %macro T2_3DN 4 ; z0, z1, mem0, mem1
91     mova     %1, %3
92     mova     %2, %1
93     pfadd    %1, %4
94     pfsub    %2, %4
95 %endmacro
96
97 %macro T4_3DN 6 ; z0, z1, z2, z3, tmp0, tmp1
98     mova     %5, %3
99     pfsub    %3, %4
100     pfadd    %5, %4 ; {t6,t5}
101     pxor     %3, [ps_m1p1] ; {t8,t7}
102     mova     %6, %1
103     pswapd   %3, %3
104     pfadd    %1, %5 ; {r0,i0}
105     pfsub    %6, %5 ; {r2,i2}
106     mova     %4, %2
107     pfadd    %2, %3 ; {r1,i1}
108     pfsub    %4, %3 ; {r3,i3}
109     SWAP     %3, %6
110 %endmacro
111
112 ;  in: %1 = {r0,i0,r2,i2,r4,i4,r6,i6}
113 ;      %2 = {r1,i1,r3,i3,r5,i5,r7,i7}
114 ;      %3, %4, %5 tmp
115 ; out: %1 = {r0,r1,r2,r3,i0,i1,i2,i3}
116 ;      %2 = {r4,r5,r6,r7,i4,i5,i6,i7}
117 %macro T8_AVX 5
118     vsubps     %5, %1, %2       ; v  = %1 - %2
119     vaddps     %3, %1, %2       ; w  = %1 + %2
120     vmulps     %2, %5, [ps_p1p1m1p1root2]  ; v *= vals1
121     vpermilps  %2, %2, [perm1]
122     vblendps   %1, %2, %3, 0x33 ; q = {w1,w2,v4,v2,w5,w6,v7,v6}
123     vshufps    %5, %3, %2, 0x4e ; r = {w3,w4,v1,v3,w7,w8,v8,v5}
124     vsubps     %4, %5, %1       ; s = r - q
125     vaddps     %1, %5, %1       ; u = r + q
126     vpermilps  %1, %1, [perm2]  ; k  = {u1,u2,u3,u4,u6,u5,u7,u8}
127     vshufps    %5, %4, %1, 0xbb
128     vshufps    %3, %4, %1, 0xee
129     vperm2f128 %3, %3, %5, 0x13
130     vxorps     %4, %4, [ps_m1m1p1m1p1m1m1m1]  ; s *= {1,1,-1,-1,1,-1,-1,-1}
131     vshufps    %2, %1, %4, 0xdd
132     vshufps    %1, %1, %4, 0x88
133     vperm2f128 %4, %2, %1, 0x02 ; v  = {k1,k3,s1,s3,k2,k4,s2,s4}
134     vperm2f128 %1, %1, %2, 0x13 ; w  = {k6,k8,s6,s8,k5,k7,s5,s7}
135     vsubps     %5, %1, %3
136     vblendps   %1, %5, %1, 0x55 ; w -= {0,s7,0,k7,0,s8,0,k8}
137     vsubps     %2, %4, %1       ; %2 = v - w
138     vaddps     %1, %4, %1       ; %1 = v + w
139 %endmacro
140
141 ; In SSE mode do one fft4 transforms
142 ; in:  %1={r0,i0,r2,i2} %2={r1,i1,r3,i3}
143 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3}
144 ;
145 ; In AVX mode do two fft4 transforms
146 ; in:  %1={r0,i0,r2,i2,r4,i4,r6,i6} %2={r1,i1,r3,i3,r5,i5,r7,i7}
147 ; out: %1={r0,r1,r2,r3,r4,r5,r6,r7} %2={i0,i1,i2,i3,i4,i5,i6,i7}
148 %macro T4_SSE 3
149     subps    %3, %1, %2       ; {t3,t4,-t8,t7}
150     addps    %1, %1, %2       ; {t1,t2,t6,t5}
151     xorps    %3, %3, [ps_p1p1m1p1]
152     shufps   %2, %1, %3, 0xbe ; {t6,t5,t7,t8}
153     shufps   %1, %1, %3, 0x44 ; {t1,t2,t3,t4}
154     subps    %3, %1, %2       ; {r2,i2,r3,i3}
155     addps    %1, %1, %2       ; {r0,i0,r1,i1}
156     shufps   %2, %1, %3, 0xdd ; {i0,i1,i2,i3}
157     shufps   %1, %1, %3, 0x88 ; {r0,r1,r2,r3}
158 %endmacro
159
160 ; In SSE mode do one FFT8
161 ; in:  %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %3={r4,i4,r6,i6} %4={r5,i5,r7,i7}
162 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %1={r4,r5,r6,r7} %2={i4,i5,i6,i7}
163 ;
164 ; In AVX mode do two FFT8
165 ; in:  %1={r0,i0,r2,i2,r8, i8, r10,i10} %2={r1,i1,r3,i3,r9, i9, r11,i11}
166 ;      %3={r4,i4,r6,i6,r12,i12,r14,i14} %4={r5,i5,r7,i7,r13,i13,r15,i15}
167 ; out: %1={r0,r1,r2,r3,r8, r9, r10,r11} %2={i0,i1,i2,i3,i8, i9, i10,i11}
168 ;      %3={r4,r5,r6,r7,r12,r13,r14,r15} %4={i4,i5,i6,i7,i12,i13,i14,i15}
169 %macro T8_SSE 6
170     addps    %6, %3, %4       ; {t1,t2,t3,t4}
171     subps    %3, %3, %4       ; {r5,i5,r7,i7}
172     shufps   %4, %3, %3, 0xb1 ; {i5,r5,i7,r7}
173     mulps    %3, %3, [ps_root2mppm] ; {-r5,i5,r7,-i7}
174     mulps    %4, %4, [ps_root2]
175     addps    %3, %3, %4       ; {t8,t7,ta,t9}
176     shufps   %4, %6, %3, 0x9c ; {t1,t4,t7,ta}
177     shufps   %6, %6, %3, 0x36 ; {t3,t2,t9,t8}
178     subps    %3, %6, %4       ; {t6,t5,tc,tb}
179     addps    %6, %6, %4       ; {t1,t2,t9,ta}
180     shufps   %5, %6, %3, 0x8d ; {t2,ta,t6,tc}
181     shufps   %6, %6, %3, 0xd8 ; {t1,t9,t5,tb}
182     subps    %3, %1, %6       ; {r4,r5,r6,r7}
183     addps    %1, %1, %6       ; {r0,r1,r2,r3}
184     subps    %4, %2, %5       ; {i4,i5,i6,i7}
185     addps    %2, %2, %5       ; {i0,i1,i2,i3}
186 %endmacro
187
188 ; scheduled for cpu-bound sizes
189 %macro PASS_SMALL 3 ; (to load m4-m7), wre, wim
190 IF%1 mova    m4, Z(4)
191 IF%1 mova    m5, Z(5)
192     mova     m0, %2 ; wre
193     mova     m1, %3 ; wim
194     mulps    m2, m4, m0 ; r2*wre
195 IF%1 mova    m6, Z2(6)
196     mulps    m3, m5, m1 ; i2*wim
197 IF%1 mova    m7, Z2(7)
198     mulps    m4, m4, m1 ; r2*wim
199     mulps    m5, m5, m0 ; i2*wre
200     addps    m2, m2, m3 ; r2*wre + i2*wim
201     mulps    m3, m1, m7 ; i3*wim
202     subps    m5, m5, m4 ; i2*wre - r2*wim
203     mulps    m1, m1, m6 ; r3*wim
204     mulps    m4, m0, m6 ; r3*wre
205     mulps    m0, m0, m7 ; i3*wre
206     subps    m4, m4, m3 ; r3*wre - i3*wim
207     mova     m3, Z(0)
208     addps    m0, m0, m1 ; i3*wre + r3*wim
209     subps    m1, m4, m2 ; t3
210     addps    m4, m4, m2 ; t5
211     subps    m3, m3, m4 ; r2
212     addps    m4, m4, Z(0) ; r0
213     mova     m6, Z(2)
214     mova   Z(4), m3
215     mova   Z(0), m4
216     subps    m3, m5, m0 ; t4
217     subps    m4, m6, m3 ; r3
218     addps    m3, m3, m6 ; r1
219     mova  Z2(6), m4
220     mova   Z(2), m3
221     mova     m2, Z(3)
222     addps    m3, m5, m0 ; t6
223     subps    m2, m2, m1 ; i3
224     mova     m7, Z(1)
225     addps    m1, m1, Z(3) ; i1
226     mova  Z2(7), m2
227     mova   Z(3), m1
228     subps    m4, m7, m3 ; i2
229     addps    m3, m3, m7 ; i0
230     mova   Z(5), m4
231     mova   Z(1), m3
232 %endmacro
233
234 ; scheduled to avoid store->load aliasing
235 %macro PASS_BIG 1 ; (!interleave)
236     mova     m4, Z(4) ; r2
237     mova     m5, Z(5) ; i2
238     mova     m0, [wq] ; wre
239     mova     m1, [wq+o1q] ; wim
240     mulps    m2, m4, m0 ; r2*wre
241     mova     m6, Z2(6) ; r3
242     mulps    m3, m5, m1 ; i2*wim
243     mova     m7, Z2(7) ; i3
244     mulps    m4, m4, m1 ; r2*wim
245     mulps    m5, m5, m0 ; i2*wre
246     addps    m2, m2, m3 ; r2*wre + i2*wim
247     mulps    m3, m1, m7 ; i3*wim
248     mulps    m1, m1, m6 ; r3*wim
249     subps    m5, m5, m4 ; i2*wre - r2*wim
250     mulps    m4, m0, m6 ; r3*wre
251     mulps    m0, m0, m7 ; i3*wre
252     subps    m4, m4, m3 ; r3*wre - i3*wim
253     mova     m3, Z(0)
254     addps    m0, m0, m1 ; i3*wre + r3*wim
255     subps    m1, m4, m2 ; t3
256     addps    m4, m4, m2 ; t5
257     subps    m3, m3, m4 ; r2
258     addps    m4, m4, Z(0) ; r0
259     mova     m6, Z(2)
260     mova   Z(4), m3
261     mova   Z(0), m4
262     subps    m3, m5, m0 ; t4
263     subps    m4, m6, m3 ; r3
264     addps    m3, m3, m6 ; r1
265 IF%1 mova Z2(6), m4
266 IF%1 mova  Z(2), m3
267     mova     m2, Z(3)
268     addps    m5, m5, m0 ; t6
269     subps    m2, m2, m1 ; i3
270     mova     m7, Z(1)
271     addps    m1, m1, Z(3) ; i1
272 IF%1 mova Z2(7), m2
273 IF%1 mova  Z(3), m1
274     subps    m6, m7, m5 ; i2
275     addps    m5, m5, m7 ; i0
276 IF%1 mova  Z(5), m6
277 IF%1 mova  Z(1), m5
278 %if %1==0
279     INTERL m1, m3, m7, Z, 2
280     INTERL m2, m4, m0, Z2, 6
281
282     mova     m1, Z(0)
283     mova     m2, Z(4)
284
285     INTERL m5, m1, m3, Z, 0
286     INTERL m6, m2, m7, Z, 4
287 %endif
288 %endmacro
289
290 %macro PUNPCK 3
291     mova      %3, %1
292     punpckldq %1, %2
293     punpckhdq %3, %2
294 %endmacro
295
296 %define Z(x) [r0+mmsize*x]
297 %define Z2(x) [r0+mmsize*x]
298 %define ZH(x) [r0+mmsize*x+mmsize/2]
299
300 INIT_YMM avx
301
302 %if HAVE_AVX
303 align 16
304 fft8_avx:
305     mova      m0, Z(0)
306     mova      m1, Z(1)
307     T8_AVX    m0, m1, m2, m3, m4
308     mova      Z(0), m0
309     mova      Z(1), m1
310     ret
311
312
313 align 16
314 fft16_avx:
315     mova       m2, Z(2)
316     mova       m3, Z(3)
317     T4_SSE     m2, m3, m7
318
319     mova       m0, Z(0)
320     mova       m1, Z(1)
321     T8_AVX     m0, m1, m4, m5, m7
322
323     mova       m4, [ps_cos16_1]
324     mova       m5, [ps_cos16_2]
325     vmulps     m6, m2, m4
326     vmulps     m7, m3, m5
327     vaddps     m7, m7, m6
328     vmulps     m2, m2, m5
329     vmulps     m3, m3, m4
330     vsubps     m3, m3, m2
331     vblendps   m2, m7, m3, 0xf0
332     vperm2f128 m3, m7, m3, 0x21
333     vaddps     m4, m2, m3
334     vsubps     m2, m3, m2
335     vperm2f128 m2, m2, m2, 0x01
336     vsubps     m3, m1, m2
337     vaddps     m1, m1, m2
338     vsubps     m5, m0, m4
339     vaddps     m0, m0, m4
340     vextractf128   Z(0), m0, 0
341     vextractf128  ZH(0), m1, 0
342     vextractf128   Z(1), m0, 1
343     vextractf128  ZH(1), m1, 1
344     vextractf128   Z(2), m5, 0
345     vextractf128  ZH(2), m3, 0
346     vextractf128   Z(3), m5, 1
347     vextractf128  ZH(3), m3, 1
348     ret
349
350 align 16
351 fft32_avx:
352     call fft16_avx
353
354     mova m0, Z(4)
355     mova m1, Z(5)
356
357     T4_SSE      m0, m1, m4
358
359     mova m2, Z(6)
360     mova m3, Z(7)
361
362     T8_SSE      m0, m1, m2, m3, m4, m6
363     ; m0={r0,r1,r2,r3,r8, r9, r10,r11} m1={i0,i1,i2,i3,i8, i9, i10,i11}
364     ; m2={r4,r5,r6,r7,r12,r13,r14,r15} m3={i4,i5,i6,i7,i12,i13,i14,i15}
365
366     vperm2f128  m4, m0, m2, 0x20
367     vperm2f128  m5, m1, m3, 0x20
368     vperm2f128  m6, m0, m2, 0x31
369     vperm2f128  m7, m1, m3, 0x31
370
371     PASS_SMALL 0, [cos_32], [cos_32+32]
372
373     ret
374
375 fft32_interleave_avx:
376     call fft32_avx
377     mov r2d, 32
378 .deint_loop:
379     mova     m2, Z(0)
380     mova     m3, Z(1)
381     vunpcklps      m0, m2, m3
382     vunpckhps      m1, m2, m3
383     vextractf128   Z(0), m0, 0
384     vextractf128  ZH(0), m1, 0
385     vextractf128   Z(1), m0, 1
386     vextractf128  ZH(1), m1, 1
387     add r0, mmsize*2
388     sub r2d, mmsize/4
389     jg .deint_loop
390     ret
391
392 %endif
393
394 INIT_XMM sse
395 %define movdqa  movaps
396
397 align 16
398 fft4_avx:
399 fft4_sse:
400     mova     m0, Z(0)
401     mova     m1, Z(1)
402     T4_SSE   m0, m1, m2
403     mova   Z(0), m0
404     mova   Z(1), m1
405     ret
406
407 align 16
408 fft8_sse:
409     mova     m0, Z(0)
410     mova     m1, Z(1)
411     T4_SSE   m0, m1, m2
412     mova     m2, Z(2)
413     mova     m3, Z(3)
414     T8_SSE   m0, m1, m2, m3, m4, m5
415     mova   Z(0), m0
416     mova   Z(1), m1
417     mova   Z(2), m2
418     mova   Z(3), m3
419     ret
420
421 align 16
422 fft16_sse:
423     mova     m0, Z(0)
424     mova     m1, Z(1)
425     T4_SSE   m0, m1, m2
426     mova     m2, Z(2)
427     mova     m3, Z(3)
428     T8_SSE   m0, m1, m2, m3, m4, m5
429     mova     m4, Z(4)
430     mova     m5, Z(5)
431     mova   Z(0), m0
432     mova   Z(1), m1
433     mova   Z(2), m2
434     mova   Z(3), m3
435     T4_SSE   m4, m5, m6
436     mova     m6, Z2(6)
437     mova     m7, Z2(7)
438     T4_SSE   m6, m7, m0
439     PASS_SMALL 0, [cos_16], [cos_16+16]
440     ret
441
442
443 %macro FFT48_3DN 0
444 align 16
445 fft4 %+ SUFFIX:
446     T2_3DN   m0, m1, Z(0), Z(1)
447     mova     m2, Z(2)
448     mova     m3, Z(3)
449     T4_3DN   m0, m1, m2, m3, m4, m5
450     PUNPCK   m0, m1, m4
451     PUNPCK   m2, m3, m5
452     mova   Z(0), m0
453     mova   Z(1), m4
454     mova   Z(2), m2
455     mova   Z(3), m5
456     ret
457
458 align 16
459 fft8 %+ SUFFIX:
460     T2_3DN   m0, m1, Z(0), Z(1)
461     mova     m2, Z(2)
462     mova     m3, Z(3)
463     T4_3DN   m0, m1, m2, m3, m4, m5
464     mova   Z(0), m0
465     mova   Z(2), m2
466     T2_3DN   m4, m5,  Z(4),  Z(5)
467     T2_3DN   m6, m7, Z2(6), Z2(7)
468     pswapd   m0, m5
469     pswapd   m2, m7
470     pxor     m0, [ps_m1p1]
471     pxor     m2, [ps_m1p1]
472     pfsub    m5, m0
473     pfadd    m7, m2
474     pfmul    m5, [ps_root2]
475     pfmul    m7, [ps_root2]
476     T4_3DN   m1, m3, m5, m7, m0, m2
477     mova   Z(5), m5
478     mova  Z2(7), m7
479     mova     m0, Z(0)
480     mova     m2, Z(2)
481     T4_3DN   m0, m2, m4, m6, m5, m7
482     PUNPCK   m0, m1, m5
483     PUNPCK   m2, m3, m7
484     mova   Z(0), m0
485     mova   Z(1), m5
486     mova   Z(2), m2
487     mova   Z(3), m7
488     PUNPCK   m4,  Z(5), m5
489     PUNPCK   m6, Z2(7), m7
490     mova   Z(4), m4
491     mova   Z(5), m5
492     mova  Z2(6), m6
493     mova  Z2(7), m7
494     ret
495 %endmacro
496
497 INIT_MMX 3dnow2
498 FFT48_3DN
499
500 %macro pswapd 2
501 %ifidn %1, %2
502     movd [r0+12], %1
503     punpckhdq %1, [r0+8]
504 %else
505     movq  %1, %2
506     psrlq %1, 32
507     punpckldq %1, %2
508 %endif
509 %endmacro
510
511 INIT_MMX 3dnow
512 FFT48_3DN
513
514
515 %define Z(x) [zq + o1q*(x&6) + mmsize*(x&1)]
516 %define Z2(x) [zq + o3q + mmsize*(x&1)]
517 %define ZH(x) [zq + o1q*(x&6) + mmsize*(x&1) + mmsize/2]
518 %define Z2H(x) [zq + o3q + mmsize*(x&1) + mmsize/2]
519
520 %macro DECL_PASS 2+ ; name, payload
521 align 16
522 %1:
523 DEFINE_ARGS z, w, n, o1, o3
524     lea o3q, [nq*3]
525     lea o1q, [nq*8]
526     shl o3q, 4
527 .loop:
528     %2
529     add zq, mmsize*2
530     add wq, mmsize
531     sub nd, mmsize/8
532     jg .loop
533     rep ret
534 %endmacro
535
536 INIT_YMM avx
537
538 %if HAVE_AVX
539 %macro INTERL_AVX 5
540     vunpckhps      %3, %2, %1
541     vunpcklps      %2, %2, %1
542     vextractf128   %4(%5), %2, 0
543     vextractf128  %4 %+ H(%5), %3, 0
544     vextractf128   %4(%5 + 1), %2, 1
545     vextractf128  %4 %+ H(%5 + 1), %3, 1
546 %endmacro
547
548 %define INTERL INTERL_AVX
549
550 DECL_PASS pass_avx, PASS_BIG 1
551 DECL_PASS pass_interleave_avx, PASS_BIG 0
552 %endif
553
554 INIT_XMM sse
555
556 %macro INTERL_SSE 5
557     mova     %3, %2
558     unpcklps %2, %1
559     unpckhps %3, %1
560     mova  %4(%5), %2
561     mova  %4(%5+1), %3
562 %endmacro
563
564 %define INTERL INTERL_SSE
565
566 DECL_PASS pass_sse, PASS_BIG 1
567 DECL_PASS pass_interleave_sse, PASS_BIG 0
568
569 INIT_MMX 3dnow
570 %define mulps pfmul
571 %define addps pfadd
572 %define subps pfsub
573 %define unpcklps punpckldq
574 %define unpckhps punpckhdq
575 DECL_PASS pass_3dnow, PASS_SMALL 1, [wq], [wq+o1q]
576 DECL_PASS pass_interleave_3dnow, PASS_BIG 0
577 %define pass_3dnow2 pass_3dnow
578 %define pass_interleave_3dnow2 pass_interleave_3dnow
579
580 %ifdef PIC
581 %define SECTION_REL - $$
582 %else
583 %define SECTION_REL
584 %endif
585
586 %macro FFT_DISPATCH 2; clobbers 5 GPRs, 8 XMMs
587     lea r2, [dispatch_tab%1]
588     mov r2, [r2 + (%2q-2)*gprsize]
589 %ifdef PIC
590     lea r3, [$$]
591     add r2, r3
592 %endif
593     call r2
594 %endmacro ; FFT_DISPATCH
595
596 %macro DECL_FFT 1-2 ; nbits, suffix
597 %ifidn %0, 1
598 %xdefine fullsuffix SUFFIX
599 %else
600 %xdefine fullsuffix %2 %+ SUFFIX
601 %endif
602 %xdefine list_of_fft fft4 %+ SUFFIX SECTION_REL, fft8 %+ SUFFIX SECTION_REL
603 %if %1>=5
604 %xdefine list_of_fft list_of_fft, fft16 %+ SUFFIX SECTION_REL
605 %endif
606 %if %1>=6
607 %xdefine list_of_fft list_of_fft, fft32 %+ fullsuffix SECTION_REL
608 %endif
609
610 %assign n 1<<%1
611 %rep 17-%1
612 %assign n2 n/2
613 %assign n4 n/4
614 %xdefine list_of_fft list_of_fft, fft %+ n %+ fullsuffix SECTION_REL
615
616 align 16
617 fft %+ n %+ fullsuffix:
618     call fft %+ n2 %+ SUFFIX
619     add r0, n*4 - (n&(-2<<%1))
620     call fft %+ n4 %+ SUFFIX
621     add r0, n*2 - (n2&(-2<<%1))
622     call fft %+ n4 %+ SUFFIX
623     sub r0, n*6 + (n2&(-2<<%1))
624     lea r1, [cos_ %+ n]
625     mov r2d, n4/2
626     jmp pass %+ fullsuffix
627
628 %assign n n*2
629 %endrep
630 %undef n
631
632 align 8
633 dispatch_tab %+ fullsuffix: pointer list_of_fft
634
635 section .text
636
637 ; On x86_32, this function does the register saving and restoring for all of fft.
638 ; The others pass args in registers and don't spill anything.
639 cglobal fft_dispatch%2, 2,5,8, z, nbits
640     FFT_DISPATCH fullsuffix, nbits
641 %if mmsize == 32
642     vzeroupper
643 %endif
644     RET
645 %endmacro ; DECL_FFT
646
647 %if HAVE_AVX
648 INIT_YMM avx
649 DECL_FFT 6
650 DECL_FFT 6, _interleave
651 %endif
652 INIT_XMM sse
653 DECL_FFT 5
654 DECL_FFT 5, _interleave
655 INIT_MMX 3dnow
656 DECL_FFT 4
657 DECL_FFT 4, _interleave
658 INIT_MMX 3dnow2
659 DECL_FFT 4
660 DECL_FFT 4, _interleave
661
662 INIT_XMM sse
663 %undef mulps
664 %undef addps
665 %undef subps
666 %undef unpcklps
667 %undef unpckhps
668
669 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
670     movaps   xmm0, [%3+%2*4]
671     movaps   xmm1, [%3+%1*4-0x10]
672     movaps   xmm2, xmm0
673     shufps   xmm0, xmm1, 0x88
674     shufps   xmm1, xmm2, 0x77
675     movlps   xmm4, [%4+%2*2]
676     movlps   xmm5, [%5+%2*2+0x0]
677     movhps   xmm4, [%4+%1*2-0x8]
678     movhps   xmm5, [%5+%1*2-0x8]
679     movaps   xmm2, xmm0
680     movaps   xmm3, xmm1
681     mulps    xmm0, xmm5
682     mulps    xmm1, xmm4
683     mulps    xmm2, xmm4
684     mulps    xmm3, xmm5
685     subps    xmm1, xmm0
686     addps    xmm2, xmm3
687     movaps   xmm0, xmm1
688     unpcklps xmm1, xmm2
689     unpckhps xmm0, xmm2
690 %endmacro
691
692 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
693     mulps      m6, %3, [%5+%1]
694     mulps      m7, %2, [%5+%1]
695     mulps      %2, %2, [%6+%1]
696     mulps      %3, %3, [%6+%1]
697     subps      %2, %2, m6
698     addps      %3, %3, m7
699 %endmacro
700
701 %macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8
702 .post:
703     vmovaps      ymm1,   [%3+%1*2]
704     vmovaps      ymm0,   [%3+%1*2+0x20]
705     vmovaps      ymm3,   [%3+%2*2]
706     vmovaps      ymm2,   [%3+%2*2+0x20]
707
708     CMUL         %1, ymm0, ymm1, %3, %4, %5
709     CMUL         %2, ymm2, ymm3, %3, %4, %5
710     vshufps      ymm1, ymm1, ymm1, 0x1b
711     vshufps      ymm3, ymm3, ymm3, 0x1b
712     vperm2f128   ymm1, ymm1, ymm1, 0x01
713     vperm2f128   ymm3, ymm3, ymm3, 0x01
714     vunpcklps    ymm6, ymm2, ymm1
715     vunpckhps    ymm4, ymm2, ymm1
716     vunpcklps    ymm7, ymm0, ymm3
717     vunpckhps    ymm5, ymm0, ymm3
718
719     vextractf128 [%3+%1*2],      ymm7, 0
720     vextractf128 [%3+%1*2+0x10], ymm5, 0
721     vextractf128 [%3+%1*2+0x20], ymm7, 1
722     vextractf128 [%3+%1*2+0x30], ymm5, 1
723
724     vextractf128 [%3+%2*2],      ymm6, 0
725     vextractf128 [%3+%2*2+0x10], ymm4, 0
726     vextractf128 [%3+%2*2+0x20], ymm6, 1
727     vextractf128 [%3+%2*2+0x30], ymm4, 1
728     sub      %2,   0x20
729     add      %1,   0x20
730     jl       .post
731 %endmacro
732
733 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
734 .post:
735     movaps   xmm1, [%3+%1*2]
736     movaps   xmm0, [%3+%1*2+0x10]
737     CMUL     %1,   xmm0, xmm1, %3, %4, %5
738     movaps   xmm5, [%3+%2*2]
739     movaps   xmm4, [%3+%2*2+0x10]
740     CMUL     %2,   xmm4, xmm5, %3, %4, %5
741     shufps   xmm1, xmm1, 0x1b
742     shufps   xmm5, xmm5, 0x1b
743     movaps   xmm6, xmm4
744     unpckhps xmm4, xmm1
745     unpcklps xmm6, xmm1
746     movaps   xmm2, xmm0
747     unpcklps xmm0, xmm5
748     unpckhps xmm2, xmm5
749     movaps   [%3+%2*2],      xmm6
750     movaps   [%3+%2*2+0x10], xmm4
751     movaps   [%3+%1*2],      xmm0
752     movaps   [%3+%1*2+0x10], xmm2
753     sub      %2,   0x10
754     add      %1,   0x10
755     jl       .post
756 %endmacro
757
758 %macro DECL_IMDCT 1
759 cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *input
760 %if ARCH_X86_64
761 %define rrevtab r7
762 %define rtcos   r8
763 %define rtsin   r9
764 %else
765 %define rrevtab r6
766 %define rtsin   r6
767 %define rtcos   r5
768 %endif
769     mov   r3d, [r0+FFTContext.mdctsize]
770     add   r2, r3
771     shr   r3, 1
772     mov   rtcos, [r0+FFTContext.tcos]
773     mov   rtsin, [r0+FFTContext.tsin]
774     add   rtcos, r3
775     add   rtsin, r3
776 %if ARCH_X86_64 == 0
777     push  rtcos
778     push  rtsin
779 %endif
780     shr   r3, 1
781     mov   rrevtab, [r0+FFTContext.revtab]
782     add   rrevtab, r3
783 %if ARCH_X86_64 == 0
784     push  rrevtab
785 %endif
786
787     sub   r3, 4
788 %if ARCH_X86_64
789     xor   r4, r4
790     sub   r4, r3
791 %endif
792 .pre:
793 %if ARCH_X86_64 == 0
794 ;unspill
795     xor   r4, r4
796     sub   r4, r3
797     mov   rtsin, [esp+4]
798     mov   rtcos, [esp+8]
799 %endif
800
801     PREROTATER r4, r3, r2, rtcos, rtsin
802 %if ARCH_X86_64
803     movzx  r5,  word [rrevtab+r4-4]
804     movzx  r6,  word [rrevtab+r4-2]
805     movzx  r10, word [rrevtab+r3]
806     movzx  r11, word [rrevtab+r3+2]
807     movlps [r1+r5 *8], xmm0
808     movhps [r1+r6 *8], xmm0
809     movlps [r1+r10*8], xmm1
810     movhps [r1+r11*8], xmm1
811     add    r4, 4
812 %else
813     mov    r6, [esp]
814     movzx  r5, word [r6+r4-4]
815     movzx  r4, word [r6+r4-2]
816     movlps [r1+r5*8], xmm0
817     movhps [r1+r4*8], xmm0
818     movzx  r5, word [r6+r3]
819     movzx  r4, word [r6+r3+2]
820     movlps [r1+r5*8], xmm1
821     movhps [r1+r4*8], xmm1
822 %endif
823     sub    r3, 4
824     jns    .pre
825
826     mov  r5, r0
827     mov  r6, r1
828     mov  r0, r1
829     mov  r1d, [r5+FFTContext.nbits]
830
831     FFT_DISPATCH SUFFIX, r1
832
833     mov  r0d, [r5+FFTContext.mdctsize]
834     add  r6, r0
835     shr  r0, 1
836 %if ARCH_X86_64 == 0
837 %define rtcos r2
838 %define rtsin r3
839     mov  rtcos, [esp+8]
840     mov  rtsin, [esp+4]
841 %endif
842     neg  r0
843     mov  r1, -mmsize
844     sub  r1, r0
845     %1 r0, r1, r6, rtcos, rtsin
846 %if ARCH_X86_64 == 0
847     add esp, 12
848 %endif
849 %if mmsize == 32
850     vzeroupper
851 %endif
852     RET
853 %endmacro
854
855 DECL_IMDCT POSROTATESHUF
856
857 INIT_YMM avx
858
859 %if HAVE_AVX
860 DECL_IMDCT POSROTATESHUF_AVX
861 %endif