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