bbf8539292f00f43377053c7c352b2974cf4aef7
[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 sw_64: dd 64
34
35 SECTION .text
36
37 ;=============================================================================
38 ; pixel avg
39 ;=============================================================================
40
41 ;-----------------------------------------------------------------------------
42 ; void x264_pixel_avg_4x4_mmxext( uint8_t *dst, int dst_stride,
43 ;                                 uint8_t *src, int src_stride );
44 ;-----------------------------------------------------------------------------
45 %macro AVGH 3
46 %assign function_align 8 ; the whole function fits in 8 bytes, so a larger align just wastes space
47 cglobal x264_pixel_avg_%1x%2_%3
48     mov eax, %2
49     jmp x264_pixel_avg_w%1_%3
50 %assign function_align 16
51 %endmacro
52
53 ;-----------------------------------------------------------------------------
54 ; void x264_pixel_avg_w4_mmxext( uint8_t *dst, int dst_stride,
55 ;                                uint8_t *src, int src_stride,
56 ;                                int height );
57 ;-----------------------------------------------------------------------------
58 %ifdef ARCH_X86_64
59     %define t0 r0
60     %define t1 r1
61     %define t2 r2
62     %define t3 r3
63     %macro AVG_START 1
64         cglobal %1, 4,5
65         .height_loop:
66     %endmacro
67 %else
68     %define t0 r1
69     %define t1 r2
70     %define t2 r3
71     %define t3 r4
72     %macro AVG_START 1
73         cglobal %1, 0,5
74         mov t0, r0m
75         mov t1, r1m
76         mov t2, r2m
77         mov t3, r3m
78         .height_loop:
79     %endmacro
80 %endif
81
82 %macro AVG_END 0
83     sub    eax, 2
84     lea    t2, [t2+t3*2]
85     lea    t0, [t0+t1*2]
86     jg     .height_loop
87     REP_RET
88 %endmacro
89
90 AVG_START x264_pixel_avg_w4_mmxext
91     movd   mm0, [t2]
92     movd   mm1, [t2+t3]
93     pavgb  mm0, [t0]
94     pavgb  mm1, [t0+t1]
95     movd   [t0], mm0
96     movd   [t0+t1], mm1
97 AVG_END
98
99 AVGH 4, 8, mmxext
100 AVGH 4, 4, mmxext
101 AVGH 4, 2, mmxext
102
103 AVG_START x264_pixel_avg_w8_mmxext
104     movq   mm0, [t2]
105     movq   mm1, [t2+t3]
106     pavgb  mm0, [t0]
107     pavgb  mm1, [t0+t1]
108     movq   [t0], mm0
109     movq   [t0+t1], mm1
110 AVG_END
111
112 AVGH 8, 16, mmxext
113 AVGH 8, 8,  mmxext
114 AVGH 8, 4,  mmxext
115
116 AVG_START x264_pixel_avg_w16_mmxext
117     movq   mm0, [t2  ]
118     movq   mm1, [t2+8]
119     movq   mm2, [t2+t3  ]
120     movq   mm3, [t2+t3+8]
121     pavgb  mm0, [t0  ]
122     pavgb  mm1, [t0+8]
123     pavgb  mm2, [t0+t1  ]
124     pavgb  mm3, [t0+t1+8]
125     movq   [t0  ], mm0
126     movq   [t0+8], mm1
127     movq   [t0+t1  ], mm2
128     movq   [t0+t1+8], mm3
129 AVG_END
130
131 AVGH 16, 16, mmxext
132 AVGH 16, 8,  mmxext
133
134 AVG_START x264_pixel_avg_w16_sse2
135     movdqu xmm0, [t2]
136     movdqu xmm1, [t2+t3]
137     pavgb  xmm0, [t0]
138     pavgb  xmm1, [t0+t1]
139     movdqa [t0], xmm0
140     movdqa [t0+t1], xmm1
141 AVG_END
142
143 AVGH 16, 16, sse2
144 AVGH 16, 8,  sse2
145
146
147
148 ;=============================================================================
149 ; pixel avg2
150 ;=============================================================================
151
152 ;-----------------------------------------------------------------------------
153 ; void x264_pixel_avg2_w4_mmxext( uint8_t *dst, int dst_stride,
154 ;                                 uint8_t *src1, int src_stride,
155 ;                                 uint8_t *src2, int height );
156 ;-----------------------------------------------------------------------------
157 %macro AVG2_W8 2
158 cglobal x264_pixel_avg2_w%1_mmxext, 6,7
159     sub    r4, r2
160     lea    r6, [r4+r3]
161 .height_loop:
162     %2     mm0, [r2]
163     %2     mm1, [r2+r3]
164     pavgb  mm0, [r2+r4]
165     pavgb  mm1, [r2+r6]
166     %2     [r0], mm0
167     %2     [r0+r1], mm1
168     sub    r5d, 2
169     lea    r2, [r2+r3*2]
170     lea    r0, [r0+r1*2]
171     jg     .height_loop
172     REP_RET
173 %endmacro
174
175 AVG2_W8 4, movd
176 AVG2_W8 8, movq
177
178 %macro AVG2_W16 2
179 cglobal x264_pixel_avg2_w%1_mmxext, 6,7
180     sub    r4, r2
181     lea    r6, [r4+r3]
182 .height_loop:
183     movq   mm0, [r2]
184     %2     mm1, [r2+8]
185     movq   mm2, [r2+r3]
186     %2     mm3, [r2+r3+8]
187     pavgb  mm0, [r2+r4]
188     pavgb  mm1, [r2+r4+8]
189     pavgb  mm2, [r2+r6]
190     pavgb  mm3, [r2+r6+8]
191     movq   [r0], mm0
192     %2     [r0+8], mm1
193     movq   [r0+r1], mm2
194     %2     [r0+r1+8], mm3
195     lea    r2, [r2+r3*2]
196     lea    r0, [r0+r1*2]
197     sub    r5d, 2
198     jg     .height_loop
199     REP_RET
200 %endmacro
201
202 AVG2_W16 12, movd
203 AVG2_W16 16, movq
204
205 cglobal x264_pixel_avg2_w20_mmxext, 6,7
206     sub    r4, r2
207     lea    r6, [r4+r3]
208 .height_loop:
209     movq   mm0, [r2]
210     movq   mm1, [r2+8]
211     movd   mm2, [r2+16]
212     movq   mm3, [r2+r3]
213     movq   mm4, [r2+r3+8]
214     movd   mm5, [r2+r3+16]
215     pavgb  mm0, [r2+r4]
216     pavgb  mm1, [r2+r4+8]
217     pavgb  mm2, [r2+r4+16]
218     pavgb  mm3, [r2+r6]
219     pavgb  mm4, [r2+r6+8]
220     pavgb  mm5, [r2+r6+16]
221     movq   [r0], mm0
222     movq   [r0+8], mm1
223     movd   [r0+16], mm2
224     movq   [r0+r1], mm3
225     movq   [r0+r1+8], mm4
226     movd   [r0+r1+16], mm5
227     lea    r2, [r2+r3*2]
228     lea    r0, [r0+r1*2]
229     sub    r5d, 2
230     jg     .height_loop
231     REP_RET
232
233 %macro PIXEL_AVG_SSE 1
234 cglobal x264_pixel_avg2_w16_%1, 6,7
235     sub    r4, r2
236     lea    r6, [r4+r3]
237 .height_loop:
238     movdqu xmm0, [r2]
239     movdqu xmm2, [r2+r3]
240     movdqu xmm1, [r2+r4]
241     movdqu xmm3, [r2+r6]
242     pavgb  xmm0, xmm1
243     pavgb  xmm2, xmm3
244     movdqa [r0], xmm0
245     movdqa [r0+r1], xmm2
246     lea    r2, [r2+r3*2]
247     lea    r0, [r0+r1*2]
248     sub    r5d, 2
249     jg     .height_loop
250     REP_RET
251
252 cglobal x264_pixel_avg2_w20_%1, 6,7
253     sub    r4, r2
254     lea    r6, [r4+r3]
255 .height_loop:
256     movdqu xmm0, [r2]
257     movdqu xmm2, [r2+r3]
258     movdqu xmm1, [r2+r4]
259     movdqu xmm3, [r2+r6]
260     movd   mm4,  [r2+16]
261     movd   mm5,  [r2+r3+16]
262     pavgb  xmm0, xmm1
263     pavgb  xmm2, xmm3
264     pavgb  mm4,  [r2+r4+16]
265     pavgb  mm5,  [r2+r6+16]
266     movdqa [r0], xmm0
267     movd   [r0+16], mm4
268     movdqa [r0+r1], xmm2
269     movd   [r0+r1+16], mm5
270     lea    r2, [r2+r3*2]
271     lea    r0, [r0+r1*2]
272     sub    r5d, 2
273     jg     .height_loop
274     REP_RET
275 %endmacro
276
277 PIXEL_AVG_SSE sse2
278 %define movdqu lddqu
279 PIXEL_AVG_SSE sse3
280 %undef movdqu
281
282 ; Cacheline split code for processors with high latencies for loads
283 ; split over cache lines.  See sad-a.asm for a more detailed explanation.
284 ; This particular instance is complicated by the fact that src1 and src2
285 ; can have different alignments.  For simplicity and code size, only the
286 ; MMX cacheline workaround is used.  As a result, in the case of SSE2
287 ; pixel_avg, the cacheline check functions calls the SSE2 version if there
288 ; is no cacheline split, and the MMX workaround if there is.
289
290 %macro INIT_SHIFT 2
291     and    eax, 7
292     shl    eax, 3
293 %ifdef PIC32
294     ; both versions work, but picgetgot is slower than gpr->mmx is slower than mem->mmx
295     mov    r2, 64
296     sub    r2, eax
297     movd   %2, eax
298     movd   %1, r2
299 %else
300     movd   %1, [sw_64 GLOBAL]
301     movd   %2, eax
302     psubw  %1, %2
303 %endif
304 %endmacro
305
306 %macro AVG_CACHELINE_CHECK 3 ; width, cacheline, instruction set
307 cglobal x264_pixel_avg2_w%1_cache%2_%3, 0,0
308     mov    eax, r2m
309     and    eax, 0x1f|(%2>>1)
310     cmp    eax, (32-%1)|(%2>>1)
311     jle x264_pixel_avg2_w%1_%3
312 ;w12 isn't needed because w16 is just as fast if there's no cacheline split
313 %if %1 == 12
314     jmp x264_pixel_avg2_w16_cache_mmxext
315 %else
316     jmp x264_pixel_avg2_w%1_cache_mmxext
317 %endif
318 %endmacro
319
320 %macro AVG_CACHELINE_START 0
321     %assign stack_offset 0
322     INIT_SHIFT mm6, mm7
323     mov    eax, r4m
324     INIT_SHIFT mm4, mm5
325     PROLOGUE 6,6,0
326     and    r2, ~7
327     and    r4, ~7
328     sub    r4, r2
329 .height_loop:
330 %endmacro
331
332 %macro AVG_CACHELINE_LOOP 2
333     movq   mm0, [r2+8+%1]
334     movq   mm1, [r2+%1]
335     movq   mm2, [r2+r4+8+%1]
336     movq   mm3, [r2+r4+%1]
337     psllq  mm0, mm6
338     psrlq  mm1, mm7
339     psllq  mm2, mm4
340     psrlq  mm3, mm5
341     por    mm0, mm1
342     por    mm2, mm3
343     pavgb  mm0, mm2
344     %2 [r0+%1], mm0
345 %endmacro
346
347 x264_pixel_avg2_w8_cache_mmxext:
348     AVG_CACHELINE_START
349     AVG_CACHELINE_LOOP 0, movq
350     add    r2, r3
351     add    r0, r1
352     dec    r5d
353     jg     .height_loop
354     RET
355
356 x264_pixel_avg2_w16_cache_mmxext:
357     AVG_CACHELINE_START
358     AVG_CACHELINE_LOOP 0, movq
359     AVG_CACHELINE_LOOP 8, movq
360     add    r2, r3
361     add    r0, r1
362     dec    r5d
363     jg .height_loop
364     RET
365
366 x264_pixel_avg2_w20_cache_mmxext:
367     AVG_CACHELINE_START
368     AVG_CACHELINE_LOOP 0, movq
369     AVG_CACHELINE_LOOP 8, movq
370     AVG_CACHELINE_LOOP 16, movd
371     add    r2, r3
372     add    r0, r1
373     dec    r5d
374     jg .height_loop
375     RET
376
377 %ifndef ARCH_X86_64
378 AVG_CACHELINE_CHECK  8, 32, mmxext
379 AVG_CACHELINE_CHECK 12, 32, mmxext
380 AVG_CACHELINE_CHECK 16, 32, mmxext
381 AVG_CACHELINE_CHECK 20, 32, mmxext
382 AVG_CACHELINE_CHECK 16, 64, mmxext
383 AVG_CACHELINE_CHECK 20, 64, mmxext
384 %endif
385
386 AVG_CACHELINE_CHECK  8, 64, mmxext
387 AVG_CACHELINE_CHECK 12, 64, mmxext
388 AVG_CACHELINE_CHECK 16, 64, sse2
389 AVG_CACHELINE_CHECK 20, 64, sse2
390
391 ;=============================================================================
392 ; pixel copy
393 ;=============================================================================
394
395 %macro COPY4 3
396     %1  mm0, [r2]
397     %1  mm1, [r2+r3]
398     %1  mm2, [r2+r3*2]
399     %1  mm3, [r2+%3]
400     %1  [r0],      mm0
401     %1  [r0+r1],   mm1
402     %1  [r0+r1*2], mm2
403     %1  [r0+%2],   mm3
404 %endmacro
405
406 ;-----------------------------------------------------------------------------
407 ; void x264_mc_copy_w4_mmx( uint8_t *dst, int i_dst_stride,
408 ;                           uint8_t *src, int i_src_stride, int i_height )
409 ;-----------------------------------------------------------------------------
410 cglobal x264_mc_copy_w4_mmx, 4,6
411     cmp     r4m, dword 4
412     lea     r5, [r3*3]
413     lea     r4, [r1*3]
414     je .end
415     COPY4 movd, r4, r5
416     lea     r2, [r2+r3*4]
417     lea     r0, [r0+r1*4]
418 .end:
419     COPY4 movd, r4, r5
420     RET
421
422 cglobal x264_mc_copy_w8_mmx, 5,7
423     lea     r6, [r3*3]
424     lea     r5, [r1*3]
425 .height_loop:
426     COPY4 movq, r5, r6
427     lea     r2, [r2+r3*4]
428     lea     r0, [r0+r1*4]
429     sub     r4d, 4
430     jg      .height_loop
431     REP_RET
432
433 cglobal x264_mc_copy_w16_mmx, 5,7
434     lea     r6, [r3*3]
435     lea     r5, [r1*3]
436 .height_loop:
437     movq    mm0, [r2]
438     movq    mm1, [r2+8]
439     movq    mm2, [r2+r3]
440     movq    mm3, [r2+r3+8]
441     movq    mm4, [r2+r3*2]
442     movq    mm5, [r2+r3*2+8]
443     movq    mm6, [r2+r6]
444     movq    mm7, [r2+r6+8]
445     movq    [r0], mm0
446     movq    [r0+8], mm1
447     movq    [r0+r1], mm2
448     movq    [r0+r1+8], mm3
449     movq    [r0+r1*2], mm4
450     movq    [r0+r1*2+8], mm5
451     movq    [r0+r5], mm6
452     movq    [r0+r5+8], mm7
453     lea     r2, [r2+r3*4]
454     lea     r0, [r0+r1*4]
455     sub     r4d, 4
456     jg      .height_loop
457     REP_RET
458
459 %macro COPY_W16_SSE2 2
460 cglobal %1, 5,7
461     lea     r6, [r3*3]
462     lea     r5, [r1*3]
463 .height_loop:
464     %2      xmm0, [r2]
465     %2      xmm1, [r2+r3]
466     %2      xmm2, [r2+r3*2]
467     %2      xmm3, [r2+r6]
468     movdqa  [r0], xmm0
469     movdqa  [r0+r1], xmm1
470     movdqa  [r0+r1*2], xmm2
471     movdqa  [r0+r5], xmm3
472     lea     r2, [r2+r3*4]
473     lea     r0, [r0+r1*4]
474     sub     r4d, 4
475     jg      .height_loop
476     REP_RET
477 %endmacro
478
479 COPY_W16_SSE2 x264_mc_copy_w16_sse2, movdqu
480 ; cacheline split with mmx has too much overhead; the speed benefit is near-zero.
481 ; but with SSE3 the overhead is zero, so there's no reason not to include it.
482 COPY_W16_SSE2 x264_mc_copy_w16_sse3, lddqu
483 COPY_W16_SSE2 x264_mc_copy_w16_aligned_sse2, movdqa
484
485
486
487 ;=============================================================================
488 ; weighted prediction
489 ;=============================================================================
490 ; implicit bipred only:
491 ; assumes log2_denom = 5, offset = 0, weight1 + weight2 = 64
492
493 %macro BIWEIGHT_4P_MMX 2
494     movd      mm0, %1
495     movd      mm1, %2
496     punpcklbw mm0, mm7
497     punpcklbw mm1, mm7
498     pmullw    mm0, mm4
499     pmullw    mm1, mm5
500     paddw     mm0, mm1
501     paddw     mm0, mm6
502     psraw     mm0, 6
503     pmaxsw    mm0, mm7
504     packuswb  mm0, mm0
505     movd      %1,  mm0
506 %endmacro
507
508 %macro BIWEIGHT_START_MMX 1
509 %ifidn r4m, r4d
510     movd    mm4, r4m
511     pshufw  mm4, mm4, 0   ; weight_dst
512 %else
513     pshufw  mm4, r4m, 0
514 %endif
515     picgetgot r4
516     movq    mm5, [pw_64 GLOBAL]
517     psubw   mm5, mm4      ; weight_src
518     movq    mm6, [pw_32 GLOBAL] ; rounding
519     pxor    mm7, mm7
520 %if %1
521 %ifidn r5m, r5d
522     %define t0 r5d
523 %else
524     %define t0 r4d
525     mov  r4d, r5m
526 %endif
527 %endif
528 .height_loop:
529 %endmacro
530
531 ;-----------------------------------------------------------------------------
532 ; int x264_pixel_avg_weight_w16_mmxext( uint8_t *dst, int, uint8_t *src, int, int i_weight, int )
533 ;-----------------------------------------------------------------------------
534 cglobal x264_pixel_avg_weight_w16_mmxext, 4,5
535     BIWEIGHT_START_MMX 1
536     BIWEIGHT_4P_MMX  [r0   ], [r2   ]
537     BIWEIGHT_4P_MMX  [r0+ 4], [r2+ 4]
538     BIWEIGHT_4P_MMX  [r0+ 8], [r2+ 8]
539     BIWEIGHT_4P_MMX  [r0+12], [r2+12]
540     add  r0, r1
541     add  r2, r3
542     dec  t0
543     jg   .height_loop
544     REP_RET
545
546 ;-----------------------------------------------------------------------------
547 ; int x264_pixel_avg_weight_w8_mmxext( uint8_t *, int, uint8_t *, int, int, int )
548 ;-----------------------------------------------------------------------------
549 cglobal x264_pixel_avg_weight_w8_mmxext, 4,5
550     BIWEIGHT_START_MMX 1
551     BIWEIGHT_4P_MMX  [r0  ], [r2  ]
552     BIWEIGHT_4P_MMX  [r0+4], [r2+4]
553     add  r0, r1
554     add  r2, r3
555     dec  t0
556     jg   .height_loop
557     REP_RET
558
559 ;-----------------------------------------------------------------------------
560 ; int x264_pixel_avg_weight_4x4_mmxext( uint8_t *, int, uint8_t *, int, int )
561 ;-----------------------------------------------------------------------------
562 cglobal x264_pixel_avg_weight_4x4_mmxext, 4,4,1
563     BIWEIGHT_START_MMX 0
564     BIWEIGHT_4P_MMX  [r0     ], [r2     ]
565     BIWEIGHT_4P_MMX  [r0+r1  ], [r2+r3  ]
566     BIWEIGHT_4P_MMX  [r0+r1*2], [r2+r3*2]
567     add  r0, r1
568     add  r2, r3
569     BIWEIGHT_4P_MMX  [r0+r1*2], [r2+r3*2]
570     RET
571
572
573
574 ;=============================================================================
575 ; prefetch
576 ;=============================================================================
577 ; FIXME assumes 64 byte cachelines
578
579 ;-----------------------------------------------------------------------------
580 ; void x264_prefetch_fenc_mmxext( uint8_t *pix_y, int stride_y, 
581 ;                                 uint8_t *pix_uv, int stride_uv, int mb_x )
582 ;-----------------------------------------------------------------------------
583 %ifdef ARCH_X86_64
584 cglobal x264_prefetch_fenc_mmxext, 5,5
585     mov    eax, r4d
586     and    eax, 3
587     imul   eax, r1d
588     lea    r0,  [r0+rax*4+64]
589     prefetcht0  [r0]
590     prefetcht0  [r0+r1]
591     lea    r0,  [r0+r1*2]
592     prefetcht0  [r0]
593     prefetcht0  [r0+r1]
594
595     and    r4d, 6
596     imul   r4d, r3d
597     lea    r2,  [r2+r4+64]
598     prefetcht0  [r2]
599     prefetcht0  [r2+r3]
600     ret
601
602 %else
603 cglobal x264_prefetch_fenc_mmxext
604     mov    r2, [esp+20]
605     mov    r1, [esp+8]
606     mov    r0, [esp+4]
607     and    r2, 3
608     imul   r2, r1
609     lea    r0, [r0+r2*4+64]
610     prefetcht0 [r0]
611     prefetcht0 [r0+r1]
612     lea    r0, [r0+r1*2]
613     prefetcht0 [r0]
614     prefetcht0 [r0+r1]
615
616     mov    r2, [esp+20]
617     mov    r1, [esp+16]
618     mov    r0, [esp+12]
619     and    r2, 6
620     imul   r2, r1
621     lea    r0, [r0+r2+64]
622     prefetcht0 [r0]
623     prefetcht0 [r0+r1]
624     ret
625 %endif ; ARCH_X86_64
626
627 ;-----------------------------------------------------------------------------
628 ; void x264_prefetch_ref_mmxext( uint8_t *pix, int stride, int parity )
629 ;-----------------------------------------------------------------------------
630 cglobal x264_prefetch_ref_mmxext, 3,3
631     dec    r2d
632     and    r2d, r1d
633     lea    r0,  [r0+r2*8+64]
634     lea    r2,  [r1*3]
635     prefetcht0  [r0]
636     prefetcht0  [r0+r1]
637     prefetcht0  [r0+r1*2]
638     prefetcht0  [r0+r2]
639     lea    r0,  [r0+r1*4]
640     prefetcht0  [r0]
641     prefetcht0  [r0+r1]
642     prefetcht0  [r0+r1*2]
643     prefetcht0  [r0+r2]
644     ret
645
646
647
648 ;=============================================================================
649 ; chroma MC
650 ;=============================================================================
651
652 ;-----------------------------------------------------------------------------
653 ; void x264_mc_chroma_mmxext( uint8_t *dst, int i_dst_stride,
654 ;                             uint8_t *src, int i_src_stride,
655 ;                             int dx, int dy,
656 ;                             int i_width, int i_height )
657 ;-----------------------------------------------------------------------------
658 cglobal x264_mc_chroma_mmxext, 0,6,1
659 %ifdef ARCH_X86_64
660     %define t0   r10d
661 %else
662     %define t0   r1d
663 %endif
664     movifnidn r2d, r2m
665     movifnidn r3d, r3m
666     movifnidn r4d, r4m
667     movifnidn r5d, r5m
668     mov     eax, r5d
669     mov     t0,  r4d
670     sar     eax, 3
671     sar     t0,  3
672     imul    eax, r3d
673     pxor    mm3, mm3
674     add     eax, t0
675     movsxdifnidn rax, eax
676     add     r2,  rax            ; src += (dx>>3) + (dy>>3) * src_stride
677     and     r4d, 7              ; dx &= 7
678     je      .mc1d
679     and     r5d, 7              ; dy &= 7
680     je      .mc1d
681
682     movd    mm0, r4d
683     movd    mm1, r5d
684     pshufw  mm5, mm0, 0         ; mm5 = dx
685     pshufw  mm6, mm1, 0         ; mm6 = dy
686
687     movq    mm4, [pw_8 GLOBAL]
688     movq    mm0, mm4
689     psubw   mm4, mm5            ; mm4 = 8-dx
690     psubw   mm0, mm6            ; mm0 = 8-dy
691
692     movq    mm7, mm5
693     pmullw  mm5, mm0            ; mm5 = dx*(8-dy) =     cB
694     pmullw  mm7, mm6            ; mm7 = dx*dy =         cD
695     pmullw  mm6, mm4            ; mm6 = (8-dx)*dy =     cC
696     pmullw  mm4, mm0            ; mm4 = (8-dx)*(8-dy) = cA
697
698     mov     r4d, r7m
699 %ifdef ARCH_X86_64
700     mov     r10, r0
701     mov     r11, r2
702 %else
703     mov     r0,  r0m
704     mov     r1,  r1m
705     mov     r5,  r2
706 %endif
707
708 ALIGN 4
709 .height_loop:
710
711     movd    mm1, [r2+r3]
712     movd    mm0, [r2]
713     punpcklbw mm1, mm3          ; 00 px1 | 00 px2 | 00 px3 | 00 px4
714     punpcklbw mm0, mm3
715     pmullw  mm1, mm6            ; 2nd line * cC
716     pmullw  mm0, mm4            ; 1st line * cA
717     paddw   mm0, mm1            ; mm0 <- result
718
719     movd    mm2, [r2+1]
720     movd    mm1, [r2+r3+1]
721     punpcklbw mm2, mm3
722     punpcklbw mm1, mm3
723
724     paddw   mm0, [pw_32 GLOBAL]
725
726     pmullw  mm2, mm5            ; line * cB
727     pmullw  mm1, mm7            ; line * cD
728     paddw   mm0, mm2
729     paddw   mm0, mm1
730     psrlw   mm0, 6
731
732     packuswb mm0, mm3           ; 00 00 00 00 px1 px2 px3 px4
733     movd    [r0], mm0
734
735     add     r2,  r3
736     add     r0,  r1             ; i_dst_stride
737     dec     r4d
738     jnz     .height_loop
739
740     sub dword r6m, 8
741     jnz     .finish             ; width != 8 so assume 4
742
743 %ifdef ARCH_X86_64
744     lea     r0, [r10+4]         ; dst
745     lea     r2, [r11+4]         ; src
746 %else
747     mov     r0,  r0m
748     lea     r2, [r5+4]
749     add     r0,  4
750 %endif
751     mov     r4d, r7m            ; i_height
752     jmp     .height_loop
753
754 ALIGN 4
755 .mc1d:
756     mov       eax, r4d
757     or        eax, r5d
758     and       eax, 7
759     cmp       r4d, 0
760     mov       r5d, 1
761     cmove     r5,  r3           ; pel_offset = dx ? 1 : src_stride
762     movd      mm6, eax
763     movq      mm5, [pw_8 GLOBAL]
764     pshufw    mm6, mm6, 0
765     movq      mm7, [pw_4 GLOBAL]
766     psubw     mm5, mm6
767
768     cmp dword r6m, 8
769     movifnidn r0d, r0m
770     movifnidn r1d, r1m
771     mov       r4d, r7m
772     je .height_loop1_w8
773
774 ALIGN 4
775 .height_loop1_w4:
776     movd      mm0, [r2+r5]
777     movd      mm1, [r2]
778     punpcklbw mm0, mm3
779     punpcklbw mm1, mm3
780     pmullw    mm0, mm6
781     pmullw    mm1, mm5
782     paddw     mm0, mm7
783     paddw     mm0, mm1
784     psrlw     mm0, 3
785     packuswb  mm0, mm3
786     movd     [r0], mm0
787     add       r2,  r3
788     add       r0,  r1
789     dec       r4d
790     jnz .height_loop1_w4
791 .finish:
792     REP_RET
793
794 ALIGN 4
795 .height_loop1_w8:
796     movq      mm0, [r2+r5]
797     movq      mm1, [r2]
798     movq      mm2, mm0
799     movq      mm4, mm1
800     punpcklbw mm0, mm3
801     punpcklbw mm1, mm3
802     punpckhbw mm2, mm3
803     punpckhbw mm4, mm3
804     pmullw    mm0, mm6
805     pmullw    mm1, mm5
806     pmullw    mm2, mm6
807     pmullw    mm4, mm5
808     paddw     mm0, mm7
809     paddw     mm2, mm7
810     paddw     mm0, mm1
811     paddw     mm2, mm4
812     psrlw     mm0, 3
813     psrlw     mm2, 3
814     packuswb  mm0, mm2
815     movq     [r0], mm0
816     add       r2,  r3
817     add       r0,  r1
818     dec       r4d
819     jnz .height_loop1_w8
820     REP_RET
821