x86: include x86inc.asm in x86util.asm
[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 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 "x86util.asm"
32
33 %if ARCH_X86_64
34 %define pointer resq
35 %else
36 %define pointer resd
37 %endif
38
39 struc FFTContext
40     .nbits:    resd 1
41     .reverse:  resd 1
42     .revtab:   pointer 1
43     .tmpbuf:   pointer 1
44     .mdctsize: resd 1
45     .mdctbits: resd 1
46     .tcos:     pointer 1
47     .tsin:     pointer 1
48     .fftperm:  pointer 1
49     .fftcalc:  pointer 1
50     .imdctcalc:pointer 1
51     .imdcthalf:pointer 1
52 endstruc
53
54 SECTION_RODATA
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 %endif
397
398 INIT_XMM sse
399
400 align 16
401 fft4_avx:
402 fft4_sse:
403     mova     m0, Z(0)
404     mova     m1, Z(1)
405     T4_SSE   m0, m1, m2
406     mova   Z(0), m0
407     mova   Z(1), m1
408     ret
409
410 align 16
411 fft8_sse:
412     mova     m0, Z(0)
413     mova     m1, Z(1)
414     T4_SSE   m0, m1, m2
415     mova     m2, Z(2)
416     mova     m3, Z(3)
417     T8_SSE   m0, m1, m2, m3, m4, m5
418     mova   Z(0), m0
419     mova   Z(1), m1
420     mova   Z(2), m2
421     mova   Z(3), m3
422     ret
423
424 align 16
425 fft16_sse:
426     mova     m0, Z(0)
427     mova     m1, Z(1)
428     T4_SSE   m0, m1, m2
429     mova     m2, Z(2)
430     mova     m3, Z(3)
431     T8_SSE   m0, m1, m2, m3, m4, m5
432     mova     m4, Z(4)
433     mova     m5, Z(5)
434     mova   Z(0), m0
435     mova   Z(1), m1
436     mova   Z(2), m2
437     mova   Z(3), m3
438     T4_SSE   m4, m5, m6
439     mova     m6, Z2(6)
440     mova     m7, Z2(7)
441     T4_SSE   m6, m7, m0
442     PASS_SMALL 0, [cos_16], [cos_16+16]
443     ret
444
445
446 %macro FFT48_3DNOW 0
447 align 16
448 fft4 %+ SUFFIX:
449     T2_3DNOW m0, m1, Z(0), Z(1)
450     mova     m2, Z(2)
451     mova     m3, Z(3)
452     T4_3DNOW m0, m1, m2, m3, m4, m5
453     PUNPCK   m0, m1, m4
454     PUNPCK   m2, m3, m5
455     mova   Z(0), m0
456     mova   Z(1), m4
457     mova   Z(2), m2
458     mova   Z(3), m5
459     ret
460
461 align 16
462 fft8 %+ SUFFIX:
463     T2_3DNOW m0, m1, Z(0), Z(1)
464     mova     m2, Z(2)
465     mova     m3, Z(3)
466     T4_3DNOW m0, m1, m2, m3, m4, m5
467     mova   Z(0), m0
468     mova   Z(2), m2
469     T2_3DNOW m4, m5,  Z(4),  Z(5)
470     T2_3DNOW m6, m7, Z2(6), Z2(7)
471     PSWAPD   m0, m5
472     PSWAPD   m2, m7
473     pxor     m0, [ps_m1p1]
474     pxor     m2, [ps_m1p1]
475     pfsub    m5, m0
476     pfadd    m7, m2
477     pfmul    m5, [ps_root2]
478     pfmul    m7, [ps_root2]
479     T4_3DNOW m1, m3, m5, m7, m0, m2
480     mova   Z(5), m5
481     mova  Z2(7), m7
482     mova     m0, Z(0)
483     mova     m2, Z(2)
484     T4_3DNOW m0, m2, m4, m6, m5, m7
485     PUNPCK   m0, m1, m5
486     PUNPCK   m2, m3, m7
487     mova   Z(0), m0
488     mova   Z(1), m5
489     mova   Z(2), m2
490     mova   Z(3), m7
491     PUNPCK   m4,  Z(5), m5
492     PUNPCK   m6, Z2(7), m7
493     mova   Z(4), m4
494     mova   Z(5), m5
495     mova  Z2(6), m6
496     mova  Z2(7), m7
497     ret
498 %endmacro
499
500 %if ARCH_X86_32
501 %macro PSWAPD 2
502 %if cpuflag(3dnowext)
503     pswapd %1, %2
504 %elifidn %1, %2
505     movd [r0+12], %1
506     punpckhdq %1, [r0+8]
507 %else
508     movq  %1, %2
509     psrlq %1, 32
510     punpckldq %1, %2
511 %endif
512 %endmacro
513
514 INIT_MMX 3dnowext
515 FFT48_3DNOW
516
517 INIT_MMX 3dnow
518 FFT48_3DNOW
519 %endif
520
521 %define Z(x) [zcq + o1q*(x&6) + mmsize*(x&1)]
522 %define Z2(x) [zcq + o3q + mmsize*(x&1)]
523 %define ZH(x) [zcq + o1q*(x&6) + mmsize*(x&1) + mmsize/2]
524 %define Z2H(x) [zcq + o3q + mmsize*(x&1) + mmsize/2]
525
526 %macro DECL_PASS 2+ ; name, payload
527 align 16
528 %1:
529 DEFINE_ARGS zc, w, n, o1, o3
530     lea o3q, [nq*3]
531     lea o1q, [nq*8]
532     shl o3q, 4
533 .loop:
534     %2
535     add zcq, mmsize*2
536     add  wq, mmsize
537     sub  nd, mmsize/8
538     jg .loop
539     rep ret
540 %endmacro
541
542 %macro FFT_DISPATCH 2; clobbers 5 GPRs, 8 XMMs
543     lea r2, [dispatch_tab%1]
544     mov r2, [r2 + (%2q-2)*gprsize]
545 %ifdef PIC
546     lea r3, [$$]
547     add r2, r3
548 %endif
549     call r2
550 %endmacro ; FFT_DISPATCH
551
552 INIT_YMM avx
553
554 %if HAVE_AVX_EXTERNAL
555 %macro INTERL_AVX 5
556     vunpckhps      %3, %2, %1
557     vunpcklps      %2, %2, %1
558     vextractf128   %4(%5), %2, 0
559     vextractf128  %4 %+ H(%5), %3, 0
560     vextractf128   %4(%5 + 1), %2, 1
561     vextractf128  %4 %+ H(%5 + 1), %3, 1
562 %endmacro
563
564 %define INTERL INTERL_AVX
565
566 DECL_PASS pass_avx, PASS_BIG 1
567 DECL_PASS pass_interleave_avx, PASS_BIG 0
568
569 cglobal fft_calc, 2,5,8
570     mov     r3d, [r0 + FFTContext.nbits]
571     mov     r0, r1
572     mov     r1, r3
573     FFT_DISPATCH _interleave %+ SUFFIX, r1
574     REP_RET
575
576 %endif
577
578 INIT_XMM sse
579
580 %macro INTERL_SSE 5
581     mova     %3, %2
582     unpcklps %2, %1
583     unpckhps %3, %1
584     mova  %4(%5), %2
585     mova  %4(%5+1), %3
586 %endmacro
587
588 %define INTERL INTERL_SSE
589
590 DECL_PASS pass_sse, PASS_BIG 1
591 DECL_PASS pass_interleave_sse, PASS_BIG 0
592
593 %macro FFT_CALC_FUNC 0
594 cglobal fft_calc, 2,5,8
595     mov     r3d, [r0 + FFTContext.nbits]
596     PUSH    r1
597     PUSH    r3
598     mov     r0, r1
599     mov     r1, r3
600     FFT_DISPATCH _interleave %+ SUFFIX, r1
601     POP     rcx
602     POP     r4
603     cmp     rcx, 3+(mmsize/16)
604     jg      .end
605     mov     r2, -1
606     add     rcx, 3
607     shl     r2, cl
608     sub     r4, r2
609 .loop:
610 %if mmsize == 8
611     PSWAPD  m0, [r4 + r2 + 4]
612     mova [r4 + r2 + 4], m0
613 %else
614     movaps   xmm0, [r4 + r2]
615     movaps   xmm1, xmm0
616     unpcklps xmm0, [r4 + r2 + 16]
617     unpckhps xmm1, [r4 + r2 + 16]
618     movaps   [r4 + r2],      xmm0
619     movaps   [r4 + r2 + 16], xmm1
620 %endif
621     add      r2, mmsize*2
622     jl       .loop
623 .end:
624 %if cpuflag(3dnow)
625     femms
626     RET
627 %else
628     REP_RET
629 %endif
630 %endmacro
631
632 %if ARCH_X86_32
633 INIT_MMX 3dnow
634 FFT_CALC_FUNC
635 INIT_MMX 3dnowext
636 FFT_CALC_FUNC
637 %endif
638 INIT_XMM sse
639 FFT_CALC_FUNC
640
641 cglobal fft_permute, 2,7,1
642     mov     r4,  [r0 + FFTContext.revtab]
643     mov     r5,  [r0 + FFTContext.tmpbuf]
644     mov     ecx, [r0 + FFTContext.nbits]
645     mov     r2, 1
646     shl     r2, cl
647     xor     r0, r0
648 %if ARCH_X86_32
649     mov     r1, r1m
650 %endif
651 .loop:
652     movaps  xmm0, [r1 + 8*r0]
653     movzx   r6, word [r4 + 2*r0]
654     movzx   r3, word [r4 + 2*r0 + 2]
655     movlps  [r5 + 8*r6], xmm0
656     movhps  [r5 + 8*r3], xmm0
657     add     r0, 2
658     cmp     r0, r2
659     jl      .loop
660     shl     r2, 3
661     add     r1, r2
662     add     r5, r2
663     neg     r2
664 ; nbits >= 2 (FFT4) and sizeof(FFTComplex)=8 => at least 32B
665 .loopcopy:
666     movaps  xmm0, [r5 + r2]
667     movaps  xmm1, [r5 + r2 + 16]
668     movaps  [r1 + r2], xmm0
669     movaps  [r1 + r2 + 16], xmm1
670     add     r2, 32
671     jl      .loopcopy
672     REP_RET
673
674 %macro IMDCT_CALC_FUNC 0
675 cglobal imdct_calc, 3,5,3
676     mov     r3d, [r0 + FFTContext.mdctsize]
677     mov     r4,  [r0 + FFTContext.imdcthalf]
678     add     r1,  r3
679     PUSH    r3
680     PUSH    r1
681 %if ARCH_X86_32
682     push    r2
683     push    r1
684     push    r0
685 %else
686     sub     rsp, 8
687 %endif
688     call    r4
689 %if ARCH_X86_32
690     add     esp, 12
691 %else
692     add     rsp, 8
693 %endif
694     POP     r1
695     POP     r3
696     lea     r0, [r1 + 2*r3]
697     mov     r2, r3
698     sub     r3, mmsize
699     neg     r2
700     mova    m2, [ps_m1m1m1m1]
701 .loop:
702 %if mmsize == 8
703     PSWAPD  m0, [r1 + r3]
704     PSWAPD  m1, [r0 + r2]
705     pxor    m0, m2
706 %else
707     mova    m0, [r1 + r3]
708     mova    m1, [r0 + r2]
709     shufps  m0, m0, 0x1b
710     shufps  m1, m1, 0x1b
711     xorps   m0, m2
712 %endif
713     mova [r0 + r3], m1
714     mova [r1 + r2], m0
715     sub     r3, mmsize
716     add     r2, mmsize
717     jl      .loop
718 %if cpuflag(3dnow)
719     femms
720     RET
721 %else
722     REP_RET
723 %endif
724 %endmacro
725
726 %if ARCH_X86_32
727 INIT_MMX 3dnow
728 IMDCT_CALC_FUNC
729 INIT_MMX 3dnowext
730 IMDCT_CALC_FUNC
731 %endif
732
733 INIT_XMM sse
734 IMDCT_CALC_FUNC
735
736 %if ARCH_X86_32
737 INIT_MMX 3dnow
738 %define mulps pfmul
739 %define addps pfadd
740 %define subps pfsub
741 %define unpcklps punpckldq
742 %define unpckhps punpckhdq
743 DECL_PASS pass_3dnow, PASS_SMALL 1, [wq], [wq+o1q]
744 DECL_PASS pass_interleave_3dnow, PASS_BIG 0
745 %define pass_3dnowext pass_3dnow
746 %define pass_interleave_3dnowext pass_interleave_3dnow
747 %endif
748
749 %ifdef PIC
750 %define SECTION_REL - $$
751 %else
752 %define SECTION_REL
753 %endif
754
755 %macro DECL_FFT 1-2 ; nbits, suffix
756 %ifidn %0, 1
757 %xdefine fullsuffix SUFFIX
758 %else
759 %xdefine fullsuffix %2 %+ SUFFIX
760 %endif
761 %xdefine list_of_fft fft4 %+ SUFFIX SECTION_REL, fft8 %+ SUFFIX SECTION_REL
762 %if %1>=5
763 %xdefine list_of_fft list_of_fft, fft16 %+ SUFFIX SECTION_REL
764 %endif
765 %if %1>=6
766 %xdefine list_of_fft list_of_fft, fft32 %+ fullsuffix SECTION_REL
767 %endif
768
769 %assign n 1<<%1
770 %rep 17-%1
771 %assign n2 n/2
772 %assign n4 n/4
773 %xdefine list_of_fft list_of_fft, fft %+ n %+ fullsuffix SECTION_REL
774
775 align 16
776 fft %+ n %+ fullsuffix:
777     call fft %+ n2 %+ SUFFIX
778     add r0, n*4 - (n&(-2<<%1))
779     call fft %+ n4 %+ SUFFIX
780     add r0, n*2 - (n2&(-2<<%1))
781     call fft %+ n4 %+ SUFFIX
782     sub r0, n*6 + (n2&(-2<<%1))
783     lea r1, [cos_ %+ n]
784     mov r2d, n4/2
785     jmp pass %+ fullsuffix
786
787 %assign n n*2
788 %endrep
789 %undef n
790
791 align 8
792 dispatch_tab %+ fullsuffix: pointer list_of_fft
793 %endmacro ; DECL_FFT
794
795 %if HAVE_AVX_EXTERNAL
796 INIT_YMM avx
797 DECL_FFT 6
798 DECL_FFT 6, _interleave
799 %endif
800 INIT_XMM sse
801 DECL_FFT 5
802 DECL_FFT 5, _interleave
803 %if ARCH_X86_32
804 INIT_MMX 3dnow
805 DECL_FFT 4
806 DECL_FFT 4, _interleave
807 INIT_MMX 3dnowext
808 DECL_FFT 4
809 DECL_FFT 4, _interleave
810 %endif
811
812 INIT_XMM sse
813 %undef mulps
814 %undef addps
815 %undef subps
816 %undef unpcklps
817 %undef unpckhps
818
819 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
820 %if mmsize == 8 ; j*2+2-n4, n4-2-j*2, input+n4, tcos+n8, tsin+n8
821     PSWAPD     m0, [%3+%2*4]
822     movq       m2, [%3+%1*4-8]
823     movq       m3, m0
824     punpckldq  m0, m2
825     punpckhdq  m2, m3
826     movd       m1, [%4+%1*2-4] ; tcos[j]
827     movd       m3, [%4+%2*2]   ; tcos[n4-j-1]
828     punpckldq  m1, [%5+%1*2-4] ; tsin[j]
829     punpckldq  m3, [%5+%2*2]   ; tsin[n4-j-1]
830
831     mova       m4, m0
832     PSWAPD     m5, m1
833     pfmul      m0, m1
834     pfmul      m4, m5
835     mova       m6, m2
836     PSWAPD     m5, m3
837     pfmul      m2, m3
838     pfmul      m6, m5
839 %if cpuflag(3dnowext)
840     pfpnacc    m0, m4
841     pfpnacc    m2, m6
842 %else
843     SBUTTERFLY dq, 0, 4, 1
844     SBUTTERFLY dq, 2, 6, 3
845     pxor       m4, m7
846     pxor       m6, m7
847     pfadd      m0, m4
848     pfadd      m2, m6
849 %endif
850 %else
851     movaps   xmm0, [%3+%2*4]
852     movaps   xmm1, [%3+%1*4-0x10]
853     movaps   xmm2, xmm0
854     shufps   xmm0, xmm1, 0x88
855     shufps   xmm1, xmm2, 0x77
856     movlps   xmm4, [%4+%2*2]
857     movlps   xmm5, [%5+%2*2+0x0]
858     movhps   xmm4, [%4+%1*2-0x8]
859     movhps   xmm5, [%5+%1*2-0x8]
860     movaps   xmm2, xmm0
861     movaps   xmm3, xmm1
862     mulps    xmm0, xmm5
863     mulps    xmm1, xmm4
864     mulps    xmm2, xmm4
865     mulps    xmm3, xmm5
866     subps    xmm1, xmm0
867     addps    xmm2, xmm3
868     movaps   xmm0, xmm1
869     unpcklps xmm1, xmm2
870     unpckhps xmm0, xmm2
871 %endif
872 %endmacro
873
874 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
875     mulps      m6, %3, [%5+%1]
876     mulps      m7, %2, [%5+%1]
877     mulps      %2, %2, [%6+%1]
878     mulps      %3, %3, [%6+%1]
879     subps      %2, %2, m6
880     addps      %3, %3, m7
881 %endmacro
882
883 %macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8
884 .post:
885     vmovaps      ymm1,   [%3+%1*2]
886     vmovaps      ymm0,   [%3+%1*2+0x20]
887     vmovaps      ymm3,   [%3+%2*2]
888     vmovaps      ymm2,   [%3+%2*2+0x20]
889
890     CMUL         %1, ymm0, ymm1, %3, %4, %5
891     CMUL         %2, ymm2, ymm3, %3, %4, %5
892     vshufps      ymm1, ymm1, ymm1, 0x1b
893     vshufps      ymm3, ymm3, ymm3, 0x1b
894     vperm2f128   ymm1, ymm1, ymm1, 0x01
895     vperm2f128   ymm3, ymm3, ymm3, 0x01
896     vunpcklps    ymm6, ymm2, ymm1
897     vunpckhps    ymm4, ymm2, ymm1
898     vunpcklps    ymm7, ymm0, ymm3
899     vunpckhps    ymm5, ymm0, ymm3
900
901     vextractf128 [%3+%1*2],      ymm7, 0
902     vextractf128 [%3+%1*2+0x10], ymm5, 0
903     vextractf128 [%3+%1*2+0x20], ymm7, 1
904     vextractf128 [%3+%1*2+0x30], ymm5, 1
905
906     vextractf128 [%3+%2*2],      ymm6, 0
907     vextractf128 [%3+%2*2+0x10], ymm4, 0
908     vextractf128 [%3+%2*2+0x20], ymm6, 1
909     vextractf128 [%3+%2*2+0x30], ymm4, 1
910     sub      %2,   0x20
911     add      %1,   0x20
912     jl       .post
913 %endmacro
914
915 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
916 .post:
917     movaps   xmm1, [%3+%1*2]
918     movaps   xmm0, [%3+%1*2+0x10]
919     CMUL     %1,   xmm0, xmm1, %3, %4, %5
920     movaps   xmm5, [%3+%2*2]
921     movaps   xmm4, [%3+%2*2+0x10]
922     CMUL     %2,   xmm4, xmm5, %3, %4, %5
923     shufps   xmm1, xmm1, 0x1b
924     shufps   xmm5, xmm5, 0x1b
925     movaps   xmm6, xmm4
926     unpckhps xmm4, xmm1
927     unpcklps xmm6, xmm1
928     movaps   xmm2, xmm0
929     unpcklps xmm0, xmm5
930     unpckhps xmm2, xmm5
931     movaps   [%3+%2*2],      xmm6
932     movaps   [%3+%2*2+0x10], xmm4
933     movaps   [%3+%1*2],      xmm0
934     movaps   [%3+%1*2+0x10], xmm2
935     sub      %2,   0x10
936     add      %1,   0x10
937     jl       .post
938 %endmacro
939
940 %macro CMUL_3DNOW 6
941     mova       m6, [%1+%2*2]
942     mova       %3, [%1+%2*2+8]
943     mova       %4, m6
944     mova       m7, %3
945     pfmul      m6, [%5+%2]
946     pfmul      %3, [%6+%2]
947     pfmul      %4, [%6+%2]
948     pfmul      m7, [%5+%2]
949     pfsub      %3, m6
950     pfadd      %4, m7
951 %endmacro
952
953 %macro POSROTATESHUF_3DNOW 5 ;j, k, z+n8, tcos+n8, tsin+n8
954 .post:
955     CMUL_3DNOW %3, %1, m0, m1, %4, %5
956     CMUL_3DNOW %3, %2, m2, m3, %4, %5
957     movd  [%3+%1*2+ 0], m0
958     movd  [%3+%2*2+12], m1
959     movd  [%3+%2*2+ 0], m2
960     movd  [%3+%1*2+12], m3
961     psrlq      m0, 32
962     psrlq      m1, 32
963     psrlq      m2, 32
964     psrlq      m3, 32
965     movd  [%3+%1*2+ 8], m0
966     movd  [%3+%2*2+ 4], m1
967     movd  [%3+%2*2+ 8], m2
968     movd  [%3+%1*2+ 4], m3
969     sub        %2, 8
970     add        %1, 8
971     jl         .post
972 %endmacro
973
974 %macro DECL_IMDCT 1
975 cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *input
976 %if ARCH_X86_64
977 %define rrevtab r7
978 %define rtcos   r8
979 %define rtsin   r9
980 %else
981 %define rrevtab r6
982 %define rtsin   r6
983 %define rtcos   r5
984 %endif
985     mov   r3d, [r0+FFTContext.mdctsize]
986     add   r2, r3
987     shr   r3, 1
988     mov   rtcos, [r0+FFTContext.tcos]
989     mov   rtsin, [r0+FFTContext.tsin]
990     add   rtcos, r3
991     add   rtsin, r3
992 %if ARCH_X86_64 == 0
993     push  rtcos
994     push  rtsin
995 %endif
996     shr   r3, 1
997     mov   rrevtab, [r0+FFTContext.revtab]
998     add   rrevtab, r3
999 %if ARCH_X86_64 == 0
1000     push  rrevtab
1001 %endif
1002
1003 %if mmsize == 8
1004     sub   r3, 2
1005 %else
1006     sub   r3, 4
1007 %endif
1008 %if ARCH_X86_64 || mmsize == 8
1009     xor   r4, r4
1010     sub   r4, r3
1011 %endif
1012 %if notcpuflag(3dnowext) && mmsize == 8
1013     movd  m7, [ps_m1m1m1m1]
1014 %endif
1015 .pre:
1016 %if ARCH_X86_64 == 0
1017 ;unspill
1018 %if mmsize != 8
1019     xor   r4, r4
1020     sub   r4, r3
1021 %endif
1022     mov   rtcos, [esp+8]
1023     mov   rtsin, [esp+4]
1024 %endif
1025
1026     PREROTATER r4, r3, r2, rtcos, rtsin
1027 %if mmsize == 8
1028     mov    r6, [esp]                ; rrevtab = ptr+n8
1029     movzx  r5,  word [rrevtab+r4-2] ; rrevtab[j]
1030     movzx  r6,  word [rrevtab+r3]   ; rrevtab[n4-j-1]
1031     mova [r1+r5*8], m0
1032     mova [r1+r6*8], m2
1033     add    r4, 2
1034     sub    r3, 2
1035 %else
1036 %if ARCH_X86_64
1037     movzx  r5,  word [rrevtab+r4-4]
1038     movzx  r6,  word [rrevtab+r4-2]
1039     movzx  r10, word [rrevtab+r3]
1040     movzx  r11, word [rrevtab+r3+2]
1041     movlps [r1+r5 *8], xmm0
1042     movhps [r1+r6 *8], xmm0
1043     movlps [r1+r10*8], xmm1
1044     movhps [r1+r11*8], xmm1
1045     add    r4, 4
1046 %else
1047     mov    r6, [esp]
1048     movzx  r5, word [r6+r4-4]
1049     movzx  r4, word [r6+r4-2]
1050     movlps [r1+r5*8], xmm0
1051     movhps [r1+r4*8], xmm0
1052     movzx  r5, word [r6+r3]
1053     movzx  r4, word [r6+r3+2]
1054     movlps [r1+r5*8], xmm1
1055     movhps [r1+r4*8], xmm1
1056 %endif
1057     sub    r3, 4
1058 %endif
1059     jns    .pre
1060
1061     mov  r5, r0
1062     mov  r6, r1
1063     mov  r0, r1
1064     mov  r1d, [r5+FFTContext.nbits]
1065
1066     FFT_DISPATCH SUFFIX, r1
1067
1068     mov  r0d, [r5+FFTContext.mdctsize]
1069     add  r6, r0
1070     shr  r0, 1
1071 %if ARCH_X86_64 == 0
1072 %define rtcos r2
1073 %define rtsin r3
1074     mov  rtcos, [esp+8]
1075     mov  rtsin, [esp+4]
1076 %endif
1077     neg  r0
1078     mov  r1, -mmsize
1079     sub  r1, r0
1080     %1 r0, r1, r6, rtcos, rtsin
1081 %if ARCH_X86_64 == 0
1082     add esp, 12
1083 %endif
1084 %if mmsize == 8
1085     femms
1086 %endif
1087     RET
1088 %endmacro
1089
1090 DECL_IMDCT POSROTATESHUF
1091
1092 %if ARCH_X86_32
1093 INIT_MMX 3dnow
1094 DECL_IMDCT POSROTATESHUF_3DNOW
1095
1096 INIT_MMX 3dnowext
1097 DECL_IMDCT POSROTATESHUF_3DNOW
1098 %endif
1099
1100 INIT_YMM avx
1101
1102 %if HAVE_AVX_EXTERNAL
1103 DECL_IMDCT POSROTATESHUF_AVX
1104 %endif