]> 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 %ifdef 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 endstruc
49
50 SECTION_RODATA
51
52 %define M_SQRT1_2 0.70710678118654752440
53 %define M_COS_PI_1_8 0.923879532511287
54 %define M_COS_PI_3_8 0.38268343236509
55
56 align 32
57 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
58 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
59
60 ps_root2: times 8 dd M_SQRT1_2
61 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
62 ps_p1p1m1p1: dd 0, 0, 1<<31, 0, 0, 0, 1<<31, 0
63
64 perm1: dd 0x00, 0x02, 0x03, 0x01, 0x03, 0x00, 0x02, 0x01
65 perm2: dd 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x02, 0x03
66 ps_p1p1m1p1root2: dd 1.0, 1.0, -1.0, 1.0, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2
67 ps_m1m1p1m1p1m1m1m1: dd 1<<31, 1<<31, 0, 1<<31, 0, 1<<31, 1<<31, 1<<31
68 ps_m1p1: dd 1<<31, 0
69
70 %assign i 16
71 %rep 13
72 cextern cos_ %+ i
73 %assign i i<<1
74 %endrep
75
76 %ifdef ARCH_X86_64
77     %define pointer dq
78 %else
79     %define pointer dd
80 %endif
81
82 %macro IF0 1+
83 %endmacro
84 %macro IF1 1+
85     %1
86 %endmacro
87
88 SECTION_TEXT
89
90 %macro T2_3DN 4 ; z0, z1, mem0, mem1
91     mova     %1, %3
92     mova     %2, %1
93     pfadd    %1, %4
94     pfsub    %2, %4
95 %endmacro
96
97 %macro T4_3DN 6 ; z0, z1, z2, z3, tmp0, tmp1
98     mova     %5, %3
99     pfsub    %3, %4
100     pfadd    %5, %4 ; {t6,t5}
101     pxor     %3, [ps_m1p1] ; {t8,t7}
102     mova     %6, %1
103     pswapd   %3, %3
104     pfadd    %1, %5 ; {r0,i0}
105     pfsub    %6, %5 ; {r2,i2}
106     mova     %4, %2
107     pfadd    %2, %3 ; {r1,i1}
108     pfsub    %4, %3 ; {r3,i3}
109     SWAP     %3, %6
110 %endmacro
111
112 ;  in: %1 = {r0,i0,r2,i2,r4,i4,r6,i6}
113 ;      %2 = {r1,i1,r3,i3,r5,i5,r7,i7}
114 ;      %3, %4, %5 tmp
115 ; out: %1 = {r0,r1,r2,r3,i0,i1,i2,i3}
116 ;      %2 = {r4,r5,r6,r7,i4,i5,i6,i7}
117 %macro T8_AVX 5
118     vsubps     %5, %1, %2       ; v  = %1 - %2
119     vaddps     %3, %1, %2       ; w  = %1 + %2
120     vmulps     %2, %5, [ps_p1p1m1p1root2]  ; v *= vals1
121     vpermilps  %2, %2, [perm1]
122     vblendps   %1, %2, %3, 0x33 ; q = {w1,w2,v4,v2,w5,w6,v7,v6}
123     vshufps    %5, %3, %2, 0x4e ; r = {w3,w4,v1,v3,w7,w8,v8,v5}
124     vsubps     %4, %5, %1       ; s = r - q
125     vaddps     %1, %5, %1       ; u = r + q
126     vpermilps  %1, %1, [perm2]  ; k  = {u1,u2,u3,u4,u6,u5,u7,u8}
127     vshufps    %5, %4, %1, 0xbb
128     vshufps    %3, %4, %1, 0xee
129     vperm2f128 %3, %3, %5, 0x13
130     vxorps     %4, %4, [ps_m1m1p1m1p1m1m1m1]  ; s *= {1,1,-1,-1,1,-1,-1,-1}
131     vshufps    %2, %1, %4, 0xdd
132     vshufps    %1, %1, %4, 0x88
133     vperm2f128 %4, %2, %1, 0x02 ; v  = {k1,k3,s1,s3,k2,k4,s2,s4}
134     vperm2f128 %1, %1, %2, 0x13 ; w  = {k6,k8,s6,s8,k5,k7,s5,s7}
135     vsubps     %5, %1, %3
136     vblendps   %1, %5, %1, 0x55 ; w -= {0,s7,0,k7,0,s8,0,k8}
137     vsubps     %2, %4, %1       ; %2 = v - w
138     vaddps     %1, %4, %1       ; %1 = v + w
139 %endmacro
140
141 ; In SSE mode do one fft4 transforms
142 ; in:  %1={r0,i0,r2,i2} %2={r1,i1,r3,i3}
143 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3}
144 ;
145 ; In AVX mode do two fft4 transforms
146 ; in:  %1={r0,i0,r2,i2,r4,i4,r6,i6} %2={r1,i1,r3,i3,r5,i5,r7,i7}
147 ; out: %1={r0,r1,r2,r3,r4,r5,r6,r7} %2={i0,i1,i2,i3,i4,i5,i6,i7}
148 %macro T4_SSE 3
149     subps    %3, %1, %2       ; {t3,t4,-t8,t7}
150     addps    %1, %1, %2       ; {t1,t2,t6,t5}
151     xorps    %3, %3, [ps_p1p1m1p1]
152     shufps   %2, %1, %3, 0xbe ; {t6,t5,t7,t8}
153     shufps   %1, %1, %3, 0x44 ; {t1,t2,t3,t4}
154     subps    %3, %1, %2       ; {r2,i2,r3,i3}
155     addps    %1, %1, %2       ; {r0,i0,r1,i1}
156     shufps   %2, %1, %3, 0xdd ; {i0,i1,i2,i3}
157     shufps   %1, %1, %3, 0x88 ; {r0,r1,r2,r3}
158 %endmacro
159
160 ; In SSE mode do one FFT8
161 ; in:  %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %3={r4,i4,r6,i6} %4={r5,i5,r7,i7}
162 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %1={r4,r5,r6,r7} %2={i4,i5,i6,i7}
163 ;
164 ; In AVX mode do two FFT8
165 ; in:  %1={r0,i0,r2,i2,r8, i8, r10,i10} %2={r1,i1,r3,i3,r9, i9, r11,i11}
166 ;      %3={r4,i4,r6,i6,r12,i12,r14,i14} %4={r5,i5,r7,i7,r13,i13,r15,i15}
167 ; out: %1={r0,r1,r2,r3,r8, r9, r10,r11} %2={i0,i1,i2,i3,i8, i9, i10,i11}
168 ;      %3={r4,r5,r6,r7,r12,r13,r14,r15} %4={i4,i5,i6,i7,i12,i13,i14,i15}
169 %macro T8_SSE 6
170     addps    %6, %3, %4       ; {t1,t2,t3,t4}
171     subps    %3, %3, %4       ; {r5,i5,r7,i7}
172     shufps   %4, %3, %3, 0xb1 ; {i5,r5,i7,r7}
173     mulps    %3, %3, [ps_root2mppm] ; {-r5,i5,r7,-i7}
174     mulps    %4, %4, [ps_root2]
175     addps    %3, %3, %4       ; {t8,t7,ta,t9}
176     shufps   %4, %6, %3, 0x9c ; {t1,t4,t7,ta}
177     shufps   %6, %6, %3, 0x36 ; {t3,t2,t9,t8}
178     subps    %3, %6, %4       ; {t6,t5,tc,tb}
179     addps    %6, %6, %4       ; {t1,t2,t9,ta}
180     shufps   %5, %6, %3, 0x8d ; {t2,ta,t6,tc}
181     shufps   %6, %6, %3, 0xd8 ; {t1,t9,t5,tb}
182     subps    %3, %1, %6       ; {r4,r5,r6,r7}
183     addps    %1, %1, %6       ; {r0,r1,r2,r3}
184     subps    %4, %2, %5       ; {i4,i5,i6,i7}
185     addps    %2, %2, %5       ; {i0,i1,i2,i3}
186 %endmacro
187
188 ; scheduled for cpu-bound sizes
189 %macro PASS_SMALL 3 ; (to load m4-m7), wre, wim
190 IF%1 mova    m4, Z(4)
191 IF%1 mova    m5, Z(5)
192     mova     m0, %2 ; wre
193     mova     m1, %3 ; wim
194     mulps    m2, m4, m0 ; r2*wre
195 IF%1 mova    m6, Z2(6)
196     mulps    m3, m5, m1 ; i2*wim
197 IF%1 mova    m7, Z2(7)
198     mulps    m4, m4, m1 ; r2*wim
199     mulps    m5, m5, m0 ; i2*wre
200     addps    m2, m2, m3 ; r2*wre + i2*wim
201     mulps    m3, m1, m7 ; i3*wim
202     subps    m5, m5, m4 ; i2*wre - r2*wim
203     mulps    m1, m1, m6 ; r3*wim
204     mulps    m4, m0, m6 ; r3*wre
205     mulps    m0, m0, m7 ; i3*wre
206     subps    m4, m4, m3 ; r3*wre - i3*wim
207     mova     m3, Z(0)
208     addps    m0, m0, m1 ; i3*wre + r3*wim
209     subps    m1, m4, m2 ; t3
210     addps    m4, m4, m2 ; t5
211     subps    m3, m3, m4 ; r2
212     addps    m4, m4, Z(0) ; r0
213     mova     m6, Z(2)
214     mova   Z(4), m3
215     mova   Z(0), m4
216     subps    m3, m5, m0 ; t4
217     subps    m4, m6, m3 ; r3
218     addps    m3, m3, m6 ; r1
219     mova  Z2(6), m4
220     mova   Z(2), m3
221     mova     m2, Z(3)
222     addps    m3, m5, m0 ; t6
223     subps    m2, m2, m1 ; i3
224     mova     m7, Z(1)
225     addps    m1, m1, Z(3) ; i1
226     mova  Z2(7), m2
227     mova   Z(3), m1
228     subps    m4, m7, m3 ; i2
229     addps    m3, m3, m7 ; i0
230     mova   Z(5), m4
231     mova   Z(1), m3
232 %endmacro
233
234 ; scheduled to avoid store->load aliasing
235 %macro PASS_BIG 1 ; (!interleave)
236     mova     m4, Z(4) ; r2
237     mova     m5, Z(5) ; i2
238     mova     m0, [wq] ; wre
239     mova     m1, [wq+o1q] ; wim
240     mulps    m2, m4, m0 ; r2*wre
241     mova     m6, Z2(6) ; r3
242     mulps    m3, m5, m1 ; i2*wim
243     mova     m7, Z2(7) ; i3
244     mulps    m4, m4, m1 ; r2*wim
245     mulps    m5, m5, m0 ; i2*wre
246     addps    m2, m2, m3 ; r2*wre + i2*wim
247     mulps    m3, m1, m7 ; i3*wim
248     mulps    m1, m1, m6 ; r3*wim
249     subps    m5, m5, m4 ; i2*wre - r2*wim
250     mulps    m4, m0, m6 ; r3*wre
251     mulps    m0, m0, m7 ; i3*wre
252     subps    m4, m4, m3 ; r3*wre - i3*wim
253     mova     m3, Z(0)
254     addps    m0, m0, m1 ; i3*wre + r3*wim
255     subps    m1, m4, m2 ; t3
256     addps    m4, m4, m2 ; t5
257     subps    m3, m3, m4 ; r2
258     addps    m4, m4, Z(0) ; r0
259     mova     m6, Z(2)
260     mova   Z(4), m3
261     mova   Z(0), m4
262     subps    m3, m5, m0 ; t4
263     subps    m4, m6, m3 ; r3
264     addps    m3, m3, m6 ; r1
265 IF%1 mova Z2(6), m4
266 IF%1 mova  Z(2), m3
267     mova     m2, Z(3)
268     addps    m5, m5, m0 ; t6
269     subps    m2, m2, m1 ; i3
270     mova     m7, Z(1)
271     addps    m1, m1, Z(3) ; i1
272 IF%1 mova Z2(7), m2
273 IF%1 mova  Z(3), m1
274     subps    m6, m7, m5 ; i2
275     addps    m5, m5, m7 ; i0
276 IF%1 mova  Z(5), m6
277 IF%1 mova  Z(1), m5
278 %if %1==0
279     INTERL m1, m3, m7, Z, 2
280     INTERL m2, m4, m0, Z2, 6
281
282     mova     m1, Z(0)
283     mova     m2, Z(4)
284
285     INTERL m5, m1, m3, Z, 0
286     INTERL m6, m2, m7, Z, 4
287 %endif
288 %endmacro
289
290 %macro PUNPCK 3
291     mova      %3, %1
292     punpckldq %1, %2
293     punpckhdq %3, %2
294 %endmacro
295
296 %define Z(x) [r0+mmsize*x]
297 %define Z2(x) [r0+mmsize*x]
298 %define ZH(x) [r0+mmsize*x+mmsize/2]
299
300 INIT_YMM
301
302 %ifdef HAVE_AVX
303 align 16
304 fft8_avx:
305     mova      m0, Z(0)
306     mova      m1, Z(1)
307     T8_AVX    m0, m1, m2, m3, m4
308     mova      Z(0), m0
309     mova      Z(1), m1
310     ret
311
312
313 align 16
314 fft16_avx:
315     mova       m2, Z(2)
316     mova       m3, Z(3)
317     T4_SSE     m2, m3, m7
318
319     mova       m0, Z(0)
320     mova       m1, Z(1)
321     T8_AVX     m0, m1, m4, m5, m7
322
323     mova       m4, [ps_cos16_1]
324     mova       m5, [ps_cos16_2]
325     vmulps     m6, m2, m4
326     vmulps     m7, m3, m5
327     vaddps     m7, m7, m6
328     vmulps     m2, m2, m5
329     vmulps     m3, m3, m4
330     vsubps     m3, m3, m2
331     vblendps   m2, m7, m3, 0xf0
332     vperm2f128 m3, m7, m3, 0x21
333     vaddps     m4, m2, m3
334     vsubps     m2, m3, m2
335     vperm2f128 m2, m2, m2, 0x01
336     vsubps     m3, m1, m2
337     vaddps     m1, m1, m2
338     vsubps     m5, m0, m4
339     vaddps     m0, m0, m4
340     vextractf128   Z(0), m0, 0
341     vextractf128  ZH(0), m1, 0
342     vextractf128   Z(1), m0, 1
343     vextractf128  ZH(1), m1, 1
344     vextractf128   Z(2), m5, 0
345     vextractf128  ZH(2), m3, 0
346     vextractf128   Z(3), m5, 1
347     vextractf128  ZH(3), m3, 1
348     ret
349
350 align 16
351 fft32_avx:
352     call fft16_avx
353
354     mova m0, Z(4)
355     mova m1, Z(5)
356
357     T4_SSE      m0, m1, m4
358
359     mova m2, Z(6)
360     mova m3, Z(7)
361
362     T8_SSE      m0, m1, m2, m3, m4, m6
363     ; m0={r0,r1,r2,r3,r8, r9, r10,r11} m1={i0,i1,i2,i3,i8, i9, i10,i11}
364     ; m2={r4,r5,r6,r7,r12,r13,r14,r15} m3={i4,i5,i6,i7,i12,i13,i14,i15}
365
366     vperm2f128  m4, m0, m2, 0x20
367     vperm2f128  m5, m1, m3, 0x20
368     vperm2f128  m6, m0, m2, 0x31
369     vperm2f128  m7, m1, m3, 0x31
370
371     PASS_SMALL 0, [cos_32], [cos_32+32]
372
373     ret
374
375 fft32_interleave_avx:
376     call fft32_avx
377     mov r2d, 32
378 .deint_loop:
379     mova     m2, Z(0)
380     mova     m3, Z(1)
381     vunpcklps      m0, m2, m3
382     vunpckhps      m1, m2, m3
383     vextractf128   Z(0), m0, 0
384     vextractf128  ZH(0), m1, 0
385     vextractf128   Z(1), m0, 1
386     vextractf128  ZH(1), m1, 1
387     add r0, mmsize*2
388     sub r2d, mmsize/4
389     jg .deint_loop
390     ret
391
392 %endif
393
394 INIT_XMM
395 %define movdqa  movaps
396
397 align 16
398 fft4_avx:
399 fft4_sse:
400     mova     m0, Z(0)
401     mova     m1, Z(1)
402     T4_SSE   m0, m1, m2
403     mova   Z(0), m0
404     mova   Z(1), m1
405     ret
406
407 align 16
408 fft8_sse:
409     mova     m0, Z(0)
410     mova     m1, Z(1)
411     T4_SSE   m0, m1, m2
412     mova     m2, Z(2)
413     mova     m3, Z(3)
414     T8_SSE   m0, m1, m2, m3, m4, m5
415     mova   Z(0), m0
416     mova   Z(1), m1
417     mova   Z(2), m2
418     mova   Z(3), m3
419     ret
420
421 align 16
422 fft16_sse:
423     mova     m0, Z(0)
424     mova     m1, Z(1)
425     T4_SSE   m0, m1, m2
426     mova     m2, Z(2)
427     mova     m3, Z(3)
428     T8_SSE   m0, m1, m2, m3, m4, m5
429     mova     m4, Z(4)
430     mova     m5, Z(5)
431     mova   Z(0), m0
432     mova   Z(1), m1
433     mova   Z(2), m2
434     mova   Z(3), m3
435     T4_SSE   m4, m5, m6
436     mova     m6, Z2(6)
437     mova     m7, Z2(7)
438     T4_SSE   m6, m7, m0
439     PASS_SMALL 0, [cos_16], [cos_16+16]
440     ret
441
442
443 INIT_MMX
444
445 %macro FFT48_3DN 1
446 align 16
447 fft4%1:
448     T2_3DN   m0, m1, Z(0), Z(1)
449     mova     m2, Z(2)
450     mova     m3, Z(3)
451     T4_3DN   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%1:
462     T2_3DN   m0, m1, Z(0), Z(1)
463     mova     m2, Z(2)
464     mova     m3, Z(3)
465     T4_3DN   m0, m1, m2, m3, m4, m5
466     mova   Z(0), m0
467     mova   Z(2), m2
468     T2_3DN   m4, m5,  Z(4),  Z(5)
469     T2_3DN   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_3DN   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_3DN   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 FFT48_3DN _3dn2
500
501 %macro pswapd 2
502 %ifidn %1, %2
503     movd [r0+12], %1
504     punpckhdq %1, [r0+8]
505 %else
506     movq  %1, %2
507     psrlq %1, 32
508     punpckldq %1, %2
509 %endif
510 %endmacro
511
512 FFT48_3DN _3dn
513
514
515 %define Z(x) [zq + o1q*(x&6) + mmsize*(x&1)]
516 %define Z2(x) [zq + o3q + mmsize*(x&1)]
517 %define ZH(x) [zq + o1q*(x&6) + mmsize*(x&1) + mmsize/2]
518 %define Z2H(x) [zq + o3q + mmsize*(x&1) + mmsize/2]
519
520 %macro DECL_PASS 2+ ; name, payload
521 align 16
522 %1:
523 DEFINE_ARGS z, w, n, o1, o3
524     lea o3q, [nq*3]
525     lea o1q, [nq*8]
526     shl o3q, 4
527 .loop:
528     %2
529     add zq, mmsize*2
530     add wq, mmsize
531     sub nd, mmsize/8
532     jg .loop
533     rep ret
534 %endmacro
535
536 INIT_YMM
537
538 %ifdef HAVE_AVX
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 %endif
553
554 INIT_XMM
555
556 %macro INTERL_SSE 5
557     mova     %3, %2
558     unpcklps %2, %1
559     unpckhps %3, %1
560     mova  %4(%5), %2
561     mova  %4(%5+1), %3
562 %endmacro
563
564 %define INTERL INTERL_SSE
565
566 DECL_PASS pass_sse, PASS_BIG 1
567 DECL_PASS pass_interleave_sse, PASS_BIG 0
568
569 INIT_MMX
570 %define mulps pfmul
571 %define addps pfadd
572 %define subps pfsub
573 %define unpcklps punpckldq
574 %define unpckhps punpckhdq
575 DECL_PASS pass_3dn, PASS_SMALL 1, [wq], [wq+o1q]
576 DECL_PASS pass_interleave_3dn, PASS_BIG 0
577 %define pass_3dn2 pass_3dn
578 %define pass_interleave_3dn2 pass_interleave_3dn
579
580 %ifdef PIC
581 %define SECTION_REL - $$
582 %else
583 %define SECTION_REL
584 %endif
585
586 %macro FFT_DISPATCH 2; clobbers 5 GPRs, 8 XMMs
587     lea r2, [dispatch_tab%1]
588     mov r2, [r2 + (%2q-2)*gprsize]
589 %ifdef PIC
590     lea r3, [$$]
591     add r2, r3
592 %endif
593     call r2
594 %endmacro ; FFT_DISPATCH
595
596 %macro DECL_FFT 2-3 ; nbits, cpu, suffix
597 %xdefine list_of_fft fft4%2 SECTION_REL, fft8%2 SECTION_REL
598 %if %1>=5
599 %xdefine list_of_fft list_of_fft, fft16%2 SECTION_REL
600 %endif
601 %if %1>=6
602 %xdefine list_of_fft list_of_fft, fft32%3%2 SECTION_REL
603 %endif
604
605 %assign n 1<<%1
606 %rep 17-%1
607 %assign n2 n/2
608 %assign n4 n/4
609 %xdefine list_of_fft list_of_fft, fft %+ n %+ %3%2 SECTION_REL
610
611 align 16
612 fft %+ n %+ %3%2:
613     call fft %+ n2 %+ %2
614     add r0, n*4 - (n&(-2<<%1))
615     call fft %+ n4 %+ %2
616     add r0, n*2 - (n2&(-2<<%1))
617     call fft %+ n4 %+ %2
618     sub r0, n*6 + (n2&(-2<<%1))
619     lea r1, [cos_ %+ n]
620     mov r2d, n4/2
621     jmp pass%3%2
622
623 %assign n n*2
624 %endrep
625 %undef n
626
627 align 8
628 dispatch_tab%3%2: pointer list_of_fft
629
630 section .text
631
632 ; On x86_32, this function does the register saving and restoring for all of fft.
633 ; The others pass args in registers and don't spill anything.
634 cglobal fft_dispatch%3%2, 2,5,8, z, nbits
635     FFT_DISPATCH %3%2, nbits
636 %ifidn %2, _avx
637     vzeroupper
638 %endif
639     RET
640 %endmacro ; DECL_FFT
641
642 %ifdef HAVE_AVX
643 DECL_FFT 6, _avx
644 DECL_FFT 6, _avx, _interleave
645 %endif
646 DECL_FFT 5, _sse
647 DECL_FFT 5, _sse, _interleave
648 DECL_FFT 4, _3dn
649 DECL_FFT 4, _3dn, _interleave
650 DECL_FFT 4, _3dn2
651 DECL_FFT 4, _3dn2, _interleave
652
653 INIT_XMM
654 %undef mulps
655 %undef addps
656 %undef subps
657 %undef unpcklps
658 %undef unpckhps
659
660 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
661     movaps   xmm0, [%3+%2*4]
662     movaps   xmm1, [%3+%1*4-0x10]
663     movaps   xmm2, xmm0
664     shufps   xmm0, xmm1, 0x88
665     shufps   xmm1, xmm2, 0x77
666     movlps   xmm4, [%4+%2*2]
667     movlps   xmm5, [%5+%2*2+0x0]
668     movhps   xmm4, [%4+%1*2-0x8]
669     movhps   xmm5, [%5+%1*2-0x8]
670     movaps   xmm2, xmm0
671     movaps   xmm3, xmm1
672     mulps    xmm0, xmm5
673     mulps    xmm1, xmm4
674     mulps    xmm2, xmm4
675     mulps    xmm3, xmm5
676     subps    xmm1, xmm0
677     addps    xmm2, xmm3
678     movaps   xmm0, xmm1
679     unpcklps xmm1, xmm2
680     unpckhps xmm0, xmm2
681 %endmacro
682
683 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
684     mulps      m6, %3, [%5+%1]
685     mulps      m7, %2, [%5+%1]
686     mulps      %2, %2, [%6+%1]
687     mulps      %3, %3, [%6+%1]
688     subps      %2, %2, m6
689     addps      %3, %3, m7
690 %endmacro
691
692 %macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8
693 .post:
694     vmovaps      ymm1,   [%3+%1*2]
695     vmovaps      ymm0,   [%3+%1*2+0x20]
696     vmovaps      ymm3,   [%3+%2*2]
697     vmovaps      ymm2,   [%3+%2*2+0x20]
698
699     CMUL         %1, ymm0, ymm1, %3, %4, %5
700     CMUL         %2, ymm2, ymm3, %3, %4, %5
701     vshufps      ymm1, ymm1, ymm1, 0x1b
702     vshufps      ymm3, ymm3, ymm3, 0x1b
703     vperm2f128   ymm1, ymm1, ymm1, 0x01
704     vperm2f128   ymm3, ymm3, ymm3, 0x01
705     vunpcklps    ymm6, ymm2, ymm1
706     vunpckhps    ymm4, ymm2, ymm1
707     vunpcklps    ymm7, ymm0, ymm3
708     vunpckhps    ymm5, ymm0, ymm3
709
710     vextractf128 [%3+%1*2],      ymm7, 0
711     vextractf128 [%3+%1*2+0x10], ymm5, 0
712     vextractf128 [%3+%1*2+0x20], ymm7, 1
713     vextractf128 [%3+%1*2+0x30], ymm5, 1
714
715     vextractf128 [%3+%2*2],      ymm6, 0
716     vextractf128 [%3+%2*2+0x10], ymm4, 0
717     vextractf128 [%3+%2*2+0x20], ymm6, 1
718     vextractf128 [%3+%2*2+0x30], ymm4, 1
719     sub      %2,   0x20
720     add      %1,   0x20
721     jl       .post
722 %endmacro
723
724 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
725 .post:
726     movaps   xmm1, [%3+%1*2]
727     movaps   xmm0, [%3+%1*2+0x10]
728     CMUL     %1,   xmm0, xmm1, %3, %4, %5
729     movaps   xmm5, [%3+%2*2]
730     movaps   xmm4, [%3+%2*2+0x10]
731     CMUL     %2,   xmm4, xmm5, %3, %4, %5
732     shufps   xmm1, xmm1, 0x1b
733     shufps   xmm5, xmm5, 0x1b
734     movaps   xmm6, xmm4
735     unpckhps xmm4, xmm1
736     unpcklps xmm6, xmm1
737     movaps   xmm2, xmm0
738     unpcklps xmm0, xmm5
739     unpckhps xmm2, xmm5
740     movaps   [%3+%2*2],      xmm6
741     movaps   [%3+%2*2+0x10], xmm4
742     movaps   [%3+%1*2],      xmm0
743     movaps   [%3+%1*2+0x10], xmm2
744     sub      %2,   0x10
745     add      %1,   0x10
746     jl       .post
747 %endmacro
748
749 %macro DECL_IMDCT 2
750 cglobal imdct_half%1, 3,7,8; FFTContext *s, FFTSample *output, const FFTSample *input
751 %ifdef ARCH_X86_64
752 %define rrevtab r10
753 %define rtcos   r11
754 %define rtsin   r12
755     push  r12
756     push  r13
757     push  r14
758 %else
759 %define rrevtab r6
760 %define rtsin   r6
761 %define rtcos   r5
762 %endif
763     mov   r3d, [r0+FFTContext.mdctsize]
764     add   r2, r3
765     shr   r3, 1
766     mov   rtcos, [r0+FFTContext.tcos]
767     mov   rtsin, [r0+FFTContext.tsin]
768     add   rtcos, r3
769     add   rtsin, r3
770 %ifndef ARCH_X86_64
771     push  rtcos
772     push  rtsin
773 %endif
774     shr   r3, 1
775     mov   rrevtab, [r0+FFTContext.revtab]
776     add   rrevtab, r3
777 %ifndef ARCH_X86_64
778     push  rrevtab
779 %endif
780
781     sub   r3, 4
782 %ifdef ARCH_X86_64
783     xor   r4, r4
784     sub   r4, r3
785 %endif
786 .pre:
787 %ifndef ARCH_X86_64
788 ;unspill
789     xor   r4, r4
790     sub   r4, r3
791     mov   rtsin, [esp+4]
792     mov   rtcos, [esp+8]
793 %endif
794
795     PREROTATER r4, r3, r2, rtcos, rtsin
796 %ifdef ARCH_X86_64
797     movzx  r5,  word [rrevtab+r4-4]
798     movzx  r6,  word [rrevtab+r4-2]
799     movzx  r13, word [rrevtab+r3]
800     movzx  r14, word [rrevtab+r3+2]
801     movlps [r1+r5 *8], xmm0
802     movhps [r1+r6 *8], xmm0
803     movlps [r1+r13*8], xmm1
804     movhps [r1+r14*8], xmm1
805     add    r4, 4
806 %else
807     mov    r6, [esp]
808     movzx  r5, word [r6+r4-4]
809     movzx  r4, word [r6+r4-2]
810     movlps [r1+r5*8], xmm0
811     movhps [r1+r4*8], xmm0
812     movzx  r5, word [r6+r3]
813     movzx  r4, word [r6+r3+2]
814     movlps [r1+r5*8], xmm1
815     movhps [r1+r4*8], xmm1
816 %endif
817     sub    r3, 4
818     jns    .pre
819
820     mov  r5, r0
821     mov  r6, r1
822     mov  r0, r1
823     mov  r1d, [r5+FFTContext.nbits]
824
825     FFT_DISPATCH %1, r1
826
827     mov  r0d, [r5+FFTContext.mdctsize]
828     add  r6, r0
829     shr  r0, 1
830 %ifndef ARCH_X86_64
831 %define rtcos r2
832 %define rtsin r3
833     mov  rtcos, [esp+8]
834     mov  rtsin, [esp+4]
835 %endif
836     neg  r0
837     mov  r1, -mmsize
838     sub  r1, r0
839     %2 r0, r1, r6, rtcos, rtsin
840 %ifdef ARCH_X86_64
841     pop  r14
842     pop  r13
843     pop  r12
844 %else
845     add esp, 12
846 %endif
847 %ifidn avx_enabled, 1
848     vzeroupper
849 %endif
850     RET
851 %endmacro
852
853 DECL_IMDCT _sse, POSROTATESHUF
854
855 INIT_YMM
856
857 %ifdef HAVE_AVX
858 DECL_IMDCT _avx, POSROTATESHUF_AVX
859 %endif