hevcdsp: add x86 SIMD for MC
[ffmpeg.git] / libavcodec / x86 / hevc_mc.asm
1 ;*****************************************************************************
2 ;* x86-optimized HEVC MC
3 ;* Copyright 2015 Anton Khirnov
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
26 pw_1023: times 8 dw 1023
27
28 cextern hevc_qpel_coeffs
29 cextern hevc_qpel_coeffs8
30
31 cextern hevc_epel_coeffs
32 cextern hevc_epel_coeffs8
33
34 cextern pw_8
35 cextern pw_16
36 cextern pw_32
37 cextern pw_64
38
39 SECTION .text
40
41 ; %1: width
42 ; %2: bit depth
43 %macro COMMON_DEFS 2
44     %assign blocksize            8
45     %assign nb_blocks            ((%1 + blocksize - 1) / blocksize)
46     %define last_block_truncated (blocksize * nb_blocks > %1)
47     %if %2 > 8
48         %define LOAD_BLOCK     movu
49         %define LOAD_HALFBLOCK movq
50         %assign pixelsize      2
51     %else
52         %define LOAD_BLOCK     movq
53         %define LOAD_HALFBLOCK movd
54         %assign pixelsize      1
55     %endif
56     %define STORE_BLOCK        mova
57     %define STORE_HALFBLOCK    movq
58 %endmacro
59
60 ; %1: block index
61 %macro BLOCK_DEFS 1
62     %if last_block_truncated && %1 == nb_blocks - 1
63         %define block_truncated 1
64         %define LOAD            LOAD_HALFBLOCK
65         %define STORE           STORE_HALFBLOCK
66     %else
67         %define block_truncated 0
68         %define LOAD            LOAD_BLOCK
69         %define STORE           STORE_BLOCK
70     %endif
71 %endmacro
72
73
74 ; hevc_get_pixels_<w>_<d>(int16_t *dst, ptrdiff_t dststride,
75 ;                         pixel   *src, ptrdiff_t srcstride,
76 ;                         int height, int mx, int my, int *mcbuffer)
77
78 ; %1: block width
79 ; %2: bit depth
80 ; %3: log2 of height unroll
81 %macro GET_PIXELS 3
82 cglobal hevc_get_pixels_ %+ %1 %+ _ %+ %2, 5, 5, 2, dst, dststride, src, srcstride, height ; rest of the args unused
83
84     %assign shift 14 - %2
85     COMMON_DEFS %1, %2
86
87 %if pixelsize == 1
88     pxor      m0, m0
89 %endif
90
91     shr       heightd, %3
92
93 .loop:
94
95 %assign i 0
96 %rep (1 << %3)
97
98 %assign j 0
99 %rep nb_blocks
100
101     BLOCK_DEFS j
102
103     LOAD       m1, [srcq + j * pixelsize * blocksize]
104 %if pixelsize == 1
105     punpcklbw  m1, m0
106 %endif
107     psllw      m1, shift
108     STORE      [dstq + j * 2 * blocksize], m1
109
110 %assign j (j + 1)
111 %endrep
112
113     add       dstq, dststrideq
114     add       srcq, srcstrideq
115
116 %assign i (i + 1)
117 %endrep
118
119     dec heightd
120     jg .loop
121     RET
122 %endmacro
123
124 INIT_XMM sse2
125 GET_PIXELS 4,  8, 1
126 GET_PIXELS 8,  8, 1
127 GET_PIXELS 12, 8, 3
128 GET_PIXELS 16, 8, 2
129 GET_PIXELS 24, 8, 3
130 GET_PIXELS 32, 8, 3
131 GET_PIXELS 48, 8, 3
132 GET_PIXELS 64, 8, 3
133
134 GET_PIXELS 4,  10, 1
135 GET_PIXELS 8,  10, 1
136 GET_PIXELS 12, 10, 3
137 GET_PIXELS 16, 10, 2
138 GET_PIXELS 24, 10, 3
139 GET_PIXELS 32, 10, 3
140 GET_PIXELS 48, 10, 3
141 GET_PIXELS 64, 10, 3
142
143 ; hevc_qpel_h/v_<w>_8(int16_t *dst, ptrdiff_t dststride,
144 ;                     uint8_t *src, ptrdiff_t srcstride,
145 ;                     int height, int mx, int my, int *mcbuffer)
146
147 ; 8-bit qpel interpolation
148 ; %1: block width
149 ; %2: 0 - horizontal; 1 - vertical
150 %macro QPEL_8 2
151 %if %2
152     %define postfix    v
153     %define mvfrac     myq
154     %define coeffsaddr r5q
155     %define pixstride  srcstrideq
156     %define pixstride3 r5q
157     %define src_m3     r6q
158 %else
159     %define postfix    h
160     %define mvfrac     mxq
161     %define coeffsaddr r6q
162     %define pixstride  1
163     %define pixstride3 3
164     %define src_m3     (srcq - 3)
165 %endif
166
167     COMMON_DEFS %1, 8
168
169 cglobal hevc_qpel_ %+ postfix %+ _ %+ %1 %+ _8, 7, 7, 7, dst, dststride, src, srcstride, height, mx, my
170     and       mvfrac, 0x3
171     dec       mvfrac
172     shl       mvfrac, 4
173     lea       coeffsaddr, [hevc_qpel_coeffs8]
174     mova      m0,         [coeffsaddr + mvfrac]
175
176     SPLATW    m1, m0, 1
177     SPLATW    m2, m0, 2
178     SPLATW    m3, m0, 3
179     SPLATW    m0, m0, 0
180
181 %if %2
182     lea       pixstride3, [srcstrideq + 2 * srcstrideq]
183     mov       src_m3, srcq
184     sub       src_m3, pixstride3
185 %endif
186
187 .loop
188
189 %assign i 0
190 %rep nb_blocks
191
192     BLOCK_DEFS i
193
194     LOAD m4, [src_m3 + i * blocksize]
195     LOAD m5, [src_m3 + i * blocksize + 1 * pixstride]
196     punpcklbw m4, m5
197     pmaddubsw m4, m0
198
199     LOAD m5, [src_m3 + i * blocksize + 2 * pixstride]
200     LOAD m6, [srcq   + i * blocksize]
201     punpcklbw m5, m6
202     pmaddubsw m5, m1
203     paddsw    m4, m5
204
205     LOAD m5, [srcq + i * blocksize + 1 * pixstride]
206     LOAD m6, [srcq + i * blocksize + 2 * pixstride]
207     punpcklbw m5, m6
208     pmaddubsw m5, m2
209     paddsw    m4, m5
210
211     LOAD m5, [srcq + i * blocksize +     pixstride3]
212     LOAD m6, [srcq + i * blocksize + 4 * pixstride]
213     punpcklbw m5, m6
214     pmaddubsw m5, m3
215     paddsw    m4, m5
216
217     STORE [dstq + i * 2 * blocksize], m4
218
219 %assign i (i + 1)
220 %endrep
221
222     add       dstq,   dststrideq
223     add       srcq,   srcstrideq
224 %if %2
225     add       src_m3, srcstrideq
226 %endif
227
228     dec heightd
229     jg .loop
230     RET
231 %endmacro
232
233 INIT_XMM ssse3
234 QPEL_8 4,  0
235 QPEL_8 8,  0
236 QPEL_8 12, 0
237 QPEL_8 16, 0
238 QPEL_8 24, 0
239 QPEL_8 32, 0
240 QPEL_8 48, 0
241 QPEL_8 64, 0
242
243 QPEL_8 4,  1
244 QPEL_8 8,  1
245 QPEL_8 12, 1
246 QPEL_8 16, 1
247 QPEL_8 24, 1
248 QPEL_8 32, 1
249 QPEL_8 48, 1
250 QPEL_8 64, 1
251
252 ; 16-bit qpel interpolation
253 ; %1: block width
254 ; %2: shift applied to the result
255 ; %3: 0 - horizontal; 1 - vertical
256 %macro QPEL_16 3
257 %if %3
258     %define mvfrac     myq
259     %define pixstride  srcstrideq
260     %define pixstride3 sstride3q
261     %define src_m3     srcm3q
262 %else
263     %define mvfrac     mxq
264     %define pixstride  2
265     %define pixstride3 6
266     %define src_m3     (srcq - 6)
267 %endif
268
269     COMMON_DEFS %1, 16
270
271     and       mvfrac, 0x3
272     dec       mvfrac
273     shl       mvfrac, 4
274     lea       coeffsregq, [hevc_qpel_coeffs]
275     mova      m0,         [coeffsregq + mvfrac]
276
277     pshufd    m1, m0, 0x55
278     pshufd    m2, m0, 0xaa
279     pshufd    m3, m0, 0xff
280     pshufd    m0, m0, 0x00
281
282 %if %3
283     lea       sstride3q, [srcstrideq + 2 * srcstrideq]
284     mov       srcm3q, srcq
285     sub       srcm3q, sstride3q
286 %endif
287
288 .loop
289
290 %assign i 0
291 %rep nb_blocks
292
293     BLOCK_DEFS i
294
295     LOAD m4,  [src_m3 + i * 2 * blocksize]
296     LOAD m5,  [src_m3 + i * 2 * blocksize + 1 * pixstride]
297     LOAD m6,  [src_m3 + i * 2 * blocksize + 2 * pixstride]
298     LOAD m7,  [srcq   + i * 2 * blocksize + 0 * pixstride]
299     LOAD m8,  [srcq   + i * 2 * blocksize + 1 * pixstride]
300     LOAD m9,  [srcq   + i * 2 * blocksize + 2 * pixstride]
301     LOAD m10, [srcq   + i * 2 * blocksize +     pixstride3]
302     LOAD m11, [srcq   + i * 2 * blocksize + 4 * pixstride]
303
304     punpcklwd m12, m4, m5
305     pmaddwd   m12, m0
306
307     punpcklwd m13, m6, m7
308     pmaddwd   m13, m1
309     paddd     m12, m13
310
311     punpcklwd m13, m8, m9
312     pmaddwd   m13, m2
313     paddd     m12, m13
314
315     punpcklwd m13, m10, m11
316     pmaddwd   m13, m3
317     paddd     m12, m13
318     psrad     m12, %2
319
320     %if block_truncated == 0
321         punpckhwd m4, m5
322         pmaddwd   m4, m0
323
324         punpckhwd m6, m7
325         pmaddwd   m6, m1
326         paddd     m4, m6
327
328         punpckhwd m8, m9
329         pmaddwd   m8, m2
330         paddd     m4, m8
331
332         punpckhwd m10, m11
333         pmaddwd   m10, m3
334         paddd     m4, m10
335
336         psrad     m4, %2
337     %endif
338     packssdw  m12, m4
339     STORE [dstq + i * 2 * blocksize], m12
340
341 %assign i (i + 1)
342 %endrep
343
344     add       dstq,   dststrideq
345     add       srcq,   srcstrideq
346 %if %3
347     add       srcm3q, srcstrideq
348 %endif
349
350     dec heightd
351     jg .loop
352     RET
353 %endmacro
354
355 %if ARCH_X86_64
356
357 %macro QPEL_H_10 1
358 cglobal hevc_qpel_h_ %+ %1 %+ _10, 7, 9, 14, dst, dststride, src, srcstride, height, mx, my, mcbuffer, coeffsreg
359 QPEL_16 %1, 2, 0
360 %endmacro
361
362 INIT_XMM avx
363 QPEL_H_10 4
364 QPEL_H_10 8
365 QPEL_H_10 12
366 QPEL_H_10 16
367 QPEL_H_10 24
368 QPEL_H_10 32
369 QPEL_H_10 48
370 QPEL_H_10 64
371
372 %macro QPEL_V_10 1
373 cglobal hevc_qpel_v_ %+ %1 %+ _10, 7, 10, 14, dst, dststride, src, srcstride, height, mx, my, sstride3, srcm3, coeffsreg
374 QPEL_16 %1, 2, 1
375 %endmacro
376
377 INIT_XMM avx
378 QPEL_V_10 4
379 QPEL_V_10 8
380 QPEL_V_10 12
381 QPEL_V_10 16
382 QPEL_V_10 24
383 QPEL_V_10 32
384 QPEL_V_10 48
385 QPEL_V_10 64
386
387 ; hevc_qpel_hv_<w>(int16_t *dst, ptrdiff_t dststride,
388 ;                  uint8_t *src, ptrdiff_t srcstride,
389 ;                  int height, int mx, int my, int *mcbuffer)
390
391 %macro QPEL_HV 1
392 cglobal hevc_qpel_hv_ %+ %1, 7, 10, 14, dst, dststride, src, srcstride, height, mx, my, sstride3, srcm3, coeffsreg
393 QPEL_16 %1, 6, 1
394 %endmacro
395
396 INIT_XMM avx
397 QPEL_HV 4
398 QPEL_HV 8
399 QPEL_HV 12
400 QPEL_HV 16
401 QPEL_HV 24
402 QPEL_HV 32
403 QPEL_HV 48
404 QPEL_HV 64
405
406 %endif ; ARCH_X86_64
407
408 ; hevc_epel_h/v_<w>_8(int16_t *dst, ptrdiff_t dststride,
409 ;                     uint8_t *src, ptrdiff_t srcstride,
410 ;                     int height, int mx, int my, int *mcbuffer)
411
412 ; 8-bit epel interpolation
413 ; %1: block width
414 ; %2: 0 - horizontal; 1 - vertical
415 %macro EPEL_8 2
416 %if %2
417     %define postfix    v
418     %define mvfrac     myq
419     %define coeffsaddr r5q
420     %define pixstride  srcstrideq
421     %define pixstride3 r5q
422 %else
423     %define postfix    h
424     %define mvfrac     mxq
425     %define coeffsaddr r6q
426     %define pixstride  1
427     %define pixstride3 3
428 %endif
429
430     COMMON_DEFS %1, 8
431
432 cglobal hevc_epel_ %+ postfix %+ _ %+ %1 %+ _8, 7, 7, 6, dst, dststride, src, srcstride, height, mx, my
433     and       mvfrac, 0x7
434     dec       mvfrac
435     shl       mvfrac, 4
436     lea       coeffsaddr, [hevc_epel_coeffs8]
437     movq      m0,         [coeffsaddr + mvfrac]
438
439     SPLATW    m1, m0, 1
440     SPLATW    m0, m0, 0
441
442 %if %2
443     lea       pixstride3, [srcstrideq + 2 * srcstrideq]
444 %endif
445     sub       srcq, pixstride
446
447 .loop
448
449 %assign i 0
450 %rep nb_blocks
451
452     BLOCK_DEFS i
453
454     LOAD m2, [srcq + i * blocksize + 0 * pixstride]
455     LOAD m3, [srcq + i * blocksize + 1 * pixstride]
456     LOAD m4, [srcq + i * blocksize + 2 * pixstride]
457     LOAD m5, [srcq + i * blocksize +     pixstride3]
458
459     punpcklbw m2, m3
460     punpcklbw m4, m5
461
462     pmaddubsw m2, m0
463     pmaddubsw m4, m1
464
465     paddsw    m2, m4
466
467     STORE [dstq + i * 2 * blocksize], m2
468
469 %assign i (i + 1)
470 %endrep
471
472     add       dstq, dststrideq
473     add       srcq, srcstrideq
474
475     dec heightd
476     jg .loop
477     RET
478 %endmacro
479
480 INIT_XMM ssse3
481 EPEL_8 4,  0
482 EPEL_8 8,  0
483 EPEL_8 12, 0
484 EPEL_8 16, 0
485 EPEL_8 24, 0
486 EPEL_8 32, 0
487
488 EPEL_8 4,  1
489 EPEL_8 8,  1
490 EPEL_8 12, 1
491 EPEL_8 16, 1
492 EPEL_8 24, 1
493 EPEL_8 32, 1
494
495 %macro EPEL_16 3
496 %if %3
497     %define mvfrac     myq
498     %define pixstride  srcstrideq
499     %define pixstride3 sstride3q
500 %else
501     %define mvfrac     mxq
502     %define pixstride  2
503     %define pixstride3 6
504 %endif
505
506     COMMON_DEFS %1, 16
507
508     and       mvfrac, 0x7
509     dec       mvfrac
510     shl       mvfrac, 5
511     lea       coeffsregq, [hevc_epel_coeffs]
512     mova      m0, [coeffsregq + mvfrac]
513
514     pshufd    m1, m0, 0x55
515     pshufd    m0, m0, 0x00
516
517 %if %3
518     lea       sstride3q, [srcstrideq + 2 * srcstrideq]
519 %endif
520     sub       srcq, pixstride
521
522 .loop
523
524 %assign i 0
525 %rep nb_blocks
526
527     BLOCK_DEFS i
528
529     LOAD m2, [srcq + i * 2 * blocksize + 0 * pixstride]
530     LOAD m3, [srcq + i * 2 * blocksize + 1 * pixstride]
531     LOAD m4, [srcq + i * 2 * blocksize + 2 * pixstride]
532     LOAD m5, [srcq + i * 2 * blocksize +     pixstride3]
533
534     punpcklwd m6, m2, m3
535     punpcklwd m7, m4, m5
536     pmaddwd   m6, m0
537     pmaddwd   m7, m1
538     paddd     m6, m7
539     psrad     m6, %2
540
541     %if block_truncated == 0
542         punpckhwd m2, m3
543         punpckhwd m4, m5
544         pmaddwd   m2, m0
545         pmaddwd   m4, m1
546         paddd     m2, m4
547         psrad     m2, %2
548     %endif
549     packssdw  m6, m2
550     STORE [dstq + i * 2 * blocksize], m6
551
552 %assign i (i + 1)
553 %endrep
554
555     add       dstq,   dststrideq
556     add       srcq,   srcstrideq
557
558     dec heightd
559     jg .loop
560     RET
561 %endmacro
562
563 %if ARCH_X86_64
564
565 %macro EPEL_H_10 1
566 cglobal hevc_epel_h_ %+ %1 %+ _10, 8, 9, 8, dst, dststride, src, srcstride, height, mx, my, sstride3, coeffsreg
567 EPEL_16 %1, 2, 0
568 %endmacro
569
570 INIT_XMM avx
571 EPEL_H_10 4
572 EPEL_H_10 8
573 EPEL_H_10 12
574 EPEL_H_10 16
575 EPEL_H_10 24
576 EPEL_H_10 32
577
578 %macro EPEL_V_10 1
579 cglobal hevc_epel_v_ %+ %1 %+ _10, 8, 9, 8, dst, dststride, src, srcstride, height, mx, my, sstride3, coeffsreg
580 EPEL_16 %1, 2, 1
581 %endmacro
582
583 INIT_XMM avx
584 EPEL_V_10 4
585 EPEL_V_10 8
586 EPEL_V_10 12
587 EPEL_V_10 16
588 EPEL_V_10 24
589 EPEL_V_10 32
590
591 ; hevc_epel_hv_<w>_8(int16_t *dst, ptrdiff_t dststride,
592 ;                    int16_t *src, ptrdiff_t srcstride,
593 ;                    int height, int mx, int my, int *mcbuffer)
594
595 %macro EPEL_HV 1
596 cglobal hevc_epel_hv_ %+ %1, 8, 9, 8, dst, dststride, src, srcstride, height, mx, my, sstride3, coeffsreg
597 EPEL_16 %1, 6, 1
598 %endmacro
599
600 INIT_XMM avx
601 EPEL_HV 4
602 EPEL_HV 8
603 EPEL_HV 12
604 EPEL_HV 16
605 EPEL_HV 24
606 EPEL_HV 32
607
608 %endif ; ARCH_X86_64
609
610 ; hevc_put_unweighted_pred_<w>_<d>(pixel   *dst, ptrdiff_t dststride,
611 ;                                  int16_t *src, ptrdiff_t srcstride,
612 ;                                  int height)
613
614 %macro AVG 5
615     %if %3
616         %if %4 == 4
617             movq %5, %2
618             paddsw %1, %5
619         %else
620             paddsw %1, %2
621         %endif
622     %endif
623 %endmacro
624
625 ; %1: 0 - one source; 1 - two sources
626 ; %2: width
627 ; %3: bit depth
628 %macro PUT_PRED 3
629 %if %1
630 cglobal hevc_put_unweighted_pred_avg_ %+ %2 %+ _ %+ %3, 6, 6, 4, dst, dststride, src, src2, srcstride, height
631 %else
632 cglobal hevc_put_unweighted_pred_ %+ %2 %+ _ %+ %3, 5, 5, 4, dst, dststride, src, srcstride, height
633 %endif
634
635 %assign shift       14 + %1 - %3
636 %assign offset      (1 << (shift - 1))
637 %define offset_data pw_ %+ offset
638
639     mova        m0, [offset_data]
640
641 %if %3 > 8
642     %define STORE_BLOCK movu
643     %define STORE_HALF  movq
644
645     %assign pixel_max ((1 << %3) - 1)
646     %define pw_pixel_max pw_ %+ pixel_max
647     pxor    m1, m1
648     mova    m2, [pw_pixel_max]
649 %else
650     %define STORE_BLOCK movq
651     %define STORE_HALF  movd
652 %endif
653
654 .loop
655 %assign i 0
656 %rep (%2 + 7) / 8
657
658     %if (i + 1) * 8 > %2
659         %define LOAD movq
660         %define STORE STORE_HALF
661     %else
662         %define LOAD mova
663         %define STORE STORE_BLOCK
664     %endif
665
666     LOAD m3, [srcq  + 16 * i]
667     AVG  m3, [src2q + 16 * i], %1, %3 - i * 8, m4
668
669     paddsw m3, m0
670     psraw  m3, shift
671
672     %if %3 == 8
673         packuswb m3, m3
674         STORE [dstq + 8 * i], m3
675     %else
676         CLIPW m3, m1, m2
677         STORE [dstq + 16 * i], m3
678     %endif
679 %assign i (i + 1)
680 %endrep
681
682     add dstq,  dststrideq
683     add srcq,  srcstrideq
684 %if %1
685     add src2q, srcstrideq
686 %endif
687
688     dec         heightd
689     jg          .loop
690     RET
691 %endmacro
692
693 INIT_XMM sse2
694 PUT_PRED 0, 4,  8
695 PUT_PRED 1, 4,  8
696 PUT_PRED 0, 8,  8
697 PUT_PRED 1, 8,  8
698 PUT_PRED 0, 12, 8
699 PUT_PRED 1, 12, 8
700 PUT_PRED 0, 16, 8
701 PUT_PRED 1, 16, 8
702 PUT_PRED 0, 24, 8
703 PUT_PRED 1, 24, 8
704 PUT_PRED 0, 32, 8
705 PUT_PRED 1, 32, 8
706 PUT_PRED 0, 48, 8
707 PUT_PRED 1, 48, 8
708 PUT_PRED 0, 64, 8
709 PUT_PRED 1, 64, 8
710
711 PUT_PRED 0, 4,  10
712 PUT_PRED 1, 4,  10
713 PUT_PRED 0, 8,  10
714 PUT_PRED 1, 8,  10
715 PUT_PRED 0, 12, 10
716 PUT_PRED 1, 12, 10
717 PUT_PRED 0, 16, 10
718 PUT_PRED 1, 16, 10
719 PUT_PRED 0, 24, 10
720 PUT_PRED 1, 24, 10
721 PUT_PRED 0, 32, 10
722 PUT_PRED 1, 32, 10
723 PUT_PRED 0, 48, 10
724 PUT_PRED 1, 48, 10
725 PUT_PRED 0, 64, 10
726 PUT_PRED 1, 64, 10
727
728 %macro PUT_WEIGHTED_PRED 3
729 %if %1
730 cglobal hevc_put_weighted_pred_avg_ %+ %2 %+ _ %+ %3, 11, 11, 8, denom, weight0, weight1, offset0, offset1, dst, dststride, src0, src1, srcstride, height
731 %else
732 cglobal hevc_put_weighted_pred_ %+ %2 %+ _ %+ %3, 8, 8, 8, denom, weight0, offset0, dst, dststride, src0, srcstride, height
733 %endif
734
735     and         denomd, 0xff
736     movsx       weight0d, weight0w
737     movsx       offset0d, offset0w
738 %if %1
739     movsx       weight1d, weight1w
740     movsx       offset1d, offset1w
741 %endif
742
743     add         denomd, 14 + %1 - %3
744     movd        m0, denomd
745
746 %if %3 > 8
747     %assign     pixel_max ((1 << %3) - 1)
748     %define     pw_pixel_max pw_ %+ pixel_max
749     pxor        m4, m4
750     mova        m5, [pw_pixel_max]
751
752     shl         offset0d, %3 - 8
753 %if %1
754     shl         offset1d, %3 - 8
755 %endif
756 %endif
757
758 %if %1
759     lea         offset0d, [offset0d + offset1d + 1]
760 %else
761     lea         offset0d, [2 * offset0d + 1]
762 %endif
763     movd        m1, offset0d
764     SPLATD      m1
765     pslld       m1, m0
766     psrad       m1, 1
767
768     movd        m2, weight0d
769     SPLATD      m2
770 %if %1
771     movd        m3, weight1d
772     SPLATD      m3
773 %endif
774
775 .loop
776 %assign i 0
777 %rep (%2 + 3) / 4
778
779     pmovsxwd   m6, [src0q + 8 * i]
780     pmulld     m6, m2
781
782 %if %1
783     pmovsxwd   m7, [src1q + 8 * i]
784     pmulld     m7, m3
785     paddd      m6, m7
786 %endif
787
788     paddd      m6, m1
789     psrad      m6, m0
790
791     packssdw   m6, m6
792
793 %if %3 > 8
794     CLIPW      m6, m4, m5
795     movq       [dstq + 8 * i], m6
796 %else
797     packuswb   m6, m6
798     movd [dstq + 4 * i], m6
799 %endif
800
801 %assign i (i + 1)
802 %endrep
803
804     add dstq,  dststrideq
805     add src0q, srcstrideq
806 %if %1
807     add src1q, srcstrideq
808 %endif
809
810     dec         heightd
811     jg          .loop
812     RET
813 %endmacro
814
815 %if ARCH_X86_64
816 INIT_XMM sse4
817 PUT_WEIGHTED_PRED 0, 4,  8
818 PUT_WEIGHTED_PRED 1, 4,  8
819 PUT_WEIGHTED_PRED 0, 8,  8
820 PUT_WEIGHTED_PRED 1, 8,  8
821 PUT_WEIGHTED_PRED 0, 12, 8
822 PUT_WEIGHTED_PRED 1, 12, 8
823 PUT_WEIGHTED_PRED 0, 16, 8
824 PUT_WEIGHTED_PRED 1, 16, 8
825 PUT_WEIGHTED_PRED 0, 24, 8
826 PUT_WEIGHTED_PRED 1, 24, 8
827 PUT_WEIGHTED_PRED 0, 32, 8
828 PUT_WEIGHTED_PRED 1, 32, 8
829 PUT_WEIGHTED_PRED 0, 48, 8
830 PUT_WEIGHTED_PRED 1, 48, 8
831 PUT_WEIGHTED_PRED 0, 64, 8
832 PUT_WEIGHTED_PRED 1, 64, 8
833
834 PUT_WEIGHTED_PRED 0, 4,  10
835 PUT_WEIGHTED_PRED 1, 4,  10
836 PUT_WEIGHTED_PRED 0, 8,  10
837 PUT_WEIGHTED_PRED 1, 8,  10
838 PUT_WEIGHTED_PRED 0, 12, 10
839 PUT_WEIGHTED_PRED 1, 12, 10
840 PUT_WEIGHTED_PRED 0, 16, 10
841 PUT_WEIGHTED_PRED 1, 16, 10
842 PUT_WEIGHTED_PRED 0, 24, 10
843 PUT_WEIGHTED_PRED 1, 24, 10
844 PUT_WEIGHTED_PRED 0, 32, 10
845 PUT_WEIGHTED_PRED 1, 32, 10
846 PUT_WEIGHTED_PRED 0, 48, 10
847 PUT_WEIGHTED_PRED 1, 48, 10
848 PUT_WEIGHTED_PRED 0, 64, 10
849 PUT_WEIGHTED_PRED 1, 64, 10
850
851 %endif ; ARCH_X86_64