wtv: Check the return value from gmtime
[ffmpeg.git] / 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 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
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_3DN 4 ; z0, z1, mem0, mem1
96     mova     %1, %3
97     mova     %2, %1
98     pfadd    %1, %4
99     pfsub    %2, %4
100 %endmacro
101
102 %macro T4_3DN 6 ; z0, z1, z2, z3, tmp0, tmp1
103     mova     %5, %3
104     pfsub    %3, %4
105     pfadd    %5, %4 ; {t6,t5}
106     pxor     %3, [ps_m1p1] ; {t8,t7}
107     mova     %6, %1
108     pswapd   %3, %3
109     pfadd    %1, %5 ; {r0,i0}
110     pfsub    %6, %5 ; {r2,i2}
111     mova     %4, %2
112     pfadd    %2, %3 ; {r1,i1}
113     pfsub    %4, %3 ; {r3,i3}
114     SWAP     %3, %6
115 %endmacro
116
117 ;  in: %1 = {r0,i0,r2,i2,r4,i4,r6,i6}
118 ;      %2 = {r1,i1,r3,i3,r5,i5,r7,i7}
119 ;      %3, %4, %5 tmp
120 ; out: %1 = {r0,r1,r2,r3,i0,i1,i2,i3}
121 ;      %2 = {r4,r5,r6,r7,i4,i5,i6,i7}
122 %macro T8_AVX 5
123     vsubps     %5, %1, %2       ; v  = %1 - %2
124     vaddps     %3, %1, %2       ; w  = %1 + %2
125     vmulps     %2, %5, [ps_p1p1m1p1root2]  ; v *= vals1
126     vpermilps  %2, %2, [perm1]
127     vblendps   %1, %2, %3, 0x33 ; q = {w1,w2,v4,v2,w5,w6,v7,v6}
128     vshufps    %5, %3, %2, 0x4e ; r = {w3,w4,v1,v3,w7,w8,v8,v5}
129     vsubps     %4, %5, %1       ; s = r - q
130     vaddps     %1, %5, %1       ; u = r + q
131     vpermilps  %1, %1, [perm2]  ; k  = {u1,u2,u3,u4,u6,u5,u7,u8}
132     vshufps    %5, %4, %1, 0xbb
133     vshufps    %3, %4, %1, 0xee
134     vperm2f128 %3, %3, %5, 0x13
135     vxorps     %4, %4, [ps_m1m1p1m1p1m1m1m1]  ; s *= {1,1,-1,-1,1,-1,-1,-1}
136     vshufps    %2, %1, %4, 0xdd
137     vshufps    %1, %1, %4, 0x88
138     vperm2f128 %4, %2, %1, 0x02 ; v  = {k1,k3,s1,s3,k2,k4,s2,s4}
139     vperm2f128 %1, %1, %2, 0x13 ; w  = {k6,k8,s6,s8,k5,k7,s5,s7}
140     vsubps     %5, %1, %3
141     vblendps   %1, %5, %1, 0x55 ; w -= {0,s7,0,k7,0,s8,0,k8}
142     vsubps     %2, %4, %1       ; %2 = v - w
143     vaddps     %1, %4, %1       ; %1 = v + w
144 %endmacro
145
146 ; In SSE mode do one fft4 transforms
147 ; in:  %1={r0,i0,r2,i2} %2={r1,i1,r3,i3}
148 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3}
149 ;
150 ; In AVX mode do two fft4 transforms
151 ; in:  %1={r0,i0,r2,i2,r4,i4,r6,i6} %2={r1,i1,r3,i3,r5,i5,r7,i7}
152 ; out: %1={r0,r1,r2,r3,r4,r5,r6,r7} %2={i0,i1,i2,i3,i4,i5,i6,i7}
153 %macro T4_SSE 3
154     subps    %3, %1, %2       ; {t3,t4,-t8,t7}
155     addps    %1, %1, %2       ; {t1,t2,t6,t5}
156     xorps    %3, %3, [ps_p1p1m1p1]
157     shufps   %2, %1, %3, 0xbe ; {t6,t5,t7,t8}
158     shufps   %1, %1, %3, 0x44 ; {t1,t2,t3,t4}
159     subps    %3, %1, %2       ; {r2,i2,r3,i3}
160     addps    %1, %1, %2       ; {r0,i0,r1,i1}
161     shufps   %2, %1, %3, 0xdd ; {i0,i1,i2,i3}
162     shufps   %1, %1, %3, 0x88 ; {r0,r1,r2,r3}
163 %endmacro
164
165 ; In SSE mode do one FFT8
166 ; in:  %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %3={r4,i4,r6,i6} %4={r5,i5,r7,i7}
167 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %1={r4,r5,r6,r7} %2={i4,i5,i6,i7}
168 ;
169 ; In AVX mode do two FFT8
170 ; in:  %1={r0,i0,r2,i2,r8, i8, r10,i10} %2={r1,i1,r3,i3,r9, i9, r11,i11}
171 ;      %3={r4,i4,r6,i6,r12,i12,r14,i14} %4={r5,i5,r7,i7,r13,i13,r15,i15}
172 ; out: %1={r0,r1,r2,r3,r8, r9, r10,r11} %2={i0,i1,i2,i3,i8, i9, i10,i11}
173 ;      %3={r4,r5,r6,r7,r12,r13,r14,r15} %4={i4,i5,i6,i7,i12,i13,i14,i15}
174 %macro T8_SSE 6
175     addps    %6, %3, %4       ; {t1,t2,t3,t4}
176     subps    %3, %3, %4       ; {r5,i5,r7,i7}
177     shufps   %4, %3, %3, 0xb1 ; {i5,r5,i7,r7}
178     mulps    %3, %3, [ps_root2mppm] ; {-r5,i5,r7,-i7}
179     mulps    %4, %4, [ps_root2]
180     addps    %3, %3, %4       ; {t8,t7,ta,t9}
181     shufps   %4, %6, %3, 0x9c ; {t1,t4,t7,ta}
182     shufps   %6, %6, %3, 0x36 ; {t3,t2,t9,t8}
183     subps    %3, %6, %4       ; {t6,t5,tc,tb}
184     addps    %6, %6, %4       ; {t1,t2,t9,ta}
185     shufps   %5, %6, %3, 0x8d ; {t2,ta,t6,tc}
186     shufps   %6, %6, %3, 0xd8 ; {t1,t9,t5,tb}
187     subps    %3, %1, %6       ; {r4,r5,r6,r7}
188     addps    %1, %1, %6       ; {r0,r1,r2,r3}
189     subps    %4, %2, %5       ; {i4,i5,i6,i7}
190     addps    %2, %2, %5       ; {i0,i1,i2,i3}
191 %endmacro
192
193 ; scheduled for cpu-bound sizes
194 %macro PASS_SMALL 3 ; (to load m4-m7), wre, wim
195 IF%1 mova    m4, Z(4)
196 IF%1 mova    m5, Z(5)
197     mova     m0, %2 ; wre
198     mova     m1, %3 ; wim
199     mulps    m2, m4, m0 ; r2*wre
200 IF%1 mova    m6, Z2(6)
201     mulps    m3, m5, m1 ; i2*wim
202 IF%1 mova    m7, Z2(7)
203     mulps    m4, m4, m1 ; r2*wim
204     mulps    m5, m5, m0 ; i2*wre
205     addps    m2, m2, m3 ; r2*wre + i2*wim
206     mulps    m3, m1, m7 ; i3*wim
207     subps    m5, m5, m4 ; i2*wre - r2*wim
208     mulps    m1, m1, m6 ; r3*wim
209     mulps    m4, m0, m6 ; r3*wre
210     mulps    m0, m0, m7 ; i3*wre
211     subps    m4, m4, m3 ; r3*wre - i3*wim
212     mova     m3, Z(0)
213     addps    m0, m0, m1 ; i3*wre + r3*wim
214     subps    m1, m4, m2 ; t3
215     addps    m4, m4, m2 ; t5
216     subps    m3, m3, m4 ; r2
217     addps    m4, m4, Z(0) ; r0
218     mova     m6, Z(2)
219     mova   Z(4), m3
220     mova   Z(0), m4
221     subps    m3, m5, m0 ; t4
222     subps    m4, m6, m3 ; r3
223     addps    m3, m3, m6 ; r1
224     mova  Z2(6), m4
225     mova   Z(2), m3
226     mova     m2, Z(3)
227     addps    m3, m5, m0 ; t6
228     subps    m2, m2, m1 ; i3
229     mova     m7, Z(1)
230     addps    m1, m1, Z(3) ; i1
231     mova  Z2(7), m2
232     mova   Z(3), m1
233     subps    m4, m7, m3 ; i2
234     addps    m3, m3, m7 ; i0
235     mova   Z(5), m4
236     mova   Z(1), m3
237 %endmacro
238
239 ; scheduled to avoid store->load aliasing
240 %macro PASS_BIG 1 ; (!interleave)
241     mova     m4, Z(4) ; r2
242     mova     m5, Z(5) ; i2
243     mova     m0, [wq] ; wre
244     mova     m1, [wq+o1q] ; wim
245     mulps    m2, m4, m0 ; r2*wre
246     mova     m6, Z2(6) ; r3
247     mulps    m3, m5, m1 ; i2*wim
248     mova     m7, Z2(7) ; i3
249     mulps    m4, m4, m1 ; r2*wim
250     mulps    m5, m5, m0 ; i2*wre
251     addps    m2, m2, m3 ; r2*wre + i2*wim
252     mulps    m3, m1, m7 ; i3*wim
253     mulps    m1, m1, m6 ; r3*wim
254     subps    m5, m5, m4 ; i2*wre - r2*wim
255     mulps    m4, m0, m6 ; r3*wre
256     mulps    m0, m0, m7 ; i3*wre
257     subps    m4, m4, m3 ; r3*wre - i3*wim
258     mova     m3, Z(0)
259     addps    m0, m0, m1 ; i3*wre + r3*wim
260     subps    m1, m4, m2 ; t3
261     addps    m4, m4, m2 ; t5
262     subps    m3, m3, m4 ; r2
263     addps    m4, m4, Z(0) ; r0
264     mova     m6, Z(2)
265     mova   Z(4), m3
266     mova   Z(0), m4
267     subps    m3, m5, m0 ; t4
268     subps    m4, m6, m3 ; r3
269     addps    m3, m3, m6 ; r1
270 IF%1 mova Z2(6), m4
271 IF%1 mova  Z(2), m3
272     mova     m2, Z(3)
273     addps    m5, m5, m0 ; t6
274     subps    m2, m2, m1 ; i3
275     mova     m7, Z(1)
276     addps    m1, m1, Z(3) ; i1
277 IF%1 mova Z2(7), m2
278 IF%1 mova  Z(3), m1
279     subps    m6, m7, m5 ; i2
280     addps    m5, m5, m7 ; i0
281 IF%1 mova  Z(5), m6
282 IF%1 mova  Z(1), m5
283 %if %1==0
284     INTERL m1, m3, m7, Z, 2
285     INTERL m2, m4, m0, Z2, 6
286
287     mova     m1, Z(0)
288     mova     m2, Z(4)
289
290     INTERL m5, m1, m3, Z, 0
291     INTERL m6, m2, m7, Z, 4
292 %endif
293 %endmacro
294
295 %macro PUNPCK 3
296     mova      %3, %1
297     punpckldq %1, %2
298     punpckhdq %3, %2
299 %endmacro
300
301 %define Z(x) [r0+mmsize*x]
302 %define Z2(x) [r0+mmsize*x]
303 %define ZH(x) [r0+mmsize*x+mmsize/2]
304
305 INIT_YMM avx
306
307 %if HAVE_AVX
308 align 16
309 fft8_avx:
310     mova      m0, Z(0)
311     mova      m1, Z(1)
312     T8_AVX    m0, m1, m2, m3, m4
313     mova      Z(0), m0
314     mova      Z(1), m1
315     ret
316
317
318 align 16
319 fft16_avx:
320     mova       m2, Z(2)
321     mova       m3, Z(3)
322     T4_SSE     m2, m3, m7
323
324     mova       m0, Z(0)
325     mova       m1, Z(1)
326     T8_AVX     m0, m1, m4, m5, m7
327
328     mova       m4, [ps_cos16_1]
329     mova       m5, [ps_cos16_2]
330     vmulps     m6, m2, m4
331     vmulps     m7, m3, m5
332     vaddps     m7, m7, m6
333     vmulps     m2, m2, m5
334     vmulps     m3, m3, m4
335     vsubps     m3, m3, m2
336     vblendps   m2, m7, m3, 0xf0
337     vperm2f128 m3, m7, m3, 0x21
338     vaddps     m4, m2, m3
339     vsubps     m2, m3, m2
340     vperm2f128 m2, m2, m2, 0x01
341     vsubps     m3, m1, m2
342     vaddps     m1, m1, m2
343     vsubps     m5, m0, m4
344     vaddps     m0, m0, m4
345     vextractf128   Z(0), m0, 0
346     vextractf128  ZH(0), m1, 0
347     vextractf128   Z(1), m0, 1
348     vextractf128  ZH(1), m1, 1
349     vextractf128   Z(2), m5, 0
350     vextractf128  ZH(2), m3, 0
351     vextractf128   Z(3), m5, 1
352     vextractf128  ZH(3), m3, 1
353     ret
354
355 align 16
356 fft32_avx:
357     call fft16_avx
358
359     mova m0, Z(4)
360     mova m1, Z(5)
361
362     T4_SSE      m0, m1, m4
363
364     mova m2, Z(6)
365     mova m3, Z(7)
366
367     T8_SSE      m0, m1, m2, m3, m4, m6
368     ; m0={r0,r1,r2,r3,r8, r9, r10,r11} m1={i0,i1,i2,i3,i8, i9, i10,i11}
369     ; m2={r4,r5,r6,r7,r12,r13,r14,r15} m3={i4,i5,i6,i7,i12,i13,i14,i15}
370
371     vperm2f128  m4, m0, m2, 0x20
372     vperm2f128  m5, m1, m3, 0x20
373     vperm2f128  m6, m0, m2, 0x31
374     vperm2f128  m7, m1, m3, 0x31
375
376     PASS_SMALL 0, [cos_32], [cos_32+32]
377
378     ret
379
380 fft32_interleave_avx:
381     call fft32_avx
382     mov r2d, 32
383 .deint_loop:
384     mova     m2, Z(0)
385     mova     m3, Z(1)
386     vunpcklps      m0, m2, m3
387     vunpckhps      m1, m2, m3
388     vextractf128   Z(0), m0, 0
389     vextractf128  ZH(0), m1, 0
390     vextractf128   Z(1), m0, 1
391     vextractf128  ZH(1), m1, 1
392     add r0, mmsize*2
393     sub r2d, mmsize/4
394     jg .deint_loop
395     ret
396 %endif
397
398 INIT_XMM sse
399 %define movdqa  movaps
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_3DN 0
448 align 16
449 fft4 %+ SUFFIX:
450     T2_3DN   m0, m1, Z(0), Z(1)
451     mova     m2, Z(2)
452     mova     m3, Z(3)
453     T4_3DN   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_3DN   m0, m1, Z(0), Z(1)
465     mova     m2, Z(2)
466     mova     m3, Z(3)
467     T4_3DN   m0, m1, m2, m3, m4, m5
468     mova   Z(0), m0
469     mova   Z(2), m2
470     T2_3DN   m4, m5,  Z(4),  Z(5)
471     T2_3DN   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_3DN   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_3DN   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 INIT_MMX 3dnow2
502 FFT48_3DN
503
504 %macro pswapd 2
505 %ifidn %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 3dnow
516 FFT48_3DN
517
518
519 %define Z(x) [zq + o1q*(x&6) + mmsize*(x&1)]
520 %define Z2(x) [zq + o3q + mmsize*(x&1)]
521 %define ZH(x) [zq + o1q*(x&6) + mmsize*(x&1) + mmsize/2]
522 %define Z2H(x) [zq + o3q + mmsize*(x&1) + mmsize/2]
523
524 %macro DECL_PASS 2+ ; name, payload
525 align 16
526 %1:
527 DEFINE_ARGS z, w, n, o1, o3
528     lea o3q, [nq*3]
529     lea o1q, [nq*8]
530     shl o3q, 4
531 .loop:
532     %2
533     add zq, mmsize*2
534     add wq, mmsize
535     sub nd, mmsize/8
536     jg .loop
537     rep ret
538 %endmacro
539
540 %macro FFT_DISPATCH 2; clobbers 5 GPRs, 8 XMMs
541     lea r2, [dispatch_tab%1]
542     mov r2, [r2 + (%2q-2)*gprsize]
543 %ifdef PIC
544     lea r3, [$$]
545     add r2, r3
546 %endif
547     call r2
548 %endmacro ; FFT_DISPATCH
549
550 INIT_YMM avx
551
552 %if HAVE_AVX
553 %macro INTERL_AVX 5
554     vunpckhps      %3, %2, %1
555     vunpcklps      %2, %2, %1
556     vextractf128   %4(%5), %2, 0
557     vextractf128  %4 %+ H(%5), %3, 0
558     vextractf128   %4(%5 + 1), %2, 1
559     vextractf128  %4 %+ H(%5 + 1), %3, 1
560 %endmacro
561
562 %define INTERL INTERL_AVX
563
564 DECL_PASS pass_avx, PASS_BIG 1
565 DECL_PASS pass_interleave_avx, PASS_BIG 0
566
567 cglobal fft_calc, 2,5,8
568     mov     r3d, [r0 + FFTContext.nbits]
569     mov     r0, r1
570     mov     r1, r3
571     FFT_DISPATCH _interleave %+ SUFFIX, r1
572     REP_RET
573
574 %endif
575
576 INIT_XMM sse
577
578 %macro INTERL_SSE 5
579     mova     %3, %2
580     unpcklps %2, %1
581     unpckhps %3, %1
582     mova  %4(%5), %2
583     mova  %4(%5+1), %3
584 %endmacro
585
586 %define INTERL INTERL_SSE
587
588 DECL_PASS pass_sse, PASS_BIG 1
589 DECL_PASS pass_interleave_sse, PASS_BIG 0
590
591 cglobal fft_calc, 2,5,8
592     mov     r3d, [r0 + FFTContext.nbits]
593     PUSH    r1
594     PUSH    r3
595     mov     r0, r1
596     mov     r1, r3
597     FFT_DISPATCH _interleave %+ SUFFIX, r1
598     POP     rcx
599     POP     r4
600     cmp     rcx, 4
601     jg      .end
602     mov     r2, -1
603     add     rcx, 3
604     shl     r2, cl
605     sub     r4, r2
606 .loop
607     movaps   xmm0, [r4 + r2]
608     movaps   xmm1, xmm0
609     unpcklps xmm0, [r4 + r2 + 16]
610     unpckhps xmm1, [r4 + r2 + 16]
611     movaps   [r4 + r2],      xmm0
612     movaps   [r4 + r2 + 16], xmm1
613     add      r2, 32
614     jl       .loop
615 .end:
616     REP_RET
617
618 cextern_naked memcpy
619
620 cglobal fft_permute, 2,7,1
621     mov     r4,  [r0 + FFTContext.revtab]
622     mov     r5,  [r0 + FFTContext.tmpbuf]
623     mov     ecx, [r0 + FFTContext.nbits]
624     mov     r2, 1
625     shl     r2, cl
626     xor     r0, r0
627 %if ARCH_X86_32
628     mov     r1, r1m
629 %endif
630 .loop:
631     movaps  xmm0, [r1 + 8*r0]
632     movzx   r6, word [r4 + 2*r0]
633     movzx   r3, word [r4 + 2*r0 + 2]
634     movlps  [r5 + 8*r6], xmm0
635     movhps  [r5 + 8*r3], xmm0
636     add     r0, 2
637     cmp     r0, r2
638     jl      .loop
639     shl     r2, 3
640 %if ARCH_X86_64
641     mov     r0, r1
642     mov     r1, r5
643 %else
644     push    r2
645     push    r5
646     push    r1
647 %endif
648 %if ARCH_X86_64 && WIN64 == 0
649     jmp     memcpy
650 %else
651     call    memcpy
652 %if ARCH_X86_32
653     add     esp, 12
654 %endif
655     REP_RET
656 %endif
657
658 cglobal imdct_calc, 3,5,3
659     mov     r3d, [r0 + FFTContext.mdctsize]
660     mov     r4,  [r0 + FFTContext.imdcthalf]
661     add     r1,  r3
662     PUSH    r3
663     PUSH    r1
664 %if ARCH_X86_32
665     push    r2
666     push    r1
667     push    r0
668 %else
669     sub     rsp, 8
670 %endif
671     call    r4
672 %if ARCH_X86_32
673     add     esp, 12
674 %else
675     add     rsp, 8
676 %endif
677     POP     r1
678     POP     r3
679     lea     r0, [r1 + 2*r3]
680     mov     r2, r3
681     sub     r3, 16
682     neg     r2
683     movaps  xmm2, [ps_m1m1m1m1]
684 .loop:
685     movaps  xmm0, [r1 + r3]
686     movaps  xmm1, [r0 + r2]
687     shufps  xmm0, xmm0, 0x1b
688     shufps  xmm1, xmm1, 0x1b
689     xorps   xmm0, xmm2
690     movaps  [r0 + r3], xmm1
691     movaps  [r1 + r2], xmm0
692     sub     r3, 16
693     add     r2, 16
694     jl      .loop
695     REP_RET
696
697 INIT_MMX 3dnow
698 %define mulps pfmul
699 %define addps pfadd
700 %define subps pfsub
701 %define unpcklps punpckldq
702 %define unpckhps punpckhdq
703 DECL_PASS pass_3dnow, PASS_SMALL 1, [wq], [wq+o1q]
704 DECL_PASS pass_interleave_3dnow, PASS_BIG 0
705 %define pass_3dnow2 pass_3dnow
706 %define pass_interleave_3dnow2 pass_interleave_3dnow
707
708 %ifdef PIC
709 %define SECTION_REL - $$
710 %else
711 %define SECTION_REL
712 %endif
713
714 %macro DECL_FFT 1-2 ; nbits, suffix
715 %ifidn %0, 1
716 %xdefine fullsuffix SUFFIX
717 %else
718 %xdefine fullsuffix %2 %+ SUFFIX
719 %endif
720 %xdefine list_of_fft fft4 %+ SUFFIX SECTION_REL, fft8 %+ SUFFIX SECTION_REL
721 %if %1>=5
722 %xdefine list_of_fft list_of_fft, fft16 %+ SUFFIX SECTION_REL
723 %endif
724 %if %1>=6
725 %xdefine list_of_fft list_of_fft, fft32 %+ fullsuffix SECTION_REL
726 %endif
727
728 %assign n 1<<%1
729 %rep 17-%1
730 %assign n2 n/2
731 %assign n4 n/4
732 %xdefine list_of_fft list_of_fft, fft %+ n %+ fullsuffix SECTION_REL
733
734 align 16
735 fft %+ n %+ fullsuffix:
736     call fft %+ n2 %+ SUFFIX
737     add r0, n*4 - (n&(-2<<%1))
738     call fft %+ n4 %+ SUFFIX
739     add r0, n*2 - (n2&(-2<<%1))
740     call fft %+ n4 %+ SUFFIX
741     sub r0, n*6 + (n2&(-2<<%1))
742     lea r1, [cos_ %+ n]
743     mov r2d, n4/2
744     jmp pass %+ fullsuffix
745
746 %assign n n*2
747 %endrep
748 %undef n
749
750 align 8
751 dispatch_tab %+ fullsuffix: pointer list_of_fft
752
753 section .text
754
755 ; On x86_32, this function does the register saving and restoring for all of fft.
756 ; The others pass args in registers and don't spill anything.
757 cglobal fft_dispatch%2, 2,5,8, z, nbits
758     FFT_DISPATCH fullsuffix, nbits
759 %if mmsize == 32
760     vzeroupper
761 %endif
762     RET
763 %endmacro ; DECL_FFT
764
765 %if HAVE_AVX
766 INIT_YMM avx
767 DECL_FFT 6
768 DECL_FFT 6, _interleave
769 %endif
770 INIT_XMM sse
771 DECL_FFT 5
772 DECL_FFT 5, _interleave
773 INIT_MMX 3dnow
774 DECL_FFT 4
775 DECL_FFT 4, _interleave
776 INIT_MMX 3dnow2
777 DECL_FFT 4
778 DECL_FFT 4, _interleave
779
780 INIT_XMM sse
781 %undef mulps
782 %undef addps
783 %undef subps
784 %undef unpcklps
785 %undef unpckhps
786
787 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
788     movaps   xmm0, [%3+%2*4]
789     movaps   xmm1, [%3+%1*4-0x10]
790     movaps   xmm2, xmm0
791     shufps   xmm0, xmm1, 0x88
792     shufps   xmm1, xmm2, 0x77
793     movlps   xmm4, [%4+%2*2]
794     movlps   xmm5, [%5+%2*2+0x0]
795     movhps   xmm4, [%4+%1*2-0x8]
796     movhps   xmm5, [%5+%1*2-0x8]
797     movaps   xmm2, xmm0
798     movaps   xmm3, xmm1
799     mulps    xmm0, xmm5
800     mulps    xmm1, xmm4
801     mulps    xmm2, xmm4
802     mulps    xmm3, xmm5
803     subps    xmm1, xmm0
804     addps    xmm2, xmm3
805     movaps   xmm0, xmm1
806     unpcklps xmm1, xmm2
807     unpckhps xmm0, xmm2
808 %endmacro
809
810 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
811     mulps      m6, %3, [%5+%1]
812     mulps      m7, %2, [%5+%1]
813     mulps      %2, %2, [%6+%1]
814     mulps      %3, %3, [%6+%1]
815     subps      %2, %2, m6
816     addps      %3, %3, m7
817 %endmacro
818
819 %macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8
820 .post:
821     vmovaps      ymm1,   [%3+%1*2]
822     vmovaps      ymm0,   [%3+%1*2+0x20]
823     vmovaps      ymm3,   [%3+%2*2]
824     vmovaps      ymm2,   [%3+%2*2+0x20]
825
826     CMUL         %1, ymm0, ymm1, %3, %4, %5
827     CMUL         %2, ymm2, ymm3, %3, %4, %5
828     vshufps      ymm1, ymm1, ymm1, 0x1b
829     vshufps      ymm3, ymm3, ymm3, 0x1b
830     vperm2f128   ymm1, ymm1, ymm1, 0x01
831     vperm2f128   ymm3, ymm3, ymm3, 0x01
832     vunpcklps    ymm6, ymm2, ymm1
833     vunpckhps    ymm4, ymm2, ymm1
834     vunpcklps    ymm7, ymm0, ymm3
835     vunpckhps    ymm5, ymm0, ymm3
836
837     vextractf128 [%3+%1*2],      ymm7, 0
838     vextractf128 [%3+%1*2+0x10], ymm5, 0
839     vextractf128 [%3+%1*2+0x20], ymm7, 1
840     vextractf128 [%3+%1*2+0x30], ymm5, 1
841
842     vextractf128 [%3+%2*2],      ymm6, 0
843     vextractf128 [%3+%2*2+0x10], ymm4, 0
844     vextractf128 [%3+%2*2+0x20], ymm6, 1
845     vextractf128 [%3+%2*2+0x30], ymm4, 1
846     sub      %2,   0x20
847     add      %1,   0x20
848     jl       .post
849 %endmacro
850
851 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
852 .post:
853     movaps   xmm1, [%3+%1*2]
854     movaps   xmm0, [%3+%1*2+0x10]
855     CMUL     %1,   xmm0, xmm1, %3, %4, %5
856     movaps   xmm5, [%3+%2*2]
857     movaps   xmm4, [%3+%2*2+0x10]
858     CMUL     %2,   xmm4, xmm5, %3, %4, %5
859     shufps   xmm1, xmm1, 0x1b
860     shufps   xmm5, xmm5, 0x1b
861     movaps   xmm6, xmm4
862     unpckhps xmm4, xmm1
863     unpcklps xmm6, xmm1
864     movaps   xmm2, xmm0
865     unpcklps xmm0, xmm5
866     unpckhps xmm2, xmm5
867     movaps   [%3+%2*2],      xmm6
868     movaps   [%3+%2*2+0x10], xmm4
869     movaps   [%3+%1*2],      xmm0
870     movaps   [%3+%1*2+0x10], xmm2
871     sub      %2,   0x10
872     add      %1,   0x10
873     jl       .post
874 %endmacro
875
876 %macro DECL_IMDCT 1
877 cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *input
878 %if ARCH_X86_64
879 %define rrevtab r7
880 %define rtcos   r8
881 %define rtsin   r9
882 %else
883 %define rrevtab r6
884 %define rtsin   r6
885 %define rtcos   r5
886 %endif
887     mov   r3d, [r0+FFTContext.mdctsize]
888     add   r2, r3
889     shr   r3, 1
890     mov   rtcos, [r0+FFTContext.tcos]
891     mov   rtsin, [r0+FFTContext.tsin]
892     add   rtcos, r3
893     add   rtsin, r3
894 %if ARCH_X86_64 == 0
895     push  rtcos
896     push  rtsin
897 %endif
898     shr   r3, 1
899     mov   rrevtab, [r0+FFTContext.revtab]
900     add   rrevtab, r3
901 %if ARCH_X86_64 == 0
902     push  rrevtab
903 %endif
904
905     sub   r3, 4
906 %if ARCH_X86_64
907     xor   r4, r4
908     sub   r4, r3
909 %endif
910 .pre:
911 %if ARCH_X86_64 == 0
912 ;unspill
913     xor   r4, r4
914     sub   r4, r3
915     mov   rtsin, [esp+4]
916     mov   rtcos, [esp+8]
917 %endif
918
919     PREROTATER r4, r3, r2, rtcos, rtsin
920 %if ARCH_X86_64
921     movzx  r5,  word [rrevtab+r4-4]
922     movzx  r6,  word [rrevtab+r4-2]
923     movzx  r10, word [rrevtab+r3]
924     movzx  r11, word [rrevtab+r3+2]
925     movlps [r1+r5 *8], xmm0
926     movhps [r1+r6 *8], xmm0
927     movlps [r1+r10*8], xmm1
928     movhps [r1+r11*8], xmm1
929     add    r4, 4
930 %else
931     mov    r6, [esp]
932     movzx  r5, word [r6+r4-4]
933     movzx  r4, word [r6+r4-2]
934     movlps [r1+r5*8], xmm0
935     movhps [r1+r4*8], xmm0
936     movzx  r5, word [r6+r3]
937     movzx  r4, word [r6+r3+2]
938     movlps [r1+r5*8], xmm1
939     movhps [r1+r4*8], xmm1
940 %endif
941     sub    r3, 4
942     jns    .pre
943
944     mov  r5, r0
945     mov  r6, r1
946     mov  r0, r1
947     mov  r1d, [r5+FFTContext.nbits]
948
949     FFT_DISPATCH SUFFIX, r1
950
951     mov  r0d, [r5+FFTContext.mdctsize]
952     add  r6, r0
953     shr  r0, 1
954 %if ARCH_X86_64 == 0
955 %define rtcos r2
956 %define rtsin r3
957     mov  rtcos, [esp+8]
958     mov  rtsin, [esp+4]
959 %endif
960     neg  r0
961     mov  r1, -mmsize
962     sub  r1, r0
963     %1 r0, r1, r6, rtcos, rtsin
964 %if ARCH_X86_64 == 0
965     add esp, 12
966 %endif
967 %if mmsize == 32
968     vzeroupper
969 %endif
970     RET
971 %endmacro
972
973 DECL_IMDCT POSROTATESHUF
974
975 INIT_YMM avx
976
977 %if HAVE_AVX
978 DECL_IMDCT POSROTATESHUF_AVX
979 %endif