]> git.sesse.net Git - x264/blob - common/x86/mc-a2.asm
Update file headers throughout x264
[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 ;*          Mathieu Monnier <manao@melix.net>
9 ;*
10 ;* This program is free software; you can redistribute it and/or modify
11 ;* it under the terms of the GNU General Public License as published by
12 ;* the Free Software Foundation; either version 2 of the License, or
13 ;* (at your option) any later version.
14 ;*
15 ;* This program is distributed in the hope that it will be useful,
16 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;* GNU General Public License for more details.
19 ;*
20 ;* You should have received a copy of the GNU General Public License
21 ;* along with this program; if not, write to the Free Software
22 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
23 ;*****************************************************************************
24
25 %include "x86inc.asm"
26
27 SECTION_RODATA
28
29 pw_1:  times 8 dw 1
30 pw_16: times 8 dw 16
31 pw_32: times 8 dw 32
32
33 SECTION .text
34
35 %macro LOAD_ADD 3
36     movh       %1, %2
37     movh       m7, %3
38     punpcklbw  %1, m0
39     punpcklbw  m7, m0
40     paddw      %1, m7
41 %endmacro
42
43 %macro FILT_V2 0
44     psubw  m1, m2  ; a-b
45     psubw  m4, m5
46     psubw  m2, m3  ; b-c
47     psubw  m5, m6
48     psllw  m2, 2
49     psllw  m5, 2
50     psubw  m1, m2  ; a-5*b+4*c
51     psubw  m4, m5
52     psllw  m3, 4
53     psllw  m6, 4
54     paddw  m1, m3  ; a-5*b+20*c
55     paddw  m4, m6
56 %endmacro
57
58 %macro FILT_H 3
59     psubw  %1, %2  ; a-b
60     psraw  %1, 2   ; (a-b)/4
61     psubw  %1, %2  ; (a-b)/4-b
62     paddw  %1, %3  ; (a-b)/4-b+c
63     psraw  %1, 2   ; ((a-b)/4-b+c)/4
64     paddw  %1, %3  ; ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
65 %endmacro
66
67 %macro FILT_H2 0
68     psubw  m1, m2
69     psubw  m4, m5
70     psraw  m1, 2
71     psraw  m4, 2
72     psubw  m1, m2
73     psubw  m4, m5
74     paddw  m1, m3
75     paddw  m4, m6
76     psraw  m1, 2
77     psraw  m4, 2
78     paddw  m1, m3
79     paddw  m4, m6
80 %endmacro
81
82 %macro FILT_PACK 1
83     paddw     m1, m7
84     paddw     m4, m7
85     psraw     m1, %1
86     psraw     m4, %1
87     packuswb  m1, m4
88 %endmacro
89
90 %macro PALIGNR_MMX 4
91     %ifnidn %4, %2
92     mova    %4, %2
93     %endif
94     %if regsize == 8
95     psllq   %1, (8-%3)*8
96     psrlq   %4, %3*8
97     %else
98     pslldq  %1, 16-%3
99     psrldq  %4, %3
100     %endif
101     por     %1, %4
102 %endmacro
103
104 %macro PALIGNR_SSSE3 4
105     palignr %1, %2, %3
106 %endmacro
107
108 INIT_MMX
109
110 %macro HPEL_V 1
111 ;-----------------------------------------------------------------------------
112 ; void x264_hpel_filter_v_mmxext( uint8_t *dst, uint8_t *src, int16_t *buf, int stride, int width );
113 ;-----------------------------------------------------------------------------
114 cglobal x264_hpel_filter_v_%1, 5,6,1
115     lea r5, [r1+r3]
116     sub r1, r3
117     sub r1, r3
118     add r0, r4
119     lea r2, [r2+r4*2]
120     neg r4
121     pxor m0, m0
122 .loop:
123     prefetcht0 [r5+r3*2+64]
124     LOAD_ADD  m1, [r1     ], [r5+r3*2] ; a0
125     LOAD_ADD  m2, [r1+r3  ], [r5+r3  ] ; b0
126     LOAD_ADD  m3, [r1+r3*2], [r5     ] ; c0
127     LOAD_ADD  m4, [r1     +regsize/2], [r5+r3*2+regsize/2] ; a1
128     LOAD_ADD  m5, [r1+r3  +regsize/2], [r5+r3  +regsize/2] ; b1
129     LOAD_ADD  m6, [r1+r3*2+regsize/2], [r5     +regsize/2] ; c1
130     FILT_V2
131     mova      m7, [pw_16 GLOBAL]
132     mova      [r2+r4*2], m1
133     mova      [r2+r4*2+regsize], m4
134     paddw     m1, m7
135     paddw     m4, m7
136     psraw     m1, 5
137     psraw     m4, 5
138     packuswb  m1, m4
139     movnt     [r0+r4], m1
140     add r1, regsize
141     add r5, regsize
142     add r4, regsize
143     jl .loop
144     REP_RET
145 %endmacro
146 HPEL_V mmxext
147
148 ;-----------------------------------------------------------------------------
149 ; void x264_hpel_filter_c_mmxext( uint8_t *dst, int16_t *buf, int width );
150 ;-----------------------------------------------------------------------------
151 cglobal x264_hpel_filter_c_mmxext, 3,3,1
152     add r0, r2
153     lea r1, [r1+r2*2]
154     neg r2
155     %define src r1+r2*2
156     movq m7, [pw_32 GLOBAL]
157 .loop:
158     movq   m1, [src-4]
159     movq   m2, [src-2]
160     movq   m3, [src  ]
161     movq   m4, [src+4]
162     movq   m5, [src+6]
163     paddw  m3, [src+2]  ; c0
164     paddw  m2, m4       ; b0
165     paddw  m1, m5       ; a0
166     movq   m6, [src+8]
167     paddw  m4, [src+14] ; a1
168     paddw  m5, [src+12] ; b1
169     paddw  m6, [src+10] ; c1
170     FILT_H2
171     FILT_PACK 6
172     movntq [r0+r2], m1
173     add r2, 8
174     jl .loop
175     REP_RET
176
177 ;-----------------------------------------------------------------------------
178 ; void x264_hpel_filter_h_mmxext( uint8_t *dst, uint8_t *src, int width );
179 ;-----------------------------------------------------------------------------
180 cglobal x264_hpel_filter_h_mmxext, 3,3,1
181     add r0, r2
182     add r1, r2
183     neg r2
184     %define src r1+r2
185     pxor m0, m0
186 .loop:
187     movd       m1, [src-2]
188     movd       m2, [src-1]
189     movd       m3, [src  ]
190     movd       m6, [src+1]
191     movd       m4, [src+2]
192     movd       m5, [src+3]
193     punpcklbw  m1, m0
194     punpcklbw  m2, m0
195     punpcklbw  m3, m0
196     punpcklbw  m6, m0
197     punpcklbw  m4, m0
198     punpcklbw  m5, m0
199     paddw      m3, m6 ; c0
200     paddw      m2, m4 ; b0
201     paddw      m1, m5 ; a0
202     movd       m7, [src+7]
203     movd       m6, [src+6]
204     punpcklbw  m7, m0
205     punpcklbw  m6, m0
206     paddw      m4, m7 ; c1
207     paddw      m5, m6 ; b1
208     movd       m7, [src+5]
209     movd       m6, [src+4]
210     punpcklbw  m7, m0
211     punpcklbw  m6, m0
212     paddw      m6, m7 ; a1
213     movq       m7, [pw_1 GLOBAL]
214     FILT_H2
215     FILT_PACK 1
216     movntq     [r0+r2], m1
217     add r2, 8
218     jl .loop
219     REP_RET
220
221 INIT_XMM
222
223 %macro HPEL_C 1
224 ;-----------------------------------------------------------------------------
225 ; void x264_hpel_filter_c_sse2( uint8_t *dst, int16_t *buf, int width );
226 ;-----------------------------------------------------------------------------
227 cglobal x264_hpel_filter_c_%1, 3,3,1
228     add r0, r2
229     lea r1, [r1+r2*2]
230     neg r2
231     %define src r1+r2*2
232 %ifidn %1, ssse3
233     mova    m7, [pw_32 GLOBAL]
234     %define tpw_32 m7
235 %elifdef ARCH_X86_64
236     mova    m8, [pw_32 GLOBAL]
237     %define tpw_32 m8
238 %else
239     %define tpw_32 [pw_32 GLOBAL]
240 %endif
241 .loop:
242     mova    m6, [src-16]
243     mova    m2, [src]
244     mova    m3, [src+16]
245     mova    m0, m2
246     mova    m1, m2
247     mova    m4, m3
248     mova    m5, m3
249     PALIGNR m3, m2, 2, m7
250     PALIGNR m4, m2, 4, m7
251     PALIGNR m5, m2, 6, m7
252     PALIGNR m0, m6, 12, m7
253     PALIGNR m1, m6, 14, m7
254     paddw   m2, m3
255     paddw   m1, m4
256     paddw   m0, m5
257     FILT_H  m0, m1, m2
258     paddw   m0, tpw_32
259     psraw   m0, 6
260     packuswb m0, m0
261     movq [r0+r2], m0
262     add r2, 8
263     jl .loop
264     REP_RET
265 %endmacro
266
267 ;-----------------------------------------------------------------------------
268 ; void x264_hpel_filter_h_sse2( uint8_t *dst, uint8_t *src, int width );
269 ;-----------------------------------------------------------------------------
270 cglobal x264_hpel_filter_h_sse2, 3,3,1
271     add r0, r2
272     add r1, r2
273     neg r2
274     %define src r1+r2
275     pxor m0, m0
276 .loop:
277     movh       m1, [src-2]
278     movh       m2, [src-1]
279     movh       m3, [src  ]
280     movh       m4, [src+1]
281     movh       m5, [src+2]
282     movh       m6, [src+3]
283     punpcklbw  m1, m0
284     punpcklbw  m2, m0
285     punpcklbw  m3, m0
286     punpcklbw  m4, m0
287     punpcklbw  m5, m0
288     punpcklbw  m6, m0
289     paddw      m3, m4 ; c0
290     paddw      m2, m5 ; b0
291     paddw      m1, m6 ; a0
292     movh       m4, [src+6]
293     movh       m5, [src+7]
294     movh       m6, [src+10]
295     movh       m7, [src+11]
296     punpcklbw  m4, m0
297     punpcklbw  m5, m0
298     punpcklbw  m6, m0
299     punpcklbw  m7, m0
300     paddw      m5, m6 ; b1
301     paddw      m4, m7 ; a1
302     movh       m6, [src+8]
303     movh       m7, [src+9]
304     punpcklbw  m6, m0
305     punpcklbw  m7, m0
306     paddw      m6, m7 ; c1
307     mova       m7, [pw_1 GLOBAL] ; FIXME xmm8
308     FILT_H2
309     FILT_PACK 1
310     movntdq    [r0+r2], m1
311     add r2, 16
312     jl .loop
313     REP_RET
314
315 %define PALIGNR PALIGNR_MMX
316 HPEL_V sse2
317 HPEL_C sse2
318 %define PALIGNR PALIGNR_SSSE3
319 HPEL_C ssse3
320
321 cglobal x264_sfence
322     sfence
323     ret
324
325
326
327 ;-----------------------------------------------------------------------------
328 ; void x264_plane_copy_mmxext( uint8_t *dst, int i_dst,
329 ;                              uint8_t *src, int i_src, int w, int h)
330 ;-----------------------------------------------------------------------------
331 cglobal x264_plane_copy_mmxext, 6,7
332     movsxdifnidn r1, r1d
333     movsxdifnidn r3, r3d
334     add    r4d, 3
335     and    r4d, ~3
336     mov    r6d, r4d
337     and    r6d, ~15
338     sub    r1,  r6
339     sub    r3,  r6
340 .loopy:
341     mov    r6d, r4d
342     sub    r6d, 64
343     jl     .endx
344 .loopx:
345     prefetchnta [r2+256]
346     movq   mm0, [r2   ]
347     movq   mm1, [r2+ 8]
348     movq   mm2, [r2+16]
349     movq   mm3, [r2+24]
350     movq   mm4, [r2+32]
351     movq   mm5, [r2+40]
352     movq   mm6, [r2+48]
353     movq   mm7, [r2+56]
354     movntq [r0   ], mm0
355     movntq [r0+ 8], mm1
356     movntq [r0+16], mm2
357     movntq [r0+24], mm3
358     movntq [r0+32], mm4
359     movntq [r0+40], mm5
360     movntq [r0+48], mm6
361     movntq [r0+56], mm7
362     add    r2,  64
363     add    r0,  64
364     sub    r6d, 64
365     jge    .loopx
366 .endx:
367     prefetchnta [r2+256]
368     add    r6d, 48
369     jl .end16
370 .loop16:
371     movq   mm0, [r2  ]
372     movq   mm1, [r2+8]
373     movntq [r0  ], mm0
374     movntq [r0+8], mm1
375     add    r2,  16
376     add    r0,  16
377     sub    r6d, 16
378     jge    .loop16
379 .end16:
380     add    r6d, 12
381     jl .end4
382 .loop4:
383     movd   mm2, [r2+r6]
384     movd   [r0+r6], mm2
385     sub    r6d, 4
386     jge .loop4
387 .end4:
388     add    r2, r3
389     add    r0, r1
390     dec    r5d
391     jg     .loopy
392     sfence
393     emms
394     RET
395
396
397
398 ; These functions are not general-use; not only do the SSE ones require aligned input,
399 ; but they also will fail if given a non-mod16 size or a size less than 64.
400 ; memzero SSE will fail for non-mod128.
401
402 ;-----------------------------------------------------------------------------
403 ; void *x264_memcpy_aligned_mmx( void *dst, const void *src, size_t n );
404 ;-----------------------------------------------------------------------------
405 cglobal x264_memcpy_aligned_mmx, 3,3
406     test r2d, 16
407     jz .copy32
408     sub r2d, 16
409     movq mm0, [r1 + r2 + 0]
410     movq mm1, [r1 + r2 + 8]
411     movq [r0 + r2 + 0], mm0
412     movq [r0 + r2 + 8], mm1
413 .copy32:
414     sub r2d, 32
415     movq mm0, [r1 + r2 +  0]
416     movq mm1, [r1 + r2 +  8]
417     movq mm2, [r1 + r2 + 16]
418     movq mm3, [r1 + r2 + 24]
419     movq [r0 + r2 +  0], mm0
420     movq [r0 + r2 +  8], mm1
421     movq [r0 + r2 + 16], mm2
422     movq [r0 + r2 + 24], mm3
423     jg .copy32
424     REP_RET
425
426 ;-----------------------------------------------------------------------------
427 ; void *x264_memcpy_aligned_sse2( void *dst, const void *src, size_t n );
428 ;-----------------------------------------------------------------------------
429 cglobal x264_memcpy_aligned_sse2, 3,3
430     test r2d, 16
431     jz .copy32
432     sub r2d, 16
433     movdqa xmm0, [r1 + r2]
434     movdqa [r0 + r2], xmm0
435 .copy32:
436     test r2d, 32
437     jz .copy64
438     sub r2d, 32
439     movdqa xmm0, [r1 + r2 +  0]
440     movdqa [r0 + r2 +  0], xmm0
441     movdqa xmm1, [r1 + r2 + 16]
442     movdqa [r0 + r2 + 16], xmm1
443 .copy64:
444     sub r2d, 64
445     movdqa xmm0, [r1 + r2 +  0]
446     movdqa [r0 + r2 +  0], xmm0
447     movdqa xmm1, [r1 + r2 + 16]
448     movdqa [r0 + r2 + 16], xmm1
449     movdqa xmm2, [r1 + r2 + 32]
450     movdqa [r0 + r2 + 32], xmm2
451     movdqa xmm3, [r1 + r2 + 48]
452     movdqa [r0 + r2 + 48], xmm3
453     jg .copy64
454     REP_RET
455
456 ;-----------------------------------------------------------------------------
457 ; void *x264_memzero_aligned( void *dst, size_t n );
458 ;-----------------------------------------------------------------------------
459 %macro MEMZERO 1
460 cglobal x264_memzero_aligned_%1, 2,2
461     pxor m0, m0
462 .loop:
463     sub r1d, regsize*8
464 %assign i 0
465 %rep 8
466     mova [r0 + r1 + i], m0
467 %assign i i+regsize
468 %endrep
469     jg .loop
470     REP_RET
471 %endmacro
472
473 INIT_MMX
474 MEMZERO mmx
475 INIT_XMM
476 MEMZERO sse2
477
478
479
480 %macro FILT8x4 7
481     mova      %3, [r0+%7]
482     mova      %4, [r0+r5+%7]
483     pavgb     %3, %4
484     pavgb     %4, [r0+r5*2+%7]
485     PALIGNR   %1, %3, 1, m6
486     PALIGNR   %2, %4, 1, m6
487     pavgb     %1, %3
488     pavgb     %2, %4
489     mova      %5, %1
490     mova      %6, %2
491     pand      %1, m7
492     pand      %2, m7
493     psrlw     %5, 8
494     psrlw     %6, 8
495 %endmacro
496
497 %macro FILT16x2 4
498     mova      m3, [r0+%4+regsize]
499     mova      m2, [r0+%4]
500     pavgb     m3, [r0+%4+r5+regsize]
501     pavgb     m2, [r0+%4+r5]
502     PALIGNR   %1, m3, 1, m6
503     pavgb     %1, m3
504     PALIGNR   m3, m2, 1, m6
505     pavgb     m3, m2
506     mova      m5, m3
507     mova      m4, %1
508     pand      m3, m7
509     pand      %1, m7
510     psrlw     m5, 8
511     psrlw     m4, 8
512     packuswb  m3, %1
513     packuswb  m5, m4
514     mova    [%2], m3
515     mova    [%3], m5
516     mova      %1, m2
517 %endmacro
518
519 %macro FILT8x2U 3
520     mova      m3, [r0+%3+8]
521     mova      m2, [r0+%3]
522     pavgb     m3, [r0+%3+r5+8]
523     pavgb     m2, [r0+%3+r5]
524     mova      m1, [r0+%3+9]
525     mova      m0, [r0+%3+1]
526     pavgb     m1, [r0+%3+r5+9]
527     pavgb     m0, [r0+%3+r5+1]
528     pavgb     m1, m3
529     pavgb     m0, m2
530     mova      m3, m1
531     mova      m2, m0
532     pand      m1, m7
533     pand      m0, m7
534     psrlw     m3, 8
535     psrlw     m2, 8
536     packuswb  m0, m1
537     packuswb  m2, m3
538     mova    [%1], m0
539     mova    [%2], m2
540 %endmacro
541
542 ;-----------------------------------------------------------------------------
543 ; void frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
544 ;                              int src_stride, int dst_stride, int width, int height )
545 ;-----------------------------------------------------------------------------
546 %macro FRAME_INIT_LOWRES 1 ; FIXME
547 cglobal x264_frame_init_lowres_core_%1, 6,7
548     ; src += 2*(height-1)*stride + 2*width
549     mov      r6d, r8m
550     dec      r6d
551     imul     r6d, r5d
552     add      r6d, r7m
553     lea       r0, [r0+r6*2]
554     ; dst += (height-1)*stride + width
555     mov      r6d, r8m
556     dec      r6d
557     imul     r6d, r6m
558     add      r6d, r7m
559     add       r1, r6
560     add       r2, r6
561     add       r3, r6
562     add       r4, r6
563     ; gap = stride - width
564     mov      r6d, r6m
565     sub      r6d, r7m
566     PUSH      r6
567     %define dst_gap [rsp+push_size]
568     mov      r6d, r5d
569     sub      r6d, r7m
570     shl      r6d, 1
571     PUSH      r6
572     %define src_gap [rsp]
573 %if regsize == 16
574     ; adjust for the odd end case
575     mov      r6d, r7m
576     and      r6d, 8
577     sub       r1, r6
578     sub       r2, r6
579     sub       r3, r6
580     sub       r4, r6
581     add  dst_gap, r6d
582 %endif ; regsize
583     pcmpeqb   m7, m7
584     psrlw     m7, 8
585 .vloop:
586     mov      r6d, r7m
587 %ifnidn %1, mmxext
588     mova      m0, [r0]
589     mova      m1, [r0+r5]
590     pavgb     m0, m1
591     pavgb     m1, [r0+r5*2]
592 %endif
593 %if regsize == 16
594     test     r6d, 8
595     jz .hloop
596     sub       r0, 16
597     FILT8x4   m0, m1, m2, m3, m4, m5, 0
598     packuswb  m0, m4
599     packuswb  m1, m5
600     movq    [r1], m0
601     movhps  [r2], m0
602     movq    [r3], m1
603     movhps  [r4], m1
604     mova      m0, m2
605     mova      m1, m3
606     sub      r6d, 8
607 %endif ; regsize
608 .hloop:
609     sub       r0, regsize*2
610     sub       r1, regsize
611     sub       r2, regsize
612     sub       r3, regsize
613     sub       r4, regsize
614 %ifdef m8
615     FILT8x4   m0, m1, m2, m3, m10, m11, regsize
616     mova      m8, m0
617     mova      m9, m1
618     FILT8x4   m2, m3, m0, m1, m4, m5, 0
619     packuswb  m2, m8
620     packuswb  m3, m9
621     packuswb  m4, m10
622     packuswb  m5, m11
623     mova    [r1], m2
624     mova    [r2], m4
625     mova    [r3], m3
626     mova    [r4], m5
627 %elifidn %1, mmxext
628     FILT8x2U  r1, r2, 0
629     FILT8x2U  r3, r4, r5
630 %else
631     FILT16x2  m0, r1, r2, 0
632     FILT16x2  m1, r3, r4, r5
633 %endif
634     sub      r6d, regsize
635     jg .hloop
636 .skip:
637     mov       r6, dst_gap
638     sub       r0, src_gap
639     sub       r1, r6
640     sub       r2, r6
641     sub       r3, r6
642     sub       r4, r6
643     dec    dword r8m
644     jg .vloop
645     ADD      rsp, 2*push_size
646     RET
647 %endmacro ; FRAME_INIT_LOWRES
648
649 INIT_MMX
650 %define PALIGNR PALIGNR_MMX
651 FRAME_INIT_LOWRES mmxext
652 %ifndef ARCH_X86_64
653 FRAME_INIT_LOWRES cache32_mmxext
654 %endif
655 INIT_XMM
656 FRAME_INIT_LOWRES sse2
657 %define PALIGNR PALIGNR_SSSE3
658 FRAME_INIT_LOWRES ssse3