x86/me_cmp: combine sad functions into a single macro
[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 ;%1 = 8/16
477 %macro SAD 1
478 cglobal sad%1, 5, 5, 3, v, pix1, pix2, stride, h
479     movu      m2, [pix2q]
480     movu      m1, [pix2q+strideq]
481     psadbw    m2, [pix1q]
482     psadbw    m1, [pix1q+strideq]
483     paddw     m2, m1
484 %if %1 != mmsize
485     movu      m0, [pix2q+8]
486     movu      m1, [pix2q+strideq+8]
487     psadbw    m0, [pix1q+8]
488     psadbw    m1, [pix1q+strideq+8]
489     paddw     m2, m0
490     paddw     m2, m1
491 %endif
492     sub       hd, 2
493
494 align 16
495 .loop:
496     lea    pix1q, [pix1q+strideq*2]
497     lea    pix2q, [pix2q+strideq*2]
498     movu      m0, [pix2q]
499     movu      m1, [pix2q+strideq]
500     psadbw    m0, [pix1q]
501     psadbw    m1, [pix1q+strideq]
502     paddw     m2, m0
503     paddw     m2, m1
504 %if %1 != mmsize
505     movu      m0, [pix2q+8]
506     movu      m1, [pix2q+strideq+8]
507     psadbw    m0, [pix1q+8]
508     psadbw    m1, [pix1q+strideq+8]
509     paddw     m2, m0
510     paddw     m2, m1
511 %endif
512     sub       hd, 2
513     jg .loop
514 %if mmsize == 16
515     movhlps   m0, m2
516     paddw     m2, m0
517 %endif
518     movd     eax, m2
519     RET
520 %endmacro
521
522 INIT_MMX mmxext
523 SAD 8
524 SAD 16
525 INIT_XMM sse2
526 SAD 16
527
528 ;------------------------------------------------------------------------------------------
529 ;int ff_sad_x2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int stride, int h);
530 ;------------------------------------------------------------------------------------------
531 ;%1 = 8/16
532 %macro SAD_X2 1
533 cglobal sad%1_x2, 5, 5, 5, v, pix1, pix2, stride, h
534     movu      m0, [pix2q]
535     movu      m2, [pix2q+strideq]
536 %if mmsize == 16
537     movu      m3, [pix2q+1]
538     movu      m4, [pix2q+strideq+1]
539     pavgb     m0, m3
540     pavgb     m2, m4
541 %else
542     pavgb     m0, [pix2q+1]
543     pavgb     m2, [pix2q+strideq+1]
544 %endif
545     psadbw    m0, [pix1q]
546     psadbw    m2, [pix1q+strideq]
547     paddw     m0, m2
548 %if %1 != mmsize
549     movu      m1, [pix2q+8]
550     movu      m2, [pix2q+strideq+8]
551     pavgb     m1, [pix2q+9]
552     pavgb     m2, [pix2q+strideq+9]
553     psadbw    m1, [pix1q+8]
554     psadbw    m2, [pix1q+strideq+8]
555     paddw     m0, m1
556     paddw     m0, m2
557 %endif
558     sub       hd, 2
559
560 align 16
561 .loop:
562     lea    pix1q, [pix1q+2*strideq]
563     lea    pix2q, [pix2q+2*strideq]
564     movu      m1, [pix2q]
565     movu      m2, [pix2q+strideq]
566 %if mmsize == 16
567     movu      m3, [pix2q+1]
568     movu      m4, [pix2q+strideq+1]
569     pavgb     m1, m3
570     pavgb     m2, m4
571 %else
572     pavgb     m1, [pix2q+1]
573     pavgb     m2, [pix2q+strideq+1]
574 %endif
575     psadbw    m1, [pix1q]
576     psadbw    m2, [pix1q+strideq]
577     paddw     m0, m1
578     paddw     m0, m2
579 %if %1 != mmsize
580     movu      m1, [pix2q+8]
581     movu      m2, [pix2q+strideq+8]
582     pavgb     m1, [pix2q+9]
583     pavgb     m2, [pix2q+strideq+9]
584     psadbw    m1, [pix1q+8]
585     psadbw    m2, [pix1q+strideq+8]
586     paddw     m0, m1
587     paddw     m0, m2
588 %endif
589     sub       hd, 2
590     jg .loop
591 %if mmsize == 16
592     movhlps   m1, m0
593     paddw     m0, m1
594 %endif
595     movd     eax, m0
596     RET
597 %endmacro
598
599 INIT_MMX mmxext
600 SAD_X2 8
601 SAD_X2 16
602 INIT_XMM sse2
603 SAD_X2 16
604
605 ;------------------------------------------------------------------------------------------
606 ;int ff_sad_y2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int stride, int h);
607 ;------------------------------------------------------------------------------------------
608 ;%1 = 8/16
609 %macro SAD_Y2 1
610 cglobal sad%1_y2, 5, 5, 4, v, pix1, pix2, stride, h
611     movu      m1, [pix2q]
612     movu      m0, [pix2q+strideq]
613     movu      m3, [pix2q+2*strideq]
614     pavgb     m1, m0
615     pavgb     m0, m3
616     psadbw    m1, [pix1q]
617     psadbw    m0, [pix1q+strideq]
618     paddw     m0, m1
619     mova      m1, m3
620 %if %1 != mmsize
621     movu      m4, [pix2q+8]
622     movu      m5, [pix2q+strideq+8]
623     movu      m6, [pix2q+2*strideq+8]
624     pavgb     m4, m5
625     pavgb     m5, m6
626     psadbw    m4, [pix1q+8]
627     psadbw    m5, [pix1q+strideq+8]
628     paddw     m0, m4
629     paddw     m0, m5
630     mova      m4, m6
631 %endif
632     add    pix2q, strideq
633     sub       hd, 2
634
635 align 16
636 .loop:
637     lea    pix1q, [pix1q+2*strideq]
638     lea    pix2q, [pix2q+2*strideq]
639     movu      m2, [pix2q]
640     movu      m3, [pix2q+strideq]
641     pavgb     m1, m2
642     pavgb     m2, m3
643     psadbw    m1, [pix1q]
644     psadbw    m2, [pix1q+strideq]
645     paddw     m0, m1
646     paddw     m0, m2
647     mova      m1, m3
648 %if %1 != mmsize
649     movu      m5, [pix2q+8]
650     movu      m6, [pix2q+strideq+8]
651     pavgb     m4, m5
652     pavgb     m5, m6
653     psadbw    m4, [pix1q+8]
654     psadbw    m5, [pix1q+strideq+8]
655     paddw     m0, m4
656     paddw     m0, m5
657     mova      m4, m6
658 %endif
659     sub       hd, 2
660     jg .loop
661 %if mmsize == 16
662     movhlps   m1, m0
663     paddw     m0, m1
664 %endif
665     movd     eax, m0
666     RET
667 %endmacro
668
669 INIT_MMX mmxext
670 SAD_Y2 8
671 SAD_Y2 16
672 INIT_XMM sse2
673 SAD_Y2 16
674
675 ;-------------------------------------------------------------------------------------------
676 ;int ff_sad_approx_xy2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int stride, int h);
677 ;-------------------------------------------------------------------------------------------
678 ;%1 = 8/16
679 %macro SAD_APPROX_XY2 1
680 cglobal sad%1_approx_xy2, 5, 5, 7, v, pix1, pix2, stride, h
681     mova      m4, [pb_1]
682     movu      m1, [pix2q]
683     movu      m0, [pix2q+strideq]
684     movu      m3, [pix2q+2*strideq]
685 %if mmsize == 16
686     movu      m5, [pix2q+1]
687     movu      m6, [pix2q+strideq+1]
688     movu      m2, [pix2q+2*strideq+1]
689     pavgb     m1, m5
690     pavgb     m0, m6
691     pavgb     m3, m2
692 %else
693     pavgb     m1, [pix2q+1]
694     pavgb     m0, [pix2q+strideq+1]
695     pavgb     m3, [pix2q+2*strideq+1]
696 %endif
697     psubusb   m0, m4
698     pavgb     m1, m0
699     pavgb     m0, m3
700     psadbw    m1, [pix1q]
701     psadbw    m0, [pix1q+strideq]
702     paddw     m0, m1
703     mova      m1, m3
704 %if %1 != mmsize
705     movu      m5, [pix2q+8]
706     movu      m6, [pix2q+strideq+8]
707     movu      m7, [pix2q+2*strideq+8]
708     pavgb     m5, [pix2q+1+8]
709     pavgb     m6, [pix2q+strideq+1+8]
710     pavgb     m7, [pix2q+2*strideq+1+8]
711     psubusb   m6, m4
712     pavgb     m5, m6
713     pavgb     m6, m7
714     psadbw    m5, [pix1q+8]
715     psadbw    m6, [pix1q+strideq+8]
716     paddw     m0, m5
717     paddw     m0, m6
718     mova      m5, m7
719 %endif
720     add    pix2q, strideq
721     sub       hd, 2
722
723 align 16
724 .loop:
725     lea    pix1q, [pix1q+2*strideq]
726     lea    pix2q, [pix2q+2*strideq]
727     movu      m2, [pix2q]
728     movu      m3, [pix2q+strideq]
729 %if mmsize == 16
730     movu      m5, [pix2q+1]
731     movu      m6, [pix2q+strideq+1]
732     pavgb     m2, m5
733     pavgb     m3, m6
734 %else
735     pavgb     m2, [pix2q+1]
736     pavgb     m3, [pix2q+strideq+1]
737 %endif
738     psubusb   m2, m4
739     pavgb     m1, m2
740     pavgb     m2, m3
741     psadbw    m1, [pix1q]
742     psadbw    m2, [pix1q+strideq]
743     paddw     m0, m1
744     paddw     m0, m2
745     mova      m1, m3
746 %if %1 != mmsize
747     movu      m6, [pix2q+8]
748     movu      m7, [pix2q+strideq+8]
749     pavgb     m6, [pix2q+8+1]
750     pavgb     m7, [pix2q+strideq+8+1]
751     psubusb   m6, m4
752     pavgb     m5, m6
753     pavgb     m6, m7
754     psadbw    m5, [pix1q+8]
755     psadbw    m6, [pix1q+strideq+8]
756     paddw     m0, m5
757     paddw     m0, m6
758     mova      m5, m7
759 %endif
760     sub       hd, 2
761     jg .loop
762 %if mmsize == 16
763     movhlps   m1, m0
764     paddw     m0, m1
765 %endif
766     movd     eax, m0
767     RET
768 %endmacro
769
770 INIT_MMX mmxext
771 SAD_APPROX_XY2 8
772 SAD_APPROX_XY2 16
773 INIT_XMM sse2
774 SAD_APPROX_XY2 16