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