]> git.sesse.net Git - x264/blob - common/x86/mc-a2.asm
f796ad17fffbf4dda37b9c299728e277e04ff8a7
[x264] / common / x86 / mc-a2.asm
1 ;*****************************************************************************
2 ;* mc-a2.asm: x86 motion compensation
3 ;*****************************************************************************
4 ;* Copyright (C) 2005-2014 x264 project
5 ;*
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>
7 ;*          Fiona Glaser <fiona@x264.com>
8 ;*          Holger Lubitz <holger@lubitz.org>
9 ;*          Mathieu Monnier <manao@melix.net>
10 ;*          Oskar Arvidsson <oskar@irock.se>
11 ;*
12 ;* This program is free software; you can redistribute it and/or modify
13 ;* it under the terms of the GNU General Public License as published by
14 ;* the Free Software Foundation; either version 2 of the License, or
15 ;* (at your option) any later version.
16 ;*
17 ;* This program is distributed in the hope that it will be useful,
18 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ;* GNU General Public License for more details.
21 ;*
22 ;* You should have received a copy of the GNU General Public License
23 ;* along with this program; if not, write to the Free Software
24 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
25 ;*
26 ;* This program is also available under a commercial proprietary license.
27 ;* For more information, contact us at licensing@x264.com.
28 ;*****************************************************************************
29
30 %include "x86inc.asm"
31 %include "x86util.asm"
32
33 SECTION_RODATA 32
34
35 filt_mul20: times 32 db 20
36 filt_mul15: times 16 db 1, -5
37 filt_mul51: times 16 db -5, 1
38 hpel_shuf: times 2 db 0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15
39 deinterleave_shuf: times 2 db 0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15
40
41 v210_mask: times 4 dq 0xc00ffc003ff003ff
42 v210_luma_shuf: times 2 db 1,2,4,5,6,7,9,10,12,13,14,15,12,13,14,15
43 v210_chroma_shuf: times 2 db 0,1,2,3,5,6,8,9,10,11,13,14,10,11,13,14
44 ; vpermd indices {0,1,2,4,5,7,_,_} merged in the 3 lsb of each dword to save a register
45 v210_mult: dw 0x2000,0x7fff,0x0801,0x2000,0x7ffa,0x0800,0x7ffc,0x0800
46            dw 0x1ffd,0x7fff,0x07ff,0x2000,0x7fff,0x0800,0x7fff,0x0800
47
48 %if HIGH_BIT_DEPTH
49 deinterleave_shuf32a: SHUFFLE_MASK_W 0,2,4,6,8,10,12,14
50 deinterleave_shuf32b: SHUFFLE_MASK_W 1,3,5,7,9,11,13,15
51 %else
52 deinterleave_shuf32a: db 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30
53 deinterleave_shuf32b: db 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31
54 %endif
55 pw_1024: times 16 dw 1024
56
57 pd_16: times 4 dd 16
58 pd_0f: times 4 dd 0xffff
59
60 pad10: times 8 dw    10*PIXEL_MAX
61 pad20: times 8 dw    20*PIXEL_MAX
62 pad30: times 8 dw    30*PIXEL_MAX
63 depad: times 4 dd 32*20*PIXEL_MAX + 512
64
65 tap1: times 4 dw  1, -5
66 tap2: times 4 dw 20, 20
67 tap3: times 4 dw -5,  1
68
69 SECTION .text
70
71 cextern pb_0
72 cextern pw_1
73 cextern pw_16
74 cextern pw_32
75 cextern pw_512
76 cextern pw_00ff
77 cextern pw_3fff
78 cextern pw_pixel_max
79 cextern pd_ffff
80
81 %macro LOAD_ADD 4
82     movh       %4, %3
83     movh       %1, %2
84     punpcklbw  %4, m0
85     punpcklbw  %1, m0
86     paddw      %1, %4
87 %endmacro
88
89 %macro LOAD_ADD_2 6
90     mova       %5, %3
91     mova       %1, %4
92     punpckhbw  %6, %5, m0
93     punpcklbw  %5, m0
94     punpckhbw  %2, %1, m0
95     punpcklbw  %1, m0
96     paddw      %1, %5
97     paddw      %2, %6
98 %endmacro
99
100 %macro FILT_V2 6
101     psubw  %1, %2  ; a-b
102     psubw  %4, %5
103     psubw  %2, %3  ; b-c
104     psubw  %5, %6
105     psllw  %2, 2
106     psllw  %5, 2
107     psubw  %1, %2  ; a-5*b+4*c
108     psllw  %3, 4
109     psubw  %4, %5
110     psllw  %6, 4
111     paddw  %1, %3  ; a-5*b+20*c
112     paddw  %4, %6
113 %endmacro
114
115 %macro FILT_H 3
116     psubw  %1, %2  ; a-b
117     psraw  %1, 2   ; (a-b)/4
118     psubw  %1, %2  ; (a-b)/4-b
119     paddw  %1, %3  ; (a-b)/4-b+c
120     psraw  %1, 2   ; ((a-b)/4-b+c)/4
121     paddw  %1, %3  ; ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
122 %endmacro
123
124 %macro FILT_H2 6
125     psubw  %1, %2
126     psubw  %4, %5
127     psraw  %1, 2
128     psraw  %4, 2
129     psubw  %1, %2
130     psubw  %4, %5
131     paddw  %1, %3
132     paddw  %4, %6
133     psraw  %1, 2
134     psraw  %4, 2
135     paddw  %1, %3
136     paddw  %4, %6
137 %endmacro
138
139 %macro FILT_PACK 3-5
140 %if cpuflag(ssse3)
141     pmulhrsw %1, %3
142     pmulhrsw %2, %3
143 %else
144     paddw    %1, %3
145     paddw    %2, %3
146 %if %0 == 5
147     psubusw  %1, %5
148     psubusw  %2, %5
149     psrlw    %1, %4
150     psrlw    %2, %4
151 %else
152     psraw    %1, %4
153     psraw    %2, %4
154 %endif
155 %endif
156 %if HIGH_BIT_DEPTH == 0
157     packuswb %1, %2
158 %endif
159 %endmacro
160
161 ;The hpel_filter routines use non-temporal writes for output.
162 ;The following defines may be uncommented for testing.
163 ;Doing the hpel_filter temporal may be a win if the last level cache
164 ;is big enough (preliminary benching suggests on the order of 4* framesize).
165
166 ;%define movntq movq
167 ;%define movntps movaps
168 ;%define sfence
169
170 %if HIGH_BIT_DEPTH
171 ;-----------------------------------------------------------------------------
172 ; void hpel_filter_v( uint16_t *dst, uint16_t *src, int16_t *buf, intptr_t stride, intptr_t width );
173 ;-----------------------------------------------------------------------------
174 %macro HPEL_FILTER 0
175 cglobal hpel_filter_v, 5,6,11
176     FIX_STRIDES r3, r4
177     lea        r5, [r1+r3]
178     sub        r1, r3
179     sub        r1, r3
180 %if num_mmregs > 8
181     mova       m8, [pad10]
182     mova       m9, [pad20]
183     mova      m10, [pad30]
184     %define s10 m8
185     %define s20 m9
186     %define s30 m10
187 %else
188     %define s10 [pad10]
189     %define s20 [pad20]
190     %define s30 [pad30]
191 %endif
192     add        r0, r4
193     add        r2, r4
194     neg        r4
195     mova       m7, [pw_pixel_max]
196     pxor       m0, m0
197 .loop:
198     mova       m1, [r1]
199     mova       m2, [r1+r3]
200     mova       m3, [r1+r3*2]
201     mova       m4, [r1+mmsize]
202     mova       m5, [r1+r3+mmsize]
203     mova       m6, [r1+r3*2+mmsize]
204     paddw      m1, [r5+r3*2]
205     paddw      m2, [r5+r3]
206     paddw      m3, [r5]
207     paddw      m4, [r5+r3*2+mmsize]
208     paddw      m5, [r5+r3+mmsize]
209     paddw      m6, [r5+mmsize]
210     add        r1, 2*mmsize
211     add        r5, 2*mmsize
212     FILT_V2    m1, m2, m3, m4, m5, m6
213     mova       m6, [pw_16]
214     psubw      m1, s20
215     psubw      m4, s20
216     mova      [r2+r4], m1
217     mova      [r2+r4+mmsize], m4
218     paddw      m1, s30
219     paddw      m4, s30
220     FILT_PACK  m1, m4, m6, 5, s10
221     CLIPW      m1, m0, m7
222     CLIPW      m4, m0, m7
223     mova      [r0+r4], m1
224     mova      [r0+r4+mmsize], m4
225     add        r4, 2*mmsize
226     jl .loop
227     RET
228
229 ;-----------------------------------------------------------------------------
230 ; void hpel_filter_c( uint16_t *dst, int16_t *buf, intptr_t width );
231 ;-----------------------------------------------------------------------------
232 cglobal hpel_filter_c, 3,3,10
233     add        r2, r2
234     add        r0, r2
235     add        r1, r2
236     neg        r2
237     mova       m0, [tap1]
238     mova       m7, [tap3]
239 %if num_mmregs > 8
240     mova       m8, [tap2]
241     mova       m9, [depad]
242     %define s1 m8
243     %define s2 m9
244 %else
245     %define s1 [tap2]
246     %define s2 [depad]
247 %endif
248 .loop:
249     movu       m1, [r1+r2-4]
250     movu       m2, [r1+r2-2]
251     mova       m3, [r1+r2+0]
252     movu       m4, [r1+r2+2]
253     movu       m5, [r1+r2+4]
254     movu       m6, [r1+r2+6]
255     pmaddwd    m1, m0
256     pmaddwd    m2, m0
257     pmaddwd    m3, s1
258     pmaddwd    m4, s1
259     pmaddwd    m5, m7
260     pmaddwd    m6, m7
261     paddd      m1, s2
262     paddd      m2, s2
263     paddd      m3, m5
264     paddd      m4, m6
265     paddd      m1, m3
266     paddd      m2, m4
267     psrad      m1, 10
268     psrad      m2, 10
269     pslld      m2, 16
270     pand       m1, [pd_0f]
271     por        m1, m2
272     CLIPW      m1, [pb_0], [pw_pixel_max]
273     mova  [r0+r2], m1
274     add        r2, mmsize
275     jl .loop
276     RET
277
278 ;-----------------------------------------------------------------------------
279 ; void hpel_filter_h( uint16_t *dst, uint16_t *src, intptr_t width );
280 ;-----------------------------------------------------------------------------
281 cglobal hpel_filter_h, 3,4,8
282     %define src r1+r2
283     add        r2, r2
284     add        r0, r2
285     add        r1, r2
286     neg        r2
287     mova       m0, [pw_pixel_max]
288 .loop:
289     movu       m1, [src-4]
290     movu       m2, [src-2]
291     mova       m3, [src+0]
292     movu       m6, [src+2]
293     movu       m4, [src+4]
294     movu       m5, [src+6]
295     paddw      m3, m6 ; c0
296     paddw      m2, m4 ; b0
297     paddw      m1, m5 ; a0
298 %if mmsize == 16
299     movu       m4, [src-4+mmsize]
300     movu       m5, [src-2+mmsize]
301 %endif
302     movu       m7, [src+4+mmsize]
303     movu       m6, [src+6+mmsize]
304     paddw      m5, m7 ; b1
305     paddw      m4, m6 ; a1
306     movu       m7, [src+2+mmsize]
307     mova       m6, [src+0+mmsize]
308     paddw      m6, m7 ; c1
309     FILT_H2    m1, m2, m3, m4, m5, m6
310     mova       m7, [pw_1]
311     pxor       m2, m2
312     FILT_PACK  m1, m4, m7, 1
313     CLIPW      m1, m2, m0
314     CLIPW      m4, m2, m0
315     mova      [r0+r2], m1
316     mova      [r0+r2+mmsize], m4
317     add        r2, mmsize*2
318     jl .loop
319     RET
320 %endmacro ; HPEL_FILTER
321
322 INIT_MMX mmx2
323 HPEL_FILTER
324 INIT_XMM sse2
325 HPEL_FILTER
326 %endif ; HIGH_BIT_DEPTH
327
328 %if HIGH_BIT_DEPTH == 0
329 %macro HPEL_V 1
330 ;-----------------------------------------------------------------------------
331 ; void hpel_filter_v( uint8_t *dst, uint8_t *src, int16_t *buf, intptr_t stride, intptr_t width );
332 ;-----------------------------------------------------------------------------
333 cglobal hpel_filter_v, 5,6,%1
334     lea r5, [r1+r3]
335     sub r1, r3
336     sub r1, r3
337     add r0, r4
338     lea r2, [r2+r4*2]
339     neg r4
340 %if cpuflag(ssse3)
341     mova m0, [filt_mul15]
342 %else
343     pxor m0, m0
344 %endif
345 .loop:
346 %if cpuflag(ssse3)
347     mova m1, [r1]
348     mova m4, [r1+r3]
349     mova m2, [r5+r3*2]
350     mova m5, [r5+r3]
351     mova m3, [r1+r3*2]
352     mova m6, [r5]
353     SBUTTERFLY bw, 1, 4, 7
354     SBUTTERFLY bw, 2, 5, 7
355     SBUTTERFLY bw, 3, 6, 7
356     pmaddubsw m1, m0
357     pmaddubsw m4, m0
358     pmaddubsw m2, m0
359     pmaddubsw m5, m0
360     pmaddubsw m3, [filt_mul20]
361     pmaddubsw m6, [filt_mul20]
362     paddw  m1, m2
363     paddw  m4, m5
364     paddw  m1, m3
365     paddw  m4, m6
366     mova   m7, [pw_1024]
367 %else
368     LOAD_ADD_2 m1, m4, [r1     ], [r5+r3*2], m6, m7            ; a0 / a1
369     LOAD_ADD_2 m2, m5, [r1+r3  ], [r5+r3  ], m6, m7            ; b0 / b1
370     LOAD_ADD   m3,     [r1+r3*2], [r5     ], m7                ; c0
371     LOAD_ADD   m6,     [r1+r3*2+mmsize/2], [r5+mmsize/2], m7   ; c1
372     FILT_V2 m1, m2, m3, m4, m5, m6
373     mova   m7, [pw_16]
374 %endif
375 %if mmsize==32
376     mova         [r2+r4*2], xm1
377     mova         [r2+r4*2+mmsize/2], xm4
378     vextracti128 [r2+r4*2+mmsize], m1, 1
379     vextracti128 [r2+r4*2+mmsize*3/2], m4, 1
380 %else
381     mova      [r2+r4*2], m1
382     mova      [r2+r4*2+mmsize], m4
383 %endif
384     FILT_PACK m1, m4, m7, 5
385     movnta    [r0+r4], m1
386     add r1, mmsize
387     add r5, mmsize
388     add r4, mmsize
389     jl .loop
390     RET
391 %endmacro
392
393 ;-----------------------------------------------------------------------------
394 ; void hpel_filter_c( uint8_t *dst, int16_t *buf, intptr_t width );
395 ;-----------------------------------------------------------------------------
396 INIT_MMX mmx2
397 cglobal hpel_filter_c, 3,3
398     add r0, r2
399     lea r1, [r1+r2*2]
400     neg r2
401     %define src r1+r2*2
402     movq m7, [pw_32]
403 .loop:
404     movq   m1, [src-4]
405     movq   m2, [src-2]
406     movq   m3, [src  ]
407     movq   m4, [src+4]
408     movq   m5, [src+6]
409     paddw  m3, [src+2]  ; c0
410     paddw  m2, m4       ; b0
411     paddw  m1, m5       ; a0
412     movq   m6, [src+8]
413     paddw  m4, [src+14] ; a1
414     paddw  m5, [src+12] ; b1
415     paddw  m6, [src+10] ; c1
416     FILT_H2 m1, m2, m3, m4, m5, m6
417     FILT_PACK m1, m4, m7, 6
418     movntq [r0+r2], m1
419     add r2, 8
420     jl .loop
421     RET
422
423 ;-----------------------------------------------------------------------------
424 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, intptr_t width );
425 ;-----------------------------------------------------------------------------
426 INIT_MMX mmx2
427 cglobal hpel_filter_h, 3,3
428     add r0, r2
429     add r1, r2
430     neg r2
431     %define src r1+r2
432     pxor m0, m0
433 .loop:
434     movd       m1, [src-2]
435     movd       m2, [src-1]
436     movd       m3, [src  ]
437     movd       m6, [src+1]
438     movd       m4, [src+2]
439     movd       m5, [src+3]
440     punpcklbw  m1, m0
441     punpcklbw  m2, m0
442     punpcklbw  m3, m0
443     punpcklbw  m6, m0
444     punpcklbw  m4, m0
445     punpcklbw  m5, m0
446     paddw      m3, m6 ; c0
447     paddw      m2, m4 ; b0
448     paddw      m1, m5 ; a0
449     movd       m7, [src+7]
450     movd       m6, [src+6]
451     punpcklbw  m7, m0
452     punpcklbw  m6, m0
453     paddw      m4, m7 ; c1
454     paddw      m5, m6 ; b1
455     movd       m7, [src+5]
456     movd       m6, [src+4]
457     punpcklbw  m7, m0
458     punpcklbw  m6, m0
459     paddw      m6, m7 ; a1
460     movq       m7, [pw_1]
461     FILT_H2 m1, m2, m3, m4, m5, m6
462     FILT_PACK m1, m4, m7, 1
463     movntq     [r0+r2], m1
464     add r2, 8
465     jl .loop
466     RET
467
468 %macro HPEL_C 0
469 ;-----------------------------------------------------------------------------
470 ; void hpel_filter_c( uint8_t *dst, int16_t *buf, intptr_t width );
471 ;-----------------------------------------------------------------------------
472 cglobal hpel_filter_c, 3,3,9
473     add r0, r2
474     lea r1, [r1+r2*2]
475     neg r2
476     %define src r1+r2*2
477 %ifnidn cpuname, sse2
478 %if cpuflag(ssse3)
479     mova    m7, [pw_512]
480 %else
481     mova    m7, [pw_32]
482 %endif
483     %define pw_rnd m7
484 %elif ARCH_X86_64
485     mova    m8, [pw_32]
486     %define pw_rnd m8
487 %else
488     %define pw_rnd [pw_32]
489 %endif
490 ; This doesn't seem to be faster (with AVX) on Sandy Bridge or Bulldozer...
491 %if mmsize==32
492 .loop:
493     movu    m4, [src-4]
494     movu    m5, [src-2]
495     mova    m6, [src+0]
496     movu    m3, [src-4+mmsize]
497     movu    m2, [src-2+mmsize]
498     mova    m1, [src+0+mmsize]
499     paddw   m4, [src+6]
500     paddw   m5, [src+4]
501     paddw   m6, [src+2]
502     paddw   m3, [src+6+mmsize]
503     paddw   m2, [src+4+mmsize]
504     paddw   m1, [src+2+mmsize]
505     FILT_H2 m4, m5, m6, m3, m2, m1
506 %else
507     mova      m0, [src-16]
508     mova      m1, [src]
509 .loop:
510     mova      m2, [src+16]
511     PALIGNR   m4, m1, m0, 12, m7
512     PALIGNR   m5, m1, m0, 14, m0
513     PALIGNR   m0, m2, m1, 6, m7
514     paddw     m4, m0
515     PALIGNR   m0, m2, m1, 4, m7
516     paddw     m5, m0
517     PALIGNR   m6, m2, m1, 2, m7
518     paddw     m6, m1
519     FILT_H    m4, m5, m6
520
521     mova      m0, m2
522     mova      m5, m2
523     PALIGNR   m2, m1, 12, m7
524     PALIGNR   m5, m1, 14, m1
525     mova      m1, [src+32]
526     PALIGNR   m3, m1, m0, 6, m7
527     paddw     m3, m2
528     PALIGNR   m6, m1, m0, 4, m7
529     paddw     m5, m6
530     PALIGNR   m6, m1, m0, 2, m7
531     paddw     m6, m0
532     FILT_H    m3, m5, m6
533 %endif
534     FILT_PACK m4, m3, pw_rnd, 6
535 %if mmsize==32
536     vpermq    m4, m4, q3120
537 %endif
538     movnta [r0+r2], m4
539     add       r2, mmsize
540     jl .loop
541     RET
542 %endmacro
543
544 ;-----------------------------------------------------------------------------
545 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, intptr_t width );
546 ;-----------------------------------------------------------------------------
547 INIT_XMM sse2
548 cglobal hpel_filter_h, 3,3,8
549     add r0, r2
550     add r1, r2
551     neg r2
552     %define src r1+r2
553     pxor m0, m0
554 .loop:
555     movh       m1, [src-2]
556     movh       m2, [src-1]
557     movh       m3, [src  ]
558     movh       m4, [src+1]
559     movh       m5, [src+2]
560     movh       m6, [src+3]
561     punpcklbw  m1, m0
562     punpcklbw  m2, m0
563     punpcklbw  m3, m0
564     punpcklbw  m4, m0
565     punpcklbw  m5, m0
566     punpcklbw  m6, m0
567     paddw      m3, m4 ; c0
568     paddw      m2, m5 ; b0
569     paddw      m1, m6 ; a0
570     movh       m4, [src+6]
571     movh       m5, [src+7]
572     movh       m6, [src+10]
573     movh       m7, [src+11]
574     punpcklbw  m4, m0
575     punpcklbw  m5, m0
576     punpcklbw  m6, m0
577     punpcklbw  m7, m0
578     paddw      m5, m6 ; b1
579     paddw      m4, m7 ; a1
580     movh       m6, [src+8]
581     movh       m7, [src+9]
582     punpcklbw  m6, m0
583     punpcklbw  m7, m0
584     paddw      m6, m7 ; c1
585     mova       m7, [pw_1] ; FIXME xmm8
586     FILT_H2 m1, m2, m3, m4, m5, m6
587     FILT_PACK m1, m4, m7, 1
588     movntps    [r0+r2], m1
589     add r2, 16
590     jl .loop
591     RET
592
593 ;-----------------------------------------------------------------------------
594 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, intptr_t width );
595 ;-----------------------------------------------------------------------------
596 %macro HPEL_H 0
597 cglobal hpel_filter_h, 3,3
598     add r0, r2
599     add r1, r2
600     neg r2
601     %define src r1+r2
602     mova      m0, [src-16]
603     mova      m1, [src]
604     mova      m7, [pw_1024]
605 .loop:
606     mova      m2, [src+16]
607     ; Using unaligned loads instead of palignr is marginally slower on SB and significantly
608     ; slower on Bulldozer, despite their fast load units -- even though it would let us avoid
609     ; the repeated loads of constants for pmaddubsw.
610     palignr   m3, m1, m0, 14
611     palignr   m4, m1, m0, 15
612     palignr   m0, m2, m1, 2
613     pmaddubsw m3, [filt_mul15]
614     pmaddubsw m4, [filt_mul15]
615     pmaddubsw m0, [filt_mul51]
616     palignr   m5, m2, m1, 1
617     palignr   m6, m2, m1, 3
618     paddw     m3, m0
619     mova      m0, m1
620     pmaddubsw m1, [filt_mul20]
621     pmaddubsw m5, [filt_mul20]
622     pmaddubsw m6, [filt_mul51]
623     paddw     m3, m1
624     paddw     m4, m5
625     paddw     m4, m6
626     FILT_PACK m3, m4, m7, 5
627     pshufb    m3, [hpel_shuf]
628     mova      m1, m2
629     movntps [r0+r2], m3
630     add r2, 16
631     jl .loop
632     RET
633 %endmacro
634
635 INIT_MMX mmx2
636 HPEL_V 0
637 INIT_XMM sse2
638 HPEL_V 8
639 %if ARCH_X86_64 == 0
640 INIT_XMM sse2
641 HPEL_C
642 INIT_XMM ssse3
643 HPEL_C
644 HPEL_V 0
645 HPEL_H
646 INIT_XMM avx
647 HPEL_C
648 HPEL_V 0
649 HPEL_H
650 INIT_YMM avx2
651 HPEL_V 8
652 HPEL_C
653
654 INIT_YMM avx2
655 cglobal hpel_filter_h, 3,3,8
656     add       r0, r2
657     add       r1, r2
658     neg       r2
659     %define src r1+r2
660     mova      m5, [filt_mul15]
661     mova      m6, [filt_mul20]
662     mova      m7, [filt_mul51]
663 .loop:
664     movu      m0, [src-2]
665     movu      m1, [src-1]
666     movu      m2, [src+2]
667     pmaddubsw m0, m5
668     pmaddubsw m1, m5
669     pmaddubsw m2, m7
670     paddw     m0, m2
671
672     mova      m2, [src+0]
673     movu      m3, [src+1]
674     movu      m4, [src+3]
675     pmaddubsw m2, m6
676     pmaddubsw m3, m6
677     pmaddubsw m4, m7
678     paddw     m0, m2
679     paddw     m1, m3
680     paddw     m1, m4
681
682     mova      m2, [pw_1024]
683     FILT_PACK m0, m1, m2, 5
684     pshufb    m0, [hpel_shuf]
685     movnta [r0+r2], m0
686     add       r2, mmsize
687     jl .loop
688     RET
689 %endif
690
691 %if ARCH_X86_64
692 %macro DO_FILT_V 5
693     ;The optimum prefetch distance is difficult to determine in checkasm:
694     ;any prefetch seems slower than not prefetching.
695     ;In real use, the prefetch seems to be a slight win.
696     ;+mmsize is picked somewhat arbitrarily here based on the fact that even one
697     ;loop iteration is going to take longer than the prefetch.
698     prefetcht0 [r1+r2*2+mmsize]
699 %if cpuflag(ssse3)
700     mova m1, [r3]
701     mova m2, [r3+r2]
702     mova %3, [r3+r2*2]
703     mova m3, [r1]
704     mova %1, [r1+r2]
705     mova %2, [r1+r2*2]
706     punpckhbw m4, m1, m2
707     punpcklbw m1, m2
708     punpckhbw m2, %1, %2
709     punpcklbw %1, %2
710     punpckhbw %2, m3, %3
711     punpcklbw m3, %3
712
713     pmaddubsw m1, m12
714     pmaddubsw m4, m12
715     pmaddubsw %1, m0
716     pmaddubsw m2, m0
717     pmaddubsw m3, m14
718     pmaddubsw %2, m14
719
720     paddw m1, %1
721     paddw m4, m2
722     paddw m1, m3
723     paddw m4, %2
724 %else
725     LOAD_ADD_2 m1, m4, [r3     ], [r1+r2*2], m2, m5            ; a0 / a1
726     LOAD_ADD_2 m2, m5, [r3+r2  ], [r1+r2  ], m3, m6            ; b0 / b1
727     LOAD_ADD_2 m3, m6, [r3+r2*2], [r1     ], %3, %4            ; c0 / c1
728     packuswb %3, %4
729     FILT_V2 m1, m2, m3, m4, m5, m6
730 %endif
731     add       r3, mmsize
732     add       r1, mmsize
733 %if mmsize==32
734     vinserti128 %1, m1, xm4, 1
735     vperm2i128  %2, m1, m4, q0301
736 %else
737     mova      %1, m1
738     mova      %2, m4
739 %endif
740     FILT_PACK m1, m4, m15, 5
741     movntps  [r8+r4+%5], m1
742 %endmacro
743
744 %macro FILT_C 3
745 %if mmsize==32
746     vperm2i128 m3, %2, %1, q0003
747 %endif
748     PALIGNR   m1, %2, %1, (mmsize-4), m3
749     PALIGNR   m2, %2, %1, (mmsize-2), m3
750 %if mmsize==32
751     vperm2i128 %1, %3, %2, q0003
752 %endif
753     PALIGNR   m3, %3, %2, 4, %1
754     PALIGNR   m4, %3, %2, 2, %1
755     paddw     m3, m2
756 %if mmsize==32
757     mova      m2, %1
758 %endif
759     mova      %1, %3
760     PALIGNR   %3, %3, %2, 6, m2
761     paddw     m4, %2
762     paddw     %3, m1
763     FILT_H    %3, m3, m4
764 %endmacro
765
766 %macro DO_FILT_C 4
767     FILT_C %1, %2, %3
768     FILT_C %2, %1, %4
769     FILT_PACK %3, %4, m15, 6
770 %if mmsize==32
771     vpermq %3, %3, q3120
772 %endif
773     movntps   [r5+r4], %3
774 %endmacro
775
776 %macro ADD8TO16 5
777     punpckhbw %3, %1, %5
778     punpcklbw %1, %5
779     punpcklbw %4, %2, %5
780     punpckhbw %2, %5
781     paddw     %2, %3
782     paddw     %1, %4
783 %endmacro
784
785 %macro DO_FILT_H 3
786 %if mmsize==32
787     vperm2i128 m3, %2, %1, q0003
788 %endif
789     PALIGNR   m1, %2, %1, (mmsize-2), m3
790     PALIGNR   m2, %2, %1, (mmsize-1), m3
791 %if mmsize==32
792     vperm2i128 m3, %3, %2, q0003
793 %endif
794     PALIGNR   m4, %3, %2, 1 , m3
795     PALIGNR   m5, %3, %2, 2 , m3
796     PALIGNR   m6, %3, %2, 3 , m3
797     mova      %1, %2
798 %if cpuflag(ssse3)
799     pmaddubsw m1, m12
800     pmaddubsw m2, m12
801     pmaddubsw %2, m14
802     pmaddubsw m4, m14
803     pmaddubsw m5, m0
804     pmaddubsw m6, m0
805     paddw     m1, %2
806     paddw     m2, m4
807     paddw     m1, m5
808     paddw     m2, m6
809     FILT_PACK m1, m2, m15, 5
810     pshufb    m1, [hpel_shuf]
811 %else ; ssse3, avx
812     ADD8TO16  m1, m6, m12, m3, m0 ; a
813     ADD8TO16  m2, m5, m12, m3, m0 ; b
814     ADD8TO16  %2, m4, m12, m3, m0 ; c
815     FILT_V2   m1, m2, %2, m6, m5, m4
816     FILT_PACK m1, m6, m15, 5
817 %endif
818     movntps [r0+r4], m1
819     mova      %2, %3
820 %endmacro
821
822 %macro HPEL 0
823 ;-----------------------------------------------------------------------------
824 ; void hpel_filter( uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
825 ;                   uint8_t *src, intptr_t stride, int width, int height )
826 ;-----------------------------------------------------------------------------
827 cglobal hpel_filter, 7,9,16
828     mov       r7, r3
829     sub      r5d, mmsize
830     mov       r8, r1
831     and       r7, mmsize-1
832     sub       r3, r7
833     add       r0, r5
834     add       r8, r5
835     add       r7, r5
836     add       r5, r2
837     mov       r2, r4
838     neg       r7
839     lea       r1, [r3+r2]
840     sub       r3, r2
841     sub       r3, r2
842     mov       r4, r7
843 %if cpuflag(ssse3)
844     mova      m0, [filt_mul51]
845     mova     m12, [filt_mul15]
846     mova     m14, [filt_mul20]
847     mova     m15, [pw_1024]
848 %else
849     pxor      m0, m0
850     mova     m15, [pw_16]
851 %endif
852 ;ALIGN 16
853 .loopy:
854 ; first filter_v
855     DO_FILT_V m8, m7, m13, m12, 0
856 ;ALIGN 16
857 .loopx:
858     DO_FILT_V m6, m5, m11, m12, mmsize
859 .lastx:
860 %if cpuflag(ssse3)
861     psrlw   m15, 1   ; pw_512
862 %else
863     paddw   m15, m15 ; pw_32
864 %endif
865     DO_FILT_C m9, m8, m7, m6
866 %if cpuflag(ssse3)
867     paddw   m15, m15 ; pw_1024
868 %else
869     psrlw   m15, 1   ; pw_16
870 %endif
871     mova     m7, m5
872     DO_FILT_H m10, m13, m11
873     add      r4, mmsize
874     jl .loopx
875     cmp      r4, mmsize
876     jl .lastx
877 ; setup regs for next y
878     sub      r4, r7
879     sub      r4, r2
880     sub      r1, r4
881     sub      r3, r4
882     add      r0, r2
883     add      r8, r2
884     add      r5, r2
885     mov      r4, r7
886     sub     r6d, 1
887     jg .loopy
888     sfence
889     RET
890 %endmacro
891
892 INIT_XMM sse2
893 HPEL
894 INIT_XMM ssse3
895 HPEL
896 INIT_XMM avx
897 HPEL
898 INIT_YMM avx2
899 HPEL
900 %endif ; ARCH_X86_64
901
902 %undef movntq
903 %undef movntps
904 %undef sfence
905 %endif ; !HIGH_BIT_DEPTH
906
907 ;-----------------------------------------------------------------------------
908 ; void plane_copy_core( pixel *dst, intptr_t i_dst,
909 ;                       pixel *src, intptr_t i_src, int w, int h )
910 ;-----------------------------------------------------------------------------
911 ; assumes i_dst and w are multiples of 16, and i_dst>w
912 INIT_MMX
913 cglobal plane_copy_core_mmx2, 6,7
914     FIX_STRIDES r1, r3, r4d
915 %if HIGH_BIT_DEPTH == 0
916     movsxdifnidn r4, r4d
917 %endif
918     sub    r1,  r4
919     sub    r3,  r4
920 .loopy:
921     lea   r6d, [r4-63]
922 .loopx:
923     prefetchnta [r2+256]
924     movq   m0, [r2   ]
925     movq   m1, [r2+ 8]
926     movntq [r0   ], m0
927     movntq [r0+ 8], m1
928     movq   m2, [r2+16]
929     movq   m3, [r2+24]
930     movntq [r0+16], m2
931     movntq [r0+24], m3
932     movq   m4, [r2+32]
933     movq   m5, [r2+40]
934     movntq [r0+32], m4
935     movntq [r0+40], m5
936     movq   m6, [r2+48]
937     movq   m7, [r2+56]
938     movntq [r0+48], m6
939     movntq [r0+56], m7
940     add    r2,  64
941     add    r0,  64
942     sub    r6d, 64
943     jg .loopx
944     prefetchnta [r2+256]
945     add    r6d, 63
946     jle .end16
947 .loop16:
948     movq   m0, [r2  ]
949     movq   m1, [r2+8]
950     movntq [r0  ], m0
951     movntq [r0+8], m1
952     add    r2,  16
953     add    r0,  16
954     sub    r6d, 16
955     jg .loop16
956 .end16:
957     add    r0, r1
958     add    r2, r3
959     dec    r5d
960     jg .loopy
961     sfence
962     emms
963     RET
964
965
966 %macro INTERLEAVE 4-5 ; dst, srcu, srcv, is_aligned, nt_hint
967 %if HIGH_BIT_DEPTH
968 %assign x 0
969 %rep 16/mmsize
970     mov%4     m0, [%2+(x/2)*mmsize]
971     mov%4     m1, [%3+(x/2)*mmsize]
972     punpckhwd m2, m0, m1
973     punpcklwd m0, m1
974     mov%5a    [%1+(x+0)*mmsize], m0
975     mov%5a    [%1+(x+1)*mmsize], m2
976     %assign x (x+2)
977 %endrep
978 %else
979     movq   m0, [%2]
980 %if mmsize==16
981 %ifidn %4, a
982     punpcklbw m0, [%3]
983 %else
984     movq   m1, [%3]
985     punpcklbw m0, m1
986 %endif
987     mov%5a [%1], m0
988 %else
989     movq   m1, [%3]
990     punpckhbw m2, m0, m1
991     punpcklbw m0, m1
992     mov%5a [%1+0], m0
993     mov%5a [%1+8], m2
994 %endif
995 %endif ; HIGH_BIT_DEPTH
996 %endmacro
997
998 %macro DEINTERLEAVE 6 ; dstu, dstv, src, dstv==dstu+8, shuffle constant, is aligned
999 %if HIGH_BIT_DEPTH
1000 %assign n 0
1001 %rep 16/mmsize
1002     mova     m0, [%3+(n+0)*mmsize]
1003     mova     m1, [%3+(n+1)*mmsize]
1004     psrld    m2, m0, 16
1005     psrld    m3, m1, 16
1006     pand     m0, %5
1007     pand     m1, %5
1008     packssdw m0, m1
1009     packssdw m2, m3
1010     mov%6    [%1+(n/2)*mmsize], m0
1011     mov%6    [%2+(n/2)*mmsize], m2
1012     %assign n (n+2)
1013 %endrep
1014 %else ; !HIGH_BIT_DEPTH
1015 %if mmsize==16
1016     mova   m0, [%3]
1017 %if cpuflag(ssse3)
1018     pshufb m0, %5
1019 %else
1020     mova   m1, m0
1021     pand   m0, %5
1022     psrlw  m1, 8
1023     packuswb m0, m1
1024 %endif
1025 %if %4
1026     mova   [%1], m0
1027 %else
1028     movq   [%1], m0
1029     movhps [%2], m0
1030 %endif
1031 %else
1032     mova   m0, [%3]
1033     mova   m1, [%3+8]
1034     mova   m2, m0
1035     mova   m3, m1
1036     pand   m0, %5
1037     pand   m1, %5
1038     psrlw  m2, 8
1039     psrlw  m3, 8
1040     packuswb m0, m1
1041     packuswb m2, m3
1042     mova   [%1], m0
1043     mova   [%2], m2
1044 %endif ; mmsize == 16
1045 %endif ; HIGH_BIT_DEPTH
1046 %endmacro
1047
1048 %macro PLANE_INTERLEAVE 0
1049 ;-----------------------------------------------------------------------------
1050 ; void plane_copy_interleave_core( uint8_t *dst,  intptr_t i_dst,
1051 ;                                  uint8_t *srcu, intptr_t i_srcu,
1052 ;                                  uint8_t *srcv, intptr_t i_srcv, int w, int h )
1053 ;-----------------------------------------------------------------------------
1054 ; assumes i_dst and w are multiples of 16, and i_dst>2*w
1055 cglobal plane_copy_interleave_core, 6,9
1056     mov   r6d, r6m
1057 %if HIGH_BIT_DEPTH
1058     FIX_STRIDES r1, r3, r5, r6d
1059     movifnidn r1mp, r1
1060     movifnidn r3mp, r3
1061     mov  r6m, r6d
1062 %endif
1063     lea    r0, [r0+r6*2]
1064     add    r2,  r6
1065     add    r4,  r6
1066 %if ARCH_X86_64
1067     DECLARE_REG_TMP 7,8
1068 %else
1069     DECLARE_REG_TMP 1,3
1070 %endif
1071     mov  t1, r1
1072     shr  t1, SIZEOF_PIXEL
1073     sub  t1, r6
1074     mov  t0d, r7m
1075 .loopy:
1076     mov    r6d, r6m
1077     neg    r6
1078 .prefetch:
1079     prefetchnta [r2+r6]
1080     prefetchnta [r4+r6]
1081     add    r6, 64
1082     jl .prefetch
1083     mov    r6d, r6m
1084     neg    r6
1085 .loopx:
1086     INTERLEAVE r0+r6*2+ 0*SIZEOF_PIXEL, r2+r6+0*SIZEOF_PIXEL, r4+r6+0*SIZEOF_PIXEL, u, nt
1087     INTERLEAVE r0+r6*2+16*SIZEOF_PIXEL, r2+r6+8*SIZEOF_PIXEL, r4+r6+8*SIZEOF_PIXEL, u, nt
1088     add    r6, 16*SIZEOF_PIXEL
1089     jl .loopx
1090 .pad:
1091 %assign n 0
1092 %rep SIZEOF_PIXEL
1093 %if mmsize==8
1094     movntq [r0+r6*2+(n+ 0)], m0
1095     movntq [r0+r6*2+(n+ 8)], m0
1096     movntq [r0+r6*2+(n+16)], m0
1097     movntq [r0+r6*2+(n+24)], m0
1098 %else
1099     movntdq [r0+r6*2+(n+ 0)], m0
1100     movntdq [r0+r6*2+(n+16)], m0
1101 %endif
1102     %assign n n+32
1103 %endrep
1104     add    r6, 16*SIZEOF_PIXEL
1105     cmp    r6, t1
1106     jl .pad
1107     add    r0, r1mp
1108     add    r2, r3mp
1109     add    r4, r5
1110     dec    t0d
1111     jg .loopy
1112     sfence
1113     emms
1114     RET
1115
1116 ;-----------------------------------------------------------------------------
1117 ; void store_interleave_chroma( uint8_t *dst, intptr_t i_dst, uint8_t *srcu, uint8_t *srcv, int height )
1118 ;-----------------------------------------------------------------------------
1119 cglobal store_interleave_chroma, 5,5
1120     FIX_STRIDES r1
1121 .loop:
1122     INTERLEAVE r0+ 0, r2+           0, r3+           0, a
1123     INTERLEAVE r0+r1, r2+FDEC_STRIDEB, r3+FDEC_STRIDEB, a
1124     add    r2, FDEC_STRIDEB*2
1125     add    r3, FDEC_STRIDEB*2
1126     lea    r0, [r0+r1*2]
1127     sub   r4d, 2
1128     jg .loop
1129     RET
1130 %endmacro ; PLANE_INTERLEAVE
1131
1132 %macro DEINTERLEAVE_START 0
1133 %if HIGH_BIT_DEPTH
1134     mova   m4, [pd_ffff]
1135 %elif cpuflag(ssse3)
1136     mova   m4, [deinterleave_shuf]
1137 %else
1138     mova   m4, [pw_00ff]
1139 %endif ; HIGH_BIT_DEPTH
1140 %endmacro
1141
1142 %macro PLANE_DEINTERLEAVE 0
1143 ;-----------------------------------------------------------------------------
1144 ; void plane_copy_deinterleave( pixel *dstu, intptr_t i_dstu,
1145 ;                               pixel *dstv, intptr_t i_dstv,
1146 ;                               pixel *src,  intptr_t i_src, int w, int h )
1147 ;-----------------------------------------------------------------------------
1148 cglobal plane_copy_deinterleave, 6,7
1149     DEINTERLEAVE_START
1150     mov    r6d, r6m
1151     FIX_STRIDES r1, r3, r5, r6d
1152 %if HIGH_BIT_DEPTH
1153     mov    r6m, r6d
1154 %endif
1155     add    r0,  r6
1156     add    r2,  r6
1157     lea    r4, [r4+r6*2]
1158 .loopy:
1159     mov    r6d, r6m
1160     neg    r6
1161 .loopx:
1162     DEINTERLEAVE r0+r6+0*SIZEOF_PIXEL, r2+r6+0*SIZEOF_PIXEL, r4+r6*2+ 0*SIZEOF_PIXEL, 0, m4, u
1163     DEINTERLEAVE r0+r6+8*SIZEOF_PIXEL, r2+r6+8*SIZEOF_PIXEL, r4+r6*2+16*SIZEOF_PIXEL, 0, m4, u
1164     add    r6, 16*SIZEOF_PIXEL
1165     jl .loopx
1166     add    r0, r1
1167     add    r2, r3
1168     add    r4, r5
1169     dec dword r7m
1170     jg .loopy
1171     RET
1172
1173 ;-----------------------------------------------------------------------------
1174 ; void load_deinterleave_chroma_fenc( pixel *dst, pixel *src, intptr_t i_src, int height )
1175 ;-----------------------------------------------------------------------------
1176 cglobal load_deinterleave_chroma_fenc, 4,4
1177     DEINTERLEAVE_START
1178     FIX_STRIDES r2
1179 .loop:
1180     DEINTERLEAVE r0+           0, r0+FENC_STRIDEB*1/2, r1+ 0, 1, m4, a
1181     DEINTERLEAVE r0+FENC_STRIDEB, r0+FENC_STRIDEB*3/2, r1+r2, 1, m4, a
1182     add    r0, FENC_STRIDEB*2
1183     lea    r1, [r1+r2*2]
1184     sub   r3d, 2
1185     jg .loop
1186     RET
1187
1188 ;-----------------------------------------------------------------------------
1189 ; void load_deinterleave_chroma_fdec( pixel *dst, pixel *src, intptr_t i_src, int height )
1190 ;-----------------------------------------------------------------------------
1191 cglobal load_deinterleave_chroma_fdec, 4,4
1192     DEINTERLEAVE_START
1193     FIX_STRIDES r2
1194 .loop:
1195     DEINTERLEAVE r0+           0, r0+FDEC_STRIDEB*1/2, r1+ 0, 0, m4, a
1196     DEINTERLEAVE r0+FDEC_STRIDEB, r0+FDEC_STRIDEB*3/2, r1+r2, 0, m4, a
1197     add    r0, FDEC_STRIDEB*2
1198     lea    r1, [r1+r2*2]
1199     sub   r3d, 2
1200     jg .loop
1201     RET
1202 %endmacro ; PLANE_DEINTERLEAVE
1203
1204 %macro PLANE_DEINTERLEAVE_V210 0
1205 ;-----------------------------------------------------------------------------
1206 ; void x264_plane_copy_deinterleave_v210( uint16_t *dsty, intptr_t i_dsty,
1207 ;                                         uint16_t *dstc, intptr_t i_dstc,
1208 ;                                         uint32_t *src, intptr_t i_src, int w, int h )
1209 ;-----------------------------------------------------------------------------
1210 %if ARCH_X86_64
1211 cglobal plane_copy_deinterleave_v210, 8,10,7
1212 %define src   r8
1213 %define org_w r9
1214 %define h     r7d
1215 %else
1216 cglobal plane_copy_deinterleave_v210, 7,7,7
1217 %define src   r4m
1218 %define org_w r6m
1219 %define h     dword r7m
1220 %endif
1221     FIX_STRIDES r1, r3, r6d
1222     shl    r5, 2
1223     add    r0, r6
1224     add    r2, r6
1225     neg    r6
1226     mov   src, r4
1227     mov org_w, r6
1228     mova   m2, [v210_mask]
1229     mova   m3, [v210_luma_shuf]
1230     mova   m4, [v210_chroma_shuf]
1231     mova   m5, [v210_mult] ; also functions as vpermd index for avx2
1232     pshufd m6, m5, q1102
1233
1234 ALIGN 16
1235 .loop:
1236     movu   m1, [r4]
1237     pandn  m0, m2, m1
1238     pand   m1, m2
1239     pshufb m0, m3
1240     pshufb m1, m4
1241     pmulhrsw m0, m5 ; y0 y1 y2 y3 y4 y5 __ __
1242     pmulhrsw m1, m6 ; u0 v0 u1 v1 u2 v2 __ __
1243 %if mmsize == 32
1244     vpermd m0, m5, m0
1245     vpermd m1, m5, m1
1246 %endif
1247     movu [r0+r6], m0
1248     movu [r2+r6], m1
1249     add    r4, mmsize
1250     add    r6, 3*mmsize/4
1251     jl .loop
1252     add    r0, r1
1253     add    r2, r3
1254     add   src, r5
1255     mov    r4, src
1256     mov    r6, org_w
1257     dec     h
1258     jg .loop
1259     RET
1260 %endmacro ; PLANE_DEINTERLEAVE_V210
1261
1262 %if HIGH_BIT_DEPTH
1263 INIT_MMX mmx2
1264 PLANE_INTERLEAVE
1265 INIT_MMX mmx
1266 PLANE_DEINTERLEAVE
1267 INIT_XMM sse2
1268 PLANE_INTERLEAVE
1269 PLANE_DEINTERLEAVE
1270 INIT_XMM ssse3
1271 PLANE_DEINTERLEAVE_V210
1272 INIT_XMM avx
1273 PLANE_INTERLEAVE
1274 PLANE_DEINTERLEAVE
1275 PLANE_DEINTERLEAVE_V210
1276 INIT_YMM avx2
1277 PLANE_DEINTERLEAVE_V210
1278 %else
1279 INIT_MMX mmx2
1280 PLANE_INTERLEAVE
1281 INIT_MMX mmx
1282 PLANE_DEINTERLEAVE
1283 INIT_XMM sse2
1284 PLANE_INTERLEAVE
1285 PLANE_DEINTERLEAVE
1286 INIT_XMM ssse3
1287 PLANE_DEINTERLEAVE
1288 %endif
1289
1290 ; These functions are not general-use; not only do the SSE ones require aligned input,
1291 ; but they also will fail if given a non-mod16 size.
1292 ; memzero SSE will fail for non-mod128.
1293
1294 ;-----------------------------------------------------------------------------
1295 ; void *memcpy_aligned( void *dst, const void *src, size_t n );
1296 ;-----------------------------------------------------------------------------
1297 %macro MEMCPY 0
1298 cglobal memcpy_aligned, 3,3
1299 %if mmsize == 16
1300     test r2d, 16
1301     jz .copy2
1302     mova  m0, [r1+r2-16]
1303     mova [r0+r2-16], m0
1304     sub  r2d, 16
1305 .copy2:
1306 %endif
1307     test r2d, 2*mmsize
1308     jz .copy4start
1309     mova  m0, [r1+r2-1*mmsize]
1310     mova  m1, [r1+r2-2*mmsize]
1311     mova [r0+r2-1*mmsize], m0
1312     mova [r0+r2-2*mmsize], m1
1313     sub  r2d, 2*mmsize
1314 .copy4start:
1315     test r2d, r2d
1316     jz .ret
1317 .copy4:
1318     mova  m0, [r1+r2-1*mmsize]
1319     mova  m1, [r1+r2-2*mmsize]
1320     mova  m2, [r1+r2-3*mmsize]
1321     mova  m3, [r1+r2-4*mmsize]
1322     mova [r0+r2-1*mmsize], m0
1323     mova [r0+r2-2*mmsize], m1
1324     mova [r0+r2-3*mmsize], m2
1325     mova [r0+r2-4*mmsize], m3
1326     sub  r2d, 4*mmsize
1327     jg .copy4
1328 .ret:
1329     REP_RET
1330 %endmacro
1331
1332 INIT_MMX mmx
1333 MEMCPY
1334 INIT_XMM sse
1335 MEMCPY
1336
1337 ;-----------------------------------------------------------------------------
1338 ; void *memzero_aligned( void *dst, size_t n );
1339 ;-----------------------------------------------------------------------------
1340 %macro MEMZERO 1
1341 cglobal memzero_aligned, 2,2
1342     add  r0, r1
1343     neg  r1
1344 %if mmsize == 8
1345     pxor m0, m0
1346 %else
1347     xorps m0, m0
1348 %endif
1349 .loop:
1350 %assign i 0
1351 %rep %1
1352     mova [r0 + r1 + i], m0
1353 %assign i i+mmsize
1354 %endrep
1355     add r1, mmsize*%1
1356     jl .loop
1357     RET
1358 %endmacro
1359
1360 INIT_MMX mmx
1361 MEMZERO 8
1362 INIT_XMM sse
1363 MEMZERO 8
1364 INIT_YMM avx
1365 MEMZERO 4
1366
1367 %if HIGH_BIT_DEPTH == 0
1368 ;-----------------------------------------------------------------------------
1369 ; void integral_init4h( uint16_t *sum, uint8_t *pix, intptr_t stride )
1370 ;-----------------------------------------------------------------------------
1371 %macro INTEGRAL_INIT4H 0
1372 cglobal integral_init4h, 3,4
1373     lea     r3, [r0+r2*2]
1374     add     r1, r2
1375     neg     r2
1376     pxor    m4, m4
1377 .loop:
1378     mova    m0, [r1+r2]
1379 %if mmsize==32
1380     movu    m1, [r1+r2+8]
1381 %else
1382     mova    m1, [r1+r2+16]
1383     palignr m1, m0, 8
1384 %endif
1385     mpsadbw m0, m4, 0
1386     mpsadbw m1, m4, 0
1387     paddw   m0, [r0+r2*2]
1388     paddw   m1, [r0+r2*2+mmsize]
1389     mova  [r3+r2*2   ], m0
1390     mova  [r3+r2*2+mmsize], m1
1391     add     r2, mmsize
1392     jl .loop
1393     RET
1394 %endmacro
1395
1396 INIT_XMM sse4
1397 INTEGRAL_INIT4H
1398 INIT_YMM avx2
1399 INTEGRAL_INIT4H
1400
1401 %macro INTEGRAL_INIT8H 0
1402 cglobal integral_init8h, 3,4
1403     lea     r3, [r0+r2*2]
1404     add     r1, r2
1405     neg     r2
1406     pxor    m4, m4
1407 .loop:
1408     mova    m0, [r1+r2]
1409 %if mmsize==32
1410     movu    m1, [r1+r2+8]
1411     mpsadbw m2, m0, m4, 100100b
1412     mpsadbw m3, m1, m4, 100100b
1413 %else
1414     mova    m1, [r1+r2+16]
1415     palignr m1, m0, 8
1416     mpsadbw m2, m0, m4, 100b
1417     mpsadbw m3, m1, m4, 100b
1418 %endif
1419     mpsadbw m0, m4, 0
1420     mpsadbw m1, m4, 0
1421     paddw   m0, [r0+r2*2]
1422     paddw   m1, [r0+r2*2+mmsize]
1423     paddw   m0, m2
1424     paddw   m1, m3
1425     mova  [r3+r2*2   ], m0
1426     mova  [r3+r2*2+mmsize], m1
1427     add     r2, mmsize
1428     jl .loop
1429     RET
1430 %endmacro
1431
1432 INIT_XMM sse4
1433 INTEGRAL_INIT8H
1434 INIT_XMM avx
1435 INTEGRAL_INIT8H
1436 INIT_YMM avx2
1437 INTEGRAL_INIT8H
1438 %endif ; !HIGH_BIT_DEPTH
1439
1440 %macro INTEGRAL_INIT_8V 0
1441 ;-----------------------------------------------------------------------------
1442 ; void integral_init8v( uint16_t *sum8, intptr_t stride )
1443 ;-----------------------------------------------------------------------------
1444 cglobal integral_init8v, 3,3
1445     add   r1, r1
1446     add   r0, r1
1447     lea   r2, [r0+r1*8]
1448     neg   r1
1449 .loop:
1450     mova  m0, [r2+r1]
1451     mova  m1, [r2+r1+mmsize]
1452     psubw m0, [r0+r1]
1453     psubw m1, [r0+r1+mmsize]
1454     mova  [r0+r1], m0
1455     mova  [r0+r1+mmsize], m1
1456     add   r1, 2*mmsize
1457     jl .loop
1458     RET
1459 %endmacro
1460
1461 INIT_MMX mmx
1462 INTEGRAL_INIT_8V
1463 INIT_XMM sse2
1464 INTEGRAL_INIT_8V
1465 INIT_YMM avx2
1466 INTEGRAL_INIT_8V
1467
1468 ;-----------------------------------------------------------------------------
1469 ; void integral_init4v( uint16_t *sum8, uint16_t *sum4, intptr_t stride )
1470 ;-----------------------------------------------------------------------------
1471 INIT_MMX mmx
1472 cglobal integral_init4v, 3,5
1473     shl   r2, 1
1474     lea   r3, [r0+r2*4]
1475     lea   r4, [r0+r2*8]
1476     mova  m0, [r0+r2]
1477     mova  m4, [r4+r2]
1478 .loop:
1479     mova  m1, m4
1480     psubw m1, m0
1481     mova  m4, [r4+r2-8]
1482     mova  m0, [r0+r2-8]
1483     paddw m1, m4
1484     mova  m3, [r3+r2-8]
1485     psubw m1, m0
1486     psubw m3, m0
1487     mova  [r0+r2-8], m1
1488     mova  [r1+r2-8], m3
1489     sub   r2, 8
1490     jge .loop
1491     RET
1492
1493 INIT_XMM sse2
1494 cglobal integral_init4v, 3,5
1495     shl     r2, 1
1496     add     r0, r2
1497     add     r1, r2
1498     lea     r3, [r0+r2*4]
1499     lea     r4, [r0+r2*8]
1500     neg     r2
1501 .loop:
1502     mova    m0, [r0+r2]
1503     mova    m1, [r4+r2]
1504     mova    m2, m0
1505     mova    m4, m1
1506     shufpd  m0, [r0+r2+16], 1
1507     shufpd  m1, [r4+r2+16], 1
1508     paddw   m0, m2
1509     paddw   m1, m4
1510     mova    m3, [r3+r2]
1511     psubw   m1, m0
1512     psubw   m3, m2
1513     mova  [r0+r2], m1
1514     mova  [r1+r2], m3
1515     add     r2, 16
1516     jl .loop
1517     RET
1518
1519 INIT_XMM ssse3
1520 cglobal integral_init4v, 3,5
1521     shl     r2, 1
1522     add     r0, r2
1523     add     r1, r2
1524     lea     r3, [r0+r2*4]
1525     lea     r4, [r0+r2*8]
1526     neg     r2
1527 .loop:
1528     mova    m2, [r0+r2]
1529     mova    m0, [r0+r2+16]
1530     mova    m4, [r4+r2]
1531     mova    m1, [r4+r2+16]
1532     palignr m0, m2, 8
1533     palignr m1, m4, 8
1534     paddw   m0, m2
1535     paddw   m1, m4
1536     mova    m3, [r3+r2]
1537     psubw   m1, m0
1538     psubw   m3, m2
1539     mova  [r0+r2], m1
1540     mova  [r1+r2], m3
1541     add     r2, 16
1542     jl .loop
1543     RET
1544
1545 INIT_YMM avx2
1546 cglobal integral_init4v, 3,5
1547     add     r2, r2
1548     add     r0, r2
1549     add     r1, r2
1550     lea     r3, [r0+r2*4]
1551     lea     r4, [r0+r2*8]
1552     neg     r2
1553 .loop:
1554     mova    m2, [r0+r2]
1555     movu    m1, [r4+r2+8]
1556     paddw   m0, m2, [r0+r2+8]
1557     paddw   m1, [r4+r2]
1558     mova    m3, [r3+r2]
1559     psubw   m1, m0
1560     psubw   m3, m2
1561     mova  [r0+r2], m1
1562     mova  [r1+r2], m3
1563     add     r2, 32
1564     jl .loop
1565     RET
1566
1567 %macro FILT8x4 7
1568     mova      %3, [r0+%7]
1569     mova      %4, [r0+r5+%7]
1570     pavgb     %3, %4
1571     pavgb     %4, [r0+r5*2+%7]
1572     PALIGNR   %1, %3, 1, m6
1573     PALIGNR   %2, %4, 1, m6
1574 %if cpuflag(xop)
1575     pavgb     %1, %3
1576     pavgb     %2, %4
1577 %else
1578     pavgb     %1, %3
1579     pavgb     %2, %4
1580     psrlw     %5, %1, 8
1581     psrlw     %6, %2, 8
1582     pand      %1, m7
1583     pand      %2, m7
1584 %endif
1585 %endmacro
1586
1587 %macro FILT32x4U 4
1588     mova      m1, [r0+r5]
1589     pavgb     m0, m1, [r0]
1590     movu      m3, [r0+r5+1]
1591     pavgb     m2, m3, [r0+1]
1592     pavgb     m1, [r0+r5*2]
1593     pavgb     m3, [r0+r5*2+1]
1594     pavgb     m0, m2
1595     pavgb     m1, m3
1596
1597     mova      m3, [r0+r5+mmsize]
1598     pavgb     m2, m3, [r0+mmsize]
1599     movu      m5, [r0+r5+1+mmsize]
1600     pavgb     m4, m5, [r0+1+mmsize]
1601     pavgb     m3, [r0+r5*2+mmsize]
1602     pavgb     m5, [r0+r5*2+1+mmsize]
1603     pavgb     m2, m4
1604     pavgb     m3, m5
1605
1606     pshufb    m0, m7
1607     pshufb    m1, m7
1608     pshufb    m2, m7
1609     pshufb    m3, m7
1610     punpckhqdq m4, m0, m2
1611     punpcklqdq m0, m0, m2
1612     punpckhqdq m5, m1, m3
1613     punpcklqdq m2, m1, m3
1614     vpermq    m0, m0, q3120
1615     vpermq    m1, m4, q3120
1616     vpermq    m2, m2, q3120
1617     vpermq    m3, m5, q3120
1618     mova    [%1], m0
1619     mova    [%2], m1
1620     mova    [%3], m2
1621     mova    [%4], m3
1622 %endmacro
1623
1624 %macro FILT16x2 4
1625     mova      m3, [r0+%4+mmsize]
1626     mova      m2, [r0+%4]
1627     pavgb     m3, [r0+%4+r5+mmsize]
1628     pavgb     m2, [r0+%4+r5]
1629     PALIGNR   %1, m3, 1, m6
1630     pavgb     %1, m3
1631     PALIGNR   m3, m2, 1, m6
1632     pavgb     m3, m2
1633 %if cpuflag(xop)
1634     vpperm    m5, m3, %1, m7
1635     vpperm    m3, m3, %1, m6
1636 %else
1637     psrlw     m5, m3, 8
1638     psrlw     m4, %1, 8
1639     pand      m3, m7
1640     pand      %1, m7
1641     packuswb  m3, %1
1642     packuswb  m5, m4
1643 %endif
1644     mova    [%2], m3
1645     mova    [%3], m5
1646     mova      %1, m2
1647 %endmacro
1648
1649 %macro FILT8x2U 3
1650     mova      m3, [r0+%3+8]
1651     mova      m2, [r0+%3]
1652     pavgb     m3, [r0+%3+r5+8]
1653     pavgb     m2, [r0+%3+r5]
1654     mova      m1, [r0+%3+9]
1655     mova      m0, [r0+%3+1]
1656     pavgb     m1, [r0+%3+r5+9]
1657     pavgb     m0, [r0+%3+r5+1]
1658     pavgb     m1, m3
1659     pavgb     m0, m2
1660     psrlw     m3, m1, 8
1661     psrlw     m2, m0, 8
1662     pand      m1, m7
1663     pand      m0, m7
1664     packuswb  m0, m1
1665     packuswb  m2, m3
1666     mova    [%1], m0
1667     mova    [%2], m2
1668 %endmacro
1669
1670 %macro FILT8xU 3
1671     mova      m3, [r0+%3+8]
1672     mova      m2, [r0+%3]
1673     pavgw     m3, [r0+%3+r5+8]
1674     pavgw     m2, [r0+%3+r5]
1675     movu      m1, [r0+%3+10]
1676     movu      m0, [r0+%3+2]
1677     pavgw     m1, [r0+%3+r5+10]
1678     pavgw     m0, [r0+%3+r5+2]
1679     pavgw     m1, m3
1680     pavgw     m0, m2
1681     psrld     m3, m1, 16
1682     psrld     m2, m0, 16
1683     pand      m1, m7
1684     pand      m0, m7
1685     packssdw  m0, m1
1686     packssdw  m2, m3
1687     movu    [%1], m0
1688     mova    [%2], m2
1689 %endmacro
1690
1691 %macro FILT8xA 4
1692     mova      m3, [r0+%4+mmsize]
1693     mova      m2, [r0+%4]
1694     pavgw     m3, [r0+%4+r5+mmsize]
1695     pavgw     m2, [r0+%4+r5]
1696     PALIGNR   %1, m3, 2, m6
1697     pavgw     %1, m3
1698     PALIGNR   m3, m2, 2, m6
1699     pavgw     m3, m2
1700 %if cpuflag(xop)
1701     vpperm    m5, m3, %1, m7
1702     vpperm    m3, m3, %1, m6
1703 %else
1704     psrld     m5, m3, 16
1705     psrld     m4, %1, 16
1706     pand      m3, m7
1707     pand      %1, m7
1708     packssdw  m3, %1
1709     packssdw  m5, m4
1710 %endif
1711     mova    [%2], m3
1712     mova    [%3], m5
1713     mova      %1, m2
1714 %endmacro
1715
1716 ;-----------------------------------------------------------------------------
1717 ; void frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
1718 ;                              intptr_t src_stride, intptr_t dst_stride, int width, int height )
1719 ;-----------------------------------------------------------------------------
1720 %macro FRAME_INIT_LOWRES 0
1721 cglobal frame_init_lowres_core, 6,7,(12-4*(BIT_DEPTH/9)) ; 8 for HIGH_BIT_DEPTH, 12 otherwise
1722 %if HIGH_BIT_DEPTH
1723     shl   dword r6m, 1
1724     FIX_STRIDES r5
1725     shl   dword r7m, 1
1726 %endif
1727 %if mmsize >= 16
1728     add   dword r7m, mmsize-1
1729     and   dword r7m, ~(mmsize-1)
1730 %endif
1731     ; src += 2*(height-1)*stride + 2*width
1732     mov      r6d, r8m
1733     dec      r6d
1734     imul     r6d, r5d
1735     add      r6d, r7m
1736     lea       r0, [r0+r6*2]
1737     ; dst += (height-1)*stride + width
1738     mov      r6d, r8m
1739     dec      r6d
1740     imul     r6d, r6m
1741     add      r6d, r7m
1742     add       r1, r6
1743     add       r2, r6
1744     add       r3, r6
1745     add       r4, r6
1746     ; gap = stride - width
1747     mov      r6d, r6m
1748     sub      r6d, r7m
1749     PUSH      r6
1750     %define dst_gap [rsp+gprsize]
1751     mov      r6d, r5d
1752     sub      r6d, r7m
1753     shl      r6d, 1
1754     PUSH      r6
1755     %define src_gap [rsp]
1756 %if HIGH_BIT_DEPTH
1757 %if cpuflag(xop)
1758     mova      m6, [deinterleave_shuf32a]
1759     mova      m7, [deinterleave_shuf32b]
1760 %else
1761     pcmpeqw   m7, m7
1762     psrld     m7, 16
1763 %endif
1764 .vloop:
1765     mov      r6d, r7m
1766 %ifnidn cpuname, mmx2
1767     mova      m0, [r0]
1768     mova      m1, [r0+r5]
1769     pavgw     m0, m1
1770     pavgw     m1, [r0+r5*2]
1771 %endif
1772 .hloop:
1773     sub       r0, mmsize*2
1774     sub       r1, mmsize
1775     sub       r2, mmsize
1776     sub       r3, mmsize
1777     sub       r4, mmsize
1778 %ifidn cpuname, mmx2
1779     FILT8xU r1, r2, 0
1780     FILT8xU r3, r4, r5
1781 %else
1782     FILT8xA m0, r1, r2, 0
1783     FILT8xA m1, r3, r4, r5
1784 %endif
1785     sub      r6d, mmsize
1786     jg .hloop
1787 %else ; !HIGH_BIT_DEPTH
1788 %if cpuflag(avx2)
1789     mova      m7, [deinterleave_shuf]
1790 %elif cpuflag(xop)
1791     mova      m6, [deinterleave_shuf32a]
1792     mova      m7, [deinterleave_shuf32b]
1793 %else
1794     pcmpeqb   m7, m7
1795     psrlw     m7, 8
1796 %endif
1797 .vloop:
1798     mov      r6d, r7m
1799 %ifnidn cpuname, mmx2
1800 %if mmsize <= 16
1801     mova      m0, [r0]
1802     mova      m1, [r0+r5]
1803     pavgb     m0, m1
1804     pavgb     m1, [r0+r5*2]
1805 %endif
1806 %endif
1807 .hloop:
1808     sub       r0, mmsize*2
1809     sub       r1, mmsize
1810     sub       r2, mmsize
1811     sub       r3, mmsize
1812     sub       r4, mmsize
1813 %if mmsize==32
1814     FILT32x4U r1, r2, r3, r4
1815 %elifdef m8
1816     FILT8x4   m0, m1, m2, m3, m10, m11, mmsize
1817     mova      m8, m0
1818     mova      m9, m1
1819     FILT8x4   m2, m3, m0, m1, m4, m5, 0
1820 %if cpuflag(xop)
1821     vpperm    m4, m2, m8, m7
1822     vpperm    m2, m2, m8, m6
1823     vpperm    m5, m3, m9, m7
1824     vpperm    m3, m3, m9, m6
1825 %else
1826     packuswb  m2, m8
1827     packuswb  m3, m9
1828     packuswb  m4, m10
1829     packuswb  m5, m11
1830 %endif
1831     mova    [r1], m2
1832     mova    [r2], m4
1833     mova    [r3], m3
1834     mova    [r4], m5
1835 %elifidn cpuname, mmx2
1836     FILT8x2U  r1, r2, 0
1837     FILT8x2U  r3, r4, r5
1838 %else
1839     FILT16x2  m0, r1, r2, 0
1840     FILT16x2  m1, r3, r4, r5
1841 %endif
1842     sub      r6d, mmsize
1843     jg .hloop
1844 %endif ; HIGH_BIT_DEPTH
1845 .skip:
1846     mov       r6, dst_gap
1847     sub       r0, src_gap
1848     sub       r1, r6
1849     sub       r2, r6
1850     sub       r3, r6
1851     sub       r4, r6
1852     dec    dword r8m
1853     jg .vloop
1854     ADD      rsp, 2*gprsize
1855     emms
1856     RET
1857 %endmacro ; FRAME_INIT_LOWRES
1858
1859 INIT_MMX mmx2
1860 FRAME_INIT_LOWRES
1861 %if ARCH_X86_64 == 0
1862 INIT_MMX cache32, mmx2
1863 FRAME_INIT_LOWRES
1864 %endif
1865 INIT_XMM sse2
1866 FRAME_INIT_LOWRES
1867 INIT_XMM ssse3
1868 FRAME_INIT_LOWRES
1869 INIT_XMM avx
1870 FRAME_INIT_LOWRES
1871 INIT_XMM xop
1872 FRAME_INIT_LOWRES
1873 %if HIGH_BIT_DEPTH==0
1874 INIT_YMM avx2
1875 FRAME_INIT_LOWRES
1876 %endif
1877
1878 ;-----------------------------------------------------------------------------
1879 ; void mbtree_propagate_cost( int *dst, uint16_t *propagate_in, uint16_t *intra_costs,
1880 ;                             uint16_t *inter_costs, uint16_t *inv_qscales, float *fps_factor, int len )
1881 ;-----------------------------------------------------------------------------
1882 %macro MBTREE 0
1883 cglobal mbtree_propagate_cost, 6,6,7
1884     movss     m6, [r5]
1885     mov      r5d, r6m
1886     lea       r0, [r0+r5*4]
1887     add      r5d, r5d
1888     add       r1, r5
1889     add       r2, r5
1890     add       r3, r5
1891     add       r4, r5
1892     neg       r5
1893     pxor      m4, m4
1894     shufps    m6, m6, 0
1895     mova      m5, [pw_3fff]
1896 .loop:
1897     movq      m2, [r2+r5] ; intra
1898     movq      m0, [r4+r5] ; invq
1899     movq      m3, [r3+r5] ; inter
1900     movq      m1, [r1+r5] ; prop
1901     punpcklwd m2, m4
1902     punpcklwd m0, m4
1903     pmaddwd   m0, m2
1904     pand      m3, m5
1905     punpcklwd m1, m4
1906     punpcklwd m3, m4
1907 %if cpuflag(fma4)
1908     cvtdq2ps  m0, m0
1909     cvtdq2ps  m1, m1
1910     fmaddps   m0, m0, m6, m1
1911     cvtdq2ps  m1, m2
1912     psubd     m2, m3
1913     cvtdq2ps  m2, m2
1914     rcpps     m3, m1
1915     mulps     m1, m3
1916     mulps     m0, m2
1917     addps     m2, m3, m3
1918     fnmaddps  m3, m1, m3, m2
1919     mulps     m0, m3
1920 %else
1921     cvtdq2ps  m0, m0
1922     mulps     m0, m6    ; intra*invq*fps_factor>>8
1923     cvtdq2ps  m1, m1    ; prop
1924     addps     m0, m1    ; prop + (intra*invq*fps_factor>>8)
1925     cvtdq2ps  m1, m2    ; intra
1926     psubd     m2, m3    ; intra - inter
1927     cvtdq2ps  m2, m2    ; intra - inter
1928     rcpps     m3, m1    ; 1 / intra 1st approximation
1929     mulps     m1, m3    ; intra * (1/intra 1st approx)
1930     mulps     m1, m3    ; intra * (1/intra 1st approx)^2
1931     mulps     m0, m2    ; (prop + (intra*invq*fps_factor>>8)) * (intra - inter)
1932     addps     m3, m3    ; 2 * (1/intra 1st approx)
1933     subps     m3, m1    ; 2nd approximation for 1/intra
1934     mulps     m0, m3    ; / intra
1935 %endif
1936     cvtps2dq  m0, m0
1937     mova [r0+r5*2], m0
1938     add       r5, 8
1939     jl .loop
1940     RET
1941 %endmacro
1942
1943 INIT_XMM sse2
1944 MBTREE
1945 ; Bulldozer only has a 128-bit float unit, so the AVX version of this function is actually slower.
1946 INIT_XMM fma4
1947 MBTREE
1948
1949 %macro INT16_UNPACK 1
1950     punpckhwd   xm4, xm%1, xm7
1951     punpcklwd  xm%1, xm7
1952     vinsertf128 m%1, m%1, xm4, 1
1953 %endmacro
1954
1955 ; FIXME: align loads to 16 bytes
1956 %macro MBTREE_AVX 1
1957 cglobal mbtree_propagate_cost, 6,6,%1
1958     vbroadcastss m6, [r5]
1959     mov         r5d, r6m
1960     lea          r0, [r0+r5*4]
1961     add         r5d, r5d
1962     add          r1, r5
1963     add          r2, r5
1964     add          r3, r5
1965     add          r4, r5
1966     neg          r5
1967     mova        xm5, [pw_3fff]
1968 %if notcpuflag(avx2)
1969     pxor        xm7, xm7
1970 %endif
1971 .loop:
1972 %if cpuflag(avx2)
1973     pmovzxwd     m0, [r2+r5]      ; intra
1974     pmovzxwd     m1, [r4+r5]      ; invq
1975     pmovzxwd     m2, [r1+r5]      ; prop
1976     pand        xm3, xm5, [r3+r5] ; inter
1977     pmovzxwd     m3, xm3
1978     pmaddwd      m1, m0
1979     psubd        m4, m0, m3
1980     cvtdq2ps     m0, m0
1981     cvtdq2ps     m1, m1
1982     cvtdq2ps     m2, m2
1983     cvtdq2ps     m4, m4
1984     fmaddps      m1, m1, m6, m2
1985     rcpps        m3, m0
1986     mulps        m2, m0, m3
1987     mulps        m1, m4
1988     addps        m4, m3, m3
1989     fnmaddps     m4, m2, m3, m4
1990     mulps        m1, m4
1991 %else
1992     movu        xm0, [r2+r5]
1993     movu        xm1, [r4+r5]
1994     movu        xm2, [r1+r5]
1995     pand        xm3, xm5, [r3+r5]
1996     INT16_UNPACK 0
1997     INT16_UNPACK 1
1998     INT16_UNPACK 2
1999     INT16_UNPACK 3
2000     cvtdq2ps     m0, m0
2001     cvtdq2ps     m1, m1
2002     cvtdq2ps     m2, m2
2003     cvtdq2ps     m3, m3
2004     mulps        m1, m0
2005     subps        m4, m0, m3
2006     mulps        m1, m6         ; intra*invq*fps_factor>>8
2007     addps        m1, m2         ; prop + (intra*invq*fps_factor>>8)
2008     rcpps        m3, m0         ; 1 / intra 1st approximation
2009     mulps        m2, m0, m3     ; intra * (1/intra 1st approx)
2010     mulps        m2, m3         ; intra * (1/intra 1st approx)^2
2011     mulps        m1, m4         ; (prop + (intra*invq*fps_factor>>8)) * (intra - inter)
2012     addps        m3, m3         ; 2 * (1/intra 1st approx)
2013     subps        m3, m2         ; 2nd approximation for 1/intra
2014     mulps        m1, m3         ; / intra
2015 %endif
2016     vcvtps2dq    m1, m1
2017     mova  [r0+r5*2], m1
2018     add          r5, 16
2019     jl .loop
2020     RET
2021 %endmacro
2022
2023 INIT_YMM avx
2024 MBTREE_AVX 8
2025 INIT_YMM avx2,fma3
2026 MBTREE_AVX 7