]> git.sesse.net Git - x264/blob - common/x86/mc-a2.asm
fa3e3bd9df1d8ba8e7db7a5253af935ace3996bc
[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 %macro FILT8x4 7
698     mova      %3, [r0+%7]
699     mova      %4, [r0+r5+%7]
700     pavgb     %3, %4
701     pavgb     %4, [r0+r5*2+%7]
702     PALIGNR   %1, %3, 1, m6
703     PALIGNR   %2, %4, 1, m6
704     pavgb     %1, %3
705     pavgb     %2, %4
706     mova      %5, %1
707     mova      %6, %2
708     pand      %1, m7
709     pand      %2, m7
710     psrlw     %5, 8
711     psrlw     %6, 8
712 %endmacro
713
714 %macro FILT16x2 4
715     mova      m3, [r0+%4+mmsize]
716     mova      m2, [r0+%4]
717     pavgb     m3, [r0+%4+r5+mmsize]
718     pavgb     m2, [r0+%4+r5]
719     PALIGNR   %1, m3, 1, m6
720     pavgb     %1, m3
721     PALIGNR   m3, m2, 1, m6
722     pavgb     m3, m2
723     mova      m5, m3
724     mova      m4, %1
725     pand      m3, m7
726     pand      %1, m7
727     psrlw     m5, 8
728     psrlw     m4, 8
729     packuswb  m3, %1
730     packuswb  m5, m4
731     mova    [%2], m3
732     mova    [%3], m5
733     mova      %1, m2
734 %endmacro
735
736 %macro FILT8x2U 3
737     mova      m3, [r0+%3+8]
738     mova      m2, [r0+%3]
739     pavgb     m3, [r0+%3+r5+8]
740     pavgb     m2, [r0+%3+r5]
741     mova      m1, [r0+%3+9]
742     mova      m0, [r0+%3+1]
743     pavgb     m1, [r0+%3+r5+9]
744     pavgb     m0, [r0+%3+r5+1]
745     pavgb     m1, m3
746     pavgb     m0, m2
747     mova      m3, m1
748     mova      m2, m0
749     pand      m1, m7
750     pand      m0, m7
751     psrlw     m3, 8
752     psrlw     m2, 8
753     packuswb  m0, m1
754     packuswb  m2, m3
755     mova    [%1], m0
756     mova    [%2], m2
757 %endmacro
758
759 ;-----------------------------------------------------------------------------
760 ; void frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
761 ;                              int src_stride, int dst_stride, int width, int height )
762 ;-----------------------------------------------------------------------------
763 %macro FRAME_INIT_LOWRES 1 ; FIXME
764 cglobal x264_frame_init_lowres_core_%1, 6,7
765     ; src += 2*(height-1)*stride + 2*width
766     mov      r6d, r8m
767     dec      r6d
768     imul     r6d, r5d
769     add      r6d, r7m
770     lea       r0, [r0+r6*2]
771     ; dst += (height-1)*stride + width
772     mov      r6d, r8m
773     dec      r6d
774     imul     r6d, r6m
775     add      r6d, r7m
776     add       r1, r6
777     add       r2, r6
778     add       r3, r6
779     add       r4, r6
780     ; gap = stride - width
781     mov      r6d, r6m
782     sub      r6d, r7m
783     PUSH      r6
784     %define dst_gap [rsp+gprsize]
785     mov      r6d, r5d
786     sub      r6d, r7m
787     shl      r6d, 1
788     PUSH      r6
789     %define src_gap [rsp]
790 %if mmsize == 16
791     ; adjust for the odd end case
792     mov      r6d, r7m
793     and      r6d, 8
794     sub       r1, r6
795     sub       r2, r6
796     sub       r3, r6
797     sub       r4, r6
798     add  dst_gap, r6d
799 %endif ; mmsize
800     pcmpeqb   m7, m7
801     psrlw     m7, 8
802 .vloop:
803     mov      r6d, r7m
804 %ifnidn %1, mmxext
805     mova      m0, [r0]
806     mova      m1, [r0+r5]
807     pavgb     m0, m1
808     pavgb     m1, [r0+r5*2]
809 %endif
810 %if mmsize == 16
811     test     r6d, 8
812     jz .hloop
813     sub       r0, 16
814     FILT8x4   m0, m1, m2, m3, m4, m5, 0
815     packuswb  m0, m4
816     packuswb  m1, m5
817     movq    [r1], m0
818     movhps  [r2], m0
819     movq    [r3], m1
820     movhps  [r4], m1
821     mova      m0, m2
822     mova      m1, m3
823     sub      r6d, 8
824 %endif ; mmsize
825 .hloop:
826     sub       r0, mmsize*2
827     sub       r1, mmsize
828     sub       r2, mmsize
829     sub       r3, mmsize
830     sub       r4, mmsize
831 %ifdef m8
832     FILT8x4   m0, m1, m2, m3, m10, m11, mmsize
833     mova      m8, m0
834     mova      m9, m1
835     FILT8x4   m2, m3, m0, m1, m4, m5, 0
836     packuswb  m2, m8
837     packuswb  m3, m9
838     packuswb  m4, m10
839     packuswb  m5, m11
840     mova    [r1], m2
841     mova    [r2], m4
842     mova    [r3], m3
843     mova    [r4], m5
844 %elifidn %1, mmxext
845     FILT8x2U  r1, r2, 0
846     FILT8x2U  r3, r4, r5
847 %else
848     FILT16x2  m0, r1, r2, 0
849     FILT16x2  m1, r3, r4, r5
850 %endif
851     sub      r6d, mmsize
852     jg .hloop
853 .skip:
854     mov       r6, dst_gap
855     sub       r0, src_gap
856     sub       r1, r6
857     sub       r2, r6
858     sub       r3, r6
859     sub       r4, r6
860     dec    dword r8m
861     jg .vloop
862     ADD      rsp, 2*gprsize
863     emms
864     RET
865 %endmacro ; FRAME_INIT_LOWRES
866
867 INIT_MMX
868 %define PALIGNR PALIGNR_MMX
869 FRAME_INIT_LOWRES mmxext
870 %ifndef ARCH_X86_64
871 FRAME_INIT_LOWRES cache32_mmxext
872 %endif
873 INIT_XMM
874 FRAME_INIT_LOWRES sse2
875 %define PALIGNR PALIGNR_SSSE3
876 FRAME_INIT_LOWRES ssse3