Move struc FFTContext below SECTION_RODATA
[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 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 %if ARCH_X86_64
34 %define pointer resq
35 %else
36 %define pointer resd
37 %endif
38
39 SECTION_RODATA
40
41 struc FFTContext
42     .nbits:    resd 1
43     .reverse:  resd 1
44     .revtab:   pointer 1
45     .tmpbuf:   pointer 1
46     .mdctsize: resd 1
47     .mdctbits: resd 1
48     .tcos:     pointer 1
49     .tsin:     pointer 1
50 endstruc
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 %if 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 %if 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 %if 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 %if HAVE_AVX
643 INIT_YMM
644 DECL_FFT 6, _avx
645 DECL_FFT 6, _avx, _interleave
646 %endif
647 INIT_XMM
648 DECL_FFT 5, _sse
649 DECL_FFT 5, _sse, _interleave
650 INIT_MMX
651 DECL_FFT 4, _3dn
652 DECL_FFT 4, _3dn, _interleave
653 DECL_FFT 4, _3dn2
654 DECL_FFT 4, _3dn2, _interleave
655
656 INIT_XMM
657 %undef mulps
658 %undef addps
659 %undef subps
660 %undef unpcklps
661 %undef unpckhps
662
663 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
664     movaps   xmm0, [%3+%2*4]
665     movaps   xmm1, [%3+%1*4-0x10]
666     movaps   xmm2, xmm0
667     shufps   xmm0, xmm1, 0x88
668     shufps   xmm1, xmm2, 0x77
669     movlps   xmm4, [%4+%2*2]
670     movlps   xmm5, [%5+%2*2+0x0]
671     movhps   xmm4, [%4+%1*2-0x8]
672     movhps   xmm5, [%5+%1*2-0x8]
673     movaps   xmm2, xmm0
674     movaps   xmm3, xmm1
675     mulps    xmm0, xmm5
676     mulps    xmm1, xmm4
677     mulps    xmm2, xmm4
678     mulps    xmm3, xmm5
679     subps    xmm1, xmm0
680     addps    xmm2, xmm3
681     movaps   xmm0, xmm1
682     unpcklps xmm1, xmm2
683     unpckhps xmm0, xmm2
684 %endmacro
685
686 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
687     mulps      m6, %3, [%5+%1]
688     mulps      m7, %2, [%5+%1]
689     mulps      %2, %2, [%6+%1]
690     mulps      %3, %3, [%6+%1]
691     subps      %2, %2, m6
692     addps      %3, %3, m7
693 %endmacro
694
695 %macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8
696 .post:
697     vmovaps      ymm1,   [%3+%1*2]
698     vmovaps      ymm0,   [%3+%1*2+0x20]
699     vmovaps      ymm3,   [%3+%2*2]
700     vmovaps      ymm2,   [%3+%2*2+0x20]
701
702     CMUL         %1, ymm0, ymm1, %3, %4, %5
703     CMUL         %2, ymm2, ymm3, %3, %4, %5
704     vshufps      ymm1, ymm1, ymm1, 0x1b
705     vshufps      ymm3, ymm3, ymm3, 0x1b
706     vperm2f128   ymm1, ymm1, ymm1, 0x01
707     vperm2f128   ymm3, ymm3, ymm3, 0x01
708     vunpcklps    ymm6, ymm2, ymm1
709     vunpckhps    ymm4, ymm2, ymm1
710     vunpcklps    ymm7, ymm0, ymm3
711     vunpckhps    ymm5, ymm0, ymm3
712
713     vextractf128 [%3+%1*2],      ymm7, 0
714     vextractf128 [%3+%1*2+0x10], ymm5, 0
715     vextractf128 [%3+%1*2+0x20], ymm7, 1
716     vextractf128 [%3+%1*2+0x30], ymm5, 1
717
718     vextractf128 [%3+%2*2],      ymm6, 0
719     vextractf128 [%3+%2*2+0x10], ymm4, 0
720     vextractf128 [%3+%2*2+0x20], ymm6, 1
721     vextractf128 [%3+%2*2+0x30], ymm4, 1
722     sub      %2,   0x20
723     add      %1,   0x20
724     jl       .post
725 %endmacro
726
727 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
728 .post:
729     movaps   xmm1, [%3+%1*2]
730     movaps   xmm0, [%3+%1*2+0x10]
731     CMUL     %1,   xmm0, xmm1, %3, %4, %5
732     movaps   xmm5, [%3+%2*2]
733     movaps   xmm4, [%3+%2*2+0x10]
734     CMUL     %2,   xmm4, xmm5, %3, %4, %5
735     shufps   xmm1, xmm1, 0x1b
736     shufps   xmm5, xmm5, 0x1b
737     movaps   xmm6, xmm4
738     unpckhps xmm4, xmm1
739     unpcklps xmm6, xmm1
740     movaps   xmm2, xmm0
741     unpcklps xmm0, xmm5
742     unpckhps xmm2, xmm5
743     movaps   [%3+%2*2],      xmm6
744     movaps   [%3+%2*2+0x10], xmm4
745     movaps   [%3+%1*2],      xmm0
746     movaps   [%3+%1*2+0x10], xmm2
747     sub      %2,   0x10
748     add      %1,   0x10
749     jl       .post
750 %endmacro
751
752 %macro DECL_IMDCT 2
753 cglobal imdct_half%1, 3,7,8; FFTContext *s, FFTSample *output, const FFTSample *input
754 %if ARCH_X86_64
755 %define rrevtab r10
756 %define rtcos   r11
757 %define rtsin   r12
758     push  r12
759     push  r13
760     push  r14
761 %else
762 %define rrevtab r6
763 %define rtsin   r6
764 %define rtcos   r5
765 %endif
766     mov   r3d, [r0+FFTContext.mdctsize]
767     add   r2, r3
768     shr   r3, 1
769     mov   rtcos, [r0+FFTContext.tcos]
770     mov   rtsin, [r0+FFTContext.tsin]
771     add   rtcos, r3
772     add   rtsin, r3
773 %if ARCH_X86_64 == 0
774     push  rtcos
775     push  rtsin
776 %endif
777     shr   r3, 1
778     mov   rrevtab, [r0+FFTContext.revtab]
779     add   rrevtab, r3
780 %if ARCH_X86_64 == 0
781     push  rrevtab
782 %endif
783
784     sub   r3, 4
785 %if ARCH_X86_64
786     xor   r4, r4
787     sub   r4, r3
788 %endif
789 .pre:
790 %if ARCH_X86_64 == 0
791 ;unspill
792     xor   r4, r4
793     sub   r4, r3
794     mov   rtsin, [esp+4]
795     mov   rtcos, [esp+8]
796 %endif
797
798     PREROTATER r4, r3, r2, rtcos, rtsin
799 %if ARCH_X86_64
800     movzx  r5,  word [rrevtab+r4-4]
801     movzx  r6,  word [rrevtab+r4-2]
802     movzx  r13, word [rrevtab+r3]
803     movzx  r14, word [rrevtab+r3+2]
804     movlps [r1+r5 *8], xmm0
805     movhps [r1+r6 *8], xmm0
806     movlps [r1+r13*8], xmm1
807     movhps [r1+r14*8], xmm1
808     add    r4, 4
809 %else
810     mov    r6, [esp]
811     movzx  r5, word [r6+r4-4]
812     movzx  r4, word [r6+r4-2]
813     movlps [r1+r5*8], xmm0
814     movhps [r1+r4*8], xmm0
815     movzx  r5, word [r6+r3]
816     movzx  r4, word [r6+r3+2]
817     movlps [r1+r5*8], xmm1
818     movhps [r1+r4*8], xmm1
819 %endif
820     sub    r3, 4
821     jns    .pre
822
823     mov  r5, r0
824     mov  r6, r1
825     mov  r0, r1
826     mov  r1d, [r5+FFTContext.nbits]
827
828     FFT_DISPATCH %1, r1
829
830     mov  r0d, [r5+FFTContext.mdctsize]
831     add  r6, r0
832     shr  r0, 1
833 %if ARCH_X86_64 == 0
834 %define rtcos r2
835 %define rtsin r3
836     mov  rtcos, [esp+8]
837     mov  rtsin, [esp+4]
838 %endif
839     neg  r0
840     mov  r1, -mmsize
841     sub  r1, r0
842     %2 r0, r1, r6, rtcos, rtsin
843 %if ARCH_X86_64
844     pop  r14
845     pop  r13
846     pop  r12
847 %else
848     add esp, 12
849 %endif
850 %ifidn avx_enabled, 1
851     vzeroupper
852 %endif
853     RET
854 %endmacro
855
856 DECL_IMDCT _sse, POSROTATESHUF
857
858 INIT_YMM
859
860 %if HAVE_AVX
861 DECL_IMDCT _avx, POSROTATESHUF_AVX
862 %endif