]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/fft_mmx.asm
fft: init functions with INIT_XMM/YMM.
[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 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 %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 %endif
392
393 INIT_XMM
394 %define movdqa  movaps
395
396 align 16
397 fft4_avx:
398 fft4_sse:
399     mova     m0, Z(0)
400     mova     m1, Z(1)
401     T4_SSE   m0, m1, m2
402     mova   Z(0), m0
403     mova   Z(1), m1
404     ret
405
406 align 16
407 fft8_sse:
408     mova     m0, Z(0)
409     mova     m1, Z(1)
410     T4_SSE   m0, m1, m2
411     mova     m2, Z(2)
412     mova     m3, Z(3)
413     T8_SSE   m0, m1, m2, m3, m4, m5
414     mova   Z(0), m0
415     mova   Z(1), m1
416     mova   Z(2), m2
417     mova   Z(3), m3
418     ret
419
420 align 16
421 fft16_sse:
422     mova     m0, Z(0)
423     mova     m1, Z(1)
424     T4_SSE   m0, m1, m2
425     mova     m2, Z(2)
426     mova     m3, Z(3)
427     T8_SSE   m0, m1, m2, m3, m4, m5
428     mova     m4, Z(4)
429     mova     m5, Z(5)
430     mova   Z(0), m0
431     mova   Z(1), m1
432     mova   Z(2), m2
433     mova   Z(3), m3
434     T4_SSE   m4, m5, m6
435     mova     m6, Z2(6)
436     mova     m7, Z2(7)
437     T4_SSE   m6, m7, m0
438     PASS_SMALL 0, [cos_16], [cos_16+16]
439     ret
440
441
442 INIT_MMX
443
444 %macro FFT48_3DN 1
445 align 16
446 fft4%1:
447     T2_3DN   m0, m1, Z(0), Z(1)
448     mova     m2, Z(2)
449     mova     m3, Z(3)
450     T4_3DN   m0, m1, m2, m3, m4, m5
451     PUNPCK   m0, m1, m4
452     PUNPCK   m2, m3, m5
453     mova   Z(0), m0
454     mova   Z(1), m4
455     mova   Z(2), m2
456     mova   Z(3), m5
457     ret
458
459 align 16
460 fft8%1:
461     T2_3DN   m0, m1, Z(0), Z(1)
462     mova     m2, Z(2)
463     mova     m3, Z(3)
464     T4_3DN   m0, m1, m2, m3, m4, m5
465     mova   Z(0), m0
466     mova   Z(2), m2
467     T2_3DN   m4, m5,  Z(4),  Z(5)
468     T2_3DN   m6, m7, Z2(6), Z2(7)
469     pswapd   m0, m5
470     pswapd   m2, m7
471     pxor     m0, [ps_m1p1]
472     pxor     m2, [ps_m1p1]
473     pfsub    m5, m0
474     pfadd    m7, m2
475     pfmul    m5, [ps_root2]
476     pfmul    m7, [ps_root2]
477     T4_3DN   m1, m3, m5, m7, m0, m2
478     mova   Z(5), m5
479     mova  Z2(7), m7
480     mova     m0, Z(0)
481     mova     m2, Z(2)
482     T4_3DN   m0, m2, m4, m6, m5, m7
483     PUNPCK   m0, m1, m5
484     PUNPCK   m2, m3, m7
485     mova   Z(0), m0
486     mova   Z(1), m5
487     mova   Z(2), m2
488     mova   Z(3), m7
489     PUNPCK   m4,  Z(5), m5
490     PUNPCK   m6, Z2(7), m7
491     mova   Z(4), m4
492     mova   Z(5), m5
493     mova  Z2(6), m6
494     mova  Z2(7), m7
495     ret
496 %endmacro
497
498 FFT48_3DN _3dn2
499
500 %macro pswapd 2
501 %ifidn %1, %2
502     movd [r0+12], %1
503     punpckhdq %1, [r0+8]
504 %else
505     movq  %1, %2
506     psrlq %1, 32
507     punpckldq %1, %2
508 %endif
509 %endmacro
510
511 FFT48_3DN _3dn
512
513
514 %define Z(x) [zq + o1q*(x&6) + mmsize*(x&1)]
515 %define Z2(x) [zq + o3q + mmsize*(x&1)]
516 %define ZH(x) [zq + o1q*(x&6) + mmsize*(x&1) + mmsize/2]
517 %define Z2H(x) [zq + o3q + mmsize*(x&1) + mmsize/2]
518
519 %macro DECL_PASS 2+ ; name, payload
520 align 16
521 %1:
522 DEFINE_ARGS z, w, n, o1, o3
523     lea o3q, [nq*3]
524     lea o1q, [nq*8]
525     shl o3q, 4
526 .loop:
527     %2
528     add zq, mmsize*2
529     add wq, mmsize
530     sub nd, mmsize/8
531     jg .loop
532     rep ret
533 %endmacro
534
535 INIT_YMM
536
537 %ifdef HAVE_AVX
538 %macro INTERL_AVX 5
539     vunpckhps      %3, %2, %1
540     vunpcklps      %2, %2, %1
541     vextractf128   %4(%5), %2, 0
542     vextractf128  %4 %+ H(%5), %3, 0
543     vextractf128   %4(%5 + 1), %2, 1
544     vextractf128  %4 %+ H(%5 + 1), %3, 1
545 %endmacro
546
547 %define INTERL INTERL_AVX
548
549 DECL_PASS pass_avx, PASS_BIG 1
550 DECL_PASS pass_interleave_avx, PASS_BIG 0
551 %endif
552
553 INIT_XMM
554
555 %macro INTERL_SSE 5
556     mova     %3, %2
557     unpcklps %2, %1
558     unpckhps %3, %1
559     mova  %4(%5), %2
560     mova  %4(%5+1), %3
561 %endmacro
562
563 %define INTERL INTERL_SSE
564
565 DECL_PASS pass_sse, PASS_BIG 1
566 DECL_PASS pass_interleave_sse, PASS_BIG 0
567
568 INIT_MMX
569 %define mulps pfmul
570 %define addps pfadd
571 %define subps pfsub
572 %define unpcklps punpckldq
573 %define unpckhps punpckhdq
574 DECL_PASS pass_3dn, PASS_SMALL 1, [wq], [wq+o1q]
575 DECL_PASS pass_interleave_3dn, PASS_BIG 0
576 %define pass_3dn2 pass_3dn
577 %define pass_interleave_3dn2 pass_interleave_3dn
578
579 %ifdef PIC
580 %define SECTION_REL - $$
581 %else
582 %define SECTION_REL
583 %endif
584
585 %macro FFT_DISPATCH 2; clobbers 5 GPRs, 8 XMMs
586     lea r2, [dispatch_tab%1]
587     mov r2, [r2 + (%2q-2)*gprsize]
588 %ifdef PIC
589     lea r3, [$$]
590     add r2, r3
591 %endif
592     call r2
593 %endmacro ; FFT_DISPATCH
594
595 %macro DECL_FFT 2-3 ; nbits, cpu, suffix
596 %xdefine list_of_fft fft4%2 SECTION_REL, fft8%2 SECTION_REL
597 %if %1>=5
598 %xdefine list_of_fft list_of_fft, fft16%2 SECTION_REL
599 %endif
600 %if %1>=6
601 %xdefine list_of_fft list_of_fft, fft32%3%2 SECTION_REL
602 %endif
603
604 %assign n 1<<%1
605 %rep 17-%1
606 %assign n2 n/2
607 %assign n4 n/4
608 %xdefine list_of_fft list_of_fft, fft %+ n %+ %3%2 SECTION_REL
609
610 align 16
611 fft %+ n %+ %3%2:
612     call fft %+ n2 %+ %2
613     add r0, n*4 - (n&(-2<<%1))
614     call fft %+ n4 %+ %2
615     add r0, n*2 - (n2&(-2<<%1))
616     call fft %+ n4 %+ %2
617     sub r0, n*6 + (n2&(-2<<%1))
618     lea r1, [cos_ %+ n]
619     mov r2d, n4/2
620     jmp pass%3%2
621
622 %assign n n*2
623 %endrep
624 %undef n
625
626 align 8
627 dispatch_tab%3%2: pointer list_of_fft
628
629 section .text
630
631 ; On x86_32, this function does the register saving and restoring for all of fft.
632 ; The others pass args in registers and don't spill anything.
633 cglobal fft_dispatch%3%2, 2,5,8, z, nbits
634     FFT_DISPATCH %3%2, nbits
635 %ifidn %2, _avx
636     vzeroupper
637 %endif
638     RET
639 %endmacro ; DECL_FFT
640
641 %ifdef HAVE_AVX
642 INIT_YMM
643 DECL_FFT 6, _avx
644 DECL_FFT 6, _avx, _interleave
645 %endif
646 INIT_XMM
647 DECL_FFT 5, _sse
648 DECL_FFT 5, _sse, _interleave
649 INIT_MMX
650 DECL_FFT 4, _3dn
651 DECL_FFT 4, _3dn, _interleave
652 DECL_FFT 4, _3dn2
653 DECL_FFT 4, _3dn2, _interleave
654
655 INIT_XMM
656 %undef mulps
657 %undef addps
658 %undef subps
659 %undef unpcklps
660 %undef unpckhps
661
662 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
663     movaps   xmm0, [%3+%2*4]
664     movaps   xmm1, [%3+%1*4-0x10]
665     movaps   xmm2, xmm0
666     shufps   xmm0, xmm1, 0x88
667     shufps   xmm1, xmm2, 0x77
668     movlps   xmm4, [%4+%2*2]
669     movlps   xmm5, [%5+%2*2+0x0]
670     movhps   xmm4, [%4+%1*2-0x8]
671     movhps   xmm5, [%5+%1*2-0x8]
672     movaps   xmm2, xmm0
673     movaps   xmm3, xmm1
674     mulps    xmm0, xmm5
675     mulps    xmm1, xmm4
676     mulps    xmm2, xmm4
677     mulps    xmm3, xmm5
678     subps    xmm1, xmm0
679     addps    xmm2, xmm3
680     movaps   xmm0, xmm1
681     unpcklps xmm1, xmm2
682     unpckhps xmm0, xmm2
683 %endmacro
684
685 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
686     mulps      m6, %3, [%5+%1]
687     mulps      m7, %2, [%5+%1]
688     mulps      %2, %2, [%6+%1]
689     mulps      %3, %3, [%6+%1]
690     subps      %2, %2, m6
691     addps      %3, %3, m7
692 %endmacro
693
694 %macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8
695 .post:
696     vmovaps      ymm1,   [%3+%1*2]
697     vmovaps      ymm0,   [%3+%1*2+0x20]
698     vmovaps      ymm3,   [%3+%2*2]
699     vmovaps      ymm2,   [%3+%2*2+0x20]
700
701     CMUL         %1, ymm0, ymm1, %3, %4, %5
702     CMUL         %2, ymm2, ymm3, %3, %4, %5
703     vshufps      ymm1, ymm1, ymm1, 0x1b
704     vshufps      ymm3, ymm3, ymm3, 0x1b
705     vperm2f128   ymm1, ymm1, ymm1, 0x01
706     vperm2f128   ymm3, ymm3, ymm3, 0x01
707     vunpcklps    ymm6, ymm2, ymm1
708     vunpckhps    ymm4, ymm2, ymm1
709     vunpcklps    ymm7, ymm0, ymm3
710     vunpckhps    ymm5, ymm0, ymm3
711
712     vextractf128 [%3+%1*2],      ymm7, 0
713     vextractf128 [%3+%1*2+0x10], ymm5, 0
714     vextractf128 [%3+%1*2+0x20], ymm7, 1
715     vextractf128 [%3+%1*2+0x30], ymm5, 1
716
717     vextractf128 [%3+%2*2],      ymm6, 0
718     vextractf128 [%3+%2*2+0x10], ymm4, 0
719     vextractf128 [%3+%2*2+0x20], ymm6, 1
720     vextractf128 [%3+%2*2+0x30], ymm4, 1
721     sub      %2,   0x20
722     add      %1,   0x20
723     jl       .post
724 %endmacro
725
726 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
727 .post:
728     movaps   xmm1, [%3+%1*2]
729     movaps   xmm0, [%3+%1*2+0x10]
730     CMUL     %1,   xmm0, xmm1, %3, %4, %5
731     movaps   xmm5, [%3+%2*2]
732     movaps   xmm4, [%3+%2*2+0x10]
733     CMUL     %2,   xmm4, xmm5, %3, %4, %5
734     shufps   xmm1, xmm1, 0x1b
735     shufps   xmm5, xmm5, 0x1b
736     movaps   xmm6, xmm4
737     unpckhps xmm4, xmm1
738     unpcklps xmm6, xmm1
739     movaps   xmm2, xmm0
740     unpcklps xmm0, xmm5
741     unpckhps xmm2, xmm5
742     movaps   [%3+%2*2],      xmm6
743     movaps   [%3+%2*2+0x10], xmm4
744     movaps   [%3+%1*2],      xmm0
745     movaps   [%3+%1*2+0x10], xmm2
746     sub      %2,   0x10
747     add      %1,   0x10
748     jl       .post
749 %endmacro
750
751 %macro DECL_IMDCT 2
752 cglobal imdct_half%1, 3,7,8; FFTContext *s, FFTSample *output, const FFTSample *input
753 %ifdef ARCH_X86_64
754 %define rrevtab r10
755 %define rtcos   r11
756 %define rtsin   r12
757     push  r12
758     push  r13
759     push  r14
760 %else
761 %define rrevtab r6
762 %define rtsin   r6
763 %define rtcos   r5
764 %endif
765     mov   r3d, [r0+FFTContext.mdctsize]
766     add   r2, r3
767     shr   r3, 1
768     mov   rtcos, [r0+FFTContext.tcos]
769     mov   rtsin, [r0+FFTContext.tsin]
770     add   rtcos, r3
771     add   rtsin, r3
772 %ifndef ARCH_X86_64
773     push  rtcos
774     push  rtsin
775 %endif
776     shr   r3, 1
777     mov   rrevtab, [r0+FFTContext.revtab]
778     add   rrevtab, r3
779 %ifndef ARCH_X86_64
780     push  rrevtab
781 %endif
782
783     sub   r3, 4
784 %ifdef ARCH_X86_64
785     xor   r4, r4
786     sub   r4, r3
787 %endif
788 .pre:
789 %ifndef ARCH_X86_64
790 ;unspill
791     xor   r4, r4
792     sub   r4, r3
793     mov   rtsin, [esp+4]
794     mov   rtcos, [esp+8]
795 %endif
796
797     PREROTATER r4, r3, r2, rtcos, rtsin
798 %ifdef ARCH_X86_64
799     movzx  r5,  word [rrevtab+r4-4]
800     movzx  r6,  word [rrevtab+r4-2]
801     movzx  r13, word [rrevtab+r3]
802     movzx  r14, word [rrevtab+r3+2]
803     movlps [r1+r5 *8], xmm0
804     movhps [r1+r6 *8], xmm0
805     movlps [r1+r13*8], xmm1
806     movhps [r1+r14*8], xmm1
807     add    r4, 4
808 %else
809     mov    r6, [esp]
810     movzx  r5, word [r6+r4-4]
811     movzx  r4, word [r6+r4-2]
812     movlps [r1+r5*8], xmm0
813     movhps [r1+r4*8], xmm0
814     movzx  r5, word [r6+r3]
815     movzx  r4, word [r6+r3+2]
816     movlps [r1+r5*8], xmm1
817     movhps [r1+r4*8], xmm1
818 %endif
819     sub    r3, 4
820     jns    .pre
821
822     mov  r5, r0
823     mov  r6, r1
824     mov  r0, r1
825     mov  r1d, [r5+FFTContext.nbits]
826
827     FFT_DISPATCH %1, r1
828
829     mov  r0d, [r5+FFTContext.mdctsize]
830     add  r6, r0
831     shr  r0, 1
832 %ifndef ARCH_X86_64
833 %define rtcos r2
834 %define rtsin r3
835     mov  rtcos, [esp+8]
836     mov  rtsin, [esp+4]
837 %endif
838     neg  r0
839     mov  r1, -mmsize
840     sub  r1, r0
841     %2 r0, r1, r6, rtcos, rtsin
842 %ifdef ARCH_X86_64
843     pop  r14
844     pop  r13
845     pop  r12
846 %else
847     add esp, 12
848 %endif
849 %ifidn avx_enabled, 1
850     vzeroupper
851 %endif
852     RET
853 %endmacro
854
855 DECL_IMDCT _sse, POSROTATESHUF
856
857 INIT_YMM
858
859 %ifdef HAVE_AVX
860 DECL_IMDCT _avx, POSROTATESHUF_AVX
861 %endif