checkasm check whether callee-saved regs are correctly saved
[x262.git] / common / x86 / mc-a.asm
1 ;*****************************************************************************
2 ;* mc-a.asm: h264 encoder library
3 ;*****************************************************************************
4 ;* Copyright (C) 2003-2008 x264 project
5 ;*
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>
7 ;*          Laurent Aimar <fenrir@via.ecp.fr>
8 ;*          Min Chen <chenm001.163.com>
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23 ;*****************************************************************************
24
25 %include "x86inc.asm"
26
27 SECTION_RODATA
28
29 pw_4:  times 4 dw  4
30 pw_8:  times 4 dw  8
31 pw_32: times 4 dw 32
32 pw_64: times 4 dw 64
33
34 SECTION .text
35
36 ;=============================================================================
37 ; pixel avg
38 ;=============================================================================
39
40 ;-----------------------------------------------------------------------------
41 ; void x264_pixel_avg_4x4_mmxext( uint8_t *dst, int dst_stride,
42 ;                                 uint8_t *src, int src_stride );
43 ;-----------------------------------------------------------------------------
44 %macro AVGH 2
45 %assign function_align 8 ; the whole function fits in 8 bytes, so a larger align just wastes space
46 cglobal x264_pixel_avg_%1x%2_mmxext
47     mov eax, %2
48     jmp x264_pixel_avg_w%1_mmxext
49 %assign function_align 16
50 %endmacro
51
52 ;-----------------------------------------------------------------------------
53 ; void x264_pixel_avg_w4_mmxext( uint8_t *dst, int dst_stride,
54 ;                                uint8_t *src, int src_stride,
55 ;                                int height );
56 ;-----------------------------------------------------------------------------
57 %ifdef ARCH_X86_64
58     %define t0 r0
59     %define t1 r1
60     %define t2 r2
61     %define t3 r3
62     %macro AVG_START 1
63         cglobal %1, 4,5
64         .height_loop:
65     %endmacro
66 %else
67     %define t0 r1
68     %define t1 r2
69     %define t2 r3
70     %define t3 r4
71     %macro AVG_START 1
72         cglobal %1, 0,5
73         mov t0, r0m
74         mov t1, r1m
75         mov t2, r2m
76         mov t3, r3m
77         .height_loop:
78     %endmacro
79 %endif
80
81 %macro AVG_END 0
82     sub    eax, 2
83     lea    t2, [t2+t3*2]
84     lea    t0, [t0+t1*2]
85     jg     .height_loop
86     REP_RET
87 %endmacro
88
89 AVG_START x264_pixel_avg_w4_mmxext
90     movd   mm0, [t2]
91     movd   mm1, [t2+t3]
92     pavgb  mm0, [t0]
93     pavgb  mm1, [t0+t1]
94     movd   [t0], mm0
95     movd   [t0+t1], mm1
96 AVG_END
97
98 AVGH 4, 8
99 AVGH 4, 4
100 AVGH 4, 2
101
102 AVG_START x264_pixel_avg_w8_mmxext
103     movq   mm0, [t2]
104     movq   mm1, [t2+t3]
105     pavgb  mm0, [t0]
106     pavgb  mm1, [t0+t1]
107     movq   [t0], mm0
108     movq   [t0+t1], mm1
109 AVG_END
110
111 AVGH 8, 16
112 AVGH 8, 8
113 AVGH 8, 4
114
115 AVG_START x264_pixel_avg_w16_mmxext
116     movq   mm0, [t2  ]
117     movq   mm1, [t2+8]
118     movq   mm2, [t2+t3  ]
119     movq   mm3, [t2+t3+8]
120     pavgb  mm0, [t0  ]
121     pavgb  mm1, [t0+8]
122     pavgb  mm2, [t0+t1  ]
123     pavgb  mm3, [t0+t1+8]
124     movq   [t0  ], mm0
125     movq   [t0+8], mm1
126     movq   [t0+t1  ], mm2
127     movq   [t0+t1+8], mm3
128 AVG_END
129
130 AVGH 16, 16
131 AVGH 16, 8
132
133 AVG_START x264_pixel_avg_w16_sse2
134     movdqu xmm0, [t2]
135     movdqu xmm1, [t2+t3]
136     pavgb  xmm0, [t0]
137     pavgb  xmm1, [t0+t1]
138     movdqa [t0], xmm0
139     movdqa [t0+t1], xmm1
140 AVG_END
141
142
143
144 ;=============================================================================
145 ; pixel avg2
146 ;=============================================================================
147
148 ;-----------------------------------------------------------------------------
149 ; void x264_pixel_avg2_w4_mmxext( uint8_t *dst, int dst_stride,
150 ;                                 uint8_t *src1, int src_stride,
151 ;                                 uint8_t *src2, int height );
152 ;-----------------------------------------------------------------------------
153 %macro AVG2_W8 2
154 cglobal x264_pixel_avg2_w%1_mmxext, 6,7
155     sub    r4, r2
156     lea    r6, [r4+r3]
157 .height_loop:
158     %2     mm0, [r2]
159     %2     mm1, [r2+r3]
160     pavgb  mm0, [r2+r4]
161     pavgb  mm1, [r2+r6]
162     %2     [r0], mm0
163     %2     [r0+r1], mm1
164     sub    r5d, 2
165     lea    r2, [r2+r3*2]
166     lea    r0, [r0+r1*2]
167     jg     .height_loop
168     REP_RET
169 %endmacro
170
171 AVG2_W8 4, movd
172 AVG2_W8 8, movq
173
174 %macro AVG2_W16 2
175 cglobal x264_pixel_avg2_w%1_mmxext, 6,7
176     sub    r4, r2
177     lea    r6, [r4+r3]
178 .height_loop:
179     movq   mm0, [r2]
180     %2     mm1, [r2+8]
181     movq   mm2, [r2+r3]
182     %2     mm3, [r2+r3+8]
183     pavgb  mm0, [r2+r4]
184     pavgb  mm1, [r2+r4+8]
185     pavgb  mm2, [r2+r6]
186     pavgb  mm3, [r2+r6+8]
187     movq   [r0], mm0
188     %2     [r0+8], mm1
189     movq   [r0+r1], mm2
190     %2     [r0+r1+8], mm3
191     lea    r2, [r2+r3*2]
192     lea    r0, [r0+r1*2]
193     sub    r5d, 2
194     jg     .height_loop
195     REP_RET
196 %endmacro
197
198 AVG2_W16 12, movd
199 AVG2_W16 16, movq
200
201 cglobal x264_pixel_avg2_w20_mmxext, 6,7
202     sub    r4, r2
203     lea    r6, [r4+r3]
204 .height_loop:
205     movq   mm0, [r2]
206     movq   mm1, [r2+8]
207     movd   mm2, [r2+16]
208     movq   mm3, [r2+r3]
209     movq   mm4, [r2+r3+8]
210     movd   mm5, [r2+r3+16]
211     pavgb  mm0, [r2+r4]
212     pavgb  mm1, [r2+r4+8]
213     pavgb  mm2, [r2+r4+16]
214     pavgb  mm3, [r2+r6]
215     pavgb  mm4, [r2+r6+8]
216     pavgb  mm5, [r2+r6+16]
217     movq   [r0], mm0
218     movq   [r0+8], mm1
219     movd   [r0+16], mm2
220     movq   [r0+r1], mm3
221     movq   [r0+r1+8], mm4
222     movd   [r0+r1+16], mm5
223     lea    r2, [r2+r3*2]
224     lea    r0, [r0+r1*2]
225     sub    r5d, 2
226     jg     .height_loop
227     REP_RET
228
229
230
231 ;=============================================================================
232 ; pixel copy
233 ;=============================================================================
234
235 %macro COPY4 3
236     %1  mm0, [r2]
237     %1  mm1, [r2+r3]
238     %1  mm2, [r2+r3*2]
239     %1  mm3, [r2+%3]
240     %1  [r0],      mm0
241     %1  [r0+r1],   mm1
242     %1  [r0+r1*2], mm2
243     %1  [r0+%2],   mm3
244 %endmacro
245
246 ;-----------------------------------------------------------------------------
247 ; void x264_mc_copy_w4_mmx( uint8_t *dst, int i_dst_stride,
248 ;                           uint8_t *src, int i_src_stride, int i_height )
249 ;-----------------------------------------------------------------------------
250 cglobal x264_mc_copy_w4_mmx, 4,6
251     cmp     r4m, dword 4
252     lea     r5, [r3*3]
253     lea     r4, [r1*3]
254     je .end
255     COPY4 movd, r4, r5
256     lea     r2, [r2+r3*4]
257     lea     r0, [r0+r1*4]
258 .end:
259     COPY4 movd, r4, r5
260     RET
261
262 cglobal x264_mc_copy_w8_mmx, 5,7
263     lea     r6, [r3*3]
264     lea     r5, [r1*3]
265 .height_loop:
266     COPY4 movq, r5, r6
267     lea     r2, [r2+r3*4]
268     lea     r0, [r0+r1*4]
269     sub     r4d, 4
270     jg      .height_loop
271     REP_RET
272
273 cglobal x264_mc_copy_w16_mmx, 5,7
274     lea     r6, [r3*3]
275     lea     r5, [r1*3]
276 .height_loop:
277     movq    mm0, [r2]
278     movq    mm1, [r2+8]
279     movq    mm2, [r2+r3]
280     movq    mm3, [r2+r3+8]
281     movq    mm4, [r2+r3*2]
282     movq    mm5, [r2+r3*2+8]
283     movq    mm6, [r2+r6]
284     movq    mm7, [r2+r6+8]
285     movq    [r0], mm0
286     movq    [r0+8], mm1
287     movq    [r0+r1], mm2
288     movq    [r0+r1+8], mm3
289     movq    [r0+r1*2], mm4
290     movq    [r0+r1*2+8], mm5
291     movq    [r0+r5], mm6
292     movq    [r0+r5+8], mm7
293     lea     r2, [r2+r3*4]
294     lea     r0, [r0+r1*4]
295     sub     r4d, 4
296     jg      .height_loop
297     REP_RET
298
299
300
301 ;=============================================================================
302 ; weighted prediction
303 ;=============================================================================
304 ; implicit bipred only:
305 ; assumes log2_denom = 5, offset = 0, weight1 + weight2 = 64
306
307 %macro BIWEIGHT_4P_MMX 2
308     movd      mm0, %1
309     movd      mm1, %2
310     punpcklbw mm0, mm7
311     punpcklbw mm1, mm7
312     pmullw    mm0, mm4
313     pmullw    mm1, mm5
314     paddw     mm0, mm1
315     paddw     mm0, mm6
316     psraw     mm0, 6
317     pmaxsw    mm0, mm7
318     packuswb  mm0, mm0
319     movd      %1,  mm0
320 %endmacro
321
322 %macro BIWEIGHT_START_MMX 1
323 %ifidn r4m, r4d
324     movd    mm4, r4m
325     pshufw  mm4, mm4, 0   ; weight_dst
326 %else
327     pshufw  mm4, r4m, 0
328 %endif
329     picgetgot r4
330     movq    mm5, [pw_64 GLOBAL]
331     psubw   mm5, mm4      ; weight_src
332     movq    mm6, [pw_32 GLOBAL] ; rounding
333     pxor    mm7, mm7
334 %if %1
335 %ifidn r5m, r5d
336     %define t0 r5d
337 %else
338     %define t0 r4d
339     mov  r4d, r5m
340 %endif
341 %endif
342 .height_loop:
343 %endmacro
344
345 ;-----------------------------------------------------------------------------
346 ; int x264_pixel_avg_weight_w16_mmxext( uint8_t *dst, int, uint8_t *src, int, int i_weight, int )
347 ;-----------------------------------------------------------------------------
348 cglobal x264_pixel_avg_weight_w16_mmxext, 4,5
349     BIWEIGHT_START_MMX 1
350     BIWEIGHT_4P_MMX  [r0   ], [r2   ]
351     BIWEIGHT_4P_MMX  [r0+ 4], [r2+ 4]
352     BIWEIGHT_4P_MMX  [r0+ 8], [r2+ 8]
353     BIWEIGHT_4P_MMX  [r0+12], [r2+12]
354     add  r0, r1
355     add  r2, r3
356     dec  t0
357     jg   .height_loop
358     REP_RET
359
360 ;-----------------------------------------------------------------------------
361 ; int x264_pixel_avg_weight_w8_mmxext( uint8_t *, int, uint8_t *, int, int, int )
362 ;-----------------------------------------------------------------------------
363 cglobal x264_pixel_avg_weight_w8_mmxext, 4,5
364     BIWEIGHT_START_MMX 1
365     BIWEIGHT_4P_MMX  [r0  ], [r2  ]
366     BIWEIGHT_4P_MMX  [r0+4], [r2+4]
367     add  r0, r1
368     add  r2, r3
369     dec  t0
370     jg   .height_loop
371     REP_RET
372
373 ;-----------------------------------------------------------------------------
374 ; int x264_pixel_avg_weight_4x4_mmxext( uint8_t *, int, uint8_t *, int, int )
375 ;-----------------------------------------------------------------------------
376 cglobal x264_pixel_avg_weight_4x4_mmxext, 4,4,1
377     BIWEIGHT_START_MMX 0
378     BIWEIGHT_4P_MMX  [r0     ], [r2     ]
379     BIWEIGHT_4P_MMX  [r0+r1  ], [r2+r3  ]
380     BIWEIGHT_4P_MMX  [r0+r1*2], [r2+r3*2]
381     add  r0, r1
382     add  r2, r3
383     BIWEIGHT_4P_MMX  [r0+r1*2], [r2+r3*2]
384     RET
385
386
387
388 ;=============================================================================
389 ; prefetch
390 ;=============================================================================
391 ; FIXME assumes 64 byte cachelines
392
393 ;-----------------------------------------------------------------------------
394 ; void x264_prefetch_fenc_mmxext( uint8_t *pix_y, int stride_y, 
395 ;                                 uint8_t *pix_uv, int stride_uv, int mb_x )
396 ;-----------------------------------------------------------------------------
397 %ifdef ARCH_X86_64
398 cglobal x264_prefetch_fenc_mmxext, 5,5
399     mov    eax, r4d
400     and    eax, 3
401     imul   eax, r1d
402     lea    r0,  [r0+rax*4+64]
403     prefetcht0  [r0]
404     prefetcht0  [r0+r1]
405     lea    r0,  [r0+r1*2]
406     prefetcht0  [r0]
407     prefetcht0  [r0+r1]
408
409     and    r4d, 6
410     imul   r4d, r3d
411     lea    r2,  [r2+r4+64]
412     prefetcht0  [r2]
413     prefetcht0  [r2+r3]
414     ret
415
416 %else
417 cglobal x264_prefetch_fenc_mmxext
418     mov    r2, [esp+20]
419     mov    r1, [esp+8]
420     mov    r0, [esp+4]
421     and    r2, 3
422     imul   r2, r1
423     lea    r0, [r0+r2*4+64]
424     prefetcht0 [r0]
425     prefetcht0 [r0+r1]
426     lea    r0, [r0+r1*2]
427     prefetcht0 [r0]
428     prefetcht0 [r0+r1]
429
430     mov    r2, [esp+20]
431     mov    r1, [esp+16]
432     mov    r0, [esp+12]
433     and    r2, 6
434     imul   r2, r1
435     lea    r0, [r0+r2+64]
436     prefetcht0 [r0]
437     prefetcht0 [r0+r1]
438     ret
439 %endif ; ARCH_X86_64
440
441 ;-----------------------------------------------------------------------------
442 ; void x264_prefetch_ref_mmxext( uint8_t *pix, int stride, int parity )
443 ;-----------------------------------------------------------------------------
444 cglobal x264_prefetch_ref_mmxext, 3,3
445     dec    r2d
446     and    r2d, r1d
447     lea    r0,  [r0+r2*8+64]
448     lea    r2,  [r1*3]
449     prefetcht0  [r0]
450     prefetcht0  [r0+r1]
451     prefetcht0  [r0+r1*2]
452     prefetcht0  [r0+r2]
453     lea    r0,  [r0+r1*4]
454     prefetcht0  [r0]
455     prefetcht0  [r0+r1]
456     prefetcht0  [r0+r1*2]
457     prefetcht0  [r0+r2]
458     ret
459
460
461
462 ;=============================================================================
463 ; chroma MC
464 ;=============================================================================
465
466 ;-----------------------------------------------------------------------------
467 ; void x264_mc_chroma_mmxext( uint8_t *dst, int i_dst_stride,
468 ;                             uint8_t *src, int i_src_stride,
469 ;                             int dx, int dy,
470 ;                             int i_width, int i_height )
471 ;-----------------------------------------------------------------------------
472 cglobal x264_mc_chroma_mmxext, 0,6,1
473 %ifdef ARCH_X86_64
474     %define t0   r10d
475 %else
476     %define t0   r1d
477 %endif
478     movifnidn r2d, r2m
479     movifnidn r3d, r3m
480     movifnidn r4d, r4m
481     movifnidn r5d, r5m
482     mov     eax, r5d
483     mov     t0,  r4d
484     sar     eax, 3
485     sar     t0,  3
486     imul    eax, r3d
487     pxor    mm3, mm3
488     add     eax, t0
489     movsxdifnidn rax, eax
490     add     r2,  rax            ; src += (dx>>3) + (dy>>3) * src_stride
491     and     r4d, 7              ; dx &= 7
492     je      .mc1d
493     and     r5d, 7              ; dy &= 7
494     je      .mc1d
495
496     movd    mm0, r4d
497     movd    mm1, r5d
498     pshufw  mm5, mm0, 0         ; mm5 = dx
499     pshufw  mm6, mm1, 0         ; mm6 = dy
500
501     movq    mm4, [pw_8 GLOBAL]
502     movq    mm0, mm4
503     psubw   mm4, mm5            ; mm4 = 8-dx
504     psubw   mm0, mm6            ; mm0 = 8-dy
505
506     movq    mm7, mm5
507     pmullw  mm5, mm0            ; mm5 = dx*(8-dy) =     cB
508     pmullw  mm7, mm6            ; mm7 = dx*dy =         cD
509     pmullw  mm6, mm4            ; mm6 = (8-dx)*dy =     cC
510     pmullw  mm4, mm0            ; mm4 = (8-dx)*(8-dy) = cA
511
512     mov     r4d, r7m
513 %ifdef ARCH_X86_64
514     mov     r10, r0
515     mov     r11, r2
516 %else
517     mov     r0,  r0m
518     mov     r1,  r1m
519     mov     r5,  r2
520 %endif
521
522 ALIGN 4
523 .height_loop
524
525     movd    mm1, [r2+r3]
526     movd    mm0, [r2]
527     punpcklbw mm1, mm3          ; 00 px1 | 00 px2 | 00 px3 | 00 px4
528     punpcklbw mm0, mm3
529     pmullw  mm1, mm6            ; 2nd line * cC
530     pmullw  mm0, mm4            ; 1st line * cA
531     paddw   mm0, mm1            ; mm0 <- result
532
533     movd    mm2, [r2+1]
534     movd    mm1, [r2+r3+1]
535     punpcklbw mm2, mm3
536     punpcklbw mm1, mm3
537
538     paddw   mm0, [pw_32 GLOBAL]
539
540     pmullw  mm2, mm5            ; line * cB
541     pmullw  mm1, mm7            ; line * cD
542     paddw   mm0, mm2
543     paddw   mm0, mm1
544     psrlw   mm0, 6
545
546     packuswb mm0, mm3           ; 00 00 00 00 px1 px2 px3 px4
547     movd    [r0], mm0
548
549     add     r2,  r3
550     add     r0,  r1             ; i_dst_stride
551     dec     r4d
552     jnz     .height_loop
553
554     sub dword r6m, 8
555     jnz     .finish             ; width != 8 so assume 4
556
557 %ifdef ARCH_X86_64
558     lea     r0, [r10+4]         ; dst
559     lea     r2, [r11+4]         ; src
560 %else
561     mov     r0,  r0m
562     lea     r2, [r5+4]
563     add     r0,  4
564 %endif
565     mov     r4d, r7m            ; i_height
566     jmp     .height_loop
567
568 .finish
569     REP_RET
570
571 ALIGN 4
572 .mc1d
573     mov       eax, r4d
574     or        eax, r5d
575     and       eax, 7
576     cmp       r4d, 0
577     mov       r5d, 1
578     cmove     r5,  r3           ; pel_offset = dx ? 1 : src_stride
579     movd      mm6, eax
580     movq      mm5, [pw_8 GLOBAL]
581     pshufw    mm6, mm6, 0
582     movq      mm7, [pw_4 GLOBAL]
583     psubw     mm5, mm6
584
585     cmp dword r6m, 8
586     movifnidn r0d, r0m
587     movifnidn r1d, r1m
588     mov       r4d, r7m
589     je .height_loop1_w8
590
591 ALIGN 4
592 .height_loop1_w4
593     movd      mm0, [r2+r5]
594     movd      mm1, [r2]
595     punpcklbw mm0, mm3
596     punpcklbw mm1, mm3
597     pmullw    mm0, mm6
598     pmullw    mm1, mm5
599     paddw     mm0, mm7
600     paddw     mm0, mm1
601     psrlw     mm0, 3
602     packuswb  mm0, mm3
603     movd     [r0], mm0
604     add       r2,  r3
605     add       r0,  r1
606     dec       r4d
607     jnz .height_loop1_w4
608     REP_RET
609
610 ALIGN 4
611 .height_loop1_w8
612     movq      mm0, [r2+r5]
613     movq      mm1, [r2]
614     movq      mm2, mm0
615     movq      mm4, mm1
616     punpcklbw mm0, mm3
617     punpcklbw mm1, mm3
618     punpckhbw mm2, mm3
619     punpckhbw mm4, mm3
620     pmullw    mm0, mm6
621     pmullw    mm1, mm5
622     pmullw    mm2, mm6
623     pmullw    mm4, mm5
624     paddw     mm0, mm7
625     paddw     mm2, mm7
626     paddw     mm0, mm1
627     paddw     mm2, mm4
628     psrlw     mm0, 3
629     psrlw     mm2, 3
630     packuswb  mm0, mm2
631     movq     [r0], mm0
632     add       r2,  r3
633     add       r0,  r1
634     dec       r4d
635     jnz .height_loop1_w8
636     REP_RET
637