x86/me_cmp: port mmxext and sse2 sad functions to yasm
[ffmpeg.git] / libavcodec / x86 / me_cmp.asm
1 ;*****************************************************************************
2 ;* SIMD-optimized motion compensation estimation
3 ;*****************************************************************************
4 ;* Copyright (c) 2000, 2001 Fabrice Bellard
5 ;* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
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
28 cextern pb_1
29
30 SECTION .text
31
32 %macro DIFF_PIXELS_1 4
33     movh            %1, %3
34     movh            %2, %4
35     punpcklbw       %2, %1
36     punpcklbw       %1, %1
37     psubw           %1, %2
38 %endmacro
39
40 ; %1=uint8_t *pix1, %2=uint8_t *pix2, %3=static offset, %4=stride, %5=stride*3
41 ; %6=temporary storage location
42 ; this macro requires $mmsize stack space (aligned) on %6 (except on SSE+x86-64)
43 %macro DIFF_PIXELS_8 6
44     DIFF_PIXELS_1   m0, m7, [%1     +%3], [%2     +%3]
45     DIFF_PIXELS_1   m1, m7, [%1+%4  +%3], [%2+%4  +%3]
46     DIFF_PIXELS_1   m2, m7, [%1+%4*2+%3], [%2+%4*2+%3]
47     add             %1, %5
48     add             %2, %5
49     DIFF_PIXELS_1   m3, m7, [%1     +%3], [%2     +%3]
50     DIFF_PIXELS_1   m4, m7, [%1+%4  +%3], [%2+%4  +%3]
51     DIFF_PIXELS_1   m5, m7, [%1+%4*2+%3], [%2+%4*2+%3]
52     DIFF_PIXELS_1   m6, m7, [%1+%5  +%3], [%2+%5  +%3]
53 %ifdef m8
54     DIFF_PIXELS_1   m7, m8, [%1+%4*4+%3], [%2+%4*4+%3]
55 %else
56     mova          [%6], m0
57     DIFF_PIXELS_1   m7, m0, [%1+%4*4+%3], [%2+%4*4+%3]
58     mova            m0, [%6]
59 %endif
60     sub             %1, %5
61     sub             %2, %5
62 %endmacro
63
64 %macro HADAMARD8 0
65     SUMSUB_BADC       w, 0, 1, 2, 3
66     SUMSUB_BADC       w, 4, 5, 6, 7
67     SUMSUB_BADC       w, 0, 2, 1, 3
68     SUMSUB_BADC       w, 4, 6, 5, 7
69     SUMSUB_BADC       w, 0, 4, 1, 5
70     SUMSUB_BADC       w, 2, 6, 3, 7
71 %endmacro
72
73 %macro ABS1_SUM 3
74     ABS1            %1, %2
75     paddusw         %3, %1
76 %endmacro
77
78 %macro ABS2_SUM 6
79     ABS2            %1, %2, %3, %4
80     paddusw         %5, %1
81     paddusw         %6, %2
82 %endmacro
83
84 %macro ABS_SUM_8x8_64 1
85     ABS2            m0, m1, m8, m9
86     ABS2_SUM        m2, m3, m8, m9, m0, m1
87     ABS2_SUM        m4, m5, m8, m9, m0, m1
88     ABS2_SUM        m6, m7, m8, m9, m0, m1
89     paddusw         m0, m1
90 %endmacro
91
92 %macro ABS_SUM_8x8_32 1
93     mova          [%1], m7
94     ABS1            m0, m7
95     ABS1            m1, m7
96     ABS1_SUM        m2, m7, m0
97     ABS1_SUM        m3, m7, m1
98     ABS1_SUM        m4, m7, m0
99     ABS1_SUM        m5, m7, m1
100     ABS1_SUM        m6, m7, m0
101     mova            m2, [%1]
102     ABS1_SUM        m2, m7, m1
103     paddusw         m0, m1
104 %endmacro
105
106 ; FIXME: HSUM saturates at 64k, while an 8x8 hadamard or dct block can get up to
107 ; about 100k on extreme inputs. But that's very unlikely to occur in natural video,
108 ; and it's even more unlikely to not have any alternative mvs/modes with lower cost.
109 %macro HSUM 3
110 %if cpuflag(sse2)
111     movhlps         %2, %1
112     paddusw         %1, %2
113     pshuflw         %2, %1, 0xE
114     paddusw         %1, %2
115     pshuflw         %2, %1, 0x1
116     paddusw         %1, %2
117     movd            %3, %1
118 %elif cpuflag(mmxext)
119     pshufw          %2, %1, 0xE
120     paddusw         %1, %2
121     pshufw          %2, %1, 0x1
122     paddusw         %1, %2
123     movd            %3, %1
124 %elif cpuflag(mmx)
125     mova            %2, %1
126     psrlq           %1, 32
127     paddusw         %1, %2
128     mova            %2, %1
129     psrlq           %1, 16
130     paddusw         %1, %2
131     movd            %3, %1
132 %endif
133 %endmacro
134
135 %macro STORE4 5
136     mova [%1+mmsize*0], %2
137     mova [%1+mmsize*1], %3
138     mova [%1+mmsize*2], %4
139     mova [%1+mmsize*3], %5
140 %endmacro
141
142 %macro LOAD4 5
143     mova            %2, [%1+mmsize*0]
144     mova            %3, [%1+mmsize*1]
145     mova            %4, [%1+mmsize*2]
146     mova            %5, [%1+mmsize*3]
147 %endmacro
148
149 %macro hadamard8_16_wrapper 2
150 cglobal hadamard8_diff, 4, 4, %1
151 %ifndef m8
152     %assign pad %2*mmsize-(4+stack_offset&(mmsize-1))
153     SUB            rsp, pad
154 %endif
155     call hadamard8x8_diff %+ SUFFIX
156 %ifndef m8
157     ADD            rsp, pad
158 %endif
159     RET
160
161 cglobal hadamard8_diff16, 5, 6, %1
162 %ifndef m8
163     %assign pad %2*mmsize-(4+stack_offset&(mmsize-1))
164     SUB            rsp, pad
165 %endif
166
167     call hadamard8x8_diff %+ SUFFIX
168     mov            r5d, eax
169
170     add             r1, 8
171     add             r2, 8
172     call hadamard8x8_diff %+ SUFFIX
173     add            r5d, eax
174
175     cmp            r4d, 16
176     jne .done
177
178     lea             r1, [r1+r3*8-8]
179     lea             r2, [r2+r3*8-8]
180     call hadamard8x8_diff %+ SUFFIX
181     add            r5d, eax
182
183     add             r1, 8
184     add             r2, 8
185     call hadamard8x8_diff %+ SUFFIX
186     add            r5d, eax
187
188 .done:
189     mov            eax, r5d
190 %ifndef m8
191     ADD            rsp, pad
192 %endif
193     RET
194 %endmacro
195
196 %macro HADAMARD8_DIFF 0-1
197 %if cpuflag(sse2)
198 hadamard8x8_diff %+ SUFFIX:
199     lea                          r0, [r3*3]
200     DIFF_PIXELS_8                r1, r2,  0, r3, r0, rsp+gprsize
201     HADAMARD8
202 %if ARCH_X86_64
203     TRANSPOSE8x8W                 0,  1,  2,  3,  4,  5,  6,  7,  8
204 %else
205     TRANSPOSE8x8W                 0,  1,  2,  3,  4,  5,  6,  7, [rsp+gprsize], [rsp+mmsize+gprsize]
206 %endif
207     HADAMARD8
208     ABS_SUM_8x8         rsp+gprsize
209     HSUM                        m0, m1, eax
210     and                         eax, 0xFFFF
211     ret
212
213 hadamard8_16_wrapper %1, 3
214 %elif cpuflag(mmx)
215 ALIGN 16
216 ; int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1,
217 ;                               uint8_t *src2, int stride, int h)
218 ; r0 = void *s = unused, int h = unused (always 8)
219 ; note how r1, r2 and r3 are not clobbered in this function, so 16x16
220 ; can simply call this 2x2x (and that's why we access rsp+gprsize
221 ; everywhere, which is rsp of calling func
222 hadamard8x8_diff %+ SUFFIX:
223     lea                          r0, [r3*3]
224
225     ; first 4x8 pixels
226     DIFF_PIXELS_8                r1, r2,  0, r3, r0, rsp+gprsize+0x60
227     HADAMARD8
228     mova         [rsp+gprsize+0x60], m7
229     TRANSPOSE4x4W                 0,  1,  2,  3,  7
230     STORE4              rsp+gprsize, m0, m1, m2, m3
231     mova                         m7, [rsp+gprsize+0x60]
232     TRANSPOSE4x4W                 4,  5,  6,  7,  0
233     STORE4         rsp+gprsize+0x40, m4, m5, m6, m7
234
235     ; second 4x8 pixels
236     DIFF_PIXELS_8                r1, r2,  4, r3, r0, rsp+gprsize+0x60
237     HADAMARD8
238     mova         [rsp+gprsize+0x60], m7
239     TRANSPOSE4x4W                 0,  1,  2,  3,  7
240     STORE4         rsp+gprsize+0x20, m0, m1, m2, m3
241     mova                         m7, [rsp+gprsize+0x60]
242     TRANSPOSE4x4W                 4,  5,  6,  7,  0
243
244     LOAD4          rsp+gprsize+0x40, m0, m1, m2, m3
245     HADAMARD8
246     ABS_SUM_8x8_32 rsp+gprsize+0x60
247     mova         [rsp+gprsize+0x60], m0
248
249     LOAD4          rsp+gprsize     , m0, m1, m2, m3
250     LOAD4          rsp+gprsize+0x20, m4, m5, m6, m7
251     HADAMARD8
252     ABS_SUM_8x8_32 rsp+gprsize
253     paddusw                      m0, [rsp+gprsize+0x60]
254
255     HSUM                         m0, m1, eax
256     and                         rax, 0xFFFF
257     ret
258
259 hadamard8_16_wrapper 0, 14
260 %endif
261 %endmacro
262
263 INIT_MMX mmx
264 HADAMARD8_DIFF
265
266 INIT_MMX mmxext
267 HADAMARD8_DIFF
268
269 INIT_XMM sse2
270 %if ARCH_X86_64
271 %define ABS_SUM_8x8 ABS_SUM_8x8_64
272 %else
273 %define ABS_SUM_8x8 ABS_SUM_8x8_32
274 %endif
275 HADAMARD8_DIFF 10
276
277 INIT_XMM ssse3
278 %define ABS_SUM_8x8 ABS_SUM_8x8_64
279 HADAMARD8_DIFF 9
280
281 ; int ff_sse*_*(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
282 ;               int line_size, int h)
283
284 %macro SUM_SQUARED_ERRORS 1
285 cglobal sse%1, 5,5,8, v, pix1, pix2, lsize, h
286 %if %1 == mmsize
287     shr       hd, 1
288 %endif
289     pxor      m0, m0         ; mm0 = 0
290     pxor      m7, m7         ; mm7 holds the sum
291
292 .next2lines: ; FIXME why are these unaligned movs? pix1[] is aligned
293     movu      m1, [pix1q]    ; m1 = pix1[0][0-15], [0-7] for mmx
294     movu      m2, [pix2q]    ; m2 = pix2[0][0-15], [0-7] for mmx
295 %if %1 == mmsize
296     movu      m3, [pix1q+lsizeq] ; m3 = pix1[1][0-15], [0-7] for mmx
297     movu      m4, [pix2q+lsizeq] ; m4 = pix2[1][0-15], [0-7] for mmx
298 %else  ; %1 / 2 == mmsize; mmx only
299     mova      m3, [pix1q+8]  ; m3 = pix1[0][8-15]
300     mova      m4, [pix2q+8]  ; m4 = pix2[0][8-15]
301 %endif
302
303     ; todo: mm1-mm2, mm3-mm4
304     ; algo: subtract mm1 from mm2 with saturation and vice versa
305     ;       OR the result to get the absolute difference
306     mova      m5, m1
307     mova      m6, m3
308     psubusb   m1, m2
309     psubusb   m3, m4
310     psubusb   m2, m5
311     psubusb   m4, m6
312
313     por       m2, m1
314     por       m4, m3
315
316     ; now convert to 16-bit vectors so we can square them
317     mova      m1, m2
318     mova      m3, m4
319
320     punpckhbw m2, m0
321     punpckhbw m4, m0
322     punpcklbw m1, m0         ; mm1 not spread over (mm1,mm2)
323     punpcklbw m3, m0         ; mm4 not spread over (mm3,mm4)
324
325     pmaddwd   m2, m2
326     pmaddwd   m4, m4
327     pmaddwd   m1, m1
328     pmaddwd   m3, m3
329
330     paddd     m1, m2
331     paddd     m3, m4
332     paddd     m7, m1
333     paddd     m7, m3
334
335 %if %1 == mmsize
336     lea    pix1q, [pix1q + 2*lsizeq]
337     lea    pix2q, [pix2q + 2*lsizeq]
338 %else
339     add    pix1q, lsizeq
340     add    pix2q, lsizeq
341 %endif
342     dec       hd
343     jnz .next2lines
344
345     HADDD     m7, m1
346     movd     eax, m7         ; return value
347     RET
348 %endmacro
349
350 INIT_MMX mmx
351 SUM_SQUARED_ERRORS 8
352
353 INIT_MMX mmx
354 SUM_SQUARED_ERRORS 16
355
356 INIT_XMM sse2
357 SUM_SQUARED_ERRORS 16
358
359 ;-----------------------------------------------
360 ;int ff_sum_abs_dctelem(int16_t *block)
361 ;-----------------------------------------------
362 ; %1 = number of xmm registers used
363 ; %2 = number of inline loops
364
365 %macro SUM_ABS_DCTELEM 2
366 cglobal sum_abs_dctelem, 1, 1, %1, block
367     pxor    m0, m0
368     pxor    m1, m1
369 %assign %%i 0
370 %rep %2
371     mova      m2, [blockq+mmsize*(0+%%i)]
372     mova      m3, [blockq+mmsize*(1+%%i)]
373     mova      m4, [blockq+mmsize*(2+%%i)]
374     mova      m5, [blockq+mmsize*(3+%%i)]
375     ABS1_SUM  m2, m6, m0
376     ABS1_SUM  m3, m6, m1
377     ABS1_SUM  m4, m6, m0
378     ABS1_SUM  m5, m6, m1
379 %assign %%i %%i+4
380 %endrep
381     paddusw m0, m1
382     HSUM    m0, m1, eax
383     and     eax, 0xFFFF
384     RET
385 %endmacro
386
387 INIT_MMX mmx
388 SUM_ABS_DCTELEM 0, 4
389 INIT_MMX mmxext
390 SUM_ABS_DCTELEM 0, 4
391 INIT_XMM sse2
392 SUM_ABS_DCTELEM 7, 2
393 INIT_XMM ssse3
394 SUM_ABS_DCTELEM 6, 2
395
396 ;------------------------------------------------------------------------------
397 ; int ff_hf_noise*_mmx(uint8_t *pix1, int lsize, int h)
398 ;------------------------------------------------------------------------------
399 ; %1 = 8/16. %2-5=m#
400 %macro HF_NOISE_PART1 5
401     mova      m%2, [pix1q]
402 %if %1 == 8
403     mova      m%3, m%2
404     psllq     m%2, 8
405     psrlq     m%3, 8
406     psrlq     m%2, 8
407 %else
408     mova      m%3, [pix1q+1]
409 %endif
410     mova      m%4, m%2
411     mova      m%5, m%3
412     punpcklbw m%2, m7
413     punpcklbw m%3, m7
414     punpckhbw m%4, m7
415     punpckhbw m%5, m7
416     psubw     m%2, m%3
417     psubw     m%4, m%5
418 %endmacro
419
420 ; %1-2 = m#
421 %macro HF_NOISE_PART2 4
422     psubw     m%1, m%3
423     psubw     m%2, m%4
424     pxor       m3, m3
425     pxor       m1, m1
426     pcmpgtw    m3, m%1
427     pcmpgtw    m1, m%2
428     pxor      m%1, m3
429     pxor      m%2, m1
430     psubw     m%1, m3
431     psubw     m%2, m1
432     paddw     m%2, m%1
433     paddw      m6, m%2
434 %endmacro
435
436 ; %1 = 8/16
437 %macro HF_NOISE 1
438 cglobal hf_noise%1, 3,3,0, pix1, lsize, h
439     movsxdifnidn lsizeq, lsized
440     sub        hd, 2
441     pxor       m7, m7
442     pxor       m6, m6
443     HF_NOISE_PART1 %1, 0, 1, 2, 3
444     add     pix1q, lsizeq
445     HF_NOISE_PART1 %1, 4, 1, 5, 3
446     HF_NOISE_PART2     0, 2, 4, 5
447     add     pix1q, lsizeq
448 .loop:
449     HF_NOISE_PART1 %1, 0, 1, 2, 3
450     HF_NOISE_PART2     4, 5, 0, 2
451     add     pix1q, lsizeq
452     HF_NOISE_PART1 %1, 4, 1, 5, 3
453     HF_NOISE_PART2     0, 2, 4, 5
454     add     pix1q, lsizeq
455     sub        hd, 2
456         jne .loop
457
458     mova       m0, m6
459     punpcklwd  m0, m7
460     punpckhwd  m6, m7
461     paddd      m6, m0
462     mova       m0, m6
463     psrlq      m6, 32
464     paddd      m0, m6
465     movd      eax, m0   ; eax = result of hf_noise8;
466     REP_RET                 ; return eax;
467 %endmacro
468
469 INIT_MMX mmx
470 HF_NOISE 8
471 HF_NOISE 16
472
473 ;---------------------------------------------------------------------------------------
474 ;int ff_sad_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int stride, int h);
475 ;---------------------------------------------------------------------------------------
476 INIT_MMX mmxext
477 cglobal sad8, 4, 4, 0, v, pix1, pix2, stride
478     movu      m2, [pix2q]
479     movu      m1, [pix2q+strideq]
480     psadbw    m2, [pix1q]
481     psadbw    m1, [pix1q+strideq]
482     paddw     m2, m1
483
484 %rep 3
485     lea    pix1q, [pix1q+strideq*2]
486     lea    pix2q, [pix2q+strideq*2]
487     movu      m0, [pix2q]
488     movu      m1, [pix2q+strideq]
489     psadbw    m0, [pix1q]
490     psadbw    m1, [pix1q+strideq]
491     paddw     m2, m0
492     paddw     m2, m1
493 %endrep
494     movd     eax, m2
495     RET
496
497 %macro SAD16 0
498 cglobal sad16, 5, 5, 3, v, pix1, pix2, stride, h
499     pxor      m2, m2
500
501 align 16
502 .loop
503     movu      m0, [pix2q]
504     movu      m1, [pix2q+strideq]
505     psadbw    m0, [pix1q]
506     psadbw    m1, [pix1q+strideq]
507     paddw     m2, m0
508     paddw     m2, m1
509 %if mmsize == 8
510     movu      m0, [pix2q+8]
511     movu      m1, [pix2q+strideq+8]
512     psadbw    m0, [pix1q+8]
513     psadbw    m1, [pix1q+strideq+8]
514     paddw     m2, m0
515     paddw     m2, m1
516 %endif
517     lea    pix1q, [pix1q+strideq*2]
518     lea    pix2q, [pix2q+strideq*2]
519     sub       hd, 2
520     jg .loop
521 %if mmsize == 16
522     movhlps   m0, m2
523     paddw     m2, m0
524 %endif
525     movd     eax, m2
526     RET
527 %endmacro
528
529 INIT_MMX mmxext
530 SAD16
531 INIT_XMM sse2
532 SAD16
533
534 ;------------------------------------------------------------------------------------------
535 ;int ff_sad_x2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int stride, int h);
536 ;------------------------------------------------------------------------------------------
537 INIT_MMX mmxext
538 cglobal sad8_x2, 4, 4, 0, v, pix1, pix2, stride
539     movu      m0, [pix2q]
540     movu      m2, [pix2q+strideq]
541     pavgb     m0, [pix2q+1]
542     pavgb     m2, [pix2q+strideq+1]
543     psadbw    m0, [pix1q]
544     psadbw    m2, [pix1q+strideq]
545     paddw     m0, m2
546
547 %rep 3
548     lea    pix1q, [pix1q+2*strideq]
549     lea    pix2q, [pix2q+2*strideq]
550     movu      m1, [pix2q]
551     movu      m2, [pix2q+strideq]
552     pavgb     m1, [pix2q+1]
553     pavgb     m2, [pix2q+strideq+1]
554     psadbw    m1, [pix1q]
555     psadbw    m2, [pix1q+strideq]
556     paddw     m0, m1
557     paddw     m0, m2
558 %endrep
559     movd     eax, m0
560     RET
561
562 %macro SAD16_X2 0
563 cglobal sad16_x2, 5, 5, 5, v, pix1, pix2, stride, h
564     pxor      m0, m0
565
566 align 16
567 .loop:
568     movu      m1, [pix2q]
569     movu      m2, [pix2q+strideq]
570 %if mmsize == 16
571     movu      m3, [pix2q+1]
572     movu      m4, [pix2q+strideq+1]
573     pavgb     m1, m3
574     pavgb     m2, m4
575 %else
576     pavgb     m1, [pix2q+1]
577     pavgb     m2, [pix2q+strideq+1]
578 %endif
579     psadbw    m1, [pix1q]
580     psadbw    m2, [pix1q+strideq]
581     paddw     m0, m1
582     paddw     m0, m2
583 %if mmsize == 8
584     movu      m1, [pix2q+8]
585     movu      m2, [pix2q+strideq+8]
586     pavgb     m1, [pix2q+9]
587     pavgb     m2, [pix2q+strideq+9]
588     psadbw    m1, [pix1q+8]
589     psadbw    m2, [pix1q+strideq+8]
590     paddw     m0, m1
591     paddw     m0, m2
592 %endif
593     lea    pix1q, [pix1q+2*strideq]
594     lea    pix2q, [pix2q+2*strideq]
595     sub       hd, 2
596     jg .loop
597 %if mmsize == 16
598     movhlps   m1, m0
599     paddw     m0, m1
600 %endif
601     movd     eax, m0
602     RET
603 %endmacro
604
605 INIT_MMX mmxext
606 SAD16_X2
607 INIT_XMM sse2
608 SAD16_X2
609
610 ;------------------------------------------------------------------------------------------
611 ;int ff_sad_y2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int stride, int h);
612 ;------------------------------------------------------------------------------------------
613 INIT_MMX mmxext
614 cglobal sad8_y2, 4, 4, 0, v, pix1, pix2, stride
615     movu      m1, [pix2q]
616     movu      m0, [pix2q+strideq]
617     movu      m3, [pix2q+2*strideq]
618     pavgb     m1, m0
619     pavgb     m0, m3
620     add    pix2q, strideq
621     psadbw    m1, [pix1q]
622     psadbw    m0, [pix1q+strideq]
623     paddw     m0, m1
624     mova      m1, m3
625
626 %rep 3
627     lea    pix1q, [pix1q+2*strideq]
628     lea    pix2q, [pix2q+2*strideq]
629     movu      m2, [pix2q]
630     movu      m3, [pix2q+strideq]
631     pavgb     m1, m2
632     pavgb     m2, m3
633     psadbw    m1, [pix1q]
634     psadbw    m2, [pix1q+strideq]
635     paddw     m0, m1
636     paddw     m0, m2
637     mova      m1, m3
638 %endrep
639     movd     eax, m0
640     RET
641
642 %macro SAD16_Y2 0
643 cglobal sad16_y2, 5, 5, 4, v, pix1, pix2, stride, h
644     movu      m1, [pix2q]
645 %if mmsize == 8
646     movu      m4, [pix2q+8]
647 %endif
648     pxor      m0, m0
649     add    pix2q, strideq
650
651 align 16
652 .loop:
653     movu      m2, [pix2q]
654     movu      m3, [pix2q+strideq]
655     pavgb     m1, m2
656     pavgb     m2, m3
657     psadbw    m1, [pix1q]
658     psadbw    m2, [pix1q+strideq]
659     paddw     m0, m1
660     paddw     m0, m2
661     mova      m1, m3
662 %if mmsize == 8
663     movu      m5, [pix2q+8]
664     movu      m6, [pix2q+strideq+8]
665     pavgb     m4, m5
666     pavgb     m5, m6
667     psadbw    m4, [pix1q+8]
668     psadbw    m5, [pix1q+strideq+8]
669     paddw     m0, m4
670     paddw     m0, m5
671     mova      m4, m6
672 %endif
673     lea    pix1q, [pix1q+2*strideq]
674     lea    pix2q, [pix2q+2*strideq]
675     sub       hd, 2
676     jg .loop
677 %if mmsize == 16
678     movhlps   m1, m0
679     paddw     m0, m1
680 %endif
681     movd     eax, m0
682     RET
683 %endmacro
684
685 INIT_MMX mmxext
686 SAD16_Y2
687 INIT_XMM sse2
688 SAD16_Y2
689
690 ;-------------------------------------------------------------------------------------------
691 ;int ff_sad_approx_xy2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int stride, int h);
692 ;-------------------------------------------------------------------------------------------
693 INIT_MMX mmxext
694 cglobal sad8_approx_xy2, 4, 4, 0, v, pix1, pix2, stride
695     pxor      m0, m0
696     mova      m4, [pb_1]
697     movu      m1, [pix2q]
698     movu      m0, [pix2q+strideq]
699     movu      m3, [pix2q+2*strideq]
700     pavgb     m1, [pix2q+1]
701     pavgb     m0, [pix2q+strideq+1]
702     pavgb     m3, [pix2q+2*strideq+1]
703     psubusb   m0, m4
704     pavgb     m1, m0
705     pavgb     m0, m3
706     add    pix2q, strideq
707     psadbw    m1, [pix1q]
708     psadbw    m0, [pix1q+strideq]
709     paddw     m0, m1
710     mova      m1, m3
711
712 %rep 3
713     lea    pix1q, [pix1q+2*strideq]
714     lea    pix2q, [pix2q+2*strideq]
715     movu      m2, [pix2q]
716     movu      m3, [pix2q+strideq]
717     pavgb     m2, [pix2q+1]
718     pavgb     m3, [pix2q+strideq+1]
719     psubusb   m2, m4
720     pavgb     m1, m2
721     pavgb     m2, m3
722     psadbw    m1, [pix1q]
723     psadbw    m2, [pix1q+strideq]
724     paddw     m0, m1
725     paddw     m0, m2
726     mova      m1, m3
727 %endrep
728     movd     eax, m0
729     RET
730
731 %macro SAD16_APPROX_XY2 0
732 cglobal sad16_approx_xy2, 5, 5, 7, v, pix1, pix2, stride, h
733     pxor      m0, m0
734     mova      m4, [pb_1]
735
736     movu      m1, [pix2q]
737 %if mmsize == 16
738     movu      m2, [pix2q+1]
739     pavgb     m1, m2
740 %else
741     movu      m5, [pix2q+8]
742     pavgb     m1, [pix2q+1]
743     pavgb     m5, [pix2q+8+1]
744 %endif
745     add    pix2q, strideq
746
747 align 16
748 .loop:
749     movu      m2, [pix2q]
750     movu      m3, [pix2q+strideq]
751 %if mmsize == 16
752     movu      m5, [pix2q+1]
753     movu      m6, [pix2q+strideq+1]
754     pavgb     m2, m5
755     pavgb     m3, m6
756 %else
757     pavgb     m2, [pix2q+1]
758     pavgb     m3, [pix2q+strideq+1]
759 %endif
760     psubusb   m2, m4
761     pavgb     m1, m2
762     pavgb     m2, m3
763     psadbw    m1, [pix1q]
764     psadbw    m2, [pix1q+strideq]
765     paddw     m0, m1
766     paddw     m0, m2
767     mova      m1, m3
768 %if mmsize == 8
769     movu      m6, [pix2q+8]
770     movu      m7, [pix2q+strideq+8]
771     pavgb     m6, [pix2q+8+1]
772     pavgb     m7, [pix2q+strideq+8+1]
773     psubusb   m6, m4
774     pavgb     m5, m6
775     pavgb     m6, m7
776     psadbw    m5, [pix1q+8]
777     psadbw    m6, [pix1q+strideq+8]
778     paddw     m0, m5
779     paddw     m0, m6
780     mova      m5, m7
781 %endif
782     lea    pix1q, [pix1q+2*strideq]
783     lea    pix2q, [pix2q+2*strideq]
784     sub       hd, 2
785     jg .loop
786 %if mmsize == 16
787     movhlps   m1, m0
788     paddw     m0, m1
789 %endif
790     movd     eax, m0
791     RET
792 %endmacro
793
794 INIT_MMX mmxext
795 SAD16_APPROX_XY2
796 INIT_XMM sse2
797 SAD16_APPROX_XY2