x86: hpeldsp: implement SSSE3 version of _xy2
[ffmpeg.git] / libavcodec / x86 / hpeldsp.asm
1 ;******************************************************************************
2 ;*
3 ;* Copyright (c) 2000-2001 Fabrice Bellard <fabrice@bellard.org>
4 ;* Copyright (c)      Nick Kurshev <nickols_k@mail.ru>
5 ;* Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
6 ;* Copyright (c) 2002 Zdenek Kabelac <kabi@informatics.muni.cz>
7 ;* Copyright (c) 2013 Daniel Kang
8 ;*
9 ;* SIMD-optimized halfpel functions
10 ;*
11 ;* This file is part of FFmpeg.
12 ;*
13 ;* FFmpeg is free software; you can redistribute it and/or
14 ;* modify it under the terms of the GNU Lesser General Public
15 ;* License as published by the Free Software Foundation; either
16 ;* version 2.1 of the License, or (at your option) any later version.
17 ;*
18 ;* FFmpeg is distributed in the hope that it will be useful,
19 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 ;* Lesser General Public License for more details.
22 ;*
23 ;* You should have received a copy of the GNU Lesser General Public
24 ;* License along with FFmpeg; if not, write to the Free Software
25 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 ;******************************************************************************
27
28 %include "libavutil/x86/x86util.asm"
29
30 SECTION_RODATA
31 cextern pb_1
32 cextern pw_2
33 pw_8192: times 8 dw (1<<13)
34 pb_interleave16: db 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15
35 pb_interleave8:  db 0, 4, 1, 5, 2, 6, 3, 7
36
37 SECTION_TEXT
38
39 ; void ff_put_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
40 %macro PUT_PIXELS8_X2 0
41 %if cpuflag(sse2)
42 cglobal put_pixels16_x2, 4,5,4
43 %else
44 cglobal put_pixels8_x2, 4,5
45 %endif
46     lea          r4, [r2*2]
47 .loop:
48     movu         m0, [r1+1]
49     movu         m1, [r1+r2+1]
50 %if cpuflag(sse2)
51     movu         m2, [r1]
52     movu         m3, [r1+r2]
53     pavgb        m0, m2
54     pavgb        m1, m3
55 %else
56     PAVGB        m0, [r1]
57     PAVGB        m1, [r1+r2]
58 %endif
59     mova       [r0], m0
60     mova    [r0+r2], m1
61     add          r1, r4
62     add          r0, r4
63     movu         m0, [r1+1]
64     movu         m1, [r1+r2+1]
65 %if cpuflag(sse2)
66     movu         m2, [r1]
67     movu         m3, [r1+r2]
68     pavgb        m0, m2
69     pavgb        m1, m3
70 %else
71     PAVGB        m0, [r1]
72     PAVGB        m1, [r1+r2]
73 %endif
74     add          r1, r4
75     mova       [r0], m0
76     mova    [r0+r2], m1
77     add          r0, r4
78     sub         r3d, 4
79     jne .loop
80     REP_RET
81 %endmacro
82
83 INIT_MMX mmxext
84 PUT_PIXELS8_X2
85 INIT_MMX 3dnow
86 PUT_PIXELS8_X2
87
88
89 ; void ff_put_pixels16_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
90 %macro PUT_PIXELS_16 0
91 cglobal put_pixels16_x2, 4,5
92     lea          r4, [r2*2]
93 .loop:
94     mova         m0, [r1]
95     mova         m1, [r1+r2]
96     mova         m2, [r1+8]
97     mova         m3, [r1+r2+8]
98     PAVGB        m0, [r1+1]
99     PAVGB        m1, [r1+r2+1]
100     PAVGB        m2, [r1+9]
101     PAVGB        m3, [r1+r2+9]
102     mova       [r0], m0
103     mova    [r0+r2], m1
104     mova     [r0+8], m2
105     mova  [r0+r2+8], m3
106     add          r1, r4
107     add          r0, r4
108     mova         m0, [r1]
109     mova         m1, [r1+r2]
110     mova         m2, [r1+8]
111     mova         m3, [r1+r2+8]
112     PAVGB        m0, [r1+1]
113     PAVGB        m1, [r1+r2+1]
114     PAVGB        m2, [r1+9]
115     PAVGB        m3, [r1+r2+9]
116     add          r1, r4
117     mova       [r0], m0
118     mova    [r0+r2], m1
119     mova     [r0+8], m2
120     mova  [r0+r2+8], m3
121     add          r0, r4
122     sub         r3d, 4
123     jne .loop
124     REP_RET
125 %endmacro
126
127 INIT_MMX mmxext
128 PUT_PIXELS_16
129 INIT_MMX 3dnow
130 PUT_PIXELS_16
131 ; The 8_X2 macro can easily be used here
132 INIT_XMM sse2
133 PUT_PIXELS8_X2
134
135
136 ; void ff_put_no_rnd_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
137 %macro PUT_NO_RND_PIXELS8_X2 0
138 cglobal put_no_rnd_pixels8_x2, 4,5
139     mova         m6, [pb_1]
140     lea          r4, [r2*2]
141 .loop:
142     mova         m0, [r1]
143     mova         m2, [r1+r2]
144     mova         m1, [r1+1]
145     mova         m3, [r1+r2+1]
146     add          r1, r4
147     psubusb      m0, m6
148     psubusb      m2, m6
149     PAVGB        m0, m1
150     PAVGB        m2, m3
151     mova       [r0], m0
152     mova    [r0+r2], m2
153     mova         m0, [r1]
154     mova         m1, [r1+1]
155     mova         m2, [r1+r2]
156     mova         m3, [r1+r2+1]
157     add          r0, r4
158     add          r1, r4
159     psubusb      m0, m6
160     psubusb      m2, m6
161     PAVGB        m0, m1
162     PAVGB        m2, m3
163     mova       [r0], m0
164     mova    [r0+r2], m2
165     add          r0, r4
166     sub         r3d, 4
167     jne .loop
168     REP_RET
169 %endmacro
170
171 INIT_MMX mmxext
172 PUT_NO_RND_PIXELS8_X2
173 INIT_MMX 3dnow
174 PUT_NO_RND_PIXELS8_X2
175
176
177 ; void ff_put_no_rnd_pixels8_x2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
178 %macro PUT_NO_RND_PIXELS8_X2_EXACT 0
179 cglobal put_no_rnd_pixels8_x2_exact, 4,5
180     lea          r4, [r2*3]
181     pcmpeqb      m6, m6
182 .loop:
183     mova         m0, [r1]
184     mova         m2, [r1+r2]
185     mova         m1, [r1+1]
186     mova         m3, [r1+r2+1]
187     pxor         m0, m6
188     pxor         m2, m6
189     pxor         m1, m6
190     pxor         m3, m6
191     PAVGB        m0, m1
192     PAVGB        m2, m3
193     pxor         m0, m6
194     pxor         m2, m6
195     mova       [r0], m0
196     mova    [r0+r2], m2
197     mova         m0, [r1+r2*2]
198     mova         m1, [r1+r2*2+1]
199     mova         m2, [r1+r4]
200     mova         m3, [r1+r4+1]
201     pxor         m0, m6
202     pxor         m1, m6
203     pxor         m2, m6
204     pxor         m3, m6
205     PAVGB        m0, m1
206     PAVGB        m2, m3
207     pxor         m0, m6
208     pxor         m2, m6
209     mova  [r0+r2*2], m0
210     mova    [r0+r4], m2
211     lea          r1, [r1+r2*4]
212     lea          r0, [r0+r2*4]
213     sub         r3d, 4
214     jg .loop
215     REP_RET
216 %endmacro
217
218 INIT_MMX mmxext
219 PUT_NO_RND_PIXELS8_X2_EXACT
220 INIT_MMX 3dnow
221 PUT_NO_RND_PIXELS8_X2_EXACT
222
223
224 ; void ff_put_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
225 %macro PUT_PIXELS8_Y2 0
226 %if cpuflag(sse2)
227 cglobal put_pixels16_y2, 4,5,3
228 %else
229 cglobal put_pixels8_y2, 4,5
230 %endif
231     lea          r4, [r2*2]
232     movu         m0, [r1]
233     sub          r0, r2
234 .loop:
235     movu         m1, [r1+r2]
236     movu         m2, [r1+r4]
237     add          r1, r4
238     PAVGB        m0, m1
239     PAVGB        m1, m2
240     mova    [r0+r2], m0
241     mova    [r0+r4], m1
242     movu         m1, [r1+r2]
243     movu         m0, [r1+r4]
244     add          r0, r4
245     add          r1, r4
246     PAVGB        m2, m1
247     PAVGB        m1, m0
248     mova    [r0+r2], m2
249     mova    [r0+r4], m1
250     add          r0, r4
251     sub         r3d, 4
252     jne .loop
253     REP_RET
254 %endmacro
255
256 INIT_MMX mmxext
257 PUT_PIXELS8_Y2
258 INIT_MMX 3dnow
259 PUT_PIXELS8_Y2
260 ; actually, put_pixels16_y2_sse2
261 INIT_XMM sse2
262 PUT_PIXELS8_Y2
263
264
265 ; void ff_put_no_rnd_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
266 %macro PUT_NO_RND_PIXELS8_Y2 0
267 cglobal put_no_rnd_pixels8_y2, 4,5
268     mova         m6, [pb_1]
269     lea          r4, [r2+r2]
270     mova         m0, [r1]
271     sub          r0, r2
272 .loop:
273     mova         m1, [r1+r2]
274     mova         m2, [r1+r4]
275     add          r1, r4
276     psubusb      m1, m6
277     PAVGB        m0, m1
278     PAVGB        m1, m2
279     mova    [r0+r2], m0
280     mova    [r0+r4], m1
281     mova         m1, [r1+r2]
282     mova         m0, [r1+r4]
283     add          r0, r4
284     add          r1, r4
285     psubusb      m1, m6
286     PAVGB        m2, m1
287     PAVGB        m1, m0
288     mova    [r0+r2], m2
289     mova    [r0+r4], m1
290     add          r0, r4
291     sub         r3d, 4
292     jne .loop
293     REP_RET
294 %endmacro
295
296 INIT_MMX mmxext
297 PUT_NO_RND_PIXELS8_Y2
298 INIT_MMX 3dnow
299 PUT_NO_RND_PIXELS8_Y2
300
301
302 ; void ff_put_no_rnd_pixels8_y2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
303 %macro PUT_NO_RND_PIXELS8_Y2_EXACT 0
304 cglobal put_no_rnd_pixels8_y2_exact, 4,5
305     lea          r4, [r2*3]
306     mova         m0, [r1]
307     pcmpeqb      m6, m6
308     add          r1, r2
309     pxor         m0, m6
310 .loop:
311     mova         m1, [r1]
312     mova         m2, [r1+r2]
313     pxor         m1, m6
314     pxor         m2, m6
315     PAVGB        m0, m1
316     PAVGB        m1, m2
317     pxor         m0, m6
318     pxor         m1, m6
319     mova       [r0], m0
320     mova    [r0+r2], m1
321     mova         m1, [r1+r2*2]
322     mova         m0, [r1+r4]
323     pxor         m1, m6
324     pxor         m0, m6
325     PAVGB        m2, m1
326     PAVGB        m1, m0
327     pxor         m2, m6
328     pxor         m1, m6
329     mova  [r0+r2*2], m2
330     mova    [r0+r4], m1
331     lea          r1, [r1+r2*4]
332     lea          r0, [r0+r2*4]
333     sub         r3d, 4
334     jg .loop
335     REP_RET
336 %endmacro
337
338 INIT_MMX mmxext
339 PUT_NO_RND_PIXELS8_Y2_EXACT
340 INIT_MMX 3dnow
341 PUT_NO_RND_PIXELS8_Y2_EXACT
342
343
344 ; void ff_avg_pixels8(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
345 %macro AVG_PIXELS8 0
346 cglobal avg_pixels8, 4,5
347     lea          r4, [r2*2]
348 .loop:
349     mova         m0, [r0]
350     mova         m1, [r0+r2]
351     PAVGB        m0, [r1]
352     PAVGB        m1, [r1+r2]
353     mova       [r0], m0
354     mova    [r0+r2], m1
355     add          r1, r4
356     add          r0, r4
357     mova         m0, [r0]
358     mova         m1, [r0+r2]
359     PAVGB        m0, [r1]
360     PAVGB        m1, [r1+r2]
361     add          r1, r4
362     mova       [r0], m0
363     mova    [r0+r2], m1
364     add          r0, r4
365     sub         r3d, 4
366     jne .loop
367     REP_RET
368 %endmacro
369
370 INIT_MMX 3dnow
371 AVG_PIXELS8
372
373
374 ; void ff_avg_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
375 %macro PAVGB_MMX 4
376     movu   %3, %1
377     por    %3, %2
378     pxor   %2, %1
379     pand   %2, %4
380     psrlq  %2, 1
381     psubb  %3, %2
382     SWAP   %2, %3
383 %endmacro
384
385 %macro AVG_PIXELS8_X2 0
386 %if cpuflag(sse2)
387 cglobal avg_pixels16_x2, 4,5,4
388 %else
389 cglobal avg_pixels8_x2, 4,5
390 %endif
391     lea          r4, [r2*2]
392 %if notcpuflag(mmxext)
393     pcmpeqd      m5, m5
394     paddb        m5, m5
395 %endif
396 .loop:
397     movu         m0, [r1]
398     movu         m2, [r1+r2]
399 %if notcpuflag(mmxext)
400     PAVGB_MMX    [r1+1], m0, m3, m5
401     PAVGB_MMX    [r1+r2+1], m2, m4, m5
402     PAVGB_MMX    [r0], m0, m3, m5
403     PAVGB_MMX    [r0+r2], m2, m4, m5
404 %else
405 %if cpuflag(sse2)
406     movu         m1, [r1+1]
407     movu         m3, [r1+r2+1]
408     pavgb        m0, m1
409     pavgb        m2, m3
410 %else
411     PAVGB        m0, [r1+1]
412     PAVGB        m2, [r1+r2+1]
413 %endif
414     PAVGB        m0, [r0]
415     PAVGB        m2, [r0+r2]
416 %endif
417     add          r1, r4
418     mova       [r0], m0
419     mova    [r0+r2], m2
420     movu         m0, [r1]
421     movu         m2, [r1+r2]
422 %if notcpuflag(mmxext)
423     PAVGB_MMX    [r1+1], m0, m3, m5
424     PAVGB_MMX    [r1+r2+1], m2, m4, m5
425 %elif cpuflag(sse2)
426     movu         m1, [r1+1]
427     movu         m3, [r1+r2+1]
428     pavgb        m0, m1
429     pavgb        m2, m3
430 %else
431     PAVGB        m0, [r1+1]
432     PAVGB        m2, [r1+r2+1]
433 %endif
434     add          r0, r4
435     add          r1, r4
436 %if notcpuflag(mmxext)
437     PAVGB_MMX    [r0], m0, m3, m5
438     PAVGB_MMX    [r0+r2], m2, m4, m5
439 %elif cpuflag(sse2)
440     pavgb        m0, [r0]
441     pavgb        m2, [r0+r2]
442 %else
443     PAVGB        m0, [r0]
444     PAVGB        m2, [r0+r2]
445 %endif
446     mova       [r0], m0
447     mova    [r0+r2], m2
448     add          r0, r4
449     sub         r3d, 4
450     jne .loop
451     REP_RET
452 %endmacro
453
454 INIT_MMX mmx
455 AVG_PIXELS8_X2
456 INIT_MMX mmxext
457 AVG_PIXELS8_X2
458 INIT_MMX 3dnow
459 AVG_PIXELS8_X2
460 ; actually avg_pixels16_x2
461 INIT_XMM sse2
462 AVG_PIXELS8_X2
463
464
465 ; void ff_avg_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
466 %macro AVG_PIXELS8_Y2 0
467 %if cpuflag(sse2)
468 cglobal avg_pixels16_y2, 4,5,3
469 %else
470 cglobal avg_pixels8_y2, 4,5
471 %endif
472     lea          r4, [r2*2]
473     movu         m0, [r1]
474     sub          r0, r2
475 .loop:
476     movu         m1, [r1+r2]
477     movu         m2, [r1+r4]
478     add          r1, r4
479     PAVGB        m0, m1
480     PAVGB        m1, m2
481     PAVGB        m0, [r0+r2]
482     PAVGB        m1, [r0+r4]
483     mova    [r0+r2], m0
484     mova    [r0+r4], m1
485     movu         m1, [r1+r2]
486     movu         m0, [r1+r4]
487     PAVGB        m2, m1
488     PAVGB        m1, m0
489     add          r0, r4
490     add          r1, r4
491     PAVGB        m2, [r0+r2]
492     PAVGB        m1, [r0+r4]
493     mova    [r0+r2], m2
494     mova    [r0+r4], m1
495     add          r0, r4
496     sub         r3d, 4
497     jne .loop
498     REP_RET
499 %endmacro
500
501 INIT_MMX mmxext
502 AVG_PIXELS8_Y2
503 INIT_MMX 3dnow
504 AVG_PIXELS8_Y2
505 ; actually avg_pixels16_y2
506 INIT_XMM sse2
507 AVG_PIXELS8_Y2
508
509
510 ; void ff_avg_pixels8_xy2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
511 ; Note this is not correctly rounded, and is therefore used for
512 ; not-bitexact output
513 %macro AVG_APPROX_PIXELS8_XY2 0
514 cglobal avg_approx_pixels8_xy2, 4,5
515     mova         m6, [pb_1]
516     lea          r4, [r2*2]
517     mova         m0, [r1]
518     PAVGB        m0, [r1+1]
519 .loop:
520     mova         m2, [r1+r4]
521     mova         m1, [r1+r2]
522     psubusb      m2, m6
523     PAVGB        m1, [r1+r2+1]
524     PAVGB        m2, [r1+r4+1]
525     add          r1, r4
526     PAVGB        m0, m1
527     PAVGB        m1, m2
528     PAVGB        m0, [r0]
529     PAVGB        m1, [r0+r2]
530     mova       [r0], m0
531     mova    [r0+r2], m1
532     mova         m1, [r1+r2]
533     mova         m0, [r1+r4]
534     PAVGB        m1, [r1+r2+1]
535     PAVGB        m0, [r1+r4+1]
536     add          r0, r4
537     add          r1, r4
538     PAVGB        m2, m1
539     PAVGB        m1, m0
540     PAVGB        m2, [r0]
541     PAVGB        m1, [r0+r2]
542     mova       [r0], m2
543     mova    [r0+r2], m1
544     add          r0, r4
545     sub         r3d, 4
546     jne .loop
547     REP_RET
548 %endmacro
549
550 INIT_MMX mmxext
551 AVG_APPROX_PIXELS8_XY2
552 INIT_MMX 3dnow
553 AVG_APPROX_PIXELS8_XY2
554
555
556 ; void ff_avg_pixels16_xy2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
557 %macro SET_PIXELS_XY2 1
558 %if cpuflag(sse2)
559 cglobal %1_pixels16_xy2, 4,5,8
560 %else
561 cglobal %1_pixels8_xy2, 4,5
562 %endif
563     pxor        m7, m7
564     mova        m6, [pw_2]
565     movu        m0, [r1]
566     movu        m4, [r1+1]
567     mova        m1, m0
568     mova        m5, m4
569     punpcklbw   m0, m7
570     punpcklbw   m4, m7
571     punpckhbw   m1, m7
572     punpckhbw   m5, m7
573     paddusw     m4, m0
574     paddusw     m5, m1
575     xor         r4, r4
576     add         r1, r2
577 .loop:
578     movu        m0, [r1+r4]
579     movu        m2, [r1+r4+1]
580     mova        m1, m0
581     mova        m3, m2
582     punpcklbw   m0, m7
583     punpcklbw   m2, m7
584     punpckhbw   m1, m7
585     punpckhbw   m3, m7
586     paddusw     m0, m2
587     paddusw     m1, m3
588     paddusw     m4, m6
589     paddusw     m5, m6
590     paddusw     m4, m0
591     paddusw     m5, m1
592     psrlw       m4, 2
593     psrlw       m5, 2
594 %ifidn %1, avg
595     mova        m3, [r0+r4]
596     packuswb    m4, m5
597     PAVGB       m4, m3
598 %else
599     packuswb    m4, m5
600 %endif
601     mova   [r0+r4], m4
602     add         r4, r2
603
604     movu        m2, [r1+r4]
605     movu        m4, [r1+r4+1]
606     mova        m3, m2
607     mova        m5, m4
608     punpcklbw   m2, m7
609     punpcklbw   m4, m7
610     punpckhbw   m3, m7
611     punpckhbw   m5, m7
612     paddusw     m4, m2
613     paddusw     m5, m3
614     paddusw     m0, m6
615     paddusw     m1, m6
616     paddusw     m0, m4
617     paddusw     m1, m5
618     psrlw       m0, 2
619     psrlw       m1, 2
620 %ifidn %1, avg
621     mova        m3, [r0+r4]
622     packuswb    m0, m1
623     PAVGB       m0, m3
624 %else
625     packuswb    m0, m1
626 %endif
627     mova   [r0+r4], m0
628     add         r4, r2
629     sub        r3d, 2
630     jnz .loop
631     REP_RET
632 %endmacro
633
634 INIT_MMX mmxext
635 SET_PIXELS_XY2 avg
636 INIT_MMX 3dnow
637 SET_PIXELS_XY2 avg
638 INIT_XMM sse2
639 SET_PIXELS_XY2 put
640 SET_PIXELS_XY2 avg
641
642 %macro SSSE3_PIXELS_XY2 1-2
643 %if %0 == 2 ; sse2
644 cglobal %1_pixels16_xy2, 4,5,%2
645     mova        m4, [pb_interleave16]
646 %else
647 cglobal %1_pixels8_xy2, 4,5
648     mova        m4, [pb_interleave8]
649 %endif
650     mova        m5, [pb_1]
651     movu        m0, [r1]
652     movu        m1, [r1+1]
653     pmaddubsw   m0, m5
654     pmaddubsw   m1, m5
655     xor         r4, r4
656     add         r1, r2
657 .loop:
658     movu        m2, [r1+r4]
659     movu        m3, [r1+r4+1]
660     pmaddubsw   m2, m5
661     pmaddubsw   m3, m5
662     paddusw     m0, m2
663     paddusw     m1, m3
664     pmulhrsw    m0, [pw_8192]
665     pmulhrsw    m1, [pw_8192]
666 %ifidn %1, avg
667     mova        m6, [r0+r4]
668     packuswb    m0, m1
669     pshufb      m0, m4
670     pavgb       m0, m6
671 %else
672     packuswb    m0, m1
673     pshufb      m0, m4
674 %endif
675     mova   [r0+r4], m0
676     add         r4, r2
677
678     movu        m0, [r1+r4]
679     movu        m1, [r1+r4+1]
680     pmaddubsw   m0, m5
681     pmaddubsw   m1, m5
682     paddusw     m2, m0
683     paddusw     m3, m1
684     pmulhrsw    m2, [pw_8192]
685     pmulhrsw    m3, [pw_8192]
686 %ifidn %1, avg
687     mova        m6, [r0+r4]
688     packuswb    m2, m3
689     pshufb      m2, m4
690     pavgb       m2, m6
691 %else
692     packuswb    m2, m3
693     pshufb      m2, m4
694 %endif
695     mova   [r0+r4], m2
696     add         r4, r2
697     sub        r3d, 2
698     jnz .loop
699     REP_RET
700 %endmacro
701
702 INIT_MMX ssse3
703 SSSE3_PIXELS_XY2 put
704 SSSE3_PIXELS_XY2 avg
705 INIT_XMM ssse3
706 SSSE3_PIXELS_XY2 put, 6
707 SSSE3_PIXELS_XY2 avg, 7