fb183ce9a67edf958c53eb851f960a5799af0ef8
[ffmpeg.git] / libavcodec / x86 / fmtconvert.asm
1 ;******************************************************************************
2 ;* x86 optimized Format Conversion Utils
3 ;* Copyright (c) 2008 Loren Merritt
4 ;*
5 ;* This file is part of Libav.
6 ;*
7 ;* Libav is free software; you can redistribute it and/or
8 ;* modify it under the terms of the GNU Lesser General Public
9 ;* License as published by the Free Software Foundation; either
10 ;* version 2.1 of the License, or (at your option) any later version.
11 ;*
12 ;* Libav is distributed in the hope that it will be useful,
13 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;* Lesser General Public License for more details.
16 ;*
17 ;* You should have received a copy of the GNU Lesser General Public
18 ;* License along with Libav; if not, write to the Free Software
19 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 ;******************************************************************************
21
22 %include "libavutil/x86/x86util.asm"
23
24 SECTION_TEXT
25
26 %macro CVTPS2PI 2
27 %if cpuflag(sse)
28     cvtps2pi %1, %2
29 %elif cpuflag(3dnow)
30     pf2id %1, %2
31 %endif
32 %endmacro
33
34 ;---------------------------------------------------------------------------------
35 ; void int32_to_float_fmul_scalar(float *dst, const int *src, float mul, int len);
36 ;---------------------------------------------------------------------------------
37 %macro INT32_TO_FLOAT_FMUL_SCALAR 1
38 %if UNIX64
39 cglobal int32_to_float_fmul_scalar, 3, 3, %1, dst, src, len
40 %else
41 cglobal int32_to_float_fmul_scalar, 4, 4, %1, dst, src, mul, len
42 %endif
43 %if WIN64
44     SWAP 0, 2
45 %elif ARCH_X86_32
46     movss   m0, mulm
47 %endif
48     SPLATD  m0
49     shl     lenq, 2
50     add     srcq, lenq
51     add     dstq, lenq
52     neg     lenq
53 .loop:
54 %if cpuflag(sse2)
55     cvtdq2ps  m1, [srcq+lenq   ]
56     cvtdq2ps  m2, [srcq+lenq+16]
57 %else
58     cvtpi2ps  m1, [srcq+lenq   ]
59     cvtpi2ps  m3, [srcq+lenq+ 8]
60     cvtpi2ps  m2, [srcq+lenq+16]
61     cvtpi2ps  m4, [srcq+lenq+24]
62     movlhps   m1, m3
63     movlhps   m2, m4
64 %endif
65     mulps     m1, m0
66     mulps     m2, m0
67     mova  [dstq+lenq   ], m1
68     mova  [dstq+lenq+16], m2
69     add     lenq, 32
70     jl .loop
71     REP_RET
72 %endmacro
73
74 INIT_XMM sse
75 %define SPLATD SPLATD_SSE
76 INT32_TO_FLOAT_FMUL_SCALAR 5
77 INIT_XMM sse2
78 %define SPLATD SPLATD_SSE2
79 INT32_TO_FLOAT_FMUL_SCALAR 3
80 %undef SPLATD
81
82
83 ;------------------------------------------------------------------------------
84 ; void ff_float_to_int16(int16_t *dst, const float *src, long len);
85 ;------------------------------------------------------------------------------
86 %macro FLOAT_TO_INT16 1
87 cglobal float_to_int16, 3, 3, %1, dst, src, len
88     add       lenq, lenq
89     lea       srcq, [srcq+2*lenq]
90     add       dstq, lenq
91     neg       lenq
92 .loop:
93 %if cpuflag(sse2)
94     cvtps2dq    m0, [srcq+2*lenq   ]
95     cvtps2dq    m1, [srcq+2*lenq+16]
96     packssdw    m0, m1
97     mova  [dstq+lenq], m0
98 %else
99     CVTPS2PI    m0, [srcq+2*lenq   ]
100     CVTPS2PI    m1, [srcq+2*lenq+ 8]
101     CVTPS2PI    m2, [srcq+2*lenq+16]
102     CVTPS2PI    m3, [srcq+2*lenq+24]
103     packssdw    m0, m1
104     packssdw    m2, m3
105     mova  [dstq+lenq  ], m0
106     mova  [dstq+lenq+8], m2
107 %endif
108     add       lenq, 16
109     js .loop
110 %if mmsize == 8
111     emms
112 %endif
113     REP_RET
114 %endmacro
115
116 INIT_XMM sse2
117 FLOAT_TO_INT16 2
118 INIT_MMX sse
119 FLOAT_TO_INT16 0
120 INIT_MMX 3dnow
121 FLOAT_TO_INT16 0
122
123 ;------------------------------------------------------------------------------
124 ; void ff_float_to_int16_step(int16_t *dst, const float *src, long len, long step);
125 ;------------------------------------------------------------------------------
126 %macro FLOAT_TO_INT16_STEP 1
127 cglobal float_to_int16_step, 4, 7, %1, dst, src, len, step, step3, v1, v2
128     add       lenq, lenq
129     lea       srcq, [srcq+2*lenq]
130     lea     step3q, [stepq*3]
131     neg       lenq
132 .loop:
133 %if cpuflag(sse2)
134     cvtps2dq    m0, [srcq+2*lenq   ]
135     cvtps2dq    m1, [srcq+2*lenq+16]
136     packssdw    m0, m1
137     movd       v1d, m0
138     psrldq      m0, 4
139     movd       v2d, m0
140     psrldq      m0, 4
141     mov     [dstq], v1w
142     mov  [dstq+stepq*4], v2w
143     shr        v1d, 16
144     shr        v2d, 16
145     mov  [dstq+stepq*2], v1w
146     mov  [dstq+step3q*2], v2w
147     lea       dstq, [dstq+stepq*8]
148     movd       v1d, m0
149     psrldq      m0, 4
150     movd       v2d, m0
151     mov     [dstq], v1w
152     mov  [dstq+stepq*4], v2w
153     shr        v1d, 16
154     shr        v2d, 16
155     mov  [dstq+stepq*2], v1w
156     mov  [dstq+step3q*2], v2w
157     lea       dstq, [dstq+stepq*8]
158 %else
159     CVTPS2PI    m0, [srcq+2*lenq   ]
160     CVTPS2PI    m1, [srcq+2*lenq+ 8]
161     CVTPS2PI    m2, [srcq+2*lenq+16]
162     CVTPS2PI    m3, [srcq+2*lenq+24]
163     packssdw    m0, m1
164     packssdw    m2, m3
165     movd       v1d, m0
166     psrlq       m0, 32
167     movd       v2d, m0
168     mov     [dstq], v1w
169     mov  [dstq+stepq*4], v2w
170     shr        v1d, 16
171     shr        v2d, 16
172     mov  [dstq+stepq*2], v1w
173     mov  [dstq+step3q*2], v2w
174     lea       dstq, [dstq+stepq*8]
175     movd       v1d, m2
176     psrlq       m2, 32
177     movd       v2d, m2
178     mov     [dstq], v1w
179     mov  [dstq+stepq*4], v2w
180     shr        v1d, 16
181     shr        v2d, 16
182     mov  [dstq+stepq*2], v1w
183     mov  [dstq+step3q*2], v2w
184     lea       dstq, [dstq+stepq*8]
185 %endif
186     add       lenq, 16
187     js .loop
188 %if mmsize == 8
189     emms
190 %endif
191     REP_RET
192 %endmacro
193
194 INIT_XMM sse2
195 FLOAT_TO_INT16_STEP 2
196 INIT_MMX sse
197 FLOAT_TO_INT16_STEP 0
198 INIT_MMX 3dnow
199 FLOAT_TO_INT16_STEP 0
200
201 ;-------------------------------------------------------------------------------
202 ; void ff_float_to_int16_interleave2(int16_t *dst, const float **src, long len);
203 ;-------------------------------------------------------------------------------
204 %macro FLOAT_TO_INT16_INTERLEAVE2 0
205 cglobal float_to_int16_interleave2, 3, 4, 2, dst, src0, src1, len
206     lea      lenq, [4*r2q]
207     mov     src1q, [src0q+gprsize]
208     mov     src0q, [src0q]
209     add      dstq, lenq
210     add     src0q, lenq
211     add     src1q, lenq
212     neg      lenq
213 .loop:
214 %if cpuflag(sse2)
215     cvtps2dq   m0, [src0q+lenq]
216     cvtps2dq   m1, [src1q+lenq]
217     packssdw   m0, m1
218     movhlps    m1, m0
219     punpcklwd  m0, m1
220     mova  [dstq+lenq], m0
221 %else
222     CVTPS2PI   m0, [src0q+lenq  ]
223     CVTPS2PI   m1, [src0q+lenq+8]
224     CVTPS2PI   m2, [src1q+lenq  ]
225     CVTPS2PI   m3, [src1q+lenq+8]
226     packssdw   m0, m1
227     packssdw   m2, m3
228     mova       m1, m0
229     punpcklwd  m0, m2
230     punpckhwd  m1, m2
231     mova  [dstq+lenq  ], m0
232     mova  [dstq+lenq+8], m1
233 %endif
234     add      lenq, 16
235     js .loop
236 %if mmsize == 8
237     emms
238 %endif
239     REP_RET
240 %endmacro
241
242 INIT_MMX 3dnow
243 FLOAT_TO_INT16_INTERLEAVE2
244 INIT_MMX sse
245 FLOAT_TO_INT16_INTERLEAVE2
246 INIT_XMM sse2
247 FLOAT_TO_INT16_INTERLEAVE2
248
249
250 %macro PSWAPD_SSE 2
251     pshufw %1, %2, 0x4e
252 %endmacro
253 %macro PSWAPD_3DNOW 2
254     movq  %1, %2
255     psrlq %1, 32
256     punpckldq %1, %2
257 %endmacro
258
259 %macro FLOAT_TO_INT16_INTERLEAVE6 0
260 ; void float_to_int16_interleave6_sse(int16_t *dst, const float **src, int len)
261 cglobal float_to_int16_interleave6, 2, 8, 0, dst, src, src1, src2, src3, src4, src5, len
262 %if ARCH_X86_64
263     mov     lend, r2d
264 %else
265     %define lend dword r2m
266 %endif
267     mov src1q, [srcq+1*gprsize]
268     mov src2q, [srcq+2*gprsize]
269     mov src3q, [srcq+3*gprsize]
270     mov src4q, [srcq+4*gprsize]
271     mov src5q, [srcq+5*gprsize]
272     mov srcq,  [srcq]
273     sub src1q, srcq
274     sub src2q, srcq
275     sub src3q, srcq
276     sub src4q, srcq
277     sub src5q, srcq
278 .loop:
279     CVTPS2PI   mm0, [srcq]
280     CVTPS2PI   mm1, [srcq+src1q]
281     CVTPS2PI   mm2, [srcq+src2q]
282     CVTPS2PI   mm3, [srcq+src3q]
283     CVTPS2PI   mm4, [srcq+src4q]
284     CVTPS2PI   mm5, [srcq+src5q]
285     packssdw   mm0, mm3
286     packssdw   mm1, mm4
287     packssdw   mm2, mm5
288     pswapd     mm3, mm0
289     punpcklwd  mm0, mm1
290     punpckhwd  mm1, mm2
291     punpcklwd  mm2, mm3
292     pswapd     mm3, mm0
293     punpckldq  mm0, mm2
294     punpckhdq  mm2, mm1
295     punpckldq  mm1, mm3
296     movq [dstq   ], mm0
297     movq [dstq+16], mm2
298     movq [dstq+ 8], mm1
299     add srcq, 8
300     add dstq, 24
301     sub lend, 2
302     jg .loop
303     emms
304     RET
305 %endmacro ; FLOAT_TO_INT16_INTERLEAVE6
306
307 INIT_MMX sse
308 %define pswapd PSWAPD_SSE
309 FLOAT_TO_INT16_INTERLEAVE6
310 INIT_MMX 3dnow
311 %define pswapd PSWAPD_3DNOW
312 FLOAT_TO_INT16_INTERLEAVE6
313 %undef pswapd
314 INIT_MMX 3dnowext
315 FLOAT_TO_INT16_INTERLEAVE6
316
317 ;-----------------------------------------------------------------------------
318 ; void ff_float_interleave6(float *dst, const float **src, unsigned int len);
319 ;-----------------------------------------------------------------------------
320
321 %macro FLOAT_INTERLEAVE6 1
322 cglobal float_interleave6, 2, 8, %1, dst, src, src1, src2, src3, src4, src5, len
323 %if ARCH_X86_64
324     mov     lend, r2d
325 %else
326     %define lend dword r2m
327 %endif
328     mov    src1q, [srcq+1*gprsize]
329     mov    src2q, [srcq+2*gprsize]
330     mov    src3q, [srcq+3*gprsize]
331     mov    src4q, [srcq+4*gprsize]
332     mov    src5q, [srcq+5*gprsize]
333     mov     srcq, [srcq]
334     sub    src1q, srcq
335     sub    src2q, srcq
336     sub    src3q, srcq
337     sub    src4q, srcq
338     sub    src5q, srcq
339 .loop:
340 %if cpuflag(sse)
341     movaps    m0, [srcq]
342     movaps    m1, [srcq+src1q]
343     movaps    m2, [srcq+src2q]
344     movaps    m3, [srcq+src3q]
345     movaps    m4, [srcq+src4q]
346     movaps    m5, [srcq+src5q]
347
348     SBUTTERFLYPS 0, 1, 6
349     SBUTTERFLYPS 2, 3, 6
350     SBUTTERFLYPS 4, 5, 6
351
352     movaps    m6, m4
353     shufps    m4, m0, 0xe4
354     movlhps   m0, m2
355     movhlps   m6, m2
356     movaps [dstq   ], m0
357     movaps [dstq+16], m4
358     movaps [dstq+32], m6
359
360     movaps    m6, m5
361     shufps    m5, m1, 0xe4
362     movlhps   m1, m3
363     movhlps   m6, m3
364     movaps [dstq+48], m1
365     movaps [dstq+64], m5
366     movaps [dstq+80], m6
367 %else ; mmx
368     movq       m0, [srcq]
369     movq       m1, [srcq+src1q]
370     movq       m2, [srcq+src2q]
371     movq       m3, [srcq+src3q]
372     movq       m4, [srcq+src4q]
373     movq       m5, [srcq+src5q]
374
375     SBUTTERFLY dq, 0, 1, 6
376     SBUTTERFLY dq, 2, 3, 6
377     SBUTTERFLY dq, 4, 5, 6
378     movq [dstq   ], m0
379     movq [dstq+ 8], m2
380     movq [dstq+16], m4
381     movq [dstq+24], m1
382     movq [dstq+32], m3
383     movq [dstq+40], m5
384 %endif
385     add      srcq, mmsize
386     add      dstq, mmsize*6
387     sub      lend, mmsize/4
388     jg .loop
389 %if mmsize == 8
390     emms
391 %endif
392     REP_RET
393 %endmacro
394
395 INIT_MMX mmx
396 FLOAT_INTERLEAVE6 0
397 INIT_XMM sse
398 FLOAT_INTERLEAVE6 7
399
400 ;-----------------------------------------------------------------------------
401 ; void ff_float_interleave2(float *dst, const float **src, unsigned int len);
402 ;-----------------------------------------------------------------------------
403
404 %macro FLOAT_INTERLEAVE2 1
405 cglobal float_interleave2, 3, 4, %1, dst, src, len, src1
406     mov     src1q, [srcq+gprsize]
407     mov      srcq, [srcq        ]
408     sub     src1q, srcq
409 .loop:
410     mova       m0, [srcq             ]
411     mova       m1, [srcq+src1q       ]
412     mova       m3, [srcq      +mmsize]
413     mova       m4, [srcq+src1q+mmsize]
414
415     mova       m2, m0
416     PUNPCKLDQ  m0, m1
417     PUNPCKHDQ  m2, m1
418
419     mova       m1, m3
420     PUNPCKLDQ  m3, m4
421     PUNPCKHDQ  m1, m4
422
423     mova  [dstq         ], m0
424     mova  [dstq+1*mmsize], m2
425     mova  [dstq+2*mmsize], m3
426     mova  [dstq+3*mmsize], m1
427
428     add      srcq, mmsize*2
429     add      dstq, mmsize*4
430     sub      lend, mmsize/2
431     jg .loop
432 %if mmsize == 8
433     emms
434 %endif
435     REP_RET
436 %endmacro
437
438 INIT_MMX mmx
439 %define PUNPCKLDQ punpckldq
440 %define PUNPCKHDQ punpckhdq
441 FLOAT_INTERLEAVE2 0
442 INIT_XMM sse
443 %define PUNPCKLDQ unpcklps
444 %define PUNPCKHDQ unpckhps
445 FLOAT_INTERLEAVE2 5