fft: port FFT/IMDCT 3dnow functions to yasm, and disable on x86-64.
[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 Libav.
10 ;*
11 ;* Libav 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 ;* Libav 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 Libav; 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 "x86inc.asm"
32 %include "x86util.asm"
33
34 %if ARCH_X86_64
35 %define pointer resq
36 %else
37 %define pointer resd
38 %endif
39
40 struc FFTContext
41     .nbits:    resd 1
42     .reverse:  resd 1
43     .revtab:   pointer 1
44     .tmpbuf:   pointer 1
45     .mdctsize: resd 1
46     .mdctbits: resd 1
47     .tcos:     pointer 1
48     .tsin:     pointer 1
49     .fftperm:  pointer 1
50     .fftcalc:  pointer 1
51     .imdctcalc:pointer 1
52     .imdcthalf:pointer 1
53 endstruc
54
55 SECTION_RODATA
56
57 %define M_SQRT1_2 0.70710678118654752440
58 %define M_COS_PI_1_8 0.923879532511287
59 %define M_COS_PI_3_8 0.38268343236509
60
61 align 32
62 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
63 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
64
65 ps_root2: times 8 dd M_SQRT1_2
66 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
67 ps_p1p1m1p1: dd 0, 0, 1<<31, 0, 0, 0, 1<<31, 0
68
69 perm1: dd 0x00, 0x02, 0x03, 0x01, 0x03, 0x00, 0x02, 0x01
70 perm2: dd 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x02, 0x03
71 ps_p1p1m1p1root2: dd 1.0, 1.0, -1.0, 1.0, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2
72 ps_m1m1p1m1p1m1m1m1: dd 1<<31, 1<<31, 0, 1<<31, 0, 1<<31, 1<<31, 1<<31
73 ps_m1m1m1m1: times 4 dd 1<<31
74 ps_m1p1: dd 1<<31, 0
75
76 %assign i 16
77 %rep 13
78 cextern cos_ %+ i
79 %assign i i<<1
80 %endrep
81
82 %if ARCH_X86_64
83     %define pointer dq
84 %else
85     %define pointer dd
86 %endif
87
88 %macro IF0 1+
89 %endmacro
90 %macro IF1 1+
91     %1
92 %endmacro
93
94 SECTION_TEXT
95
96 %macro T2_3DN 4 ; z0, z1, mem0, mem1
97     mova     %1, %3
98     mova     %2, %1
99     pfadd    %1, %4
100     pfsub    %2, %4
101 %endmacro
102
103 %macro T4_3DN 6 ; z0, z1, z2, z3, tmp0, tmp1
104     mova     %5, %3
105     pfsub    %3, %4
106     pfadd    %5, %4 ; {t6,t5}
107     pxor     %3, [ps_m1p1] ; {t8,t7}
108     mova     %6, %1
109     PSWAPD   %3, %3
110     pfadd    %1, %5 ; {r0,i0}
111     pfsub    %6, %5 ; {r2,i2}
112     mova     %4, %2
113     pfadd    %2, %3 ; {r1,i1}
114     pfsub    %4, %3 ; {r3,i3}
115     SWAP     %3, %6
116 %endmacro
117
118 ;  in: %1 = {r0,i0,r2,i2,r4,i4,r6,i6}
119 ;      %2 = {r1,i1,r3,i3,r5,i5,r7,i7}
120 ;      %3, %4, %5 tmp
121 ; out: %1 = {r0,r1,r2,r3,i0,i1,i2,i3}
122 ;      %2 = {r4,r5,r6,r7,i4,i5,i6,i7}
123 %macro T8_AVX 5
124     vsubps     %5, %1, %2       ; v  = %1 - %2
125     vaddps     %3, %1, %2       ; w  = %1 + %2
126     vmulps     %2, %5, [ps_p1p1m1p1root2]  ; v *= vals1
127     vpermilps  %2, %2, [perm1]
128     vblendps   %1, %2, %3, 0x33 ; q = {w1,w2,v4,v2,w5,w6,v7,v6}
129     vshufps    %5, %3, %2, 0x4e ; r = {w3,w4,v1,v3,w7,w8,v8,v5}
130     vsubps     %4, %5, %1       ; s = r - q
131     vaddps     %1, %5, %1       ; u = r + q
132     vpermilps  %1, %1, [perm2]  ; k  = {u1,u2,u3,u4,u6,u5,u7,u8}
133     vshufps    %5, %4, %1, 0xbb
134     vshufps    %3, %4, %1, 0xee
135     vperm2f128 %3, %3, %5, 0x13
136     vxorps     %4, %4, [ps_m1m1p1m1p1m1m1m1]  ; s *= {1,1,-1,-1,1,-1,-1,-1}
137     vshufps    %2, %1, %4, 0xdd
138     vshufps    %1, %1, %4, 0x88
139     vperm2f128 %4, %2, %1, 0x02 ; v  = {k1,k3,s1,s3,k2,k4,s2,s4}
140     vperm2f128 %1, %1, %2, 0x13 ; w  = {k6,k8,s6,s8,k5,k7,s5,s7}
141     vsubps     %5, %1, %3
142     vblendps   %1, %5, %1, 0x55 ; w -= {0,s7,0,k7,0,s8,0,k8}
143     vsubps     %2, %4, %1       ; %2 = v - w
144     vaddps     %1, %4, %1       ; %1 = v + w
145 %endmacro
146
147 ; In SSE mode do one fft4 transforms
148 ; in:  %1={r0,i0,r2,i2} %2={r1,i1,r3,i3}
149 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3}
150 ;
151 ; In AVX mode do two fft4 transforms
152 ; in:  %1={r0,i0,r2,i2,r4,i4,r6,i6} %2={r1,i1,r3,i3,r5,i5,r7,i7}
153 ; out: %1={r0,r1,r2,r3,r4,r5,r6,r7} %2={i0,i1,i2,i3,i4,i5,i6,i7}
154 %macro T4_SSE 3
155     subps    %3, %1, %2       ; {t3,t4,-t8,t7}
156     addps    %1, %1, %2       ; {t1,t2,t6,t5}
157     xorps    %3, %3, [ps_p1p1m1p1]
158     shufps   %2, %1, %3, 0xbe ; {t6,t5,t7,t8}
159     shufps   %1, %1, %3, 0x44 ; {t1,t2,t3,t4}
160     subps    %3, %1, %2       ; {r2,i2,r3,i3}
161     addps    %1, %1, %2       ; {r0,i0,r1,i1}
162     shufps   %2, %1, %3, 0xdd ; {i0,i1,i2,i3}
163     shufps   %1, %1, %3, 0x88 ; {r0,r1,r2,r3}
164 %endmacro
165
166 ; In SSE mode do one FFT8
167 ; in:  %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %3={r4,i4,r6,i6} %4={r5,i5,r7,i7}
168 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %1={r4,r5,r6,r7} %2={i4,i5,i6,i7}
169 ;
170 ; In AVX mode do two FFT8
171 ; in:  %1={r0,i0,r2,i2,r8, i8, r10,i10} %2={r1,i1,r3,i3,r9, i9, r11,i11}
172 ;      %3={r4,i4,r6,i6,r12,i12,r14,i14} %4={r5,i5,r7,i7,r13,i13,r15,i15}
173 ; out: %1={r0,r1,r2,r3,r8, r9, r10,r11} %2={i0,i1,i2,i3,i8, i9, i10,i11}
174 ;      %3={r4,r5,r6,r7,r12,r13,r14,r15} %4={i4,i5,i6,i7,i12,i13,i14,i15}
175 %macro T8_SSE 6
176     addps    %6, %3, %4       ; {t1,t2,t3,t4}
177     subps    %3, %3, %4       ; {r5,i5,r7,i7}
178     shufps   %4, %3, %3, 0xb1 ; {i5,r5,i7,r7}
179     mulps    %3, %3, [ps_root2mppm] ; {-r5,i5,r7,-i7}
180     mulps    %4, %4, [ps_root2]
181     addps    %3, %3, %4       ; {t8,t7,ta,t9}
182     shufps   %4, %6, %3, 0x9c ; {t1,t4,t7,ta}
183     shufps   %6, %6, %3, 0x36 ; {t3,t2,t9,t8}
184     subps    %3, %6, %4       ; {t6,t5,tc,tb}
185     addps    %6, %6, %4       ; {t1,t2,t9,ta}
186     shufps   %5, %6, %3, 0x8d ; {t2,ta,t6,tc}
187     shufps   %6, %6, %3, 0xd8 ; {t1,t9,t5,tb}
188     subps    %3, %1, %6       ; {r4,r5,r6,r7}
189     addps    %1, %1, %6       ; {r0,r1,r2,r3}
190     subps    %4, %2, %5       ; {i4,i5,i6,i7}
191     addps    %2, %2, %5       ; {i0,i1,i2,i3}
192 %endmacro
193
194 ; scheduled for cpu-bound sizes
195 %macro PASS_SMALL 3 ; (to load m4-m7), wre, wim
196 IF%1 mova    m4, Z(4)
197 IF%1 mova    m5, Z(5)
198     mova     m0, %2 ; wre
199     mova     m1, %3 ; wim
200     mulps    m2, m4, m0 ; r2*wre
201 IF%1 mova    m6, Z2(6)
202     mulps    m3, m5, m1 ; i2*wim
203 IF%1 mova    m7, Z2(7)
204     mulps    m4, m4, m1 ; r2*wim
205     mulps    m5, m5, m0 ; i2*wre
206     addps    m2, m2, m3 ; r2*wre + i2*wim
207     mulps    m3, m1, m7 ; i3*wim
208     subps    m5, m5, m4 ; i2*wre - r2*wim
209     mulps    m1, m1, m6 ; r3*wim
210     mulps    m4, m0, m6 ; r3*wre
211     mulps    m0, m0, m7 ; i3*wre
212     subps    m4, m4, m3 ; r3*wre - i3*wim
213     mova     m3, Z(0)
214     addps    m0, m0, m1 ; i3*wre + r3*wim
215     subps    m1, m4, m2 ; t3
216     addps    m4, m4, m2 ; t5
217     subps    m3, m3, m4 ; r2
218     addps    m4, m4, Z(0) ; r0
219     mova     m6, Z(2)
220     mova   Z(4), m3
221     mova   Z(0), m4
222     subps    m3, m5, m0 ; t4
223     subps    m4, m6, m3 ; r3
224     addps    m3, m3, m6 ; r1
225     mova  Z2(6), m4
226     mova   Z(2), m3
227     mova     m2, Z(3)
228     addps    m3, m5, m0 ; t6
229     subps    m2, m2, m1 ; i3
230     mova     m7, Z(1)
231     addps    m1, m1, Z(3) ; i1
232     mova  Z2(7), m2
233     mova   Z(3), m1
234     subps    m4, m7, m3 ; i2
235     addps    m3, m3, m7 ; i0
236     mova   Z(5), m4
237     mova   Z(1), m3
238 %endmacro
239
240 ; scheduled to avoid store->load aliasing
241 %macro PASS_BIG 1 ; (!interleave)
242     mova     m4, Z(4) ; r2
243     mova     m5, Z(5) ; i2
244     mova     m0, [wq] ; wre
245     mova     m1, [wq+o1q] ; wim
246     mulps    m2, m4, m0 ; r2*wre
247     mova     m6, Z2(6) ; r3
248     mulps    m3, m5, m1 ; i2*wim
249     mova     m7, Z2(7) ; i3
250     mulps    m4, m4, m1 ; r2*wim
251     mulps    m5, m5, m0 ; i2*wre
252     addps    m2, m2, m3 ; r2*wre + i2*wim
253     mulps    m3, m1, m7 ; i3*wim
254     mulps    m1, m1, m6 ; r3*wim
255     subps    m5, m5, m4 ; i2*wre - r2*wim
256     mulps    m4, m0, m6 ; r3*wre
257     mulps    m0, m0, m7 ; i3*wre
258     subps    m4, m4, m3 ; r3*wre - i3*wim
259     mova     m3, Z(0)
260     addps    m0, m0, m1 ; i3*wre + r3*wim
261     subps    m1, m4, m2 ; t3
262     addps    m4, m4, m2 ; t5
263     subps    m3, m3, m4 ; r2
264     addps    m4, m4, Z(0) ; r0
265     mova     m6, Z(2)
266     mova   Z(4), m3
267     mova   Z(0), m4
268     subps    m3, m5, m0 ; t4
269     subps    m4, m6, m3 ; r3
270     addps    m3, m3, m6 ; r1
271 IF%1 mova Z2(6), m4
272 IF%1 mova  Z(2), m3
273     mova     m2, Z(3)
274     addps    m5, m5, m0 ; t6
275     subps    m2, m2, m1 ; i3
276     mova     m7, Z(1)
277     addps    m1, m1, Z(3) ; i1
278 IF%1 mova Z2(7), m2
279 IF%1 mova  Z(3), m1
280     subps    m6, m7, m5 ; i2
281     addps    m5, m5, m7 ; i0
282 IF%1 mova  Z(5), m6
283 IF%1 mova  Z(1), m5
284 %if %1==0
285     INTERL m1, m3, m7, Z, 2
286     INTERL m2, m4, m0, Z2, 6
287
288     mova     m1, Z(0)
289     mova     m2, Z(4)
290
291     INTERL m5, m1, m3, Z, 0
292     INTERL m6, m2, m7, Z, 4
293 %endif
294 %endmacro
295
296 %macro PUNPCK 3
297     mova      %3, %1
298     punpckldq %1, %2
299     punpckhdq %3, %2
300 %endmacro
301
302 %define Z(x) [r0+mmsize*x]
303 %define Z2(x) [r0+mmsize*x]
304 %define ZH(x) [r0+mmsize*x+mmsize/2]
305
306 INIT_YMM avx
307
308 %if HAVE_AVX
309 align 16
310 fft8_avx:
311     mova      m0, Z(0)
312     mova      m1, Z(1)
313     T8_AVX    m0, m1, m2, m3, m4
314     mova      Z(0), m0
315     mova      Z(1), m1
316     ret
317
318
319 align 16
320 fft16_avx:
321     mova       m2, Z(2)
322     mova       m3, Z(3)
323     T4_SSE     m2, m3, m7
324
325     mova       m0, Z(0)
326     mova       m1, Z(1)
327     T8_AVX     m0, m1, m4, m5, m7
328
329     mova       m4, [ps_cos16_1]
330     mova       m5, [ps_cos16_2]
331     vmulps     m6, m2, m4
332     vmulps     m7, m3, m5
333     vaddps     m7, m7, m6
334     vmulps     m2, m2, m5
335     vmulps     m3, m3, m4
336     vsubps     m3, m3, m2
337     vblendps   m2, m7, m3, 0xf0
338     vperm2f128 m3, m7, m3, 0x21
339     vaddps     m4, m2, m3
340     vsubps     m2, m3, m2
341     vperm2f128 m2, m2, m2, 0x01
342     vsubps     m3, m1, m2
343     vaddps     m1, m1, m2
344     vsubps     m5, m0, m4
345     vaddps     m0, m0, m4
346     vextractf128   Z(0), m0, 0
347     vextractf128  ZH(0), m1, 0
348     vextractf128   Z(1), m0, 1
349     vextractf128  ZH(1), m1, 1
350     vextractf128   Z(2), m5, 0
351     vextractf128  ZH(2), m3, 0
352     vextractf128   Z(3), m5, 1
353     vextractf128  ZH(3), m3, 1
354     ret
355
356 align 16
357 fft32_avx:
358     call fft16_avx
359
360     mova m0, Z(4)
361     mova m1, Z(5)
362
363     T4_SSE      m0, m1, m4
364
365     mova m2, Z(6)
366     mova m3, Z(7)
367
368     T8_SSE      m0, m1, m2, m3, m4, m6
369     ; m0={r0,r1,r2,r3,r8, r9, r10,r11} m1={i0,i1,i2,i3,i8, i9, i10,i11}
370     ; m2={r4,r5,r6,r7,r12,r13,r14,r15} m3={i4,i5,i6,i7,i12,i13,i14,i15}
371
372     vperm2f128  m4, m0, m2, 0x20
373     vperm2f128  m5, m1, m3, 0x20
374     vperm2f128  m6, m0, m2, 0x31
375     vperm2f128  m7, m1, m3, 0x31
376
377     PASS_SMALL 0, [cos_32], [cos_32+32]
378
379     ret
380
381 fft32_interleave_avx:
382     call fft32_avx
383     mov r2d, 32
384 .deint_loop:
385     mova     m2, Z(0)
386     mova     m3, Z(1)
387     vunpcklps      m0, m2, m3
388     vunpckhps      m1, m2, m3
389     vextractf128   Z(0), m0, 0
390     vextractf128  ZH(0), m1, 0
391     vextractf128   Z(1), m0, 1
392     vextractf128  ZH(1), m1, 1
393     add r0, mmsize*2
394     sub r2d, mmsize/4
395     jg .deint_loop
396     ret
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_3DN 0
448 align 16
449 fft4 %+ SUFFIX:
450     T2_3DN   m0, m1, Z(0), Z(1)
451     mova     m2, Z(2)
452     mova     m3, Z(3)
453     T4_3DN   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_3DN   m0, m1, Z(0), Z(1)
465     mova     m2, Z(2)
466     mova     m3, Z(3)
467     T4_3DN   m0, m1, m2, m3, m4, m5
468     mova   Z(0), m0
469     mova   Z(2), m2
470     T2_3DN   m4, m5,  Z(4),  Z(5)
471     T2_3DN   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_3DN   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_3DN   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(3dnow2)
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 3dnow2
516 FFT48_3DN
517
518 INIT_MMX 3dnow
519 FFT48_3DN
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
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 3dnow2
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 3dnow2
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_3dnow2 pass_3dnow
747 %define pass_interleave_3dnow2 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
795 section .text
796
797 ; On x86_32, this function does the register saving and restoring for all of fft.
798 ; The others pass args in registers and don't spill anything.
799 cglobal fft_dispatch%2, 2,5,8, zc, nbits
800     FFT_DISPATCH fullsuffix, nbits
801     RET
802 %endmacro ; DECL_FFT
803
804 %if HAVE_AVX
805 INIT_YMM avx
806 DECL_FFT 6
807 DECL_FFT 6, _interleave
808 %endif
809 INIT_XMM sse
810 DECL_FFT 5
811 DECL_FFT 5, _interleave
812 %if ARCH_X86_32
813 INIT_MMX 3dnow
814 DECL_FFT 4
815 DECL_FFT 4, _interleave
816 INIT_MMX 3dnow2
817 DECL_FFT 4
818 DECL_FFT 4, _interleave
819 %endif
820
821 INIT_XMM sse
822 %undef mulps
823 %undef addps
824 %undef subps
825 %undef unpcklps
826 %undef unpckhps
827
828 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
829 %if mmsize == 8 ; j*2+2-n4, n4-2-j*2, input+n4, tcos+n8, tsin+n8
830     PSWAPD     m0, [%3+%2*4]
831     movq       m2, [%3+%1*4-8]
832     movq       m3, m0
833     punpckldq  m0, m2
834     punpckhdq  m2, m3
835     movd       m1, [%4+%1*2-4] ; tcos[j]
836     movd       m3, [%4+%2*2]   ; tcos[n4-j-1]
837     punpckldq  m1, [%5+%1*2-4] ; tsin[j]
838     punpckldq  m3, [%5+%2*2]   ; tsin[n4-j-1]
839
840     mova       m4, m0
841     PSWAPD     m5, m1
842     pfmul      m0, m1
843     pfmul      m4, m5
844     mova       m6, m2
845     PSWAPD     m5, m3
846     pfmul      m2, m3
847     pfmul      m6, m5
848 %if cpuflag(3dnow2)
849     pfpnacc    m0, m4
850     pfpnacc    m2, m6
851 %else
852     SBUTTERFLY dq, 0, 4, 1
853     SBUTTERFLY dq, 2, 6, 3
854     pxor       m4, m7
855     pxor       m6, m7
856     pfadd      m0, m4
857     pfadd      m2, m6
858 %endif
859 %else
860     movaps   xmm0, [%3+%2*4]
861     movaps   xmm1, [%3+%1*4-0x10]
862     movaps   xmm2, xmm0
863     shufps   xmm0, xmm1, 0x88
864     shufps   xmm1, xmm2, 0x77
865     movlps   xmm4, [%4+%2*2]
866     movlps   xmm5, [%5+%2*2+0x0]
867     movhps   xmm4, [%4+%1*2-0x8]
868     movhps   xmm5, [%5+%1*2-0x8]
869     movaps   xmm2, xmm0
870     movaps   xmm3, xmm1
871     mulps    xmm0, xmm5
872     mulps    xmm1, xmm4
873     mulps    xmm2, xmm4
874     mulps    xmm3, xmm5
875     subps    xmm1, xmm0
876     addps    xmm2, xmm3
877     movaps   xmm0, xmm1
878     unpcklps xmm1, xmm2
879     unpckhps xmm0, xmm2
880 %endif
881 %endmacro
882
883 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
884     mulps      m6, %3, [%5+%1]
885     mulps      m7, %2, [%5+%1]
886     mulps      %2, %2, [%6+%1]
887     mulps      %3, %3, [%6+%1]
888     subps      %2, %2, m6
889     addps      %3, %3, m7
890 %endmacro
891
892 %macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8
893 .post:
894     vmovaps      ymm1,   [%3+%1*2]
895     vmovaps      ymm0,   [%3+%1*2+0x20]
896     vmovaps      ymm3,   [%3+%2*2]
897     vmovaps      ymm2,   [%3+%2*2+0x20]
898
899     CMUL         %1, ymm0, ymm1, %3, %4, %5
900     CMUL         %2, ymm2, ymm3, %3, %4, %5
901     vshufps      ymm1, ymm1, ymm1, 0x1b
902     vshufps      ymm3, ymm3, ymm3, 0x1b
903     vperm2f128   ymm1, ymm1, ymm1, 0x01
904     vperm2f128   ymm3, ymm3, ymm3, 0x01
905     vunpcklps    ymm6, ymm2, ymm1
906     vunpckhps    ymm4, ymm2, ymm1
907     vunpcklps    ymm7, ymm0, ymm3
908     vunpckhps    ymm5, ymm0, ymm3
909
910     vextractf128 [%3+%1*2],      ymm7, 0
911     vextractf128 [%3+%1*2+0x10], ymm5, 0
912     vextractf128 [%3+%1*2+0x20], ymm7, 1
913     vextractf128 [%3+%1*2+0x30], ymm5, 1
914
915     vextractf128 [%3+%2*2],      ymm6, 0
916     vextractf128 [%3+%2*2+0x10], ymm4, 0
917     vextractf128 [%3+%2*2+0x20], ymm6, 1
918     vextractf128 [%3+%2*2+0x30], ymm4, 1
919     sub      %2,   0x20
920     add      %1,   0x20
921     jl       .post
922 %endmacro
923
924 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
925 .post:
926     movaps   xmm1, [%3+%1*2]
927     movaps   xmm0, [%3+%1*2+0x10]
928     CMUL     %1,   xmm0, xmm1, %3, %4, %5
929     movaps   xmm5, [%3+%2*2]
930     movaps   xmm4, [%3+%2*2+0x10]
931     CMUL     %2,   xmm4, xmm5, %3, %4, %5
932     shufps   xmm1, xmm1, 0x1b
933     shufps   xmm5, xmm5, 0x1b
934     movaps   xmm6, xmm4
935     unpckhps xmm4, xmm1
936     unpcklps xmm6, xmm1
937     movaps   xmm2, xmm0
938     unpcklps xmm0, xmm5
939     unpckhps xmm2, xmm5
940     movaps   [%3+%2*2],      xmm6
941     movaps   [%3+%2*2+0x10], xmm4
942     movaps   [%3+%1*2],      xmm0
943     movaps   [%3+%1*2+0x10], xmm2
944     sub      %2,   0x10
945     add      %1,   0x10
946     jl       .post
947 %endmacro
948
949 %macro CMUL_3DNOW 6
950     mova       m6, [%1+%2*2]
951     mova       %3, [%1+%2*2+8]
952     mova       %4, m6
953     mova       m7, %3
954     pfmul      m6, [%5+%2]
955     pfmul      %3, [%6+%2]
956     pfmul      %4, [%6+%2]
957     pfmul      m7, [%5+%2]
958     pfsub      %3, m6
959     pfadd      %4, m7
960 %endmacro
961
962 %macro POSROTATESHUF_3DNOW 5 ;j, k, z+n8, tcos+n8, tsin+n8
963 .post:
964     CMUL_3DNOW %3, %1, m0, m1, %4, %5
965     CMUL_3DNOW %3, %2, m2, m3, %4, %5
966     movd  [%3+%1*2+ 0], m0
967     movd  [%3+%2*2+12], m1
968     movd  [%3+%2*2+ 0], m2
969     movd  [%3+%1*2+12], m3
970     psrlq      m0, 32
971     psrlq      m1, 32
972     psrlq      m2, 32
973     psrlq      m3, 32
974     movd  [%3+%1*2+ 8], m0
975     movd  [%3+%2*2+ 4], m1
976     movd  [%3+%2*2+ 8], m2
977     movd  [%3+%1*2+ 4], m3
978     sub        %2, 8
979     add        %1, 8
980     jl         .post
981 %endmacro
982
983 %macro DECL_IMDCT 1
984 cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *input
985 %if ARCH_X86_64
986 %define rrevtab r7
987 %define rtcos   r8
988 %define rtsin   r9
989 %else
990 %define rrevtab r6
991 %define rtsin   r6
992 %define rtcos   r5
993 %endif
994     mov   r3d, [r0+FFTContext.mdctsize]
995     add   r2, r3
996     shr   r3, 1
997     mov   rtcos, [r0+FFTContext.tcos]
998     mov   rtsin, [r0+FFTContext.tsin]
999     add   rtcos, r3
1000     add   rtsin, r3
1001 %if ARCH_X86_64 == 0
1002     push  rtcos
1003     push  rtsin
1004 %endif
1005     shr   r3, 1
1006     mov   rrevtab, [r0+FFTContext.revtab]
1007     add   rrevtab, r3
1008 %if ARCH_X86_64 == 0
1009     push  rrevtab
1010 %endif
1011
1012     sub   r3, mmsize/4
1013 %if ARCH_X86_64 || mmsize == 8
1014     xor   r4, r4
1015     sub   r4, r3
1016 %endif
1017 %if notcpuflag(3dnow2) && mmsize == 8
1018     movd  m7, [ps_m1m1m1m1]
1019 %endif
1020 .pre:
1021 %if ARCH_X86_64 == 0
1022 ;unspill
1023 %if mmsize != 8
1024     xor   r4, r4
1025     sub   r4, r3
1026 %endif
1027     mov   rtcos, [esp+8]
1028     mov   rtsin, [esp+4]
1029 %endif
1030
1031     PREROTATER r4, r3, r2, rtcos, rtsin
1032 %if mmsize == 8
1033     mov    r6, [esp]                ; rrevtab = ptr+n8
1034     movzx  r5,  word [rrevtab+r4-2] ; rrevtab[j]
1035     movzx  r6,  word [rrevtab+r3]   ; rrevtab[n4-j-1]
1036     mova [r1+r5*8], m0
1037     mova [r1+r6*8], m2
1038     add    r4, 2
1039 %elif ARCH_X86_64
1040     movzx  r5,  word [rrevtab+r4-4]
1041     movzx  r6,  word [rrevtab+r4-2]
1042     movzx  r10, word [rrevtab+r3]
1043     movzx  r11, word [rrevtab+r3+2]
1044     movlps [r1+r5 *8], xmm0
1045     movhps [r1+r6 *8], xmm0
1046     movlps [r1+r10*8], xmm1
1047     movhps [r1+r11*8], xmm1
1048     add    r4, 4
1049 %else
1050     mov    r6, [esp]
1051     movzx  r5, word [r6+r4-4]
1052     movzx  r4, word [r6+r4-2]
1053     movlps [r1+r5*8], xmm0
1054     movhps [r1+r4*8], xmm0
1055     movzx  r5, word [r6+r3]
1056     movzx  r4, word [r6+r3+2]
1057     movlps [r1+r5*8], xmm1
1058     movhps [r1+r4*8], xmm1
1059 %endif
1060     sub    r3, mmsize/4
1061     jns    .pre
1062
1063     mov  r5, r0
1064     mov  r6, r1
1065     mov  r0, r1
1066     mov  r1d, [r5+FFTContext.nbits]
1067
1068     FFT_DISPATCH SUFFIX, r1
1069
1070     mov  r0d, [r5+FFTContext.mdctsize]
1071     add  r6, r0
1072     shr  r0, 1
1073 %if ARCH_X86_64 == 0
1074 %define rtcos r2
1075 %define rtsin r3
1076     mov  rtcos, [esp+8]
1077     mov  rtsin, [esp+4]
1078 %endif
1079     neg  r0
1080     mov  r1, -mmsize
1081     sub  r1, r0
1082     %1 r0, r1, r6, rtcos, rtsin
1083 %if ARCH_X86_64 == 0
1084     add esp, 12
1085 %endif
1086 %if mmsize == 8
1087     femms
1088 %endif
1089     RET
1090 %endmacro
1091
1092 DECL_IMDCT POSROTATESHUF
1093
1094 %if ARCH_X86_32
1095 INIT_MMX 3dnow
1096 DECL_IMDCT POSROTATESHUF_3DNOW
1097
1098 INIT_MMX 3dnow2
1099 DECL_IMDCT POSROTATESHUF_3DNOW
1100 %endif
1101
1102 INIT_YMM avx
1103
1104 %if HAVE_AVX
1105 DECL_IMDCT POSROTATESHUF_AVX
1106 %endif