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