floatdsp: move vector_fmul_add from dsputil to avfloatdsp.
[ffmpeg.git] / libavcodec / x86 / dsputil.asm
1 ;******************************************************************************
2 ;* MMX optimized DSP 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_RODATA
25 pb_f: times 16 db 15
26 pb_zzzzzzzz77777777: times 8 db -1
27 pb_7: times 8 db 7
28 pb_zzzz3333zzzzbbbb: db -1,-1,-1,-1,3,3,3,3,-1,-1,-1,-1,11,11,11,11
29 pb_zz11zz55zz99zzdd: db -1,-1,1,1,-1,-1,5,5,-1,-1,9,9,-1,-1,13,13
30 pb_revwords: SHUFFLE_MASK_W 7, 6, 5, 4, 3, 2, 1, 0
31 pd_16384: times 4 dd 16384
32 pb_bswap32: db 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
33
34 SECTION_TEXT
35
36 %macro SCALARPRODUCT 0
37 ; int scalarproduct_int16(int16_t *v1, int16_t *v2, int order)
38 cglobal scalarproduct_int16, 3,3,3, v1, v2, order
39     shl orderq, 1
40     add v1q, orderq
41     add v2q, orderq
42     neg orderq
43     pxor    m2, m2
44 .loop:
45     movu    m0, [v1q + orderq]
46     movu    m1, [v1q + orderq + mmsize]
47     pmaddwd m0, [v2q + orderq]
48     pmaddwd m1, [v2q + orderq + mmsize]
49     paddd   m2, m0
50     paddd   m2, m1
51     add     orderq, mmsize*2
52     jl .loop
53 %if mmsize == 16
54     movhlps m0, m2
55     paddd   m2, m0
56     pshuflw m0, m2, 0x4e
57 %else
58     pshufw  m0, m2, 0x4e
59 %endif
60     paddd   m2, m0
61     movd   eax, m2
62     RET
63
64 ; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul)
65 cglobal scalarproduct_and_madd_int16, 4,4,8, v1, v2, v3, order, mul
66     shl orderq, 1
67     movd    m7, mulm
68 %if mmsize == 16
69     pshuflw m7, m7, 0
70     punpcklqdq m7, m7
71 %else
72     pshufw  m7, m7, 0
73 %endif
74     pxor    m6, m6
75     add v1q, orderq
76     add v2q, orderq
77     add v3q, orderq
78     neg orderq
79 .loop:
80     movu    m0, [v2q + orderq]
81     movu    m1, [v2q + orderq + mmsize]
82     mova    m4, [v1q + orderq]
83     mova    m5, [v1q + orderq + mmsize]
84     movu    m2, [v3q + orderq]
85     movu    m3, [v3q + orderq + mmsize]
86     pmaddwd m0, m4
87     pmaddwd m1, m5
88     pmullw  m2, m7
89     pmullw  m3, m7
90     paddd   m6, m0
91     paddd   m6, m1
92     paddw   m2, m4
93     paddw   m3, m5
94     mova    [v1q + orderq], m2
95     mova    [v1q + orderq + mmsize], m3
96     add     orderq, mmsize*2
97     jl .loop
98 %if mmsize == 16
99     movhlps m0, m6
100     paddd   m6, m0
101     pshuflw m0, m6, 0x4e
102 %else
103     pshufw  m0, m6, 0x4e
104 %endif
105     paddd   m6, m0
106     movd   eax, m6
107     RET
108 %endmacro
109
110 INIT_MMX mmxext
111 SCALARPRODUCT
112 INIT_XMM sse2
113 SCALARPRODUCT
114
115 %macro SCALARPRODUCT_LOOP 1
116 align 16
117 .loop%1:
118     sub     orderq, mmsize*2
119 %if %1
120     mova    m1, m4
121     mova    m4, [v2q + orderq]
122     mova    m0, [v2q + orderq + mmsize]
123     palignr m1, m0, %1
124     palignr m0, m4, %1
125     mova    m3, m5
126     mova    m5, [v3q + orderq]
127     mova    m2, [v3q + orderq + mmsize]
128     palignr m3, m2, %1
129     palignr m2, m5, %1
130 %else
131     mova    m0, [v2q + orderq]
132     mova    m1, [v2q + orderq + mmsize]
133     mova    m2, [v3q + orderq]
134     mova    m3, [v3q + orderq + mmsize]
135 %endif
136     %define t0  [v1q + orderq]
137     %define t1  [v1q + orderq + mmsize]
138 %if ARCH_X86_64
139     mova    m8, t0
140     mova    m9, t1
141     %define t0  m8
142     %define t1  m9
143 %endif
144     pmaddwd m0, t0
145     pmaddwd m1, t1
146     pmullw  m2, m7
147     pmullw  m3, m7
148     paddw   m2, t0
149     paddw   m3, t1
150     paddd   m6, m0
151     paddd   m6, m1
152     mova    [v1q + orderq], m2
153     mova    [v1q + orderq + mmsize], m3
154     jg .loop%1
155 %if %1
156     jmp .end
157 %endif
158 %endmacro
159
160 ; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul)
161 INIT_XMM ssse3
162 cglobal scalarproduct_and_madd_int16, 4,5,10, v1, v2, v3, order, mul
163     shl orderq, 1
164     movd    m7, mulm
165     pshuflw m7, m7, 0
166     punpcklqdq m7, m7
167     pxor    m6, m6
168     mov    r4d, v2d
169     and    r4d, 15
170     and    v2q, ~15
171     and    v3q, ~15
172     mova    m4, [v2q + orderq]
173     mova    m5, [v3q + orderq]
174     ; linear is faster than branch tree or jump table, because the branches taken are cyclic (i.e. predictable)
175     cmp    r4d, 0
176     je .loop0
177     cmp    r4d, 2
178     je .loop2
179     cmp    r4d, 4
180     je .loop4
181     cmp    r4d, 6
182     je .loop6
183     cmp    r4d, 8
184     je .loop8
185     cmp    r4d, 10
186     je .loop10
187     cmp    r4d, 12
188     je .loop12
189 SCALARPRODUCT_LOOP 14
190 SCALARPRODUCT_LOOP 12
191 SCALARPRODUCT_LOOP 10
192 SCALARPRODUCT_LOOP 8
193 SCALARPRODUCT_LOOP 6
194 SCALARPRODUCT_LOOP 4
195 SCALARPRODUCT_LOOP 2
196 SCALARPRODUCT_LOOP 0
197 .end:
198     movhlps m0, m6
199     paddd   m6, m0
200     pshuflw m0, m6, 0x4e
201     paddd   m6, m0
202     movd   eax, m6
203     RET
204
205
206 ;-----------------------------------------------------------------------------
207 ; void ff_apply_window_int16(int16_t *output, const int16_t *input,
208 ;                            const int16_t *window, unsigned int len)
209 ;-----------------------------------------------------------------------------
210
211 %macro REVERSE_WORDS 1-2
212 %if cpuflag(ssse3) && notcpuflag(atom)
213     pshufb  %1, %2
214 %elif cpuflag(sse2)
215     pshuflw  %1, %1, 0x1B
216     pshufhw  %1, %1, 0x1B
217     pshufd   %1, %1, 0x4E
218 %elif cpuflag(mmxext)
219     pshufw   %1, %1, 0x1B
220 %endif
221 %endmacro
222
223 %macro MUL16FIXED 3
224 %if cpuflag(ssse3) ; dst, src, unused
225 ; dst = ((dst * src) + (1<<14)) >> 15
226     pmulhrsw   %1, %2
227 %elif cpuflag(mmxext) ; dst, src, temp
228 ; dst = (dst * src) >> 15
229 ; pmulhw cuts off the bottom bit, so we have to lshift by 1 and add it back
230 ; in from the pmullw result.
231     mova    %3, %1
232     pmulhw  %1, %2
233     pmullw  %3, %2
234     psrlw   %3, 15
235     psllw   %1, 1
236     por     %1, %3
237 %endif
238 %endmacro
239
240 %macro APPLY_WINDOW_INT16 1 ; %1 bitexact version
241 %if %1
242 cglobal apply_window_int16, 4,5,6, output, input, window, offset, offset2
243 %else
244 cglobal apply_window_int16_round, 4,5,6, output, input, window, offset, offset2
245 %endif
246     lea     offset2q, [offsetq-mmsize]
247 %if cpuflag(ssse3) && notcpuflag(atom)
248     mova          m5, [pb_revwords]
249     ALIGN 16
250 %elif %1
251     mova          m5, [pd_16384]
252 %endif
253 .loop:
254 %if cpuflag(ssse3)
255     ; This version does the 16x16->16 multiplication in-place without expanding
256     ; to 32-bit. The ssse3 version is bit-identical.
257     mova          m0, [windowq+offset2q]
258     mova          m1, [ inputq+offset2q]
259     pmulhrsw      m1, m0
260     REVERSE_WORDS m0, m5
261     pmulhrsw      m0, [ inputq+offsetq ]
262     mova  [outputq+offset2q], m1
263     mova  [outputq+offsetq ], m0
264 %elif %1
265     ; This version expands 16-bit to 32-bit, multiplies by the window,
266     ; adds 16384 for rounding, right shifts 15, then repacks back to words to
267     ; save to the output. The window is reversed for the second half.
268     mova          m3, [windowq+offset2q]
269     mova          m4, [ inputq+offset2q]
270     pxor          m0, m0
271     punpcklwd     m0, m3
272     punpcklwd     m1, m4
273     pmaddwd       m0, m1
274     paddd         m0, m5
275     psrad         m0, 15
276     pxor          m2, m2
277     punpckhwd     m2, m3
278     punpckhwd     m1, m4
279     pmaddwd       m2, m1
280     paddd         m2, m5
281     psrad         m2, 15
282     packssdw      m0, m2
283     mova  [outputq+offset2q], m0
284     REVERSE_WORDS m3
285     mova          m4, [ inputq+offsetq]
286     pxor          m0, m0
287     punpcklwd     m0, m3
288     punpcklwd     m1, m4
289     pmaddwd       m0, m1
290     paddd         m0, m5
291     psrad         m0, 15
292     pxor          m2, m2
293     punpckhwd     m2, m3
294     punpckhwd     m1, m4
295     pmaddwd       m2, m1
296     paddd         m2, m5
297     psrad         m2, 15
298     packssdw      m0, m2
299     mova  [outputq+offsetq], m0
300 %else
301     ; This version does the 16x16->16 multiplication in-place without expanding
302     ; to 32-bit. The mmxext and sse2 versions do not use rounding, and
303     ; therefore are not bit-identical to the C version.
304     mova          m0, [windowq+offset2q]
305     mova          m1, [ inputq+offset2q]
306     mova          m2, [ inputq+offsetq ]
307     MUL16FIXED    m1, m0, m3
308     REVERSE_WORDS m0
309     MUL16FIXED    m2, m0, m3
310     mova  [outputq+offset2q], m1
311     mova  [outputq+offsetq ], m2
312 %endif
313     add      offsetd, mmsize
314     sub     offset2d, mmsize
315     jae .loop
316     REP_RET
317 %endmacro
318
319 INIT_MMX mmxext
320 APPLY_WINDOW_INT16 0
321 INIT_XMM sse2
322 APPLY_WINDOW_INT16 0
323
324 INIT_MMX mmxext
325 APPLY_WINDOW_INT16 1
326 INIT_XMM sse2
327 APPLY_WINDOW_INT16 1
328 INIT_XMM ssse3
329 APPLY_WINDOW_INT16 1
330 INIT_XMM ssse3, atom
331 APPLY_WINDOW_INT16 1
332
333
334 ; void add_hfyu_median_prediction_mmxext(uint8_t *dst, const uint8_t *top, const uint8_t *diff, int w, int *left, int *left_top)
335 INIT_MMX mmxext
336 cglobal add_hfyu_median_prediction, 6,6,0, dst, top, diff, w, left, left_top
337     movq    mm0, [topq]
338     movq    mm2, mm0
339     movd    mm4, [left_topq]
340     psllq   mm2, 8
341     movq    mm1, mm0
342     por     mm4, mm2
343     movd    mm3, [leftq]
344     psubb   mm0, mm4 ; t-tl
345     add    dstq, wq
346     add    topq, wq
347     add   diffq, wq
348     neg      wq
349     jmp .skip
350 .loop:
351     movq    mm4, [topq+wq]
352     movq    mm0, mm4
353     psllq   mm4, 8
354     por     mm4, mm1
355     movq    mm1, mm0 ; t
356     psubb   mm0, mm4 ; t-tl
357 .skip:
358     movq    mm2, [diffq+wq]
359 %assign i 0
360 %rep 8
361     movq    mm4, mm0
362     paddb   mm4, mm3 ; t-tl+l
363     movq    mm5, mm3
364     pmaxub  mm3, mm1
365     pminub  mm5, mm1
366     pminub  mm3, mm4
367     pmaxub  mm3, mm5 ; median
368     paddb   mm3, mm2 ; +residual
369 %if i==0
370     movq    mm7, mm3
371     psllq   mm7, 56
372 %else
373     movq    mm6, mm3
374     psrlq   mm7, 8
375     psllq   mm6, 56
376     por     mm7, mm6
377 %endif
378 %if i<7
379     psrlq   mm0, 8
380     psrlq   mm1, 8
381     psrlq   mm2, 8
382 %endif
383 %assign i i+1
384 %endrep
385     movq [dstq+wq], mm7
386     add      wq, 8
387     jl .loop
388     movzx   r2d, byte [dstq-1]
389     mov [leftq], r2d
390     movzx   r2d, byte [topq-1]
391     mov [left_topq], r2d
392     RET
393
394
395 %macro ADD_HFYU_LEFT_LOOP 2 ; %1 = dst_is_aligned, %2 = src_is_aligned
396     add     srcq, wq
397     add     dstq, wq
398     neg     wq
399 %%.loop:
400 %if %2
401     mova    m1, [srcq+wq]
402 %else
403     movu    m1, [srcq+wq]
404 %endif
405     mova    m2, m1
406     psllw   m1, 8
407     paddb   m1, m2
408     mova    m2, m1
409     pshufb  m1, m3
410     paddb   m1, m2
411     pshufb  m0, m5
412     mova    m2, m1
413     pshufb  m1, m4
414     paddb   m1, m2
415 %if mmsize == 16
416     mova    m2, m1
417     pshufb  m1, m6
418     paddb   m1, m2
419 %endif
420     paddb   m0, m1
421 %if %1
422     mova    [dstq+wq], m0
423 %else
424     movq    [dstq+wq], m0
425     movhps  [dstq+wq+8], m0
426 %endif
427     add     wq, mmsize
428     jl %%.loop
429     mov     eax, mmsize-1
430     sub     eax, wd
431     movd    m1, eax
432     pshufb  m0, m1
433     movd    eax, m0
434     RET
435 %endmacro
436
437 ; int add_hfyu_left_prediction(uint8_t *dst, const uint8_t *src, int w, int left)
438 INIT_MMX ssse3
439 cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left
440 .skip_prologue:
441     mova    m5, [pb_7]
442     mova    m4, [pb_zzzz3333zzzzbbbb]
443     mova    m3, [pb_zz11zz55zz99zzdd]
444     movd    m0, leftm
445     psllq   m0, 56
446     ADD_HFYU_LEFT_LOOP 1, 1
447
448 INIT_XMM sse4
449 cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left
450     mova    m5, [pb_f]
451     mova    m6, [pb_zzzzzzzz77777777]
452     mova    m4, [pb_zzzz3333zzzzbbbb]
453     mova    m3, [pb_zz11zz55zz99zzdd]
454     movd    m0, leftm
455     pslldq  m0, 15
456     test    srcq, 15
457     jnz .src_unaligned
458     test    dstq, 15
459     jnz .dst_unaligned
460     ADD_HFYU_LEFT_LOOP 1, 1
461 .dst_unaligned:
462     ADD_HFYU_LEFT_LOOP 0, 1
463 .src_unaligned:
464     ADD_HFYU_LEFT_LOOP 0, 0
465
466
467 ; float scalarproduct_float_sse(const float *v1, const float *v2, int len)
468 INIT_XMM sse
469 cglobal scalarproduct_float, 3,3,2, v1, v2, offset
470     neg offsetq
471     shl offsetq, 2
472     sub v1q, offsetq
473     sub v2q, offsetq
474     xorps xmm0, xmm0
475     .loop:
476         movaps   xmm1, [v1q+offsetq]
477         mulps    xmm1, [v2q+offsetq]
478         addps    xmm0, xmm1
479         add      offsetq, 16
480         js       .loop
481     movhlps xmm1, xmm0
482     addps   xmm0, xmm1
483     movss   xmm1, xmm0
484     shufps  xmm0, xmm0, 1
485     addss   xmm0, xmm1
486 %if ARCH_X86_64 == 0
487     movss   r0m,  xmm0
488     fld     dword r0m
489 %endif
490     RET
491
492 ;-----------------------------------------------------------------------------
493 ; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min,
494 ;                           int32_t max, unsigned int len)
495 ;-----------------------------------------------------------------------------
496
497 ; %1 = number of xmm registers used
498 ; %2 = number of inline load/process/store loops per asm loop
499 ; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop
500 ; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2)
501 ; %5 = suffix
502 %macro VECTOR_CLIP_INT32 4-5
503 cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len
504 %if %4
505     cvtsi2ss  m4, minm
506     cvtsi2ss  m5, maxm
507 %else
508     movd      m4, minm
509     movd      m5, maxm
510 %endif
511     SPLATD    m4
512     SPLATD    m5
513 .loop:
514 %assign %%i 1
515 %rep %2
516     mova      m0,  [srcq+mmsize*0*%%i]
517     mova      m1,  [srcq+mmsize*1*%%i]
518     mova      m2,  [srcq+mmsize*2*%%i]
519     mova      m3,  [srcq+mmsize*3*%%i]
520 %if %3
521     mova      m7,  [srcq+mmsize*4*%%i]
522     mova      m8,  [srcq+mmsize*5*%%i]
523     mova      m9,  [srcq+mmsize*6*%%i]
524     mova      m10, [srcq+mmsize*7*%%i]
525 %endif
526     CLIPD  m0,  m4, m5, m6
527     CLIPD  m1,  m4, m5, m6
528     CLIPD  m2,  m4, m5, m6
529     CLIPD  m3,  m4, m5, m6
530 %if %3
531     CLIPD  m7,  m4, m5, m6
532     CLIPD  m8,  m4, m5, m6
533     CLIPD  m9,  m4, m5, m6
534     CLIPD  m10, m4, m5, m6
535 %endif
536     mova  [dstq+mmsize*0*%%i], m0
537     mova  [dstq+mmsize*1*%%i], m1
538     mova  [dstq+mmsize*2*%%i], m2
539     mova  [dstq+mmsize*3*%%i], m3
540 %if %3
541     mova  [dstq+mmsize*4*%%i], m7
542     mova  [dstq+mmsize*5*%%i], m8
543     mova  [dstq+mmsize*6*%%i], m9
544     mova  [dstq+mmsize*7*%%i], m10
545 %endif
546 %assign %%i %%i+1
547 %endrep
548     add     srcq, mmsize*4*(%2+%3)
549     add     dstq, mmsize*4*(%2+%3)
550     sub     lend, mmsize*(%2+%3)
551     jg .loop
552     REP_RET
553 %endmacro
554
555 INIT_MMX mmx
556 %define CLIPD CLIPD_MMX
557 VECTOR_CLIP_INT32 0, 1, 0, 0
558 INIT_XMM sse2
559 VECTOR_CLIP_INT32 6, 1, 0, 0, _int
560 %define CLIPD CLIPD_SSE2
561 VECTOR_CLIP_INT32 6, 2, 0, 1
562 INIT_XMM sse4
563 %define CLIPD CLIPD_SSE41
564 %ifdef m8
565 VECTOR_CLIP_INT32 11, 1, 1, 0
566 %else
567 VECTOR_CLIP_INT32 6, 1, 0, 0
568 %endif
569
570 ;-----------------------------------------------------------------------------
571 ; void vector_fmul_reverse(float *dst, const float *src0, const float *src1,
572 ;                          int len)
573 ;-----------------------------------------------------------------------------
574 %macro VECTOR_FMUL_REVERSE 0
575 cglobal vector_fmul_reverse, 4,4,2, dst, src0, src1, len
576     lea       lenq, [lend*4 - 2*mmsize]
577 ALIGN 16
578 .loop:
579 %if cpuflag(avx)
580     vmovaps     xmm0, [src1q + 16]
581     vinsertf128 m0, m0, [src1q], 1
582     vshufps     m0, m0, m0, q0123
583     vmovaps     xmm1, [src1q + mmsize + 16]
584     vinsertf128 m1, m1, [src1q + mmsize], 1
585     vshufps     m1, m1, m1, q0123
586 %else
587     mova    m0, [src1q]
588     mova    m1, [src1q + mmsize]
589     shufps  m0, m0, q0123
590     shufps  m1, m1, q0123
591 %endif
592     mulps   m0, m0, [src0q + lenq + mmsize]
593     mulps   m1, m1, [src0q + lenq]
594     mova    [dstq + lenq + mmsize], m0
595     mova    [dstq + lenq], m1
596     add     src1q, 2*mmsize
597     sub     lenq,  2*mmsize
598     jge     .loop
599     REP_RET
600 %endmacro
601
602 INIT_XMM sse
603 VECTOR_FMUL_REVERSE
604 INIT_YMM avx
605 VECTOR_FMUL_REVERSE
606
607 ; %1 = aligned/unaligned
608 %macro BSWAP_LOOPS  1
609     mov      r3, r2
610     sar      r2, 3
611     jz       .left4_%1
612 .loop8_%1:
613     mov%1    m0, [r1 +  0]
614     mov%1    m1, [r1 + 16]
615 %if cpuflag(ssse3)
616     pshufb   m0, m2
617     pshufb   m1, m2
618     mova     [r0 +  0], m0
619     mova     [r0 + 16], m1
620 %else
621     pshuflw  m0, m0, 10110001b
622     pshuflw  m1, m1, 10110001b
623     pshufhw  m0, m0, 10110001b
624     pshufhw  m1, m1, 10110001b
625     mova     m2, m0
626     mova     m3, m1
627     psllw    m0, 8
628     psllw    m1, 8
629     psrlw    m2, 8
630     psrlw    m3, 8
631     por      m2, m0
632     por      m3, m1
633     mova     [r0 +  0], m2
634     mova     [r0 + 16], m3
635 %endif
636     add      r0, 32
637     add      r1, 32
638     dec      r2
639     jnz      .loop8_%1
640 .left4_%1:
641     mov      r2, r3
642     and      r3, 4
643     jz       .left
644     mov%1    m0, [r1]
645 %if cpuflag(ssse3)
646     pshufb   m0, m2
647     mova     [r0], m0
648 %else
649     pshuflw  m0, m0, 10110001b
650     pshufhw  m0, m0, 10110001b
651     mova     m2, m0
652     psllw    m0, 8
653     psrlw    m2, 8
654     por      m2, m0
655     mova     [r0], m2
656 %endif
657     add      r1, 16
658     add      r0, 16
659 %endmacro
660
661 ; void bswap_buf(uint32_t *dst, const uint32_t *src, int w);
662 %macro BSWAP32_BUF 0
663 %if cpuflag(ssse3)
664 cglobal bswap32_buf, 3,4,3
665     mov      r3, r1
666     mova     m2, [pb_bswap32]
667 %else
668 cglobal bswap32_buf, 3,4,5
669     mov      r3, r1
670 %endif
671     and      r3, 15
672     jz       .start_align
673     BSWAP_LOOPS  u
674     jmp      .left
675 .start_align:
676     BSWAP_LOOPS  a
677 .left:
678 %if cpuflag(ssse3)
679     mov      r3, r2
680     and      r2, 2
681     jz       .left1
682     movq     m0, [r1]
683     pshufb   m0, m2
684     movq     [r0], m0
685     add      r1, 8
686     add      r0, 8
687 .left1:
688     and      r3, 1
689     jz       .end
690     mov      r2d, [r1]
691     bswap    r2d
692     mov      [r0], r2d
693 %else
694     and      r2, 3
695     jz       .end
696 .loop2:
697     mov      r3d, [r1]
698     bswap    r3d
699     mov      [r0], r3d
700     add      r1, 4
701     add      r0, 4
702     dec      r2
703     jnz      .loop2
704 %endif
705 .end:
706     RET
707 %endmacro
708
709 INIT_XMM sse2
710 BSWAP32_BUF
711
712 INIT_XMM ssse3
713 BSWAP32_BUF
714
715 %macro op_avgh 3
716     movh   %3, %2
717     pavgb  %1, %3
718     movh   %2, %1
719 %endmacro
720
721 %macro op_avg 2
722     pavgb  %1, %2
723     mova   %2, %1
724 %endmacro
725
726 %macro op_puth 2-3
727     movh   %2, %1
728 %endmacro
729
730 %macro op_put 2
731     mova   %2, %1
732 %endmacro
733
734 ; void pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
735 %macro PIXELS4_L2 1
736 %define OP op_%1h
737 cglobal %1_pixels4_l2, 6,6
738     movsxdifnidn r3, r3d
739     movsxdifnidn r4, r4d
740     test        r5d, 1
741     je        .loop
742     movd         m0, [r1]
743     movd         m1, [r2]
744     add          r1, r4
745     add          r2, 4
746     pavgb        m0, m1
747     OP           m0, [r0], m3
748     add          r0, r3
749     dec         r5d
750 .loop:
751     mova         m0, [r1]
752     mova         m1, [r1+r4]
753     lea          r1, [r1+2*r4]
754     pavgb        m0, [r2]
755     pavgb        m1, [r2+4]
756     OP           m0, [r0], m3
757     OP           m1, [r0+r3], m3
758     lea          r0, [r0+2*r3]
759     mova         m0, [r1]
760     mova         m1, [r1+r4]
761     lea          r1, [r1+2*r4]
762     pavgb        m0, [r2+8]
763     pavgb        m1, [r2+12]
764     OP           m0, [r0], m3
765     OP           m1, [r0+r3], m3
766     lea          r0, [r0+2*r3]
767     add          r2, 16
768     sub         r5d, 4
769     jne       .loop
770     REP_RET
771 %endmacro
772
773 INIT_MMX mmxext
774 PIXELS4_L2 put
775 PIXELS4_L2 avg
776
777 ; void pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
778 %macro PIXELS8_L2 1
779 %define OP op_%1
780 cglobal %1_pixels8_l2, 6,6
781     movsxdifnidn r3, r3d
782     movsxdifnidn r4, r4d
783     test        r5d, 1
784     je        .loop
785     mova         m0, [r1]
786     mova         m1, [r2]
787     add          r1, r4
788     add          r2, 8
789     pavgb        m0, m1
790     OP           m0, [r0]
791     add          r0, r3
792     dec         r5d
793 .loop:
794     mova         m0, [r1]
795     mova         m1, [r1+r4]
796     lea          r1, [r1+2*r4]
797     pavgb        m0, [r2]
798     pavgb        m1, [r2+8]
799     OP           m0, [r0]
800     OP           m1, [r0+r3]
801     lea          r0, [r0+2*r3]
802     mova         m0, [r1]
803     mova         m1, [r1+r4]
804     lea          r1, [r1+2*r4]
805     pavgb        m0, [r2+16]
806     pavgb        m1, [r2+24]
807     OP           m0, [r0]
808     OP           m1, [r0+r3]
809     lea          r0, [r0+2*r3]
810     add          r2, 32
811     sub         r5d, 4
812     jne       .loop
813     REP_RET
814 %endmacro
815
816 INIT_MMX mmxext
817 PIXELS8_L2 put
818 PIXELS8_L2 avg
819
820 ; void pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
821 %macro PIXELS16_L2 1
822 %define OP op_%1
823 cglobal %1_pixels16_l2, 6,6
824     movsxdifnidn r3, r3d
825     movsxdifnidn r4, r4d
826     test        r5d, 1
827     je        .loop
828     mova         m0, [r1]
829     mova         m1, [r1+8]
830     pavgb        m0, [r2]
831     pavgb        m1, [r2+8]
832     add          r1, r4
833     add          r2, 16
834     OP           m0, [r0]
835     OP           m1, [r0+8]
836     add          r0, r3
837     dec         r5d
838 .loop:
839     mova         m0, [r1]
840     mova         m1, [r1+8]
841     add          r1, r4
842     pavgb        m0, [r2]
843     pavgb        m1, [r2+8]
844     OP           m0, [r0]
845     OP           m1, [r0+8]
846     add          r0, r3
847     mova         m0, [r1]
848     mova         m1, [r1+8]
849     add          r1, r4
850     pavgb        m0, [r2+16]
851     pavgb        m1, [r2+24]
852     OP           m0, [r0]
853     OP           m1, [r0+8]
854     add          r0, r3
855     add          r2, 32
856     sub         r5d, 2
857     jne       .loop
858     REP_RET
859 %endmacro
860
861 INIT_MMX mmxext
862 PIXELS16_L2 put
863 PIXELS16_L2 avg
864
865 INIT_MMX mmxext
866 ; void pixels(uint8_t *block, const uint8_t *pixels, int line_size, int h)
867 %macro PIXELS48 2
868 %if %2 == 4
869 %define OP movh
870 %else
871 %define OP mova
872 %endif
873 cglobal %1_pixels%2, 4,5
874     movsxdifnidn r2, r2d
875     lea          r4, [r2*3]
876 .loop:
877     OP           m0, [r1]
878     OP           m1, [r1+r2]
879     OP           m2, [r1+r2*2]
880     OP           m3, [r1+r4]
881     lea          r1, [r1+r2*4]
882 %ifidn %1, avg
883     pavgb        m0, [r0]
884     pavgb        m1, [r0+r2]
885     pavgb        m2, [r0+r2*2]
886     pavgb        m3, [r0+r4]
887 %endif
888     OP         [r0], m0
889     OP      [r0+r2], m1
890     OP    [r0+r2*2], m2
891     OP      [r0+r4], m3
892     sub         r3d, 4
893     lea          r0, [r0+r2*4]
894     jne       .loop
895     RET
896 %endmacro
897
898 PIXELS48 put, 4
899 PIXELS48 avg, 4
900 PIXELS48 put, 8
901 PIXELS48 avg, 8
902
903 INIT_XMM sse2
904 ; void put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
905 cglobal put_pixels16, 4,5,4
906     movsxdifnidn r2, r2d
907     lea          r4, [r2*3]
908 .loop:
909     movu         m0, [r1]
910     movu         m1, [r1+r2]
911     movu         m2, [r1+r2*2]
912     movu         m3, [r1+r4]
913     lea          r1, [r1+r2*4]
914     mova       [r0], m0
915     mova    [r0+r2], m1
916     mova  [r0+r2*2], m2
917     mova    [r0+r4], m3
918     sub         r3d, 4
919     lea          r0, [r0+r2*4]
920     jnz       .loop
921     REP_RET
922
923 ; void avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
924 cglobal avg_pixels16, 4,5,4
925     movsxdifnidn r2, r2d
926     lea          r4, [r2*3]
927 .loop:
928     movu         m0, [r1]
929     movu         m1, [r1+r2]
930     movu         m2, [r1+r2*2]
931     movu         m3, [r1+r4]
932     lea          r1, [r1+r2*4]
933     pavgb        m0, [r0]
934     pavgb        m1, [r0+r2]
935     pavgb        m2, [r0+r2*2]
936     pavgb        m3, [r0+r4]
937     mova       [r0], m0
938     mova    [r0+r2], m1
939     mova  [r0+r2*2], m2
940     mova    [r0+r4], m3
941     sub         r3d, 4
942     lea          r0, [r0+r2*4]
943     jnz       .loop
944     REP_RET