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