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