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