Merge commit '6860b4081d046558c44b1b42f22022ea341a2a73'
[ffmpeg.git] / libavcodec / x86 / fft.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/x86util.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     .fftperm:  pointer 1
51     .fftcalc:  pointer 1
52     .imdctcalc:pointer 1
53     .imdcthalf:pointer 1
54 endstruc
55
56 %define M_SQRT1_2 0.70710678118654752440
57 %define M_COS_PI_1_8 0.923879532511287
58 %define M_COS_PI_3_8 0.38268343236509
59
60 align 32
61 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
62 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
63
64 ps_root2: times 8 dd M_SQRT1_2
65 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
66 ps_p1p1m1p1: dd 0, 0, 1<<31, 0, 0, 0, 1<<31, 0
67
68 perm1: dd 0x00, 0x02, 0x03, 0x01, 0x03, 0x00, 0x02, 0x01
69 perm2: dd 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x02, 0x03
70 ps_p1p1m1p1root2: dd 1.0, 1.0, -1.0, 1.0, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2
71 ps_m1m1p1m1p1m1m1m1: dd 1<<31, 1<<31, 0, 1<<31, 0, 1<<31, 1<<31, 1<<31
72 ps_m1m1m1m1: times 4 dd 1<<31
73 ps_m1p1: dd 1<<31, 0
74
75 %assign i 16
76 %rep 13
77 cextern cos_ %+ i
78 %assign i i<<1
79 %endrep
80
81 %if ARCH_X86_64
82     %define pointer dq
83 %else
84     %define pointer dd
85 %endif
86
87 %macro IF0 1+
88 %endmacro
89 %macro IF1 1+
90     %1
91 %endmacro
92
93 SECTION_TEXT
94
95 %macro T2_3DNOW 4 ; z0, z1, mem0, mem1
96     mova     %1, %3
97     mova     %2, %1
98     pfadd    %1, %4
99     pfsub    %2, %4
100 %endmacro
101
102 %macro T4_3DNOW 6 ; z0, z1, z2, z3, tmp0, tmp1
103     mova     %5, %3
104     pfsub    %3, %4
105     pfadd    %5, %4 ; {t6,t5}
106     pxor     %3, [ps_m1p1] ; {t8,t7}
107     mova     %6, %1
108     PSWAPD   %3, %3
109     pfadd    %1, %5 ; {r0,i0}
110     pfsub    %6, %5 ; {r2,i2}
111     mova     %4, %2
112     pfadd    %2, %3 ; {r1,i1}
113     pfsub    %4, %3 ; {r3,i3}
114     SWAP     %3, %6
115 %endmacro
116
117 ;  in: %1 = {r0,i0,r2,i2,r4,i4,r6,i6}
118 ;      %2 = {r1,i1,r3,i3,r5,i5,r7,i7}
119 ;      %3, %4, %5 tmp
120 ; out: %1 = {r0,r1,r2,r3,i0,i1,i2,i3}
121 ;      %2 = {r4,r5,r6,r7,i4,i5,i6,i7}
122 %macro T8_AVX 5
123     vsubps     %5, %1, %2       ; v  = %1 - %2
124     vaddps     %3, %1, %2       ; w  = %1 + %2
125     vmulps     %2, %5, [ps_p1p1m1p1root2]  ; v *= vals1
126     vpermilps  %2, %2, [perm1]
127     vblendps   %1, %2, %3, 0x33 ; q = {w1,w2,v4,v2,w5,w6,v7,v6}
128     vshufps    %5, %3, %2, 0x4e ; r = {w3,w4,v1,v3,w7,w8,v8,v5}
129     vsubps     %4, %5, %1       ; s = r - q
130     vaddps     %1, %5, %1       ; u = r + q
131     vpermilps  %1, %1, [perm2]  ; k  = {u1,u2,u3,u4,u6,u5,u7,u8}
132     vshufps    %5, %4, %1, 0xbb
133     vshufps    %3, %4, %1, 0xee
134     vperm2f128 %3, %3, %5, 0x13
135     vxorps     %4, %4, [ps_m1m1p1m1p1m1m1m1]  ; s *= {1,1,-1,-1,1,-1,-1,-1}
136     vshufps    %2, %1, %4, 0xdd
137     vshufps    %1, %1, %4, 0x88
138     vperm2f128 %4, %2, %1, 0x02 ; v  = {k1,k3,s1,s3,k2,k4,s2,s4}
139     vperm2f128 %1, %1, %2, 0x13 ; w  = {k6,k8,s6,s8,k5,k7,s5,s7}
140     vsubps     %5, %1, %3
141     vblendps   %1, %5, %1, 0x55 ; w -= {0,s7,0,k7,0,s8,0,k8}
142     vsubps     %2, %4, %1       ; %2 = v - w
143     vaddps     %1, %4, %1       ; %1 = v + w
144 %endmacro
145
146 ; In SSE mode do one fft4 transforms
147 ; in:  %1={r0,i0,r2,i2} %2={r1,i1,r3,i3}
148 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3}
149 ;
150 ; In AVX mode do two fft4 transforms
151 ; in:  %1={r0,i0,r2,i2,r4,i4,r6,i6} %2={r1,i1,r3,i3,r5,i5,r7,i7}
152 ; out: %1={r0,r1,r2,r3,r4,r5,r6,r7} %2={i0,i1,i2,i3,i4,i5,i6,i7}
153 %macro T4_SSE 3
154     subps    %3, %1, %2       ; {t3,t4,-t8,t7}
155     addps    %1, %1, %2       ; {t1,t2,t6,t5}
156     xorps    %3, %3, [ps_p1p1m1p1]
157     shufps   %2, %1, %3, 0xbe ; {t6,t5,t7,t8}
158     shufps   %1, %1, %3, 0x44 ; {t1,t2,t3,t4}
159     subps    %3, %1, %2       ; {r2,i2,r3,i3}
160     addps    %1, %1, %2       ; {r0,i0,r1,i1}
161     shufps   %2, %1, %3, 0xdd ; {i0,i1,i2,i3}
162     shufps   %1, %1, %3, 0x88 ; {r0,r1,r2,r3}
163 %endmacro
164
165 ; In SSE mode do one FFT8
166 ; in:  %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %3={r4,i4,r6,i6} %4={r5,i5,r7,i7}
167 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %1={r4,r5,r6,r7} %2={i4,i5,i6,i7}
168 ;
169 ; In AVX mode do two FFT8
170 ; in:  %1={r0,i0,r2,i2,r8, i8, r10,i10} %2={r1,i1,r3,i3,r9, i9, r11,i11}
171 ;      %3={r4,i4,r6,i6,r12,i12,r14,i14} %4={r5,i5,r7,i7,r13,i13,r15,i15}
172 ; out: %1={r0,r1,r2,r3,r8, r9, r10,r11} %2={i0,i1,i2,i3,i8, i9, i10,i11}
173 ;      %3={r4,r5,r6,r7,r12,r13,r14,r15} %4={i4,i5,i6,i7,i12,i13,i14,i15}
174 %macro T8_SSE 6
175     addps    %6, %3, %4       ; {t1,t2,t3,t4}
176     subps    %3, %3, %4       ; {r5,i5,r7,i7}
177     shufps   %4, %3, %3, 0xb1 ; {i5,r5,i7,r7}
178     mulps    %3, %3, [ps_root2mppm] ; {-r5,i5,r7,-i7}
179     mulps    %4, %4, [ps_root2]
180     addps    %3, %3, %4       ; {t8,t7,ta,t9}
181     shufps   %4, %6, %3, 0x9c ; {t1,t4,t7,ta}
182     shufps   %6, %6, %3, 0x36 ; {t3,t2,t9,t8}
183     subps    %3, %6, %4       ; {t6,t5,tc,tb}
184     addps    %6, %6, %4       ; {t1,t2,t9,ta}
185     shufps   %5, %6, %3, 0x8d ; {t2,ta,t6,tc}
186     shufps   %6, %6, %3, 0xd8 ; {t1,t9,t5,tb}
187     subps    %3, %1, %6       ; {r4,r5,r6,r7}
188     addps    %1, %1, %6       ; {r0,r1,r2,r3}
189     subps    %4, %2, %5       ; {i4,i5,i6,i7}
190     addps    %2, %2, %5       ; {i0,i1,i2,i3}
191 %endmacro
192
193 ; scheduled for cpu-bound sizes
194 %macro PASS_SMALL 3 ; (to load m4-m7), wre, wim
195 IF%1 mova    m4, Z(4)
196 IF%1 mova    m5, Z(5)
197     mova     m0, %2 ; wre
198     mova     m1, %3 ; wim
199     mulps    m2, m4, m0 ; r2*wre
200 IF%1 mova    m6, Z2(6)
201     mulps    m3, m5, m1 ; i2*wim
202 IF%1 mova    m7, Z2(7)
203     mulps    m4, m4, m1 ; r2*wim
204     mulps    m5, m5, m0 ; i2*wre
205     addps    m2, m2, m3 ; r2*wre + i2*wim
206     mulps    m3, m1, m7 ; i3*wim
207     subps    m5, m5, m4 ; i2*wre - r2*wim
208     mulps    m1, m1, m6 ; r3*wim
209     mulps    m4, m0, m6 ; r3*wre
210     mulps    m0, m0, m7 ; i3*wre
211     subps    m4, m4, m3 ; r3*wre - i3*wim
212     mova     m3, Z(0)
213     addps    m0, m0, m1 ; i3*wre + r3*wim
214     subps    m1, m4, m2 ; t3
215     addps    m4, m4, m2 ; t5
216     subps    m3, m3, m4 ; r2
217     addps    m4, m4, Z(0) ; r0
218     mova     m6, Z(2)
219     mova   Z(4), m3
220     mova   Z(0), m4
221     subps    m3, m5, m0 ; t4
222     subps    m4, m6, m3 ; r3
223     addps    m3, m3, m6 ; r1
224     mova  Z2(6), m4
225     mova   Z(2), m3
226     mova     m2, Z(3)
227     addps    m3, m5, m0 ; t6
228     subps    m2, m2, m1 ; i3
229     mova     m7, Z(1)
230     addps    m1, m1, Z(3) ; i1
231     mova  Z2(7), m2
232     mova   Z(3), m1
233     subps    m4, m7, m3 ; i2
234     addps    m3, m3, m7 ; i0
235     mova   Z(5), m4
236     mova   Z(1), m3
237 %endmacro
238
239 ; scheduled to avoid store->load aliasing
240 %macro PASS_BIG 1 ; (!interleave)
241     mova     m4, Z(4) ; r2
242     mova     m5, Z(5) ; i2
243     mova     m0, [wq] ; wre
244     mova     m1, [wq+o1q] ; wim
245     mulps    m2, m4, m0 ; r2*wre
246     mova     m6, Z2(6) ; r3
247     mulps    m3, m5, m1 ; i2*wim
248     mova     m7, Z2(7) ; i3
249     mulps    m4, m4, m1 ; r2*wim
250     mulps    m5, m5, m0 ; i2*wre
251     addps    m2, m2, m3 ; r2*wre + i2*wim
252     mulps    m3, m1, m7 ; i3*wim
253     mulps    m1, m1, m6 ; r3*wim
254     subps    m5, m5, m4 ; i2*wre - r2*wim
255     mulps    m4, m0, m6 ; r3*wre
256     mulps    m0, m0, m7 ; i3*wre
257     subps    m4, m4, m3 ; r3*wre - i3*wim
258     mova     m3, Z(0)
259     addps    m0, m0, m1 ; i3*wre + r3*wim
260     subps    m1, m4, m2 ; t3
261     addps    m4, m4, m2 ; t5
262     subps    m3, m3, m4 ; r2
263     addps    m4, m4, Z(0) ; r0
264     mova     m6, Z(2)
265     mova   Z(4), m3
266     mova   Z(0), m4
267     subps    m3, m5, m0 ; t4
268     subps    m4, m6, m3 ; r3
269     addps    m3, m3, m6 ; r1
270 IF%1 mova Z2(6), m4
271 IF%1 mova  Z(2), m3
272     mova     m2, Z(3)
273     addps    m5, m5, m0 ; t6
274     subps    m2, m2, m1 ; i3
275     mova     m7, Z(1)
276     addps    m1, m1, Z(3) ; i1
277 IF%1 mova Z2(7), m2
278 IF%1 mova  Z(3), m1
279     subps    m6, m7, m5 ; i2
280     addps    m5, m5, m7 ; i0
281 IF%1 mova  Z(5), m6
282 IF%1 mova  Z(1), m5
283 %if %1==0
284     INTERL m1, m3, m7, Z, 2
285     INTERL m2, m4, m0, Z2, 6
286
287     mova     m1, Z(0)
288     mova     m2, Z(4)
289
290     INTERL m5, m1, m3, Z, 0
291     INTERL m6, m2, m7, Z, 4
292 %endif
293 %endmacro
294
295 %macro PUNPCK 3
296     mova      %3, %1
297     punpckldq %1, %2
298     punpckhdq %3, %2
299 %endmacro
300
301 %define Z(x) [r0+mmsize*x]
302 %define Z2(x) [r0+mmsize*x]
303 %define ZH(x) [r0+mmsize*x+mmsize/2]
304
305 INIT_YMM avx
306
307 %if HAVE_AVX_EXTERNAL
308 align 16
309 fft8_avx:
310     mova      m0, Z(0)
311     mova      m1, Z(1)
312     T8_AVX    m0, m1, m2, m3, m4
313     mova      Z(0), m0
314     mova      Z(1), m1
315     ret
316
317
318 align 16
319 fft16_avx:
320     mova       m2, Z(2)
321     mova       m3, Z(3)
322     T4_SSE     m2, m3, m7
323
324     mova       m0, Z(0)
325     mova       m1, Z(1)
326     T8_AVX     m0, m1, m4, m5, m7
327
328     mova       m4, [ps_cos16_1]
329     mova       m5, [ps_cos16_2]
330     vmulps     m6, m2, m4
331     vmulps     m7, m3, m5
332     vaddps     m7, m7, m6
333     vmulps     m2, m2, m5
334     vmulps     m3, m3, m4
335     vsubps     m3, m3, m2
336     vblendps   m2, m7, m3, 0xf0
337     vperm2f128 m3, m7, m3, 0x21
338     vaddps     m4, m2, m3
339     vsubps     m2, m3, m2
340     vperm2f128 m2, m2, m2, 0x01
341     vsubps     m3, m1, m2
342     vaddps     m1, m1, m2
343     vsubps     m5, m0, m4
344     vaddps     m0, m0, m4
345     vextractf128   Z(0), m0, 0
346     vextractf128  ZH(0), m1, 0
347     vextractf128   Z(1), m0, 1
348     vextractf128  ZH(1), m1, 1
349     vextractf128   Z(2), m5, 0
350     vextractf128  ZH(2), m3, 0
351     vextractf128   Z(3), m5, 1
352     vextractf128  ZH(3), m3, 1
353     ret
354
355 align 16
356 fft32_avx:
357     call fft16_avx
358
359     mova m0, Z(4)
360     mova m1, Z(5)
361
362     T4_SSE      m0, m1, m4
363
364     mova m2, Z(6)
365     mova m3, Z(7)
366
367     T8_SSE      m0, m1, m2, m3, m4, m6
368     ; m0={r0,r1,r2,r3,r8, r9, r10,r11} m1={i0,i1,i2,i3,i8, i9, i10,i11}
369     ; m2={r4,r5,r6,r7,r12,r13,r14,r15} m3={i4,i5,i6,i7,i12,i13,i14,i15}
370
371     vperm2f128  m4, m0, m2, 0x20
372     vperm2f128  m5, m1, m3, 0x20
373     vperm2f128  m6, m0, m2, 0x31
374     vperm2f128  m7, m1, m3, 0x31
375
376     PASS_SMALL 0, [cos_32], [cos_32+32]
377
378     ret
379
380 fft32_interleave_avx:
381     call fft32_avx
382     mov r2d, 32
383 .deint_loop:
384     mova     m2, Z(0)
385     mova     m3, Z(1)
386     vunpcklps      m0, m2, m3
387     vunpckhps      m1, m2, m3
388     vextractf128   Z(0), m0, 0
389     vextractf128  ZH(0), m1, 0
390     vextractf128   Z(1), m0, 1
391     vextractf128  ZH(1), m1, 1
392     add r0, mmsize*2
393     sub r2d, mmsize/4
394     jg .deint_loop
395     ret
396
397 %endif
398
399 INIT_XMM sse
400
401 align 16
402 fft4_avx:
403 fft4_sse:
404     mova     m0, Z(0)
405     mova     m1, Z(1)
406     T4_SSE   m0, m1, m2
407     mova   Z(0), m0
408     mova   Z(1), m1
409     ret
410
411 align 16
412 fft8_sse:
413     mova     m0, Z(0)
414     mova     m1, Z(1)
415     T4_SSE   m0, m1, m2
416     mova     m2, Z(2)
417     mova     m3, Z(3)
418     T8_SSE   m0, m1, m2, m3, m4, m5
419     mova   Z(0), m0
420     mova   Z(1), m1
421     mova   Z(2), m2
422     mova   Z(3), m3
423     ret
424
425 align 16
426 fft16_sse:
427     mova     m0, Z(0)
428     mova     m1, Z(1)
429     T4_SSE   m0, m1, m2
430     mova     m2, Z(2)
431     mova     m3, Z(3)
432     T8_SSE   m0, m1, m2, m3, m4, m5
433     mova     m4, Z(4)
434     mova     m5, Z(5)
435     mova   Z(0), m0
436     mova   Z(1), m1
437     mova   Z(2), m2
438     mova   Z(3), m3
439     T4_SSE   m4, m5, m6
440     mova     m6, Z2(6)
441     mova     m7, Z2(7)
442     T4_SSE   m6, m7, m0
443     PASS_SMALL 0, [cos_16], [cos_16+16]
444     ret
445
446
447 %macro FFT48_3DNOW 0
448 align 16
449 fft4 %+ SUFFIX:
450     T2_3DNOW m0, m1, Z(0), Z(1)
451     mova     m2, Z(2)
452     mova     m3, Z(3)
453     T4_3DNOW m0, m1, m2, m3, m4, m5
454     PUNPCK   m0, m1, m4
455     PUNPCK   m2, m3, m5
456     mova   Z(0), m0
457     mova   Z(1), m4
458     mova   Z(2), m2
459     mova   Z(3), m5
460     ret
461
462 align 16
463 fft8 %+ SUFFIX:
464     T2_3DNOW m0, m1, Z(0), Z(1)
465     mova     m2, Z(2)
466     mova     m3, Z(3)
467     T4_3DNOW m0, m1, m2, m3, m4, m5
468     mova   Z(0), m0
469     mova   Z(2), m2
470     T2_3DNOW m4, m5,  Z(4),  Z(5)
471     T2_3DNOW m6, m7, Z2(6), Z2(7)
472     PSWAPD   m0, m5
473     PSWAPD   m2, m7
474     pxor     m0, [ps_m1p1]
475     pxor     m2, [ps_m1p1]
476     pfsub    m5, m0
477     pfadd    m7, m2
478     pfmul    m5, [ps_root2]
479     pfmul    m7, [ps_root2]
480     T4_3DNOW m1, m3, m5, m7, m0, m2
481     mova   Z(5), m5
482     mova  Z2(7), m7
483     mova     m0, Z(0)
484     mova     m2, Z(2)
485     T4_3DNOW m0, m2, m4, m6, m5, m7
486     PUNPCK   m0, m1, m5
487     PUNPCK   m2, m3, m7
488     mova   Z(0), m0
489     mova   Z(1), m5
490     mova   Z(2), m2
491     mova   Z(3), m7
492     PUNPCK   m4,  Z(5), m5
493     PUNPCK   m6, Z2(7), m7
494     mova   Z(4), m4
495     mova   Z(5), m5
496     mova  Z2(6), m6
497     mova  Z2(7), m7
498     ret
499 %endmacro
500
501 %if ARCH_X86_32
502 %macro PSWAPD 2
503 %if cpuflag(3dnowext)
504     pswapd %1, %2
505 %elifidn %1, %2
506     movd [r0+12], %1
507     punpckhdq %1, [r0+8]
508 %else
509     movq  %1, %2
510     psrlq %1, 32
511     punpckldq %1, %2
512 %endif
513 %endmacro
514
515 INIT_MMX 3dnowext
516 FFT48_3DNOW
517
518 INIT_MMX 3dnow
519 FFT48_3DNOW
520 %endif
521
522 %define Z(x) [zcq + o1q*(x&6) + mmsize*(x&1)]
523 %define Z2(x) [zcq + o3q + mmsize*(x&1)]
524 %define ZH(x) [zcq + o1q*(x&6) + mmsize*(x&1) + mmsize/2]
525 %define Z2H(x) [zcq + o3q + mmsize*(x&1) + mmsize/2]
526
527 %macro DECL_PASS 2+ ; name, payload
528 align 16
529 %1:
530 DEFINE_ARGS zc, w, n, o1, o3
531     lea o3q, [nq*3]
532     lea o1q, [nq*8]
533     shl o3q, 4
534 .loop:
535     %2
536     add zcq, mmsize*2
537     add  wq, mmsize
538     sub  nd, mmsize/8
539     jg .loop
540     rep ret
541 %endmacro
542
543 %macro FFT_DISPATCH 2; clobbers 5 GPRs, 8 XMMs
544     lea r2, [dispatch_tab%1]
545     mov r2, [r2 + (%2q-2)*gprsize]
546 %ifdef PIC
547     lea r3, [$$]
548     add r2, r3
549 %endif
550     call r2
551 %endmacro ; FFT_DISPATCH
552
553 INIT_YMM avx
554
555 %if HAVE_AVX_EXTERNAL
556 %macro INTERL_AVX 5
557     vunpckhps      %3, %2, %1
558     vunpcklps      %2, %2, %1
559     vextractf128   %4(%5), %2, 0
560     vextractf128  %4 %+ H(%5), %3, 0
561     vextractf128   %4(%5 + 1), %2, 1
562     vextractf128  %4 %+ H(%5 + 1), %3, 1
563 %endmacro
564
565 %define INTERL INTERL_AVX
566
567 DECL_PASS pass_avx, PASS_BIG 1
568 DECL_PASS pass_interleave_avx, PASS_BIG 0
569
570 cglobal fft_calc, 2,5,8
571     mov     r3d, [r0 + FFTContext.nbits]
572     mov     r0, r1
573     mov     r1, r3
574     FFT_DISPATCH _interleave %+ SUFFIX, r1
575     REP_RET
576
577 %endif
578
579 INIT_XMM sse
580
581 %macro INTERL_SSE 5
582     mova     %3, %2
583     unpcklps %2, %1
584     unpckhps %3, %1
585     mova  %4(%5), %2
586     mova  %4(%5+1), %3
587 %endmacro
588
589 %define INTERL INTERL_SSE
590
591 DECL_PASS pass_sse, PASS_BIG 1
592 DECL_PASS pass_interleave_sse, PASS_BIG 0
593
594 %macro FFT_CALC_FUNC 0
595 cglobal fft_calc, 2,5,8
596     mov     r3d, [r0 + FFTContext.nbits]
597     PUSH    r1
598     PUSH    r3
599     mov     r0, r1
600     mov     r1, r3
601     FFT_DISPATCH _interleave %+ SUFFIX, r1
602     POP     rcx
603     POP     r4
604     cmp     rcx, 3+(mmsize/16)
605     jg      .end
606     mov     r2, -1
607     add     rcx, 3
608     shl     r2, cl
609     sub     r4, r2
610 .loop:
611 %if mmsize == 8
612     PSWAPD  m0, [r4 + r2 + 4]
613     mova [r4 + r2 + 4], m0
614 %else
615     movaps   xmm0, [r4 + r2]
616     movaps   xmm1, xmm0
617     unpcklps xmm0, [r4 + r2 + 16]
618     unpckhps xmm1, [r4 + r2 + 16]
619     movaps   [r4 + r2],      xmm0
620     movaps   [r4 + r2 + 16], xmm1
621 %endif
622     add      r2, mmsize*2
623     jl       .loop
624 .end:
625 %if cpuflag(3dnow)
626     femms
627     RET
628 %else
629     REP_RET
630 %endif
631 %endmacro
632
633 %if ARCH_X86_32
634 INIT_MMX 3dnow
635 FFT_CALC_FUNC
636 INIT_MMX 3dnowext
637 FFT_CALC_FUNC
638 %endif
639 INIT_XMM sse
640 FFT_CALC_FUNC
641
642 cglobal fft_permute, 2,7,1
643     mov     r4,  [r0 + FFTContext.revtab]
644     mov     r5,  [r0 + FFTContext.tmpbuf]
645     mov     ecx, [r0 + FFTContext.nbits]
646     mov     r2, 1
647     shl     r2, cl
648     xor     r0, r0
649 %if ARCH_X86_32
650     mov     r1, r1m
651 %endif
652 .loop:
653     movaps  xmm0, [r1 + 8*r0]
654     movzx   r6, word [r4 + 2*r0]
655     movzx   r3, word [r4 + 2*r0 + 2]
656     movlps  [r5 + 8*r6], xmm0
657     movhps  [r5 + 8*r3], xmm0
658     add     r0, 2
659     cmp     r0, r2
660     jl      .loop
661     shl     r2, 3
662     add     r1, r2
663     add     r5, r2
664     neg     r2
665 ; nbits >= 2 (FFT4) and sizeof(FFTComplex)=8 => at least 32B
666 .loopcopy:
667     movaps  xmm0, [r5 + r2]
668     movaps  xmm1, [r5 + r2 + 16]
669     movaps  [r1 + r2], xmm0
670     movaps  [r1 + r2 + 16], xmm1
671     add     r2, 32
672     jl      .loopcopy
673     REP_RET
674
675 %macro IMDCT_CALC_FUNC 0
676 cglobal imdct_calc, 3,5,3
677     mov     r3d, [r0 + FFTContext.mdctsize]
678     mov     r4,  [r0 + FFTContext.imdcthalf]
679     add     r1,  r3
680     PUSH    r3
681     PUSH    r1
682 %if ARCH_X86_32
683     push    r2
684     push    r1
685     push    r0
686 %else
687     sub     rsp, 8
688 %endif
689     call    r4
690 %if ARCH_X86_32
691     add     esp, 12
692 %else
693     add     rsp, 8
694 %endif
695     POP     r1
696     POP     r3
697     lea     r0, [r1 + 2*r3]
698     mov     r2, r3
699     sub     r3, mmsize
700     neg     r2
701     mova    m2, [ps_m1m1m1m1]
702 .loop:
703 %if mmsize == 8
704     PSWAPD  m0, [r1 + r3]
705     PSWAPD  m1, [r0 + r2]
706     pxor    m0, m2
707 %else
708     mova    m0, [r1 + r3]
709     mova    m1, [r0 + r2]
710     shufps  m0, m0, 0x1b
711     shufps  m1, m1, 0x1b
712     xorps   m0, m2
713 %endif
714     mova [r0 + r3], m1
715     mova [r1 + r2], m0
716     sub     r3, mmsize
717     add     r2, mmsize
718     jl      .loop
719 %if cpuflag(3dnow)
720     femms
721     RET
722 %else
723     REP_RET
724 %endif
725 %endmacro
726
727 %if ARCH_X86_32
728 INIT_MMX 3dnow
729 IMDCT_CALC_FUNC
730 INIT_MMX 3dnowext
731 IMDCT_CALC_FUNC
732 %endif
733
734 INIT_XMM sse
735 IMDCT_CALC_FUNC
736
737 %if ARCH_X86_32
738 INIT_MMX 3dnow
739 %define mulps pfmul
740 %define addps pfadd
741 %define subps pfsub
742 %define unpcklps punpckldq
743 %define unpckhps punpckhdq
744 DECL_PASS pass_3dnow, PASS_SMALL 1, [wq], [wq+o1q]
745 DECL_PASS pass_interleave_3dnow, PASS_BIG 0
746 %define pass_3dnowext pass_3dnow
747 %define pass_interleave_3dnowext pass_interleave_3dnow
748 %endif
749
750 %ifdef PIC
751 %define SECTION_REL - $$
752 %else
753 %define SECTION_REL
754 %endif
755
756 %macro DECL_FFT 1-2 ; nbits, suffix
757 %ifidn %0, 1
758 %xdefine fullsuffix SUFFIX
759 %else
760 %xdefine fullsuffix %2 %+ SUFFIX
761 %endif
762 %xdefine list_of_fft fft4 %+ SUFFIX SECTION_REL, fft8 %+ SUFFIX SECTION_REL
763 %if %1>=5
764 %xdefine list_of_fft list_of_fft, fft16 %+ SUFFIX SECTION_REL
765 %endif
766 %if %1>=6
767 %xdefine list_of_fft list_of_fft, fft32 %+ fullsuffix SECTION_REL
768 %endif
769
770 %assign n 1<<%1
771 %rep 17-%1
772 %assign n2 n/2
773 %assign n4 n/4
774 %xdefine list_of_fft list_of_fft, fft %+ n %+ fullsuffix SECTION_REL
775
776 align 16
777 fft %+ n %+ fullsuffix:
778     call fft %+ n2 %+ SUFFIX
779     add r0, n*4 - (n&(-2<<%1))
780     call fft %+ n4 %+ SUFFIX
781     add r0, n*2 - (n2&(-2<<%1))
782     call fft %+ n4 %+ SUFFIX
783     sub r0, n*6 + (n2&(-2<<%1))
784     lea r1, [cos_ %+ n]
785     mov r2d, n4/2
786     jmp pass %+ fullsuffix
787
788 %assign n n*2
789 %endrep
790 %undef n
791
792 align 8
793 dispatch_tab %+ fullsuffix: pointer list_of_fft
794 %endmacro ; DECL_FFT
795
796 %if HAVE_AVX_EXTERNAL
797 INIT_YMM avx
798 DECL_FFT 6
799 DECL_FFT 6, _interleave
800 %endif
801 INIT_XMM sse
802 DECL_FFT 5
803 DECL_FFT 5, _interleave
804 %if ARCH_X86_32
805 INIT_MMX 3dnow
806 DECL_FFT 4
807 DECL_FFT 4, _interleave
808 INIT_MMX 3dnowext
809 DECL_FFT 4
810 DECL_FFT 4, _interleave
811 %endif
812
813 INIT_XMM sse
814 %undef mulps
815 %undef addps
816 %undef subps
817 %undef unpcklps
818 %undef unpckhps
819
820 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
821 %if mmsize == 8 ; j*2+2-n4, n4-2-j*2, input+n4, tcos+n8, tsin+n8
822     PSWAPD     m0, [%3+%2*4]
823     movq       m2, [%3+%1*4-8]
824     movq       m3, m0
825     punpckldq  m0, m2
826     punpckhdq  m2, m3
827     movd       m1, [%4+%1*2-4] ; tcos[j]
828     movd       m3, [%4+%2*2]   ; tcos[n4-j-1]
829     punpckldq  m1, [%5+%1*2-4] ; tsin[j]
830     punpckldq  m3, [%5+%2*2]   ; tsin[n4-j-1]
831
832     mova       m4, m0
833     PSWAPD     m5, m1
834     pfmul      m0, m1
835     pfmul      m4, m5
836     mova       m6, m2
837     PSWAPD     m5, m3
838     pfmul      m2, m3
839     pfmul      m6, m5
840 %if cpuflag(3dnowext)
841     pfpnacc    m0, m4
842     pfpnacc    m2, m6
843 %else
844     SBUTTERFLY dq, 0, 4, 1
845     SBUTTERFLY dq, 2, 6, 3
846     pxor       m4, m7
847     pxor       m6, m7
848     pfadd      m0, m4
849     pfadd      m2, m6
850 %endif
851 %else
852     movaps   xmm0, [%3+%2*4]
853     movaps   xmm1, [%3+%1*4-0x10]
854     movaps   xmm2, xmm0
855     shufps   xmm0, xmm1, 0x88
856     shufps   xmm1, xmm2, 0x77
857     movlps   xmm4, [%4+%2*2]
858     movlps   xmm5, [%5+%2*2+0x0]
859     movhps   xmm4, [%4+%1*2-0x8]
860     movhps   xmm5, [%5+%1*2-0x8]
861     movaps   xmm2, xmm0
862     movaps   xmm3, xmm1
863     mulps    xmm0, xmm5
864     mulps    xmm1, xmm4
865     mulps    xmm2, xmm4
866     mulps    xmm3, xmm5
867     subps    xmm1, xmm0
868     addps    xmm2, xmm3
869     movaps   xmm0, xmm1
870     unpcklps xmm1, xmm2
871     unpckhps xmm0, xmm2
872 %endif
873 %endmacro
874
875 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
876     mulps      m6, %3, [%5+%1]
877     mulps      m7, %2, [%5+%1]
878     mulps      %2, %2, [%6+%1]
879     mulps      %3, %3, [%6+%1]
880     subps      %2, %2, m6
881     addps      %3, %3, m7
882 %endmacro
883
884 %macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8
885 .post:
886     vmovaps      ymm1,   [%3+%1*2]
887     vmovaps      ymm0,   [%3+%1*2+0x20]
888     vmovaps      ymm3,   [%3+%2*2]
889     vmovaps      ymm2,   [%3+%2*2+0x20]
890
891     CMUL         %1, ymm0, ymm1, %3, %4, %5
892     CMUL         %2, ymm2, ymm3, %3, %4, %5
893     vshufps      ymm1, ymm1, ymm1, 0x1b
894     vshufps      ymm3, ymm3, ymm3, 0x1b
895     vperm2f128   ymm1, ymm1, ymm1, 0x01
896     vperm2f128   ymm3, ymm3, ymm3, 0x01
897     vunpcklps    ymm6, ymm2, ymm1
898     vunpckhps    ymm4, ymm2, ymm1
899     vunpcklps    ymm7, ymm0, ymm3
900     vunpckhps    ymm5, ymm0, ymm3
901
902     vextractf128 [%3+%1*2],      ymm7, 0
903     vextractf128 [%3+%1*2+0x10], ymm5, 0
904     vextractf128 [%3+%1*2+0x20], ymm7, 1
905     vextractf128 [%3+%1*2+0x30], ymm5, 1
906
907     vextractf128 [%3+%2*2],      ymm6, 0
908     vextractf128 [%3+%2*2+0x10], ymm4, 0
909     vextractf128 [%3+%2*2+0x20], ymm6, 1
910     vextractf128 [%3+%2*2+0x30], ymm4, 1
911     sub      %2,   0x20
912     add      %1,   0x20
913     jl       .post
914 %endmacro
915
916 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
917 .post:
918     movaps   xmm1, [%3+%1*2]
919     movaps   xmm0, [%3+%1*2+0x10]
920     CMUL     %1,   xmm0, xmm1, %3, %4, %5
921     movaps   xmm5, [%3+%2*2]
922     movaps   xmm4, [%3+%2*2+0x10]
923     CMUL     %2,   xmm4, xmm5, %3, %4, %5
924     shufps   xmm1, xmm1, 0x1b
925     shufps   xmm5, xmm5, 0x1b
926     movaps   xmm6, xmm4
927     unpckhps xmm4, xmm1
928     unpcklps xmm6, xmm1
929     movaps   xmm2, xmm0
930     unpcklps xmm0, xmm5
931     unpckhps xmm2, xmm5
932     movaps   [%3+%2*2],      xmm6
933     movaps   [%3+%2*2+0x10], xmm4
934     movaps   [%3+%1*2],      xmm0
935     movaps   [%3+%1*2+0x10], xmm2
936     sub      %2,   0x10
937     add      %1,   0x10
938     jl       .post
939 %endmacro
940
941 %macro CMUL_3DNOW 6
942     mova       m6, [%1+%2*2]
943     mova       %3, [%1+%2*2+8]
944     mova       %4, m6
945     mova       m7, %3
946     pfmul      m6, [%5+%2]
947     pfmul      %3, [%6+%2]
948     pfmul      %4, [%6+%2]
949     pfmul      m7, [%5+%2]
950     pfsub      %3, m6
951     pfadd      %4, m7
952 %endmacro
953
954 %macro POSROTATESHUF_3DNOW 5 ;j, k, z+n8, tcos+n8, tsin+n8
955 .post:
956     CMUL_3DNOW %3, %1, m0, m1, %4, %5
957     CMUL_3DNOW %3, %2, m2, m3, %4, %5
958     movd  [%3+%1*2+ 0], m0
959     movd  [%3+%2*2+12], m1
960     movd  [%3+%2*2+ 0], m2
961     movd  [%3+%1*2+12], m3
962     psrlq      m0, 32
963     psrlq      m1, 32
964     psrlq      m2, 32
965     psrlq      m3, 32
966     movd  [%3+%1*2+ 8], m0
967     movd  [%3+%2*2+ 4], m1
968     movd  [%3+%2*2+ 8], m2
969     movd  [%3+%1*2+ 4], m3
970     sub        %2, 8
971     add        %1, 8
972     jl         .post
973 %endmacro
974
975 %macro DECL_IMDCT 1
976 cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *input
977 %if ARCH_X86_64
978 %define rrevtab r7
979 %define rtcos   r8
980 %define rtsin   r9
981 %else
982 %define rrevtab r6
983 %define rtsin   r6
984 %define rtcos   r5
985 %endif
986     mov   r3d, [r0+FFTContext.mdctsize]
987     add   r2, r3
988     shr   r3, 1
989     mov   rtcos, [r0+FFTContext.tcos]
990     mov   rtsin, [r0+FFTContext.tsin]
991     add   rtcos, r3
992     add   rtsin, r3
993 %if ARCH_X86_64 == 0
994     push  rtcos
995     push  rtsin
996 %endif
997     shr   r3, 1
998     mov   rrevtab, [r0+FFTContext.revtab]
999     add   rrevtab, r3
1000 %if ARCH_X86_64 == 0
1001     push  rrevtab
1002 %endif
1003
1004 %if mmsize == 8
1005     sub   r3, 2
1006 %else
1007     sub   r3, 4
1008 %endif
1009 %if ARCH_X86_64 || mmsize == 8
1010     xor   r4, r4
1011     sub   r4, r3
1012 %endif
1013 %if notcpuflag(3dnowext) && mmsize == 8
1014     movd  m7, [ps_m1m1m1m1]
1015 %endif
1016 .pre:
1017 %if ARCH_X86_64 == 0
1018 ;unspill
1019 %if mmsize != 8
1020     xor   r4, r4
1021     sub   r4, r3
1022 %endif
1023     mov   rtcos, [esp+8]
1024     mov   rtsin, [esp+4]
1025 %endif
1026
1027     PREROTATER r4, r3, r2, rtcos, rtsin
1028 %if mmsize == 8
1029     mov    r6, [esp]                ; rrevtab = ptr+n8
1030     movzx  r5,  word [rrevtab+r4-2] ; rrevtab[j]
1031     movzx  r6,  word [rrevtab+r3]   ; rrevtab[n4-j-1]
1032     mova [r1+r5*8], m0
1033     mova [r1+r6*8], m2
1034     add    r4, 2
1035     sub    r3, 2
1036 %else
1037 %if ARCH_X86_64
1038     movzx  r5,  word [rrevtab+r4-4]
1039     movzx  r6,  word [rrevtab+r4-2]
1040     movzx  r10, word [rrevtab+r3]
1041     movzx  r11, word [rrevtab+r3+2]
1042     movlps [r1+r5 *8], xmm0
1043     movhps [r1+r6 *8], xmm0
1044     movlps [r1+r10*8], xmm1
1045     movhps [r1+r11*8], xmm1
1046     add    r4, 4
1047 %else
1048     mov    r6, [esp]
1049     movzx  r5, word [r6+r4-4]
1050     movzx  r4, word [r6+r4-2]
1051     movlps [r1+r5*8], xmm0
1052     movhps [r1+r4*8], xmm0
1053     movzx  r5, word [r6+r3]
1054     movzx  r4, word [r6+r3+2]
1055     movlps [r1+r5*8], xmm1
1056     movhps [r1+r4*8], xmm1
1057 %endif
1058     sub    r3, 4
1059 %endif
1060     jns    .pre
1061
1062     mov  r5, r0
1063     mov  r6, r1
1064     mov  r0, r1
1065     mov  r1d, [r5+FFTContext.nbits]
1066
1067     FFT_DISPATCH SUFFIX, r1
1068
1069     mov  r0d, [r5+FFTContext.mdctsize]
1070     add  r6, r0
1071     shr  r0, 1
1072 %if ARCH_X86_64 == 0
1073 %define rtcos r2
1074 %define rtsin r3
1075     mov  rtcos, [esp+8]
1076     mov  rtsin, [esp+4]
1077 %endif
1078     neg  r0
1079     mov  r1, -mmsize
1080     sub  r1, r0
1081     %1 r0, r1, r6, rtcos, rtsin
1082 %if ARCH_X86_64 == 0
1083     add esp, 12
1084 %endif
1085 %if mmsize == 8
1086     femms
1087 %endif
1088     RET
1089 %endmacro
1090
1091 DECL_IMDCT POSROTATESHUF
1092
1093 %if ARCH_X86_32
1094 INIT_MMX 3dnow
1095 DECL_IMDCT POSROTATESHUF_3DNOW
1096
1097 INIT_MMX 3dnowext
1098 DECL_IMDCT POSROTATESHUF_3DNOW
1099 %endif
1100
1101 INIT_YMM avx
1102
1103 %if HAVE_AVX_EXTERNAL
1104 DECL_IMDCT POSROTATESHUF_AVX
1105 %endif