]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/fft.asm
indeo4: update AVCodecContext width/height on size change
[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 "x86inc.asm"
32 %include "x86util.asm"
33
34 %if ARCH_X86_64
35 %define pointer resq
36 %else
37 %define pointer resd
38 %endif
39
40 struc FFTContext
41     .nbits:    resd 1
42     .reverse:  resd 1
43     .revtab:   pointer 1
44     .tmpbuf:   pointer 1
45     .mdctsize: resd 1
46     .mdctbits: resd 1
47     .tcos:     pointer 1
48     .tsin:     pointer 1
49     .fftperm:  pointer 1
50     .fftcalc:  pointer 1
51     .imdctcalc:pointer 1
52     .imdcthalf:pointer 1
53 endstruc
54
55 SECTION_RODATA
56
57 %define M_SQRT1_2 0.70710678118654752440
58 %define M_COS_PI_1_8 0.923879532511287
59 %define M_COS_PI_3_8 0.38268343236509
60
61 align 32
62 ps_cos16_1: dd 1.0, M_COS_PI_1_8, M_SQRT1_2, M_COS_PI_3_8, 1.0, M_COS_PI_1_8, M_SQRT1_2, M_COS_PI_3_8
63 ps_cos16_2: dd 0, M_COS_PI_3_8, M_SQRT1_2, M_COS_PI_1_8, 0, -M_COS_PI_3_8, -M_SQRT1_2, -M_COS_PI_1_8
64
65 ps_root2: times 8 dd M_SQRT1_2
66 ps_root2mppm: dd -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2
67 ps_p1p1m1p1: dd 0, 0, 1<<31, 0, 0, 0, 1<<31, 0
68
69 perm1: dd 0x00, 0x02, 0x03, 0x01, 0x03, 0x00, 0x02, 0x01
70 perm2: dd 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x02, 0x03
71 ps_p1p1m1p1root2: dd 1.0, 1.0, -1.0, 1.0, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2
72 ps_m1m1p1m1p1m1m1m1: dd 1<<31, 1<<31, 0, 1<<31, 0, 1<<31, 1<<31, 1<<31
73 ps_m1m1m1m1: times 4 dd 1<<31
74 ps_m1p1: dd 1<<31, 0
75
76 %assign i 16
77 %rep 13
78 cextern cos_ %+ i
79 %assign i i<<1
80 %endrep
81
82 %if ARCH_X86_64
83     %define pointer dq
84 %else
85     %define pointer dd
86 %endif
87
88 %macro IF0 1+
89 %endmacro
90 %macro IF1 1+
91     %1
92 %endmacro
93
94 SECTION_TEXT
95
96 %macro T2_3DNOW 4 ; z0, z1, mem0, mem1
97     mova     %1, %3
98     mova     %2, %1
99     pfadd    %1, %4
100     pfsub    %2, %4
101 %endmacro
102
103 %macro T4_3DNOW 6 ; z0, z1, z2, z3, tmp0, tmp1
104     mova     %5, %3
105     pfsub    %3, %4
106     pfadd    %5, %4 ; {t6,t5}
107     pxor     %3, [ps_m1p1] ; {t8,t7}
108     mova     %6, %1
109     PSWAPD   %3, %3
110     pfadd    %1, %5 ; {r0,i0}
111     pfsub    %6, %5 ; {r2,i2}
112     mova     %4, %2
113     pfadd    %2, %3 ; {r1,i1}
114     pfsub    %4, %3 ; {r3,i3}
115     SWAP     %3, %6
116 %endmacro
117
118 ;  in: %1 = {r0,i0,r2,i2,r4,i4,r6,i6}
119 ;      %2 = {r1,i1,r3,i3,r5,i5,r7,i7}
120 ;      %3, %4, %5 tmp
121 ; out: %1 = {r0,r1,r2,r3,i0,i1,i2,i3}
122 ;      %2 = {r4,r5,r6,r7,i4,i5,i6,i7}
123 %macro T8_AVX 5
124     vsubps     %5, %1, %2       ; v  = %1 - %2
125     vaddps     %3, %1, %2       ; w  = %1 + %2
126     vmulps     %2, %5, [ps_p1p1m1p1root2]  ; v *= vals1
127     vpermilps  %2, %2, [perm1]
128     vblendps   %1, %2, %3, 0x33 ; q = {w1,w2,v4,v2,w5,w6,v7,v6}
129     vshufps    %5, %3, %2, 0x4e ; r = {w3,w4,v1,v3,w7,w8,v8,v5}
130     vsubps     %4, %5, %1       ; s = r - q
131     vaddps     %1, %5, %1       ; u = r + q
132     vpermilps  %1, %1, [perm2]  ; k  = {u1,u2,u3,u4,u6,u5,u7,u8}
133     vshufps    %5, %4, %1, 0xbb
134     vshufps    %3, %4, %1, 0xee
135     vperm2f128 %3, %3, %5, 0x13
136     vxorps     %4, %4, [ps_m1m1p1m1p1m1m1m1]  ; s *= {1,1,-1,-1,1,-1,-1,-1}
137     vshufps    %2, %1, %4, 0xdd
138     vshufps    %1, %1, %4, 0x88
139     vperm2f128 %4, %2, %1, 0x02 ; v  = {k1,k3,s1,s3,k2,k4,s2,s4}
140     vperm2f128 %1, %1, %2, 0x13 ; w  = {k6,k8,s6,s8,k5,k7,s5,s7}
141     vsubps     %5, %1, %3
142     vblendps   %1, %5, %1, 0x55 ; w -= {0,s7,0,k7,0,s8,0,k8}
143     vsubps     %2, %4, %1       ; %2 = v - w
144     vaddps     %1, %4, %1       ; %1 = v + w
145 %endmacro
146
147 ; In SSE mode do one fft4 transforms
148 ; in:  %1={r0,i0,r2,i2} %2={r1,i1,r3,i3}
149 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3}
150 ;
151 ; In AVX mode do two fft4 transforms
152 ; in:  %1={r0,i0,r2,i2,r4,i4,r6,i6} %2={r1,i1,r3,i3,r5,i5,r7,i7}
153 ; out: %1={r0,r1,r2,r3,r4,r5,r6,r7} %2={i0,i1,i2,i3,i4,i5,i6,i7}
154 %macro T4_SSE 3
155     subps    %3, %1, %2       ; {t3,t4,-t8,t7}
156     addps    %1, %1, %2       ; {t1,t2,t6,t5}
157     xorps    %3, %3, [ps_p1p1m1p1]
158     shufps   %2, %1, %3, 0xbe ; {t6,t5,t7,t8}
159     shufps   %1, %1, %3, 0x44 ; {t1,t2,t3,t4}
160     subps    %3, %1, %2       ; {r2,i2,r3,i3}
161     addps    %1, %1, %2       ; {r0,i0,r1,i1}
162     shufps   %2, %1, %3, 0xdd ; {i0,i1,i2,i3}
163     shufps   %1, %1, %3, 0x88 ; {r0,r1,r2,r3}
164 %endmacro
165
166 ; In SSE mode do one FFT8
167 ; in:  %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %3={r4,i4,r6,i6} %4={r5,i5,r7,i7}
168 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %1={r4,r5,r6,r7} %2={i4,i5,i6,i7}
169 ;
170 ; In AVX mode do two FFT8
171 ; in:  %1={r0,i0,r2,i2,r8, i8, r10,i10} %2={r1,i1,r3,i3,r9, i9, r11,i11}
172 ;      %3={r4,i4,r6,i6,r12,i12,r14,i14} %4={r5,i5,r7,i7,r13,i13,r15,i15}
173 ; out: %1={r0,r1,r2,r3,r8, r9, r10,r11} %2={i0,i1,i2,i3,i8, i9, i10,i11}
174 ;      %3={r4,r5,r6,r7,r12,r13,r14,r15} %4={i4,i5,i6,i7,i12,i13,i14,i15}
175 %macro T8_SSE 6
176     addps    %6, %3, %4       ; {t1,t2,t3,t4}
177     subps    %3, %3, %4       ; {r5,i5,r7,i7}
178     shufps   %4, %3, %3, 0xb1 ; {i5,r5,i7,r7}
179     mulps    %3, %3, [ps_root2mppm] ; {-r5,i5,r7,-i7}
180     mulps    %4, %4, [ps_root2]
181     addps    %3, %3, %4       ; {t8,t7,ta,t9}
182     shufps   %4, %6, %3, 0x9c ; {t1,t4,t7,ta}
183     shufps   %6, %6, %3, 0x36 ; {t3,t2,t9,t8}
184     subps    %3, %6, %4       ; {t6,t5,tc,tb}
185     addps    %6, %6, %4       ; {t1,t2,t9,ta}
186     shufps   %5, %6, %3, 0x8d ; {t2,ta,t6,tc}
187     shufps   %6, %6, %3, 0xd8 ; {t1,t9,t5,tb}
188     subps    %3, %1, %6       ; {r4,r5,r6,r7}
189     addps    %1, %1, %6       ; {r0,r1,r2,r3}
190     subps    %4, %2, %5       ; {i4,i5,i6,i7}
191     addps    %2, %2, %5       ; {i0,i1,i2,i3}
192 %endmacro
193
194 ; scheduled for cpu-bound sizes
195 %macro PASS_SMALL 3 ; (to load m4-m7), wre, wim
196 IF%1 mova    m4, Z(4)
197 IF%1 mova    m5, Z(5)
198     mova     m0, %2 ; wre
199     mova     m1, %3 ; wim
200     mulps    m2, m4, m0 ; r2*wre
201 IF%1 mova    m6, Z2(6)
202     mulps    m3, m5, m1 ; i2*wim
203 IF%1 mova    m7, Z2(7)
204     mulps    m4, m4, m1 ; r2*wim
205     mulps    m5, m5, m0 ; i2*wre
206     addps    m2, m2, m3 ; r2*wre + i2*wim
207     mulps    m3, m1, m7 ; i3*wim
208     subps    m5, m5, m4 ; i2*wre - r2*wim
209     mulps    m1, m1, m6 ; r3*wim
210     mulps    m4, m0, m6 ; r3*wre
211     mulps    m0, m0, m7 ; i3*wre
212     subps    m4, m4, m3 ; r3*wre - i3*wim
213     mova     m3, Z(0)
214     addps    m0, m0, m1 ; i3*wre + r3*wim
215     subps    m1, m4, m2 ; t3
216     addps    m4, m4, m2 ; t5
217     subps    m3, m3, m4 ; r2
218     addps    m4, m4, Z(0) ; r0
219     mova     m6, Z(2)
220     mova   Z(4), m3
221     mova   Z(0), m4
222     subps    m3, m5, m0 ; t4
223     subps    m4, m6, m3 ; r3
224     addps    m3, m3, m6 ; r1
225     mova  Z2(6), m4
226     mova   Z(2), m3
227     mova     m2, Z(3)
228     addps    m3, m5, m0 ; t6
229     subps    m2, m2, m1 ; i3
230     mova     m7, Z(1)
231     addps    m1, m1, Z(3) ; i1
232     mova  Z2(7), m2
233     mova   Z(3), m1
234     subps    m4, m7, m3 ; i2
235     addps    m3, m3, m7 ; i0
236     mova   Z(5), m4
237     mova   Z(1), m3
238 %endmacro
239
240 ; scheduled to avoid store->load aliasing
241 %macro PASS_BIG 1 ; (!interleave)
242     mova     m4, Z(4) ; r2
243     mova     m5, Z(5) ; i2
244     mova     m0, [wq] ; wre
245     mova     m1, [wq+o1q] ; wim
246     mulps    m2, m4, m0 ; r2*wre
247     mova     m6, Z2(6) ; r3
248     mulps    m3, m5, m1 ; i2*wim
249     mova     m7, Z2(7) ; i3
250     mulps    m4, m4, m1 ; r2*wim
251     mulps    m5, m5, m0 ; i2*wre
252     addps    m2, m2, m3 ; r2*wre + i2*wim
253     mulps    m3, m1, m7 ; i3*wim
254     mulps    m1, m1, m6 ; r3*wim
255     subps    m5, m5, m4 ; i2*wre - r2*wim
256     mulps    m4, m0, m6 ; r3*wre
257     mulps    m0, m0, m7 ; i3*wre
258     subps    m4, m4, m3 ; r3*wre - i3*wim
259     mova     m3, Z(0)
260     addps    m0, m0, m1 ; i3*wre + r3*wim
261     subps    m1, m4, m2 ; t3
262     addps    m4, m4, m2 ; t5
263     subps    m3, m3, m4 ; r2
264     addps    m4, m4, Z(0) ; r0
265     mova     m6, Z(2)
266     mova   Z(4), m3
267     mova   Z(0), m4
268     subps    m3, m5, m0 ; t4
269     subps    m4, m6, m3 ; r3
270     addps    m3, m3, m6 ; r1
271 IF%1 mova Z2(6), m4
272 IF%1 mova  Z(2), m3
273     mova     m2, Z(3)
274     addps    m5, m5, m0 ; t6
275     subps    m2, m2, m1 ; i3
276     mova     m7, Z(1)
277     addps    m1, m1, Z(3) ; i1
278 IF%1 mova Z2(7), m2
279 IF%1 mova  Z(3), m1
280     subps    m6, m7, m5 ; i2
281     addps    m5, m5, m7 ; i0
282 IF%1 mova  Z(5), m6
283 IF%1 mova  Z(1), m5
284 %if %1==0
285     INTERL m1, m3, m7, Z, 2
286     INTERL m2, m4, m0, Z2, 6
287
288     mova     m1, Z(0)
289     mova     m2, Z(4)
290
291     INTERL m5, m1, m3, Z, 0
292     INTERL m6, m2, m7, Z, 4
293 %endif
294 %endmacro
295
296 %macro PUNPCK 3
297     mova      %3, %1
298     punpckldq %1, %2
299     punpckhdq %3, %2
300 %endmacro
301
302 %define Z(x) [r0+mmsize*x]
303 %define Z2(x) [r0+mmsize*x]
304 %define ZH(x) [r0+mmsize*x+mmsize/2]
305
306 INIT_YMM avx
307
308 %if HAVE_AVX_EXTERNAL
309 align 16
310 fft8_avx:
311     mova      m0, Z(0)
312     mova      m1, Z(1)
313     T8_AVX    m0, m1, m2, m3, m4
314     mova      Z(0), m0
315     mova      Z(1), m1
316     ret
317
318
319 align 16
320 fft16_avx:
321     mova       m2, Z(2)
322     mova       m3, Z(3)
323     T4_SSE     m2, m3, m7
324
325     mova       m0, Z(0)
326     mova       m1, Z(1)
327     T8_AVX     m0, m1, m4, m5, m7
328
329     mova       m4, [ps_cos16_1]
330     mova       m5, [ps_cos16_2]
331     vmulps     m6, m2, m4
332     vmulps     m7, m3, m5
333     vaddps     m7, m7, m6
334     vmulps     m2, m2, m5
335     vmulps     m3, m3, m4
336     vsubps     m3, m3, m2
337     vblendps   m2, m7, m3, 0xf0
338     vperm2f128 m3, m7, m3, 0x21
339     vaddps     m4, m2, m3
340     vsubps     m2, m3, m2
341     vperm2f128 m2, m2, m2, 0x01
342     vsubps     m3, m1, m2
343     vaddps     m1, m1, m2
344     vsubps     m5, m0, m4
345     vaddps     m0, m0, m4
346     vextractf128   Z(0), m0, 0
347     vextractf128  ZH(0), m1, 0
348     vextractf128   Z(1), m0, 1
349     vextractf128  ZH(1), m1, 1
350     vextractf128   Z(2), m5, 0
351     vextractf128  ZH(2), m3, 0
352     vextractf128   Z(3), m5, 1
353     vextractf128  ZH(3), m3, 1
354     ret
355
356 align 16
357 fft32_avx:
358     call fft16_avx
359
360     mova m0, Z(4)
361     mova m1, Z(5)
362
363     T4_SSE      m0, m1, m4
364
365     mova m2, Z(6)
366     mova m3, Z(7)
367
368     T8_SSE      m0, m1, m2, m3, m4, m6
369     ; m0={r0,r1,r2,r3,r8, r9, r10,r11} m1={i0,i1,i2,i3,i8, i9, i10,i11}
370     ; m2={r4,r5,r6,r7,r12,r13,r14,r15} m3={i4,i5,i6,i7,i12,i13,i14,i15}
371
372     vperm2f128  m4, m0, m2, 0x20
373     vperm2f128  m5, m1, m3, 0x20
374     vperm2f128  m6, m0, m2, 0x31
375     vperm2f128  m7, m1, m3, 0x31
376
377     PASS_SMALL 0, [cos_32], [cos_32+32]
378
379     ret
380
381 fft32_interleave_avx:
382     call fft32_avx
383     mov r2d, 32
384 .deint_loop:
385     mova     m2, Z(0)
386     mova     m3, Z(1)
387     vunpcklps      m0, m2, m3
388     vunpckhps      m1, m2, m3
389     vextractf128   Z(0), m0, 0
390     vextractf128  ZH(0), m1, 0
391     vextractf128   Z(1), m0, 1
392     vextractf128  ZH(1), m1, 1
393     add r0, mmsize*2
394     sub r2d, mmsize/4
395     jg .deint_loop
396     ret
397 %endif
398
399 INIT_XMM sse
400
401 align 16
402 fft4_avx:
403 fft4_sse:
404     mova     m0, Z(0)
405     mova     m1, Z(1)
406     T4_SSE   m0, m1, m2
407     mova   Z(0), m0
408     mova   Z(1), m1
409     ret
410
411 align 16
412 fft8_sse:
413     mova     m0, Z(0)
414     mova     m1, Z(1)
415     T4_SSE   m0, m1, m2
416     mova     m2, Z(2)
417     mova     m3, Z(3)
418     T8_SSE   m0, m1, m2, m3, m4, m5
419     mova   Z(0), m0
420     mova   Z(1), m1
421     mova   Z(2), m2
422     mova   Z(3), m3
423     ret
424
425 align 16
426 fft16_sse:
427     mova     m0, Z(0)
428     mova     m1, Z(1)
429     T4_SSE   m0, m1, m2
430     mova     m2, Z(2)
431     mova     m3, Z(3)
432     T8_SSE   m0, m1, m2, m3, m4, m5
433     mova     m4, Z(4)
434     mova     m5, Z(5)
435     mova   Z(0), m0
436     mova   Z(1), m1
437     mova   Z(2), m2
438     mova   Z(3), m3
439     T4_SSE   m4, m5, m6
440     mova     m6, Z2(6)
441     mova     m7, Z2(7)
442     T4_SSE   m6, m7, m0
443     PASS_SMALL 0, [cos_16], [cos_16+16]
444     ret
445
446
447 %macro FFT48_3DNOW 0
448 align 16
449 fft4 %+ SUFFIX:
450     T2_3DNOW m0, m1, Z(0), Z(1)
451     mova     m2, Z(2)
452     mova     m3, Z(3)
453     T4_3DNOW m0, m1, m2, m3, m4, m5
454     PUNPCK   m0, m1, m4
455     PUNPCK   m2, m3, m5
456     mova   Z(0), m0
457     mova   Z(1), m4
458     mova   Z(2), m2
459     mova   Z(3), m5
460     ret
461
462 align 16
463 fft8 %+ SUFFIX:
464     T2_3DNOW m0, m1, Z(0), Z(1)
465     mova     m2, Z(2)
466     mova     m3, Z(3)
467     T4_3DNOW m0, m1, m2, m3, m4, m5
468     mova   Z(0), m0
469     mova   Z(2), m2
470     T2_3DNOW m4, m5,  Z(4),  Z(5)
471     T2_3DNOW m6, m7, Z2(6), Z2(7)
472     PSWAPD   m0, m5
473     PSWAPD   m2, m7
474     pxor     m0, [ps_m1p1]
475     pxor     m2, [ps_m1p1]
476     pfsub    m5, m0
477     pfadd    m7, m2
478     pfmul    m5, [ps_root2]
479     pfmul    m7, [ps_root2]
480     T4_3DNOW m1, m3, m5, m7, m0, m2
481     mova   Z(5), m5
482     mova  Z2(7), m7
483     mova     m0, Z(0)
484     mova     m2, Z(2)
485     T4_3DNOW m0, m2, m4, m6, m5, m7
486     PUNPCK   m0, m1, m5
487     PUNPCK   m2, m3, m7
488     mova   Z(0), m0
489     mova   Z(1), m5
490     mova   Z(2), m2
491     mova   Z(3), m7
492     PUNPCK   m4,  Z(5), m5
493     PUNPCK   m6, Z2(7), m7
494     mova   Z(4), m4
495     mova   Z(5), m5
496     mova  Z2(6), m6
497     mova  Z2(7), m7
498     ret
499 %endmacro
500
501 %if ARCH_X86_32
502 %macro PSWAPD 2
503 %if cpuflag(3dnowext)
504     pswapd %1, %2
505 %elifidn %1, %2
506     movd [r0+12], %1
507     punpckhdq %1, [r0+8]
508 %else
509     movq  %1, %2
510     psrlq %1, 32
511     punpckldq %1, %2
512 %endif
513 %endmacro
514
515 INIT_MMX 3dnowext
516 FFT48_3DNOW
517
518 INIT_MMX 3dnow
519 FFT48_3DNOW
520 %endif
521
522 %define Z(x) [zcq + o1q*(x&6) + mmsize*(x&1)]
523 %define Z2(x) [zcq + o3q + mmsize*(x&1)]
524 %define ZH(x) [zcq + o1q*(x&6) + mmsize*(x&1) + mmsize/2]
525 %define Z2H(x) [zcq + o3q + mmsize*(x&1) + mmsize/2]
526
527 %macro DECL_PASS 2+ ; name, payload
528 align 16
529 %1:
530 DEFINE_ARGS zc, w, n, o1, o3
531     lea o3q, [nq*3]
532     lea o1q, [nq*8]
533     shl o3q, 4
534 .loop:
535     %2
536     add zcq, mmsize*2
537     add  wq, mmsize
538     sub  nd, mmsize/8
539     jg .loop
540     rep ret
541 %endmacro
542
543 %macro FFT_DISPATCH 2; clobbers 5 GPRs, 8 XMMs
544     lea r2, [dispatch_tab%1]
545     mov r2, [r2 + (%2q-2)*gprsize]
546 %ifdef PIC
547     lea r3, [$$]
548     add r2, r3
549 %endif
550     call r2
551 %endmacro ; FFT_DISPATCH
552
553 INIT_YMM avx
554
555 %if HAVE_AVX_EXTERNAL
556 %macro INTERL_AVX 5
557     vunpckhps      %3, %2, %1
558     vunpcklps      %2, %2, %1
559     vextractf128   %4(%5), %2, 0
560     vextractf128  %4 %+ H(%5), %3, 0
561     vextractf128   %4(%5 + 1), %2, 1
562     vextractf128  %4 %+ H(%5 + 1), %3, 1
563 %endmacro
564
565 %define INTERL INTERL_AVX
566
567 DECL_PASS pass_avx, PASS_BIG 1
568 DECL_PASS pass_interleave_avx, PASS_BIG 0
569
570 cglobal fft_calc, 2,5,8
571     mov     r3d, [r0 + FFTContext.nbits]
572     mov     r0, r1
573     mov     r1, r3
574     FFT_DISPATCH _interleave %+ SUFFIX, r1
575     REP_RET
576
577 %endif
578
579 INIT_XMM sse
580
581 %macro INTERL_SSE 5
582     mova     %3, %2
583     unpcklps %2, %1
584     unpckhps %3, %1
585     mova  %4(%5), %2
586     mova  %4(%5+1), %3
587 %endmacro
588
589 %define INTERL INTERL_SSE
590
591 DECL_PASS pass_sse, PASS_BIG 1
592 DECL_PASS pass_interleave_sse, PASS_BIG 0
593
594 %macro FFT_CALC_FUNC 0
595 cglobal fft_calc, 2,5,8
596     mov     r3d, [r0 + FFTContext.nbits]
597     PUSH    r1
598     PUSH    r3
599     mov     r0, r1
600     mov     r1, r3
601     FFT_DISPATCH _interleave %+ SUFFIX, r1
602     POP     rcx
603     POP     r4
604     cmp     rcx, 3+(mmsize/16)
605     jg      .end
606     mov     r2, -1
607     add     rcx, 3
608     shl     r2, cl
609     sub     r4, r2
610 .loop:
611 %if mmsize == 8
612     PSWAPD  m0, [r4 + r2 + 4]
613     mova [r4 + r2 + 4], m0
614 %else
615     movaps   xmm0, [r4 + r2]
616     movaps   xmm1, xmm0
617     unpcklps xmm0, [r4 + r2 + 16]
618     unpckhps xmm1, [r4 + r2 + 16]
619     movaps   [r4 + r2],      xmm0
620     movaps   [r4 + r2 + 16], xmm1
621 %endif
622     add      r2, mmsize*2
623     jl       .loop
624 .end:
625 %if cpuflag(3dnow)
626     femms
627     RET
628 %else
629     REP_RET
630 %endif
631 %endmacro
632
633 %if ARCH_X86_32
634 INIT_MMX 3dnow
635 FFT_CALC_FUNC
636 INIT_MMX 3dnowext
637 FFT_CALC_FUNC
638 %endif
639 INIT_XMM sse
640 FFT_CALC_FUNC
641
642 cglobal fft_permute, 2,7,1
643     mov     r4,  [r0 + FFTContext.revtab]
644     mov     r5,  [r0 + FFTContext.tmpbuf]
645     mov     ecx, [r0 + FFTContext.nbits]
646     mov     r2, 1
647     shl     r2, cl
648     xor     r0, r0
649 %if ARCH_X86_32
650     mov     r1, r1m
651 %endif
652 .loop:
653     movaps  xmm0, [r1 + 8*r0]
654     movzx   r6, word [r4 + 2*r0]
655     movzx   r3, word [r4 + 2*r0 + 2]
656     movlps  [r5 + 8*r6], xmm0
657     movhps  [r5 + 8*r3], xmm0
658     add     r0, 2
659     cmp     r0, r2
660     jl      .loop
661     shl     r2, 3
662     add     r1, r2
663     add     r5, r2
664     neg     r2
665 ; nbits >= 2 (FFT4) and sizeof(FFTComplex)=8 => at least 32B
666 .loopcopy:
667     movaps  xmm0, [r5 + r2]
668     movaps  xmm1, [r5 + r2 + 16]
669     movaps  [r1 + r2], xmm0
670     movaps  [r1 + r2 + 16], xmm1
671     add     r2, 32
672     jl      .loopcopy
673     REP_RET
674
675 %macro IMDCT_CALC_FUNC 0
676 cglobal imdct_calc, 3,5,3
677     mov     r3d, [r0 + FFTContext.mdctsize]
678     mov     r4,  [r0 + FFTContext.imdcthalf]
679     add     r1,  r3
680     PUSH    r3
681     PUSH    r1
682 %if ARCH_X86_32
683     push    r2
684     push    r1
685     push    r0
686 %else
687     sub     rsp, 8
688 %endif
689     call    r4
690 %if ARCH_X86_32
691     add     esp, 12
692 %else
693     add     rsp, 8
694 %endif
695     POP     r1
696     POP     r3
697     lea     r0, [r1 + 2*r3]
698     mov     r2, r3
699     sub     r3, mmsize
700     neg     r2
701     mova    m2, [ps_m1m1m1m1]
702 .loop:
703 %if mmsize == 8
704     PSWAPD  m0, [r1 + r3]
705     PSWAPD  m1, [r0 + r2]
706     pxor    m0, m2
707 %else
708     mova    m0, [r1 + r3]
709     mova    m1, [r0 + r2]
710     shufps  m0, m0, 0x1b
711     shufps  m1, m1, 0x1b
712     xorps   m0, m2
713 %endif
714     mova [r0 + r3], m1
715     mova [r1 + r2], m0
716     sub     r3, mmsize
717     add     r2, mmsize
718     jl      .loop
719 %if cpuflag(3dnow)
720     femms
721     RET
722 %else
723     REP_RET
724 %endif
725 %endmacro
726
727 %if ARCH_X86_32
728 INIT_MMX 3dnow
729 IMDCT_CALC_FUNC
730 INIT_MMX 3dnowext
731 IMDCT_CALC_FUNC
732 %endif
733
734 INIT_XMM sse
735 IMDCT_CALC_FUNC
736
737 %if ARCH_X86_32
738 INIT_MMX 3dnow
739 %define mulps pfmul
740 %define addps pfadd
741 %define subps pfsub
742 %define unpcklps punpckldq
743 %define unpckhps punpckhdq
744 DECL_PASS pass_3dnow, PASS_SMALL 1, [wq], [wq+o1q]
745 DECL_PASS pass_interleave_3dnow, PASS_BIG 0
746 %define pass_3dnowext pass_3dnow
747 %define pass_interleave_3dnowext pass_interleave_3dnow
748 %endif
749
750 %ifdef PIC
751 %define SECTION_REL - $$
752 %else
753 %define SECTION_REL
754 %endif
755
756 %macro DECL_FFT 1-2 ; nbits, suffix
757 %ifidn %0, 1
758 %xdefine fullsuffix SUFFIX
759 %else
760 %xdefine fullsuffix %2 %+ SUFFIX
761 %endif
762 %xdefine list_of_fft fft4 %+ SUFFIX SECTION_REL, fft8 %+ SUFFIX SECTION_REL
763 %if %1>=5
764 %xdefine list_of_fft list_of_fft, fft16 %+ SUFFIX SECTION_REL
765 %endif
766 %if %1>=6
767 %xdefine list_of_fft list_of_fft, fft32 %+ fullsuffix SECTION_REL
768 %endif
769
770 %assign n 1<<%1
771 %rep 17-%1
772 %assign n2 n/2
773 %assign n4 n/4
774 %xdefine list_of_fft list_of_fft, fft %+ n %+ fullsuffix SECTION_REL
775
776 align 16
777 fft %+ n %+ fullsuffix:
778     call fft %+ n2 %+ SUFFIX
779     add r0, n*4 - (n&(-2<<%1))
780     call fft %+ n4 %+ SUFFIX
781     add r0, n*2 - (n2&(-2<<%1))
782     call fft %+ n4 %+ SUFFIX
783     sub r0, n*6 + (n2&(-2<<%1))
784     lea r1, [cos_ %+ n]
785     mov r2d, n4/2
786     jmp pass %+ fullsuffix
787
788 %assign n n*2
789 %endrep
790 %undef n
791
792 align 8
793 dispatch_tab %+ fullsuffix: pointer list_of_fft
794 %endmacro ; DECL_FFT
795
796 %if HAVE_AVX_EXTERNAL
797 INIT_YMM avx
798 DECL_FFT 6
799 DECL_FFT 6, _interleave
800 %endif
801 INIT_XMM sse
802 DECL_FFT 5
803 DECL_FFT 5, _interleave
804 %if ARCH_X86_32
805 INIT_MMX 3dnow
806 DECL_FFT 4
807 DECL_FFT 4, _interleave
808 INIT_MMX 3dnowext
809 DECL_FFT 4
810 DECL_FFT 4, _interleave
811 %endif
812
813 INIT_XMM sse
814 %undef mulps
815 %undef addps
816 %undef subps
817 %undef unpcklps
818 %undef unpckhps
819
820 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
821 %if mmsize == 8 ; j*2+2-n4, n4-2-j*2, input+n4, tcos+n8, tsin+n8
822     PSWAPD     m0, [%3+%2*4]
823     movq       m2, [%3+%1*4-8]
824     movq       m3, m0
825     punpckldq  m0, m2
826     punpckhdq  m2, m3
827     movd       m1, [%4+%1*2-4] ; tcos[j]
828     movd       m3, [%4+%2*2]   ; tcos[n4-j-1]
829     punpckldq  m1, [%5+%1*2-4] ; tsin[j]
830     punpckldq  m3, [%5+%2*2]   ; tsin[n4-j-1]
831
832     mova       m4, m0
833     PSWAPD     m5, m1
834     pfmul      m0, m1
835     pfmul      m4, m5
836     mova       m6, m2
837     PSWAPD     m5, m3
838     pfmul      m2, m3
839     pfmul      m6, m5
840 %if cpuflag(3dnowext)
841     pfpnacc    m0, m4
842     pfpnacc    m2, m6
843 %else
844     SBUTTERFLY dq, 0, 4, 1
845     SBUTTERFLY dq, 2, 6, 3
846     pxor       m4, m7
847     pxor       m6, m7
848     pfadd      m0, m4
849     pfadd      m2, m6
850 %endif
851 %else
852     movaps   xmm0, [%3+%2*4]
853     movaps   xmm1, [%3+%1*4-0x10]
854     movaps   xmm2, xmm0
855     shufps   xmm0, xmm1, 0x88
856     shufps   xmm1, xmm2, 0x77
857     movlps   xmm4, [%4+%2*2]
858     movlps   xmm5, [%5+%2*2+0x0]
859     movhps   xmm4, [%4+%1*2-0x8]
860     movhps   xmm5, [%5+%1*2-0x8]
861     movaps   xmm2, xmm0
862     movaps   xmm3, xmm1
863     mulps    xmm0, xmm5
864     mulps    xmm1, xmm4
865     mulps    xmm2, xmm4
866     mulps    xmm3, xmm5
867     subps    xmm1, xmm0
868     addps    xmm2, xmm3
869     movaps   xmm0, xmm1
870     unpcklps xmm1, xmm2
871     unpckhps xmm0, xmm2
872 %endif
873 %endmacro
874
875 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
876     mulps      m6, %3, [%5+%1]
877     mulps      m7, %2, [%5+%1]
878     mulps      %2, %2, [%6+%1]
879     mulps      %3, %3, [%6+%1]
880     subps      %2, %2, m6
881     addps      %3, %3, m7
882 %endmacro
883
884 %macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8
885 .post:
886     vmovaps      ymm1,   [%3+%1*2]
887     vmovaps      ymm0,   [%3+%1*2+0x20]
888     vmovaps      ymm3,   [%3+%2*2]
889     vmovaps      ymm2,   [%3+%2*2+0x20]
890
891     CMUL         %1, ymm0, ymm1, %3, %4, %5
892     CMUL         %2, ymm2, ymm3, %3, %4, %5
893     vshufps      ymm1, ymm1, ymm1, 0x1b
894     vshufps      ymm3, ymm3, ymm3, 0x1b
895     vperm2f128   ymm1, ymm1, ymm1, 0x01
896     vperm2f128   ymm3, ymm3, ymm3, 0x01
897     vunpcklps    ymm6, ymm2, ymm1
898     vunpckhps    ymm4, ymm2, ymm1
899     vunpcklps    ymm7, ymm0, ymm3
900     vunpckhps    ymm5, ymm0, ymm3
901
902     vextractf128 [%3+%1*2],      ymm7, 0
903     vextractf128 [%3+%1*2+0x10], ymm5, 0
904     vextractf128 [%3+%1*2+0x20], ymm7, 1
905     vextractf128 [%3+%1*2+0x30], ymm5, 1
906
907     vextractf128 [%3+%2*2],      ymm6, 0
908     vextractf128 [%3+%2*2+0x10], ymm4, 0
909     vextractf128 [%3+%2*2+0x20], ymm6, 1
910     vextractf128 [%3+%2*2+0x30], ymm4, 1
911     sub      %2,   0x20
912     add      %1,   0x20
913     jl       .post
914 %endmacro
915
916 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
917 .post:
918     movaps   xmm1, [%3+%1*2]
919     movaps   xmm0, [%3+%1*2+0x10]
920     CMUL     %1,   xmm0, xmm1, %3, %4, %5
921     movaps   xmm5, [%3+%2*2]
922     movaps   xmm4, [%3+%2*2+0x10]
923     CMUL     %2,   xmm4, xmm5, %3, %4, %5
924     shufps   xmm1, xmm1, 0x1b
925     shufps   xmm5, xmm5, 0x1b
926     movaps   xmm6, xmm4
927     unpckhps xmm4, xmm1
928     unpcklps xmm6, xmm1
929     movaps   xmm2, xmm0
930     unpcklps xmm0, xmm5
931     unpckhps xmm2, xmm5
932     movaps   [%3+%2*2],      xmm6
933     movaps   [%3+%2*2+0x10], xmm4
934     movaps   [%3+%1*2],      xmm0
935     movaps   [%3+%1*2+0x10], xmm2
936     sub      %2,   0x10
937     add      %1,   0x10
938     jl       .post
939 %endmacro
940
941 %macro CMUL_3DNOW 6
942     mova       m6, [%1+%2*2]
943     mova       %3, [%1+%2*2+8]
944     mova       %4, m6
945     mova       m7, %3
946     pfmul      m6, [%5+%2]
947     pfmul      %3, [%6+%2]
948     pfmul      %4, [%6+%2]
949     pfmul      m7, [%5+%2]
950     pfsub      %3, m6
951     pfadd      %4, m7
952 %endmacro
953
954 %macro POSROTATESHUF_3DNOW 5 ;j, k, z+n8, tcos+n8, tsin+n8
955 .post:
956     CMUL_3DNOW %3, %1, m0, m1, %4, %5
957     CMUL_3DNOW %3, %2, m2, m3, %4, %5
958     movd  [%3+%1*2+ 0], m0
959     movd  [%3+%2*2+12], m1
960     movd  [%3+%2*2+ 0], m2
961     movd  [%3+%1*2+12], m3
962     psrlq      m0, 32
963     psrlq      m1, 32
964     psrlq      m2, 32
965     psrlq      m3, 32
966     movd  [%3+%1*2+ 8], m0
967     movd  [%3+%2*2+ 4], m1
968     movd  [%3+%2*2+ 8], m2
969     movd  [%3+%1*2+ 4], m3
970     sub        %2, 8
971     add        %1, 8
972     jl         .post
973 %endmacro
974
975 %macro DECL_IMDCT 1
976 cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *input
977 %if ARCH_X86_64
978 %define rrevtab r7
979 %define rtcos   r8
980 %define rtsin   r9
981 %else
982 %define rrevtab r6
983 %define rtsin   r6
984 %define rtcos   r5
985 %endif
986     mov   r3d, [r0+FFTContext.mdctsize]
987     add   r2, r3
988     shr   r3, 1
989     mov   rtcos, [r0+FFTContext.tcos]
990     mov   rtsin, [r0+FFTContext.tsin]
991     add   rtcos, r3
992     add   rtsin, r3
993 %if ARCH_X86_64 == 0
994     push  rtcos
995     push  rtsin
996 %endif
997     shr   r3, 1
998     mov   rrevtab, [r0+FFTContext.revtab]
999     add   rrevtab, r3
1000 %if ARCH_X86_64 == 0
1001     push  rrevtab
1002 %endif
1003
1004 %if mmsize == 8
1005     sub   r3, 2
1006 %else
1007     sub   r3, 4
1008 %endif
1009 %if ARCH_X86_64 || mmsize == 8
1010     xor   r4, r4
1011     sub   r4, r3
1012 %endif
1013 %if notcpuflag(3dnowext) && mmsize == 8
1014     movd  m7, [ps_m1m1m1m1]
1015 %endif
1016 .pre:
1017 %if ARCH_X86_64 == 0
1018 ;unspill
1019 %if mmsize != 8
1020     xor   r4, r4
1021     sub   r4, r3
1022 %endif
1023     mov   rtcos, [esp+8]
1024     mov   rtsin, [esp+4]
1025 %endif
1026
1027     PREROTATER r4, r3, r2, rtcos, rtsin
1028 %if mmsize == 8
1029     mov    r6, [esp]                ; rrevtab = ptr+n8
1030     movzx  r5,  word [rrevtab+r4-2] ; rrevtab[j]
1031     movzx  r6,  word [rrevtab+r3]   ; rrevtab[n4-j-1]
1032     mova [r1+r5*8], m0
1033     mova [r1+r6*8], m2
1034     add    r4, 2
1035     sub    r3, 2
1036 %else
1037 %if ARCH_X86_64
1038     movzx  r5,  word [rrevtab+r4-4]
1039     movzx  r6,  word [rrevtab+r4-2]
1040     movzx  r10, word [rrevtab+r3]
1041     movzx  r11, word [rrevtab+r3+2]
1042     movlps [r1+r5 *8], xmm0
1043     movhps [r1+r6 *8], xmm0
1044     movlps [r1+r10*8], xmm1
1045     movhps [r1+r11*8], xmm1
1046     add    r4, 4
1047 %else
1048     mov    r6, [esp]
1049     movzx  r5, word [r6+r4-4]
1050     movzx  r4, word [r6+r4-2]
1051     movlps [r1+r5*8], xmm0
1052     movhps [r1+r4*8], xmm0
1053     movzx  r5, word [r6+r3]
1054     movzx  r4, word [r6+r3+2]
1055     movlps [r1+r5*8], xmm1
1056     movhps [r1+r4*8], xmm1
1057 %endif
1058     sub    r3, 4
1059 %endif
1060     jns    .pre
1061
1062     mov  r5, r0
1063     mov  r6, r1
1064     mov  r0, r1
1065     mov  r1d, [r5+FFTContext.nbits]
1066
1067     FFT_DISPATCH SUFFIX, r1
1068
1069     mov  r0d, [r5+FFTContext.mdctsize]
1070     add  r6, r0
1071     shr  r0, 1
1072 %if ARCH_X86_64 == 0
1073 %define rtcos r2
1074 %define rtsin r3
1075     mov  rtcos, [esp+8]
1076     mov  rtsin, [esp+4]
1077 %endif
1078     neg  r0
1079     mov  r1, -mmsize
1080     sub  r1, r0
1081     %1 r0, r1, r6, rtcos, rtsin
1082 %if ARCH_X86_64 == 0
1083     add esp, 12
1084 %endif
1085 %if mmsize == 8
1086     femms
1087 %endif
1088     RET
1089 %endmacro
1090
1091 DECL_IMDCT POSROTATESHUF
1092
1093 %if ARCH_X86_32
1094 INIT_MMX 3dnow
1095 DECL_IMDCT POSROTATESHUF_3DNOW
1096
1097 INIT_MMX 3dnowext
1098 DECL_IMDCT POSROTATESHUF_3DNOW
1099 %endif
1100
1101 INIT_YMM avx
1102
1103 %if HAVE_AVX_EXTERNAL
1104 DECL_IMDCT POSROTATESHUF_AVX
1105 %endif