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