x86: Refactor PSWAPD fallback implementations and port to cpuflags
[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 %macro FLOAT_TO_INT16_INTERLEAVE6 0
250 ; void float_to_int16_interleave6_sse(int16_t *dst, const float **src, int len)
251 cglobal float_to_int16_interleave6, 2, 8, 0, dst, src, src1, src2, src3, src4, src5, len
252 %if ARCH_X86_64
253     mov     lend, r2d
254 %else
255     %define lend dword r2m
256 %endif
257     mov src1q, [srcq+1*gprsize]
258     mov src2q, [srcq+2*gprsize]
259     mov src3q, [srcq+3*gprsize]
260     mov src4q, [srcq+4*gprsize]
261     mov src5q, [srcq+5*gprsize]
262     mov srcq,  [srcq]
263     sub src1q, srcq
264     sub src2q, srcq
265     sub src3q, srcq
266     sub src4q, srcq
267     sub src5q, srcq
268 .loop:
269     CVTPS2PI   mm0, [srcq]
270     CVTPS2PI   mm1, [srcq+src1q]
271     CVTPS2PI   mm2, [srcq+src2q]
272     CVTPS2PI   mm3, [srcq+src3q]
273     CVTPS2PI   mm4, [srcq+src4q]
274     CVTPS2PI   mm5, [srcq+src5q]
275     packssdw   mm0, mm3
276     packssdw   mm1, mm4
277     packssdw   mm2, mm5
278     PSWAPD     mm3, mm0
279     punpcklwd  mm0, mm1
280     punpckhwd  mm1, mm2
281     punpcklwd  mm2, mm3
282     PSWAPD     mm3, mm0
283     punpckldq  mm0, mm2
284     punpckhdq  mm2, mm1
285     punpckldq  mm1, mm3
286     movq [dstq   ], mm0
287     movq [dstq+16], mm2
288     movq [dstq+ 8], mm1
289     add srcq, 8
290     add dstq, 24
291     sub lend, 2
292     jg .loop
293     emms
294     RET
295 %endmacro ; FLOAT_TO_INT16_INTERLEAVE6
296
297 INIT_MMX sse
298 FLOAT_TO_INT16_INTERLEAVE6
299 INIT_MMX 3dnow
300 FLOAT_TO_INT16_INTERLEAVE6
301 INIT_MMX 3dnowext
302 FLOAT_TO_INT16_INTERLEAVE6
303
304 ;-----------------------------------------------------------------------------
305 ; void ff_float_interleave6(float *dst, const float **src, unsigned int len);
306 ;-----------------------------------------------------------------------------
307
308 %macro FLOAT_INTERLEAVE6 1
309 cglobal float_interleave6, 2, 8, %1, dst, src, src1, src2, src3, src4, src5, len
310 %if ARCH_X86_64
311     mov     lend, r2d
312 %else
313     %define lend dword r2m
314 %endif
315     mov    src1q, [srcq+1*gprsize]
316     mov    src2q, [srcq+2*gprsize]
317     mov    src3q, [srcq+3*gprsize]
318     mov    src4q, [srcq+4*gprsize]
319     mov    src5q, [srcq+5*gprsize]
320     mov     srcq, [srcq]
321     sub    src1q, srcq
322     sub    src2q, srcq
323     sub    src3q, srcq
324     sub    src4q, srcq
325     sub    src5q, srcq
326 .loop:
327 %if cpuflag(sse)
328     movaps    m0, [srcq]
329     movaps    m1, [srcq+src1q]
330     movaps    m2, [srcq+src2q]
331     movaps    m3, [srcq+src3q]
332     movaps    m4, [srcq+src4q]
333     movaps    m5, [srcq+src5q]
334
335     SBUTTERFLYPS 0, 1, 6
336     SBUTTERFLYPS 2, 3, 6
337     SBUTTERFLYPS 4, 5, 6
338
339     movaps    m6, m4
340     shufps    m4, m0, 0xe4
341     movlhps   m0, m2
342     movhlps   m6, m2
343     movaps [dstq   ], m0
344     movaps [dstq+16], m4
345     movaps [dstq+32], m6
346
347     movaps    m6, m5
348     shufps    m5, m1, 0xe4
349     movlhps   m1, m3
350     movhlps   m6, m3
351     movaps [dstq+48], m1
352     movaps [dstq+64], m5
353     movaps [dstq+80], m6
354 %else ; mmx
355     movq       m0, [srcq]
356     movq       m1, [srcq+src1q]
357     movq       m2, [srcq+src2q]
358     movq       m3, [srcq+src3q]
359     movq       m4, [srcq+src4q]
360     movq       m5, [srcq+src5q]
361
362     SBUTTERFLY dq, 0, 1, 6
363     SBUTTERFLY dq, 2, 3, 6
364     SBUTTERFLY dq, 4, 5, 6
365     movq [dstq   ], m0
366     movq [dstq+ 8], m2
367     movq [dstq+16], m4
368     movq [dstq+24], m1
369     movq [dstq+32], m3
370     movq [dstq+40], m5
371 %endif
372     add      srcq, mmsize
373     add      dstq, mmsize*6
374     sub      lend, mmsize/4
375     jg .loop
376 %if mmsize == 8
377     emms
378 %endif
379     REP_RET
380 %endmacro
381
382 INIT_MMX mmx
383 FLOAT_INTERLEAVE6 0
384 INIT_XMM sse
385 FLOAT_INTERLEAVE6 7
386
387 ;-----------------------------------------------------------------------------
388 ; void ff_float_interleave2(float *dst, const float **src, unsigned int len);
389 ;-----------------------------------------------------------------------------
390
391 %macro FLOAT_INTERLEAVE2 1
392 cglobal float_interleave2, 3, 4, %1, dst, src, len, src1
393     mov     src1q, [srcq+gprsize]
394     mov      srcq, [srcq        ]
395     sub     src1q, srcq
396 .loop:
397     mova       m0, [srcq             ]
398     mova       m1, [srcq+src1q       ]
399     mova       m3, [srcq      +mmsize]
400     mova       m4, [srcq+src1q+mmsize]
401
402     mova       m2, m0
403     PUNPCKLDQ  m0, m1
404     PUNPCKHDQ  m2, m1
405
406     mova       m1, m3
407     PUNPCKLDQ  m3, m4
408     PUNPCKHDQ  m1, m4
409
410     mova  [dstq         ], m0
411     mova  [dstq+1*mmsize], m2
412     mova  [dstq+2*mmsize], m3
413     mova  [dstq+3*mmsize], m1
414
415     add      srcq, mmsize*2
416     add      dstq, mmsize*4
417     sub      lend, mmsize/2
418     jg .loop
419 %if mmsize == 8
420     emms
421 %endif
422     REP_RET
423 %endmacro
424
425 INIT_MMX mmx
426 %define PUNPCKLDQ punpckldq
427 %define PUNPCKHDQ punpckhdq
428 FLOAT_INTERLEAVE2 0
429 INIT_XMM sse
430 %define PUNPCKLDQ unpcklps
431 %define PUNPCKHDQ unpckhps
432 FLOAT_INTERLEAVE2 5