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