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