]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/fft_mmx.asm
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / 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     .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_3DN 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_3DN 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
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 %define movdqa  movaps
401
402 align 16
403 fft4_avx:
404 fft4_sse:
405     mova     m0, Z(0)
406     mova     m1, Z(1)
407     T4_SSE   m0, m1, m2
408     mova   Z(0), m0
409     mova   Z(1), m1
410     ret
411
412 align 16
413 fft8_sse:
414     mova     m0, Z(0)
415     mova     m1, Z(1)
416     T4_SSE   m0, m1, m2
417     mova     m2, Z(2)
418     mova     m3, Z(3)
419     T8_SSE   m0, m1, m2, m3, m4, m5
420     mova   Z(0), m0
421     mova   Z(1), m1
422     mova   Z(2), m2
423     mova   Z(3), m3
424     ret
425
426 align 16
427 fft16_sse:
428     mova     m0, Z(0)
429     mova     m1, Z(1)
430     T4_SSE   m0, m1, m2
431     mova     m2, Z(2)
432     mova     m3, Z(3)
433     T8_SSE   m0, m1, m2, m3, m4, m5
434     mova     m4, Z(4)
435     mova     m5, Z(5)
436     mova   Z(0), m0
437     mova   Z(1), m1
438     mova   Z(2), m2
439     mova   Z(3), m3
440     T4_SSE   m4, m5, m6
441     mova     m6, Z2(6)
442     mova     m7, Z2(7)
443     T4_SSE   m6, m7, m0
444     PASS_SMALL 0, [cos_16], [cos_16+16]
445     ret
446
447
448 %macro FFT48_3DN 0
449 align 16
450 fft4 %+ SUFFIX:
451     T2_3DN   m0, m1, Z(0), Z(1)
452     mova     m2, Z(2)
453     mova     m3, Z(3)
454     T4_3DN   m0, m1, m2, m3, m4, m5
455     PUNPCK   m0, m1, m4
456     PUNPCK   m2, m3, m5
457     mova   Z(0), m0
458     mova   Z(1), m4
459     mova   Z(2), m2
460     mova   Z(3), m5
461     ret
462
463 align 16
464 fft8 %+ SUFFIX:
465     T2_3DN   m0, m1, Z(0), Z(1)
466     mova     m2, Z(2)
467     mova     m3, Z(3)
468     T4_3DN   m0, m1, m2, m3, m4, m5
469     mova   Z(0), m0
470     mova   Z(2), m2
471     T2_3DN   m4, m5,  Z(4),  Z(5)
472     T2_3DN   m6, m7, Z2(6), Z2(7)
473     pswapd   m0, m5
474     pswapd   m2, m7
475     pxor     m0, [ps_m1p1]
476     pxor     m2, [ps_m1p1]
477     pfsub    m5, m0
478     pfadd    m7, m2
479     pfmul    m5, [ps_root2]
480     pfmul    m7, [ps_root2]
481     T4_3DN   m1, m3, m5, m7, m0, m2
482     mova   Z(5), m5
483     mova  Z2(7), m7
484     mova     m0, Z(0)
485     mova     m2, Z(2)
486     T4_3DN   m0, m2, m4, m6, m5, m7
487     PUNPCK   m0, m1, m5
488     PUNPCK   m2, m3, m7
489     mova   Z(0), m0
490     mova   Z(1), m5
491     mova   Z(2), m2
492     mova   Z(3), m7
493     PUNPCK   m4,  Z(5), m5
494     PUNPCK   m6, Z2(7), m7
495     mova   Z(4), m4
496     mova   Z(5), m5
497     mova  Z2(6), m6
498     mova  Z2(7), m7
499     ret
500 %endmacro
501
502 INIT_MMX 3dnow2
503 FFT48_3DN
504
505 %macro pswapd 2
506 %ifidn %1, %2
507     movd [r0+12], %1
508     punpckhdq %1, [r0+8]
509 %else
510     movq  %1, %2
511     psrlq %1, 32
512     punpckldq %1, %2
513 %endif
514 %endmacro
515
516 INIT_MMX 3dnow
517 FFT48_3DN
518
519
520 %define Z(x) [zq + o1q*(x&6) + mmsize*(x&1)]
521 %define Z2(x) [zq + o3q + mmsize*(x&1)]
522 %define ZH(x) [zq + o1q*(x&6) + mmsize*(x&1) + mmsize/2]
523 %define Z2H(x) [zq + o3q + mmsize*(x&1) + mmsize/2]
524
525 %macro DECL_PASS 2+ ; name, payload
526 align 16
527 %1:
528 DEFINE_ARGS z, w, n, o1, o3
529     lea o3q, [nq*3]
530     lea o1q, [nq*8]
531     shl o3q, 4
532 .loop:
533     %2
534     add zq, mmsize*2
535     add wq, mmsize
536     sub nd, mmsize/8
537     jg .loop
538     rep ret
539 %endmacro
540
541 %macro FFT_DISPATCH 2; clobbers 5 GPRs, 8 XMMs
542     lea r2, [dispatch_tab%1]
543     mov r2, [r2 + (%2q-2)*gprsize]
544 %ifdef PIC
545     lea r3, [$$]
546     add r2, r3
547 %endif
548     call r2
549 %endmacro ; FFT_DISPATCH
550
551 INIT_YMM avx
552
553 %if HAVE_AVX
554 %macro INTERL_AVX 5
555     vunpckhps      %3, %2, %1
556     vunpcklps      %2, %2, %1
557     vextractf128   %4(%5), %2, 0
558     vextractf128  %4 %+ H(%5), %3, 0
559     vextractf128   %4(%5 + 1), %2, 1
560     vextractf128  %4 %+ H(%5 + 1), %3, 1
561 %endmacro
562
563 %define INTERL INTERL_AVX
564
565 DECL_PASS pass_avx, PASS_BIG 1
566 DECL_PASS pass_interleave_avx, PASS_BIG 0
567
568 cglobal fft_calc, 2,5,8
569     mov     r3d, [r0 + FFTContext.nbits]
570     mov     r0, r1
571     mov     r1, r3
572     FFT_DISPATCH _interleave %+ SUFFIX, r1
573     REP_RET
574
575 %endif
576
577 INIT_XMM sse
578
579 %macro INTERL_SSE 5
580     mova     %3, %2
581     unpcklps %2, %1
582     unpckhps %3, %1
583     mova  %4(%5), %2
584     mova  %4(%5+1), %3
585 %endmacro
586
587 %define INTERL INTERL_SSE
588
589 DECL_PASS pass_sse, PASS_BIG 1
590 DECL_PASS pass_interleave_sse, PASS_BIG 0
591
592 cglobal fft_calc, 2,5,8
593     mov     r3d, [r0 + FFTContext.nbits]
594     PUSH    r1
595     PUSH    r3
596     mov     r0, r1
597     mov     r1, r3
598     FFT_DISPATCH _interleave %+ SUFFIX, r1
599     POP     rcx
600     POP     r4
601     cmp     rcx, 4
602     jg      .end
603     mov     r2, -1
604     add     rcx, 3
605     shl     r2, cl
606     sub     r4, r2
607 .loop
608     movaps   xmm0, [r4 + r2]
609     movaps   xmm1, xmm0
610     unpcklps xmm0, [r4 + r2 + 16]
611     unpckhps xmm1, [r4 + r2 + 16]
612     movaps   [r4 + r2],      xmm0
613     movaps   [r4 + r2 + 16], xmm1
614     add      r2, 32
615     jl       .loop
616 .end:
617     REP_RET
618
619 cglobal fft_permute, 2,7,1
620     mov     r4,  [r0 + FFTContext.revtab]
621     mov     r5,  [r0 + FFTContext.tmpbuf]
622     mov     ecx, [r0 + FFTContext.nbits]
623     mov     r2, 1
624     shl     r2, cl
625     xor     r0, r0
626 %if ARCH_X86_32
627     mov     r1, r1m
628 %endif
629 .loop:
630     movaps  xmm0, [r1 + 8*r0]
631     movzx   r6, word [r4 + 2*r0]
632     movzx   r3, word [r4 + 2*r0 + 2]
633     movlps  [r5 + 8*r6], xmm0
634     movhps  [r5 + 8*r3], xmm0
635     add     r0, 2
636     cmp     r0, r2
637     jl      .loop
638     shl     r2, 3
639     add     r1, r2
640     add     r5, r2
641     neg     r2
642 ; nbits >= 2 (FFT4) and sizeof(FFTComplex)=8 => at least 32B
643 .loopcopy:
644     movaps  xmm0, [r5 + r2]
645     movaps  xmm1, [r5 + r2 + 16]
646     movaps  [r1 + r2], xmm0
647     movaps  [r1 + r2 + 16], xmm1
648     add     r2, 32
649     jl      .loopcopy
650     REP_RET
651
652 cglobal imdct_calc, 3,5,3
653     mov     r3d, [r0 + FFTContext.mdctsize]
654     mov     r4,  [r0 + FFTContext.imdcthalf]
655     add     r1,  r3
656     PUSH    r3
657     PUSH    r1
658 %if ARCH_X86_32
659     push    r2
660     push    r1
661     push    r0
662 %else
663     sub     rsp, 8
664 %endif
665     call    r4
666 %if ARCH_X86_32
667     add     esp, 12
668 %else
669     add     rsp, 8
670 %endif
671     POP     r1
672     POP     r3
673     lea     r0, [r1 + 2*r3]
674     mov     r2, r3
675     sub     r3, 16
676     neg     r2
677     movaps  xmm2, [ps_m1m1m1m1]
678 .loop:
679     movaps  xmm0, [r1 + r3]
680     movaps  xmm1, [r0 + r2]
681     shufps  xmm0, xmm0, 0x1b
682     shufps  xmm1, xmm1, 0x1b
683     xorps   xmm0, xmm2
684     movaps  [r0 + r3], xmm1
685     movaps  [r1 + r2], xmm0
686     sub     r3, 16
687     add     r2, 16
688     jl      .loop
689     REP_RET
690
691 INIT_MMX 3dnow
692 %define mulps pfmul
693 %define addps pfadd
694 %define subps pfsub
695 %define unpcklps punpckldq
696 %define unpckhps punpckhdq
697 DECL_PASS pass_3dnow, PASS_SMALL 1, [wq], [wq+o1q]
698 DECL_PASS pass_interleave_3dnow, PASS_BIG 0
699 %define pass_3dnow2 pass_3dnow
700 %define pass_interleave_3dnow2 pass_interleave_3dnow
701
702 %ifdef PIC
703 %define SECTION_REL - $$
704 %else
705 %define SECTION_REL
706 %endif
707
708 %macro DECL_FFT 1-2 ; nbits, suffix
709 %ifidn %0, 1
710 %xdefine fullsuffix SUFFIX
711 %else
712 %xdefine fullsuffix %2 %+ SUFFIX
713 %endif
714 %xdefine list_of_fft fft4 %+ SUFFIX SECTION_REL, fft8 %+ SUFFIX SECTION_REL
715 %if %1>=5
716 %xdefine list_of_fft list_of_fft, fft16 %+ SUFFIX SECTION_REL
717 %endif
718 %if %1>=6
719 %xdefine list_of_fft list_of_fft, fft32 %+ fullsuffix SECTION_REL
720 %endif
721
722 %assign n 1<<%1
723 %rep 17-%1
724 %assign n2 n/2
725 %assign n4 n/4
726 %xdefine list_of_fft list_of_fft, fft %+ n %+ fullsuffix SECTION_REL
727
728 align 16
729 fft %+ n %+ fullsuffix:
730     call fft %+ n2 %+ SUFFIX
731     add r0, n*4 - (n&(-2<<%1))
732     call fft %+ n4 %+ SUFFIX
733     add r0, n*2 - (n2&(-2<<%1))
734     call fft %+ n4 %+ SUFFIX
735     sub r0, n*6 + (n2&(-2<<%1))
736     lea r1, [cos_ %+ n]
737     mov r2d, n4/2
738     jmp pass %+ fullsuffix
739
740 %assign n n*2
741 %endrep
742 %undef n
743
744 align 8
745 dispatch_tab %+ fullsuffix: pointer list_of_fft
746
747 section .text
748
749 ; On x86_32, this function does the register saving and restoring for all of fft.
750 ; The others pass args in registers and don't spill anything.
751 cglobal fft_dispatch%2, 2,5,8, z, nbits
752     FFT_DISPATCH fullsuffix, nbits
753 %if mmsize == 32
754     vzeroupper
755 %endif
756     RET
757 %endmacro ; DECL_FFT
758
759 %if HAVE_AVX
760 INIT_YMM avx
761 DECL_FFT 6
762 DECL_FFT 6, _interleave
763 %endif
764 INIT_XMM sse
765 DECL_FFT 5
766 DECL_FFT 5, _interleave
767 INIT_MMX 3dnow
768 DECL_FFT 4
769 DECL_FFT 4, _interleave
770 INIT_MMX 3dnow2
771 DECL_FFT 4
772 DECL_FFT 4, _interleave
773
774 INIT_XMM sse
775 %undef mulps
776 %undef addps
777 %undef subps
778 %undef unpcklps
779 %undef unpckhps
780
781 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
782     movaps   xmm0, [%3+%2*4]
783     movaps   xmm1, [%3+%1*4-0x10]
784     movaps   xmm2, xmm0
785     shufps   xmm0, xmm1, 0x88
786     shufps   xmm1, xmm2, 0x77
787     movlps   xmm4, [%4+%2*2]
788     movlps   xmm5, [%5+%2*2+0x0]
789     movhps   xmm4, [%4+%1*2-0x8]
790     movhps   xmm5, [%5+%1*2-0x8]
791     movaps   xmm2, xmm0
792     movaps   xmm3, xmm1
793     mulps    xmm0, xmm5
794     mulps    xmm1, xmm4
795     mulps    xmm2, xmm4
796     mulps    xmm3, xmm5
797     subps    xmm1, xmm0
798     addps    xmm2, xmm3
799     movaps   xmm0, xmm1
800     unpcklps xmm1, xmm2
801     unpckhps xmm0, xmm2
802 %endmacro
803
804 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
805     mulps      m6, %3, [%5+%1]
806     mulps      m7, %2, [%5+%1]
807     mulps      %2, %2, [%6+%1]
808     mulps      %3, %3, [%6+%1]
809     subps      %2, %2, m6
810     addps      %3, %3, m7
811 %endmacro
812
813 %macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8
814 .post:
815     vmovaps      ymm1,   [%3+%1*2]
816     vmovaps      ymm0,   [%3+%1*2+0x20]
817     vmovaps      ymm3,   [%3+%2*2]
818     vmovaps      ymm2,   [%3+%2*2+0x20]
819
820     CMUL         %1, ymm0, ymm1, %3, %4, %5
821     CMUL         %2, ymm2, ymm3, %3, %4, %5
822     vshufps      ymm1, ymm1, ymm1, 0x1b
823     vshufps      ymm3, ymm3, ymm3, 0x1b
824     vperm2f128   ymm1, ymm1, ymm1, 0x01
825     vperm2f128   ymm3, ymm3, ymm3, 0x01
826     vunpcklps    ymm6, ymm2, ymm1
827     vunpckhps    ymm4, ymm2, ymm1
828     vunpcklps    ymm7, ymm0, ymm3
829     vunpckhps    ymm5, ymm0, ymm3
830
831     vextractf128 [%3+%1*2],      ymm7, 0
832     vextractf128 [%3+%1*2+0x10], ymm5, 0
833     vextractf128 [%3+%1*2+0x20], ymm7, 1
834     vextractf128 [%3+%1*2+0x30], ymm5, 1
835
836     vextractf128 [%3+%2*2],      ymm6, 0
837     vextractf128 [%3+%2*2+0x10], ymm4, 0
838     vextractf128 [%3+%2*2+0x20], ymm6, 1
839     vextractf128 [%3+%2*2+0x30], ymm4, 1
840     sub      %2,   0x20
841     add      %1,   0x20
842     jl       .post
843 %endmacro
844
845 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
846 .post:
847     movaps   xmm1, [%3+%1*2]
848     movaps   xmm0, [%3+%1*2+0x10]
849     CMUL     %1,   xmm0, xmm1, %3, %4, %5
850     movaps   xmm5, [%3+%2*2]
851     movaps   xmm4, [%3+%2*2+0x10]
852     CMUL     %2,   xmm4, xmm5, %3, %4, %5
853     shufps   xmm1, xmm1, 0x1b
854     shufps   xmm5, xmm5, 0x1b
855     movaps   xmm6, xmm4
856     unpckhps xmm4, xmm1
857     unpcklps xmm6, xmm1
858     movaps   xmm2, xmm0
859     unpcklps xmm0, xmm5
860     unpckhps xmm2, xmm5
861     movaps   [%3+%2*2],      xmm6
862     movaps   [%3+%2*2+0x10], xmm4
863     movaps   [%3+%1*2],      xmm0
864     movaps   [%3+%1*2+0x10], xmm2
865     sub      %2,   0x10
866     add      %1,   0x10
867     jl       .post
868 %endmacro
869
870 %macro DECL_IMDCT 1
871 cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *input
872 %if ARCH_X86_64
873 %define rrevtab r7
874 %define rtcos   r8
875 %define rtsin   r9
876 %else
877 %define rrevtab r6
878 %define rtsin   r6
879 %define rtcos   r5
880 %endif
881     mov   r3d, [r0+FFTContext.mdctsize]
882     add   r2, r3
883     shr   r3, 1
884     mov   rtcos, [r0+FFTContext.tcos]
885     mov   rtsin, [r0+FFTContext.tsin]
886     add   rtcos, r3
887     add   rtsin, r3
888 %if ARCH_X86_64 == 0
889     push  rtcos
890     push  rtsin
891 %endif
892     shr   r3, 1
893     mov   rrevtab, [r0+FFTContext.revtab]
894     add   rrevtab, r3
895 %if ARCH_X86_64 == 0
896     push  rrevtab
897 %endif
898
899     sub   r3, 4
900 %if ARCH_X86_64
901     xor   r4, r4
902     sub   r4, r3
903 %endif
904 .pre:
905 %if ARCH_X86_64 == 0
906 ;unspill
907     xor   r4, r4
908     sub   r4, r3
909     mov   rtsin, [esp+4]
910     mov   rtcos, [esp+8]
911 %endif
912
913     PREROTATER r4, r3, r2, rtcos, rtsin
914 %if ARCH_X86_64
915     movzx  r5,  word [rrevtab+r4-4]
916     movzx  r6,  word [rrevtab+r4-2]
917     movzx  r10, word [rrevtab+r3]
918     movzx  r11, word [rrevtab+r3+2]
919     movlps [r1+r5 *8], xmm0
920     movhps [r1+r6 *8], xmm0
921     movlps [r1+r10*8], xmm1
922     movhps [r1+r11*8], xmm1
923     add    r4, 4
924 %else
925     mov    r6, [esp]
926     movzx  r5, word [r6+r4-4]
927     movzx  r4, word [r6+r4-2]
928     movlps [r1+r5*8], xmm0
929     movhps [r1+r4*8], xmm0
930     movzx  r5, word [r6+r3]
931     movzx  r4, word [r6+r3+2]
932     movlps [r1+r5*8], xmm1
933     movhps [r1+r4*8], xmm1
934 %endif
935     sub    r3, 4
936     jns    .pre
937
938     mov  r5, r0
939     mov  r6, r1
940     mov  r0, r1
941     mov  r1d, [r5+FFTContext.nbits]
942
943     FFT_DISPATCH SUFFIX, r1
944
945     mov  r0d, [r5+FFTContext.mdctsize]
946     add  r6, r0
947     shr  r0, 1
948 %if ARCH_X86_64 == 0
949 %define rtcos r2
950 %define rtsin r3
951     mov  rtcos, [esp+8]
952     mov  rtsin, [esp+4]
953 %endif
954     neg  r0
955     mov  r1, -mmsize
956     sub  r1, r0
957     %1 r0, r1, r6, rtcos, rtsin
958 %if ARCH_X86_64 == 0
959     add esp, 12
960 %endif
961 %if mmsize == 32
962     vzeroupper
963 %endif
964     RET
965 %endmacro
966
967 DECL_IMDCT POSROTATESHUF
968
969 INIT_YMM avx
970
971 %if HAVE_AVX
972 DECL_IMDCT POSROTATESHUF_AVX
973 %endif