27e77d565d8909e6929b39a6465e875556fc8f21
[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 ; %1 = aligned/unaligned
571 %macro BSWAP_LOOPS  1
572     mov      r3, r2
573     sar      r2, 3
574     jz       .left4_%1
575 .loop8_%1:
576     mov%1    m0, [r1 +  0]
577     mov%1    m1, [r1 + 16]
578 %if cpuflag(ssse3)
579     pshufb   m0, m2
580     pshufb   m1, m2
581     mova     [r0 +  0], m0
582     mova     [r0 + 16], m1
583 %else
584     pshuflw  m0, m0, 10110001b
585     pshuflw  m1, m1, 10110001b
586     pshufhw  m0, m0, 10110001b
587     pshufhw  m1, m1, 10110001b
588     mova     m2, m0
589     mova     m3, m1
590     psllw    m0, 8
591     psllw    m1, 8
592     psrlw    m2, 8
593     psrlw    m3, 8
594     por      m2, m0
595     por      m3, m1
596     mova     [r0 +  0], m2
597     mova     [r0 + 16], m3
598 %endif
599     add      r0, 32
600     add      r1, 32
601     dec      r2
602     jnz      .loop8_%1
603 .left4_%1:
604     mov      r2, r3
605     and      r3, 4
606     jz       .left
607     mov%1    m0, [r1]
608 %if cpuflag(ssse3)
609     pshufb   m0, m2
610     mova     [r0], m0
611 %else
612     pshuflw  m0, m0, 10110001b
613     pshufhw  m0, m0, 10110001b
614     mova     m2, m0
615     psllw    m0, 8
616     psrlw    m2, 8
617     por      m2, m0
618     mova     [r0], m2
619 %endif
620     add      r1, 16
621     add      r0, 16
622 %endmacro
623
624 ; void bswap_buf(uint32_t *dst, const uint32_t *src, int w);
625 %macro BSWAP32_BUF 0
626 %if cpuflag(ssse3)
627 cglobal bswap32_buf, 3,4,3
628     mov      r3, r1
629     mova     m2, [pb_bswap32]
630 %else
631 cglobal bswap32_buf, 3,4,5
632     mov      r3, r1
633 %endif
634     and      r3, 15
635     jz       .start_align
636     BSWAP_LOOPS  u
637     jmp      .left
638 .start_align:
639     BSWAP_LOOPS  a
640 .left:
641 %if cpuflag(ssse3)
642     mov      r3, r2
643     and      r2, 2
644     jz       .left1
645     movq     m0, [r1]
646     pshufb   m0, m2
647     movq     [r0], m0
648     add      r1, 8
649     add      r0, 8
650 .left1:
651     and      r3, 1
652     jz       .end
653     mov      r2d, [r1]
654     bswap    r2d
655     mov      [r0], r2d
656 %else
657     and      r2, 3
658     jz       .end
659 .loop2:
660     mov      r3d, [r1]
661     bswap    r3d
662     mov      [r0], r3d
663     add      r1, 4
664     add      r0, 4
665     dec      r2
666     jnz      .loop2
667 %endif
668 .end:
669     RET
670 %endmacro
671
672 INIT_XMM sse2
673 BSWAP32_BUF
674
675 INIT_XMM ssse3
676 BSWAP32_BUF
677
678 %macro op_avgh 3
679     movh   %3, %2
680     pavgb  %1, %3
681     movh   %2, %1
682 %endmacro
683
684 %macro op_avg 2
685     pavgb  %1, %2
686     mova   %2, %1
687 %endmacro
688
689 %macro op_puth 2-3
690     movh   %2, %1
691 %endmacro
692
693 %macro op_put 2
694     mova   %2, %1
695 %endmacro
696
697 ; void pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
698 %macro PIXELS4_L2 1
699 %define OP op_%1h
700 cglobal %1_pixels4_l2, 6,6
701     movsxdifnidn r3, r3d
702     movsxdifnidn r4, r4d
703     test        r5d, 1
704     je        .loop
705     movd         m0, [r1]
706     movd         m1, [r2]
707     add          r1, r4
708     add          r2, 4
709     pavgb        m0, m1
710     OP           m0, [r0], m3
711     add          r0, r3
712     dec         r5d
713 .loop:
714     mova         m0, [r1]
715     mova         m1, [r1+r4]
716     lea          r1, [r1+2*r4]
717     pavgb        m0, [r2]
718     pavgb        m1, [r2+4]
719     OP           m0, [r0], m3
720     OP           m1, [r0+r3], m3
721     lea          r0, [r0+2*r3]
722     mova         m0, [r1]
723     mova         m1, [r1+r4]
724     lea          r1, [r1+2*r4]
725     pavgb        m0, [r2+8]
726     pavgb        m1, [r2+12]
727     OP           m0, [r0], m3
728     OP           m1, [r0+r3], m3
729     lea          r0, [r0+2*r3]
730     add          r2, 16
731     sub         r5d, 4
732     jne       .loop
733     REP_RET
734 %endmacro
735
736 INIT_MMX mmxext
737 PIXELS4_L2 put
738 PIXELS4_L2 avg
739
740 ; void pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
741 %macro PIXELS8_L2 1
742 %define OP op_%1
743 cglobal %1_pixels8_l2, 6,6
744     movsxdifnidn r3, r3d
745     movsxdifnidn r4, r4d
746     test        r5d, 1
747     je        .loop
748     mova         m0, [r1]
749     mova         m1, [r2]
750     add          r1, r4
751     add          r2, 8
752     pavgb        m0, m1
753     OP           m0, [r0]
754     add          r0, r3
755     dec         r5d
756 .loop:
757     mova         m0, [r1]
758     mova         m1, [r1+r4]
759     lea          r1, [r1+2*r4]
760     pavgb        m0, [r2]
761     pavgb        m1, [r2+8]
762     OP           m0, [r0]
763     OP           m1, [r0+r3]
764     lea          r0, [r0+2*r3]
765     mova         m0, [r1]
766     mova         m1, [r1+r4]
767     lea          r1, [r1+2*r4]
768     pavgb        m0, [r2+16]
769     pavgb        m1, [r2+24]
770     OP           m0, [r0]
771     OP           m1, [r0+r3]
772     lea          r0, [r0+2*r3]
773     add          r2, 32
774     sub         r5d, 4
775     jne       .loop
776     REP_RET
777 %endmacro
778
779 INIT_MMX mmxext
780 PIXELS8_L2 put
781 PIXELS8_L2 avg
782
783 ; void pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
784 %macro PIXELS16_L2 1
785 %define OP op_%1
786 cglobal %1_pixels16_l2, 6,6
787     movsxdifnidn r3, r3d
788     movsxdifnidn r4, r4d
789     test        r5d, 1
790     je        .loop
791     mova         m0, [r1]
792     mova         m1, [r1+8]
793     pavgb        m0, [r2]
794     pavgb        m1, [r2+8]
795     add          r1, r4
796     add          r2, 16
797     OP           m0, [r0]
798     OP           m1, [r0+8]
799     add          r0, r3
800     dec         r5d
801 .loop:
802     mova         m0, [r1]
803     mova         m1, [r1+8]
804     add          r1, r4
805     pavgb        m0, [r2]
806     pavgb        m1, [r2+8]
807     OP           m0, [r0]
808     OP           m1, [r0+8]
809     add          r0, r3
810     mova         m0, [r1]
811     mova         m1, [r1+8]
812     add          r1, r4
813     pavgb        m0, [r2+16]
814     pavgb        m1, [r2+24]
815     OP           m0, [r0]
816     OP           m1, [r0+8]
817     add          r0, r3
818     add          r2, 32
819     sub         r5d, 2
820     jne       .loop
821     REP_RET
822 %endmacro
823
824 INIT_MMX mmxext
825 PIXELS16_L2 put
826 PIXELS16_L2 avg
827
828 INIT_MMX mmxext
829 ; void pixels(uint8_t *block, const uint8_t *pixels, int line_size, int h)
830 %macro PIXELS48 2
831 %if %2 == 4
832 %define OP movh
833 %else
834 %define OP mova
835 %endif
836 cglobal %1_pixels%2, 4,5
837     movsxdifnidn r2, r2d
838     lea          r4, [r2*3]
839 .loop:
840     OP           m0, [r1]
841     OP           m1, [r1+r2]
842     OP           m2, [r1+r2*2]
843     OP           m3, [r1+r4]
844     lea          r1, [r1+r2*4]
845 %ifidn %1, avg
846     pavgb        m0, [r0]
847     pavgb        m1, [r0+r2]
848     pavgb        m2, [r0+r2*2]
849     pavgb        m3, [r0+r4]
850 %endif
851     OP         [r0], m0
852     OP      [r0+r2], m1
853     OP    [r0+r2*2], m2
854     OP      [r0+r4], m3
855     sub         r3d, 4
856     lea          r0, [r0+r2*4]
857     jne       .loop
858     RET
859 %endmacro
860
861 PIXELS48 put, 4
862 PIXELS48 avg, 4
863 PIXELS48 put, 8
864 PIXELS48 avg, 8
865
866 INIT_XMM sse2
867 ; void put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
868 cglobal put_pixels16, 4,5,4
869     movsxdifnidn r2, r2d
870     lea          r4, [r2*3]
871 .loop:
872     movu         m0, [r1]
873     movu         m1, [r1+r2]
874     movu         m2, [r1+r2*2]
875     movu         m3, [r1+r4]
876     lea          r1, [r1+r2*4]
877     mova       [r0], m0
878     mova    [r0+r2], m1
879     mova  [r0+r2*2], m2
880     mova    [r0+r4], m3
881     sub         r3d, 4
882     lea          r0, [r0+r2*4]
883     jnz       .loop
884     REP_RET
885
886 ; void avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
887 cglobal avg_pixels16, 4,5,4
888     movsxdifnidn r2, r2d
889     lea          r4, [r2*3]
890 .loop:
891     movu         m0, [r1]
892     movu         m1, [r1+r2]
893     movu         m2, [r1+r2*2]
894     movu         m3, [r1+r4]
895     lea          r1, [r1+r2*4]
896     pavgb        m0, [r0]
897     pavgb        m1, [r0+r2]
898     pavgb        m2, [r0+r2*2]
899     pavgb        m3, [r0+r4]
900     mova       [r0], m0
901     mova    [r0+r2], m1
902     mova  [r0+r2*2], m2
903     mova    [r0+r4], m3
904     sub         r3d, 4
905     lea          r0, [r0+r2*4]
906     jnz       .loop
907     REP_RET