48508af81c82dc21708336d4ab41417337c141fd
[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_s16_6ch(int16_t *dst, float *const *src, int len,
586 ;                              int channels);
587 ;------------------------------------------------------------------------------
588
589 %macro CONV_FLTP_TO_S16_6CH 0
590 %if ARCH_X86_64
591 cglobal conv_fltp_to_s16_6ch, 3,8,7, dst, src, len, src1, src2, src3, src4, src5
592 %else
593 cglobal conv_fltp_to_s16_6ch, 2,7,7, dst, src, src1, src2, src3, src4, src5
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     movaps      xmm6, [pf_s16_scale]
608 .loop:
609 %if cpuflag(sse2)
610     mulps         m0, m6, [srcq      ]
611     mulps         m1, m6, [srcq+src1q]
612     mulps         m2, m6, [srcq+src2q]
613     mulps         m3, m6, [srcq+src3q]
614     mulps         m4, m6, [srcq+src4q]
615     mulps         m5, m6, [srcq+src5q]
616     cvtps2dq      m0, m0
617     cvtps2dq      m1, m1
618     cvtps2dq      m2, m2
619     cvtps2dq      m3, m3
620     cvtps2dq      m4, m4
621     cvtps2dq      m5, m5
622     packssdw      m0, m3            ; m0 =  0,  6, 12, 18,  3,  9, 15, 21
623     packssdw      m1, m4            ; m1 =  1,  7, 13, 19,  4, 10, 16, 22
624     packssdw      m2, m5            ; m2 =  2,  8, 14, 20,  5, 11, 17, 23
625                                     ; unpack words:
626     movhlps       m3, m0            ; m3 =  3,  9, 15, 21,  x,  x,  x,  x
627     punpcklwd     m0, m1            ; m0 =  0,  1,  6,  7, 12, 13, 18, 19
628     punpckhwd     m1, m2            ; m1 =  4,  5, 10, 11, 16, 17, 22, 23
629     punpcklwd     m2, m3            ; m2 =  2,  3,  8,  9, 14, 15, 20, 21
630                                     ; blend dwords:
631     shufps        m3, m0, m2, q2020 ; m3 =  0,  1, 12, 13,  2,  3, 14, 15
632     shufps        m0, m1, q2031     ; m0 =  6,  7, 18, 19,  4,  5, 16, 17
633     shufps        m2, m1, q3131     ; m2 =  8,  9, 20, 21, 10, 11, 22, 23
634                                     ; shuffle dwords:
635     shufps        m1, m2, m3, q3120 ; m1 =  8,  9, 10, 11, 12, 13, 14, 15
636     shufps        m3, m0,     q0220 ; m3 =  0,  1,  2,  3,  4,  5,  6,  7
637     shufps        m0, m2,     q3113 ; m0 = 16, 17, 18, 19, 20, 21, 22, 23
638     mova  [dstq+0*mmsize], m3
639     mova  [dstq+1*mmsize], m1
640     mova  [dstq+2*mmsize], m0
641 %else ; sse
642     movlps      xmm0, [srcq      ]
643     movlps      xmm1, [srcq+src1q]
644     movlps      xmm2, [srcq+src2q]
645     movlps      xmm3, [srcq+src3q]
646     movlps      xmm4, [srcq+src4q]
647     movlps      xmm5, [srcq+src5q]
648     mulps       xmm0, xmm6
649     mulps       xmm1, xmm6
650     mulps       xmm2, xmm6
651     mulps       xmm3, xmm6
652     mulps       xmm4, xmm6
653     mulps       xmm5, xmm6
654     cvtps2pi     mm0, xmm0
655     cvtps2pi     mm1, xmm1
656     cvtps2pi     mm2, xmm2
657     cvtps2pi     mm3, xmm3
658     cvtps2pi     mm4, xmm4
659     cvtps2pi     mm5, xmm5
660     packssdw     mm0, mm3           ; m0 =  0,  6,  3,  9
661     packssdw     mm1, mm4           ; m1 =  1,  7,  4, 10
662     packssdw     mm2, mm5           ; m2 =  2,  8,  5, 11
663                                     ; unpack words
664     pshufw       mm3, mm0, q1032    ; m3 =  3,  9,  0,  6
665     punpcklwd    mm0, mm1           ; m0 =  0,  1,  6,  7
666     punpckhwd    mm1, mm2           ; m1 =  4,  5, 10, 11
667     punpcklwd    mm2, mm3           ; m2 =  2,  3,  8,  9
668                                     ; unpack dwords
669     pshufw       mm3, mm0, q1032    ; m3 =  6,  7,  0,  1
670     punpckldq    mm0, mm2           ; m0 =  0,  1,  2,  3 (final)
671     punpckhdq    mm2, mm1           ; m2 =  8,  9, 10, 11 (final)
672     punpckldq    mm1, mm3           ; m1 =  4,  5,  6,  7 (final)
673     mova  [dstq+0*mmsize], mm0
674     mova  [dstq+1*mmsize], mm1
675     mova  [dstq+2*mmsize], mm2
676 %endif
677     add       srcq, mmsize
678     add       dstq, mmsize*3
679     sub       lend, mmsize/4
680     jg .loop
681 %if mmsize == 8
682     emms
683     RET
684 %else
685     REP_RET
686 %endif
687 %endmacro
688
689 INIT_MMX sse
690 CONV_FLTP_TO_S16_6CH
691 INIT_XMM sse2
692 CONV_FLTP_TO_S16_6CH
693 %if HAVE_AVX
694 INIT_XMM avx
695 CONV_FLTP_TO_S16_6CH
696 %endif
697
698 ;------------------------------------------------------------------------------
699 ; void ff_conv_fltp_to_flt_2ch(float *dst, float *const *src, int len,
700 ;                              int channels);
701 ;------------------------------------------------------------------------------
702
703 %macro CONV_FLTP_TO_FLT_2CH 0
704 cglobal conv_fltp_to_flt_2ch, 3,4,5, dst, src0, len, src1
705     mov  src1q, [src0q+gprsize]
706     mov  src0q, [src0q]
707     lea   lenq, [4*lend]
708     add  src0q, lenq
709     add  src1q, lenq
710     lea   dstq, [dstq+2*lenq]
711     neg   lenq
712 .loop
713     mova    m0, [src0q+lenq       ]
714     mova    m1, [src1q+lenq       ]
715     mova    m2, [src0q+lenq+mmsize]
716     mova    m3, [src1q+lenq+mmsize]
717     SBUTTERFLYPS 0, 1, 4
718     SBUTTERFLYPS 2, 3, 4
719     mova  [dstq+2*lenq+0*mmsize], m0
720     mova  [dstq+2*lenq+1*mmsize], m1
721     mova  [dstq+2*lenq+2*mmsize], m2
722     mova  [dstq+2*lenq+3*mmsize], m3
723     add   lenq, 2*mmsize
724     jl .loop
725     REP_RET
726 %endmacro
727
728 INIT_XMM sse
729 CONV_FLTP_TO_FLT_2CH
730 %if HAVE_AVX
731 INIT_XMM avx
732 CONV_FLTP_TO_FLT_2CH
733 %endif
734
735 ;-----------------------------------------------------------------------------
736 ; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len,
737 ;                              int channels);
738 ;-----------------------------------------------------------------------------
739
740 %macro CONV_FLTP_TO_FLT_6CH 0
741 cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
742 %if ARCH_X86_64
743     mov     lend, r2d
744 %else
745     %define lend dword r2m
746 %endif
747     mov    src1q, [srcq+1*gprsize]
748     mov    src2q, [srcq+2*gprsize]
749     mov    src3q, [srcq+3*gprsize]
750     mov    src4q, [srcq+4*gprsize]
751     mov    src5q, [srcq+5*gprsize]
752     mov     srcq, [srcq]
753     sub    src1q, srcq
754     sub    src2q, srcq
755     sub    src3q, srcq
756     sub    src4q, srcq
757     sub    src5q, srcq
758 .loop:
759     mova      m0, [srcq      ]
760     mova      m1, [srcq+src1q]
761     mova      m2, [srcq+src2q]
762     mova      m3, [srcq+src3q]
763     mova      m4, [srcq+src4q]
764     mova      m5, [srcq+src5q]
765 %if cpuflag(sse4)
766     SBUTTERFLYPS 0, 1, 6
767     SBUTTERFLYPS 2, 3, 6
768     SBUTTERFLYPS 4, 5, 6
769
770     blendps   m6, m4, m0, 1100b
771     movlhps   m0, m2
772     movhlps   m4, m2
773     blendps   m2, m5, m1, 1100b
774     movlhps   m1, m3
775     movhlps   m5, m3
776
777     movaps [dstq   ], m0
778     movaps [dstq+16], m6
779     movaps [dstq+32], m4
780     movaps [dstq+48], m1
781     movaps [dstq+64], m2
782     movaps [dstq+80], m5
783 %else ; mmx
784     SBUTTERFLY dq, 0, 1, 6
785     SBUTTERFLY dq, 2, 3, 6
786     SBUTTERFLY dq, 4, 5, 6
787
788     movq   [dstq   ], m0
789     movq   [dstq+ 8], m2
790     movq   [dstq+16], m4
791     movq   [dstq+24], m1
792     movq   [dstq+32], m3
793     movq   [dstq+40], m5
794 %endif
795     add      srcq, mmsize
796     add      dstq, mmsize*6
797     sub      lend, mmsize/4
798     jg .loop
799 %if mmsize == 8
800     emms
801     RET
802 %else
803     REP_RET
804 %endif
805 %endmacro
806
807 INIT_MMX mmx
808 CONV_FLTP_TO_FLT_6CH
809 INIT_XMM sse4
810 CONV_FLTP_TO_FLT_6CH
811 %if HAVE_AVX
812 INIT_XMM avx
813 CONV_FLTP_TO_FLT_6CH
814 %endif