65f4b37d8fac04f0acd05a69e359e9426f1fbdbc
[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 ; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min,
468 ;                           int32_t max, unsigned int len)
469 ;-----------------------------------------------------------------------------
470
471 ; %1 = number of xmm registers used
472 ; %2 = number of inline load/process/store loops per asm loop
473 ; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop
474 ; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2)
475 ; %5 = suffix
476 %macro VECTOR_CLIP_INT32 4-5
477 cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len
478 %if %4
479     cvtsi2ss  m4, minm
480     cvtsi2ss  m5, maxm
481 %else
482     movd      m4, minm
483     movd      m5, maxm
484 %endif
485     SPLATD    m4
486     SPLATD    m5
487 .loop:
488 %assign %%i 1
489 %rep %2
490     mova      m0,  [srcq+mmsize*0*%%i]
491     mova      m1,  [srcq+mmsize*1*%%i]
492     mova      m2,  [srcq+mmsize*2*%%i]
493     mova      m3,  [srcq+mmsize*3*%%i]
494 %if %3
495     mova      m7,  [srcq+mmsize*4*%%i]
496     mova      m8,  [srcq+mmsize*5*%%i]
497     mova      m9,  [srcq+mmsize*6*%%i]
498     mova      m10, [srcq+mmsize*7*%%i]
499 %endif
500     CLIPD  m0,  m4, m5, m6
501     CLIPD  m1,  m4, m5, m6
502     CLIPD  m2,  m4, m5, m6
503     CLIPD  m3,  m4, m5, m6
504 %if %3
505     CLIPD  m7,  m4, m5, m6
506     CLIPD  m8,  m4, m5, m6
507     CLIPD  m9,  m4, m5, m6
508     CLIPD  m10, m4, m5, m6
509 %endif
510     mova  [dstq+mmsize*0*%%i], m0
511     mova  [dstq+mmsize*1*%%i], m1
512     mova  [dstq+mmsize*2*%%i], m2
513     mova  [dstq+mmsize*3*%%i], m3
514 %if %3
515     mova  [dstq+mmsize*4*%%i], m7
516     mova  [dstq+mmsize*5*%%i], m8
517     mova  [dstq+mmsize*6*%%i], m9
518     mova  [dstq+mmsize*7*%%i], m10
519 %endif
520 %assign %%i %%i+1
521 %endrep
522     add     srcq, mmsize*4*(%2+%3)
523     add     dstq, mmsize*4*(%2+%3)
524     sub     lend, mmsize*(%2+%3)
525     jg .loop
526     REP_RET
527 %endmacro
528
529 INIT_MMX mmx
530 %define CLIPD CLIPD_MMX
531 VECTOR_CLIP_INT32 0, 1, 0, 0
532 INIT_XMM sse2
533 VECTOR_CLIP_INT32 6, 1, 0, 0, _int
534 %define CLIPD CLIPD_SSE2
535 VECTOR_CLIP_INT32 6, 2, 0, 1
536 INIT_XMM sse4
537 %define CLIPD CLIPD_SSE41
538 %ifdef m8
539 VECTOR_CLIP_INT32 11, 1, 1, 0
540 %else
541 VECTOR_CLIP_INT32 6, 1, 0, 0
542 %endif
543
544 ; %1 = aligned/unaligned
545 %macro BSWAP_LOOPS  1
546     mov      r3, r2
547     sar      r2, 3
548     jz       .left4_%1
549 .loop8_%1:
550     mov%1    m0, [r1 +  0]
551     mov%1    m1, [r1 + 16]
552 %if cpuflag(ssse3)
553     pshufb   m0, m2
554     pshufb   m1, m2
555     mova     [r0 +  0], m0
556     mova     [r0 + 16], m1
557 %else
558     pshuflw  m0, m0, 10110001b
559     pshuflw  m1, m1, 10110001b
560     pshufhw  m0, m0, 10110001b
561     pshufhw  m1, m1, 10110001b
562     mova     m2, m0
563     mova     m3, m1
564     psllw    m0, 8
565     psllw    m1, 8
566     psrlw    m2, 8
567     psrlw    m3, 8
568     por      m2, m0
569     por      m3, m1
570     mova     [r0 +  0], m2
571     mova     [r0 + 16], m3
572 %endif
573     add      r0, 32
574     add      r1, 32
575     dec      r2
576     jnz      .loop8_%1
577 .left4_%1:
578     mov      r2, r3
579     and      r3, 4
580     jz       .left
581     mov%1    m0, [r1]
582 %if cpuflag(ssse3)
583     pshufb   m0, m2
584     mova     [r0], m0
585 %else
586     pshuflw  m0, m0, 10110001b
587     pshufhw  m0, m0, 10110001b
588     mova     m2, m0
589     psllw    m0, 8
590     psrlw    m2, 8
591     por      m2, m0
592     mova     [r0], m2
593 %endif
594     add      r1, 16
595     add      r0, 16
596 %endmacro
597
598 ; void bswap_buf(uint32_t *dst, const uint32_t *src, int w);
599 %macro BSWAP32_BUF 0
600 %if cpuflag(ssse3)
601 cglobal bswap32_buf, 3,4,3
602     mov      r3, r1
603     mova     m2, [pb_bswap32]
604 %else
605 cglobal bswap32_buf, 3,4,5
606     mov      r3, r1
607 %endif
608     and      r3, 15
609     jz       .start_align
610     BSWAP_LOOPS  u
611     jmp      .left
612 .start_align:
613     BSWAP_LOOPS  a
614 .left:
615 %if cpuflag(ssse3)
616     mov      r3, r2
617     and      r2, 2
618     jz       .left1
619     movq     m0, [r1]
620     pshufb   m0, m2
621     movq     [r0], m0
622     add      r1, 8
623     add      r0, 8
624 .left1:
625     and      r3, 1
626     jz       .end
627     mov      r2d, [r1]
628     bswap    r2d
629     mov      [r0], r2d
630 %else
631     and      r2, 3
632     jz       .end
633 .loop2:
634     mov      r3d, [r1]
635     bswap    r3d
636     mov      [r0], r3d
637     add      r1, 4
638     add      r0, 4
639     dec      r2
640     jnz      .loop2
641 %endif
642 .end:
643     RET
644 %endmacro
645
646 INIT_XMM sse2
647 BSWAP32_BUF
648
649 INIT_XMM ssse3
650 BSWAP32_BUF
651
652 %macro op_avgh 3
653     movh   %3, %2
654     pavgb  %1, %3
655     movh   %2, %1
656 %endmacro
657
658 %macro op_avg 2
659     pavgb  %1, %2
660     mova   %2, %1
661 %endmacro
662
663 %macro op_puth 2-3
664     movh   %2, %1
665 %endmacro
666
667 %macro op_put 2
668     mova   %2, %1
669 %endmacro
670
671 ; void pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
672 %macro PIXELS4_L2 1
673 %define OP op_%1h
674 cglobal %1_pixels4_l2, 6,6
675     movsxdifnidn r3, r3d
676     movsxdifnidn r4, r4d
677     test        r5d, 1
678     je        .loop
679     movd         m0, [r1]
680     movd         m1, [r2]
681     add          r1, r4
682     add          r2, 4
683     pavgb        m0, m1
684     OP           m0, [r0], m3
685     add          r0, r3
686     dec         r5d
687 .loop:
688     mova         m0, [r1]
689     mova         m1, [r1+r4]
690     lea          r1, [r1+2*r4]
691     pavgb        m0, [r2]
692     pavgb        m1, [r2+4]
693     OP           m0, [r0], m3
694     OP           m1, [r0+r3], m3
695     lea          r0, [r0+2*r3]
696     mova         m0, [r1]
697     mova         m1, [r1+r4]
698     lea          r1, [r1+2*r4]
699     pavgb        m0, [r2+8]
700     pavgb        m1, [r2+12]
701     OP           m0, [r0], m3
702     OP           m1, [r0+r3], m3
703     lea          r0, [r0+2*r3]
704     add          r2, 16
705     sub         r5d, 4
706     jne       .loop
707     REP_RET
708 %endmacro
709
710 INIT_MMX mmxext
711 PIXELS4_L2 put
712 PIXELS4_L2 avg
713
714 ; void pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
715 %macro PIXELS8_L2 1
716 %define OP op_%1
717 cglobal %1_pixels8_l2, 6,6
718     movsxdifnidn r3, r3d
719     movsxdifnidn r4, r4d
720     test        r5d, 1
721     je        .loop
722     mova         m0, [r1]
723     mova         m1, [r2]
724     add          r1, r4
725     add          r2, 8
726     pavgb        m0, m1
727     OP           m0, [r0]
728     add          r0, r3
729     dec         r5d
730 .loop:
731     mova         m0, [r1]
732     mova         m1, [r1+r4]
733     lea          r1, [r1+2*r4]
734     pavgb        m0, [r2]
735     pavgb        m1, [r2+8]
736     OP           m0, [r0]
737     OP           m1, [r0+r3]
738     lea          r0, [r0+2*r3]
739     mova         m0, [r1]
740     mova         m1, [r1+r4]
741     lea          r1, [r1+2*r4]
742     pavgb        m0, [r2+16]
743     pavgb        m1, [r2+24]
744     OP           m0, [r0]
745     OP           m1, [r0+r3]
746     lea          r0, [r0+2*r3]
747     add          r2, 32
748     sub         r5d, 4
749     jne       .loop
750     REP_RET
751 %endmacro
752
753 INIT_MMX mmxext
754 PIXELS8_L2 put
755 PIXELS8_L2 avg
756
757 ; void pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
758 %macro PIXELS16_L2 1
759 %define OP op_%1
760 cglobal %1_pixels16_l2, 6,6
761     movsxdifnidn r3, r3d
762     movsxdifnidn r4, r4d
763     test        r5d, 1
764     je        .loop
765     mova         m0, [r1]
766     mova         m1, [r1+8]
767     pavgb        m0, [r2]
768     pavgb        m1, [r2+8]
769     add          r1, r4
770     add          r2, 16
771     OP           m0, [r0]
772     OP           m1, [r0+8]
773     add          r0, r3
774     dec         r5d
775 .loop:
776     mova         m0, [r1]
777     mova         m1, [r1+8]
778     add          r1, r4
779     pavgb        m0, [r2]
780     pavgb        m1, [r2+8]
781     OP           m0, [r0]
782     OP           m1, [r0+8]
783     add          r0, r3
784     mova         m0, [r1]
785     mova         m1, [r1+8]
786     add          r1, r4
787     pavgb        m0, [r2+16]
788     pavgb        m1, [r2+24]
789     OP           m0, [r0]
790     OP           m1, [r0+8]
791     add          r0, r3
792     add          r2, 32
793     sub         r5d, 2
794     jne       .loop
795     REP_RET
796 %endmacro
797
798 INIT_MMX mmxext
799 PIXELS16_L2 put
800 PIXELS16_L2 avg
801
802 INIT_MMX mmxext
803 ; void pixels(uint8_t *block, const uint8_t *pixels, int line_size, int h)
804 %macro PIXELS48 2
805 %if %2 == 4
806 %define OP movh
807 %else
808 %define OP mova
809 %endif
810 cglobal %1_pixels%2, 4,5
811     movsxdifnidn r2, r2d
812     lea          r4, [r2*3]
813 .loop:
814     OP           m0, [r1]
815     OP           m1, [r1+r2]
816     OP           m2, [r1+r2*2]
817     OP           m3, [r1+r4]
818     lea          r1, [r1+r2*4]
819 %ifidn %1, avg
820     pavgb        m0, [r0]
821     pavgb        m1, [r0+r2]
822     pavgb        m2, [r0+r2*2]
823     pavgb        m3, [r0+r4]
824 %endif
825     OP         [r0], m0
826     OP      [r0+r2], m1
827     OP    [r0+r2*2], m2
828     OP      [r0+r4], m3
829     sub         r3d, 4
830     lea          r0, [r0+r2*4]
831     jne       .loop
832     RET
833 %endmacro
834
835 PIXELS48 put, 4
836 PIXELS48 avg, 4
837 PIXELS48 put, 8
838 PIXELS48 avg, 8
839
840 INIT_XMM sse2
841 ; void put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
842 cglobal put_pixels16, 4,5,4
843     movsxdifnidn r2, r2d
844     lea          r4, [r2*3]
845 .loop:
846     movu         m0, [r1]
847     movu         m1, [r1+r2]
848     movu         m2, [r1+r2*2]
849     movu         m3, [r1+r4]
850     lea          r1, [r1+r2*4]
851     mova       [r0], m0
852     mova    [r0+r2], m1
853     mova  [r0+r2*2], m2
854     mova    [r0+r4], m3
855     sub         r3d, 4
856     lea          r0, [r0+r2*4]
857     jnz       .loop
858     REP_RET
859
860 ; void avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
861 cglobal avg_pixels16, 4,5,4
862     movsxdifnidn r2, r2d
863     lea          r4, [r2*3]
864 .loop:
865     movu         m0, [r1]
866     movu         m1, [r1+r2]
867     movu         m2, [r1+r2*2]
868     movu         m3, [r1+r4]
869     lea          r1, [r1+r2*4]
870     pavgb        m0, [r0]
871     pavgb        m1, [r0+r2]
872     pavgb        m2, [r0+r2*2]
873     pavgb        m3, [r0+r4]
874     mova       [r0], m0
875     mova    [r0+r2], m1
876     mova  [r0+r2*2], m2
877     mova    [r0+r4], m3
878     sub         r3d, 4
879     lea          r0, [r0+r2*4]
880     jnz       .loop
881     REP_RET