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