]> git.sesse.net Git - x264/blob - common/x86/mc-a2.asm
Faster SSSE3 hpel_filter_v
[x264] / common / x86 / mc-a2.asm
1 ;*****************************************************************************
2 ;* mc-a2.asm: h264 encoder library
3 ;*****************************************************************************
4 ;* Copyright (C) 2005-2008 x264 project
5 ;*
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>
7 ;*          Fiona Glaser <fiona@x264.com>
8 ;*          Holger Lubitz <hal@duncan.ol.sub.de>
9 ;*          Mathieu Monnier <manao@melix.net>
10 ;*
11 ;* This program is free software; you can redistribute it and/or modify
12 ;* it under the terms of the GNU General Public License as published by
13 ;* the Free Software Foundation; either version 2 of the License, or
14 ;* (at your option) any later version.
15 ;*
16 ;* This program is distributed in the hope that it will be useful,
17 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;* GNU General Public License for more details.
20 ;*
21 ;* You should have received a copy of the GNU General Public License
22 ;* along with this program; if not, write to the Free Software
23 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
24 ;*****************************************************************************
25
26 %include "x86inc.asm"
27 %include "x86util.asm"
28
29 SECTION_RODATA
30
31 filt_mul20: times 16 db 20
32 filt_mul51: times 8 db 1, -5
33
34 pw_1:  times 8 dw 1
35 pw_16: times 8 dw 16
36 pw_32: times 8 dw 32
37
38 SECTION .text
39
40 %macro LOAD_ADD 4
41     movh       %4, %3
42     movh       %1, %2
43     punpcklbw  %4, m0
44     punpcklbw  %1, m0
45     paddw      %1, %4
46 %endmacro
47
48 %macro LOAD_ADD_2 6
49     mova       %5, %3
50     mova       %1, %4
51     mova       %6, %5
52     mova       %2, %1
53     punpcklbw  %5, m0
54     punpcklbw  %1, m0
55     punpckhbw  %6, m0
56     punpckhbw  %2, m0
57     paddw      %1, %5
58     paddw      %2, %6
59 %endmacro
60
61 %macro FILT_V2 0
62     psubw  m1, m2  ; a-b
63     psubw  m4, m5
64     psubw  m2, m3  ; b-c
65     psubw  m5, m6
66     psllw  m2, 2
67     psllw  m5, 2
68     psubw  m1, m2  ; a-5*b+4*c
69     psubw  m4, m5
70     psllw  m3, 4
71     psllw  m6, 4
72     paddw  m1, m3  ; a-5*b+20*c
73     paddw  m4, m6
74 %endmacro
75
76 %macro FILT_H 3
77     psubw  %1, %2  ; a-b
78     psraw  %1, 2   ; (a-b)/4
79     psubw  %1, %2  ; (a-b)/4-b
80     paddw  %1, %3  ; (a-b)/4-b+c
81     psraw  %1, 2   ; ((a-b)/4-b+c)/4
82     paddw  %1, %3  ; ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
83 %endmacro
84
85 %macro FILT_H2 6
86     psubw  %1, %2
87     psubw  %4, %5
88     psraw  %1, 2
89     psraw  %4, 2
90     psubw  %1, %2
91     psubw  %4, %5
92     paddw  %1, %3
93     paddw  %4, %6
94     psraw  %1, 2
95     psraw  %4, 2
96     paddw  %1, %3
97     paddw  %4, %6
98 %endmacro
99
100 %macro FILT_PACK 3
101     paddw     %1, m7
102     paddw     %2, m7
103     psraw     %1, %3
104     psraw     %2, %3
105     packuswb  %1, %2
106 %endmacro
107
108 INIT_MMX
109
110 %macro HPEL_V 1-2 0
111 ;-----------------------------------------------------------------------------
112 ; void x264_hpel_filter_v_mmxext( uint8_t *dst, uint8_t *src, int16_t *buf, int stride, int width );
113 ;-----------------------------------------------------------------------------
114 cglobal x264_hpel_filter_v_%1, 5,6,%2
115 %ifdef WIN64
116     movsxd   r4, r4d
117 %endif
118     lea r5, [r1+r3]
119     sub r1, r3
120     sub r1, r3
121     add r0, r4
122     lea r2, [r2+r4*2]
123     neg r4
124 %ifnidn %1, ssse3
125     pxor m0, m0
126 %else
127     mova m0, [filt_mul51 GLOBAL]
128 %endif
129 .loop:
130 %ifidn %1, ssse3
131     mova m1, [r1]
132     mova m4, [r1+r3]
133     mova m2, [r5+r3*2]
134     mova m5, [r5+r3]
135     mova m3, [r1+r3*2]
136     mova m6, [r5]
137     SBUTTERFLY bw, 1, 4, 7
138     SBUTTERFLY bw, 2, 5, 7
139     SBUTTERFLY bw, 3, 6, 7
140     pmaddubsw m1, m0
141     pmaddubsw m4, m0
142     pmaddubsw m2, m0
143     pmaddubsw m5, m0
144     pmaddubsw m3, [filt_mul20 GLOBAL]
145     pmaddubsw m6, [filt_mul20 GLOBAL]
146     paddw  m1, m2
147     paddw  m4, m5
148     paddw  m1, m3
149     paddw  m4, m6
150 %else
151     LOAD_ADD_2 m1, m4, [r1     ], [r5+r3*2], m6, m7            ; a0 / a1
152     LOAD_ADD_2 m2, m5, [r1+r3  ], [r5+r3  ], m6, m7            ; b0 / b1
153     LOAD_ADD   m3,     [r1+r3*2], [r5     ], m7                ; c0
154     LOAD_ADD   m6,     [r1+r3*2+mmsize/2], [r5+mmsize/2], m7 ; c1
155     FILT_V2
156 %endif
157     mova      m7, [pw_16 GLOBAL]
158     mova      [r2+r4*2], m1
159     mova      [r2+r4*2+mmsize], m4
160     paddw     m1, m7
161     paddw     m4, m7
162     psraw     m1, 5
163     psraw     m4, 5
164     packuswb  m1, m4
165     mova     [r0+r4], m1
166     add r1, mmsize
167     add r5, mmsize
168     add r4, mmsize
169     jl .loop
170     REP_RET
171 %endmacro
172 HPEL_V mmxext
173
174 ;-----------------------------------------------------------------------------
175 ; void x264_hpel_filter_c_mmxext( uint8_t *dst, int16_t *buf, int width );
176 ;-----------------------------------------------------------------------------
177 cglobal x264_hpel_filter_c_mmxext, 3,3
178     add r0, r2
179     lea r1, [r1+r2*2]
180     neg r2
181     %define src r1+r2*2
182     movq m7, [pw_32 GLOBAL]
183 .loop:
184     movq   m1, [src-4]
185     movq   m2, [src-2]
186     movq   m3, [src  ]
187     movq   m4, [src+4]
188     movq   m5, [src+6]
189     paddw  m3, [src+2]  ; c0
190     paddw  m2, m4       ; b0
191     paddw  m1, m5       ; a0
192     movq   m6, [src+8]
193     paddw  m4, [src+14] ; a1
194     paddw  m5, [src+12] ; b1
195     paddw  m6, [src+10] ; c1
196     FILT_H2 m1, m2, m3, m4, m5, m6
197     FILT_PACK m1, m4, 6
198     movntq [r0+r2], m1
199     add r2, 8
200     jl .loop
201     REP_RET
202
203 ;-----------------------------------------------------------------------------
204 ; void x264_hpel_filter_h_mmxext( uint8_t *dst, uint8_t *src, int width );
205 ;-----------------------------------------------------------------------------
206 cglobal x264_hpel_filter_h_mmxext, 3,3
207     add r0, r2
208     add r1, r2
209     neg r2
210     %define src r1+r2
211     pxor m0, m0
212 .loop:
213     movd       m1, [src-2]
214     movd       m2, [src-1]
215     movd       m3, [src  ]
216     movd       m6, [src+1]
217     movd       m4, [src+2]
218     movd       m5, [src+3]
219     punpcklbw  m1, m0
220     punpcklbw  m2, m0
221     punpcklbw  m3, m0
222     punpcklbw  m6, m0
223     punpcklbw  m4, m0
224     punpcklbw  m5, m0
225     paddw      m3, m6 ; c0
226     paddw      m2, m4 ; b0
227     paddw      m1, m5 ; a0
228     movd       m7, [src+7]
229     movd       m6, [src+6]
230     punpcklbw  m7, m0
231     punpcklbw  m6, m0
232     paddw      m4, m7 ; c1
233     paddw      m5, m6 ; b1
234     movd       m7, [src+5]
235     movd       m6, [src+4]
236     punpcklbw  m7, m0
237     punpcklbw  m6, m0
238     paddw      m6, m7 ; a1
239     movq       m7, [pw_1 GLOBAL]
240     FILT_H2 m1, m2, m3, m4, m5, m6
241     FILT_PACK m1, m4, 1
242     movntq     [r0+r2], m1
243     add r2, 8
244     jl .loop
245     REP_RET
246
247 INIT_XMM
248
249 %macro HPEL_C 1
250 ;-----------------------------------------------------------------------------
251 ; void x264_hpel_filter_c_sse2( uint8_t *dst, int16_t *buf, int width );
252 ;-----------------------------------------------------------------------------
253 cglobal x264_hpel_filter_c_%1, 3,3,9
254     add r0, r2
255     lea r1, [r1+r2*2]
256     neg r2
257     %define src r1+r2*2
258 %ifidn %1, ssse3
259     mova    m7, [pw_32 GLOBAL]
260     %define tpw_32 m7
261 %elifdef ARCH_X86_64
262     mova    m8, [pw_32 GLOBAL]
263     %define tpw_32 m8
264 %else
265     %define tpw_32 [pw_32 GLOBAL]
266 %endif
267 .loop:
268 %ifidn %1,sse2_misalign
269     movu    m0, [src-4]
270     movu    m1, [src-2]
271     mova    m2, [src]
272     paddw   m0, [src+6]
273     paddw   m1, [src+4]
274     paddw   m2, [src+2]
275 %else
276     mova    m6, [src-16]
277     mova    m2, [src]
278     mova    m3, [src+16]
279     mova    m0, m2
280     mova    m1, m2
281     mova    m4, m3
282     mova    m5, m3
283     PALIGNR m3, m2, 2, m7
284     PALIGNR m4, m2, 4, m7
285     PALIGNR m5, m2, 6, m7
286     PALIGNR m0, m6, 12, m7
287     PALIGNR m1, m6, 14, m7
288     paddw   m2, m3
289     paddw   m1, m4
290     paddw   m0, m5
291 %endif
292     FILT_H  m0, m1, m2
293     paddw   m0, tpw_32
294     psraw   m0, 6
295     packuswb m0, m0
296     movq [r0+r2], m0
297     add r2, 8
298     jl .loop
299     REP_RET
300 %endmacro
301
302 ;-----------------------------------------------------------------------------
303 ; void x264_hpel_filter_h_sse2( uint8_t *dst, uint8_t *src, int width );
304 ;-----------------------------------------------------------------------------
305 cglobal x264_hpel_filter_h_sse2, 3,3,8
306     add r0, r2
307     add r1, r2
308     neg r2
309     %define src r1+r2
310     pxor m0, m0
311 .loop:
312     movh       m1, [src-2]
313     movh       m2, [src-1]
314     movh       m3, [src  ]
315     movh       m4, [src+1]
316     movh       m5, [src+2]
317     movh       m6, [src+3]
318     punpcklbw  m1, m0
319     punpcklbw  m2, m0
320     punpcklbw  m3, m0
321     punpcklbw  m4, m0
322     punpcklbw  m5, m0
323     punpcklbw  m6, m0
324     paddw      m3, m4 ; c0
325     paddw      m2, m5 ; b0
326     paddw      m1, m6 ; a0
327     movh       m4, [src+6]
328     movh       m5, [src+7]
329     movh       m6, [src+10]
330     movh       m7, [src+11]
331     punpcklbw  m4, m0
332     punpcklbw  m5, m0
333     punpcklbw  m6, m0
334     punpcklbw  m7, m0
335     paddw      m5, m6 ; b1
336     paddw      m4, m7 ; a1
337     movh       m6, [src+8]
338     movh       m7, [src+9]
339     punpcklbw  m6, m0
340     punpcklbw  m7, m0
341     paddw      m6, m7 ; c1
342     mova       m7, [pw_1 GLOBAL] ; FIXME xmm8
343     FILT_H2 m1, m2, m3, m4, m5, m6
344     FILT_PACK m1, m4, 1
345     movntdq    [r0+r2], m1
346     add r2, 16
347     jl .loop
348     REP_RET
349
350 %ifndef ARCH_X86_64
351 ;-----------------------------------------------------------------------------
352 ; void x264_hpel_filter_h_ssse3( uint8_t *dst, uint8_t *src, int width );
353 ;-----------------------------------------------------------------------------
354 cglobal x264_hpel_filter_h_ssse3, 3,3
355     add r0, r2
356     add r1, r2
357     neg r2
358     %define src r1+r2
359     pxor m0, m0
360     movh m1, [src-8]
361     punpcklbw m1, m0         ; 00 -1 00 -2 00 -3 00 -4 00 -5 00 -6 00 -7 00 -8
362     movh m2, [src]
363     punpcklbw m2, m0
364     mova       m7, [pw_1 GLOBAL]
365 .loop:
366     movh       m3, [src+8]
367     punpcklbw  m3, m0
368
369     mova       m4, m2
370     palignr    m2, m1, 14
371     mova       m5, m3
372     palignr    m3, m4, 4
373     paddw      m3, m2
374
375     mova       m2, m4
376     palignr    m4, m1, 12
377     mova       m1, m5
378     palignr    m5, m2, 6
379     paddw      m5, m4
380
381     mova       m4, m1
382     palignr    m1, m2, 2
383     paddw      m1, m2
384
385     FILT_H     m5, m3, m1
386
387     movh       m1, [src+16]
388     punpcklbw  m1, m0
389
390     mova       m3, m4
391     palignr    m4, m2, 14
392     mova       m6, m1
393     palignr    m1, m3, 4
394     paddw      m1, m4
395
396     mova       m4, m3
397     palignr    m3, m2, 12
398     mova       m2, m6
399     palignr    m6, m4, 6
400     paddw      m6, m3
401
402     mova       m3, m2
403     palignr    m2, m4, 2
404     paddw      m2, m4
405
406     FILT_H m6, m1, m2
407     FILT_PACK m5, m6, 1
408     movdqa    [r0+r2], m5
409
410     add r2, 16
411     mova      m2, m3
412     mova      m1, m4
413
414     jl .loop
415     REP_RET
416 %endif
417
418 %define PALIGNR PALIGNR_MMX
419 %ifndef ARCH_X86_64
420 HPEL_C sse2
421 %endif
422 HPEL_V sse2, 8
423 HPEL_C sse2_misalign
424 %define PALIGNR PALIGNR_SSSE3
425 HPEL_C ssse3
426 HPEL_V ssse3
427
428 %ifdef ARCH_X86_64
429
430 %macro DO_FILT_V 6
431 %ifidn %6, ssse3
432     mova m1, [r3]
433     mova m2, [r3+r2]
434     mova %3, [r3+r2*2]
435     mova m3, [r1]
436     mova %4, [r1+r2]
437     mova m0, [r1+r2*2]
438     mova %2, [filt_mul51 GLOBAL]
439     mova m4, m1
440     punpcklbw m1, m2
441     punpckhbw m4, m2
442     mova m2, m0
443     punpcklbw m0, %4
444     punpckhbw m2, %4
445     mova %1, m3
446     punpcklbw m3, %3
447     punpckhbw %1, %3
448     mova %3, m3
449     mova %4, %1
450     pmaddubsw m1, %2
451     pmaddubsw m4, %2
452     pmaddubsw m0, %2
453     pmaddubsw m2, %2
454     pmaddubsw m3, [filt_mul20 GLOBAL]
455     pmaddubsw %1, [filt_mul20 GLOBAL]
456     psrlw     %3, 8
457     psrlw     %4, 8
458     paddw m1, m0
459     paddw m4, m2
460     paddw m1, m3
461     paddw m4, %1
462 %else
463     LOAD_ADD_2 m1, m4, [r3     ], [r1+r2*2], m2, m5            ; a0 / a1
464     LOAD_ADD_2 m2, m5, [r3+r2  ], [r1+r2  ], m3, m6            ; b0 / b1
465     LOAD_ADD_2 m3, m6, [r3+r2*2], [r1     ], %3, %4            ; c0 / c1
466     FILT_V2
467 %endif
468     mova      %1, m1
469     mova      %2, m4
470     paddw     m1, m15
471     paddw     m4, m15
472     add       r3, 16
473     add       r1, 16
474     psraw     m1, 5
475     psraw     m4, 5
476     packuswb  m1, m4
477     movntps  [r11+r4+%5], m1
478 %endmacro
479
480 %macro DO_FILT_H 4
481     mova      m1, %2
482     PALIGNR   m1, %1, 12, m4
483     mova      m2, %2
484     PALIGNR   m2, %1, 14, m4
485     mova      %1, %3
486     PALIGNR   %3, %2, 6, m4
487     mova      m3, %1
488     PALIGNR   m3, %2, 4, m4
489     mova      m4, %1
490     paddw     %3, m1
491     PALIGNR   m4, %2, 2, m1
492     paddw     m3, m2
493     paddw     m4, %2
494     FILT_H    %3, m3, m4
495     paddw     %3, m15
496     psraw     %3, %4
497 %endmacro
498
499 %macro DO_FILT_CC 4
500     DO_FILT_H %1, %2, %3, 6
501     DO_FILT_H %2, %1, %4, 6
502     packuswb  %3, %4
503     movntps   [r5+r4], %3
504 %endmacro
505
506 %macro DO_FILT_HH 4
507     DO_FILT_H %1, %2, %3, 1
508     DO_FILT_H %2, %1, %4, 1
509     packuswb  %3, %4
510     movntps   [r0+r4], %3
511 %endmacro
512
513 %macro DO_FILT_H2 6
514     DO_FILT_H %1, %2, %3, 6
515     psrlw    m15, 5
516     DO_FILT_H %4, %5, %6, 1
517     packuswb  %6, %3
518 %endmacro
519
520 %macro HPEL 1
521 ;-----------------------------------------------------------------------------
522 ; void x264_hpel_filter_sse2( uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
523 ;                             uint8_t *src, int stride, int width, int height)
524 ;-----------------------------------------------------------------------------
525 cglobal x264_hpel_filter_%1, 7,7,16
526 %ifdef WIN64
527     movsxd   r4, r4d
528     movsxd   r5, r5d
529 %endif
530     mov      r10, r3
531     sub       r5, 16
532     mov      r11, r1
533     and      r10, 15
534     sub       r3, r10
535     add       r0, r5
536     add      r11, r5
537     add      r10, r5
538     add       r5, r2
539     mov       r2, r4
540     neg      r10
541     lea       r1, [r3+r2]
542     sub       r3, r2
543     sub       r3, r2
544     mov       r4, r10
545 %ifidn %1, sse2
546     pxor      m0, m0
547 %endif
548     pcmpeqw  m15, m15
549     psrlw    m15, 15 ; pw_1
550     psllw    m15, 4
551 ;ALIGN 16
552 .loopy:
553 ; first filter_v
554 ; prefetching does not help here! lots of variants tested, all slower
555     DO_FILT_V m8, m7, m13, m12, 0, %1
556 ;ALIGN 16
557 .loopx:
558     DO_FILT_V m6, m5, m11, m10, 16, %1
559 .lastx:
560     paddw    m15, m15
561     DO_FILT_CC m9, m8, m7, m6
562     movdqa   m7, m12        ; not really necessary, but seems free and
563     movdqa   m6, m11         ; gives far shorter code
564     psrlw    m15, 5
565     DO_FILT_HH m14, m13, m7, m6
566     psllw    m15, 4 ; pw_16
567     movdqa   m7, m5
568     movdqa  m12, m10
569     add      r4, 16
570     jl .loopx
571     cmp      r4, 16
572     jl .lastx
573 ; setup regs for next y
574     sub      r4, r10
575     sub      r4, r2
576     sub      r1, r4
577     sub      r3, r4
578     add      r0, r2
579     add     r11, r2
580     add      r5, r2
581     mov      r4, r10
582     sub     r6d, 1
583     jg .loopy
584     sfence
585     RET
586 %endmacro
587
588 %define PALIGNR PALIGNR_MMX
589 HPEL sse2
590 %define PALIGNR PALIGNR_SSSE3
591 HPEL ssse3
592
593 %endif
594
595 cglobal x264_sfence
596     sfence
597     ret
598
599 ;-----------------------------------------------------------------------------
600 ; void x264_plane_copy_mmxext( uint8_t *dst, int i_dst,
601 ;                              uint8_t *src, int i_src, int w, int h)
602 ;-----------------------------------------------------------------------------
603 cglobal x264_plane_copy_mmxext, 6,7
604     movsxdifnidn r1, r1d
605     movsxdifnidn r3, r3d
606     add    r4d, 3
607     and    r4d, ~3
608     mov    r6d, r4d
609     and    r6d, ~15
610     sub    r1,  r6
611     sub    r3,  r6
612 .loopy:
613     mov    r6d, r4d
614     sub    r6d, 64
615     jl     .endx
616 .loopx:
617     prefetchnta [r2+256]
618     movq   mm0, [r2   ]
619     movq   mm1, [r2+ 8]
620     movq   mm2, [r2+16]
621     movq   mm3, [r2+24]
622     movq   mm4, [r2+32]
623     movq   mm5, [r2+40]
624     movq   mm6, [r2+48]
625     movq   mm7, [r2+56]
626     movntq [r0   ], mm0
627     movntq [r0+ 8], mm1
628     movntq [r0+16], mm2
629     movntq [r0+24], mm3
630     movntq [r0+32], mm4
631     movntq [r0+40], mm5
632     movntq [r0+48], mm6
633     movntq [r0+56], mm7
634     add    r2,  64
635     add    r0,  64
636     sub    r6d, 64
637     jge    .loopx
638 .endx:
639     prefetchnta [r2+256]
640     add    r6d, 48
641     jl .end16
642 .loop16:
643     movq   mm0, [r2  ]
644     movq   mm1, [r2+8]
645     movntq [r0  ], mm0
646     movntq [r0+8], mm1
647     add    r2,  16
648     add    r0,  16
649     sub    r6d, 16
650     jge    .loop16
651 .end16:
652     add    r6d, 12
653     jl .end4
654 .loop4:
655     movd   mm2, [r2+r6]
656     movd   [r0+r6], mm2
657     sub    r6d, 4
658     jge .loop4
659 .end4:
660     add    r2, r3
661     add    r0, r1
662     dec    r5d
663     jg     .loopy
664     sfence
665     emms
666     RET
667
668
669
670 ; These functions are not general-use; not only do the SSE ones require aligned input,
671 ; but they also will fail if given a non-mod16 size or a size less than 64.
672 ; memzero SSE will fail for non-mod128.
673
674 ;-----------------------------------------------------------------------------
675 ; void *x264_memcpy_aligned_mmx( void *dst, const void *src, size_t n );
676 ;-----------------------------------------------------------------------------
677 cglobal x264_memcpy_aligned_mmx, 3,3
678     test r2d, 16
679     jz .copy32
680     sub r2d, 16
681     movq mm0, [r1 + r2 + 0]
682     movq mm1, [r1 + r2 + 8]
683     movq [r0 + r2 + 0], mm0
684     movq [r0 + r2 + 8], mm1
685 .copy32:
686     sub r2d, 32
687     movq mm0, [r1 + r2 +  0]
688     movq mm1, [r1 + r2 +  8]
689     movq mm2, [r1 + r2 + 16]
690     movq mm3, [r1 + r2 + 24]
691     movq [r0 + r2 +  0], mm0
692     movq [r0 + r2 +  8], mm1
693     movq [r0 + r2 + 16], mm2
694     movq [r0 + r2 + 24], mm3
695     jg .copy32
696     REP_RET
697
698 ;-----------------------------------------------------------------------------
699 ; void *x264_memcpy_aligned_sse2( void *dst, const void *src, size_t n );
700 ;-----------------------------------------------------------------------------
701 cglobal x264_memcpy_aligned_sse2, 3,3
702     test r2d, 16
703     jz .copy32
704     sub r2d, 16
705     movdqa xmm0, [r1 + r2]
706     movdqa [r0 + r2], xmm0
707 .copy32:
708     test r2d, 32
709     jz .copy64
710     sub r2d, 32
711     movdqa xmm0, [r1 + r2 +  0]
712     movdqa [r0 + r2 +  0], xmm0
713     movdqa xmm1, [r1 + r2 + 16]
714     movdqa [r0 + r2 + 16], xmm1
715 .copy64:
716     sub r2d, 64
717     movdqa xmm0, [r1 + r2 +  0]
718     movdqa [r0 + r2 +  0], xmm0
719     movdqa xmm1, [r1 + r2 + 16]
720     movdqa [r0 + r2 + 16], xmm1
721     movdqa xmm2, [r1 + r2 + 32]
722     movdqa [r0 + r2 + 32], xmm2
723     movdqa xmm3, [r1 + r2 + 48]
724     movdqa [r0 + r2 + 48], xmm3
725     jg .copy64
726     REP_RET
727
728 ;-----------------------------------------------------------------------------
729 ; void *x264_memzero_aligned( void *dst, size_t n );
730 ;-----------------------------------------------------------------------------
731 %macro MEMZERO 1
732 cglobal x264_memzero_aligned_%1, 2,2
733     pxor m0, m0
734 .loop:
735     sub r1d, mmsize*8
736 %assign i 0
737 %rep 8
738     mova [r0 + r1 + i], m0
739 %assign i i+mmsize
740 %endrep
741     jg .loop
742     REP_RET
743 %endmacro
744
745 INIT_MMX
746 MEMZERO mmx
747 INIT_XMM
748 MEMZERO sse2
749
750
751
752 ;-----------------------------------------------------------------------------
753 ; void x264_integral_init4h_sse4( uint16_t *sum, uint8_t *pix, int stride )
754 ;-----------------------------------------------------------------------------
755 cglobal x264_integral_init4h_sse4, 3,4
756     lea     r3, [r0+r2*2]
757     add     r1, r2
758     neg     r2
759     pxor    m4, m4
760 .loop:
761     movdqa  m0, [r1+r2]
762     movdqu  m1, [r1+r2+8]
763     mpsadbw m0, m4, 0
764     mpsadbw m1, m4, 0
765     paddw   m0, [r0+r2*2]
766     paddw   m1, [r0+r2*2+16]
767     movdqa  [r3+r2*2   ], m0
768     movdqa  [r3+r2*2+16], m1
769     add     r2, 16
770     jl .loop
771     REP_RET
772
773 cglobal x264_integral_init8h_sse4, 3,4
774     lea     r3, [r0+r2*2]
775     add     r1, r2
776     neg     r2
777     pxor    m4, m4
778 .loop:
779     movdqa  m0, [r1+r2]
780     movdqu  m1, [r1+r2+8]
781     movdqa  m2, m0
782     movdqa  m3, m1
783     mpsadbw m0, m4, 0
784     mpsadbw m1, m4, 0
785     mpsadbw m2, m4, 4
786     mpsadbw m3, m4, 4
787     paddw   m0, [r0+r2*2]
788     paddw   m1, [r0+r2*2+16]
789     paddw   m0, m2
790     paddw   m1, m3
791     movdqa  [r3+r2*2   ], m0
792     movdqa  [r3+r2*2+16], m1
793     add     r2, 16
794     jl .loop
795     REP_RET
796
797 %macro INTEGRAL_INIT 1
798 ;-----------------------------------------------------------------------------
799 ; void x264_integral_init4v_mmx( uint16_t *sum8, uint16_t *sum4, int stride )
800 ;-----------------------------------------------------------------------------
801 cglobal x264_integral_init4v_%1, 3,5
802     shl   r2, 1
803     add   r0, r2
804     add   r1, r2
805     lea   r3, [r0+r2*4]
806     lea   r4, [r0+r2*8]
807     neg   r2
808 .loop:
809     movu  m0, [r0+r2+8]
810     mova  m2, [r0+r2]
811     movu  m1, [r4+r2+8]
812     paddw m0, m2
813     paddw m1, [r4+r2]
814     mova  m3, [r3+r2]
815     psubw m1, m0
816     psubw m3, m2
817     mova  [r0+r2], m1
818     mova  [r1+r2], m3
819     add   r2, mmsize
820     jl .loop
821     REP_RET
822
823 ;-----------------------------------------------------------------------------
824 ; void x264_integral_init8v_mmx( uint16_t *sum8, int stride )
825 ;-----------------------------------------------------------------------------
826 cglobal x264_integral_init8v_%1, 3,3
827     shl   r1, 1
828     add   r0, r1
829     lea   r2, [r0+r1*8]
830     neg   r1
831 .loop:
832     mova  m0, [r2+r1]
833     mova  m1, [r2+r1+mmsize]
834     psubw m0, [r0+r1]
835     psubw m1, [r0+r1+mmsize]
836     mova  [r0+r1], m0
837     mova  [r0+r1+mmsize], m1
838     add   r1, 2*mmsize
839     jl .loop
840     REP_RET
841 %endmacro
842
843 INIT_MMX
844 INTEGRAL_INIT mmx
845 INIT_XMM
846 INTEGRAL_INIT sse2
847
848
849
850 %macro FILT8x4 7
851     mova      %3, [r0+%7]
852     mova      %4, [r0+r5+%7]
853     pavgb     %3, %4
854     pavgb     %4, [r0+r5*2+%7]
855     PALIGNR   %1, %3, 1, m6
856     PALIGNR   %2, %4, 1, m6
857     pavgb     %1, %3
858     pavgb     %2, %4
859     mova      %5, %1
860     mova      %6, %2
861     pand      %1, m7
862     pand      %2, m7
863     psrlw     %5, 8
864     psrlw     %6, 8
865 %endmacro
866
867 %macro FILT16x2 4
868     mova      m3, [r0+%4+mmsize]
869     mova      m2, [r0+%4]
870     pavgb     m3, [r0+%4+r5+mmsize]
871     pavgb     m2, [r0+%4+r5]
872     PALIGNR   %1, m3, 1, m6
873     pavgb     %1, m3
874     PALIGNR   m3, m2, 1, m6
875     pavgb     m3, m2
876     mova      m5, m3
877     mova      m4, %1
878     pand      m3, m7
879     pand      %1, m7
880     psrlw     m5, 8
881     psrlw     m4, 8
882     packuswb  m3, %1
883     packuswb  m5, m4
884     mova    [%2], m3
885     mova    [%3], m5
886     mova      %1, m2
887 %endmacro
888
889 %macro FILT8x2U 3
890     mova      m3, [r0+%3+8]
891     mova      m2, [r0+%3]
892     pavgb     m3, [r0+%3+r5+8]
893     pavgb     m2, [r0+%3+r5]
894     mova      m1, [r0+%3+9]
895     mova      m0, [r0+%3+1]
896     pavgb     m1, [r0+%3+r5+9]
897     pavgb     m0, [r0+%3+r5+1]
898     pavgb     m1, m3
899     pavgb     m0, m2
900     mova      m3, m1
901     mova      m2, m0
902     pand      m1, m7
903     pand      m0, m7
904     psrlw     m3, 8
905     psrlw     m2, 8
906     packuswb  m0, m1
907     packuswb  m2, m3
908     mova    [%1], m0
909     mova    [%2], m2
910 %endmacro
911
912 ;-----------------------------------------------------------------------------
913 ; void frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
914 ;                              int src_stride, int dst_stride, int width, int height )
915 ;-----------------------------------------------------------------------------
916 %macro FRAME_INIT_LOWRES 1-2 0 ; FIXME
917 cglobal x264_frame_init_lowres_core_%1, 6,7,%2
918 %ifdef WIN64
919     movsxd   r5, r5d
920 %endif
921     ; src += 2*(height-1)*stride + 2*width
922     mov      r6d, r8m
923     dec      r6d
924     imul     r6d, r5d
925     add      r6d, r7m
926     lea       r0, [r0+r6*2]
927     ; dst += (height-1)*stride + width
928     mov      r6d, r8m
929     dec      r6d
930     imul     r6d, r6m
931     add      r6d, r7m
932     add       r1, r6
933     add       r2, r6
934     add       r3, r6
935     add       r4, r6
936     ; gap = stride - width
937     mov      r6d, r6m
938     sub      r6d, r7m
939     PUSH      r6
940     %define dst_gap [rsp+gprsize]
941     mov      r6d, r5d
942     sub      r6d, r7m
943     shl      r6d, 1
944     PUSH      r6
945     %define src_gap [rsp]
946 %if mmsize == 16
947     ; adjust for the odd end case
948     mov      r6d, r7m
949     and      r6d, 8
950     sub       r1, r6
951     sub       r2, r6
952     sub       r3, r6
953     sub       r4, r6
954     add  dst_gap, r6d
955 %endif ; mmsize
956     pcmpeqb   m7, m7
957     psrlw     m7, 8
958 .vloop:
959     mov      r6d, r7m
960 %ifnidn %1, mmxext
961     mova      m0, [r0]
962     mova      m1, [r0+r5]
963     pavgb     m0, m1
964     pavgb     m1, [r0+r5*2]
965 %endif
966 %if mmsize == 16
967     test     r6d, 8
968     jz .hloop
969     sub       r0, 16
970     FILT8x4   m0, m1, m2, m3, m4, m5, 0
971     packuswb  m0, m4
972     packuswb  m1, m5
973     movq    [r1], m0
974     movhps  [r2], m0
975     movq    [r3], m1
976     movhps  [r4], m1
977     mova      m0, m2
978     mova      m1, m3
979     sub      r6d, 8
980 %endif ; mmsize
981 .hloop:
982     sub       r0, mmsize*2
983     sub       r1, mmsize
984     sub       r2, mmsize
985     sub       r3, mmsize
986     sub       r4, mmsize
987 %ifdef m8
988     FILT8x4   m0, m1, m2, m3, m10, m11, mmsize
989     mova      m8, m0
990     mova      m9, m1
991     FILT8x4   m2, m3, m0, m1, m4, m5, 0
992     packuswb  m2, m8
993     packuswb  m3, m9
994     packuswb  m4, m10
995     packuswb  m5, m11
996     mova    [r1], m2
997     mova    [r2], m4
998     mova    [r3], m3
999     mova    [r4], m5
1000 %elifidn %1, mmxext
1001     FILT8x2U  r1, r2, 0
1002     FILT8x2U  r3, r4, r5
1003 %else
1004     FILT16x2  m0, r1, r2, 0
1005     FILT16x2  m1, r3, r4, r5
1006 %endif
1007     sub      r6d, mmsize
1008     jg .hloop
1009 .skip:
1010     mov       r6, dst_gap
1011     sub       r0, src_gap
1012     sub       r1, r6
1013     sub       r2, r6
1014     sub       r3, r6
1015     sub       r4, r6
1016     dec    dword r8m
1017     jg .vloop
1018     ADD      rsp, 2*gprsize
1019     emms
1020     RET
1021 %endmacro ; FRAME_INIT_LOWRES
1022
1023 INIT_MMX
1024 %define PALIGNR PALIGNR_MMX
1025 FRAME_INIT_LOWRES mmxext
1026 %ifndef ARCH_X86_64
1027 FRAME_INIT_LOWRES cache32_mmxext
1028 %endif
1029 INIT_XMM
1030 FRAME_INIT_LOWRES sse2, 12
1031 %define PALIGNR PALIGNR_SSSE3
1032 FRAME_INIT_LOWRES ssse3, 12