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