lavr: x86: optimized 2-channel s16p to s16 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_fltp_to_flt_6ch(float *dst, float *const *src, int len,
265 ;                              int channels);
266 ;-----------------------------------------------------------------------------
267
268 %macro CONV_FLTP_TO_FLT_6CH 0
269 cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
270 %if ARCH_X86_64
271     mov     lend, r2d
272 %else
273     %define lend dword r2m
274 %endif
275     mov    src1q, [srcq+1*gprsize]
276     mov    src2q, [srcq+2*gprsize]
277     mov    src3q, [srcq+3*gprsize]
278     mov    src4q, [srcq+4*gprsize]
279     mov    src5q, [srcq+5*gprsize]
280     mov     srcq, [srcq]
281     sub    src1q, srcq
282     sub    src2q, srcq
283     sub    src3q, srcq
284     sub    src4q, srcq
285     sub    src5q, srcq
286 .loop:
287     mova      m0, [srcq      ]
288     mova      m1, [srcq+src1q]
289     mova      m2, [srcq+src2q]
290     mova      m3, [srcq+src3q]
291     mova      m4, [srcq+src4q]
292     mova      m5, [srcq+src5q]
293 %if cpuflag(sse4)
294     SBUTTERFLYPS 0, 1, 6
295     SBUTTERFLYPS 2, 3, 6
296     SBUTTERFLYPS 4, 5, 6
297
298     blendps   m6, m4, m0, 1100b
299     movlhps   m0, m2
300     movhlps   m4, m2
301     blendps   m2, m5, m1, 1100b
302     movlhps   m1, m3
303     movhlps   m5, m3
304
305     movaps [dstq   ], m0
306     movaps [dstq+16], m6
307     movaps [dstq+32], m4
308     movaps [dstq+48], m1
309     movaps [dstq+64], m2
310     movaps [dstq+80], m5
311 %else ; mmx
312     SBUTTERFLY dq, 0, 1, 6
313     SBUTTERFLY dq, 2, 3, 6
314     SBUTTERFLY dq, 4, 5, 6
315
316     movq   [dstq   ], m0
317     movq   [dstq+ 8], m2
318     movq   [dstq+16], m4
319     movq   [dstq+24], m1
320     movq   [dstq+32], m3
321     movq   [dstq+40], m5
322 %endif
323     add      srcq, mmsize
324     add      dstq, mmsize*6
325     sub      lend, mmsize/4
326     jg .loop
327 %if mmsize == 8
328     emms
329     RET
330 %else
331     REP_RET
332 %endif
333 %endmacro
334
335 INIT_MMX mmx
336 CONV_FLTP_TO_FLT_6CH
337 INIT_XMM sse4
338 CONV_FLTP_TO_FLT_6CH
339 %if HAVE_AVX
340 INIT_XMM avx
341 CONV_FLTP_TO_FLT_6CH
342 %endif