lavr: add x86-optimized mixing functions
[ffmpeg.git] / libavresample / x86 / audio_mix.asm
1 ;******************************************************************************
2 ;* x86 optimized channel mixing
3 ;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4 ;*
5 ;* This file is part of Libav.
6 ;*
7 ;* Libav 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 ;* Libav 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 Libav; if not, write to the Free Software
19 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 ;******************************************************************************
21
22 %include "x86inc.asm"
23 %include "x86util.asm"
24 %include "util.asm"
25
26 SECTION_TEXT
27
28 ;-----------------------------------------------------------------------------
29 ; void ff_mix_2_to_1_fltp_flt(float **src, float **matrix, int len,
30 ;                             int out_ch, int in_ch);
31 ;-----------------------------------------------------------------------------
32
33 %macro MIX_2_TO_1_FLTP_FLT 0
34 cglobal mix_2_to_1_fltp_flt, 3,4,6, src, matrix, len, src1
35     mov       src1q, [srcq+gprsize]
36     mov        srcq, [srcq        ]
37     sub       src1q, srcq
38     mov     matrixq, [matrixq  ]
39     VBROADCASTSS m4, [matrixq  ]
40     VBROADCASTSS m5, [matrixq+4]
41     ALIGN 16
42 .loop:
43     mulps        m0, m4, [srcq             ]
44     mulps        m1, m5, [srcq+src1q       ]
45     mulps        m2, m4, [srcq+      mmsize]
46     mulps        m3, m5, [srcq+src1q+mmsize]
47     addps        m0, m0, m1
48     addps        m2, m2, m3
49     mova  [srcq       ], m0
50     mova  [srcq+mmsize], m2
51     add        srcq, mmsize*2
52     sub        lend, mmsize*2/4
53     jg .loop
54     REP_RET
55 %endmacro
56
57 INIT_XMM sse
58 MIX_2_TO_1_FLTP_FLT
59 %if HAVE_AVX
60 INIT_YMM avx
61 MIX_2_TO_1_FLTP_FLT
62 %endif
63
64 ;-----------------------------------------------------------------------------
65 ; void ff_mix_2_to_1_s16p_flt(int16_t **src, float **matrix, int len,
66 ;                             int out_ch, int in_ch);
67 ;-----------------------------------------------------------------------------
68
69 %macro MIX_2_TO_1_S16P_FLT 0
70 cglobal mix_2_to_1_s16p_flt, 3,4,6, src, matrix, len, src1
71     mov       src1q, [srcq+gprsize]
72     mov        srcq, [srcq]
73     sub       src1q, srcq
74     mov     matrixq, [matrixq  ]
75     VBROADCASTSS m4, [matrixq  ]
76     VBROADCASTSS m5, [matrixq+4]
77     ALIGN 16
78 .loop:
79     mova         m0, [srcq      ]
80     mova         m2, [srcq+src1q]
81     S16_TO_S32_SX 0, 1
82     S16_TO_S32_SX 2, 3
83     cvtdq2ps     m0, m0
84     cvtdq2ps     m1, m1
85     cvtdq2ps     m2, m2
86     cvtdq2ps     m3, m3
87     mulps        m0, m4
88     mulps        m1, m4
89     mulps        m2, m5
90     mulps        m3, m5
91     addps        m0, m2
92     addps        m1, m3
93     cvtps2dq     m0, m0
94     cvtps2dq     m1, m1
95     packssdw     m0, m1
96     mova     [srcq], m0
97     add        srcq, mmsize
98     sub        lend, mmsize/2
99     jg .loop
100     REP_RET
101 %endmacro
102
103 INIT_XMM sse2
104 MIX_2_TO_1_S16P_FLT
105 INIT_XMM sse4
106 MIX_2_TO_1_S16P_FLT
107
108 ;-----------------------------------------------------------------------------
109 ; void ff_mix_2_to_1_s16p_q8(int16_t **src, int16_t **matrix, int len,
110 ;                            int out_ch, int in_ch);
111 ;-----------------------------------------------------------------------------
112
113 INIT_XMM sse2
114 cglobal mix_2_to_1_s16p_q8, 3,4,6, src, matrix, len, src1
115     mov       src1q, [srcq+gprsize]
116     mov        srcq, [srcq]
117     sub       src1q, srcq
118     mov     matrixq, [matrixq]
119     movd         m4, [matrixq]
120     movd         m5, [matrixq]
121     SPLATW       m4, m4, 0
122     SPLATW       m5, m5, 1
123     pxor         m0, m0
124     punpcklwd    m4, m0
125     punpcklwd    m5, m0
126     ALIGN 16
127 .loop:
128     mova         m0, [srcq      ]
129     mova         m2, [srcq+src1q]
130     punpckhwd    m1, m0, m0
131     punpcklwd    m0, m0
132     punpckhwd    m3, m2, m2
133     punpcklwd    m2, m2
134     pmaddwd      m0, m4
135     pmaddwd      m1, m4
136     pmaddwd      m2, m5
137     pmaddwd      m3, m5
138     paddd        m0, m2
139     paddd        m1, m3
140     psrad        m0, 8
141     psrad        m1, 8
142     packssdw     m0, m1
143     mova     [srcq], m0
144     add        srcq, mmsize
145     sub        lend, mmsize/2
146     jg .loop
147     REP_RET
148
149 ;-----------------------------------------------------------------------------
150 ; void ff_mix_1_to_2_fltp_flt(float **src, float **matrix, int len,
151 ;                             int out_ch, int in_ch);
152 ;-----------------------------------------------------------------------------
153
154 %macro MIX_1_TO_2_FLTP_FLT 0
155 cglobal mix_1_to_2_fltp_flt, 3,5,4, src0, matrix0, len, src1, matrix1
156     mov       src1q, [src0q+gprsize]
157     mov       src0q, [src0q]
158     sub       src1q, src0q
159     mov    matrix1q, [matrix0q+gprsize]
160     mov    matrix0q, [matrix0q]
161     VBROADCASTSS m2, [matrix0q]
162     VBROADCASTSS m3, [matrix1q]
163     ALIGN 16
164 .loop:
165     mova         m0, [src0q]
166     mulps        m1, m0, m3
167     mulps        m0, m0, m2
168     mova  [src0q      ], m0
169     mova  [src0q+src1q], m1
170     add       src0q, mmsize
171     sub        lend, mmsize/4
172     jg .loop
173     REP_RET
174 %endmacro
175
176 INIT_XMM sse
177 MIX_1_TO_2_FLTP_FLT
178 %if HAVE_AVX
179 INIT_YMM avx
180 MIX_1_TO_2_FLTP_FLT
181 %endif
182
183 ;-----------------------------------------------------------------------------
184 ; void ff_mix_1_to_2_s16p_flt(int16_t **src, float **matrix, int len,
185 ;                             int out_ch, int in_ch);
186 ;-----------------------------------------------------------------------------
187
188 %macro MIX_1_TO_2_S16P_FLT 0
189 cglobal mix_1_to_2_s16p_flt, 3,5,6, src0, matrix0, len, src1, matrix1
190     mov       src1q, [src0q+gprsize]
191     mov       src0q, [src0q]
192     sub       src1q, src0q
193     mov    matrix1q, [matrix0q+gprsize]
194     mov    matrix0q, [matrix0q]
195     VBROADCASTSS m4, [matrix0q]
196     VBROADCASTSS m5, [matrix1q]
197     ALIGN 16
198 .loop:
199     mova         m0, [src0q]
200     S16_TO_S32_SX 0, 2
201     cvtdq2ps     m0, m0
202     cvtdq2ps     m2, m2
203     mulps        m1, m0, m5
204     mulps        m0, m0, m4
205     mulps        m3, m2, m5
206     mulps        m2, m2, m4
207     cvtps2dq     m0, m0
208     cvtps2dq     m1, m1
209     cvtps2dq     m2, m2
210     cvtps2dq     m3, m3
211     packssdw     m0, m2
212     packssdw     m1, m3
213     mova  [src0q      ], m0
214     mova  [src0q+src1q], m1
215     add       src0q, mmsize
216     sub        lend, mmsize/2
217     jg .loop
218     REP_RET
219 %endmacro
220
221 INIT_XMM sse2
222 MIX_1_TO_2_S16P_FLT
223 INIT_XMM sse4
224 MIX_1_TO_2_S16P_FLT
225 %if HAVE_AVX
226 INIT_XMM avx
227 MIX_1_TO_2_S16P_FLT
228 %endif
229
230 ;-----------------------------------------------------------------------------
231 ; void ff_mix_3_8_to_1_2_fltp/s16p_flt(float/int16_t **src, float **matrix,
232 ;                                      int len, int out_ch, int in_ch);
233 ;-----------------------------------------------------------------------------
234
235 %macro MIX_3_8_TO_1_2_FLT 3 ; %1 = in channels, %2 = out channels, %3 = s16p or fltp
236 ; define some names to make the code clearer
237 %assign  in_channels %1
238 %assign out_channels %2
239 %assign stereo out_channels - 1
240 %ifidn %3, s16p
241     %assign is_s16 1
242 %else
243     %assign is_s16 0
244 %endif
245
246 ; determine how many matrix elements must go on the stack vs. mmregs
247 %assign matrix_elements in_channels * out_channels
248 %if is_s16
249     %if stereo
250         %assign needed_mmregs 7
251     %else
252         %assign needed_mmregs 5
253     %endif
254 %else
255     %if stereo
256         %assign needed_mmregs 4
257     %else
258         %assign needed_mmregs 3
259     %endif
260 %endif
261 %assign matrix_elements_mm num_mmregs - needed_mmregs
262 %if matrix_elements < matrix_elements_mm
263     %assign matrix_elements_mm matrix_elements
264 %endif
265 %if matrix_elements_mm < matrix_elements
266     %assign matrix_elements_stack matrix_elements - matrix_elements_mm
267 %else
268     %assign matrix_elements_stack 0
269 %endif
270
271 cglobal mix_%1_to_%2_%3_flt, 3,in_channels+2,needed_mmregs+matrix_elements_mm, src0, src1, len, src2, src3, src4, src5, src6, src7
272
273 ; get aligned stack space if needed
274 %if matrix_elements_stack > 0
275     %if mmsize == 32
276     %assign bkpreg %1 + 1
277     %define bkpq r %+ bkpreg %+ q
278     mov           bkpq, rsp
279     and           rsp, ~(mmsize-1)
280     sub           rsp, matrix_elements_stack * mmsize
281     %else
282     %assign pad matrix_elements_stack * mmsize + (mmsize - gprsize) - (stack_offset & (mmsize - gprsize))
283     SUB           rsp, pad
284     %endif
285 %endif
286
287 ; load matrix pointers
288 %define matrix0q r1q
289 %define matrix1q r3q
290 %if stereo
291     mov      matrix1q, [matrix0q+gprsize]
292 %endif
293     mov      matrix0q, [matrix0q]
294
295 ; define matrix coeff names
296 %assign %%i 0
297 %assign %%j needed_mmregs
298 %rep in_channels
299     %if %%i >= matrix_elements_mm
300         CAT_XDEFINE mx_stack_0_, %%i, 1
301         CAT_XDEFINE mx_0_, %%i, [rsp+(%%i-matrix_elements_mm)*mmsize]
302     %else
303         CAT_XDEFINE mx_stack_0_, %%i, 0
304         CAT_XDEFINE mx_0_, %%i, m %+ %%j
305         %assign %%j %%j+1
306     %endif
307     %assign %%i %%i+1
308 %endrep
309 %if stereo
310 %assign %%i 0
311 %rep in_channels
312     %if in_channels + %%i >= matrix_elements_mm
313         CAT_XDEFINE mx_stack_1_, %%i, 1
314         CAT_XDEFINE mx_1_, %%i, [rsp+(in_channels+%%i-matrix_elements_mm)*mmsize]
315     %else
316         CAT_XDEFINE mx_stack_1_, %%i, 0
317         CAT_XDEFINE mx_1_, %%i, m %+ %%j
318         %assign %%j %%j+1
319     %endif
320     %assign %%i %%i+1
321 %endrep
322 %endif
323
324 ; load/splat matrix coeffs
325 %assign %%i 0
326 %rep in_channels
327     %if mx_stack_0_ %+ %%i
328         VBROADCASTSS m0, [matrix0q+4*%%i]
329         mova  mx_0_ %+ %%i, m0
330     %else
331         VBROADCASTSS mx_0_ %+ %%i, [matrix0q+4*%%i]
332     %endif
333     %if stereo
334     %if mx_stack_1_ %+ %%i
335         VBROADCASTSS m0, [matrix1q+4*%%i]
336         mova  mx_1_ %+ %%i, m0
337     %else
338         VBROADCASTSS mx_1_ %+ %%i, [matrix1q+4*%%i]
339     %endif
340     %endif
341     %assign %%i %%i+1
342 %endrep
343
344 ; load channel pointers to registers as offsets from the first channel pointer
345 %if ARCH_X86_64
346     movsxd       lenq, r2d
347 %endif
348     shl          lenq, 2-is_s16
349 %assign %%i 1
350 %rep (in_channels - 1)
351     %if ARCH_X86_32 && in_channels >= 7 && %%i >= 5
352     mov         src5q, [src0q+%%i*gprsize]
353     add         src5q, lenq
354     mov         src %+ %%i %+ m, src5q
355     %else
356     mov         src %+ %%i %+ q, [src0q+%%i*gprsize]
357     add         src %+ %%i %+ q, lenq
358     %endif
359     %assign %%i %%i+1
360 %endrep
361     mov         src0q, [src0q]
362     add         src0q, lenq
363     neg          lenq
364 .loop
365 ; for x86-32 with 7-8 channels we do not have enough gp registers for all src
366 ; pointers, so we have to load some of them from the stack each time
367 %define copy_src_from_stack ARCH_X86_32 && in_channels >= 7 && %%i >= 5
368 %if is_s16
369     ; mix with s16p input
370     mova           m0, [src0q+lenq]
371     S16_TO_S32_SX   0, 1
372     cvtdq2ps       m0, m0
373     cvtdq2ps       m1, m1
374     %if stereo
375     mulps          m2, m0, mx_1_0
376     mulps          m3, m1, mx_1_0
377     %endif
378     mulps          m0, m0, mx_0_0
379     mulps          m1, m1, mx_0_0
380 %assign %%i 1
381 %rep (in_channels - 1)
382     %if copy_src_from_stack
383         %define src_ptr src5q
384     %else
385         %define src_ptr src %+ %%i %+ q
386     %endif
387     %if stereo
388     %if copy_src_from_stack
389     mov       src_ptr, src %+ %%i %+ m
390     %endif
391     mova           m4, [src_ptr+lenq]
392     S16_TO_S32_SX   4, 5
393     cvtdq2ps       m4, m4
394     cvtdq2ps       m5, m5
395     fmaddps        m2, m4, mx_1_ %+ %%i, m2, m6
396     fmaddps        m3, m5, mx_1_ %+ %%i, m3, m6
397     fmaddps        m0, m4, mx_0_ %+ %%i, m0, m4
398     fmaddps        m1, m5, mx_0_ %+ %%i, m1, m5
399     %else
400     %if copy_src_from_stack
401     mov       src_ptr, src %+ %%i %+ m
402     %endif
403     mova           m2, [src_ptr+lenq]
404     S16_TO_S32_SX   2, 3
405     cvtdq2ps       m2, m2
406     cvtdq2ps       m3, m3
407     fmaddps        m0, m2, mx_0_ %+ %%i, m0, m4
408     fmaddps        m1, m3, mx_0_ %+ %%i, m1, m4
409     %endif
410     %assign %%i %%i+1
411 %endrep
412     %if stereo
413     cvtps2dq       m2, m2
414     cvtps2dq       m3, m3
415     packssdw       m2, m3
416     mova [src1q+lenq], m2
417     %endif
418     cvtps2dq       m0, m0
419     cvtps2dq       m1, m1
420     packssdw       m0, m1
421     mova [src0q+lenq], m0
422 %else
423     ; mix with fltp input
424     %if stereo || mx_stack_0_0
425     mova           m0, [src0q+lenq]
426     %endif
427     %if stereo
428     mulps          m1, m0, mx_1_0
429     %endif
430     %if stereo || mx_stack_0_0
431     mulps          m0, m0, mx_0_0
432     %else
433     mulps          m0, [src0q+lenq], mx_0_0
434     %endif
435 %assign %%i 1
436 %rep (in_channels - 1)
437     %if copy_src_from_stack
438         %define src_ptr src5q
439         mov   src_ptr, src %+ %%i %+ m
440     %else
441         %define src_ptr src %+ %%i %+ q
442     %endif
443     ; avoid extra load for mono if matrix is in a mm register
444     %if stereo || mx_stack_0_ %+ %%i
445     mova           m2, [src_ptr+lenq]
446     %endif
447     %if stereo
448     fmaddps        m1, m2, mx_1_ %+ %%i, m1, m3
449     %endif
450     %if stereo || mx_stack_0_ %+ %%i
451     fmaddps        m0, m2, mx_0_ %+ %%i, m0, m2
452     %else
453     fmaddps        m0, mx_0_ %+ %%i, [src_ptr+lenq], m0, m1
454     %endif
455     %assign %%i %%i+1
456 %endrep
457     mova [src0q+lenq], m0
458     %if stereo
459     mova [src1q+lenq], m1
460     %endif
461 %endif
462
463     add          lenq, mmsize
464     jl .loop
465 ; restore stack pointer
466 %if matrix_elements_stack > 0
467     %if mmsize == 32
468     mov           rsp, bkpq
469     %else
470     ADD           rsp, pad
471     %endif
472 %endif
473 ; zero ymm high halves
474 %if mmsize == 32
475     vzeroupper
476 %endif
477     RET
478 %endmacro
479
480 %macro MIX_3_8_TO_1_2_FLT_FUNCS 0
481 %assign %%i 3
482 %rep 6
483     INIT_XMM sse
484     MIX_3_8_TO_1_2_FLT %%i, 1, fltp
485     MIX_3_8_TO_1_2_FLT %%i, 2, fltp
486     INIT_XMM sse2
487     MIX_3_8_TO_1_2_FLT %%i, 1, s16p
488     MIX_3_8_TO_1_2_FLT %%i, 2, s16p
489     INIT_XMM sse4
490     MIX_3_8_TO_1_2_FLT %%i, 1, s16p
491     MIX_3_8_TO_1_2_FLT %%i, 2, s16p
492     ; do not use ymm AVX or FMA4 in x86-32 for 6 or more channels due to stack alignment issues
493     %if HAVE_AVX
494     %if ARCH_X86_64 || %%i < 6
495     INIT_YMM avx
496     %else
497     INIT_XMM avx
498     %endif
499     MIX_3_8_TO_1_2_FLT %%i, 1, fltp
500     MIX_3_8_TO_1_2_FLT %%i, 2, fltp
501     INIT_XMM avx
502     MIX_3_8_TO_1_2_FLT %%i, 1, s16p
503     MIX_3_8_TO_1_2_FLT %%i, 2, s16p
504     %endif
505     %if HAVE_FMA4
506     %if ARCH_X86_64 || %%i < 6
507     INIT_YMM fma4
508     %else
509     INIT_XMM fma4
510     %endif
511     MIX_3_8_TO_1_2_FLT %%i, 1, fltp
512     MIX_3_8_TO_1_2_FLT %%i, 2, fltp
513     INIT_XMM fma4
514     MIX_3_8_TO_1_2_FLT %%i, 1, s16p
515     MIX_3_8_TO_1_2_FLT %%i, 2, s16p
516     %endif
517     %assign %%i %%i+1
518 %endrep
519 %endmacro
520
521 MIX_3_8_TO_1_2_FLT_FUNCS