lavr: Add x86-optimized function for flt to s32 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 %if mmsize == 32
149     vzeroupper
150     RET
151 %else
152     REP_RET
153 %endif
154 %endmacro
155
156 INIT_XMM sse2
157 CONV_S32_TO_FLT
158 %if HAVE_AVX
159 INIT_YMM avx
160 CONV_S32_TO_FLT
161 %endif
162
163 ;------------------------------------------------------------------------------
164 ; void ff_conv_flt_to_s16(int16_t *dst, const float *src, int len);
165 ;------------------------------------------------------------------------------
166
167 INIT_XMM sse2
168 cglobal conv_flt_to_s16, 3,3,5, dst, src, len
169     lea     lenq, [2*lend]
170     lea     srcq, [srcq+2*lenq]
171     add     dstq, lenq
172     neg     lenq
173     mova      m4, [pf_s16_scale]
174 .loop:
175     mova      m0, [srcq+2*lenq         ]
176     mova      m1, [srcq+2*lenq+1*mmsize]
177     mova      m2, [srcq+2*lenq+2*mmsize]
178     mova      m3, [srcq+2*lenq+3*mmsize]
179     mulps     m0, m4
180     mulps     m1, m4
181     mulps     m2, m4
182     mulps     m3, m4
183     cvtps2dq  m0, m0
184     cvtps2dq  m1, m1
185     cvtps2dq  m2, m2
186     cvtps2dq  m3, m3
187     packssdw  m0, m1
188     packssdw  m2, m3
189     mova  [dstq+lenq       ], m0
190     mova  [dstq+lenq+mmsize], m2
191     add     lenq, mmsize*2
192     jl .loop
193     REP_RET
194
195 ;------------------------------------------------------------------------------
196 ; void ff_conv_flt_to_s32(int32_t *dst, const float *src, int len);
197 ;------------------------------------------------------------------------------
198
199 %macro CONV_FLT_TO_S32 0
200 cglobal conv_flt_to_s32, 3,3,5, dst, src, len
201     lea     lenq, [lend*4]
202     add     srcq, lenq
203     add     dstq, lenq
204     neg     lenq
205     mova      m4, [pf_s32_scale]
206 .loop:
207     mulps     m0, m4, [srcq+lenq         ]
208     mulps     m1, m4, [srcq+lenq+1*mmsize]
209     mulps     m2, m4, [srcq+lenq+2*mmsize]
210     mulps     m3, m4, [srcq+lenq+3*mmsize]
211     cvtps2dq  m0, m0
212     cvtps2dq  m1, m1
213     cvtps2dq  m2, m2
214     cvtps2dq  m3, m3
215     mova  [dstq+lenq         ], m0
216     mova  [dstq+lenq+1*mmsize], m1
217     mova  [dstq+lenq+2*mmsize], m2
218     mova  [dstq+lenq+3*mmsize], m3
219     add     lenq, mmsize*4
220     jl .loop
221 %if mmsize == 32
222     vzeroupper
223     RET
224 %else
225     REP_RET
226 %endif
227 %endmacro
228
229 INIT_XMM sse2
230 CONV_FLT_TO_S32
231 %if HAVE_AVX
232 INIT_YMM avx
233 CONV_FLT_TO_S32
234 %endif
235
236 ;-----------------------------------------------------------------------------
237 ; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len,
238 ;                              int channels);
239 ;-----------------------------------------------------------------------------
240
241 %macro CONV_FLTP_TO_FLT_6CH 0
242 cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
243 %if ARCH_X86_64
244     mov     lend, r2d
245 %else
246     %define lend dword r2m
247 %endif
248     mov    src1q, [srcq+1*gprsize]
249     mov    src2q, [srcq+2*gprsize]
250     mov    src3q, [srcq+3*gprsize]
251     mov    src4q, [srcq+4*gprsize]
252     mov    src5q, [srcq+5*gprsize]
253     mov     srcq, [srcq]
254     sub    src1q, srcq
255     sub    src2q, srcq
256     sub    src3q, srcq
257     sub    src4q, srcq
258     sub    src5q, srcq
259 .loop:
260     mova      m0, [srcq      ]
261     mova      m1, [srcq+src1q]
262     mova      m2, [srcq+src2q]
263     mova      m3, [srcq+src3q]
264     mova      m4, [srcq+src4q]
265     mova      m5, [srcq+src5q]
266 %if cpuflag(sse4)
267     SBUTTERFLYPS 0, 1, 6
268     SBUTTERFLYPS 2, 3, 6
269     SBUTTERFLYPS 4, 5, 6
270
271     blendps   m6, m4, m0, 1100b
272     movlhps   m0, m2
273     movhlps   m4, m2
274     blendps   m2, m5, m1, 1100b
275     movlhps   m1, m3
276     movhlps   m5, m3
277
278     movaps [dstq   ], m0
279     movaps [dstq+16], m6
280     movaps [dstq+32], m4
281     movaps [dstq+48], m1
282     movaps [dstq+64], m2
283     movaps [dstq+80], m5
284 %else ; mmx
285     SBUTTERFLY dq, 0, 1, 6
286     SBUTTERFLY dq, 2, 3, 6
287     SBUTTERFLY dq, 4, 5, 6
288
289     movq   [dstq   ], m0
290     movq   [dstq+ 8], m2
291     movq   [dstq+16], m4
292     movq   [dstq+24], m1
293     movq   [dstq+32], m3
294     movq   [dstq+40], m5
295 %endif
296     add      srcq, mmsize
297     add      dstq, mmsize*6
298     sub      lend, mmsize/4
299     jg .loop
300 %if mmsize == 8
301     emms
302     RET
303 %else
304     REP_RET
305 %endif
306 %endmacro
307
308 INIT_MMX mmx
309 CONV_FLTP_TO_FLT_6CH
310 INIT_XMM sse4
311 CONV_FLTP_TO_FLT_6CH
312 %if HAVE_AVX
313 INIT_XMM avx
314 CONV_FLTP_TO_FLT_6CH
315 %endif