lavr: x86: optimized 2-channel fltp 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 pb_shuf_unpack_even:      db -1, -1,  0,  1, -1, -1,  2,  3, -1, -1,  8,  9, -1, -1, 10, 11
34 pb_shuf_unpack_odd:       db -1, -1,  4,  5, -1, -1,  6,  7, -1, -1, 12, 13, -1, -1, 14, 15
35 pb_interleave_words: SHUFFLE_MASK_W  0,  4,  1,  5,  2,  6,  3,  7
36
37 SECTION_TEXT
38
39 ;------------------------------------------------------------------------------
40 ; void ff_conv_s16_to_s32(int32_t *dst, const int16_t *src, int len);
41 ;------------------------------------------------------------------------------
42
43 INIT_XMM sse2
44 cglobal conv_s16_to_s32, 3,3,3, dst, src, len
45     lea      lenq, [2*lend]
46     lea      dstq, [dstq+2*lenq]
47     add      srcq, lenq
48     neg      lenq
49 .loop:
50     mova       m2, [srcq+lenq]
51     pxor       m0, m0
52     pxor       m1, m1
53     punpcklwd  m0, m2
54     punpckhwd  m1, m2
55     mova  [dstq+2*lenq       ], m0
56     mova  [dstq+2*lenq+mmsize], m1
57     add      lenq, mmsize
58     jl .loop
59     REP_RET
60
61 ;------------------------------------------------------------------------------
62 ; void ff_conv_s16_to_flt(float *dst, const int16_t *src, int len);
63 ;------------------------------------------------------------------------------
64
65 %macro CONV_S16_TO_FLT 0
66 cglobal conv_s16_to_flt, 3,3,3, dst, src, len
67     lea      lenq, [2*lend]
68     add      srcq, lenq
69     lea      dstq, [dstq + 2*lenq]
70     neg      lenq
71     mova       m2, [pf_s16_inv_scale]
72     ALIGN 16
73 .loop:
74     mova       m0, [srcq+lenq]
75     S16_TO_S32_SX 0, 1
76     cvtdq2ps   m0, m0
77     cvtdq2ps   m1, m1
78     mulps      m0, m2
79     mulps      m1, m2
80     mova  [dstq+2*lenq       ], m0
81     mova  [dstq+2*lenq+mmsize], m1
82     add      lenq, mmsize
83     jl .loop
84     REP_RET
85 %endmacro
86
87 INIT_XMM sse2
88 CONV_S16_TO_FLT
89 INIT_XMM sse4
90 CONV_S16_TO_FLT
91
92 ;------------------------------------------------------------------------------
93 ; void ff_conv_s32_to_s16(int16_t *dst, const int32_t *src, int len);
94 ;------------------------------------------------------------------------------
95
96 %macro CONV_S32_TO_S16 0
97 cglobal conv_s32_to_s16, 3,3,4, dst, src, len
98     lea     lenq, [2*lend]
99     lea     srcq, [srcq+2*lenq]
100     add     dstq, lenq
101     neg     lenq
102 .loop:
103     mova      m0, [srcq+2*lenq         ]
104     mova      m1, [srcq+2*lenq+  mmsize]
105     mova      m2, [srcq+2*lenq+2*mmsize]
106     mova      m3, [srcq+2*lenq+3*mmsize]
107     psrad     m0, 16
108     psrad     m1, 16
109     psrad     m2, 16
110     psrad     m3, 16
111     packssdw  m0, m1
112     packssdw  m2, m3
113     mova  [dstq+lenq       ], m0
114     mova  [dstq+lenq+mmsize], m2
115     add     lenq, mmsize*2
116     jl .loop
117 %if mmsize == 8
118     emms
119     RET
120 %else
121     REP_RET
122 %endif
123 %endmacro
124
125 INIT_MMX mmx
126 CONV_S32_TO_S16
127 INIT_XMM sse2
128 CONV_S32_TO_S16
129
130 ;------------------------------------------------------------------------------
131 ; void ff_conv_s32_to_flt(float *dst, const int32_t *src, int len);
132 ;------------------------------------------------------------------------------
133
134 %macro CONV_S32_TO_FLT 0
135 cglobal conv_s32_to_flt, 3,3,3, dst, src, len
136     lea     lenq, [4*lend]
137     add     srcq, lenq
138     add     dstq, lenq
139     neg     lenq
140     mova      m0, [pf_s32_inv_scale]
141     ALIGN 16
142 .loop:
143     cvtdq2ps  m1, [srcq+lenq       ]
144     cvtdq2ps  m2, [srcq+lenq+mmsize]
145     mulps     m1, m1, m0
146     mulps     m2, m2, m0
147     mova  [dstq+lenq       ], m1
148     mova  [dstq+lenq+mmsize], m2
149     add     lenq, mmsize*2
150     jl .loop
151     REP_RET
152 %endmacro
153
154 INIT_XMM sse2
155 CONV_S32_TO_FLT
156 %if HAVE_AVX
157 INIT_YMM avx
158 CONV_S32_TO_FLT
159 %endif
160
161 ;------------------------------------------------------------------------------
162 ; void ff_conv_flt_to_s16(int16_t *dst, const float *src, int len);
163 ;------------------------------------------------------------------------------
164
165 INIT_XMM sse2
166 cglobal conv_flt_to_s16, 3,3,5, dst, src, len
167     lea     lenq, [2*lend]
168     lea     srcq, [srcq+2*lenq]
169     add     dstq, lenq
170     neg     lenq
171     mova      m4, [pf_s16_scale]
172 .loop:
173     mova      m0, [srcq+2*lenq         ]
174     mova      m1, [srcq+2*lenq+1*mmsize]
175     mova      m2, [srcq+2*lenq+2*mmsize]
176     mova      m3, [srcq+2*lenq+3*mmsize]
177     mulps     m0, m4
178     mulps     m1, m4
179     mulps     m2, m4
180     mulps     m3, m4
181     cvtps2dq  m0, m0
182     cvtps2dq  m1, m1
183     cvtps2dq  m2, m2
184     cvtps2dq  m3, m3
185     packssdw  m0, m1
186     packssdw  m2, m3
187     mova  [dstq+lenq       ], m0
188     mova  [dstq+lenq+mmsize], m2
189     add     lenq, mmsize*2
190     jl .loop
191     REP_RET
192
193 ;------------------------------------------------------------------------------
194 ; void ff_conv_flt_to_s32(int32_t *dst, const float *src, int len);
195 ;------------------------------------------------------------------------------
196
197 %macro CONV_FLT_TO_S32 0
198 cglobal conv_flt_to_s32, 3,3,5, dst, src, len
199     lea     lenq, [lend*4]
200     add     srcq, lenq
201     add     dstq, lenq
202     neg     lenq
203     mova      m4, [pf_s32_scale]
204 .loop:
205     mulps     m0, m4, [srcq+lenq         ]
206     mulps     m1, m4, [srcq+lenq+1*mmsize]
207     mulps     m2, m4, [srcq+lenq+2*mmsize]
208     mulps     m3, m4, [srcq+lenq+3*mmsize]
209     cvtps2dq  m0, m0
210     cvtps2dq  m1, m1
211     cvtps2dq  m2, m2
212     cvtps2dq  m3, m3
213     mova  [dstq+lenq         ], m0
214     mova  [dstq+lenq+1*mmsize], m1
215     mova  [dstq+lenq+2*mmsize], m2
216     mova  [dstq+lenq+3*mmsize], m3
217     add     lenq, mmsize*4
218     jl .loop
219     REP_RET
220 %endmacro
221
222 INIT_XMM sse2
223 CONV_FLT_TO_S32
224 %if HAVE_AVX
225 INIT_YMM avx
226 CONV_FLT_TO_S32
227 %endif
228
229 ;------------------------------------------------------------------------------
230 ; void ff_conv_s16p_to_s16_2ch(int16_t *dst, int16_t *const *src, int len,
231 ;                              int channels);
232 ;------------------------------------------------------------------------------
233
234 %macro CONV_S16P_TO_S16_2CH 0
235 cglobal conv_s16p_to_s16_2ch, 3,4,5, dst, src0, len, src1
236     mov       src1q, [src0q+gprsize]
237     mov       src0q, [src0q        ]
238     lea        lenq, [2*lend]
239     add       src0q, lenq
240     add       src1q, lenq
241     lea        dstq, [dstq+2*lenq]
242     neg        lenq
243 .loop
244     mova         m0, [src0q+lenq       ]
245     mova         m1, [src1q+lenq       ]
246     mova         m2, [src0q+lenq+mmsize]
247     mova         m3, [src1q+lenq+mmsize]
248     SBUTTERFLY2  wd, 0, 1, 4
249     SBUTTERFLY2  wd, 2, 3, 4
250     mova  [dstq+2*lenq+0*mmsize], m0
251     mova  [dstq+2*lenq+1*mmsize], m1
252     mova  [dstq+2*lenq+2*mmsize], m2
253     mova  [dstq+2*lenq+3*mmsize], m3
254     add        lenq, 2*mmsize
255     jl .loop
256     REP_RET
257 %endmacro
258
259 INIT_XMM sse2
260 CONV_S16P_TO_S16_2CH
261 %if HAVE_AVX
262 INIT_XMM avx
263 CONV_S16P_TO_S16_2CH
264 %endif
265
266 ;------------------------------------------------------------------------------
267 ; void ff_conv_s16p_to_s16_6ch(int16_t *dst, int16_t *const *src, int len,
268 ;                              int channels);
269 ;------------------------------------------------------------------------------
270
271 ;------------------------------------------------------------------------------
272 ; NOTE: In the 6-channel functions, len could be used as an index on x86-64
273 ;       instead of just a counter, which would avoid incrementing the
274 ;       pointers, but the extra complexity and amount of code is not worth
275 ;       the small gain. On x86-32 there are not enough registers to use len
276 ;       as an index without keeping two of the pointers on the stack and
277 ;       loading them in each iteration.
278 ;------------------------------------------------------------------------------
279
280 %macro CONV_S16P_TO_S16_6CH 0
281 %if ARCH_X86_64
282 cglobal conv_s16p_to_s16_6ch, 3,8,7, dst, src0, len, src1, src2, src3, src4, src5
283 %else
284 cglobal conv_s16p_to_s16_6ch, 2,7,7, dst, src0, src1, src2, src3, src4, src5
285 %define lend dword r2m
286 %endif
287     mov      src1q, [src0q+1*gprsize]
288     mov      src2q, [src0q+2*gprsize]
289     mov      src3q, [src0q+3*gprsize]
290     mov      src4q, [src0q+4*gprsize]
291     mov      src5q, [src0q+5*gprsize]
292     mov      src0q, [src0q]
293     sub      src1q, src0q
294     sub      src2q, src0q
295     sub      src3q, src0q
296     sub      src4q, src0q
297     sub      src5q, src0q
298 .loop:
299 %if cpuflag(sse2slow)
300     movq        m0, [src0q      ]   ; m0 =  0,  6, 12, 18,  x,  x,  x,  x
301     movq        m1, [src0q+src1q]   ; m1 =  1,  7, 13, 19,  x,  x,  x,  x
302     movq        m2, [src0q+src2q]   ; m2 =  2,  8, 14, 20,  x,  x,  x,  x
303     movq        m3, [src0q+src3q]   ; m3 =  3,  9, 15, 21,  x,  x,  x,  x
304     movq        m4, [src0q+src4q]   ; m4 =  4, 10, 16, 22,  x,  x,  x,  x
305     movq        m5, [src0q+src5q]   ; m5 =  5, 11, 17, 23,  x,  x,  x,  x
306                                     ; unpack words:
307     punpcklwd   m0, m1              ; m0 =  0,  1,  6,  7, 12, 13, 18, 19
308     punpcklwd   m2, m3              ; m2 =  4,  5, 10, 11, 16, 17, 22, 23
309     punpcklwd   m4, m5              ; m4 =  2,  3,  8,  9, 14, 15, 20, 21
310                                     ; blend dwords
311     shufps      m1, m0, m2, q2020   ; m1 =  0,  1, 12, 13,  2,  3, 14, 15
312     shufps      m0, m4, q2031       ; m0 =  6,  7, 18, 19,  4,  5, 16, 17
313     shufps      m2, m4, q3131       ; m2 =  8,  9, 20, 21, 10, 11, 22, 23
314                                     ; shuffle dwords
315     pshufd      m0, m0, q1302       ; m0 =  4,  5,  6,  7, 16, 17, 18, 19
316     pshufd      m1, m1, q3120       ; m1 =  0,  1,  2,  3, 12, 13, 14, 15
317     pshufd      m2, m2, q3120       ; m2 =  8,  9, 10, 11, 20, 21, 22, 23
318     movq   [dstq+0*mmsize/2], m1
319     movq   [dstq+1*mmsize/2], m0
320     movq   [dstq+2*mmsize/2], m2
321     movhps [dstq+3*mmsize/2], m1
322     movhps [dstq+4*mmsize/2], m0
323     movhps [dstq+5*mmsize/2], m2
324     add      src0q, mmsize/2
325     add       dstq, mmsize*3
326     sub       lend, mmsize/4
327 %else
328     mova        m0, [src0q      ]   ; m0 =  0,  6, 12, 18, 24, 30, 36, 42
329     mova        m1, [src0q+src1q]   ; m1 =  1,  7, 13, 19, 25, 31, 37, 43
330     mova        m2, [src0q+src2q]   ; m2 =  2,  8, 14, 20, 26, 32, 38, 44
331     mova        m3, [src0q+src3q]   ; m3 =  3,  9, 15, 21, 27, 33, 39, 45
332     mova        m4, [src0q+src4q]   ; m4 =  4, 10, 16, 22, 28, 34, 40, 46
333     mova        m5, [src0q+src5q]   ; m5 =  5, 11, 17, 23, 29, 35, 41, 47
334                                     ; unpack words:
335     SBUTTERFLY2 wd, 0, 1, 6         ; m0 =  0,  1,  6,  7, 12, 13, 18, 19
336                                     ; m1 = 24, 25, 30, 31, 36, 37, 42, 43
337     SBUTTERFLY2 wd, 2, 3, 6         ; m2 =  2,  3,  8,  9, 14, 15, 20, 21
338                                     ; m3 = 26, 27, 32, 33, 38, 39, 44, 45
339     SBUTTERFLY2 wd, 4, 5, 6         ; m4 =  4,  5, 10, 11, 16, 17, 22, 23
340                                     ; m5 = 28, 29, 34, 35, 40, 41, 46, 47
341                                     ; blend dwords
342     shufps      m6, m0, m2, q2020   ; m6 =  0,  1, 12, 13,  2,  3, 14, 15
343     shufps      m0, m4, q2031       ; m0 =  6,  7, 18, 19,  4,  5, 16, 17
344     shufps      m2, m4, q3131       ; m2 =  8,  9, 20, 21, 10, 11, 22, 23
345     SWAP 4,6                        ; m4 =  0,  1, 12, 13,  2,  3, 14, 15
346     shufps      m6, m1, m3, q2020   ; m6 = 24, 25, 36, 37, 26, 27, 38, 39
347     shufps      m1, m5, q2031       ; m1 = 30, 31, 42, 43, 28, 29, 40, 41
348     shufps      m3, m5, q3131       ; m3 = 32, 33, 44, 45, 34, 35, 46, 47
349     SWAP 5,6                        ; m5 = 24, 25, 36, 37, 26, 27, 38, 39
350                                     ; shuffle dwords
351     pshufd      m0, m0, q1302       ; m0 =  4,  5,  6,  7, 16, 17, 18, 19
352     pshufd      m2, m2, q3120       ; m2 =  8,  9, 10, 11, 20, 21, 22, 23
353     pshufd      m4, m4, q3120       ; m4 =  0,  1,  2,  3, 12, 13, 14, 15
354     pshufd      m1, m1, q1302       ; m1 = 28, 29, 30, 31, 40, 41, 42, 43
355     pshufd      m3, m3, q3120       ; m3 = 32, 33, 34, 35, 44, 45, 46, 47
356     pshufd      m5, m5, q3120       ; m5 = 24, 25, 26, 27, 36, 37, 38, 39
357                                     ; shuffle qwords
358     punpcklqdq  m6, m4, m0          ; m6 =  0,  1,  2,  3,  4,  5,  6,  7
359     punpckhqdq  m0, m2              ; m0 = 16, 17, 18, 19, 20, 21, 22, 23
360     shufps      m2, m4, q3210       ; m2 =  8,  9, 10, 11, 12, 13, 14, 15
361     SWAP 4,6                        ; m4 =  0,  1,  2,  3,  4,  5,  6,  7
362     punpcklqdq  m6, m5, m1          ; m6 = 24, 25, 26, 27, 28, 29, 30, 31
363     punpckhqdq  m1, m3              ; m1 = 40, 41, 42, 43, 44, 45, 46, 47
364     shufps      m3, m5, q3210       ; m3 = 32, 33, 34, 35, 36, 37, 38, 39
365     SWAP 5,6                        ; m5 = 24, 25, 26, 27, 28, 29, 30, 31
366     mova   [dstq+0*mmsize], m4
367     mova   [dstq+1*mmsize], m2
368     mova   [dstq+2*mmsize], m0
369     mova   [dstq+3*mmsize], m5
370     mova   [dstq+4*mmsize], m3
371     mova   [dstq+5*mmsize], m1
372     add      src0q, mmsize
373     add       dstq, mmsize*6
374     sub       lend, mmsize/2
375 %endif
376     jg .loop
377     REP_RET
378 %endmacro
379
380 INIT_XMM sse2
381 CONV_S16P_TO_S16_6CH
382 INIT_XMM sse2slow
383 CONV_S16P_TO_S16_6CH
384 %if HAVE_AVX
385 INIT_XMM avx
386 CONV_S16P_TO_S16_6CH
387 %endif
388
389 ;------------------------------------------------------------------------------
390 ; void ff_conv_s16p_to_flt_2ch(float *dst, int16_t *const *src, int len,
391 ;                              int channels);
392 ;------------------------------------------------------------------------------
393
394 %macro CONV_S16P_TO_FLT_2CH 0
395 cglobal conv_s16p_to_flt_2ch, 3,4,6, dst, src0, len, src1
396     lea       lenq, [2*lend]
397     mov      src1q, [src0q+gprsize]
398     mov      src0q, [src0q        ]
399     lea       dstq, [dstq+4*lenq]
400     add      src0q, lenq
401     add      src1q, lenq
402     neg       lenq
403     mova        m5, [pf_s32_inv_scale]
404 .loop:
405     mova        m2, [src0q+lenq]    ; m2 =  0,  2,  4,  6,  8, 10, 12, 14
406     mova        m4, [src1q+lenq]    ; m4 =  1,  3,  5,  7,  9, 11, 13, 15
407     SBUTTERFLY2 wd, 2, 4, 3         ; m2 =  0,  1,  2,  3,  4,  5,  6,  7
408                                     ; m4 =  8,  9, 10, 11, 12, 13, 14, 15
409     pxor        m3, m3
410     punpcklwd   m0, m3, m2          ; m0 =      0,      1,      2,      3
411     punpckhwd   m1, m3, m2          ; m1 =      4,      5,      6,      7
412     punpcklwd   m2, m3, m4          ; m2 =      8,      9,     10,     11
413     punpckhwd   m3, m4              ; m3 =     12,     13,     14,     15
414     cvtdq2ps    m0, m0
415     cvtdq2ps    m1, m1
416     cvtdq2ps    m2, m2
417     cvtdq2ps    m3, m3
418     mulps       m0, m5
419     mulps       m1, m5
420     mulps       m2, m5
421     mulps       m3, m5
422     mova  [dstq+4*lenq         ], m0
423     mova  [dstq+4*lenq+  mmsize], m1
424     mova  [dstq+4*lenq+2*mmsize], m2
425     mova  [dstq+4*lenq+3*mmsize], m3
426     add       lenq, mmsize
427     jl .loop
428     REP_RET
429 %endmacro
430
431 INIT_XMM sse2
432 CONV_S16P_TO_FLT_2CH
433 %if HAVE_AVX
434 INIT_XMM avx
435 CONV_S16P_TO_FLT_2CH
436 %endif
437
438 ;------------------------------------------------------------------------------
439 ; void ff_conv_s16p_to_flt_6ch(float *dst, int16_t *const *src, int len,
440 ;                              int channels);
441 ;------------------------------------------------------------------------------
442
443 %macro CONV_S16P_TO_FLT_6CH 0
444 %if ARCH_X86_64
445 cglobal conv_s16p_to_flt_6ch, 3,8,8, dst, src, len, src1, src2, src3, src4, src5
446 %else
447 cglobal conv_s16p_to_flt_6ch, 2,7,8, dst, src, src1, src2, src3, src4, src5
448 %define lend dword r2m
449 %endif
450     mov     src1q, [srcq+1*gprsize]
451     mov     src2q, [srcq+2*gprsize]
452     mov     src3q, [srcq+3*gprsize]
453     mov     src4q, [srcq+4*gprsize]
454     mov     src5q, [srcq+5*gprsize]
455     mov      srcq, [srcq]
456     sub     src1q, srcq
457     sub     src2q, srcq
458     sub     src3q, srcq
459     sub     src4q, srcq
460     sub     src5q, srcq
461     mova       m7, [pf_s32_inv_scale]
462 %if cpuflag(ssse3)
463     %define unpack_even m6
464     mova       m6, [pb_shuf_unpack_even]
465 %if ARCH_X86_64
466     %define unpack_odd m8
467     mova       m8, [pb_shuf_unpack_odd]
468 %else
469     %define unpack_odd [pb_shuf_unpack_odd]
470 %endif
471 %endif
472 .loop:
473     movq       m0, [srcq      ]  ; m0 =  0,  6, 12, 18,  x,  x,  x,  x
474     movq       m1, [srcq+src1q]  ; m1 =  1,  7, 13, 19,  x,  x,  x,  x
475     movq       m2, [srcq+src2q]  ; m2 =  2,  8, 14, 20,  x,  x,  x,  x
476     movq       m3, [srcq+src3q]  ; m3 =  3,  9, 15, 21,  x,  x,  x,  x
477     movq       m4, [srcq+src4q]  ; m4 =  4, 10, 16, 22,  x,  x,  x,  x
478     movq       m5, [srcq+src5q]  ; m5 =  5, 11, 17, 23,  x,  x,  x,  x
479                                  ; unpack words:
480     punpcklwd  m0, m1            ; m0 =  0,  1,  6,  7, 12, 13, 18, 19
481     punpcklwd  m2, m3            ; m2 =  2,  3,  8,  9, 14, 15, 20, 21
482     punpcklwd  m4, m5            ; m4 =  4,  5, 10, 11, 16, 17, 22, 23
483                                  ; blend dwords
484     shufps     m1, m4, m0, q3120 ; m1 =  4,  5, 16, 17,  6,  7, 18, 19
485     shufps         m0, m2, q2020 ; m0 =  0,  1, 12, 13,  2,  3, 14, 15
486     shufps         m2, m4, q3131 ; m2 =  8,  9, 20, 21, 10, 11, 22, 23
487 %if cpuflag(ssse3)
488     pshufb     m3, m0, unpack_odd   ; m3 =  12,     13,     14,     15
489     pshufb         m0, unpack_even  ; m0 =   0,      1,      2,      3
490     pshufb     m4, m1, unpack_odd   ; m4 =  16,     17,     18,     19
491     pshufb         m1, unpack_even  ; m1 =   4,      5,      6,      7
492     pshufb     m5, m2, unpack_odd   ; m5 =  20,     21,     22,     23
493     pshufb         m2, unpack_even  ; m2 =   8,      9,     10,     11
494 %else
495                                  ; shuffle dwords
496     pshufd     m0, m0, q3120     ; m0 =  0,  1,  2,  3, 12, 13, 14, 15
497     pshufd     m1, m1, q3120     ; m1 =  4,  5,  6,  7, 16, 17, 18, 19
498     pshufd     m2, m2, q3120     ; m2 =  8,  9, 10, 11, 20, 21, 22, 23
499     pxor       m6, m6            ; convert s16 in m0-m2 to s32 in m0-m5
500     punpcklwd  m3, m6, m0        ; m3 =      0,      1,      2,      3
501     punpckhwd  m4, m6, m0        ; m4 =     12,     13,     14,     15
502     punpcklwd  m0, m6, m1        ; m0 =      4,      5,      6,      7
503     punpckhwd  m5, m6, m1        ; m5 =     16,     17,     18,     19
504     punpcklwd  m1, m6, m2        ; m1 =      8,      9,     10,     11
505     punpckhwd      m6, m2        ; m6 =     20,     21,     22,     23
506     SWAP 6,2,1,0,3,4,5           ; swap registers 3,0,1,4,5,6 to 0,1,2,3,4,5
507 %endif
508     cvtdq2ps   m0, m0            ; convert s32 to float
509     cvtdq2ps   m1, m1
510     cvtdq2ps   m2, m2
511     cvtdq2ps   m3, m3
512     cvtdq2ps   m4, m4
513     cvtdq2ps   m5, m5
514     mulps      m0, m7            ; scale float from s32 range to [-1.0,1.0]
515     mulps      m1, m7
516     mulps      m2, m7
517     mulps      m3, m7
518     mulps      m4, m7
519     mulps      m5, m7
520     mova  [dstq         ], m0
521     mova  [dstq+  mmsize], m1
522     mova  [dstq+2*mmsize], m2
523     mova  [dstq+3*mmsize], m3
524     mova  [dstq+4*mmsize], m4
525     mova  [dstq+5*mmsize], m5
526     add      srcq, mmsize/2
527     add      dstq, mmsize*6
528     sub      lend, mmsize/4
529     jg .loop
530     REP_RET
531 %endmacro
532
533 INIT_XMM sse2
534 CONV_S16P_TO_FLT_6CH
535 INIT_XMM ssse3
536 CONV_S16P_TO_FLT_6CH
537 %if HAVE_AVX
538 INIT_XMM avx
539 CONV_S16P_TO_FLT_6CH
540 %endif
541
542 ;------------------------------------------------------------------------------
543 ; void ff_conv_fltp_to_s16_2ch(int16_t *dst, float *const *src, int len,
544 ;                              int channels);
545 ;------------------------------------------------------------------------------
546
547 %macro CONV_FLTP_TO_S16_2CH 0
548 cglobal conv_fltp_to_s16_2ch, 3,4,3, dst, src0, len, src1
549     lea      lenq, [4*lend]
550     mov     src1q, [src0q+gprsize]
551     mov     src0q, [src0q        ]
552     add      dstq, lenq
553     add     src0q, lenq
554     add     src1q, lenq
555     neg      lenq
556     mova       m2, [pf_s16_scale]
557 %if cpuflag(ssse3)
558     mova       m3, [pb_interleave_words]
559 %endif
560 .loop:
561     mulps      m0, m2, [src0q+lenq] ; m0 =    0,    2,    4,    6
562     mulps      m1, m2, [src1q+lenq] ; m1 =    1,    3,    5,    7
563     cvtps2dq   m0, m0
564     cvtps2dq   m1, m1
565 %if cpuflag(ssse3)
566     packssdw   m0, m1               ; m0 = 0, 2, 4, 6, 1, 3, 5, 7
567     pshufb     m0, m3               ; m0 = 0, 1, 2, 3, 4, 5, 6, 7
568 %else
569     packssdw   m0, m0               ; m0 = 0, 2, 4, 6, x, x, x, x
570     packssdw   m1, m1               ; m1 = 1, 3, 5, 7, x, x, x, x
571     punpcklwd  m0, m1               ; m0 = 0, 1, 2, 3, 4, 5, 6, 7
572 %endif
573     mova  [dstq+lenq], m0
574     add      lenq, mmsize
575     jl .loop
576     REP_RET
577 %endmacro
578
579 INIT_XMM sse2
580 CONV_FLTP_TO_S16_2CH
581 INIT_XMM ssse3
582 CONV_FLTP_TO_S16_2CH
583
584 ;-----------------------------------------------------------------------------
585 ; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len,
586 ;                              int channels);
587 ;-----------------------------------------------------------------------------
588
589 %macro CONV_FLTP_TO_FLT_6CH 0
590 cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
591 %if ARCH_X86_64
592     mov     lend, r2d
593 %else
594     %define lend dword r2m
595 %endif
596     mov    src1q, [srcq+1*gprsize]
597     mov    src2q, [srcq+2*gprsize]
598     mov    src3q, [srcq+3*gprsize]
599     mov    src4q, [srcq+4*gprsize]
600     mov    src5q, [srcq+5*gprsize]
601     mov     srcq, [srcq]
602     sub    src1q, srcq
603     sub    src2q, srcq
604     sub    src3q, srcq
605     sub    src4q, srcq
606     sub    src5q, srcq
607 .loop:
608     mova      m0, [srcq      ]
609     mova      m1, [srcq+src1q]
610     mova      m2, [srcq+src2q]
611     mova      m3, [srcq+src3q]
612     mova      m4, [srcq+src4q]
613     mova      m5, [srcq+src5q]
614 %if cpuflag(sse4)
615     SBUTTERFLYPS 0, 1, 6
616     SBUTTERFLYPS 2, 3, 6
617     SBUTTERFLYPS 4, 5, 6
618
619     blendps   m6, m4, m0, 1100b
620     movlhps   m0, m2
621     movhlps   m4, m2
622     blendps   m2, m5, m1, 1100b
623     movlhps   m1, m3
624     movhlps   m5, m3
625
626     movaps [dstq   ], m0
627     movaps [dstq+16], m6
628     movaps [dstq+32], m4
629     movaps [dstq+48], m1
630     movaps [dstq+64], m2
631     movaps [dstq+80], m5
632 %else ; mmx
633     SBUTTERFLY dq, 0, 1, 6
634     SBUTTERFLY dq, 2, 3, 6
635     SBUTTERFLY dq, 4, 5, 6
636
637     movq   [dstq   ], m0
638     movq   [dstq+ 8], m2
639     movq   [dstq+16], m4
640     movq   [dstq+24], m1
641     movq   [dstq+32], m3
642     movq   [dstq+40], m5
643 %endif
644     add      srcq, mmsize
645     add      dstq, mmsize*6
646     sub      lend, mmsize/4
647     jg .loop
648 %if mmsize == 8
649     emms
650     RET
651 %else
652     REP_RET
653 %endif
654 %endmacro
655
656 INIT_MMX mmx
657 CONV_FLTP_TO_FLT_6CH
658 INIT_XMM sse4
659 CONV_FLTP_TO_FLT_6CH
660 %if HAVE_AVX
661 INIT_XMM avx
662 CONV_FLTP_TO_FLT_6CH
663 %endif