]> git.sesse.net Git - x264/blob - common/x86/mc-a2.asm
Faster, more accurate psy-RD caching
[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_mmxext( uint8_t *dst, int i_dst,
602 ;                              uint8_t *src, int i_src, int w, int h)
603 ;-----------------------------------------------------------------------------
604 cglobal x264_plane_copy_mmxext, 6,7
605     movsxdifnidn r1, r1d
606     movsxdifnidn r3, r3d
607     add    r4d, 3
608     and    r4d, ~3
609     mov    r6d, r4d
610     and    r6d, ~15
611     sub    r1,  r6
612     sub    r3,  r6
613 .loopy:
614     mov    r6d, r4d
615     sub    r6d, 64
616     jl     .endx
617 .loopx:
618     prefetchnta [r2+256]
619     movq   mm0, [r2   ]
620     movq   mm1, [r2+ 8]
621     movq   mm2, [r2+16]
622     movq   mm3, [r2+24]
623     movq   mm4, [r2+32]
624     movq   mm5, [r2+40]
625     movq   mm6, [r2+48]
626     movq   mm7, [r2+56]
627     movntq [r0   ], mm0
628     movntq [r0+ 8], mm1
629     movntq [r0+16], mm2
630     movntq [r0+24], mm3
631     movntq [r0+32], mm4
632     movntq [r0+40], mm5
633     movntq [r0+48], mm6
634     movntq [r0+56], mm7
635     add    r2,  64
636     add    r0,  64
637     sub    r6d, 64
638     jge    .loopx
639 .endx:
640     prefetchnta [r2+256]
641     add    r6d, 48
642     jl .end16
643 .loop16:
644     movq   mm0, [r2  ]
645     movq   mm1, [r2+8]
646     movntq [r0  ], mm0
647     movntq [r0+8], mm1
648     add    r2,  16
649     add    r0,  16
650     sub    r6d, 16
651     jge    .loop16
652 .end16:
653     add    r6d, 12
654     jl .end4
655 .loop4:
656     movd   mm2, [r2+r6]
657     movd   [r0+r6], mm2
658     sub    r6d, 4
659     jge .loop4
660 .end4:
661     add    r2, r3
662     add    r0, r1
663     dec    r5d
664     jg     .loopy
665     sfence
666     emms
667     RET
668
669
670
671 ; These functions are not general-use; not only do the SSE ones require aligned input,
672 ; but they also will fail if given a non-mod16 size or a size less than 64.
673 ; memzero SSE will fail for non-mod128.
674
675 ;-----------------------------------------------------------------------------
676 ; void *x264_memcpy_aligned_mmx( void *dst, const void *src, size_t n );
677 ;-----------------------------------------------------------------------------
678 cglobal x264_memcpy_aligned_mmx, 3,3
679     test r2d, 16
680     jz .copy32
681     sub r2d, 16
682     movq mm0, [r1 + r2 + 0]
683     movq mm1, [r1 + r2 + 8]
684     movq [r0 + r2 + 0], mm0
685     movq [r0 + r2 + 8], mm1
686 .copy32:
687     sub r2d, 32
688     movq mm0, [r1 + r2 +  0]
689     movq mm1, [r1 + r2 +  8]
690     movq mm2, [r1 + r2 + 16]
691     movq mm3, [r1 + r2 + 24]
692     movq [r0 + r2 +  0], mm0
693     movq [r0 + r2 +  8], mm1
694     movq [r0 + r2 + 16], mm2
695     movq [r0 + r2 + 24], mm3
696     jg .copy32
697     REP_RET
698
699 ;-----------------------------------------------------------------------------
700 ; void *x264_memcpy_aligned_sse2( void *dst, const void *src, size_t n );
701 ;-----------------------------------------------------------------------------
702 cglobal x264_memcpy_aligned_sse2, 3,3
703     test r2d, 16
704     jz .copy32
705     sub r2d, 16
706     movdqa xmm0, [r1 + r2]
707     movdqa [r0 + r2], xmm0
708 .copy32:
709     test r2d, 32
710     jz .copy64
711     sub r2d, 32
712     movdqa xmm0, [r1 + r2 +  0]
713     movdqa [r0 + r2 +  0], xmm0
714     movdqa xmm1, [r1 + r2 + 16]
715     movdqa [r0 + r2 + 16], xmm1
716 .copy64:
717     sub r2d, 64
718     movdqa xmm0, [r1 + r2 +  0]
719     movdqa [r0 + r2 +  0], xmm0
720     movdqa xmm1, [r1 + r2 + 16]
721     movdqa [r0 + r2 + 16], xmm1
722     movdqa xmm2, [r1 + r2 + 32]
723     movdqa [r0 + r2 + 32], xmm2
724     movdqa xmm3, [r1 + r2 + 48]
725     movdqa [r0 + r2 + 48], xmm3
726     jg .copy64
727     REP_RET
728
729 ;-----------------------------------------------------------------------------
730 ; void *x264_memzero_aligned( void *dst, size_t n );
731 ;-----------------------------------------------------------------------------
732 %macro MEMZERO 1
733 cglobal x264_memzero_aligned_%1, 2,2
734     add  r0, r1
735     neg  r1
736     pxor m0, m0
737 .loop:
738 %assign i 0
739 %rep 8
740     mova [r0 + r1 + i], m0
741 %assign i i+mmsize
742 %endrep
743     add r1d, mmsize*8
744     jl .loop
745     REP_RET
746 %endmacro
747
748 INIT_MMX
749 MEMZERO mmx
750 INIT_XMM
751 MEMZERO sse2
752
753
754
755 ;-----------------------------------------------------------------------------
756 ; void x264_integral_init4h_sse4( uint16_t *sum, uint8_t *pix, int stride )
757 ;-----------------------------------------------------------------------------
758 cglobal x264_integral_init4h_sse4, 3,4
759     lea     r3, [r0+r2*2]
760     add     r1, r2
761     neg     r2
762     pxor    m4, m4
763 .loop:
764     movdqa  m0, [r1+r2]
765     movdqa  m1, [r1+r2+16]
766     palignr m1, m0, 8
767     mpsadbw m0, m4, 0
768     mpsadbw m1, m4, 0
769     paddw   m0, [r0+r2*2]
770     paddw   m1, [r0+r2*2+16]
771     movdqa  [r3+r2*2   ], m0
772     movdqa  [r3+r2*2+16], m1
773     add     r2, 16
774     jl .loop
775     REP_RET
776
777 cglobal x264_integral_init8h_sse4, 3,4
778     lea     r3, [r0+r2*2]
779     add     r1, r2
780     neg     r2
781     pxor    m4, m4
782 .loop:
783     movdqa  m0, [r1+r2]
784     movdqa  m1, [r1+r2+16]
785     palignr m1, m0, 8
786     movdqa  m2, m0
787     movdqa  m3, m1
788     mpsadbw m0, m4, 0
789     mpsadbw m1, m4, 0
790     mpsadbw m2, m4, 4
791     mpsadbw m3, m4, 4
792     paddw   m0, [r0+r2*2]
793     paddw   m1, [r0+r2*2+16]
794     paddw   m0, m2
795     paddw   m1, m3
796     movdqa  [r3+r2*2   ], m0
797     movdqa  [r3+r2*2+16], m1
798     add     r2, 16
799     jl .loop
800     REP_RET
801
802 %macro INTEGRAL_INIT_8V 1
803 ;-----------------------------------------------------------------------------
804 ; void x264_integral_init8v_mmx( uint16_t *sum8, int stride )
805 ;-----------------------------------------------------------------------------
806 cglobal x264_integral_init8v_%1, 3,3
807     shl   r1, 1
808     add   r0, r1
809     lea   r2, [r0+r1*8]
810     neg   r1
811 .loop:
812     mova  m0, [r2+r1]
813     mova  m1, [r2+r1+mmsize]
814     psubw m0, [r0+r1]
815     psubw m1, [r0+r1+mmsize]
816     mova  [r0+r1], m0
817     mova  [r0+r1+mmsize], m1
818     add   r1, 2*mmsize
819     jl .loop
820     REP_RET
821 %endmacro
822
823 INIT_MMX
824 INTEGRAL_INIT_8V mmx
825 INIT_XMM
826 INTEGRAL_INIT_8V sse2
827
828 ;-----------------------------------------------------------------------------
829 ; void x264_integral_init4v_mmx( uint16_t *sum8, uint16_t *sum4, int stride )
830 ;-----------------------------------------------------------------------------
831 INIT_MMX
832 cglobal x264_integral_init4v_mmx, 3,5
833     shl   r2, 1
834     lea   r3, [r0+r2*4]
835     lea   r4, [r0+r2*8]
836     mova  m0, [r0+r2]
837     mova  m4, [r4+r2]
838 .loop:
839     sub   r2, 8
840     mova  m1, m4
841     psubw m1, m0
842     mova  m4, [r4+r2]
843     mova  m0, [r0+r2]
844     paddw m1, m4
845     mova  m3, [r3+r2]
846     psubw m1, m0
847     psubw m3, m0
848     mova  [r0+r2], m1
849     mova  [r1+r2], m3
850     jge .loop
851     REP_RET
852
853 INIT_XMM
854 cglobal x264_integral_init4v_sse2, 3,5
855     shl     r2, 1
856     add     r0, r2
857     add     r1, r2
858     lea     r3, [r0+r2*4]
859     lea     r4, [r0+r2*8]
860     neg     r2
861 .loop:
862     mova    m0, [r0+r2]
863     mova    m1, [r4+r2]
864     mova    m2, m0
865     mova    m4, m1
866     shufpd  m0, [r0+r2+16], 1
867     shufpd  m1, [r4+r2+16], 1
868     paddw   m0, m2
869     paddw   m1, m4
870     mova    m3, [r3+r2]
871     psubw   m1, m0
872     psubw   m3, m2
873     mova  [r0+r2], m1
874     mova  [r1+r2], m3
875     add     r2, 16
876     jl .loop
877     REP_RET
878
879 cglobal x264_integral_init4v_ssse3, 3,5
880     shl     r2, 1
881     add     r0, r2
882     add     r1, r2
883     lea     r3, [r0+r2*4]
884     lea     r4, [r0+r2*8]
885     neg     r2
886 .loop:
887     mova    m2, [r0+r2]
888     mova    m0, [r0+r2+16]
889     mova    m4, [r4+r2]
890     mova    m1, [r4+r2+16]
891     palignr m0, m2, 8
892     palignr m1, m4, 8
893     paddw   m0, m2
894     paddw   m1, m4
895     mova    m3, [r3+r2]
896     psubw   m1, m0
897     psubw   m3, m2
898     mova  [r0+r2], m1
899     mova  [r1+r2], m3
900     add     r2, 16
901     jl .loop
902     REP_RET
903
904 %macro FILT8x4 7
905     mova      %3, [r0+%7]
906     mova      %4, [r0+r5+%7]
907     pavgb     %3, %4
908     pavgb     %4, [r0+r5*2+%7]
909     PALIGNR   %1, %3, 1, m6
910     PALIGNR   %2, %4, 1, m6
911     pavgb     %1, %3
912     pavgb     %2, %4
913     mova      %5, %1
914     mova      %6, %2
915     pand      %1, m7
916     pand      %2, m7
917     psrlw     %5, 8
918     psrlw     %6, 8
919 %endmacro
920
921 %macro FILT16x2 4
922     mova      m3, [r0+%4+mmsize]
923     mova      m2, [r0+%4]
924     pavgb     m3, [r0+%4+r5+mmsize]
925     pavgb     m2, [r0+%4+r5]
926     PALIGNR   %1, m3, 1, m6
927     pavgb     %1, m3
928     PALIGNR   m3, m2, 1, m6
929     pavgb     m3, m2
930     mova      m5, m3
931     mova      m4, %1
932     pand      m3, m7
933     pand      %1, m7
934     psrlw     m5, 8
935     psrlw     m4, 8
936     packuswb  m3, %1
937     packuswb  m5, m4
938     mova    [%2], m3
939     mova    [%3], m5
940     mova      %1, m2
941 %endmacro
942
943 %macro FILT8x2U 3
944     mova      m3, [r0+%3+8]
945     mova      m2, [r0+%3]
946     pavgb     m3, [r0+%3+r5+8]
947     pavgb     m2, [r0+%3+r5]
948     mova      m1, [r0+%3+9]
949     mova      m0, [r0+%3+1]
950     pavgb     m1, [r0+%3+r5+9]
951     pavgb     m0, [r0+%3+r5+1]
952     pavgb     m1, m3
953     pavgb     m0, m2
954     mova      m3, m1
955     mova      m2, m0
956     pand      m1, m7
957     pand      m0, m7
958     psrlw     m3, 8
959     psrlw     m2, 8
960     packuswb  m0, m1
961     packuswb  m2, m3
962     mova    [%1], m0
963     mova    [%2], m2
964 %endmacro
965
966 ;-----------------------------------------------------------------------------
967 ; void frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
968 ;                              int src_stride, int dst_stride, int width, int height )
969 ;-----------------------------------------------------------------------------
970 %macro FRAME_INIT_LOWRES 1-2 0 ; FIXME
971 cglobal x264_frame_init_lowres_core_%1, 6,7,%2
972 %ifdef WIN64
973     movsxd   r5, r5d
974 %endif
975     ; src += 2*(height-1)*stride + 2*width
976     mov      r6d, r8m
977     dec      r6d
978     imul     r6d, r5d
979     add      r6d, r7m
980     lea       r0, [r0+r6*2]
981     ; dst += (height-1)*stride + width
982     mov      r6d, r8m
983     dec      r6d
984     imul     r6d, r6m
985     add      r6d, r7m
986     add       r1, r6
987     add       r2, r6
988     add       r3, r6
989     add       r4, r6
990     ; gap = stride - width
991     mov      r6d, r6m
992     sub      r6d, r7m
993     PUSH      r6
994     %define dst_gap [rsp+gprsize]
995     mov      r6d, r5d
996     sub      r6d, r7m
997     shl      r6d, 1
998     PUSH      r6
999     %define src_gap [rsp]
1000 %if mmsize == 16
1001     ; adjust for the odd end case
1002     mov      r6d, r7m
1003     and      r6d, 8
1004     sub       r1, r6
1005     sub       r2, r6
1006     sub       r3, r6
1007     sub       r4, r6
1008     add  dst_gap, r6d
1009 %endif ; mmsize
1010     pcmpeqb   m7, m7
1011     psrlw     m7, 8
1012 .vloop:
1013     mov      r6d, r7m
1014 %ifnidn %1, mmxext
1015     mova      m0, [r0]
1016     mova      m1, [r0+r5]
1017     pavgb     m0, m1
1018     pavgb     m1, [r0+r5*2]
1019 %endif
1020 %if mmsize == 16
1021     test     r6d, 8
1022     jz .hloop
1023     sub       r0, 16
1024     FILT8x4   m0, m1, m2, m3, m4, m5, 0
1025     packuswb  m0, m4
1026     packuswb  m1, m5
1027     movq    [r1], m0
1028     movhps  [r2], m0
1029     movq    [r3], m1
1030     movhps  [r4], m1
1031     mova      m0, m2
1032     mova      m1, m3
1033     sub      r6d, 8
1034 %endif ; mmsize
1035 .hloop:
1036     sub       r0, mmsize*2
1037     sub       r1, mmsize
1038     sub       r2, mmsize
1039     sub       r3, mmsize
1040     sub       r4, mmsize
1041 %ifdef m8
1042     FILT8x4   m0, m1, m2, m3, m10, m11, mmsize
1043     mova      m8, m0
1044     mova      m9, m1
1045     FILT8x4   m2, m3, m0, m1, m4, m5, 0
1046     packuswb  m2, m8
1047     packuswb  m3, m9
1048     packuswb  m4, m10
1049     packuswb  m5, m11
1050     mova    [r1], m2
1051     mova    [r2], m4
1052     mova    [r3], m3
1053     mova    [r4], m5
1054 %elifidn %1, mmxext
1055     FILT8x2U  r1, r2, 0
1056     FILT8x2U  r3, r4, r5
1057 %else
1058     FILT16x2  m0, r1, r2, 0
1059     FILT16x2  m1, r3, r4, r5
1060 %endif
1061     sub      r6d, mmsize
1062     jg .hloop
1063 .skip:
1064     mov       r6, dst_gap
1065     sub       r0, src_gap
1066     sub       r1, r6
1067     sub       r2, r6
1068     sub       r3, r6
1069     sub       r4, r6
1070     dec    dword r8m
1071     jg .vloop
1072     ADD      rsp, 2*gprsize
1073     emms
1074     RET
1075 %endmacro ; FRAME_INIT_LOWRES
1076
1077 INIT_MMX
1078 %define PALIGNR PALIGNR_MMX
1079 FRAME_INIT_LOWRES mmxext
1080 %ifndef ARCH_X86_64
1081 FRAME_INIT_LOWRES cache32_mmxext
1082 %endif
1083 INIT_XMM
1084 FRAME_INIT_LOWRES sse2, 12
1085 %define PALIGNR PALIGNR_SSSE3
1086 FRAME_INIT_LOWRES ssse3, 12
1087
1088 ;-----------------------------------------------------------------------------
1089 ; void mbtree_propagate_cost( int *dst, uint16_t *propagate_in, uint16_t *intra_costs,
1090 ;                             uint16_t *inter_costs, uint16_t *inv_qscales, int len )
1091 ;-----------------------------------------------------------------------------
1092 cglobal x264_mbtree_propagate_cost_sse2, 6,6
1093     shl r5d, 1
1094     lea r0, [r0+r5*2]
1095     add r1, r5
1096     add r2, r5
1097     add r3, r5
1098     add r4, r5
1099     neg r5
1100     pxor      xmm5, xmm5
1101     movdqa    xmm4, [pd_128]
1102 .loop:
1103     movq      xmm2, [r2+r5] ; intra
1104     movq      xmm0, [r4+r5] ; invq
1105     punpcklwd xmm2, xmm5
1106     punpcklwd xmm0, xmm5
1107     pmaddwd   xmm0, xmm2
1108     paddd     xmm0, xmm4
1109     psrld     xmm0, 8       ; intra*invq>>8
1110     movq      xmm1, [r1+r5] ; prop
1111     movq      xmm3, [r3+r5] ; inter
1112     punpcklwd xmm1, xmm5
1113     punpcklwd xmm3, xmm5
1114     paddd     xmm0, xmm1    ; prop + (intra*invq>>8)
1115     cvtdq2ps  xmm1, xmm2    ; intra
1116     psubd     xmm2, xmm3    ; intra - inter
1117     cvtdq2ps  xmm0, xmm0
1118     cvtdq2ps  xmm2, xmm2
1119     mulps     xmm0, xmm2    ; (prop + (intra*invq>>8)) * (intra - inter)
1120     divps     xmm0, xmm1    ; / intra
1121     cvttps2dq xmm0, xmm0    ; truncation isn't really desired, but matches the integer implementation
1122     movdqa [r0+r5*2], xmm0
1123     add r5, 8
1124     jl .loop
1125     REP_RET
1126