]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/dsputil.asm
x86: consistently use unaligned movs in the unaligned bswap
[ffmpeg] / 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     mov%1    [r0 +  0], m0
556     mov%1    [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     mov%1    [r0 +  0], m2
571     mov%1    [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     mov%1    [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     mov%1    [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
653 ; FIXME: All of the code below should be put back in h264_qpel_8bit.asm.
654 ; Unfortunately it is unconditionally used from dsputil_mmx.c since 71155d7 ..
655
656 %macro op_avgh 3
657     movh   %3, %2
658     pavgb  %1, %3
659     movh   %2, %1
660 %endmacro
661
662 %macro op_avg 2
663     pavgb  %1, %2
664     mova   %2, %1
665 %endmacro
666
667 %macro op_puth 2-3
668     movh   %2, %1
669 %endmacro
670
671 %macro op_put 2
672     mova   %2, %1
673 %endmacro
674
675 ; void pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
676 %macro PIXELS4_L2 1
677 %define OP op_%1h
678 cglobal %1_pixels4_l2, 6,6
679     movsxdifnidn r3, r3d
680     movsxdifnidn r4, r4d
681     test        r5d, 1
682     je        .loop
683     movd         m0, [r1]
684     movd         m1, [r2]
685     add          r1, r4
686     add          r2, 4
687     pavgb        m0, m1
688     OP           m0, [r0], m3
689     add          r0, r3
690     dec         r5d
691 .loop:
692     mova         m0, [r1]
693     mova         m1, [r1+r4]
694     lea          r1, [r1+2*r4]
695     pavgb        m0, [r2]
696     pavgb        m1, [r2+4]
697     OP           m0, [r0], m3
698     OP           m1, [r0+r3], m3
699     lea          r0, [r0+2*r3]
700     mova         m0, [r1]
701     mova         m1, [r1+r4]
702     lea          r1, [r1+2*r4]
703     pavgb        m0, [r2+8]
704     pavgb        m1, [r2+12]
705     OP           m0, [r0], m3
706     OP           m1, [r0+r3], m3
707     lea          r0, [r0+2*r3]
708     add          r2, 16
709     sub         r5d, 4
710     jne       .loop
711     REP_RET
712 %endmacro
713
714 INIT_MMX mmxext
715 PIXELS4_L2 put
716 PIXELS4_L2 avg
717
718 ; void pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
719 %macro PIXELS8_L2 1
720 %define OP op_%1
721 cglobal %1_pixels8_l2, 6,6
722     movsxdifnidn r3, r3d
723     movsxdifnidn r4, r4d
724     test        r5d, 1
725     je        .loop
726     mova         m0, [r1]
727     mova         m1, [r2]
728     add          r1, r4
729     add          r2, 8
730     pavgb        m0, m1
731     OP           m0, [r0]
732     add          r0, r3
733     dec         r5d
734 .loop:
735     mova         m0, [r1]
736     mova         m1, [r1+r4]
737     lea          r1, [r1+2*r4]
738     pavgb        m0, [r2]
739     pavgb        m1, [r2+8]
740     OP           m0, [r0]
741     OP           m1, [r0+r3]
742     lea          r0, [r0+2*r3]
743     mova         m0, [r1]
744     mova         m1, [r1+r4]
745     lea          r1, [r1+2*r4]
746     pavgb        m0, [r2+16]
747     pavgb        m1, [r2+24]
748     OP           m0, [r0]
749     OP           m1, [r0+r3]
750     lea          r0, [r0+2*r3]
751     add          r2, 32
752     sub         r5d, 4
753     jne       .loop
754     REP_RET
755 %endmacro
756
757 INIT_MMX mmxext
758 PIXELS8_L2 put
759 PIXELS8_L2 avg
760
761 ; void pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
762 %macro PIXELS16_L2 1
763 %define OP op_%1
764 cglobal %1_pixels16_l2, 6,6
765     movsxdifnidn r3, r3d
766     movsxdifnidn r4, r4d
767     test        r5d, 1
768     je        .loop
769     mova         m0, [r1]
770     mova         m1, [r1+8]
771     pavgb        m0, [r2]
772     pavgb        m1, [r2+8]
773     add          r1, r4
774     add          r2, 16
775     OP           m0, [r0]
776     OP           m1, [r0+8]
777     add          r0, r3
778     dec         r5d
779 .loop:
780     mova         m0, [r1]
781     mova         m1, [r1+8]
782     add          r1, r4
783     pavgb        m0, [r2]
784     pavgb        m1, [r2+8]
785     OP           m0, [r0]
786     OP           m1, [r0+8]
787     add          r0, r3
788     mova         m0, [r1]
789     mova         m1, [r1+8]
790     add          r1, r4
791     pavgb        m0, [r2+16]
792     pavgb        m1, [r2+24]
793     OP           m0, [r0]
794     OP           m1, [r0+8]
795     add          r0, r3
796     add          r2, 32
797     sub         r5d, 2
798     jne       .loop
799     REP_RET
800 %endmacro
801
802 INIT_MMX mmxext
803 PIXELS16_L2 put
804 PIXELS16_L2 avg
805
806 INIT_MMX mmxext
807 ; void pixels(uint8_t *block, const uint8_t *pixels, int line_size, int h)
808 %macro PIXELS48 2
809 %if %2 == 4
810 %define OP movh
811 %else
812 %define OP mova
813 %endif
814 cglobal %1_pixels%2, 4,5
815     movsxdifnidn r2, r2d
816     lea          r4, [r2*3]
817 .loop:
818     OP           m0, [r1]
819     OP           m1, [r1+r2]
820     OP           m2, [r1+r2*2]
821     OP           m3, [r1+r4]
822     lea          r1, [r1+r2*4]
823 %ifidn %1, avg
824     pavgb        m0, [r0]
825     pavgb        m1, [r0+r2]
826     pavgb        m2, [r0+r2*2]
827     pavgb        m3, [r0+r4]
828 %endif
829     OP         [r0], m0
830     OP      [r0+r2], m1
831     OP    [r0+r2*2], m2
832     OP      [r0+r4], m3
833     sub         r3d, 4
834     lea          r0, [r0+r2*4]
835     jne       .loop
836     RET
837 %endmacro
838
839 PIXELS48 put, 4
840 PIXELS48 avg, 4
841 PIXELS48 put, 8
842 PIXELS48 avg, 8