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