lavr: x86: optimized 2-channel s16p to flt conversion
[ffmpeg.git] / libavresample / x86 / audio_convert.asm
1 ;******************************************************************************
2 ;* x86 optimized Format Conversion Utils
3 ;* Copyright (c) 2008 Loren Merritt
4 ;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
5 ;*
6 ;* This file is part of Libav.
7 ;*
8 ;* Libav is free software; you can redistribute it and/or
9 ;* modify it under the terms of the GNU Lesser General Public
10 ;* License as published by the Free Software Foundation; either
11 ;* version 2.1 of the License, or (at your option) any later version.
12 ;*
13 ;* Libav is distributed in the hope that it will be useful,
14 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 ;* Lesser General Public License for more details.
17 ;*
18 ;* You should have received a copy of the GNU Lesser General Public
19 ;* License along with Libav; if not, write to the Free Software
20 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 ;******************************************************************************
22
23 %include "x86inc.asm"
24 %include "x86util.asm"
25 %include "util.asm"
26
27 SECTION_RODATA 32
28
29 pf_s32_inv_scale: times 8 dd 0x30000000
30 pf_s32_scale:     times 8 dd 0x4f000000
31 pf_s16_inv_scale: times 4 dd 0x38000000
32 pf_s16_scale:     times 4 dd 0x47000000
33
34 SECTION_TEXT
35
36 ;------------------------------------------------------------------------------
37 ; void ff_conv_s16_to_s32(int32_t *dst, const int16_t *src, int len);
38 ;------------------------------------------------------------------------------
39
40 INIT_XMM sse2
41 cglobal conv_s16_to_s32, 3,3,3, dst, src, len
42     lea      lenq, [2*lend]
43     lea      dstq, [dstq+2*lenq]
44     add      srcq, lenq
45     neg      lenq
46 .loop:
47     mova       m2, [srcq+lenq]
48     pxor       m0, m0
49     pxor       m1, m1
50     punpcklwd  m0, m2
51     punpckhwd  m1, m2
52     mova  [dstq+2*lenq       ], m0
53     mova  [dstq+2*lenq+mmsize], m1
54     add      lenq, mmsize
55     jl .loop
56     REP_RET
57
58 ;------------------------------------------------------------------------------
59 ; void ff_conv_s16_to_flt(float *dst, const int16_t *src, int len);
60 ;------------------------------------------------------------------------------
61
62 %macro CONV_S16_TO_FLT 0
63 cglobal conv_s16_to_flt, 3,3,3, dst, src, len
64     lea      lenq, [2*lend]
65     add      srcq, lenq
66     lea      dstq, [dstq + 2*lenq]
67     neg      lenq
68     mova       m2, [pf_s16_inv_scale]
69     ALIGN 16
70 .loop:
71     mova       m0, [srcq+lenq]
72     S16_TO_S32_SX 0, 1
73     cvtdq2ps   m0, m0
74     cvtdq2ps   m1, m1
75     mulps      m0, m2
76     mulps      m1, m2
77     mova  [dstq+2*lenq       ], m0
78     mova  [dstq+2*lenq+mmsize], m1
79     add      lenq, mmsize
80     jl .loop
81     REP_RET
82 %endmacro
83
84 INIT_XMM sse2
85 CONV_S16_TO_FLT
86 INIT_XMM sse4
87 CONV_S16_TO_FLT
88
89 ;------------------------------------------------------------------------------
90 ; void ff_conv_s32_to_s16(int16_t *dst, const int32_t *src, int len);
91 ;------------------------------------------------------------------------------
92
93 %macro CONV_S32_TO_S16 0
94 cglobal conv_s32_to_s16, 3,3,4, dst, src, len
95     lea     lenq, [2*lend]
96     lea     srcq, [srcq+2*lenq]
97     add     dstq, lenq
98     neg     lenq
99 .loop:
100     mova      m0, [srcq+2*lenq         ]
101     mova      m1, [srcq+2*lenq+  mmsize]
102     mova      m2, [srcq+2*lenq+2*mmsize]
103     mova      m3, [srcq+2*lenq+3*mmsize]
104     psrad     m0, 16
105     psrad     m1, 16
106     psrad     m2, 16
107     psrad     m3, 16
108     packssdw  m0, m1
109     packssdw  m2, m3
110     mova  [dstq+lenq       ], m0
111     mova  [dstq+lenq+mmsize], m2
112     add     lenq, mmsize*2
113     jl .loop
114 %if mmsize == 8
115     emms
116     RET
117 %else
118     REP_RET
119 %endif
120 %endmacro
121
122 INIT_MMX mmx
123 CONV_S32_TO_S16
124 INIT_XMM sse2
125 CONV_S32_TO_S16
126
127 ;------------------------------------------------------------------------------
128 ; void ff_conv_s32_to_flt(float *dst, const int32_t *src, int len);
129 ;------------------------------------------------------------------------------
130
131 %macro CONV_S32_TO_FLT 0
132 cglobal conv_s32_to_flt, 3,3,3, dst, src, len
133     lea     lenq, [4*lend]
134     add     srcq, lenq
135     add     dstq, lenq
136     neg     lenq
137     mova      m0, [pf_s32_inv_scale]
138     ALIGN 16
139 .loop:
140     cvtdq2ps  m1, [srcq+lenq       ]
141     cvtdq2ps  m2, [srcq+lenq+mmsize]
142     mulps     m1, m1, m0
143     mulps     m2, m2, m0
144     mova  [dstq+lenq       ], m1
145     mova  [dstq+lenq+mmsize], m2
146     add     lenq, mmsize*2
147     jl .loop
148     REP_RET
149 %endmacro
150
151 INIT_XMM sse2
152 CONV_S32_TO_FLT
153 %if HAVE_AVX
154 INIT_YMM avx
155 CONV_S32_TO_FLT
156 %endif
157
158 ;------------------------------------------------------------------------------
159 ; void ff_conv_flt_to_s16(int16_t *dst, const float *src, int len);
160 ;------------------------------------------------------------------------------
161
162 INIT_XMM sse2
163 cglobal conv_flt_to_s16, 3,3,5, dst, src, len
164     lea     lenq, [2*lend]
165     lea     srcq, [srcq+2*lenq]
166     add     dstq, lenq
167     neg     lenq
168     mova      m4, [pf_s16_scale]
169 .loop:
170     mova      m0, [srcq+2*lenq         ]
171     mova      m1, [srcq+2*lenq+1*mmsize]
172     mova      m2, [srcq+2*lenq+2*mmsize]
173     mova      m3, [srcq+2*lenq+3*mmsize]
174     mulps     m0, m4
175     mulps     m1, m4
176     mulps     m2, m4
177     mulps     m3, m4
178     cvtps2dq  m0, m0
179     cvtps2dq  m1, m1
180     cvtps2dq  m2, m2
181     cvtps2dq  m3, m3
182     packssdw  m0, m1
183     packssdw  m2, m3
184     mova  [dstq+lenq       ], m0
185     mova  [dstq+lenq+mmsize], m2
186     add     lenq, mmsize*2
187     jl .loop
188     REP_RET
189
190 ;------------------------------------------------------------------------------
191 ; void ff_conv_flt_to_s32(int32_t *dst, const float *src, int len);
192 ;------------------------------------------------------------------------------
193
194 %macro CONV_FLT_TO_S32 0
195 cglobal conv_flt_to_s32, 3,3,5, dst, src, len
196     lea     lenq, [lend*4]
197     add     srcq, lenq
198     add     dstq, lenq
199     neg     lenq
200     mova      m4, [pf_s32_scale]
201 .loop:
202     mulps     m0, m4, [srcq+lenq         ]
203     mulps     m1, m4, [srcq+lenq+1*mmsize]
204     mulps     m2, m4, [srcq+lenq+2*mmsize]
205     mulps     m3, m4, [srcq+lenq+3*mmsize]
206     cvtps2dq  m0, m0
207     cvtps2dq  m1, m1
208     cvtps2dq  m2, m2
209     cvtps2dq  m3, m3
210     mova  [dstq+lenq         ], m0
211     mova  [dstq+lenq+1*mmsize], m1
212     mova  [dstq+lenq+2*mmsize], m2
213     mova  [dstq+lenq+3*mmsize], m3
214     add     lenq, mmsize*4
215     jl .loop
216     REP_RET
217 %endmacro
218
219 INIT_XMM sse2
220 CONV_FLT_TO_S32
221 %if HAVE_AVX
222 INIT_YMM avx
223 CONV_FLT_TO_S32
224 %endif
225
226 ;------------------------------------------------------------------------------
227 ; void ff_conv_s16p_to_s16_2ch(int16_t *dst, int16_t *const *src, int len,
228 ;                              int channels);
229 ;------------------------------------------------------------------------------
230
231 %macro CONV_S16P_TO_S16_2CH 0
232 cglobal conv_s16p_to_s16_2ch, 3,4,5, dst, src0, len, src1
233     mov       src1q, [src0q+gprsize]
234     mov       src0q, [src0q        ]
235     lea        lenq, [2*lend]
236     add       src0q, lenq
237     add       src1q, lenq
238     lea        dstq, [dstq+2*lenq]
239     neg        lenq
240 .loop
241     mova         m0, [src0q+lenq       ]
242     mova         m1, [src1q+lenq       ]
243     mova         m2, [src0q+lenq+mmsize]
244     mova         m3, [src1q+lenq+mmsize]
245     SBUTTERFLY2  wd, 0, 1, 4
246     SBUTTERFLY2  wd, 2, 3, 4
247     mova  [dstq+2*lenq+0*mmsize], m0
248     mova  [dstq+2*lenq+1*mmsize], m1
249     mova  [dstq+2*lenq+2*mmsize], m2
250     mova  [dstq+2*lenq+3*mmsize], m3
251     add        lenq, 2*mmsize
252     jl .loop
253     REP_RET
254 %endmacro
255
256 INIT_XMM sse2
257 CONV_S16P_TO_S16_2CH
258 %if HAVE_AVX
259 INIT_XMM avx
260 CONV_S16P_TO_S16_2CH
261 %endif
262
263 ;------------------------------------------------------------------------------
264 ; void ff_conv_s16p_to_s16_6ch(int16_t *dst, int16_t *const *src, int len,
265 ;                              int channels);
266 ;------------------------------------------------------------------------------
267
268 ;------------------------------------------------------------------------------
269 ; NOTE: In the 6-channel functions, len could be used as an index on x86-64
270 ;       instead of just a counter, which would avoid incrementing the
271 ;       pointers, but the extra complexity and amount of code is not worth
272 ;       the small gain. On x86-32 there are not enough registers to use len
273 ;       as an index without keeping two of the pointers on the stack and
274 ;       loading them in each iteration.
275 ;------------------------------------------------------------------------------
276
277 %macro CONV_S16P_TO_S16_6CH 0
278 %if ARCH_X86_64
279 cglobal conv_s16p_to_s16_6ch, 3,8,7, dst, src0, len, src1, src2, src3, src4, src5
280 %else
281 cglobal conv_s16p_to_s16_6ch, 2,7,7, dst, src0, src1, src2, src3, src4, src5
282 %define lend dword r2m
283 %endif
284     mov      src1q, [src0q+1*gprsize]
285     mov      src2q, [src0q+2*gprsize]
286     mov      src3q, [src0q+3*gprsize]
287     mov      src4q, [src0q+4*gprsize]
288     mov      src5q, [src0q+5*gprsize]
289     mov      src0q, [src0q]
290     sub      src1q, src0q
291     sub      src2q, src0q
292     sub      src3q, src0q
293     sub      src4q, src0q
294     sub      src5q, src0q
295 .loop:
296 %if cpuflag(sse2slow)
297     movq        m0, [src0q      ]   ; m0 =  0,  6, 12, 18,  x,  x,  x,  x
298     movq        m1, [src0q+src1q]   ; m1 =  1,  7, 13, 19,  x,  x,  x,  x
299     movq        m2, [src0q+src2q]   ; m2 =  2,  8, 14, 20,  x,  x,  x,  x
300     movq        m3, [src0q+src3q]   ; m3 =  3,  9, 15, 21,  x,  x,  x,  x
301     movq        m4, [src0q+src4q]   ; m4 =  4, 10, 16, 22,  x,  x,  x,  x
302     movq        m5, [src0q+src5q]   ; m5 =  5, 11, 17, 23,  x,  x,  x,  x
303                                     ; unpack words:
304     punpcklwd   m0, m1              ; m0 =  0,  1,  6,  7, 12, 13, 18, 19
305     punpcklwd   m2, m3              ; m2 =  4,  5, 10, 11, 16, 17, 22, 23
306     punpcklwd   m4, m5              ; m4 =  2,  3,  8,  9, 14, 15, 20, 21
307                                     ; blend dwords
308     shufps      m1, m0, m2, q2020   ; m1 =  0,  1, 12, 13,  2,  3, 14, 15
309     shufps      m0, m4, q2031       ; m0 =  6,  7, 18, 19,  4,  5, 16, 17
310     shufps      m2, m4, q3131       ; m2 =  8,  9, 20, 21, 10, 11, 22, 23
311                                     ; shuffle dwords
312     pshufd      m0, m0, q1302       ; m0 =  4,  5,  6,  7, 16, 17, 18, 19
313     pshufd      m1, m1, q3120       ; m1 =  0,  1,  2,  3, 12, 13, 14, 15
314     pshufd      m2, m2, q3120       ; m2 =  8,  9, 10, 11, 20, 21, 22, 23
315     movq   [dstq+0*mmsize/2], m1
316     movq   [dstq+1*mmsize/2], m0
317     movq   [dstq+2*mmsize/2], m2
318     movhps [dstq+3*mmsize/2], m1
319     movhps [dstq+4*mmsize/2], m0
320     movhps [dstq+5*mmsize/2], m2
321     add      src0q, mmsize/2
322     add       dstq, mmsize*3
323     sub       lend, mmsize/4
324 %else
325     mova        m0, [src0q      ]   ; m0 =  0,  6, 12, 18, 24, 30, 36, 42
326     mova        m1, [src0q+src1q]   ; m1 =  1,  7, 13, 19, 25, 31, 37, 43
327     mova        m2, [src0q+src2q]   ; m2 =  2,  8, 14, 20, 26, 32, 38, 44
328     mova        m3, [src0q+src3q]   ; m3 =  3,  9, 15, 21, 27, 33, 39, 45
329     mova        m4, [src0q+src4q]   ; m4 =  4, 10, 16, 22, 28, 34, 40, 46
330     mova        m5, [src0q+src5q]   ; m5 =  5, 11, 17, 23, 29, 35, 41, 47
331                                     ; unpack words:
332     SBUTTERFLY2 wd, 0, 1, 6         ; m0 =  0,  1,  6,  7, 12, 13, 18, 19
333                                     ; m1 = 24, 25, 30, 31, 36, 37, 42, 43
334     SBUTTERFLY2 wd, 2, 3, 6         ; m2 =  2,  3,  8,  9, 14, 15, 20, 21
335                                     ; m3 = 26, 27, 32, 33, 38, 39, 44, 45
336     SBUTTERFLY2 wd, 4, 5, 6         ; m4 =  4,  5, 10, 11, 16, 17, 22, 23
337                                     ; m5 = 28, 29, 34, 35, 40, 41, 46, 47
338                                     ; blend dwords
339     shufps      m6, m0, m2, q2020   ; m6 =  0,  1, 12, 13,  2,  3, 14, 15
340     shufps      m0, m4, q2031       ; m0 =  6,  7, 18, 19,  4,  5, 16, 17
341     shufps      m2, m4, q3131       ; m2 =  8,  9, 20, 21, 10, 11, 22, 23
342     SWAP 4,6                        ; m4 =  0,  1, 12, 13,  2,  3, 14, 15
343     shufps      m6, m1, m3, q2020   ; m6 = 24, 25, 36, 37, 26, 27, 38, 39
344     shufps      m1, m5, q2031       ; m1 = 30, 31, 42, 43, 28, 29, 40, 41
345     shufps      m3, m5, q3131       ; m3 = 32, 33, 44, 45, 34, 35, 46, 47
346     SWAP 5,6                        ; m5 = 24, 25, 36, 37, 26, 27, 38, 39
347                                     ; shuffle dwords
348     pshufd      m0, m0, q1302       ; m0 =  4,  5,  6,  7, 16, 17, 18, 19
349     pshufd      m2, m2, q3120       ; m2 =  8,  9, 10, 11, 20, 21, 22, 23
350     pshufd      m4, m4, q3120       ; m4 =  0,  1,  2,  3, 12, 13, 14, 15
351     pshufd      m1, m1, q1302       ; m1 = 28, 29, 30, 31, 40, 41, 42, 43
352     pshufd      m3, m3, q3120       ; m3 = 32, 33, 34, 35, 44, 45, 46, 47
353     pshufd      m5, m5, q3120       ; m5 = 24, 25, 26, 27, 36, 37, 38, 39
354                                     ; shuffle qwords
355     punpcklqdq  m6, m4, m0          ; m6 =  0,  1,  2,  3,  4,  5,  6,  7
356     punpckhqdq  m0, m2              ; m0 = 16, 17, 18, 19, 20, 21, 22, 23
357     shufps      m2, m4, q3210       ; m2 =  8,  9, 10, 11, 12, 13, 14, 15
358     SWAP 4,6                        ; m4 =  0,  1,  2,  3,  4,  5,  6,  7
359     punpcklqdq  m6, m5, m1          ; m6 = 24, 25, 26, 27, 28, 29, 30, 31
360     punpckhqdq  m1, m3              ; m1 = 40, 41, 42, 43, 44, 45, 46, 47
361     shufps      m3, m5, q3210       ; m3 = 32, 33, 34, 35, 36, 37, 38, 39
362     SWAP 5,6                        ; m5 = 24, 25, 26, 27, 28, 29, 30, 31
363     mova   [dstq+0*mmsize], m4
364     mova   [dstq+1*mmsize], m2
365     mova   [dstq+2*mmsize], m0
366     mova   [dstq+3*mmsize], m5
367     mova   [dstq+4*mmsize], m3
368     mova   [dstq+5*mmsize], m1
369     add      src0q, mmsize
370     add       dstq, mmsize*6
371     sub       lend, mmsize/2
372 %endif
373     jg .loop
374     REP_RET
375 %endmacro
376
377 INIT_XMM sse2
378 CONV_S16P_TO_S16_6CH
379 INIT_XMM sse2slow
380 CONV_S16P_TO_S16_6CH
381 %if HAVE_AVX
382 INIT_XMM avx
383 CONV_S16P_TO_S16_6CH
384 %endif
385
386 ;------------------------------------------------------------------------------
387 ; void ff_conv_s16p_to_flt_2ch(float *dst, int16_t *const *src, int len,
388 ;                              int channels);
389 ;------------------------------------------------------------------------------
390
391 %macro CONV_S16P_TO_FLT_2CH 0
392 cglobal conv_s16p_to_flt_2ch, 3,4,6, dst, src0, len, src1
393     lea       lenq, [2*lend]
394     mov      src1q, [src0q+gprsize]
395     mov      src0q, [src0q        ]
396     lea       dstq, [dstq+4*lenq]
397     add      src0q, lenq
398     add      src1q, lenq
399     neg       lenq
400     mova        m5, [pf_s32_inv_scale]
401 .loop:
402     mova        m2, [src0q+lenq]    ; m2 =  0,  2,  4,  6,  8, 10, 12, 14
403     mova        m4, [src1q+lenq]    ; m4 =  1,  3,  5,  7,  9, 11, 13, 15
404     SBUTTERFLY2 wd, 2, 4, 3         ; m2 =  0,  1,  2,  3,  4,  5,  6,  7
405                                     ; m4 =  8,  9, 10, 11, 12, 13, 14, 15
406     pxor        m3, m3
407     punpcklwd   m0, m3, m2          ; m0 =      0,      1,      2,      3
408     punpckhwd   m1, m3, m2          ; m1 =      4,      5,      6,      7
409     punpcklwd   m2, m3, m4          ; m2 =      8,      9,     10,     11
410     punpckhwd   m3, m4              ; m3 =     12,     13,     14,     15
411     cvtdq2ps    m0, m0
412     cvtdq2ps    m1, m1
413     cvtdq2ps    m2, m2
414     cvtdq2ps    m3, m3
415     mulps       m0, m5
416     mulps       m1, m5
417     mulps       m2, m5
418     mulps       m3, m5
419     mova  [dstq+4*lenq         ], m0
420     mova  [dstq+4*lenq+  mmsize], m1
421     mova  [dstq+4*lenq+2*mmsize], m2
422     mova  [dstq+4*lenq+3*mmsize], m3
423     add       lenq, mmsize
424     jl .loop
425     REP_RET
426 %endmacro
427
428 INIT_XMM sse2
429 CONV_S16P_TO_FLT_2CH
430 %if HAVE_AVX
431 INIT_XMM avx
432 CONV_S16P_TO_FLT_2CH
433 %endif
434
435 ;-----------------------------------------------------------------------------
436 ; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len,
437 ;                              int channels);
438 ;-----------------------------------------------------------------------------
439
440 %macro CONV_FLTP_TO_FLT_6CH 0
441 cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
442 %if ARCH_X86_64
443     mov     lend, r2d
444 %else
445     %define lend dword r2m
446 %endif
447     mov    src1q, [srcq+1*gprsize]
448     mov    src2q, [srcq+2*gprsize]
449     mov    src3q, [srcq+3*gprsize]
450     mov    src4q, [srcq+4*gprsize]
451     mov    src5q, [srcq+5*gprsize]
452     mov     srcq, [srcq]
453     sub    src1q, srcq
454     sub    src2q, srcq
455     sub    src3q, srcq
456     sub    src4q, srcq
457     sub    src5q, srcq
458 .loop:
459     mova      m0, [srcq      ]
460     mova      m1, [srcq+src1q]
461     mova      m2, [srcq+src2q]
462     mova      m3, [srcq+src3q]
463     mova      m4, [srcq+src4q]
464     mova      m5, [srcq+src5q]
465 %if cpuflag(sse4)
466     SBUTTERFLYPS 0, 1, 6
467     SBUTTERFLYPS 2, 3, 6
468     SBUTTERFLYPS 4, 5, 6
469
470     blendps   m6, m4, m0, 1100b
471     movlhps   m0, m2
472     movhlps   m4, m2
473     blendps   m2, m5, m1, 1100b
474     movlhps   m1, m3
475     movhlps   m5, m3
476
477     movaps [dstq   ], m0
478     movaps [dstq+16], m6
479     movaps [dstq+32], m4
480     movaps [dstq+48], m1
481     movaps [dstq+64], m2
482     movaps [dstq+80], m5
483 %else ; mmx
484     SBUTTERFLY dq, 0, 1, 6
485     SBUTTERFLY dq, 2, 3, 6
486     SBUTTERFLY dq, 4, 5, 6
487
488     movq   [dstq   ], m0
489     movq   [dstq+ 8], m2
490     movq   [dstq+16], m4
491     movq   [dstq+24], m1
492     movq   [dstq+32], m3
493     movq   [dstq+40], m5
494 %endif
495     add      srcq, mmsize
496     add      dstq, mmsize*6
497     sub      lend, mmsize/4
498     jg .loop
499 %if mmsize == 8
500     emms
501     RET
502 %else
503     REP_RET
504 %endif
505 %endmacro
506
507 INIT_MMX mmx
508 CONV_FLTP_TO_FLT_6CH
509 INIT_XMM sse4
510 CONV_FLTP_TO_FLT_6CH
511 %if HAVE_AVX
512 INIT_XMM avx
513 CONV_FLTP_TO_FLT_6CH
514 %endif