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