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