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