ea78396e7c91d8f8dd21fa7e605f0dd4425241f3
[ffmpeg.git] / libavcodec / x86 / fft_mmx.asm
1 ;******************************************************************************
2 ;* FFT transform with SSE/3DNow optimizations
3 ;* Copyright (c) 2008 Loren Merritt
4 ;*
5 ;* This file is part of FFmpeg.
6 ;*
7 ;* FFmpeg is free software; you can redistribute it and/or
8 ;* modify it under the terms of the GNU Lesser General Public
9 ;* License as published by the Free Software Foundation; either
10 ;* version 2.1 of the License, or (at your option) any later version.
11 ;*
12 ;* FFmpeg is distributed in the hope that it will be useful,
13 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;* Lesser General Public License for more details.
16 ;*
17 ;* You should have received a copy of the GNU Lesser General Public
18 ;* License along with FFmpeg; if not, write to the Free Software
19 ;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 ;******************************************************************************
21
22 ; These functions are not individually interchangeable with the C versions.
23 ; While C takes arrays of FFTComplex, SSE/3DNow leave intermediate results
24 ; in blocks as conventient to the vector size.
25 ; i.e. {4x real, 4x imaginary, 4x real, ...} (or 2x respectively)
26
27 %include "x86inc.asm"
28
29 SECTION_RODATA
30
31 %define M_SQRT1_2 0.70710678118654752440
32 ps_root2: times 4 dd M_SQRT1_2
33 ps_root2mppm: dd -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2
34 ps_m1p1: dd 1<<31, 0
35
36 %assign i 16
37 %rep 13
38 cextern cos_ %+ i
39 %assign i i<<1
40 %endrep
41
42 %ifdef ARCH_X86_64
43     %define pointer dq
44 %else
45     %define pointer dd
46 %endif
47
48 %macro IF0 1+
49 %endmacro
50 %macro IF1 1+
51     %1
52 %endmacro
53
54 section .text align=16
55
56 %macro T2_3DN 4 ; z0, z1, mem0, mem1
57     mova     %1, %3
58     mova     %2, %1
59     pfadd    %1, %4
60     pfsub    %2, %4
61 %endmacro
62
63 %macro T4_3DN 6 ; z0, z1, z2, z3, tmp0, tmp1
64     mova     %5, %3
65     pfsub    %3, %4
66     pfadd    %5, %4 ; {t6,t5}
67     pxor     %3, [ps_m1p1] ; {t8,t7}
68     mova     %6, %1
69     pswapd   %3, %3
70     pfadd    %1, %5 ; {r0,i0}
71     pfsub    %6, %5 ; {r2,i2}
72     mova     %4, %2
73     pfadd    %2, %3 ; {r1,i1}
74     pfsub    %4, %3 ; {r3,i3}
75     SWAP     %3, %6
76 %endmacro
77
78 ; in:  %1={r0,i0,r1,i1} %2={r2,i2,r3,i3}
79 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3}
80 %macro T4_SSE 3
81     mova     %3, %1
82     shufps   %1, %2, 0x64 ; {r0,i0,r3,i2}
83     shufps   %3, %2, 0xce ; {r1,i1,r2,i3}
84     mova     %2, %1
85     addps    %1, %3       ; {t1,t2,t6,t5}
86     subps    %2, %3       ; {t3,t4,t8,t7}
87     mova     %3, %1
88     shufps   %1, %2, 0x44 ; {t1,t2,t3,t4}
89     shufps   %3, %2, 0xbe ; {t6,t5,t7,t8}
90     mova     %2, %1
91     addps    %1, %3       ; {r0,i0,r1,i1}
92     subps    %2, %3       ; {r2,i2,r3,i3}
93     mova     %3, %1
94     shufps   %1, %2, 0x88 ; {r0,r1,r2,r3}
95     shufps   %3, %2, 0xdd ; {i0,i1,i2,i3}
96     SWAP     %2, %3
97 %endmacro
98
99 %macro T8_SSE 6 ; r0,i0,r1,i1,t0,t1
100     mova     %5, %3
101     shufps   %3, %4, 0x44 ; {r4,i4,r6,i6}
102     shufps   %5, %4, 0xee ; {r5,i5,r7,i7}
103     mova     %6, %3
104     subps    %3, %5       ; {r5,i5,r7,i7}
105     addps    %6, %5       ; {t1,t2,t3,t4}
106     mova     %5, %3
107     shufps   %5, %5, 0xb1 ; {i5,r5,i7,r7}
108     mulps    %3, [ps_root2mppm] ; {-r5,i5,r7,-i7}
109     mulps    %5, [ps_root2]
110     addps    %3, %5       ; {t8,t7,ta,t9}
111     mova     %5, %6
112     shufps   %6, %3, 0x36 ; {t3,t2,t9,t8}
113     shufps   %5, %3, 0x9c ; {t1,t4,t7,ta}
114     mova     %3, %6
115     addps    %6, %5       ; {t1,t2,t9,ta}
116     subps    %3, %5       ; {t6,t5,tc,tb}
117     mova     %5, %6
118     shufps   %6, %3, 0xd8 ; {t1,t9,t5,tb}
119     shufps   %5, %3, 0x8d ; {t2,ta,t6,tc}
120     mova     %3, %1
121     mova     %4, %2
122     addps    %1, %6       ; {r0,r1,r2,r3}
123     addps    %2, %5       ; {i0,i1,i2,i3}
124     subps    %3, %6       ; {r4,r5,r6,r7}
125     subps    %4, %5       ; {i4,i5,i6,i7}
126 %endmacro
127
128 ; scheduled for cpu-bound sizes
129 %macro PASS_SMALL 3 ; (to load m4-m7), wre, wim
130 IF%1 mova    m4, Z(4)
131 IF%1 mova    m5, Z(5)
132     mova     m0, %2 ; wre
133     mova     m2, m4
134     mova     m1, %3 ; wim
135     mova     m3, m5
136     mulps    m2, m0 ; r2*wre
137 IF%1 mova    m6, Z(6)
138     mulps    m3, m1 ; i2*wim
139 IF%1 mova    m7, Z(7)
140     mulps    m4, m1 ; r2*wim
141     mulps    m5, m0 ; i2*wre
142     addps    m2, m3 ; r2*wre + i2*wim
143     mova     m3, m1
144     mulps    m1, m6 ; r3*wim
145     subps    m5, m4 ; i2*wre - r2*wim
146     mova     m4, m0
147     mulps    m3, m7 ; i3*wim
148     mulps    m4, m6 ; r3*wre
149     mulps    m0, m7 ; i3*wre
150     subps    m4, m3 ; r3*wre - i3*wim
151     mova     m3, Z(0)
152     addps    m0, m1 ; i3*wre + r3*wim
153     mova     m1, m4
154     addps    m4, m2 ; t5
155     subps    m1, m2 ; t3
156     subps    m3, m4 ; r2
157     addps    m4, Z(0) ; r0
158     mova     m6, Z(2)
159     mova   Z(4), m3
160     mova   Z(0), m4
161     mova     m3, m5
162     subps    m5, m0 ; t4
163     mova     m4, m6
164     subps    m6, m5 ; r3
165     addps    m5, m4 ; r1
166     mova   Z(6), m6
167     mova   Z(2), m5
168     mova     m2, Z(3)
169     addps    m3, m0 ; t6
170     subps    m2, m1 ; i3
171     mova     m7, Z(1)
172     addps    m1, Z(3) ; i1
173     mova   Z(7), m2
174     mova   Z(3), m1
175     mova     m4, m7
176     subps    m7, m3 ; i2
177     addps    m3, m4 ; i0
178     mova   Z(5), m7
179     mova   Z(1), m3
180 %endmacro
181
182 ; scheduled to avoid store->load aliasing
183 %macro PASS_BIG 1 ; (!interleave)
184     mova     m4, Z(4) ; r2
185     mova     m5, Z(5) ; i2
186     mova     m2, m4
187     mova     m0, [wq] ; wre
188     mova     m3, m5
189     mova     m1, [wq+o1q] ; wim
190     mulps    m2, m0 ; r2*wre
191     mova     m6, Z(6) ; r3
192     mulps    m3, m1 ; i2*wim
193     mova     m7, Z(7) ; i3
194     mulps    m4, m1 ; r2*wim
195     mulps    m5, m0 ; i2*wre
196     addps    m2, m3 ; r2*wre + i2*wim
197     mova     m3, m1
198     mulps    m1, m6 ; r3*wim
199     subps    m5, m4 ; i2*wre - r2*wim
200     mova     m4, m0
201     mulps    m3, m7 ; i3*wim
202     mulps    m4, m6 ; r3*wre
203     mulps    m0, m7 ; i3*wre
204     subps    m4, m3 ; r3*wre - i3*wim
205     mova     m3, Z(0)
206     addps    m0, m1 ; i3*wre + r3*wim
207     mova     m1, m4
208     addps    m4, m2 ; t5
209     subps    m1, m2 ; t3
210     subps    m3, m4 ; r2
211     addps    m4, Z(0) ; r0
212     mova     m6, Z(2)
213     mova   Z(4), m3
214     mova   Z(0), m4
215     mova     m3, m5
216     subps    m5, m0 ; t4
217     mova     m4, m6
218     subps    m6, m5 ; r3
219     addps    m5, m4 ; r1
220 IF%1 mova  Z(6), m6
221 IF%1 mova  Z(2), m5
222     mova     m2, Z(3)
223     addps    m3, m0 ; t6
224     subps    m2, m1 ; i3
225     mova     m7, Z(1)
226     addps    m1, Z(3) ; i1
227 IF%1 mova  Z(7), m2
228 IF%1 mova  Z(3), m1
229     mova     m4, m7
230     subps    m7, m3 ; i2
231     addps    m3, m4 ; i0
232 IF%1 mova  Z(5), m7
233 IF%1 mova  Z(1), m3
234 %if %1==0
235     mova     m4, m5 ; r1
236     mova     m0, m6 ; r3
237     unpcklps m5, m1
238     unpckhps m4, m1
239     unpcklps m6, m2
240     unpckhps m0, m2
241     mova     m1, Z(0)
242     mova     m2, Z(4)
243     mova   Z(2), m5
244     mova   Z(3), m4
245     mova   Z(6), m6
246     mova   Z(7), m0
247     mova     m5, m1 ; r0
248     mova     m4, m2 ; r2
249     unpcklps m1, m3
250     unpckhps m5, m3
251     unpcklps m2, m7
252     unpckhps m4, m7
253     mova   Z(0), m1
254     mova   Z(1), m5
255     mova   Z(4), m2
256     mova   Z(5), m4
257 %endif
258 %endmacro
259
260 %macro PUNPCK 3
261     mova      %3, %1
262     punpckldq %1, %2
263     punpckhdq %3, %2
264 %endmacro
265
266 INIT_XMM
267 %define mova movaps
268
269 %define Z(x) [r0+mmsize*x]
270
271 align 16
272 fft4_sse:
273     mova     m0, Z(0)
274     mova     m1, Z(1)
275     T4_SSE   m0, m1, m2
276     mova   Z(0), m0
277     mova   Z(1), m1
278     ret
279
280 align 16
281 fft8_sse:
282     mova     m0, Z(0)
283     mova     m1, Z(1)
284     T4_SSE   m0, m1, m2
285     mova     m2, Z(2)
286     mova     m3, Z(3)
287     T8_SSE   m0, m1, m2, m3, m4, m5
288     mova   Z(0), m0
289     mova   Z(1), m1
290     mova   Z(2), m2
291     mova   Z(3), m3
292     ret
293
294 align 16
295 fft16_sse:
296     mova     m0, Z(0)
297     mova     m1, Z(1)
298     T4_SSE   m0, m1, m2
299     mova     m2, Z(2)
300     mova     m3, Z(3)
301     T8_SSE   m0, m1, m2, m3, m4, m5
302     mova     m4, Z(4)
303     mova     m5, Z(5)
304     mova   Z(0), m0
305     mova   Z(1), m1
306     mova   Z(2), m2
307     mova   Z(3), m3
308     T4_SSE   m4, m5, m6
309     mova     m6, Z(6)
310     mova     m7, Z(7)
311     T4_SSE   m6, m7, m0
312     PASS_SMALL 0, [cos_16], [cos_16+16]
313     ret
314
315
316 INIT_MMX
317
318 %macro FFT48_3DN 1
319 align 16
320 fft4%1:
321     T2_3DN   m0, m1, Z(0), Z(1)
322     mova     m2, Z(2)
323     mova     m3, Z(3)
324     T4_3DN   m0, m1, m2, m3, m4, m5
325     PUNPCK   m0, m1, m4
326     PUNPCK   m2, m3, m5
327     mova   Z(0), m0
328     mova   Z(1), m4
329     mova   Z(2), m2
330     mova   Z(3), m5
331     ret
332
333 align 16
334 fft8%1:
335     T2_3DN   m0, m1, Z(0), Z(1)
336     mova     m2, Z(2)
337     mova     m3, Z(3)
338     T4_3DN   m0, m1, m2, m3, m4, m5
339     mova   Z(0), m0
340     mova   Z(2), m2
341     T2_3DN   m4, m5, Z(4), Z(5)
342     T2_3DN   m6, m7, Z(6), Z(7)
343     pswapd   m0, m5
344     pswapd   m2, m7
345     pxor     m0, [ps_m1p1]
346     pxor     m2, [ps_m1p1]
347     pfsub    m5, m0
348     pfadd    m7, m2
349     pfmul    m5, [ps_root2]
350     pfmul    m7, [ps_root2]
351     T4_3DN   m1, m3, m5, m7, m0, m2
352     mova   Z(5), m5
353     mova   Z(7), m7
354     mova     m0, Z(0)
355     mova     m2, Z(2)
356     T4_3DN   m0, m2, m4, m6, m5, m7
357     PUNPCK   m0, m1, m5
358     PUNPCK   m2, m3, m7
359     mova   Z(0), m0
360     mova   Z(1), m5
361     mova   Z(2), m2
362     mova   Z(3), m7
363     PUNPCK   m4, Z(5), m5
364     PUNPCK   m6, Z(7), m7
365     mova   Z(4), m4
366     mova   Z(5), m5
367     mova   Z(6), m6
368     mova   Z(7), m7
369     ret
370 %endmacro
371
372 FFT48_3DN _3dn2
373
374 %macro pswapd 2
375 %ifidn %1, %2
376     movd [r0+12], %1
377     punpckhdq %1, [r0+8]
378 %else
379     movq  %1, %2
380     psrlq %1, 32
381     punpckldq %1, %2
382 %endif
383 %endmacro
384
385 FFT48_3DN _3dn
386
387
388 %define Z(x) [zq + o1q*(x&6)*((x/6)^1) + o3q*(x/6) + mmsize*(x&1)]
389
390 %macro DECL_PASS 2+ ; name, payload
391 align 16
392 %1:
393 DEFINE_ARGS z, w, n, o1, o3
394     lea o3q, [nq*3]
395     lea o1q, [nq*8]
396     shl o3q, 4
397 .loop:
398     %2
399     add zq, mmsize*2
400     add wq, mmsize
401     sub nd, mmsize/8
402     jg .loop
403     rep ret
404 %endmacro
405
406 INIT_XMM
407 %define mova movaps
408 DECL_PASS pass_sse, PASS_BIG 1
409 DECL_PASS pass_interleave_sse, PASS_BIG 0
410
411 INIT_MMX
412 %define mulps pfmul
413 %define addps pfadd
414 %define subps pfsub
415 %define unpcklps punpckldq
416 %define unpckhps punpckhdq
417 DECL_PASS pass_3dn, PASS_SMALL 1, [wq], [wq+o1q]
418 DECL_PASS pass_interleave_3dn, PASS_BIG 0
419 %define pass_3dn2 pass_3dn
420 %define pass_interleave_3dn2 pass_interleave_3dn
421
422 %ifdef PIC
423 %define SECTION_REL - $$
424 %else
425 %define SECTION_REL
426 %endif
427
428 %macro DECL_FFT 2-3 ; nbits, cpu, suffix
429 %xdefine list_of_fft fft4%2 SECTION_REL, fft8%2 SECTION_REL
430 %if %1==5
431 %xdefine list_of_fft list_of_fft, fft16%2 SECTION_REL
432 %endif
433
434 %assign n 1<<%1
435 %rep 17-%1
436 %assign n2 n/2
437 %assign n4 n/4
438 %xdefine list_of_fft list_of_fft, fft %+ n %+ %3%2 SECTION_REL
439
440 align 16
441 fft %+ n %+ %3%2:
442     call fft %+ n2 %+ %2
443     add r0, n*4 - (n&(-2<<%1))
444     call fft %+ n4 %+ %2
445     add r0, n*2 - (n2&(-2<<%1))
446     call fft %+ n4 %+ %2
447     sub r0, n*6 + (n2&(-2<<%1))
448     lea r1, [cos_ %+ n]
449     mov r2d, n4/2
450     jmp pass%3%2
451
452 %assign n n*2
453 %endrep
454 %undef n
455
456 align 8
457 dispatch_tab%3%2: pointer list_of_fft
458
459 section .text
460
461 ; On x86_32, this function does the register saving and restoring for all of fft.
462 ; The others pass args in registers and don't spill anything.
463 cglobal fft_dispatch%3%2, 2,5,8, z, nbits
464     lea r2, [dispatch_tab%3%2]
465     mov r2, [r2 + (nbitsq-2)*gprsize]
466 %ifdef PIC
467     lea r3, [$$]
468     add r2, r3
469 %endif
470     call r2
471     RET
472 %endmacro ; DECL_FFT
473
474 DECL_FFT 5, _sse
475 DECL_FFT 5, _sse, _interleave
476 DECL_FFT 4, _3dn
477 DECL_FFT 4, _3dn, _interleave
478 DECL_FFT 4, _3dn2
479 DECL_FFT 4, _3dn2, _interleave
480