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