x86: h264_qpel_10bit: port to cpuflags
[ffmpeg.git] / libavcodec / x86 / h264_qpel_10bit.asm
1 ;*****************************************************************************
2 ;* MMX/SSE2/AVX-optimized 10-bit H.264 qpel code
3 ;*****************************************************************************
4 ;* Copyright (C) 2011 x264 project
5 ;*
6 ;* Authors: Daniel Kang <daniel.d.kang@gmail.com>
7 ;*
8 ;* This file is part of Libav.
9 ;*
10 ;* Libav is free software; you can redistribute it and/or
11 ;* modify it under the terms of the GNU Lesser General Public
12 ;* License as published by the Free Software Foundation; either
13 ;* version 2.1 of the License, or (at your option) any later version.
14 ;*
15 ;* Libav is distributed in the hope that it will be useful,
16 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ;* Lesser General Public License for more details.
19 ;*
20 ;* You should have received a copy of the GNU Lesser General Public
21 ;* License along with Libav; if not, write to the Free Software
22 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 ;******************************************************************************
24
25 %include "libavutil/x86/x86util.asm"
26
27 SECTION_RODATA 32
28
29 cextern pw_16
30 cextern pw_1
31 cextern pb_0
32
33 pw_pixel_max: times 8 dw ((1 << 10)-1)
34
35 pad10: times 8 dw 10*1023
36 pad20: times 8 dw 20*1023
37 pad30: times 8 dw 30*1023
38 depad: times 4 dd 32*20*1023 + 512
39 depad2: times 8 dw 20*1023 + 16*1022 + 16
40 unpad: times 8 dw 16*1022/32 ; needs to be mod 16
41
42 tap1: times 4 dw  1, -5
43 tap2: times 4 dw 20, 20
44 tap3: times 4 dw -5,  1
45 pd_0f: times 4 dd 0xffff
46
47 SECTION .text
48
49
50 %macro AVG_MOV 2
51     pavgw %2, %1
52     mova  %1, %2
53 %endmacro
54
55 %macro ADDW 3
56 %if mmsize == 8
57     paddw %1, %2
58 %else
59     movu  %3, %2
60     paddw %1, %3
61 %endif
62 %endmacro
63
64 %macro FILT_H 4
65     paddw  %1, %4
66     psubw  %1, %2  ; a-b
67     psraw  %1, 2   ; (a-b)/4
68     psubw  %1, %2  ; (a-b)/4-b
69     paddw  %1, %3  ; (a-b)/4-b+c
70     psraw  %1, 2   ; ((a-b)/4-b+c)/4
71     paddw  %1, %3  ; ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
72 %endmacro
73
74 %macro PRELOAD_V 0
75     lea      r3, [r2*3]
76     sub      r1, r3
77     movu     m0, [r1+r2]
78     movu     m1, [r1+r2*2]
79     add      r1, r3
80     movu     m2, [r1]
81     movu     m3, [r1+r2]
82     movu     m4, [r1+r2*2]
83     add      r1, r3
84 %endmacro
85
86 %macro FILT_V 8
87     movu     %6, [r1]
88     paddw    %1, %6
89     mova     %7, %2
90     paddw    %7, %5
91     mova     %8, %3
92     paddw    %8, %4
93     FILT_H   %1, %7, %8, [pw_16]
94     psraw    %1, 1
95     CLIPW    %1, [pb_0], [pw_pixel_max]
96 %endmacro
97
98 %macro MC 1
99 %define OP_MOV mova
100 INIT_MMX mmxext
101 %1 put, 4
102 INIT_XMM sse2
103 %1 put, 8
104
105 %define OP_MOV AVG_MOV
106 INIT_MMX mmxext
107 %1 avg, 4
108 INIT_XMM sse2
109 %1 avg, 8
110 %endmacro
111
112 %macro MCAxA_OP 7
113 %if ARCH_X86_32
114 cglobal %1_h264_qpel%4_%2_10, %5,%6,%7
115     call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX
116     mov  r0, r0m
117     mov  r1, r1m
118     add  r0, %3*2
119     add  r1, %3*2
120     call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX
121     mov  r0, r0m
122     mov  r1, r1m
123     lea  r0, [r0+r2*%3]
124     lea  r1, [r1+r2*%3]
125     call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX
126     mov  r0, r0m
127     mov  r1, r1m
128     lea  r0, [r0+r2*%3+%3*2]
129     lea  r1, [r1+r2*%3+%3*2]
130     call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX
131     RET
132 %else ; ARCH_X86_64
133 cglobal %1_h264_qpel%4_%2_10, %5,%6 + 2,%7
134     mov r%6, r0
135 %assign p1 %6+1
136     mov r %+ p1, r1
137     call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX
138     lea  r0, [r%6+%3*2]
139     lea  r1, [r %+ p1+%3*2]
140     call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX
141     lea  r0, [r%6+r2*%3]
142     lea  r1, [r %+ p1+r2*%3]
143     call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX
144     lea  r0, [r%6+r2*%3+%3*2]
145     lea  r1, [r %+ p1+r2*%3+%3*2]
146 %if UNIX64 == 0 ; fall through to function
147     call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX
148     RET
149 %endif
150 %endif
151 %endmacro
152
153 ;cpu, put/avg, mc, 4/8, ...
154 %macro cglobal_mc 6
155 %assign i %3*2
156 %if ARCH_X86_32 || cpuflag(sse2)
157 MCAxA_OP %1, %2, %3, i, %4,%5,%6
158 %endif
159
160 cglobal %1_h264_qpel%3_%2_10, %4,%5,%6
161 %if UNIX64 == 0 ; no prologue or epilogue for UNIX64
162     call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX
163     RET
164 %endif
165
166 stub_%1_h264_qpel%3_%2_10 %+ SUFFIX:
167 %endmacro
168
169 ;-----------------------------------------------------------------------------
170 ; void h264_qpel_mc00(uint8_t *dst, uint8_t *src, int stride)
171 ;-----------------------------------------------------------------------------
172 %macro COPY4 0
173     movu          m0, [r1     ]
174     OP_MOV [r0     ], m0
175     movu          m0, [r1+r2  ]
176     OP_MOV [r0+r2  ], m0
177     movu          m0, [r1+r2*2]
178     OP_MOV [r0+r2*2], m0
179     movu          m0, [r1+r3  ]
180     OP_MOV [r0+r3  ], m0
181 %endmacro
182
183 %macro MC00 1
184 INIT_MMX mmxext
185 cglobal_mc %1, mc00, 4, 3,4,0
186     lea           r3, [r2*3]
187     COPY4
188     ret
189
190 INIT_XMM sse2
191 cglobal %1_h264_qpel8_mc00_10, 3,4
192     lea  r3, [r2*3]
193     COPY4
194     lea  r0, [r0+r2*4]
195     lea  r1, [r1+r2*4]
196     COPY4
197     RET
198
199 cglobal %1_h264_qpel16_mc00_10, 3,4
200     mov r3d, 8
201 .loop:
202     movu           m0, [r1      ]
203     movu           m1, [r1   +16]
204     OP_MOV [r0      ], m0
205     OP_MOV [r0   +16], m1
206     movu           m0, [r1+r2   ]
207     movu           m1, [r1+r2+16]
208     OP_MOV [r0+r2   ], m0
209     OP_MOV [r0+r2+16], m1
210     lea            r0, [r0+r2*2]
211     lea            r1, [r1+r2*2]
212     dec r3d
213     jg .loop
214     REP_RET
215 %endmacro
216
217 %define OP_MOV mova
218 MC00 put
219
220 %define OP_MOV AVG_MOV
221 MC00 avg
222
223 ;-----------------------------------------------------------------------------
224 ; void h264_qpel_mc20(uint8_t *dst, uint8_t *src, int stride)
225 ;-----------------------------------------------------------------------------
226 %macro MC_CACHE 1
227 %define OP_MOV mova
228 %define PALIGNR PALIGNR_MMX
229 INIT_MMX mmxext
230 %1 put, 4
231 INIT_XMM sse2, cache64
232 %1 put, 8
233 INIT_XMM ssse3, cache64
234 %define PALIGNR PALIGNR_SSSE3
235 %1 put, 8
236 INIT_XMM sse2
237 %1 put, 8, 0
238
239 %define OP_MOV AVG_MOV
240 %define PALIGNR PALIGNR_MMX
241 INIT_MMX mmxext
242 %1 avg, 4
243 INIT_XMM sse2, cache64
244 %1 avg, 8
245 INIT_XMM ssse3, cache64
246 %define PALIGNR PALIGNR_SSSE3
247 %1 avg, 8
248 INIT_XMM sse2
249 %1 avg, 8, 0
250 %endmacro
251
252 %macro MC20 2-3
253 cglobal_mc %1, mc20, %2, 3,4,9
254     mov     r3d, %2
255     mova     m1, [pw_pixel_max]
256 %if num_mmregs > 8
257     mova     m8, [pw_16]
258     %define p16 m8
259 %else
260     %define p16 [pw_16]
261 %endif
262 .nextrow:
263 %if %0 == 4
264     movu     m2, [r1-4]
265     movu     m3, [r1-2]
266     movu     m4, [r1+0]
267     ADDW     m2, [r1+6], m5
268     ADDW     m3, [r1+4], m5
269     ADDW     m4, [r1+2], m5
270 %else ; movu is slow on these processors
271 %if mmsize==16
272     movu     m2, [r1-4]
273     movu     m0, [r1+6]
274     mova     m6, m0
275     psrldq   m0, 6
276
277     paddw    m6, m2
278     PALIGNR  m3, m0, m2, 2, m5
279     PALIGNR  m7, m0, m2, 8, m5
280     paddw    m3, m7
281     PALIGNR  m4, m0, m2, 4, m5
282     PALIGNR  m7, m0, m2, 6, m5
283     paddw    m4, m7
284     SWAP      2, 6
285 %else
286     movu     m2, [r1-4]
287     movu     m6, [r1+4]
288     PALIGNR  m3, m6, m2, 2, m5
289     paddw    m3, m6
290     PALIGNR  m4, m6, m2, 4, m5
291     PALIGNR  m7, m6, m2, 6, m5
292     paddw    m4, m7
293     paddw    m2, [r1+6]
294 %endif
295 %endif
296
297     FILT_H   m2, m3, m4, p16
298     psraw    m2, 1
299     pxor     m0, m0
300     CLIPW    m2, m0, m1
301     OP_MOV [r0], m2
302     add      r0, r2
303     add      r1, r2
304     dec     r3d
305     jg .nextrow
306     rep ret
307 %endmacro
308
309 MC_CACHE MC20
310
311 ;-----------------------------------------------------------------------------
312 ; void h264_qpel_mc30(uint8_t *dst, uint8_t *src, int stride)
313 ;-----------------------------------------------------------------------------
314 %macro MC30 2-3
315 cglobal_mc %1, mc30, %2, 3,5,9
316     lea r4, [r1+2]
317     jmp stub_%1_h264_qpel%2_mc10_10 %+ SUFFIX %+ .body
318 %endmacro
319
320 MC_CACHE MC30
321
322 ;-----------------------------------------------------------------------------
323 ; void h264_qpel_mc10(uint8_t *dst, uint8_t *src, int stride)
324 ;-----------------------------------------------------------------------------
325 %macro MC10 2-3
326 cglobal_mc %1, mc10, %2, 3,5,9
327     mov      r4, r1
328 .body:
329     mov     r3d, %2
330     mova     m1, [pw_pixel_max]
331 %if num_mmregs > 8
332     mova     m8, [pw_16]
333     %define p16 m8
334 %else
335     %define p16 [pw_16]
336 %endif
337 .nextrow:
338 %if %0 == 4
339     movu     m2, [r1-4]
340     movu     m3, [r1-2]
341     movu     m4, [r1+0]
342     ADDW     m2, [r1+6], m5
343     ADDW     m3, [r1+4], m5
344     ADDW     m4, [r1+2], m5
345 %else ; movu is slow on these processors
346 %if mmsize==16
347     movu     m2, [r1-4]
348     movu     m0, [r1+6]
349     mova     m6, m0
350     psrldq   m0, 6
351
352     paddw    m6, m2
353     PALIGNR  m3, m0, m2, 2, m5
354     PALIGNR  m7, m0, m2, 8, m5
355     paddw    m3, m7
356     PALIGNR  m4, m0, m2, 4, m5
357     PALIGNR  m7, m0, m2, 6, m5
358     paddw    m4, m7
359     SWAP      2, 6
360 %else
361     movu     m2, [r1-4]
362     movu     m6, [r1+4]
363     PALIGNR  m3, m6, m2, 2, m5
364     paddw    m3, m6
365     PALIGNR  m4, m6, m2, 4, m5
366     PALIGNR  m7, m6, m2, 6, m5
367     paddw    m4, m7
368     paddw    m2, [r1+6]
369 %endif
370 %endif
371
372     FILT_H   m2, m3, m4, p16
373     psraw    m2, 1
374     pxor     m0, m0
375     CLIPW    m2, m0, m1
376     movu     m3, [r4]
377     pavgw    m2, m3
378     OP_MOV [r0], m2
379     add      r0, r2
380     add      r1, r2
381     add      r4, r2
382     dec     r3d
383     jg .nextrow
384     rep ret
385 %endmacro
386
387 MC_CACHE MC10
388
389 ;-----------------------------------------------------------------------------
390 ; void h264_qpel_mc02(uint8_t *dst, uint8_t *src, int stride)
391 ;-----------------------------------------------------------------------------
392 %macro V_FILT 10
393 v_filt%9_%10_10
394     add    r4, r2
395 .no_addr4:
396     FILT_V m0, m1, m2, m3, m4, m5, m6, m7
397     add    r1, r2
398     add    r0, r2
399     ret
400 %endmacro
401
402 INIT_MMX mmxext
403 RESET_MM_PERMUTATION
404 %assign i 0
405 %rep 4
406 V_FILT m0, m1, m2, m3, m4, m5, m6, m7, 4, i
407 SWAP 0,1,2,3,4,5
408 %assign i i+1
409 %endrep
410
411 INIT_XMM sse2
412 RESET_MM_PERMUTATION
413 %assign i 0
414 %rep 6
415 V_FILT m0, m1, m2, m3, m4, m5, m6, m7, 8, i
416 SWAP 0,1,2,3,4,5
417 %assign i i+1
418 %endrep
419
420 %macro MC02 2
421 cglobal_mc %1, mc02, %2, 3,4,8
422     PRELOAD_V
423
424     sub      r0, r2
425 %assign j 0
426 %rep %2
427     %assign i (j % 6)
428     call v_filt%2_ %+ i %+ _10.no_addr4
429     OP_MOV [r0], m0
430     SWAP 0,1,2,3,4,5
431     %assign j j+1
432 %endrep
433     ret
434 %endmacro
435
436 MC MC02
437
438 ;-----------------------------------------------------------------------------
439 ; void h264_qpel_mc01(uint8_t *dst, uint8_t *src, int stride)
440 ;-----------------------------------------------------------------------------
441 %macro MC01 2
442 cglobal_mc %1, mc01, %2, 3,5,8
443     mov      r4, r1
444 .body:
445     PRELOAD_V
446
447     sub      r4, r2
448     sub      r0, r2
449 %assign j 0
450 %rep %2
451     %assign i (j % 6)
452     call v_filt%2_ %+ i %+ _10
453     movu     m7, [r4]
454     pavgw    m0, m7
455     OP_MOV [r0], m0
456     SWAP 0,1,2,3,4,5
457     %assign j j+1
458 %endrep
459     ret
460 %endmacro
461
462 MC MC01
463
464 ;-----------------------------------------------------------------------------
465 ; void h264_qpel_mc03(uint8_t *dst, uint8_t *src, int stride)
466 ;-----------------------------------------------------------------------------
467 %macro MC03 2
468 cglobal_mc %1, mc03, %2, 3,5,8
469     lea r4, [r1+r2]
470     jmp stub_%1_h264_qpel%2_mc01_10 %+ SUFFIX %+ .body
471 %endmacro
472
473 MC MC03
474
475 ;-----------------------------------------------------------------------------
476 ; void h264_qpel_mc11(uint8_t *dst, uint8_t *src, int stride)
477 ;-----------------------------------------------------------------------------
478 %macro H_FILT_AVG 2-3
479 h_filt%1_%2_10:
480 ;FILT_H with fewer registers and averaged with the FILT_V result
481 ;m6,m7 are tmp registers, m0 is the FILT_V result, the rest are to be used next in the next iteration
482 ;unfortunately I need three registers, so m5 will have to be re-read from memory
483     movu     m5, [r4-4]
484     ADDW     m5, [r4+6], m7
485     movu     m6, [r4-2]
486     ADDW     m6, [r4+4], m7
487     paddw    m5, [pw_16]
488     psubw    m5, m6  ; a-b
489     psraw    m5, 2   ; (a-b)/4
490     psubw    m5, m6  ; (a-b)/4-b
491     movu     m6, [r4+0]
492     ADDW     m6, [r4+2], m7
493     paddw    m5, m6  ; (a-b)/4-b+c
494     psraw    m5, 2   ; ((a-b)/4-b+c)/4
495     paddw    m5, m6  ; ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
496     psraw    m5, 1
497     CLIPW    m5, [pb_0], [pw_pixel_max]
498 ;avg FILT_V, FILT_H
499     pavgw    m0, m5
500 %if %0!=4
501     movu     m5, [r1+r5]
502 %endif
503     ret
504 %endmacro
505
506 INIT_MMX mmxext
507 RESET_MM_PERMUTATION
508 %assign i 0
509 %rep 3
510 H_FILT_AVG 4, i
511 SWAP 0,1,2,3,4,5
512 %assign i i+1
513 %endrep
514 H_FILT_AVG 4, i, 0
515
516 INIT_XMM sse2
517 RESET_MM_PERMUTATION
518 %assign i 0
519 %rep 6
520 %if i==1
521 H_FILT_AVG 8, i, 0
522 %else
523 H_FILT_AVG 8, i
524 %endif
525 SWAP 0,1,2,3,4,5
526 %assign i i+1
527 %endrep
528
529 %macro MC11 2
530 ; this REALLY needs x86_64
531 cglobal_mc %1, mc11, %2, 3,6,8
532     mov      r4, r1
533 .body:
534     PRELOAD_V
535
536     sub      r0, r2
537     sub      r4, r2
538     mov      r5, r2
539     neg      r5
540 %assign j 0
541 %rep %2
542     %assign i (j % 6)
543     call v_filt%2_ %+ i %+ _10
544     call h_filt%2_ %+ i %+ _10
545 %if %2==8 && i==1
546     movu     m5, [r1+r5]
547 %endif
548     OP_MOV [r0], m0
549     SWAP 0,1,2,3,4,5
550     %assign j j+1
551 %endrep
552     ret
553 %endmacro
554
555 MC MC11
556
557 ;-----------------------------------------------------------------------------
558 ; void h264_qpel_mc31(uint8_t *dst, uint8_t *src, int stride)
559 ;-----------------------------------------------------------------------------
560 %macro MC31 2
561 cglobal_mc %1, mc31, %2, 3,6,8
562     mov r4, r1
563     add r1, 2
564     jmp stub_%1_h264_qpel%2_mc11_10 %+ SUFFIX %+ .body
565 %endmacro
566
567 MC MC31
568
569 ;-----------------------------------------------------------------------------
570 ; void h264_qpel_mc13(uint8_t *dst, uint8_t *src, int stride)
571 ;-----------------------------------------------------------------------------
572 %macro MC13 2
573 cglobal_mc %1, mc13, %2, 3,7,12
574     lea r4, [r1+r2]
575     jmp stub_%1_h264_qpel%2_mc11_10 %+ SUFFIX %+ .body
576 %endmacro
577
578 MC MC13
579
580 ;-----------------------------------------------------------------------------
581 ; void h264_qpel_mc33(uint8_t *dst, uint8_t *src, int stride)
582 ;-----------------------------------------------------------------------------
583 %macro MC33 2
584 cglobal_mc %1, mc33, %2, 3,6,8
585     lea r4, [r1+r2]
586     add r1, 2
587     jmp stub_%1_h264_qpel%2_mc11_10 %+ SUFFIX %+ .body
588 %endmacro
589
590 MC MC33
591
592 ;-----------------------------------------------------------------------------
593 ; void h264_qpel_mc22(uint8_t *dst, uint8_t *src, int stride)
594 ;-----------------------------------------------------------------------------
595 %macro FILT_H2 3
596     psubw  %1, %2  ; a-b
597     psubw  %2, %3  ; b-c
598     psllw  %2, 2
599     psubw  %1, %2  ; a-5*b+4*c
600     psllw  %3, 4
601     paddw  %1, %3  ; a-5*b+20*c
602 %endmacro
603
604 %macro FILT_VNRD 8
605     movu     %6, [r1]
606     paddw    %1, %6
607     mova     %7, %2
608     paddw    %7, %5
609     mova     %8, %3
610     paddw    %8, %4
611     FILT_H2  %1, %7, %8
612 %endmacro
613
614 %macro HV 1
615 %if mmsize==16
616 %define PAD 12
617 %define COUNT 2
618 %else
619 %define PAD 4
620 %define COUNT 3
621 %endif
622 put_hv%1_10:
623     neg      r2           ; This actually saves instructions
624     lea      r1, [r1+r2*2-mmsize+PAD]
625     lea      r4, [rsp+PAD+gprsize]
626     mov     r3d, COUNT
627 .v_loop:
628     movu     m0, [r1]
629     sub      r1, r2
630     movu     m1, [r1]
631     sub      r1, r2
632     movu     m2, [r1]
633     sub      r1, r2
634     movu     m3, [r1]
635     sub      r1, r2
636     movu     m4, [r1]
637     sub      r1, r2
638 %assign i 0
639 %rep %1-1
640     FILT_VNRD m0, m1, m2, m3, m4, m5, m6, m7
641     psubw    m0, [pad20]
642     movu     [r4+i*mmsize*3], m0
643     sub      r1, r2
644     SWAP 0,1,2,3,4,5
645 %assign i i+1
646 %endrep
647     FILT_VNRD m0, m1, m2, m3, m4, m5, m6, m7
648     psubw    m0, [pad20]
649     movu     [r4+i*mmsize*3], m0
650     add      r4, mmsize
651     lea      r1, [r1+r2*8+mmsize]
652 %if %1==8
653     lea      r1, [r1+r2*4]
654 %endif
655     dec      r3d
656     jg .v_loop
657     neg      r2
658     ret
659 %endmacro
660
661 INIT_MMX mmxext
662 HV 4
663 INIT_XMM sse2
664 HV 8
665
666 %macro H_LOOP 1
667 %if num_mmregs > 8
668     %define s1 m8
669     %define s2 m9
670     %define s3 m10
671     %define d1 m11
672 %else
673     %define s1 [tap1]
674     %define s2 [tap2]
675     %define s3 [tap3]
676     %define d1 [depad]
677 %endif
678 h%1_loop_op:
679     movu       m1, [r1+mmsize-4]
680     movu       m2, [r1+mmsize-2]
681     mova       m3, [r1+mmsize+0]
682     movu       m4, [r1+mmsize+2]
683     movu       m5, [r1+mmsize+4]
684     movu       m6, [r1+mmsize+6]
685 %if num_mmregs > 8
686     pmaddwd    m1, s1
687     pmaddwd    m2, s1
688     pmaddwd    m3, s2
689     pmaddwd    m4, s2
690     pmaddwd    m5, s3
691     pmaddwd    m6, s3
692     paddd      m1, d1
693     paddd      m2, d1
694 %else
695     mova       m0, s1
696     pmaddwd    m1, m0
697     pmaddwd    m2, m0
698     mova       m0, s2
699     pmaddwd    m3, m0
700     pmaddwd    m4, m0
701     mova       m0, s3
702     pmaddwd    m5, m0
703     pmaddwd    m6, m0
704     mova       m0, d1
705     paddd      m1, m0
706     paddd      m2, m0
707 %endif
708     paddd      m3, m5
709     paddd      m4, m6
710     paddd      m1, m3
711     paddd      m2, m4
712     psrad      m1, 10
713     psrad      m2, 10
714     pslld      m2, 16
715     pand       m1, [pd_0f]
716     por        m1, m2
717 %if num_mmregs <= 8
718     pxor       m0, m0
719 %endif
720     CLIPW      m1, m0, m7
721     add        r1, mmsize*3
722     ret
723 %endmacro
724
725 INIT_MMX mmxext
726 H_LOOP 4
727 INIT_XMM sse2
728 H_LOOP 8
729
730 %macro MC22 2
731 cglobal_mc %1, mc22, %2, 3,7,12
732 %define PAD mmsize*8*4*2      ; SIZE*16*4*sizeof(pixel)
733     mov      r6, rsp          ; backup stack pointer
734     and     rsp, ~(mmsize-1)  ; align stack
735     sub     rsp, PAD
736
737     call put_hv%2_10
738
739     mov       r3d, %2
740     mova       m7, [pw_pixel_max]
741 %if num_mmregs > 8
742     pxor       m0, m0
743     mova       m8, [tap1]
744     mova       m9, [tap2]
745     mova      m10, [tap3]
746     mova      m11, [depad]
747 %endif
748     mov        r1, rsp
749 .h_loop:
750     call h%2_loop_op
751
752     OP_MOV   [r0], m1
753     add        r0, r2
754     dec       r3d
755     jg .h_loop
756
757     mov     rsp, r6          ; restore stack pointer
758     ret
759 %endmacro
760
761 MC MC22
762
763 ;-----------------------------------------------------------------------------
764 ; void h264_qpel_mc12(uint8_t *dst, uint8_t *src, int stride)
765 ;-----------------------------------------------------------------------------
766 %macro MC12 2
767 cglobal_mc %1, mc12, %2, 3,7,12
768 %define PAD mmsize*8*4*2        ; SIZE*16*4*sizeof(pixel)
769     mov        r6, rsp          ; backup stack pointer
770     and       rsp, ~(mmsize-1)  ; align stack
771     sub       rsp, PAD
772
773     call put_hv%2_10
774
775     xor       r4d, r4d
776 .body:
777     mov       r3d, %2
778     pxor       m0, m0
779     mova       m7, [pw_pixel_max]
780 %if num_mmregs > 8
781     mova       m8, [tap1]
782     mova       m9, [tap2]
783     mova      m10, [tap3]
784     mova      m11, [depad]
785 %endif
786     mov        r1, rsp
787 .h_loop:
788     call h%2_loop_op
789
790     movu       m3, [r1+r4-2*mmsize] ; movu needed for mc32, etc
791     paddw      m3, [depad2]
792     psrlw      m3, 5
793     psubw      m3, [unpad]
794     CLIPW      m3, m0, m7
795     pavgw      m1, m3
796
797     OP_MOV   [r0], m1
798     add        r0, r2
799     dec       r3d
800     jg .h_loop
801
802     mov     rsp, r6          ; restore stack pointer
803     ret
804 %endmacro
805
806 MC MC12
807
808 ;-----------------------------------------------------------------------------
809 ; void h264_qpel_mc32(uint8_t *dst, uint8_t *src, int stride)
810 ;-----------------------------------------------------------------------------
811 %macro MC32 2
812 cglobal_mc %1, mc32, %2, 3,7,12
813 %define PAD mmsize*8*3*2  ; SIZE*16*4*sizeof(pixel)
814     mov  r6, rsp          ; backup stack pointer
815     and rsp, ~(mmsize-1)  ; align stack
816     sub rsp, PAD
817
818     call put_hv%2_10
819
820     mov r4d, 2            ; sizeof(pixel)
821     jmp stub_%1_h264_qpel%2_mc12_10 %+ SUFFIX %+ .body
822 %endmacro
823
824 MC MC32
825
826 ;-----------------------------------------------------------------------------
827 ; void h264_qpel_mc21(uint8_t *dst, uint8_t *src, int stride)
828 ;-----------------------------------------------------------------------------
829 %macro H_NRD 1
830 put_h%1_10:
831     add       rsp, gprsize
832     mov       r3d, %1
833     xor       r4d, r4d
834     mova       m6, [pad20]
835 .nextrow:
836     movu       m2, [r5-4]
837     movu       m3, [r5-2]
838     movu       m4, [r5+0]
839     ADDW       m2, [r5+6], m5
840     ADDW       m3, [r5+4], m5
841     ADDW       m4, [r5+2], m5
842
843     FILT_H2    m2, m3, m4
844     psubw      m2, m6
845     mova [rsp+r4], m2
846     add       r4d, mmsize*3
847     add        r5, r2
848     dec       r3d
849     jg .nextrow
850     sub       rsp, gprsize
851     ret
852 %endmacro
853
854 INIT_MMX mmxext
855 H_NRD 4
856 INIT_XMM sse2
857 H_NRD 8
858
859 %macro MC21 2
860 cglobal_mc %1, mc21, %2, 3,7,12
861     mov   r5, r1
862 .body:
863 %define PAD mmsize*8*3*2   ; SIZE*16*4*sizeof(pixel)
864     mov   r6, rsp          ; backup stack pointer
865     and  rsp, ~(mmsize-1)  ; align stack
866
867     sub  rsp, PAD
868     call put_h%2_10
869
870     sub  rsp, PAD
871     call put_hv%2_10
872
873     mov r4d, PAD-mmsize    ; H buffer
874     jmp stub_%1_h264_qpel%2_mc12_10 %+ SUFFIX %+ .body
875 %endmacro
876
877 MC MC21
878
879 ;-----------------------------------------------------------------------------
880 ; void h264_qpel_mc23(uint8_t *dst, uint8_t *src, int stride)
881 ;-----------------------------------------------------------------------------
882 %macro MC23 2
883 cglobal_mc %1, mc23, %2, 3,7,12
884     lea   r5, [r1+r2]
885     jmp stub_%1_h264_qpel%2_mc21_10 %+ SUFFIX %+ .body
886 %endmacro
887
888 MC MC23