]> git.sesse.net Git - x264/blob - common/x86/mc-a2.asm
BMI1 decimate functions
[x264] / common / x86 / mc-a2.asm
1 ;*****************************************************************************
2 ;* mc-a2.asm: x86 motion compensation
3 ;*****************************************************************************
4 ;* Copyright (C) 2005-2012 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
34
35 filt_mul20: times 16 db 20
36 filt_mul15: times 8 db 1, -5
37 filt_mul51: times 8 db -5, 1
38 hpel_shuf: db 0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15
39 deinterleave_shuf: 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     REP_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     REP_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     REP_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     mova      [r2+r4*2], m1
361     mova      [r2+r4*2+mmsize], m4
362     FILT_PACK m1, m4, 5, m7
363     movnta    [r0+r4], m1
364     add r1, mmsize
365     add r5, mmsize
366     add r4, mmsize
367     jl .loop
368     REP_RET
369 %endmacro
370
371 ;-----------------------------------------------------------------------------
372 ; void hpel_filter_c( uint8_t *dst, int16_t *buf, intptr_t width );
373 ;-----------------------------------------------------------------------------
374 INIT_MMX
375 cglobal hpel_filter_c_mmx2, 3,3
376     add r0, r2
377     lea r1, [r1+r2*2]
378     neg r2
379     %define src r1+r2*2
380     movq m7, [pw_32]
381 .loop:
382     movq   m1, [src-4]
383     movq   m2, [src-2]
384     movq   m3, [src  ]
385     movq   m4, [src+4]
386     movq   m5, [src+6]
387     paddw  m3, [src+2]  ; c0
388     paddw  m2, m4       ; b0
389     paddw  m1, m5       ; a0
390     movq   m6, [src+8]
391     paddw  m4, [src+14] ; a1
392     paddw  m5, [src+12] ; b1
393     paddw  m6, [src+10] ; c1
394     FILT_H2 m1, m2, m3, m4, m5, m6
395     FILT_PACK m1, m4, 6, m7
396     movntq [r0+r2], m1
397     add r2, 8
398     jl .loop
399     REP_RET
400
401 ;-----------------------------------------------------------------------------
402 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, intptr_t width );
403 ;-----------------------------------------------------------------------------
404 cglobal hpel_filter_h_mmx2, 3,3
405     add r0, r2
406     add r1, r2
407     neg r2
408     %define src r1+r2
409     pxor m0, m0
410 .loop:
411     movd       m1, [src-2]
412     movd       m2, [src-1]
413     movd       m3, [src  ]
414     movd       m6, [src+1]
415     movd       m4, [src+2]
416     movd       m5, [src+3]
417     punpcklbw  m1, m0
418     punpcklbw  m2, m0
419     punpcklbw  m3, m0
420     punpcklbw  m6, m0
421     punpcklbw  m4, m0
422     punpcklbw  m5, m0
423     paddw      m3, m6 ; c0
424     paddw      m2, m4 ; b0
425     paddw      m1, m5 ; a0
426     movd       m7, [src+7]
427     movd       m6, [src+6]
428     punpcklbw  m7, m0
429     punpcklbw  m6, m0
430     paddw      m4, m7 ; c1
431     paddw      m5, m6 ; b1
432     movd       m7, [src+5]
433     movd       m6, [src+4]
434     punpcklbw  m7, m0
435     punpcklbw  m6, m0
436     paddw      m6, m7 ; a1
437     movq       m7, [pw_1]
438     FILT_H2 m1, m2, m3, m4, m5, m6
439     FILT_PACK m1, m4, 1, m7
440     movntq     [r0+r2], m1
441     add r2, 8
442     jl .loop
443     REP_RET
444
445 INIT_XMM
446
447 %macro HPEL_C 0
448 ;-----------------------------------------------------------------------------
449 ; void hpel_filter_c( uint8_t *dst, int16_t *buf, intptr_t width );
450 ;-----------------------------------------------------------------------------
451 cglobal hpel_filter_c, 3,3,9
452     add r0, r2
453     lea r1, [r1+r2*2]
454     neg r2
455     %define src r1+r2*2
456 %ifnidn cpuname, sse2
457     mova    m7, [pw_32]
458     %define tpw_32 m7
459 %elif ARCH_X86_64
460     mova    m8, [pw_32]
461     %define tpw_32 m8
462 %else
463     %define tpw_32 [pw_32]
464 %endif
465 ; This doesn't seem to be faster (with AVX) on Sandy Bridge or Bulldozer...
466 %if cpuflag(misalign)
467 .loop:
468     movu    m4, [src-4]
469     movu    m5, [src-2]
470     mova    m6, [src]
471     movu    m3, [src+12]
472     movu    m2, [src+14]
473     mova    m1, [src+16]
474     paddw   m4, [src+6]
475     paddw   m5, [src+4]
476     paddw   m6, [src+2]
477     paddw   m3, [src+22]
478     paddw   m2, [src+20]
479     paddw   m1, [src+18]
480     FILT_H2 m4, m5, m6, m3, m2, m1
481 %else
482     mova      m0, [src-16]
483     mova      m1, [src]
484 .loop:
485     mova      m2, [src+16]
486     PALIGNR   m4, m1, m0, 12, m7
487     PALIGNR   m5, m1, m0, 14, m0
488     PALIGNR   m0, m2, m1, 6, m7
489     paddw     m4, m0
490     PALIGNR   m0, m2, m1, 4, m7
491     paddw     m5, m0
492     PALIGNR   m6, m2, m1, 2, m7
493     paddw     m6, m1
494     FILT_H    m4, m5, m6
495
496     mova      m0, m2
497     mova      m5, m2
498     PALIGNR   m2, m1, 12, m7
499     PALIGNR   m5, m1, 14, m1
500     mova      m1, [src+32]
501     PALIGNR   m3, m1, m0, 6, m7
502     paddw     m3, m2
503     PALIGNR   m6, m1, m0, 4, m7
504     paddw     m5, m6
505     PALIGNR   m6, m1, m0, 2, m7
506     paddw     m6, m0
507     FILT_H    m3, m5, m6
508 %endif
509     FILT_PACK m4, m3, 6, tpw_32
510     movntps [r0+r2], m4
511     add r2, 16
512     jl .loop
513     REP_RET
514 %endmacro
515
516 ;-----------------------------------------------------------------------------
517 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, intptr_t width );
518 ;-----------------------------------------------------------------------------
519 cglobal hpel_filter_h_sse2, 3,3,8
520     add r0, r2
521     add r1, r2
522     neg r2
523     %define src r1+r2
524     pxor m0, m0
525 .loop:
526     movh       m1, [src-2]
527     movh       m2, [src-1]
528     movh       m3, [src  ]
529     movh       m4, [src+1]
530     movh       m5, [src+2]
531     movh       m6, [src+3]
532     punpcklbw  m1, m0
533     punpcklbw  m2, m0
534     punpcklbw  m3, m0
535     punpcklbw  m4, m0
536     punpcklbw  m5, m0
537     punpcklbw  m6, m0
538     paddw      m3, m4 ; c0
539     paddw      m2, m5 ; b0
540     paddw      m1, m6 ; a0
541     movh       m4, [src+6]
542     movh       m5, [src+7]
543     movh       m6, [src+10]
544     movh       m7, [src+11]
545     punpcklbw  m4, m0
546     punpcklbw  m5, m0
547     punpcklbw  m6, m0
548     punpcklbw  m7, m0
549     paddw      m5, m6 ; b1
550     paddw      m4, m7 ; a1
551     movh       m6, [src+8]
552     movh       m7, [src+9]
553     punpcklbw  m6, m0
554     punpcklbw  m7, m0
555     paddw      m6, m7 ; c1
556     mova       m7, [pw_1] ; FIXME xmm8
557     FILT_H2 m1, m2, m3, m4, m5, m6
558     FILT_PACK m1, m4, 1, m7
559     movntps    [r0+r2], m1
560     add r2, 16
561     jl .loop
562     REP_RET
563
564 ;-----------------------------------------------------------------------------
565 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, intptr_t width );
566 ;-----------------------------------------------------------------------------
567 %macro HPEL_H 0
568 cglobal hpel_filter_h, 3,3
569     add r0, r2
570     add r1, r2
571     neg r2
572     %define src r1+r2
573     mova      m0, [src-16]
574     mova      m1, [src]
575     mova      m7, [pw_16]
576 .loop:
577     mova      m2, [src+16]
578     ; Using unaligned loads instead of palignr is marginally slower on SB and significantly
579     ; slower on Bulldozer, despite their fast load units -- even though it would let us avoid
580     ; the repeated loads of constants for pmaddubsw.
581     palignr   m3, m1, m0, 14
582     palignr   m4, m1, m0, 15
583     palignr   m0, m2, m1, 2
584     pmaddubsw m3, [filt_mul15]
585     pmaddubsw m4, [filt_mul15]
586     pmaddubsw m0, [filt_mul51]
587     palignr   m5, m2, m1, 1
588     palignr   m6, m2, m1, 3
589     paddw     m3, m0
590     mova      m0, m1
591     pmaddubsw m1, [filt_mul20]
592     pmaddubsw m5, [filt_mul20]
593     pmaddubsw m6, [filt_mul51]
594     paddw     m3, m1
595     paddw     m4, m5
596     paddw     m4, m6
597     FILT_PACK m3, m4, 5, m7
598     pshufb    m3, [hpel_shuf]
599     mova      m1, m2
600     movntps [r0+r2], m3
601     add r2, 16
602     jl .loop
603     REP_RET
604 %endmacro
605
606 INIT_MMX mmx2
607 HPEL_V 0
608 INIT_XMM sse2
609 HPEL_V 8
610 INIT_XMM sse2, misalign
611 HPEL_C
612 %if ARCH_X86_64 == 0
613 INIT_XMM sse2
614 HPEL_C
615 INIT_XMM ssse3
616 HPEL_C
617 HPEL_V 0
618 HPEL_H
619 INIT_XMM avx
620 HPEL_C
621 HPEL_V 0
622 HPEL_H
623 %endif
624
625 %if ARCH_X86_64
626 %macro DO_FILT_V 5
627     ;The optimum prefetch distance is difficult to determine in checkasm:
628     ;any prefetch seems slower than not prefetching.
629     ;In real use, the prefetch seems to be a slight win.
630     ;+16 is picked somewhat arbitrarily here based on the fact that even one
631     ;loop iteration is going to take longer than the prefetch.
632     prefetcht0 [r1+r2*2+16]
633 %if cpuflag(ssse3)
634     mova m1, [r3]
635     mova m2, [r3+r2]
636     mova %3, [r3+r2*2]
637     mova m3, [r1]
638     mova %1, [r1+r2]
639     mova %2, [r1+r2*2]
640     punpckhbw m4, m1, m2
641     punpcklbw m1, m2
642     punpckhbw m2, %1, %2
643     punpcklbw %1, %2
644     punpckhbw %2, m3, %3
645     punpcklbw m3, %3
646
647     pmaddubsw m1, m12
648     pmaddubsw m4, m12
649     pmaddubsw %1, m0
650     pmaddubsw m2, m0
651     pmaddubsw m3, m14
652     pmaddubsw %2, m14
653
654     paddw m1, %1
655     paddw m4, m2
656     paddw m1, m3
657     paddw m4, %2
658 %else
659     LOAD_ADD_2 m1, m4, [r3     ], [r1+r2*2], m2, m5            ; a0 / a1
660     LOAD_ADD_2 m2, m5, [r3+r2  ], [r1+r2  ], m3, m6            ; b0 / b1
661     LOAD_ADD_2 m3, m6, [r3+r2*2], [r1     ], %3, %4            ; c0 / c1
662     packuswb %3, %4
663     FILT_V2 m1, m2, m3, m4, m5, m6
664 %endif
665     add       r3, 16
666     add       r1, 16
667     mova      %1, m1
668     mova      %2, m4
669     FILT_PACK m1, m4, 5, m15
670     movntps  [r8+r4+%5], m1
671 %endmacro
672
673 %macro FILT_C 4
674     PALIGNR   m1, %2, %1, 12, m2
675     PALIGNR   m2, %2, %1, 14, %1
676     PALIGNR   m3, %3, %2, 4, %1
677     PALIGNR   m4, %3, %2, 2, %1
678     paddw     m3, m2
679     mova      %1, %3
680     PALIGNR   %3, %2, 6, m2
681     paddw     m4, %2
682     paddw     %3, m1
683     FILT_H    %3, m3, m4
684 %endmacro
685
686 %macro DO_FILT_C 4
687     FILT_C %1, %2, %3, 6
688     FILT_C %2, %1, %4, 6
689     FILT_PACK %3, %4, 6, m15
690     movntps   [r5+r4], %3
691 %endmacro
692
693 %macro ADD8TO16 5
694     punpckhbw %3, %1, %5
695     punpcklbw %1, %5
696     punpcklbw %4, %2, %5
697     punpckhbw %2, %5
698     paddw     %2, %3
699     paddw     %1, %4
700 %endmacro
701
702 %macro DO_FILT_H 3
703     PALIGNR   m1, %2, %1, 14, m3
704     PALIGNR   m2, %2, %1, 15, m3
705     PALIGNR   m4, %3, %2, 1 , m3
706     PALIGNR   m5, %3, %2, 2 , m3
707     PALIGNR   m6, %3, %2, 3 , m3
708     mova      %1, %2
709 %if cpuflag(ssse3)
710     pmaddubsw m1, m12
711     pmaddubsw m2, m12
712     pmaddubsw %2, m14
713     pmaddubsw m4, m14
714     pmaddubsw m5, m0
715     pmaddubsw m6, m0
716     paddw     m1, %2
717     paddw     m2, m4
718     paddw     m1, m5
719     paddw     m2, m6
720     FILT_PACK m1, m2, 5, m15
721     pshufb    m1, [hpel_shuf]
722 %else ; ssse3, avx
723     ADD8TO16  m1, m6, m12, m3, m0 ; a
724     ADD8TO16  m2, m5, m12, m3, m0 ; b
725     ADD8TO16  %2, m4, m12, m3, m0 ; c
726     FILT_V2   m1, m2, %2, m6, m5, m4
727     FILT_PACK m1, m6, 5, m15
728 %endif
729     movntps [r0+r4], m1
730     mova      %2, %3
731 %endmacro
732
733 %macro HPEL 0
734 ;-----------------------------------------------------------------------------
735 ; void hpel_filter( uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
736 ;                   uint8_t *src, intptr_t stride, int width, int height )
737 ;-----------------------------------------------------------------------------
738 cglobal hpel_filter, 7,9,16
739     mov       r7, r3
740     sub      r5d, 16
741     mov       r8, r1
742     and       r7, 15
743     sub       r3, r7
744     add       r0, r5
745     add       r8, r5
746     add       r7, r5
747     add       r5, r2
748     mov       r2, r4
749     neg       r7
750     lea       r1, [r3+r2]
751     sub       r3, r2
752     sub       r3, r2
753     mov       r4, r7
754     mova     m15, [pw_16]
755 %if cpuflag(ssse3)
756     mova      m0, [filt_mul51]
757     mova     m12, [filt_mul15]
758     mova     m14, [filt_mul20]
759 %else
760     pxor      m0, m0
761 %endif
762 ;ALIGN 16
763 .loopy:
764 ; first filter_v
765     DO_FILT_V m8, m7, m13, m12, 0
766 ;ALIGN 16
767 .loopx:
768     DO_FILT_V m6, m5, m11, m12, 16
769 .lastx:
770     paddw   m15, m15 ; pw_32
771     DO_FILT_C m9, m8, m7, m6
772     psrlw   m15, 1 ; pw_16
773     movdqa   m7, m5
774     DO_FILT_H m10, m13, m11
775     add      r4, 16
776     jl .loopx
777     cmp      r4, 16
778     jl .lastx
779 ; setup regs for next y
780     sub      r4, r7
781     sub      r4, r2
782     sub      r1, r4
783     sub      r3, r4
784     add      r0, r2
785     add      r8, r2
786     add      r5, r2
787     mov      r4, r7
788     sub     r6d, 1
789     jg .loopy
790     sfence
791     RET
792 %endmacro
793
794 INIT_XMM sse2
795 HPEL
796 INIT_XMM ssse3
797 HPEL
798 INIT_XMM avx
799 HPEL
800 %endif ; ARCH_X86_64
801
802 %undef movntq
803 %undef movntps
804 %undef sfence
805 %endif ; !HIGH_BIT_DEPTH
806
807 ;-----------------------------------------------------------------------------
808 ; void plane_copy_core( pixel *dst, intptr_t i_dst,
809 ;                       pixel *src, intptr_t i_src, int w, int h )
810 ;-----------------------------------------------------------------------------
811 ; assumes i_dst and w are multiples of 16, and i_dst>w
812 INIT_MMX
813 cglobal plane_copy_core_mmx2, 6,7
814     FIX_STRIDES r1, r3, r4d
815 %if HIGH_BIT_DEPTH == 0
816     movsxdifnidn r4, r4d
817 %endif
818     sub    r1,  r4
819     sub    r3,  r4
820 .loopy:
821     lea   r6d, [r4-63]
822 .loopx:
823     prefetchnta [r2+256]
824     movq   m0, [r2   ]
825     movq   m1, [r2+ 8]
826     movntq [r0   ], m0
827     movntq [r0+ 8], m1
828     movq   m2, [r2+16]
829     movq   m3, [r2+24]
830     movntq [r0+16], m2
831     movntq [r0+24], m3
832     movq   m4, [r2+32]
833     movq   m5, [r2+40]
834     movntq [r0+32], m4
835     movntq [r0+40], m5
836     movq   m6, [r2+48]
837     movq   m7, [r2+56]
838     movntq [r0+48], m6
839     movntq [r0+56], m7
840     add    r2,  64
841     add    r0,  64
842     sub    r6d, 64
843     jg .loopx
844     prefetchnta [r2+256]
845     add    r6d, 63
846     jle .end16
847 .loop16:
848     movq   m0, [r2  ]
849     movq   m1, [r2+8]
850     movntq [r0  ], m0
851     movntq [r0+8], m1
852     add    r2,  16
853     add    r0,  16
854     sub    r6d, 16
855     jg .loop16
856 .end16:
857     add    r0, r1
858     add    r2, r3
859     dec    r5d
860     jg .loopy
861     sfence
862     emms
863     RET
864
865
866 %macro INTERLEAVE 4-5 ; dst, srcu, srcv, is_aligned, nt_hint
867 %if HIGH_BIT_DEPTH
868 %assign x 0
869 %rep 16/mmsize
870     mov%4     m0, [%2+(x/2)*mmsize]
871     mov%4     m1, [%3+(x/2)*mmsize]
872     punpckhwd m2, m0, m1
873     punpcklwd m0, m1
874     mov%5a    [%1+(x+0)*mmsize], m0
875     mov%5a    [%1+(x+1)*mmsize], m2
876     %assign x (x+2)
877 %endrep
878 %else
879     movq   m0, [%2]
880 %if mmsize==16
881 %ifidn %4, a
882     punpcklbw m0, [%3]
883 %else
884     movq   m1, [%3]
885     punpcklbw m0, m1
886 %endif
887     mov%5a [%1], m0
888 %else
889     movq   m1, [%3]
890     punpckhbw m2, m0, m1
891     punpcklbw m0, m1
892     mov%5a [%1+0], m0
893     mov%5a [%1+8], m2
894 %endif
895 %endif ; HIGH_BIT_DEPTH
896 %endmacro
897
898 %macro DEINTERLEAVE 6 ; dstu, dstv, src, dstv==dstu+8, shuffle constant, is aligned
899 %if HIGH_BIT_DEPTH
900 %assign n 0
901 %rep 16/mmsize
902     mova     m0, [%3+(n+0)*mmsize]
903     mova     m1, [%3+(n+1)*mmsize]
904     psrld    m2, m0, 16
905     psrld    m3, m1, 16
906     pand     m0, %5
907     pand     m1, %5
908     packssdw m0, m1
909     packssdw m2, m3
910     mov%6    [%1+(n/2)*mmsize], m0
911     mov%6    [%2+(n/2)*mmsize], m2
912     %assign n (n+2)
913 %endrep
914 %else ; !HIGH_BIT_DEPTH
915 %if mmsize==16
916     mova   m0, [%3]
917 %if cpuflag(ssse3)
918     pshufb m0, %5
919 %else
920     mova   m1, m0
921     pand   m0, %5
922     psrlw  m1, 8
923     packuswb m0, m1
924 %endif
925 %if %4
926     mova   [%1], m0
927 %else
928     movq   [%1], m0
929     movhps [%2], m0
930 %endif
931 %else
932     mova   m0, [%3]
933     mova   m1, [%3+8]
934     mova   m2, m0
935     mova   m3, m1
936     pand   m0, %5
937     pand   m1, %5
938     psrlw  m2, 8
939     psrlw  m3, 8
940     packuswb m0, m1
941     packuswb m2, m3
942     mova   [%1], m0
943     mova   [%2], m2
944 %endif ; mmsize == 16
945 %endif ; HIGH_BIT_DEPTH
946 %endmacro
947
948 %macro PLANE_INTERLEAVE 0
949 ;-----------------------------------------------------------------------------
950 ; void plane_copy_interleave_core( uint8_t *dst,  intptr_t i_dst,
951 ;                                  uint8_t *srcu, intptr_t i_srcu,
952 ;                                  uint8_t *srcv, intptr_t i_srcv, int w, int h )
953 ;-----------------------------------------------------------------------------
954 ; assumes i_dst and w are multiples of 16, and i_dst>2*w
955 cglobal plane_copy_interleave_core, 6,9
956     mov   r6d, r6m
957 %if HIGH_BIT_DEPTH
958     FIX_STRIDES r1, r3, r5, r6d
959     movifnidn r1mp, r1
960     movifnidn r3mp, r3
961     mov  r6m, r6d
962 %endif
963     lea    r0, [r0+r6*2]
964     add    r2,  r6
965     add    r4,  r6
966 %if ARCH_X86_64
967     DECLARE_REG_TMP 7,8
968 %else
969     DECLARE_REG_TMP 1,3
970 %endif
971     mov  t1, r1
972     shr  t1, SIZEOF_PIXEL
973     sub  t1, r6
974     mov  t0d, r7m
975 .loopy:
976     mov    r6d, r6m
977     neg    r6
978 .prefetch:
979     prefetchnta [r2+r6]
980     prefetchnta [r4+r6]
981     add    r6, 64
982     jl .prefetch
983     mov    r6d, r6m
984     neg    r6
985 .loopx:
986     INTERLEAVE r0+r6*2+ 0*SIZEOF_PIXEL, r2+r6+0*SIZEOF_PIXEL, r4+r6+0*SIZEOF_PIXEL, u, nt
987     INTERLEAVE r0+r6*2+16*SIZEOF_PIXEL, r2+r6+8*SIZEOF_PIXEL, r4+r6+8*SIZEOF_PIXEL, u, nt
988     add    r6, 16*SIZEOF_PIXEL
989     jl .loopx
990 .pad:
991 %assign n 0
992 %rep SIZEOF_PIXEL
993 %if mmsize==8
994     movntq [r0+r6*2+(n+ 0)], m0
995     movntq [r0+r6*2+(n+ 8)], m0
996     movntq [r0+r6*2+(n+16)], m0
997     movntq [r0+r6*2+(n+24)], m0
998 %else
999     movntdq [r0+r6*2+(n+ 0)], m0
1000     movntdq [r0+r6*2+(n+16)], m0
1001 %endif
1002     %assign n n+32
1003 %endrep
1004     add    r6, 16*SIZEOF_PIXEL
1005     cmp    r6, t1
1006     jl .pad
1007     add    r0, r1mp
1008     add    r2, r3mp
1009     add    r4, r5
1010     dec    t0d
1011     jg .loopy
1012     sfence
1013     emms
1014     RET
1015
1016 ;-----------------------------------------------------------------------------
1017 ; void store_interleave_chroma( uint8_t *dst, intptr_t i_dst, uint8_t *srcu, uint8_t *srcv, int height )
1018 ;-----------------------------------------------------------------------------
1019 cglobal store_interleave_chroma, 5,5
1020     FIX_STRIDES r1
1021 .loop:
1022     INTERLEAVE r0+ 0, r2+           0, r3+           0, a
1023     INTERLEAVE r0+r1, r2+FDEC_STRIDEB, r3+FDEC_STRIDEB, a
1024     add    r2, FDEC_STRIDEB*2
1025     add    r3, FDEC_STRIDEB*2
1026     lea    r0, [r0+r1*2]
1027     sub   r4d, 2
1028     jg .loop
1029     REP_RET
1030 %endmacro ; PLANE_INTERLEAVE
1031
1032 %macro DEINTERLEAVE_START 0
1033 %if HIGH_BIT_DEPTH
1034     mova   m4, [pd_ffff]
1035 %elif cpuflag(ssse3)
1036     mova   m4, [deinterleave_shuf]
1037 %else
1038     mova   m4, [pw_00ff]
1039 %endif ; HIGH_BIT_DEPTH
1040 %endmacro
1041
1042 %macro PLANE_DEINTERLEAVE 0
1043 ;-----------------------------------------------------------------------------
1044 ; void plane_copy_deinterleave( pixel *dstu, intptr_t i_dstu,
1045 ;                               pixel *dstv, intptr_t i_dstv,
1046 ;                               pixel *src,  intptr_t i_src, int w, int h )
1047 ;-----------------------------------------------------------------------------
1048 cglobal plane_copy_deinterleave, 6,7
1049     DEINTERLEAVE_START
1050     mov    r6d, r6m
1051     FIX_STRIDES r1, r3, r5, r6d
1052 %if HIGH_BIT_DEPTH
1053     mov    r6m, r6d
1054 %endif
1055     add    r0,  r6
1056     add    r2,  r6
1057     lea    r4, [r4+r6*2]
1058 .loopy:
1059     mov    r6d, r6m
1060     neg    r6
1061 .loopx:
1062     DEINTERLEAVE r0+r6+0*SIZEOF_PIXEL, r2+r6+0*SIZEOF_PIXEL, r4+r6*2+ 0*SIZEOF_PIXEL, 0, m4, u
1063     DEINTERLEAVE r0+r6+8*SIZEOF_PIXEL, r2+r6+8*SIZEOF_PIXEL, r4+r6*2+16*SIZEOF_PIXEL, 0, m4, u
1064     add    r6, 16*SIZEOF_PIXEL
1065     jl .loopx
1066     add    r0, r1
1067     add    r2, r3
1068     add    r4, r5
1069     dec dword r7m
1070     jg .loopy
1071     REP_RET
1072
1073 ;-----------------------------------------------------------------------------
1074 ; void load_deinterleave_chroma_fenc( pixel *dst, pixel *src, intptr_t i_src, int height )
1075 ;-----------------------------------------------------------------------------
1076 cglobal load_deinterleave_chroma_fenc, 4,4
1077     DEINTERLEAVE_START
1078     FIX_STRIDES r2
1079 .loop:
1080     DEINTERLEAVE r0+           0, r0+FENC_STRIDEB*1/2, r1+ 0, 1, m4, a
1081     DEINTERLEAVE r0+FENC_STRIDEB, r0+FENC_STRIDEB*3/2, r1+r2, 1, m4, a
1082     add    r0, FENC_STRIDEB*2
1083     lea    r1, [r1+r2*2]
1084     sub   r3d, 2
1085     jg .loop
1086     REP_RET
1087
1088 ;-----------------------------------------------------------------------------
1089 ; void load_deinterleave_chroma_fdec( pixel *dst, pixel *src, intptr_t i_src, int height )
1090 ;-----------------------------------------------------------------------------
1091 cglobal load_deinterleave_chroma_fdec, 4,4
1092     DEINTERLEAVE_START
1093     FIX_STRIDES r2
1094 .loop:
1095     DEINTERLEAVE r0+           0, r0+FDEC_STRIDEB*1/2, r1+ 0, 0, m4, a
1096     DEINTERLEAVE r0+FDEC_STRIDEB, r0+FDEC_STRIDEB*3/2, r1+r2, 0, m4, a
1097     add    r0, FDEC_STRIDEB*2
1098     lea    r1, [r1+r2*2]
1099     sub   r3d, 2
1100     jg .loop
1101     REP_RET
1102 %endmacro ; PLANE_DEINTERLEAVE
1103
1104 %if HIGH_BIT_DEPTH
1105 INIT_MMX mmx2
1106 PLANE_INTERLEAVE
1107 INIT_MMX mmx
1108 PLANE_DEINTERLEAVE
1109 INIT_XMM sse2
1110 PLANE_INTERLEAVE
1111 PLANE_DEINTERLEAVE
1112 INIT_XMM avx
1113 PLANE_INTERLEAVE
1114 PLANE_DEINTERLEAVE
1115 %else
1116 INIT_MMX mmx2
1117 PLANE_INTERLEAVE
1118 INIT_MMX mmx
1119 PLANE_DEINTERLEAVE
1120 INIT_XMM sse2
1121 PLANE_INTERLEAVE
1122 PLANE_DEINTERLEAVE
1123 INIT_XMM ssse3
1124 PLANE_DEINTERLEAVE
1125 %endif
1126
1127 ; These functions are not general-use; not only do the SSE ones require aligned input,
1128 ; but they also will fail if given a non-mod16 size.
1129 ; memzero SSE will fail for non-mod128.
1130
1131 ;-----------------------------------------------------------------------------
1132 ; void *memcpy_aligned( void *dst, const void *src, size_t n );
1133 ;-----------------------------------------------------------------------------
1134 INIT_MMX
1135 cglobal memcpy_aligned_mmx, 3,3
1136     test r2d, 16
1137     jz .copy32start
1138     movq mm0, [r1 + r2 - 16]
1139     movq mm1, [r1 + r2 -  8]
1140     movq [r0 + r2 - 16], mm0
1141     movq [r0 + r2 -  8], mm1
1142     sub  r2d, 16
1143 .copy32start
1144     test r2d, r2d
1145     jz .ret
1146 .copy32:
1147     movq mm0, [r1 + r2 - 32]
1148     movq mm1, [r1 + r2 - 24]
1149     movq mm2, [r1 + r2 - 16]
1150     movq mm3, [r1 + r2 -  8]
1151     movq [r0 + r2 - 32], mm0
1152     movq [r0 + r2 - 24], mm1
1153     movq [r0 + r2 - 16], mm2
1154     movq [r0 + r2 -  8], mm3
1155     sub  r2d, 32
1156     jg .copy32
1157 .ret
1158     REP_RET
1159
1160 ;-----------------------------------------------------------------------------
1161 ; void *memcpy_aligned( void *dst, const void *src, size_t n );
1162 ;-----------------------------------------------------------------------------
1163 cglobal memcpy_aligned_sse2, 3,3
1164     test r2d, 16
1165     jz .copy32
1166     movdqa xmm0, [r1 + r2 - 16]
1167     movdqa [r0 + r2 - 16], xmm0
1168     sub  r2d, 16
1169 .copy32:
1170     test r2d, 32
1171     jz .copy64start
1172     movdqa xmm0, [r1 + r2 - 32]
1173     movdqa [r0 + r2 - 32], xmm0
1174     movdqa xmm1, [r1 + r2 - 16]
1175     movdqa [r0 + r2 - 16], xmm1
1176     sub  r2d, 32
1177 .copy64start
1178     test r2d, r2d
1179     jz .ret
1180 .copy64:
1181     movdqa xmm0, [r1 + r2 - 64]
1182     movdqa [r0 + r2 - 64], xmm0
1183     movdqa xmm1, [r1 + r2 - 48]
1184     movdqa [r0 + r2 - 48], xmm1
1185     movdqa xmm2, [r1 + r2 - 32]
1186     movdqa [r0 + r2 - 32], xmm2
1187     movdqa xmm3, [r1 + r2 - 16]
1188     movdqa [r0 + r2 - 16], xmm3
1189     sub  r2d, 64
1190     jg .copy64
1191 .ret:
1192     REP_RET
1193
1194 ;-----------------------------------------------------------------------------
1195 ; void *memzero_aligned( void *dst, size_t n );
1196 ;-----------------------------------------------------------------------------
1197 %macro MEMZERO 0
1198 cglobal memzero_aligned, 2,2
1199     add  r0, r1
1200     neg  r1
1201     pxor m0, m0
1202 .loop:
1203 %assign i 0
1204 %rep 8
1205     mova [r0 + r1 + i], m0
1206 %assign i i+mmsize
1207 %endrep
1208     add r1, mmsize*8
1209     jl .loop
1210     REP_RET
1211 %endmacro
1212
1213 INIT_MMX mmx
1214 MEMZERO
1215 INIT_XMM sse2
1216 MEMZERO
1217
1218
1219
1220 %if HIGH_BIT_DEPTH == 0
1221 ;-----------------------------------------------------------------------------
1222 ; void integral_init4h( uint16_t *sum, uint8_t *pix, intptr_t stride )
1223 ;-----------------------------------------------------------------------------
1224 INIT_XMM
1225 cglobal integral_init4h_sse4, 3,4
1226     lea     r3, [r0+r2*2]
1227     add     r1, r2
1228     neg     r2
1229     pxor    m4, m4
1230 .loop:
1231     movdqa  m0, [r1+r2]
1232     movdqa  m1, [r1+r2+16]
1233     palignr m1, m0, 8
1234     mpsadbw m0, m4, 0
1235     mpsadbw m1, m4, 0
1236     paddw   m0, [r0+r2*2]
1237     paddw   m1, [r0+r2*2+16]
1238     movdqa  [r3+r2*2   ], m0
1239     movdqa  [r3+r2*2+16], m1
1240     add     r2, 16
1241     jl .loop
1242     REP_RET
1243
1244 %macro INTEGRAL_INIT8H 0
1245 cglobal integral_init8h, 3,4
1246     lea     r3, [r0+r2*2]
1247     add     r1, r2
1248     neg     r2
1249     pxor    m4, m4
1250 .loop:
1251     movdqa  m0, [r1+r2]
1252     movdqa  m1, [r1+r2+16]
1253     palignr m1, m0, 8
1254     mpsadbw m2, m0, m4, 4
1255     mpsadbw m3, m1, m4, 4
1256     mpsadbw m0, m4, 0
1257     mpsadbw m1, m4, 0
1258     paddw   m0, [r0+r2*2]
1259     paddw   m1, [r0+r2*2+16]
1260     paddw   m0, m2
1261     paddw   m1, m3
1262     movdqa  [r3+r2*2   ], m0
1263     movdqa  [r3+r2*2+16], m1
1264     add     r2, 16
1265     jl .loop
1266     REP_RET
1267 %endmacro
1268
1269 INIT_XMM sse4
1270 INTEGRAL_INIT8H
1271 INIT_XMM avx
1272 INTEGRAL_INIT8H
1273 %endif ; !HIGH_BIT_DEPTH
1274
1275 %macro INTEGRAL_INIT_8V 0
1276 ;-----------------------------------------------------------------------------
1277 ; void integral_init8v( uint16_t *sum8, intptr_t stride )
1278 ;-----------------------------------------------------------------------------
1279 cglobal integral_init8v, 3,3
1280     shl   r1, 1
1281     add   r0, r1
1282     lea   r2, [r0+r1*8]
1283     neg   r1
1284 .loop:
1285     mova  m0, [r2+r1]
1286     mova  m1, [r2+r1+mmsize]
1287     psubw m0, [r0+r1]
1288     psubw m1, [r0+r1+mmsize]
1289     mova  [r0+r1], m0
1290     mova  [r0+r1+mmsize], m1
1291     add   r1, 2*mmsize
1292     jl .loop
1293     REP_RET
1294 %endmacro
1295
1296 INIT_MMX mmx
1297 INTEGRAL_INIT_8V
1298 INIT_XMM sse2
1299 INTEGRAL_INIT_8V
1300
1301 ;-----------------------------------------------------------------------------
1302 ; void integral_init4v( uint16_t *sum8, uint16_t *sum4, intptr_t stride )
1303 ;-----------------------------------------------------------------------------
1304 INIT_MMX
1305 cglobal integral_init4v_mmx, 3,5
1306     shl   r2, 1
1307     lea   r3, [r0+r2*4]
1308     lea   r4, [r0+r2*8]
1309     mova  m0, [r0+r2]
1310     mova  m4, [r4+r2]
1311 .loop:
1312     mova  m1, m4
1313     psubw m1, m0
1314     mova  m4, [r4+r2-8]
1315     mova  m0, [r0+r2-8]
1316     paddw m1, m4
1317     mova  m3, [r3+r2-8]
1318     psubw m1, m0
1319     psubw m3, m0
1320     mova  [r0+r2-8], m1
1321     mova  [r1+r2-8], m3
1322     sub   r2, 8
1323     jge .loop
1324     REP_RET
1325
1326 INIT_XMM
1327 cglobal integral_init4v_sse2, 3,5
1328     shl     r2, 1
1329     add     r0, r2
1330     add     r1, r2
1331     lea     r3, [r0+r2*4]
1332     lea     r4, [r0+r2*8]
1333     neg     r2
1334 .loop:
1335     mova    m0, [r0+r2]
1336     mova    m1, [r4+r2]
1337     mova    m2, m0
1338     mova    m4, m1
1339     shufpd  m0, [r0+r2+16], 1
1340     shufpd  m1, [r4+r2+16], 1
1341     paddw   m0, m2
1342     paddw   m1, m4
1343     mova    m3, [r3+r2]
1344     psubw   m1, m0
1345     psubw   m3, m2
1346     mova  [r0+r2], m1
1347     mova  [r1+r2], m3
1348     add     r2, 16
1349     jl .loop
1350     REP_RET
1351
1352 cglobal integral_init4v_ssse3, 3,5
1353     shl     r2, 1
1354     add     r0, r2
1355     add     r1, r2
1356     lea     r3, [r0+r2*4]
1357     lea     r4, [r0+r2*8]
1358     neg     r2
1359 .loop:
1360     mova    m2, [r0+r2]
1361     mova    m0, [r0+r2+16]
1362     mova    m4, [r4+r2]
1363     mova    m1, [r4+r2+16]
1364     palignr m0, m2, 8
1365     palignr m1, m4, 8
1366     paddw   m0, m2
1367     paddw   m1, m4
1368     mova    m3, [r3+r2]
1369     psubw   m1, m0
1370     psubw   m3, m2
1371     mova  [r0+r2], m1
1372     mova  [r1+r2], m3
1373     add     r2, 16
1374     jl .loop
1375     REP_RET
1376
1377 %macro FILT8x4 7
1378     mova      %3, [r0+%7]
1379     mova      %4, [r0+r5+%7]
1380     pavgb     %3, %4
1381     pavgb     %4, [r0+r5*2+%7]
1382     PALIGNR   %1, %3, 1, m6
1383     PALIGNR   %2, %4, 1, m6
1384 %if cpuflag(xop)
1385     pavgb     %1, %3
1386     pavgb     %2, %4
1387 %else
1388     pavgb     %1, %3
1389     pavgb     %2, %4
1390     psrlw     %5, %1, 8
1391     psrlw     %6, %2, 8
1392     pand      %1, m7
1393     pand      %2, m7
1394 %endif
1395 %endmacro
1396
1397 %macro FILT16x2 4
1398     mova      m3, [r0+%4+mmsize]
1399     mova      m2, [r0+%4]
1400     pavgb     m3, [r0+%4+r5+mmsize]
1401     pavgb     m2, [r0+%4+r5]
1402     PALIGNR   %1, m3, 1, m6
1403     pavgb     %1, m3
1404     PALIGNR   m3, m2, 1, m6
1405     pavgb     m3, m2
1406 %if cpuflag(xop)
1407     vpperm    m5, m3, %1, m7
1408     vpperm    m3, m3, %1, m6
1409 %else
1410     psrlw     m5, m3, 8
1411     psrlw     m4, %1, 8
1412     pand      m3, m7
1413     pand      %1, m7
1414     packuswb  m3, %1
1415     packuswb  m5, m4
1416 %endif
1417     mova    [%2], m3
1418     mova    [%3], m5
1419     mova      %1, m2
1420 %endmacro
1421
1422 %macro FILT8x2U 3
1423     mova      m3, [r0+%3+8]
1424     mova      m2, [r0+%3]
1425     pavgb     m3, [r0+%3+r5+8]
1426     pavgb     m2, [r0+%3+r5]
1427     mova      m1, [r0+%3+9]
1428     mova      m0, [r0+%3+1]
1429     pavgb     m1, [r0+%3+r5+9]
1430     pavgb     m0, [r0+%3+r5+1]
1431     pavgb     m1, m3
1432     pavgb     m0, m2
1433     psrlw     m3, m1, 8
1434     psrlw     m2, m0, 8
1435     pand      m1, m7
1436     pand      m0, m7
1437     packuswb  m0, m1
1438     packuswb  m2, m3
1439     mova    [%1], m0
1440     mova    [%2], m2
1441 %endmacro
1442
1443 %macro FILT8xU 3
1444     mova      m3, [r0+%3+8]
1445     mova      m2, [r0+%3]
1446     pavgw     m3, [r0+%3+r5+8]
1447     pavgw     m2, [r0+%3+r5]
1448     movu      m1, [r0+%3+10]
1449     movu      m0, [r0+%3+2]
1450     pavgw     m1, [r0+%3+r5+10]
1451     pavgw     m0, [r0+%3+r5+2]
1452     pavgw     m1, m3
1453     pavgw     m0, m2
1454     psrld     m3, m1, 16
1455     psrld     m2, m0, 16
1456     pand      m1, m7
1457     pand      m0, m7
1458     packssdw  m0, m1
1459     packssdw  m2, m3
1460     movu    [%1], m0
1461     mova    [%2], m2
1462 %endmacro
1463
1464 %macro FILT8xA 4
1465     mova      m3, [r0+%4+mmsize]
1466     mova      m2, [r0+%4]
1467     pavgw     m3, [r0+%4+r5+mmsize]
1468     pavgw     m2, [r0+%4+r5]
1469     PALIGNR   %1, m3, 2, m6
1470     pavgw     %1, m3
1471     PALIGNR   m3, m2, 2, m6
1472     pavgw     m3, m2
1473 %if cpuflag(xop)
1474     vpperm    m5, m3, %1, m7
1475     vpperm    m3, m3, %1, m6
1476 %else
1477     psrld     m5, m3, 16
1478     psrld     m4, %1, 16
1479     pand      m3, m7
1480     pand      %1, m7
1481     packssdw  m3, %1
1482     packssdw  m5, m4
1483 %endif
1484     mova    [%2], m3
1485     mova    [%3], m5
1486     mova      %1, m2
1487 %endmacro
1488
1489 ;-----------------------------------------------------------------------------
1490 ; void frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
1491 ;                              intptr_t src_stride, intptr_t dst_stride, int width, int height )
1492 ;-----------------------------------------------------------------------------
1493 %macro FRAME_INIT_LOWRES 0
1494 cglobal frame_init_lowres_core, 6,7,(12-4*(BIT_DEPTH/9)) ; 8 for HIGH_BIT_DEPTH, 12 otherwise
1495 %if HIGH_BIT_DEPTH
1496     shl   dword r6m, 1
1497     FIX_STRIDES r5
1498     shl   dword r7m, 1
1499 %endif
1500     ; src += 2*(height-1)*stride + 2*width
1501     mov      r6d, r8m
1502     dec      r6d
1503     imul     r6d, r5d
1504     add      r6d, r7m
1505     lea       r0, [r0+r6*2]
1506     ; dst += (height-1)*stride + width
1507     mov      r6d, r8m
1508     dec      r6d
1509     imul     r6d, r6m
1510     add      r6d, r7m
1511     add       r1, r6
1512     add       r2, r6
1513     add       r3, r6
1514     add       r4, r6
1515     ; gap = stride - width
1516     mov      r6d, r6m
1517     sub      r6d, r7m
1518     PUSH      r6
1519     %define dst_gap [rsp+gprsize]
1520     mov      r6d, r5d
1521     sub      r6d, r7m
1522     shl      r6d, 1
1523     PUSH      r6
1524     %define src_gap [rsp]
1525 %if HIGH_BIT_DEPTH
1526 %if cpuflag(xop)
1527     mova      m6, [deinterleave_shuf32a]
1528     mova      m7, [deinterleave_shuf32b]
1529 %else
1530     pcmpeqw   m7, m7
1531     psrld     m7, 16
1532 %endif
1533 .vloop:
1534     mov      r6d, r7m
1535 %ifnidn cpuname, mmx2
1536     mova      m0, [r0]
1537     mova      m1, [r0+r5]
1538     pavgw     m0, m1
1539     pavgw     m1, [r0+r5*2]
1540 %endif
1541 .hloop:
1542     sub       r0, mmsize*2
1543     sub       r1, mmsize
1544     sub       r2, mmsize
1545     sub       r3, mmsize
1546     sub       r4, mmsize
1547 %ifidn cpuname, mmx2
1548     FILT8xU r1, r2, 0
1549     FILT8xU r3, r4, r5
1550 %else
1551     FILT8xA m0, r1, r2, 0
1552     FILT8xA m1, r3, r4, r5
1553 %endif
1554     sub      r6d, mmsize
1555     jg .hloop
1556 %else ; !HIGH_BIT_DEPTH
1557 %if mmsize == 16
1558     ; adjust for the odd end case
1559     mov      r6d, r7m
1560     and      r6d, 8
1561     sub       r1, r6
1562     sub       r2, r6
1563     sub       r3, r6
1564     sub       r4, r6
1565     add  dst_gap, r6d
1566 %endif ; mmsize
1567 %if cpuflag(xop)
1568     mova      m6, [deinterleave_shuf32a]
1569     mova      m7, [deinterleave_shuf32b]
1570 %else
1571     pcmpeqb   m7, m7
1572     psrlw     m7, 8
1573 %endif
1574 .vloop:
1575     mov      r6d, r7m
1576 %ifnidn cpuname, mmx2
1577     mova      m0, [r0]
1578     mova      m1, [r0+r5]
1579     pavgb     m0, m1
1580     pavgb     m1, [r0+r5*2]
1581 %endif
1582 %if mmsize == 16
1583     test     r6d, 8
1584     jz .hloop
1585     sub       r0, 16
1586     FILT8x4   m0, m1, m2, m3, m4, m5, 0
1587 %if cpuflag(xop)
1588     mova      m4, m0
1589     vpperm    m0, m4, m1, m6
1590     vpperm    m1, m4, m1, m7
1591     movq    [r1], m0
1592     movq    [r2], m1
1593     movhps  [r3], m0
1594     movhps  [r4], m1
1595 %else
1596     packuswb  m0, m4
1597     packuswb  m1, m5
1598     movq    [r1], m0
1599     movhps  [r2], m0
1600     movq    [r3], m1
1601     movhps  [r4], m1
1602 %endif
1603     mova      m0, m2
1604     mova      m1, m3
1605     sub      r6d, 8
1606     jz .skip
1607 %endif ; mmsize
1608 .hloop:
1609     sub       r0, mmsize*2
1610     sub       r1, mmsize
1611     sub       r2, mmsize
1612     sub       r3, mmsize
1613     sub       r4, mmsize
1614 %ifdef m8
1615     FILT8x4   m0, m1, m2, m3, m10, m11, mmsize
1616     mova      m8, m0
1617     mova      m9, m1
1618     FILT8x4   m2, m3, m0, m1, m4, m5, 0
1619 %if cpuflag(xop)
1620     vpperm    m4, m2, m8, m7
1621     vpperm    m2, m2, m8, m6
1622     vpperm    m5, m3, m9, m7
1623     vpperm    m3, m3, m9, m6
1624 %else
1625     packuswb  m2, m8
1626     packuswb  m3, m9
1627     packuswb  m4, m10
1628     packuswb  m5, m11
1629 %endif
1630     mova    [r1], m2
1631     mova    [r2], m4
1632     mova    [r3], m3
1633     mova    [r4], m5
1634 %elifidn cpuname, mmx2
1635     FILT8x2U  r1, r2, 0
1636     FILT8x2U  r3, r4, r5
1637 %else
1638     FILT16x2  m0, r1, r2, 0
1639     FILT16x2  m1, r3, r4, r5
1640 %endif
1641     sub      r6d, mmsize
1642     jg .hloop
1643 %endif ; HIGH_BIT_DEPTH
1644 .skip:
1645     mov       r6, dst_gap
1646     sub       r0, src_gap
1647     sub       r1, r6
1648     sub       r2, r6
1649     sub       r3, r6
1650     sub       r4, r6
1651     dec    dword r8m
1652     jg .vloop
1653     ADD      rsp, 2*gprsize
1654     emms
1655     RET
1656 %endmacro ; FRAME_INIT_LOWRES
1657
1658 INIT_MMX mmx2
1659 FRAME_INIT_LOWRES
1660 %if ARCH_X86_64 == 0
1661 INIT_MMX cache32, mmx2
1662 FRAME_INIT_LOWRES
1663 %endif
1664 INIT_XMM sse2
1665 FRAME_INIT_LOWRES
1666 INIT_XMM ssse3
1667 FRAME_INIT_LOWRES
1668 INIT_XMM avx
1669 FRAME_INIT_LOWRES
1670 INIT_XMM xop
1671 FRAME_INIT_LOWRES
1672
1673 ;-----------------------------------------------------------------------------
1674 ; void mbtree_propagate_cost( int *dst, uint16_t *propagate_in, uint16_t *intra_costs,
1675 ;                             uint16_t *inter_costs, uint16_t *inv_qscales, float *fps_factor, int len )
1676 ;-----------------------------------------------------------------------------
1677 %macro MBTREE 0
1678 cglobal mbtree_propagate_cost, 7,7,7
1679     add        r6d, r6d
1680     lea         r0, [r0+r6*2]
1681     add         r1, r6
1682     add         r2, r6
1683     add         r3, r6
1684     add         r4, r6
1685     neg         r6
1686     pxor      xmm4, xmm4
1687     movss     xmm6, [r5]
1688     shufps    xmm6, xmm6, 0
1689     mulps     xmm6, [pf_inv256]
1690     movdqa    xmm5, [pw_3fff]
1691 .loop:
1692     movq      xmm2, [r2+r6] ; intra
1693     movq      xmm0, [r4+r6] ; invq
1694     movq      xmm3, [r3+r6] ; inter
1695     movq      xmm1, [r1+r6] ; prop
1696     punpcklwd xmm2, xmm4
1697     punpcklwd xmm0, xmm4
1698     pmaddwd   xmm0, xmm2
1699     pand      xmm3, xmm5
1700     punpcklwd xmm1, xmm4
1701     punpcklwd xmm3, xmm4
1702 %if cpuflag(fma4)
1703     cvtdq2ps  xmm0, xmm0
1704     cvtdq2ps  xmm1, xmm1
1705     vfmaddps  xmm0, xmm0, xmm6, xmm1
1706     cvtdq2ps  xmm1, xmm2
1707     psubd     xmm2, xmm3
1708     cvtdq2ps  xmm2, xmm2
1709     rcpps     xmm3, xmm1
1710     mulps     xmm1, xmm3
1711     mulps     xmm0, xmm2
1712     addps     xmm2, xmm3, xmm3
1713     vfnmaddps xmm3, xmm1, xmm3, xmm2
1714     mulps     xmm0, xmm3
1715 %else
1716     cvtdq2ps  xmm0, xmm0
1717     mulps     xmm0, xmm6    ; intra*invq*fps_factor>>8
1718     cvtdq2ps  xmm1, xmm1    ; prop
1719     addps     xmm0, xmm1    ; prop + (intra*invq*fps_factor>>8)
1720     cvtdq2ps  xmm1, xmm2    ; intra
1721     psubd     xmm2, xmm3    ; intra - inter
1722     cvtdq2ps  xmm2, xmm2    ; intra - inter
1723     rcpps     xmm3, xmm1    ; 1 / intra 1st approximation
1724     mulps     xmm1, xmm3    ; intra * (1/intra 1st approx)
1725     mulps     xmm1, xmm3    ; intra * (1/intra 1st approx)^2
1726     mulps     xmm0, xmm2    ; (prop + (intra*invq*fps_factor>>8)) * (intra - inter)
1727     addps     xmm3, xmm3    ; 2 * (1/intra 1st approx)
1728     subps     xmm3, xmm1    ; 2nd approximation for 1/intra
1729     mulps     xmm0, xmm3    ; / intra
1730 %endif
1731     cvtps2dq  xmm0, xmm0
1732     movdqa [r0+r6*2], xmm0
1733     add         r6, 8
1734     jl .loop
1735     REP_RET
1736 %endmacro
1737
1738 INIT_XMM sse2
1739 MBTREE
1740 ; Bulldozer only has a 128-bit float unit, so the AVX version of this function is actually slower.
1741 INIT_XMM fma4
1742 MBTREE
1743
1744 %macro INT16_TO_FLOAT 1
1745     vpunpckhwd   xmm4, xmm%1, xmm7
1746     vpunpcklwd  xmm%1, xmm7
1747     vinsertf128 ymm%1, ymm%1, xmm4, 1
1748     vcvtdq2ps   ymm%1, ymm%1
1749 %endmacro
1750
1751 ; FIXME: align loads/stores to 16 bytes
1752 INIT_YMM avx
1753 cglobal mbtree_propagate_cost, 7,7,8
1754     add           r6d, r6d
1755     lea            r0, [r0+r6*2]
1756     add            r1, r6
1757     add            r2, r6
1758     add            r3, r6
1759     add            r4, r6
1760     neg            r6
1761     vmovdqa      xmm5, [pw_3fff]
1762     vbroadcastss ymm6, [r5]
1763     vmulps       ymm6, ymm6, [pf_inv256]
1764     vpxor        xmm7, xmm7
1765 .loop:
1766     vmovdqu      xmm0, [r2+r6]       ; intra
1767     vmovdqu      xmm1, [r4+r6]       ; invq
1768     vmovdqu      xmm2, [r1+r6]       ; prop
1769     vpand        xmm3, xmm5, [r3+r6] ; inter
1770     INT16_TO_FLOAT 0
1771     INT16_TO_FLOAT 1
1772     INT16_TO_FLOAT 2
1773     INT16_TO_FLOAT 3
1774     vmulps       ymm1, ymm1, ymm0
1775     vsubps       ymm4, ymm0, ymm3
1776     vmulps       ymm1, ymm1, ymm6    ; intra*invq*fps_factor>>8
1777     vaddps       ymm1, ymm1, ymm2    ; prop + (intra*invq*fps_factor>>8)
1778     vrcpps       ymm3, ymm0          ; 1 / intra 1st approximation
1779     vmulps       ymm2, ymm0, ymm3    ; intra * (1/intra 1st approx)
1780     vmulps       ymm2, ymm2, ymm3    ; intra * (1/intra 1st approx)^2
1781     vmulps       ymm1, ymm1, ymm4    ; (prop + (intra*invq*fps_factor>>8)) * (intra - inter)
1782     vaddps       ymm3, ymm3, ymm3    ; 2 * (1/intra 1st approx)
1783     vsubps       ymm3, ymm3, ymm2    ; 2nd approximation for 1/intra
1784     vmulps       ymm1, ymm1, ymm3    ; / intra
1785     vcvtps2dq    ymm1, ymm1
1786     vmovdqu [r0+r6*2], ymm1
1787     add            r6, 16
1788     jl .loop
1789     vzeroupper
1790     RET