2c7438134c3ce1354dbd533c913de1bb39899c8c
[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 "libavutil/x86/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 32
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 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
61 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
62
63 ps_root2: times 8 dd M_SQRT1_2
64 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
65 ps_p1p1m1p1: dd 0, 0, 1<<31, 0, 0, 0, 1<<31, 0
66
67 perm1: dd 0x00, 0x02, 0x03, 0x01, 0x03, 0x00, 0x02, 0x01
68 perm2: dd 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x02, 0x03
69 ps_p1p1m1p1root2: dd 1.0, 1.0, -1.0, 1.0, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2
70 ps_m1m1p1m1p1m1m1m1: dd 1<<31, 1<<31, 0, 1<<31, 0, 1<<31, 1<<31, 1<<31
71 ps_m1m1m1m1: times 4 dd 1<<31
72 ps_m1p1: dd 1<<31, 0
73
74 %assign i 16
75 %rep 13
76 cextern cos_ %+ i
77 %assign i i<<1
78 %endrep
79
80 %if ARCH_X86_64
81     %define pointer dq
82 %else
83     %define pointer dd
84 %endif
85
86 %macro IF0 1+
87 %endmacro
88 %macro IF1 1+
89     %1
90 %endmacro
91
92 SECTION .text
93
94 %macro T2_3DNOW 4 ; z0, z1, mem0, mem1
95     mova     %1, %3
96     mova     %2, %1
97     pfadd    %1, %4
98     pfsub    %2, %4
99 %endmacro
100
101 %macro T4_3DNOW 6 ; z0, z1, z2, z3, tmp0, tmp1
102     mova     %5, %3
103     pfsub    %3, %4
104     pfadd    %5, %4 ; {t6,t5}
105     pxor     %3, [ps_m1p1] ; {t8,t7}
106     mova     %6, %1
107     movd [r0+12], %3
108     punpckhdq %3, [r0+8]
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 align 16
308 fft8_avx:
309     mova      m0, Z(0)
310     mova      m1, Z(1)
311     T8_AVX    m0, m1, m2, m3, m4
312     mova      Z(0), m0
313     mova      Z(1), m1
314     ret
315
316
317 align 16
318 fft16_avx:
319     mova       m2, Z(2)
320     mova       m3, Z(3)
321     T4_SSE     m2, m3, m7
322
323     mova       m0, Z(0)
324     mova       m1, Z(1)
325     T8_AVX     m0, m1, m4, m5, m7
326
327     mova       m4, [ps_cos16_1]
328     mova       m5, [ps_cos16_2]
329     vmulps     m6, m2, m4
330     vmulps     m7, m3, m5
331     vaddps     m7, m7, m6
332     vmulps     m2, m2, m5
333     vmulps     m3, m3, m4
334     vsubps     m3, m3, m2
335     vblendps   m2, m7, m3, 0xf0
336     vperm2f128 m3, m7, m3, 0x21
337     vaddps     m4, m2, m3
338     vsubps     m2, m3, m2
339     vperm2f128 m2, m2, m2, 0x01
340     vsubps     m3, m1, m2
341     vaddps     m1, m1, m2
342     vsubps     m5, m0, m4
343     vaddps     m0, m0, m4
344     vextractf128   Z(0), m0, 0
345     vextractf128  ZH(0), m1, 0
346     vextractf128   Z(1), m0, 1
347     vextractf128  ZH(1), m1, 1
348     vextractf128   Z(2), m5, 0
349     vextractf128  ZH(2), m3, 0
350     vextractf128   Z(3), m5, 1
351     vextractf128  ZH(3), m3, 1
352     ret
353
354 align 16
355 fft32_avx:
356     call fft16_avx
357
358     mova m0, Z(4)
359     mova m1, Z(5)
360
361     T4_SSE      m0, m1, m4
362
363     mova m2, Z(6)
364     mova m3, Z(7)
365
366     T8_SSE      m0, m1, m2, m3, m4, m6
367     ; m0={r0,r1,r2,r3,r8, r9, r10,r11} m1={i0,i1,i2,i3,i8, i9, i10,i11}
368     ; m2={r4,r5,r6,r7,r12,r13,r14,r15} m3={i4,i5,i6,i7,i12,i13,i14,i15}
369
370     vperm2f128  m4, m0, m2, 0x20
371     vperm2f128  m5, m1, m3, 0x20
372     vperm2f128  m6, m0, m2, 0x31
373     vperm2f128  m7, m1, m3, 0x31
374
375     PASS_SMALL 0, [cos_32], [cos_32+32]
376
377     ret
378
379 fft32_interleave_avx:
380     call fft32_avx
381     mov r2d, 32
382 .deint_loop:
383     mova     m2, Z(0)
384     mova     m3, Z(1)
385     vunpcklps      m0, m2, m3
386     vunpckhps      m1, m2, m3
387     vextractf128   Z(0), m0, 0
388     vextractf128  ZH(0), m1, 0
389     vextractf128   Z(1), m0, 1
390     vextractf128  ZH(1), m1, 1
391     add r0, mmsize*2
392     sub r2d, mmsize/4
393     jg .deint_loop
394     ret
395
396 INIT_XMM sse
397
398 align 16
399 fft4_avx:
400 fft4_sse:
401     mova     m0, Z(0)
402     mova     m1, Z(1)
403     T4_SSE   m0, m1, m2
404     mova   Z(0), m0
405     mova   Z(1), m1
406     ret
407
408 align 16
409 fft8_sse:
410     mova     m0, Z(0)
411     mova     m1, Z(1)
412     T4_SSE   m0, m1, m2
413     mova     m2, Z(2)
414     mova     m3, Z(3)
415     T8_SSE   m0, m1, m2, m3, m4, m5
416     mova   Z(0), m0
417     mova   Z(1), m1
418     mova   Z(2), m2
419     mova   Z(3), m3
420     ret
421
422 align 16
423 fft16_sse:
424     mova     m0, Z(0)
425     mova     m1, Z(1)
426     T4_SSE   m0, m1, m2
427     mova     m2, Z(2)
428     mova     m3, Z(3)
429     T8_SSE   m0, m1, m2, m3, m4, m5
430     mova     m4, Z(4)
431     mova     m5, Z(5)
432     mova   Z(0), m0
433     mova   Z(1), m1
434     mova   Z(2), m2
435     mova   Z(3), m3
436     T4_SSE   m4, m5, m6
437     mova     m6, Z2(6)
438     mova     m7, Z2(7)
439     T4_SSE   m6, m7, m0
440     PASS_SMALL 0, [cos_16], [cos_16+16]
441     ret
442
443
444 %macro FFT48_3DNOW 0
445 align 16
446 fft4 %+ SUFFIX:
447     T2_3DNOW m0, m1, Z(0), Z(1)
448     mova     m2, Z(2)
449     mova     m3, Z(3)
450     T4_3DNOW m0, m1, m2, m3, m4, m5
451     PUNPCK   m0, m1, m4
452     PUNPCK   m2, m3, m5
453     mova   Z(0), m0
454     mova   Z(1), m4
455     mova   Z(2), m2
456     mova   Z(3), m5
457     ret
458
459 align 16
460 fft8 %+ SUFFIX:
461     T2_3DNOW m0, m1, Z(0), Z(1)
462     mova     m2, Z(2)
463     mova     m3, Z(3)
464     T4_3DNOW m0, m1, m2, m3, m4, m5
465     mova   Z(0), m0
466     mova   Z(2), m2
467     T2_3DNOW m4, m5,  Z(4),  Z(5)
468     T2_3DNOW m6, m7, Z2(6), Z2(7)
469     PSWAPD   m0, m5
470     PSWAPD   m2, m7
471     pxor     m0, [ps_m1p1]
472     pxor     m2, [ps_m1p1]
473     pfsub    m5, m0
474     pfadd    m7, m2
475     pfmul    m5, [ps_root2]
476     pfmul    m7, [ps_root2]
477     T4_3DNOW m1, m3, m5, m7, m0, m2
478     mova   Z(5), m5
479     mova  Z2(7), m7
480     mova     m0, Z(0)
481     mova     m2, Z(2)
482     T4_3DNOW m0, m2, m4, m6, m5, m7
483     PUNPCK   m0, m1, m5
484     PUNPCK   m2, m3, m7
485     mova   Z(0), m0
486     mova   Z(1), m5
487     mova   Z(2), m2
488     mova   Z(3), m7
489     PUNPCK   m4,  Z(5), m5
490     PUNPCK   m6, Z2(7), m7
491     mova   Z(4), m4
492     mova   Z(5), m5
493     mova  Z2(6), m6
494     mova  Z2(7), m7
495     ret
496 %endmacro
497
498 %if ARCH_X86_32
499 INIT_MMX 3dnowext
500 FFT48_3DNOW
501
502 INIT_MMX 3dnow
503 FFT48_3DNOW
504 %endif
505
506 %define Z(x) [zcq + o1q*(x&6) + mmsize*(x&1)]
507 %define Z2(x) [zcq + o3q + mmsize*(x&1)]
508 %define ZH(x) [zcq + o1q*(x&6) + mmsize*(x&1) + mmsize/2]
509 %define Z2H(x) [zcq + o3q + mmsize*(x&1) + mmsize/2]
510
511 %macro DECL_PASS 2+ ; name, payload
512 align 16
513 %1:
514 DEFINE_ARGS zc, w, n, o1, o3
515     lea o3q, [nq*3]
516     lea o1q, [nq*8]
517     shl o3q, 4
518 .loop:
519     %2
520     add zcq, mmsize*2
521     add  wq, mmsize
522     sub  nd, mmsize/8
523     jg .loop
524     rep ret
525 %endmacro
526
527 %macro FFT_DISPATCH 2; clobbers 5 GPRs, 8 XMMs
528     lea r2, [dispatch_tab%1]
529     mov r2, [r2 + (%2q-2)*gprsize]
530 %ifdef PIC
531     lea r3, [$$]
532     add r2, r3
533 %endif
534     call r2
535 %endmacro ; FFT_DISPATCH
536
537 INIT_YMM avx
538
539 %macro INTERL_AVX 5
540     vunpckhps      %3, %2, %1
541     vunpcklps      %2, %2, %1
542     vextractf128   %4(%5), %2, 0
543     vextractf128  %4 %+ H(%5), %3, 0
544     vextractf128   %4(%5 + 1), %2, 1
545     vextractf128  %4 %+ H(%5 + 1), %3, 1
546 %endmacro
547
548 %define INTERL INTERL_AVX
549
550 DECL_PASS pass_avx, PASS_BIG 1
551 DECL_PASS pass_interleave_avx, PASS_BIG 0
552
553 cglobal fft_calc, 2,5,8
554     mov     r3d, [r0 + FFTContext.nbits]
555     mov     r0, r1
556     mov     r1, r3
557     FFT_DISPATCH _interleave %+ SUFFIX, r1
558     REP_RET
559
560
561 INIT_XMM sse
562
563 %macro INTERL_SSE 5
564     mova     %3, %2
565     unpcklps %2, %1
566     unpckhps %3, %1
567     mova  %4(%5), %2
568     mova  %4(%5+1), %3
569 %endmacro
570
571 %define INTERL INTERL_SSE
572
573 DECL_PASS pass_sse, PASS_BIG 1
574 DECL_PASS pass_interleave_sse, PASS_BIG 0
575
576 %macro FFT_CALC_FUNC 0
577 cglobal fft_calc, 2,5,8
578     mov     r3d, [r0 + FFTContext.nbits]
579     PUSH    r1
580     PUSH    r3
581     mov     r0, r1
582     mov     r1, r3
583     FFT_DISPATCH _interleave %+ SUFFIX, r1
584     POP     rcx
585     POP     r4
586     cmp     rcx, 3+(mmsize/16)
587     jg      .end
588     mov     r2, -1
589     add     rcx, 3
590     shl     r2, cl
591     sub     r4, r2
592 .loop:
593 %if mmsize == 8
594     PSWAPD  m0, [r4 + r2 + 4]
595     mova [r4 + r2 + 4], m0
596 %else
597     movaps   xmm0, [r4 + r2]
598     movaps   xmm1, xmm0
599     unpcklps xmm0, [r4 + r2 + 16]
600     unpckhps xmm1, [r4 + r2 + 16]
601     movaps   [r4 + r2],      xmm0
602     movaps   [r4 + r2 + 16], xmm1
603 %endif
604     add      r2, mmsize*2
605     jl       .loop
606 .end:
607 %if cpuflag(3dnow)
608     femms
609     RET
610 %else
611     REP_RET
612 %endif
613 %endmacro
614
615 %if ARCH_X86_32
616 INIT_MMX 3dnow
617 FFT_CALC_FUNC
618 INIT_MMX 3dnowext
619 FFT_CALC_FUNC
620 %endif
621 INIT_XMM sse
622 FFT_CALC_FUNC
623
624 cglobal fft_permute, 2,7,1
625     mov     r4,  [r0 + FFTContext.revtab]
626     mov     r5,  [r0 + FFTContext.tmpbuf]
627     mov     ecx, [r0 + FFTContext.nbits]
628     mov     r2, 1
629     shl     r2, cl
630     xor     r0, r0
631 %if ARCH_X86_32
632     mov     r1, r1m
633 %endif
634 .loop:
635     movaps  xmm0, [r1 + 8*r0]
636     movzx   r6, word [r4 + 2*r0]
637     movzx   r3, word [r4 + 2*r0 + 2]
638     movlps  [r5 + 8*r6], xmm0
639     movhps  [r5 + 8*r3], xmm0
640     add     r0, 2
641     cmp     r0, r2
642     jl      .loop
643     shl     r2, 3
644     add     r1, r2
645     add     r5, r2
646     neg     r2
647 ; nbits >= 2 (FFT4) and sizeof(FFTComplex)=8 => at least 32B
648 .loopcopy:
649     movaps  xmm0, [r5 + r2]
650     movaps  xmm1, [r5 + r2 + 16]
651     movaps  [r1 + r2], xmm0
652     movaps  [r1 + r2 + 16], xmm1
653     add     r2, 32
654     jl      .loopcopy
655     REP_RET
656
657 %if ARCH_X86_32
658 INIT_MMX 3dnow
659 %define mulps pfmul
660 %define addps pfadd
661 %define subps pfsub
662 %define unpcklps punpckldq
663 %define unpckhps punpckhdq
664 DECL_PASS pass_3dnow, PASS_SMALL 1, [wq], [wq+o1q]
665 DECL_PASS pass_interleave_3dnow, PASS_BIG 0
666 %define pass_3dnowext pass_3dnow
667 %define pass_interleave_3dnowext pass_interleave_3dnow
668 %endif
669
670 %ifdef PIC
671 %define SECTION_REL - $$
672 %else
673 %define SECTION_REL
674 %endif
675
676 %macro DECL_FFT 1-2 ; nbits, suffix
677 %ifidn %0, 1
678 %xdefine fullsuffix SUFFIX
679 %else
680 %xdefine fullsuffix %2 %+ SUFFIX
681 %endif
682 %xdefine list_of_fft fft4 %+ SUFFIX SECTION_REL, fft8 %+ SUFFIX SECTION_REL
683 %if %1>=5
684 %xdefine list_of_fft list_of_fft, fft16 %+ SUFFIX SECTION_REL
685 %endif
686 %if %1>=6
687 %xdefine list_of_fft list_of_fft, fft32 %+ fullsuffix SECTION_REL
688 %endif
689
690 %assign n 1<<%1
691 %rep 17-%1
692 %assign n2 n/2
693 %assign n4 n/4
694 %xdefine list_of_fft list_of_fft, fft %+ n %+ fullsuffix SECTION_REL
695
696 align 16
697 fft %+ n %+ fullsuffix:
698     call fft %+ n2 %+ SUFFIX
699     add r0, n*4 - (n&(-2<<%1))
700     call fft %+ n4 %+ SUFFIX
701     add r0, n*2 - (n2&(-2<<%1))
702     call fft %+ n4 %+ SUFFIX
703     sub r0, n*6 + (n2&(-2<<%1))
704     lea r1, [cos_ %+ n]
705     mov r2d, n4/2
706     jmp pass %+ fullsuffix
707
708 %assign n n*2
709 %endrep
710 %undef n
711
712 align 8
713 dispatch_tab %+ fullsuffix: pointer list_of_fft
714 %endmacro ; DECL_FFT
715
716 INIT_YMM avx
717 DECL_FFT 6
718 DECL_FFT 6, _interleave
719 INIT_XMM sse
720 DECL_FFT 5
721 DECL_FFT 5, _interleave
722 %if ARCH_X86_32
723 INIT_MMX 3dnow
724 DECL_FFT 4
725 DECL_FFT 4, _interleave
726 INIT_MMX 3dnowext
727 DECL_FFT 4
728 DECL_FFT 4, _interleave
729 %endif
730
731 %if CONFIG_MDCT
732
733 %macro IMDCT_CALC_FUNC 0
734 cglobal imdct_calc, 3,5,3
735     mov     r3d, [r0 + FFTContext.mdctsize]
736     mov     r4,  [r0 + FFTContext.imdcthalf]
737     add     r1,  r3
738     PUSH    r3
739     PUSH    r1
740 %if ARCH_X86_32
741     push    r2
742     push    r1
743     push    r0
744 %else
745     sub     rsp, 8+32*WIN64 ; allocate win64 shadow space
746 %endif
747     call    r4
748 %if ARCH_X86_32
749     add     esp, 12
750 %else
751     add     rsp, 8+32*WIN64
752 %endif
753     POP     r1
754     POP     r3
755     lea     r0, [r1 + 2*r3]
756     mov     r2, r3
757     sub     r3, mmsize
758     neg     r2
759     mova    m2, [ps_m1m1m1m1]
760 .loop:
761 %if mmsize == 8
762     PSWAPD  m0, [r1 + r3]
763     PSWAPD  m1, [r0 + r2]
764     pxor    m0, m2
765 %else
766     mova    m0, [r1 + r3]
767     mova    m1, [r0 + r2]
768     shufps  m0, m0, 0x1b
769     shufps  m1, m1, 0x1b
770     xorps   m0, m2
771 %endif
772     mova [r0 + r3], m1
773     mova [r1 + r2], m0
774     sub     r3, mmsize
775     add     r2, mmsize
776     jl      .loop
777 %if cpuflag(3dnow)
778     femms
779     RET
780 %else
781     REP_RET
782 %endif
783 %endmacro
784
785 %if ARCH_X86_32
786 INIT_MMX 3dnow
787 IMDCT_CALC_FUNC
788 INIT_MMX 3dnowext
789 IMDCT_CALC_FUNC
790 %endif
791
792 INIT_XMM sse
793 IMDCT_CALC_FUNC
794
795 INIT_XMM sse
796 %undef mulps
797 %undef addps
798 %undef subps
799 %undef unpcklps
800 %undef unpckhps
801
802 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
803 %if mmsize == 8 ; j*2+2-n4, n4-2-j*2, input+n4, tcos+n8, tsin+n8
804     PSWAPD     m0, [%3+%2*4]
805     movq       m2, [%3+%1*4-8]
806     movq       m3, m0
807     punpckldq  m0, m2
808     punpckhdq  m2, m3
809     movd       m1, [%4+%1*2-4] ; tcos[j]
810     movd       m3, [%4+%2*2]   ; tcos[n4-j-1]
811     punpckldq  m1, [%5+%1*2-4] ; tsin[j]
812     punpckldq  m3, [%5+%2*2]   ; tsin[n4-j-1]
813
814     mova       m4, m0
815     PSWAPD     m5, m1
816     pfmul      m0, m1
817     pfmul      m4, m5
818     mova       m6, m2
819     PSWAPD     m5, m3
820     pfmul      m2, m3
821     pfmul      m6, m5
822 %if cpuflag(3dnowext)
823     pfpnacc    m0, m4
824     pfpnacc    m2, m6
825 %else
826     SBUTTERFLY dq, 0, 4, 1
827     SBUTTERFLY dq, 2, 6, 3
828     pxor       m4, m7
829     pxor       m6, m7
830     pfadd      m0, m4
831     pfadd      m2, m6
832 %endif
833 %else
834     movaps   xmm0, [%3+%2*4]
835     movaps   xmm1, [%3+%1*4-0x10]
836     movaps   xmm2, xmm0
837     shufps   xmm0, xmm1, 0x88
838     shufps   xmm1, xmm2, 0x77
839     movlps   xmm4, [%4+%2*2]
840     movlps   xmm5, [%5+%2*2+0x0]
841     movhps   xmm4, [%4+%1*2-0x8]
842     movhps   xmm5, [%5+%1*2-0x8]
843     movaps   xmm2, xmm0
844     movaps   xmm3, xmm1
845     mulps    xmm0, xmm5
846     mulps    xmm1, xmm4
847     mulps    xmm2, xmm4
848     mulps    xmm3, xmm5
849     subps    xmm1, xmm0
850     addps    xmm2, xmm3
851     movaps   xmm0, xmm1
852     unpcklps xmm1, xmm2
853     unpckhps xmm0, xmm2
854 %endif
855 %endmacro
856
857 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
858     mulps      m6, %3, [%5+%1]
859     mulps      m7, %2, [%5+%1]
860     mulps      %2, %2, [%6+%1]
861     mulps      %3, %3, [%6+%1]
862     subps      %2, %2, m6
863     addps      %3, %3, m7
864 %endmacro
865
866 %macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8
867 .post:
868     vmovaps      ymm1,   [%3+%1*2]
869     vmovaps      ymm0,   [%3+%1*2+0x20]
870     vmovaps      ymm3,   [%3+%2*2]
871     vmovaps      ymm2,   [%3+%2*2+0x20]
872
873     CMUL         %1, ymm0, ymm1, %3, %4, %5
874     CMUL         %2, ymm2, ymm3, %3, %4, %5
875     vshufps      ymm1, ymm1, ymm1, 0x1b
876     vshufps      ymm3, ymm3, ymm3, 0x1b
877     vperm2f128   ymm1, ymm1, ymm1, 0x01
878     vperm2f128   ymm3, ymm3, ymm3, 0x01
879     vunpcklps    ymm6, ymm2, ymm1
880     vunpckhps    ymm4, ymm2, ymm1
881     vunpcklps    ymm7, ymm0, ymm3
882     vunpckhps    ymm5, ymm0, ymm3
883
884     vextractf128 [%3+%1*2],      ymm7, 0
885     vextractf128 [%3+%1*2+0x10], ymm5, 0
886     vextractf128 [%3+%1*2+0x20], ymm7, 1
887     vextractf128 [%3+%1*2+0x30], ymm5, 1
888
889     vextractf128 [%3+%2*2],      ymm6, 0
890     vextractf128 [%3+%2*2+0x10], ymm4, 0
891     vextractf128 [%3+%2*2+0x20], ymm6, 1
892     vextractf128 [%3+%2*2+0x30], ymm4, 1
893     sub      %2,   0x20
894     add      %1,   0x20
895     jl       .post
896 %endmacro
897
898 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
899 .post:
900     movaps   xmm1, [%3+%1*2]
901     movaps   xmm0, [%3+%1*2+0x10]
902     CMUL     %1,   xmm0, xmm1, %3, %4, %5
903     movaps   xmm5, [%3+%2*2]
904     movaps   xmm4, [%3+%2*2+0x10]
905     CMUL     %2,   xmm4, xmm5, %3, %4, %5
906     shufps   xmm1, xmm1, 0x1b
907     shufps   xmm5, xmm5, 0x1b
908     movaps   xmm6, xmm4
909     unpckhps xmm4, xmm1
910     unpcklps xmm6, xmm1
911     movaps   xmm2, xmm0
912     unpcklps xmm0, xmm5
913     unpckhps xmm2, xmm5
914     movaps   [%3+%2*2],      xmm6
915     movaps   [%3+%2*2+0x10], xmm4
916     movaps   [%3+%1*2],      xmm0
917     movaps   [%3+%1*2+0x10], xmm2
918     sub      %2,   0x10
919     add      %1,   0x10
920     jl       .post
921 %endmacro
922
923 %macro CMUL_3DNOW 6
924     mova       m6, [%1+%2*2]
925     mova       %3, [%1+%2*2+8]
926     mova       %4, m6
927     mova       m7, %3
928     pfmul      m6, [%5+%2]
929     pfmul      %3, [%6+%2]
930     pfmul      %4, [%6+%2]
931     pfmul      m7, [%5+%2]
932     pfsub      %3, m6
933     pfadd      %4, m7
934 %endmacro
935
936 %macro POSROTATESHUF_3DNOW 5 ;j, k, z+n8, tcos+n8, tsin+n8
937 .post:
938     CMUL_3DNOW %3, %1, m0, m1, %4, %5
939     CMUL_3DNOW %3, %2, m2, m3, %4, %5
940     movd  [%3+%1*2+ 0], m0
941     movd  [%3+%2*2+12], m1
942     movd  [%3+%2*2+ 0], m2
943     movd  [%3+%1*2+12], m3
944     psrlq      m0, 32
945     psrlq      m1, 32
946     psrlq      m2, 32
947     psrlq      m3, 32
948     movd  [%3+%1*2+ 8], m0
949     movd  [%3+%2*2+ 4], m1
950     movd  [%3+%2*2+ 8], m2
951     movd  [%3+%1*2+ 4], m3
952     sub        %2, 8
953     add        %1, 8
954     jl         .post
955 %endmacro
956
957 %macro DECL_IMDCT 1
958 cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *input
959 %if ARCH_X86_64
960 %define rrevtab r7
961 %define rtcos   r8
962 %define rtsin   r9
963 %else
964 %define rrevtab r6
965 %define rtsin   r6
966 %define rtcos   r5
967 %endif
968     mov   r3d, [r0+FFTContext.mdctsize]
969     add   r2, r3
970     shr   r3, 1
971     mov   rtcos, [r0+FFTContext.tcos]
972     mov   rtsin, [r0+FFTContext.tsin]
973     add   rtcos, r3
974     add   rtsin, r3
975 %if ARCH_X86_64 == 0
976     push  rtcos
977     push  rtsin
978 %endif
979     shr   r3, 1
980     mov   rrevtab, [r0+FFTContext.revtab]
981     add   rrevtab, r3
982 %if ARCH_X86_64 == 0
983     push  rrevtab
984 %endif
985
986 %if mmsize == 8
987     sub   r3, 2
988 %else
989     sub   r3, 4
990 %endif
991 %if ARCH_X86_64 || mmsize == 8
992     xor   r4, r4
993     sub   r4, r3
994 %endif
995 %if notcpuflag(3dnowext) && mmsize == 8
996     movd  m7, [ps_m1m1m1m1]
997 %endif
998 .pre:
999 %if ARCH_X86_64 == 0
1000 ;unspill
1001 %if mmsize != 8
1002     xor   r4, r4
1003     sub   r4, r3
1004 %endif
1005     mov   rtcos, [esp+8]
1006     mov   rtsin, [esp+4]
1007 %endif
1008
1009     PREROTATER r4, r3, r2, rtcos, rtsin
1010 %if mmsize == 8
1011     mov    r6, [esp]                ; rrevtab = ptr+n8
1012     movzx  r5,  word [rrevtab+r4-2] ; rrevtab[j]
1013     movzx  r6,  word [rrevtab+r3]   ; rrevtab[n4-j-1]
1014     mova [r1+r5*8], m0
1015     mova [r1+r6*8], m2
1016     add    r4, 2
1017     sub    r3, 2
1018 %else
1019 %if ARCH_X86_64
1020     movzx  r5,  word [rrevtab+r4-4]
1021     movzx  r6,  word [rrevtab+r4-2]
1022     movzx  r10, word [rrevtab+r3]
1023     movzx  r11, word [rrevtab+r3+2]
1024     movlps [r1+r5 *8], xmm0
1025     movhps [r1+r6 *8], xmm0
1026     movlps [r1+r10*8], xmm1
1027     movhps [r1+r11*8], xmm1
1028     add    r4, 4
1029 %else
1030     mov    r6, [esp]
1031     movzx  r5, word [r6+r4-4]
1032     movzx  r4, word [r6+r4-2]
1033     movlps [r1+r5*8], xmm0
1034     movhps [r1+r4*8], xmm0
1035     movzx  r5, word [r6+r3]
1036     movzx  r4, word [r6+r3+2]
1037     movlps [r1+r5*8], xmm1
1038     movhps [r1+r4*8], xmm1
1039 %endif
1040     sub    r3, 4
1041 %endif
1042     jns    .pre
1043
1044     mov  r5, r0
1045     mov  r6, r1
1046     mov  r0, r1
1047     mov  r1d, [r5+FFTContext.nbits]
1048
1049     FFT_DISPATCH SUFFIX, r1
1050
1051     mov  r0d, [r5+FFTContext.mdctsize]
1052     add  r6, r0
1053     shr  r0, 1
1054 %if ARCH_X86_64 == 0
1055 %define rtcos r2
1056 %define rtsin r3
1057     mov  rtcos, [esp+8]
1058     mov  rtsin, [esp+4]
1059 %endif
1060     neg  r0
1061     mov  r1, -mmsize
1062     sub  r1, r0
1063     %1 r0, r1, r6, rtcos, rtsin
1064 %if ARCH_X86_64 == 0
1065     add esp, 12
1066 %endif
1067 %if mmsize == 8
1068     femms
1069 %endif
1070     RET
1071 %endmacro
1072
1073 DECL_IMDCT POSROTATESHUF
1074
1075 %if ARCH_X86_32
1076 INIT_MMX 3dnow
1077 DECL_IMDCT POSROTATESHUF_3DNOW
1078
1079 INIT_MMX 3dnowext
1080 DECL_IMDCT POSROTATESHUF_3DNOW
1081 %endif
1082
1083 INIT_YMM avx
1084 DECL_IMDCT POSROTATESHUF_AVX
1085
1086 %endif ; CONFIG_MDCT