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