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