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