e7d8fcad6643c7d576a7afe9f4537c76ac270da7
[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 pb_deinterleave_words: SHUFFLE_MASK_W  0,  2,  4,  6,  1,  3,  5,  7
37
38 SECTION_TEXT
39
40 ;------------------------------------------------------------------------------
41 ; void ff_conv_s16_to_s32(int32_t *dst, const int16_t *src, int len);
42 ;------------------------------------------------------------------------------
43
44 INIT_XMM sse2
45 cglobal conv_s16_to_s32, 3,3,3, dst, src, len
46     lea      lenq, [2*lend]
47     lea      dstq, [dstq+2*lenq]
48     add      srcq, lenq
49     neg      lenq
50 .loop:
51     mova       m2, [srcq+lenq]
52     pxor       m0, m0
53     pxor       m1, m1
54     punpcklwd  m0, m2
55     punpckhwd  m1, m2
56     mova  [dstq+2*lenq       ], m0
57     mova  [dstq+2*lenq+mmsize], m1
58     add      lenq, mmsize
59     jl .loop
60     REP_RET
61
62 ;------------------------------------------------------------------------------
63 ; void ff_conv_s16_to_flt(float *dst, const int16_t *src, int len);
64 ;------------------------------------------------------------------------------
65
66 %macro CONV_S16_TO_FLT 0
67 cglobal conv_s16_to_flt, 3,3,3, dst, src, len
68     lea      lenq, [2*lend]
69     add      srcq, lenq
70     lea      dstq, [dstq + 2*lenq]
71     neg      lenq
72     mova       m2, [pf_s16_inv_scale]
73     ALIGN 16
74 .loop:
75     mova       m0, [srcq+lenq]
76     S16_TO_S32_SX 0, 1
77     cvtdq2ps   m0, m0
78     cvtdq2ps   m1, m1
79     mulps      m0, m2
80     mulps      m1, m2
81     mova  [dstq+2*lenq       ], m0
82     mova  [dstq+2*lenq+mmsize], m1
83     add      lenq, mmsize
84     jl .loop
85     REP_RET
86 %endmacro
87
88 INIT_XMM sse2
89 CONV_S16_TO_FLT
90 INIT_XMM sse4
91 CONV_S16_TO_FLT
92
93 ;------------------------------------------------------------------------------
94 ; void ff_conv_s32_to_s16(int16_t *dst, const int32_t *src, int len);
95 ;------------------------------------------------------------------------------
96
97 %macro CONV_S32_TO_S16 0
98 cglobal conv_s32_to_s16, 3,3,4, dst, src, len
99     lea     lenq, [2*lend]
100     lea     srcq, [srcq+2*lenq]
101     add     dstq, lenq
102     neg     lenq
103 .loop:
104     mova      m0, [srcq+2*lenq         ]
105     mova      m1, [srcq+2*lenq+  mmsize]
106     mova      m2, [srcq+2*lenq+2*mmsize]
107     mova      m3, [srcq+2*lenq+3*mmsize]
108     psrad     m0, 16
109     psrad     m1, 16
110     psrad     m2, 16
111     psrad     m3, 16
112     packssdw  m0, m1
113     packssdw  m2, m3
114     mova  [dstq+lenq       ], m0
115     mova  [dstq+lenq+mmsize], m2
116     add     lenq, mmsize*2
117     jl .loop
118 %if mmsize == 8
119     emms
120     RET
121 %else
122     REP_RET
123 %endif
124 %endmacro
125
126 INIT_MMX mmx
127 CONV_S32_TO_S16
128 INIT_XMM sse2
129 CONV_S32_TO_S16
130
131 ;------------------------------------------------------------------------------
132 ; void ff_conv_s32_to_flt(float *dst, const int32_t *src, int len);
133 ;------------------------------------------------------------------------------
134
135 %macro CONV_S32_TO_FLT 0
136 cglobal conv_s32_to_flt, 3,3,3, dst, src, len
137     lea     lenq, [4*lend]
138     add     srcq, lenq
139     add     dstq, lenq
140     neg     lenq
141     mova      m0, [pf_s32_inv_scale]
142     ALIGN 16
143 .loop:
144     cvtdq2ps  m1, [srcq+lenq       ]
145     cvtdq2ps  m2, [srcq+lenq+mmsize]
146     mulps     m1, m1, m0
147     mulps     m2, m2, m0
148     mova  [dstq+lenq       ], m1
149     mova  [dstq+lenq+mmsize], m2
150     add     lenq, mmsize*2
151     jl .loop
152     REP_RET
153 %endmacro
154
155 INIT_XMM sse2
156 CONV_S32_TO_FLT
157 %if HAVE_AVX
158 INIT_YMM avx
159 CONV_S32_TO_FLT
160 %endif
161
162 ;------------------------------------------------------------------------------
163 ; void ff_conv_flt_to_s16(int16_t *dst, const float *src, int len);
164 ;------------------------------------------------------------------------------
165
166 INIT_XMM sse2
167 cglobal conv_flt_to_s16, 3,3,5, dst, src, len
168     lea     lenq, [2*lend]
169     lea     srcq, [srcq+2*lenq]
170     add     dstq, lenq
171     neg     lenq
172     mova      m4, [pf_s16_scale]
173 .loop:
174     mova      m0, [srcq+2*lenq         ]
175     mova      m1, [srcq+2*lenq+1*mmsize]
176     mova      m2, [srcq+2*lenq+2*mmsize]
177     mova      m3, [srcq+2*lenq+3*mmsize]
178     mulps     m0, m4
179     mulps     m1, m4
180     mulps     m2, m4
181     mulps     m3, m4
182     cvtps2dq  m0, m0
183     cvtps2dq  m1, m1
184     cvtps2dq  m2, m2
185     cvtps2dq  m3, m3
186     packssdw  m0, m1
187     packssdw  m2, m3
188     mova  [dstq+lenq       ], m0
189     mova  [dstq+lenq+mmsize], m2
190     add     lenq, mmsize*2
191     jl .loop
192     REP_RET
193
194 ;------------------------------------------------------------------------------
195 ; void ff_conv_flt_to_s32(int32_t *dst, const float *src, int len);
196 ;------------------------------------------------------------------------------
197
198 %macro CONV_FLT_TO_S32 0
199 cglobal conv_flt_to_s32, 3,3,5, dst, src, len
200     lea     lenq, [lend*4]
201     add     srcq, lenq
202     add     dstq, lenq
203     neg     lenq
204     mova      m4, [pf_s32_scale]
205 .loop:
206     mulps     m0, m4, [srcq+lenq         ]
207     mulps     m1, m4, [srcq+lenq+1*mmsize]
208     mulps     m2, m4, [srcq+lenq+2*mmsize]
209     mulps     m3, m4, [srcq+lenq+3*mmsize]
210     cvtps2dq  m0, m0
211     cvtps2dq  m1, m1
212     cvtps2dq  m2, m2
213     cvtps2dq  m3, m3
214     mova  [dstq+lenq         ], m0
215     mova  [dstq+lenq+1*mmsize], m1
216     mova  [dstq+lenq+2*mmsize], m2
217     mova  [dstq+lenq+3*mmsize], m3
218     add     lenq, mmsize*4
219     jl .loop
220     REP_RET
221 %endmacro
222
223 INIT_XMM sse2
224 CONV_FLT_TO_S32
225 %if HAVE_AVX
226 INIT_YMM avx
227 CONV_FLT_TO_S32
228 %endif
229
230 ;------------------------------------------------------------------------------
231 ; void ff_conv_s16p_to_s16_2ch(int16_t *dst, int16_t *const *src, int len,
232 ;                              int channels);
233 ;------------------------------------------------------------------------------
234
235 %macro CONV_S16P_TO_S16_2CH 0
236 cglobal conv_s16p_to_s16_2ch, 3,4,5, dst, src0, len, src1
237     mov       src1q, [src0q+gprsize]
238     mov       src0q, [src0q        ]
239     lea        lenq, [2*lend]
240     add       src0q, lenq
241     add       src1q, lenq
242     lea        dstq, [dstq+2*lenq]
243     neg        lenq
244 .loop
245     mova         m0, [src0q+lenq       ]
246     mova         m1, [src1q+lenq       ]
247     mova         m2, [src0q+lenq+mmsize]
248     mova         m3, [src1q+lenq+mmsize]
249     SBUTTERFLY2  wd, 0, 1, 4
250     SBUTTERFLY2  wd, 2, 3, 4
251     mova  [dstq+2*lenq+0*mmsize], m0
252     mova  [dstq+2*lenq+1*mmsize], m1
253     mova  [dstq+2*lenq+2*mmsize], m2
254     mova  [dstq+2*lenq+3*mmsize], m3
255     add        lenq, 2*mmsize
256     jl .loop
257     REP_RET
258 %endmacro
259
260 INIT_XMM sse2
261 CONV_S16P_TO_S16_2CH
262 %if HAVE_AVX
263 INIT_XMM avx
264 CONV_S16P_TO_S16_2CH
265 %endif
266
267 ;------------------------------------------------------------------------------
268 ; void ff_conv_s16p_to_s16_6ch(int16_t *dst, int16_t *const *src, int len,
269 ;                              int channels);
270 ;------------------------------------------------------------------------------
271
272 ;------------------------------------------------------------------------------
273 ; NOTE: In the 6-channel functions, len could be used as an index on x86-64
274 ;       instead of just a counter, which would avoid incrementing the
275 ;       pointers, but the extra complexity and amount of code is not worth
276 ;       the small gain. On x86-32 there are not enough registers to use len
277 ;       as an index without keeping two of the pointers on the stack and
278 ;       loading them in each iteration.
279 ;------------------------------------------------------------------------------
280
281 %macro CONV_S16P_TO_S16_6CH 0
282 %if ARCH_X86_64
283 cglobal conv_s16p_to_s16_6ch, 3,8,7, dst, src0, len, src1, src2, src3, src4, src5
284 %else
285 cglobal conv_s16p_to_s16_6ch, 2,7,7, dst, src0, src1, src2, src3, src4, src5
286 %define lend dword r2m
287 %endif
288     mov      src1q, [src0q+1*gprsize]
289     mov      src2q, [src0q+2*gprsize]
290     mov      src3q, [src0q+3*gprsize]
291     mov      src4q, [src0q+4*gprsize]
292     mov      src5q, [src0q+5*gprsize]
293     mov      src0q, [src0q]
294     sub      src1q, src0q
295     sub      src2q, src0q
296     sub      src3q, src0q
297     sub      src4q, src0q
298     sub      src5q, src0q
299 .loop:
300 %if cpuflag(sse2slow)
301     movq        m0, [src0q      ]   ; m0 =  0,  6, 12, 18,  x,  x,  x,  x
302     movq        m1, [src0q+src1q]   ; m1 =  1,  7, 13, 19,  x,  x,  x,  x
303     movq        m2, [src0q+src2q]   ; m2 =  2,  8, 14, 20,  x,  x,  x,  x
304     movq        m3, [src0q+src3q]   ; m3 =  3,  9, 15, 21,  x,  x,  x,  x
305     movq        m4, [src0q+src4q]   ; m4 =  4, 10, 16, 22,  x,  x,  x,  x
306     movq        m5, [src0q+src5q]   ; m5 =  5, 11, 17, 23,  x,  x,  x,  x
307                                     ; unpack words:
308     punpcklwd   m0, m1              ; m0 =  0,  1,  6,  7, 12, 13, 18, 19
309     punpcklwd   m2, m3              ; m2 =  4,  5, 10, 11, 16, 17, 22, 23
310     punpcklwd   m4, m5              ; m4 =  2,  3,  8,  9, 14, 15, 20, 21
311                                     ; blend dwords
312     shufps      m1, m0, m2, q2020   ; m1 =  0,  1, 12, 13,  2,  3, 14, 15
313     shufps      m0, m4, q2031       ; m0 =  6,  7, 18, 19,  4,  5, 16, 17
314     shufps      m2, m4, q3131       ; m2 =  8,  9, 20, 21, 10, 11, 22, 23
315                                     ; shuffle dwords
316     pshufd      m0, m0, q1302       ; m0 =  4,  5,  6,  7, 16, 17, 18, 19
317     pshufd      m1, m1, q3120       ; m1 =  0,  1,  2,  3, 12, 13, 14, 15
318     pshufd      m2, m2, q3120       ; m2 =  8,  9, 10, 11, 20, 21, 22, 23
319     movq   [dstq+0*mmsize/2], m1
320     movq   [dstq+1*mmsize/2], m0
321     movq   [dstq+2*mmsize/2], m2
322     movhps [dstq+3*mmsize/2], m1
323     movhps [dstq+4*mmsize/2], m0
324     movhps [dstq+5*mmsize/2], m2
325     add      src0q, mmsize/2
326     add       dstq, mmsize*3
327     sub       lend, mmsize/4
328 %else
329     mova        m0, [src0q      ]   ; m0 =  0,  6, 12, 18, 24, 30, 36, 42
330     mova        m1, [src0q+src1q]   ; m1 =  1,  7, 13, 19, 25, 31, 37, 43
331     mova        m2, [src0q+src2q]   ; m2 =  2,  8, 14, 20, 26, 32, 38, 44
332     mova        m3, [src0q+src3q]   ; m3 =  3,  9, 15, 21, 27, 33, 39, 45
333     mova        m4, [src0q+src4q]   ; m4 =  4, 10, 16, 22, 28, 34, 40, 46
334     mova        m5, [src0q+src5q]   ; m5 =  5, 11, 17, 23, 29, 35, 41, 47
335                                     ; unpack words:
336     SBUTTERFLY2 wd, 0, 1, 6         ; m0 =  0,  1,  6,  7, 12, 13, 18, 19
337                                     ; m1 = 24, 25, 30, 31, 36, 37, 42, 43
338     SBUTTERFLY2 wd, 2, 3, 6         ; m2 =  2,  3,  8,  9, 14, 15, 20, 21
339                                     ; m3 = 26, 27, 32, 33, 38, 39, 44, 45
340     SBUTTERFLY2 wd, 4, 5, 6         ; m4 =  4,  5, 10, 11, 16, 17, 22, 23
341                                     ; m5 = 28, 29, 34, 35, 40, 41, 46, 47
342                                     ; blend dwords
343     shufps      m6, m0, m2, q2020   ; m6 =  0,  1, 12, 13,  2,  3, 14, 15
344     shufps      m0, m4, q2031       ; m0 =  6,  7, 18, 19,  4,  5, 16, 17
345     shufps      m2, m4, q3131       ; m2 =  8,  9, 20, 21, 10, 11, 22, 23
346     SWAP 4,6                        ; m4 =  0,  1, 12, 13,  2,  3, 14, 15
347     shufps      m6, m1, m3, q2020   ; m6 = 24, 25, 36, 37, 26, 27, 38, 39
348     shufps      m1, m5, q2031       ; m1 = 30, 31, 42, 43, 28, 29, 40, 41
349     shufps      m3, m5, q3131       ; m3 = 32, 33, 44, 45, 34, 35, 46, 47
350     SWAP 5,6                        ; m5 = 24, 25, 36, 37, 26, 27, 38, 39
351                                     ; shuffle dwords
352     pshufd      m0, m0, q1302       ; m0 =  4,  5,  6,  7, 16, 17, 18, 19
353     pshufd      m2, m2, q3120       ; m2 =  8,  9, 10, 11, 20, 21, 22, 23
354     pshufd      m4, m4, q3120       ; m4 =  0,  1,  2,  3, 12, 13, 14, 15
355     pshufd      m1, m1, q1302       ; m1 = 28, 29, 30, 31, 40, 41, 42, 43
356     pshufd      m3, m3, q3120       ; m3 = 32, 33, 34, 35, 44, 45, 46, 47
357     pshufd      m5, m5, q3120       ; m5 = 24, 25, 26, 27, 36, 37, 38, 39
358                                     ; shuffle qwords
359     punpcklqdq  m6, m4, m0          ; m6 =  0,  1,  2,  3,  4,  5,  6,  7
360     punpckhqdq  m0, m2              ; m0 = 16, 17, 18, 19, 20, 21, 22, 23
361     shufps      m2, m4, q3210       ; m2 =  8,  9, 10, 11, 12, 13, 14, 15
362     SWAP 4,6                        ; m4 =  0,  1,  2,  3,  4,  5,  6,  7
363     punpcklqdq  m6, m5, m1          ; m6 = 24, 25, 26, 27, 28, 29, 30, 31
364     punpckhqdq  m1, m3              ; m1 = 40, 41, 42, 43, 44, 45, 46, 47
365     shufps      m3, m5, q3210       ; m3 = 32, 33, 34, 35, 36, 37, 38, 39
366     SWAP 5,6                        ; m5 = 24, 25, 26, 27, 28, 29, 30, 31
367     mova   [dstq+0*mmsize], m4
368     mova   [dstq+1*mmsize], m2
369     mova   [dstq+2*mmsize], m0
370     mova   [dstq+3*mmsize], m5
371     mova   [dstq+4*mmsize], m3
372     mova   [dstq+5*mmsize], m1
373     add      src0q, mmsize
374     add       dstq, mmsize*6
375     sub       lend, mmsize/2
376 %endif
377     jg .loop
378     REP_RET
379 %endmacro
380
381 INIT_XMM sse2
382 CONV_S16P_TO_S16_6CH
383 INIT_XMM sse2slow
384 CONV_S16P_TO_S16_6CH
385 %if HAVE_AVX
386 INIT_XMM avx
387 CONV_S16P_TO_S16_6CH
388 %endif
389
390 ;------------------------------------------------------------------------------
391 ; void ff_conv_s16p_to_flt_2ch(float *dst, int16_t *const *src, int len,
392 ;                              int channels);
393 ;------------------------------------------------------------------------------
394
395 %macro CONV_S16P_TO_FLT_2CH 0
396 cglobal conv_s16p_to_flt_2ch, 3,4,6, dst, src0, len, src1
397     lea       lenq, [2*lend]
398     mov      src1q, [src0q+gprsize]
399     mov      src0q, [src0q        ]
400     lea       dstq, [dstq+4*lenq]
401     add      src0q, lenq
402     add      src1q, lenq
403     neg       lenq
404     mova        m5, [pf_s32_inv_scale]
405 .loop:
406     mova        m2, [src0q+lenq]    ; m2 =  0,  2,  4,  6,  8, 10, 12, 14
407     mova        m4, [src1q+lenq]    ; m4 =  1,  3,  5,  7,  9, 11, 13, 15
408     SBUTTERFLY2 wd, 2, 4, 3         ; m2 =  0,  1,  2,  3,  4,  5,  6,  7
409                                     ; m4 =  8,  9, 10, 11, 12, 13, 14, 15
410     pxor        m3, m3
411     punpcklwd   m0, m3, m2          ; m0 =      0,      1,      2,      3
412     punpckhwd   m1, m3, m2          ; m1 =      4,      5,      6,      7
413     punpcklwd   m2, m3, m4          ; m2 =      8,      9,     10,     11
414     punpckhwd   m3, m4              ; m3 =     12,     13,     14,     15
415     cvtdq2ps    m0, m0
416     cvtdq2ps    m1, m1
417     cvtdq2ps    m2, m2
418     cvtdq2ps    m3, m3
419     mulps       m0, m5
420     mulps       m1, m5
421     mulps       m2, m5
422     mulps       m3, m5
423     mova  [dstq+4*lenq         ], m0
424     mova  [dstq+4*lenq+  mmsize], m1
425     mova  [dstq+4*lenq+2*mmsize], m2
426     mova  [dstq+4*lenq+3*mmsize], m3
427     add       lenq, mmsize
428     jl .loop
429     REP_RET
430 %endmacro
431
432 INIT_XMM sse2
433 CONV_S16P_TO_FLT_2CH
434 %if HAVE_AVX
435 INIT_XMM avx
436 CONV_S16P_TO_FLT_2CH
437 %endif
438
439 ;------------------------------------------------------------------------------
440 ; void ff_conv_s16p_to_flt_6ch(float *dst, int16_t *const *src, int len,
441 ;                              int channels);
442 ;------------------------------------------------------------------------------
443
444 %macro CONV_S16P_TO_FLT_6CH 0
445 %if ARCH_X86_64
446 cglobal conv_s16p_to_flt_6ch, 3,8,8, dst, src, len, src1, src2, src3, src4, src5
447 %else
448 cglobal conv_s16p_to_flt_6ch, 2,7,8, dst, src, src1, src2, src3, src4, src5
449 %define lend dword r2m
450 %endif
451     mov     src1q, [srcq+1*gprsize]
452     mov     src2q, [srcq+2*gprsize]
453     mov     src3q, [srcq+3*gprsize]
454     mov     src4q, [srcq+4*gprsize]
455     mov     src5q, [srcq+5*gprsize]
456     mov      srcq, [srcq]
457     sub     src1q, srcq
458     sub     src2q, srcq
459     sub     src3q, srcq
460     sub     src4q, srcq
461     sub     src5q, srcq
462     mova       m7, [pf_s32_inv_scale]
463 %if cpuflag(ssse3)
464     %define unpack_even m6
465     mova       m6, [pb_shuf_unpack_even]
466 %if ARCH_X86_64
467     %define unpack_odd m8
468     mova       m8, [pb_shuf_unpack_odd]
469 %else
470     %define unpack_odd [pb_shuf_unpack_odd]
471 %endif
472 %endif
473 .loop:
474     movq       m0, [srcq      ]  ; m0 =  0,  6, 12, 18,  x,  x,  x,  x
475     movq       m1, [srcq+src1q]  ; m1 =  1,  7, 13, 19,  x,  x,  x,  x
476     movq       m2, [srcq+src2q]  ; m2 =  2,  8, 14, 20,  x,  x,  x,  x
477     movq       m3, [srcq+src3q]  ; m3 =  3,  9, 15, 21,  x,  x,  x,  x
478     movq       m4, [srcq+src4q]  ; m4 =  4, 10, 16, 22,  x,  x,  x,  x
479     movq       m5, [srcq+src5q]  ; m5 =  5, 11, 17, 23,  x,  x,  x,  x
480                                  ; unpack words:
481     punpcklwd  m0, m1            ; m0 =  0,  1,  6,  7, 12, 13, 18, 19
482     punpcklwd  m2, m3            ; m2 =  2,  3,  8,  9, 14, 15, 20, 21
483     punpcklwd  m4, m5            ; m4 =  4,  5, 10, 11, 16, 17, 22, 23
484                                  ; blend dwords
485     shufps     m1, m4, m0, q3120 ; m1 =  4,  5, 16, 17,  6,  7, 18, 19
486     shufps         m0, m2, q2020 ; m0 =  0,  1, 12, 13,  2,  3, 14, 15
487     shufps         m2, m4, q3131 ; m2 =  8,  9, 20, 21, 10, 11, 22, 23
488 %if cpuflag(ssse3)
489     pshufb     m3, m0, unpack_odd   ; m3 =  12,     13,     14,     15
490     pshufb         m0, unpack_even  ; m0 =   0,      1,      2,      3
491     pshufb     m4, m1, unpack_odd   ; m4 =  16,     17,     18,     19
492     pshufb         m1, unpack_even  ; m1 =   4,      5,      6,      7
493     pshufb     m5, m2, unpack_odd   ; m5 =  20,     21,     22,     23
494     pshufb         m2, unpack_even  ; m2 =   8,      9,     10,     11
495 %else
496                                  ; shuffle dwords
497     pshufd     m0, m0, q3120     ; m0 =  0,  1,  2,  3, 12, 13, 14, 15
498     pshufd     m1, m1, q3120     ; m1 =  4,  5,  6,  7, 16, 17, 18, 19
499     pshufd     m2, m2, q3120     ; m2 =  8,  9, 10, 11, 20, 21, 22, 23
500     pxor       m6, m6            ; convert s16 in m0-m2 to s32 in m0-m5
501     punpcklwd  m3, m6, m0        ; m3 =      0,      1,      2,      3
502     punpckhwd  m4, m6, m0        ; m4 =     12,     13,     14,     15
503     punpcklwd  m0, m6, m1        ; m0 =      4,      5,      6,      7
504     punpckhwd  m5, m6, m1        ; m5 =     16,     17,     18,     19
505     punpcklwd  m1, m6, m2        ; m1 =      8,      9,     10,     11
506     punpckhwd      m6, m2        ; m6 =     20,     21,     22,     23
507     SWAP 6,2,1,0,3,4,5           ; swap registers 3,0,1,4,5,6 to 0,1,2,3,4,5
508 %endif
509     cvtdq2ps   m0, m0            ; convert s32 to float
510     cvtdq2ps   m1, m1
511     cvtdq2ps   m2, m2
512     cvtdq2ps   m3, m3
513     cvtdq2ps   m4, m4
514     cvtdq2ps   m5, m5
515     mulps      m0, m7            ; scale float from s32 range to [-1.0,1.0]
516     mulps      m1, m7
517     mulps      m2, m7
518     mulps      m3, m7
519     mulps      m4, m7
520     mulps      m5, m7
521     mova  [dstq         ], m0
522     mova  [dstq+  mmsize], m1
523     mova  [dstq+2*mmsize], m2
524     mova  [dstq+3*mmsize], m3
525     mova  [dstq+4*mmsize], m4
526     mova  [dstq+5*mmsize], m5
527     add      srcq, mmsize/2
528     add      dstq, mmsize*6
529     sub      lend, mmsize/4
530     jg .loop
531     REP_RET
532 %endmacro
533
534 INIT_XMM sse2
535 CONV_S16P_TO_FLT_6CH
536 INIT_XMM ssse3
537 CONV_S16P_TO_FLT_6CH
538 %if HAVE_AVX
539 INIT_XMM avx
540 CONV_S16P_TO_FLT_6CH
541 %endif
542
543 ;------------------------------------------------------------------------------
544 ; void ff_conv_fltp_to_s16_2ch(int16_t *dst, float *const *src, int len,
545 ;                              int channels);
546 ;------------------------------------------------------------------------------
547
548 %macro CONV_FLTP_TO_S16_2CH 0
549 cglobal conv_fltp_to_s16_2ch, 3,4,3, dst, src0, len, src1
550     lea      lenq, [4*lend]
551     mov     src1q, [src0q+gprsize]
552     mov     src0q, [src0q        ]
553     add      dstq, lenq
554     add     src0q, lenq
555     add     src1q, lenq
556     neg      lenq
557     mova       m2, [pf_s16_scale]
558 %if cpuflag(ssse3)
559     mova       m3, [pb_interleave_words]
560 %endif
561 .loop:
562     mulps      m0, m2, [src0q+lenq] ; m0 =    0,    2,    4,    6
563     mulps      m1, m2, [src1q+lenq] ; m1 =    1,    3,    5,    7
564     cvtps2dq   m0, m0
565     cvtps2dq   m1, m1
566 %if cpuflag(ssse3)
567     packssdw   m0, m1               ; m0 = 0, 2, 4, 6, 1, 3, 5, 7
568     pshufb     m0, m3               ; m0 = 0, 1, 2, 3, 4, 5, 6, 7
569 %else
570     packssdw   m0, m0               ; m0 = 0, 2, 4, 6, x, x, x, x
571     packssdw   m1, m1               ; m1 = 1, 3, 5, 7, x, x, x, x
572     punpcklwd  m0, m1               ; m0 = 0, 1, 2, 3, 4, 5, 6, 7
573 %endif
574     mova  [dstq+lenq], m0
575     add      lenq, mmsize
576     jl .loop
577     REP_RET
578 %endmacro
579
580 INIT_XMM sse2
581 CONV_FLTP_TO_S16_2CH
582 INIT_XMM ssse3
583 CONV_FLTP_TO_S16_2CH
584
585 ;------------------------------------------------------------------------------
586 ; void ff_conv_fltp_to_s16_6ch(int16_t *dst, float *const *src, int len,
587 ;                              int channels);
588 ;------------------------------------------------------------------------------
589
590 %macro CONV_FLTP_TO_S16_6CH 0
591 %if ARCH_X86_64
592 cglobal conv_fltp_to_s16_6ch, 3,8,7, dst, src, len, src1, src2, src3, src4, src5
593 %else
594 cglobal conv_fltp_to_s16_6ch, 2,7,7, dst, src, src1, src2, src3, src4, src5
595 %define lend dword r2m
596 %endif
597     mov        src1q, [srcq+1*gprsize]
598     mov        src2q, [srcq+2*gprsize]
599     mov        src3q, [srcq+3*gprsize]
600     mov        src4q, [srcq+4*gprsize]
601     mov        src5q, [srcq+5*gprsize]
602     mov         srcq, [srcq]
603     sub        src1q, srcq
604     sub        src2q, srcq
605     sub        src3q, srcq
606     sub        src4q, srcq
607     sub        src5q, srcq
608     movaps      xmm6, [pf_s16_scale]
609 .loop:
610 %if cpuflag(sse2)
611     mulps         m0, m6, [srcq      ]
612     mulps         m1, m6, [srcq+src1q]
613     mulps         m2, m6, [srcq+src2q]
614     mulps         m3, m6, [srcq+src3q]
615     mulps         m4, m6, [srcq+src4q]
616     mulps         m5, m6, [srcq+src5q]
617     cvtps2dq      m0, m0
618     cvtps2dq      m1, m1
619     cvtps2dq      m2, m2
620     cvtps2dq      m3, m3
621     cvtps2dq      m4, m4
622     cvtps2dq      m5, m5
623     packssdw      m0, m3            ; m0 =  0,  6, 12, 18,  3,  9, 15, 21
624     packssdw      m1, m4            ; m1 =  1,  7, 13, 19,  4, 10, 16, 22
625     packssdw      m2, m5            ; m2 =  2,  8, 14, 20,  5, 11, 17, 23
626                                     ; unpack words:
627     movhlps       m3, m0            ; m3 =  3,  9, 15, 21,  x,  x,  x,  x
628     punpcklwd     m0, m1            ; m0 =  0,  1,  6,  7, 12, 13, 18, 19
629     punpckhwd     m1, m2            ; m1 =  4,  5, 10, 11, 16, 17, 22, 23
630     punpcklwd     m2, m3            ; m2 =  2,  3,  8,  9, 14, 15, 20, 21
631                                     ; blend dwords:
632     shufps        m3, m0, m2, q2020 ; m3 =  0,  1, 12, 13,  2,  3, 14, 15
633     shufps        m0, m1, q2031     ; m0 =  6,  7, 18, 19,  4,  5, 16, 17
634     shufps        m2, m1, q3131     ; m2 =  8,  9, 20, 21, 10, 11, 22, 23
635                                     ; shuffle dwords:
636     shufps        m1, m2, m3, q3120 ; m1 =  8,  9, 10, 11, 12, 13, 14, 15
637     shufps        m3, m0,     q0220 ; m3 =  0,  1,  2,  3,  4,  5,  6,  7
638     shufps        m0, m2,     q3113 ; m0 = 16, 17, 18, 19, 20, 21, 22, 23
639     mova  [dstq+0*mmsize], m3
640     mova  [dstq+1*mmsize], m1
641     mova  [dstq+2*mmsize], m0
642 %else ; sse
643     movlps      xmm0, [srcq      ]
644     movlps      xmm1, [srcq+src1q]
645     movlps      xmm2, [srcq+src2q]
646     movlps      xmm3, [srcq+src3q]
647     movlps      xmm4, [srcq+src4q]
648     movlps      xmm5, [srcq+src5q]
649     mulps       xmm0, xmm6
650     mulps       xmm1, xmm6
651     mulps       xmm2, xmm6
652     mulps       xmm3, xmm6
653     mulps       xmm4, xmm6
654     mulps       xmm5, xmm6
655     cvtps2pi     mm0, xmm0
656     cvtps2pi     mm1, xmm1
657     cvtps2pi     mm2, xmm2
658     cvtps2pi     mm3, xmm3
659     cvtps2pi     mm4, xmm4
660     cvtps2pi     mm5, xmm5
661     packssdw     mm0, mm3           ; m0 =  0,  6,  3,  9
662     packssdw     mm1, mm4           ; m1 =  1,  7,  4, 10
663     packssdw     mm2, mm5           ; m2 =  2,  8,  5, 11
664                                     ; unpack words
665     pshufw       mm3, mm0, q1032    ; m3 =  3,  9,  0,  6
666     punpcklwd    mm0, mm1           ; m0 =  0,  1,  6,  7
667     punpckhwd    mm1, mm2           ; m1 =  4,  5, 10, 11
668     punpcklwd    mm2, mm3           ; m2 =  2,  3,  8,  9
669                                     ; unpack dwords
670     pshufw       mm3, mm0, q1032    ; m3 =  6,  7,  0,  1
671     punpckldq    mm0, mm2           ; m0 =  0,  1,  2,  3 (final)
672     punpckhdq    mm2, mm1           ; m2 =  8,  9, 10, 11 (final)
673     punpckldq    mm1, mm3           ; m1 =  4,  5,  6,  7 (final)
674     mova  [dstq+0*mmsize], mm0
675     mova  [dstq+1*mmsize], mm1
676     mova  [dstq+2*mmsize], mm2
677 %endif
678     add       srcq, mmsize
679     add       dstq, mmsize*3
680     sub       lend, mmsize/4
681     jg .loop
682 %if mmsize == 8
683     emms
684     RET
685 %else
686     REP_RET
687 %endif
688 %endmacro
689
690 INIT_MMX sse
691 CONV_FLTP_TO_S16_6CH
692 INIT_XMM sse2
693 CONV_FLTP_TO_S16_6CH
694 %if HAVE_AVX
695 INIT_XMM avx
696 CONV_FLTP_TO_S16_6CH
697 %endif
698
699 ;------------------------------------------------------------------------------
700 ; void ff_conv_fltp_to_flt_2ch(float *dst, float *const *src, int len,
701 ;                              int channels);
702 ;------------------------------------------------------------------------------
703
704 %macro CONV_FLTP_TO_FLT_2CH 0
705 cglobal conv_fltp_to_flt_2ch, 3,4,5, dst, src0, len, src1
706     mov  src1q, [src0q+gprsize]
707     mov  src0q, [src0q]
708     lea   lenq, [4*lend]
709     add  src0q, lenq
710     add  src1q, lenq
711     lea   dstq, [dstq+2*lenq]
712     neg   lenq
713 .loop
714     mova    m0, [src0q+lenq       ]
715     mova    m1, [src1q+lenq       ]
716     mova    m2, [src0q+lenq+mmsize]
717     mova    m3, [src1q+lenq+mmsize]
718     SBUTTERFLYPS 0, 1, 4
719     SBUTTERFLYPS 2, 3, 4
720     mova  [dstq+2*lenq+0*mmsize], m0
721     mova  [dstq+2*lenq+1*mmsize], m1
722     mova  [dstq+2*lenq+2*mmsize], m2
723     mova  [dstq+2*lenq+3*mmsize], m3
724     add   lenq, 2*mmsize
725     jl .loop
726     REP_RET
727 %endmacro
728
729 INIT_XMM sse
730 CONV_FLTP_TO_FLT_2CH
731 %if HAVE_AVX
732 INIT_XMM avx
733 CONV_FLTP_TO_FLT_2CH
734 %endif
735
736 ;-----------------------------------------------------------------------------
737 ; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len,
738 ;                              int channels);
739 ;-----------------------------------------------------------------------------
740
741 %macro CONV_FLTP_TO_FLT_6CH 0
742 cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
743 %if ARCH_X86_64
744     mov     lend, r2d
745 %else
746     %define lend dword r2m
747 %endif
748     mov    src1q, [srcq+1*gprsize]
749     mov    src2q, [srcq+2*gprsize]
750     mov    src3q, [srcq+3*gprsize]
751     mov    src4q, [srcq+4*gprsize]
752     mov    src5q, [srcq+5*gprsize]
753     mov     srcq, [srcq]
754     sub    src1q, srcq
755     sub    src2q, srcq
756     sub    src3q, srcq
757     sub    src4q, srcq
758     sub    src5q, srcq
759 .loop:
760     mova      m0, [srcq      ]
761     mova      m1, [srcq+src1q]
762     mova      m2, [srcq+src2q]
763     mova      m3, [srcq+src3q]
764     mova      m4, [srcq+src4q]
765     mova      m5, [srcq+src5q]
766 %if cpuflag(sse4)
767     SBUTTERFLYPS 0, 1, 6
768     SBUTTERFLYPS 2, 3, 6
769     SBUTTERFLYPS 4, 5, 6
770
771     blendps   m6, m4, m0, 1100b
772     movlhps   m0, m2
773     movhlps   m4, m2
774     blendps   m2, m5, m1, 1100b
775     movlhps   m1, m3
776     movhlps   m5, m3
777
778     movaps [dstq   ], m0
779     movaps [dstq+16], m6
780     movaps [dstq+32], m4
781     movaps [dstq+48], m1
782     movaps [dstq+64], m2
783     movaps [dstq+80], m5
784 %else ; mmx
785     SBUTTERFLY dq, 0, 1, 6
786     SBUTTERFLY dq, 2, 3, 6
787     SBUTTERFLY dq, 4, 5, 6
788
789     movq   [dstq   ], m0
790     movq   [dstq+ 8], m2
791     movq   [dstq+16], m4
792     movq   [dstq+24], m1
793     movq   [dstq+32], m3
794     movq   [dstq+40], m5
795 %endif
796     add      srcq, mmsize
797     add      dstq, mmsize*6
798     sub      lend, mmsize/4
799     jg .loop
800 %if mmsize == 8
801     emms
802     RET
803 %else
804     REP_RET
805 %endif
806 %endmacro
807
808 INIT_MMX mmx
809 CONV_FLTP_TO_FLT_6CH
810 INIT_XMM sse4
811 CONV_FLTP_TO_FLT_6CH
812 %if HAVE_AVX
813 INIT_XMM avx
814 CONV_FLTP_TO_FLT_6CH
815 %endif
816
817 ;------------------------------------------------------------------------------
818 ; void ff_conv_s16_to_s16p_2ch(int16_t *const *dst, int16_t *src, int len,
819 ;                              int channels);
820 ;------------------------------------------------------------------------------
821
822 %macro CONV_S16_TO_S16P_2CH 0
823 cglobal conv_s16_to_s16p_2ch, 3,4,4, dst0, src, len, dst1
824     lea       lenq, [2*lend]
825     mov      dst1q, [dst0q+gprsize]
826     mov      dst0q, [dst0q        ]
827     lea       srcq, [srcq+2*lenq]
828     add      dst0q, lenq
829     add      dst1q, lenq
830     neg       lenq
831 %if cpuflag(ssse3)
832     mova        m3, [pb_deinterleave_words]
833 %endif
834 .loop:
835     mova        m0, [srcq+2*lenq       ]  ; m0 =  0,  1,  2,  3,  4,  5,  6,  7
836     mova        m1, [srcq+2*lenq+mmsize]  ; m1 =  8,  9, 10, 11, 12, 13, 14, 15
837 %if cpuflag(ssse3)
838     pshufb      m0, m3                    ; m0 =  0,  2,  4,  6,  1,  3,  5,  7
839     pshufb      m1, m3                    ; m1 =  8, 10, 12, 14,  9, 11, 13, 15
840     SBUTTERFLY2 qdq, 0, 1, 2              ; m0 =  0,  2,  4,  6,  8, 10, 12, 14
841                                           ; m1 =  1,  3,  5,  7,  9, 11, 13, 15
842 %else ; sse2
843     pshuflw     m0, m0, q3120             ; m0 =  0,  2,  1,  3,  4,  5,  6,  7
844     pshufhw     m0, m0, q3120             ; m0 =  0,  2,  1,  3,  4,  6,  5,  7
845     pshuflw     m1, m1, q3120             ; m1 =  8, 10,  9, 11, 12, 13, 14, 15
846     pshufhw     m1, m1, q3120             ; m1 =  8, 10,  9, 11, 12, 14, 13, 15
847     DEINT2_PS    0, 1, 2                  ; m0 =  0,  2,  4,  6,  8, 10, 12, 14
848                                           ; m1 =  1,  3,  5,  7,  9, 11, 13, 15
849 %endif
850     mova  [dst0q+lenq], m0
851     mova  [dst1q+lenq], m1
852     add       lenq, mmsize
853     jl .loop
854     REP_RET
855 %endmacro
856
857 INIT_XMM sse2
858 CONV_S16_TO_S16P_2CH
859 INIT_XMM ssse3
860 CONV_S16_TO_S16P_2CH
861 %if HAVE_AVX
862 INIT_XMM avx
863 CONV_S16_TO_S16P_2CH
864 %endif
865
866 ;------------------------------------------------------------------------------
867 ; void ff_conv_s16_to_s16p_6ch(int16_t *const *dst, int16_t *src, int len,
868 ;                              int channels);
869 ;------------------------------------------------------------------------------
870
871 %macro CONV_S16_TO_S16P_6CH 0
872 %if ARCH_X86_64
873 cglobal conv_s16_to_s16p_6ch, 3,8,5, dst, src, len, dst1, dst2, dst3, dst4, dst5
874 %else
875 cglobal conv_s16_to_s16p_6ch, 2,7,5, dst, src, dst1, dst2, dst3, dst4, dst5
876 %define lend dword r2m
877 %endif
878     mov     dst1q, [dstq+  gprsize]
879     mov     dst2q, [dstq+2*gprsize]
880     mov     dst3q, [dstq+3*gprsize]
881     mov     dst4q, [dstq+4*gprsize]
882     mov     dst5q, [dstq+5*gprsize]
883     mov      dstq, [dstq          ]
884     sub     dst1q, dstq
885     sub     dst2q, dstq
886     sub     dst3q, dstq
887     sub     dst4q, dstq
888     sub     dst5q, dstq
889 .loop:
890     mova       m0, [srcq+0*mmsize]      ; m0 =  0,  1,  2,  3,  4,  5,  6,  7
891     mova       m3, [srcq+1*mmsize]      ; m3 =  8,  9, 10, 11, 12, 13, 14, 15
892     mova       m2, [srcq+2*mmsize]      ; m2 = 16, 17, 18, 19, 20, 21, 22, 23
893     PALIGNR    m1, m3, m0, 12, m4       ; m1 =  6,  7,  8,  9, 10, 11,  x,  x
894     shufps     m3, m2, q1032            ; m3 = 12, 13, 14, 15, 16, 17, 18, 19
895     psrldq     m2, 4                    ; m2 = 18, 19, 20, 21, 22, 23,  x,  x
896     SBUTTERFLY2 wd, 0, 1, 4             ; m0 =  0,  6,  1,  7,  2,  8,  3,  9
897                                         ; m1 =  4, 10,  5, 11,  x,  x,  x,  x
898     SBUTTERFLY2 wd, 3, 2, 4             ; m3 = 12, 18, 13, 19, 14, 20, 15, 21
899                                         ; m2 = 16, 22, 17, 23,  x,  x,  x,  x
900     SBUTTERFLY2 dq, 0, 3, 4             ; m0 =  0,  6, 12, 18,  1,  7, 13, 19
901                                         ; m3 =  2,  8, 14, 20,  3,  9, 15, 21
902     punpckldq  m1, m2                   ; m1 =  4, 10, 16, 22,  5, 11, 17, 23
903     movq    [dstq      ], m0
904     movhps  [dstq+dst1q], m0
905     movq    [dstq+dst2q], m3
906     movhps  [dstq+dst3q], m3
907     movq    [dstq+dst4q], m1
908     movhps  [dstq+dst5q], m1
909     add      srcq, mmsize*3
910     add      dstq, mmsize/2
911     sub      lend, mmsize/4
912     jg .loop
913     REP_RET
914 %endmacro
915
916 %define PALIGNR PALIGNR_MMX
917 INIT_XMM sse2
918 CONV_S16_TO_S16P_6CH
919 %define PALIGNR PALIGNR_SSSE3
920 INIT_XMM ssse3
921 CONV_S16_TO_S16P_6CH
922 %if HAVE_AVX
923 INIT_XMM avx
924 CONV_S16_TO_S16P_6CH
925 %endif