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