]> git.sesse.net Git - x264/blob - common/x86/mc-a2.asm
Faster deblock strength asm on conroe/penryn
[x264] / common / x86 / mc-a2.asm
1 ;*****************************************************************************
2 ;* mc-a2.asm: h264 encoder library
3 ;*****************************************************************************
4 ;* Copyright (C) 2005-2008 x264 project
5 ;*
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>
7 ;*          Fiona Glaser <fiona@x264.com>
8 ;*          Holger Lubitz <holger@lubitz.org>
9 ;*          Mathieu Monnier <manao@melix.net>
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 %include "x86util.asm"
28
29 SECTION_RODATA
30
31 filt_mul20: times 16 db 20
32 filt_mul15: times 8 db 1, -5
33 filt_mul51: times 8 db -5, 1
34 hpel_shuf: db 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15
35
36 SECTION .text
37
38 cextern pw_1
39 cextern pw_16
40 cextern pw_32
41 cextern pd_128
42 cextern pw_3fff
43
44 %macro LOAD_ADD 4
45     movh       %4, %3
46     movh       %1, %2
47     punpcklbw  %4, m0
48     punpcklbw  %1, m0
49     paddw      %1, %4
50 %endmacro
51
52 %macro LOAD_ADD_2 6
53     mova       %5, %3
54     mova       %1, %4
55     mova       %6, %5
56     mova       %2, %1
57     punpcklbw  %5, m0
58     punpcklbw  %1, m0
59     punpckhbw  %6, m0
60     punpckhbw  %2, m0
61     paddw      %1, %5
62     paddw      %2, %6
63 %endmacro
64
65 %macro FILT_V2 6
66     psubw  %1, %2  ; a-b
67     psubw  %4, %5
68     psubw  %2, %3  ; b-c
69     psubw  %5, %6
70     psllw  %2, 2
71     psllw  %5, 2
72     psubw  %1, %2  ; a-5*b+4*c
73     psllw  %3, 4
74     psubw  %4, %5
75     psllw  %6, 4
76     paddw  %1, %3  ; a-5*b+20*c
77     paddw  %4, %6
78 %endmacro
79
80 %macro FILT_H 3
81     psubw  %1, %2  ; a-b
82     psraw  %1, 2   ; (a-b)/4
83     psubw  %1, %2  ; (a-b)/4-b
84     paddw  %1, %3  ; (a-b)/4-b+c
85     psraw  %1, 2   ; ((a-b)/4-b+c)/4
86     paddw  %1, %3  ; ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
87 %endmacro
88
89 %macro FILT_H2 6
90     psubw  %1, %2
91     psubw  %4, %5
92     psraw  %1, 2
93     psraw  %4, 2
94     psubw  %1, %2
95     psubw  %4, %5
96     paddw  %1, %3
97     paddw  %4, %6
98     psraw  %1, 2
99     psraw  %4, 2
100     paddw  %1, %3
101     paddw  %4, %6
102 %endmacro
103
104 %macro FILT_PACK 4
105     paddw     %1, %4
106     paddw     %2, %4
107     psraw     %1, %3
108     psraw     %2, %3
109     packuswb  %1, %2
110 %endmacro
111
112 ;The hpel_filter routines use non-temporal writes for output.
113 ;The following defines may be uncommented for testing.
114 ;Doing the hpel_filter temporal may be a win if the last level cache
115 ;is big enough (preliminary benching suggests on the order of 4* framesize).
116
117 ;%define movntq movq
118 ;%define movntps movaps
119 ;%define sfence
120
121 INIT_MMX
122
123 %macro HPEL_V 1-2 0
124 ;-----------------------------------------------------------------------------
125 ; void hpel_filter_v( uint8_t *dst, uint8_t *src, int16_t *buf, int stride, int width );
126 ;-----------------------------------------------------------------------------
127 cglobal hpel_filter_v_%1, 5,6,%2
128 %ifdef WIN64
129     movsxd   r4, r4d
130 %endif
131     lea r5, [r1+r3]
132     sub r1, r3
133     sub r1, r3
134     add r0, r4
135     lea r2, [r2+r4*2]
136     neg r4
137 %ifnidn %1, ssse3
138     pxor m0, m0
139 %else
140     mova m0, [filt_mul15]
141 %endif
142 .loop:
143 %ifidn %1, ssse3
144     mova m1, [r1]
145     mova m4, [r1+r3]
146     mova m2, [r5+r3*2]
147     mova m5, [r5+r3]
148     mova m3, [r1+r3*2]
149     mova m6, [r5]
150     SBUTTERFLY bw, 1, 4, 7
151     SBUTTERFLY bw, 2, 5, 7
152     SBUTTERFLY bw, 3, 6, 7
153     pmaddubsw m1, m0
154     pmaddubsw m4, m0
155     pmaddubsw m2, m0
156     pmaddubsw m5, m0
157     pmaddubsw m3, [filt_mul20]
158     pmaddubsw m6, [filt_mul20]
159     paddw  m1, m2
160     paddw  m4, m5
161     paddw  m1, m3
162     paddw  m4, m6
163 %else
164     LOAD_ADD_2 m1, m4, [r1     ], [r5+r3*2], m6, m7            ; a0 / a1
165     LOAD_ADD_2 m2, m5, [r1+r3  ], [r5+r3  ], m6, m7            ; b0 / b1
166     LOAD_ADD   m3,     [r1+r3*2], [r5     ], m7                ; c0
167     LOAD_ADD   m6,     [r1+r3*2+mmsize/2], [r5+mmsize/2], m7 ; c1
168     FILT_V2 m1, m2, m3, m4, m5, m6
169 %endif
170     mova      m7, [pw_16]
171     mova      [r2+r4*2], m1
172     mova      [r2+r4*2+mmsize], m4
173     FILT_PACK m1, m4, 5, m7
174     movnt     [r0+r4], m1
175     add r1, mmsize
176     add r5, mmsize
177     add r4, mmsize
178     jl .loop
179     REP_RET
180 %endmacro
181 HPEL_V mmxext
182
183 ;-----------------------------------------------------------------------------
184 ; void hpel_filter_c( uint8_t *dst, int16_t *buf, int width );
185 ;-----------------------------------------------------------------------------
186 cglobal hpel_filter_c_mmxext, 3,3
187     add r0, r2
188     lea r1, [r1+r2*2]
189     neg r2
190     %define src r1+r2*2
191     movq m7, [pw_32]
192 .loop:
193     movq   m1, [src-4]
194     movq   m2, [src-2]
195     movq   m3, [src  ]
196     movq   m4, [src+4]
197     movq   m5, [src+6]
198     paddw  m3, [src+2]  ; c0
199     paddw  m2, m4       ; b0
200     paddw  m1, m5       ; a0
201     movq   m6, [src+8]
202     paddw  m4, [src+14] ; a1
203     paddw  m5, [src+12] ; b1
204     paddw  m6, [src+10] ; c1
205     FILT_H2 m1, m2, m3, m4, m5, m6
206     FILT_PACK m1, m4, 6, m7
207     movntq [r0+r2], m1
208     add r2, 8
209     jl .loop
210     REP_RET
211
212 ;-----------------------------------------------------------------------------
213 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, int width );
214 ;-----------------------------------------------------------------------------
215 cglobal hpel_filter_h_mmxext, 3,3
216     add r0, r2
217     add r1, r2
218     neg r2
219     %define src r1+r2
220     pxor m0, m0
221 .loop:
222     movd       m1, [src-2]
223     movd       m2, [src-1]
224     movd       m3, [src  ]
225     movd       m6, [src+1]
226     movd       m4, [src+2]
227     movd       m5, [src+3]
228     punpcklbw  m1, m0
229     punpcklbw  m2, m0
230     punpcklbw  m3, m0
231     punpcklbw  m6, m0
232     punpcklbw  m4, m0
233     punpcklbw  m5, m0
234     paddw      m3, m6 ; c0
235     paddw      m2, m4 ; b0
236     paddw      m1, m5 ; a0
237     movd       m7, [src+7]
238     movd       m6, [src+6]
239     punpcklbw  m7, m0
240     punpcklbw  m6, m0
241     paddw      m4, m7 ; c1
242     paddw      m5, m6 ; b1
243     movd       m7, [src+5]
244     movd       m6, [src+4]
245     punpcklbw  m7, m0
246     punpcklbw  m6, m0
247     paddw      m6, m7 ; a1
248     movq       m7, [pw_1]
249     FILT_H2 m1, m2, m3, m4, m5, m6
250     FILT_PACK m1, m4, 1, m7
251     movntq     [r0+r2], m1
252     add r2, 8
253     jl .loop
254     REP_RET
255
256 INIT_XMM
257
258 %macro HPEL_C 1
259 ;-----------------------------------------------------------------------------
260 ; void hpel_filter_c( uint8_t *dst, int16_t *buf, int width );
261 ;-----------------------------------------------------------------------------
262 cglobal hpel_filter_c_%1, 3,3,9
263     add r0, r2
264     lea r1, [r1+r2*2]
265     neg r2
266     %define src r1+r2*2
267 %ifnidn %1, sse2
268     mova    m7, [pw_32]
269     %define tpw_32 m7
270 %elifdef ARCH_X86_64
271     mova    m8, [pw_32]
272     %define tpw_32 m8
273 %else
274     %define tpw_32 [pw_32]
275 %endif
276 %ifidn %1,sse2_misalign
277 .loop:
278     movu    m4, [src-4]
279     movu    m5, [src-2]
280     mova    m6, [src]
281     movu    m3, [src+12]
282     movu    m2, [src+14]
283     mova    m1, [src+16]
284     paddw   m4, [src+6]
285     paddw   m5, [src+4]
286     paddw   m6, [src+2]
287     paddw   m3, [src+22]
288     paddw   m2, [src+20]
289     paddw   m1, [src+18]
290     FILT_H2 m4, m5, m6, m3, m2, m1
291 %else
292     mova      m0, [src-16]
293     mova      m1, [src]
294 .loop:
295     mova      m2, [src+16]
296     mova      m4, m1
297     PALIGNR   m4, m0, 12, m7
298     mova      m5, m1
299     PALIGNR   m5, m0, 14, m0
300     mova      m0, m2
301     PALIGNR   m0, m1, 6, m7
302     paddw     m4, m0
303     mova      m0, m2
304     PALIGNR   m0, m1, 4, m7
305     paddw     m5, m0
306     mova      m6, m2
307     PALIGNR   m6, m1, 2, m7
308     paddw     m6, m1
309     FILT_H    m4, m5, m6
310
311     mova      m0, m2
312     mova      m5, m2
313     PALIGNR   m2, m1, 12, m7
314     PALIGNR   m5, m1, 14, m1
315     mova      m1, [src+32]
316     mova      m3, m1
317     PALIGNR   m3, m0, 6, m7
318     paddw     m3, m2
319     mova      m6, m1
320     PALIGNR   m6, m0, 4, m7
321     paddw     m5, m6
322     mova      m6, m1
323     PALIGNR   m6, m0, 2, m7
324     paddw     m6, m0
325     FILT_H    m3, m5, m6
326 %endif
327     FILT_PACK m4, m3, 6, tpw_32
328     movntps [r0+r2], m4
329     add r2, 16
330     jl .loop
331     REP_RET
332 %endmacro
333
334 ;-----------------------------------------------------------------------------
335 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, int width );
336 ;-----------------------------------------------------------------------------
337 cglobal hpel_filter_h_sse2, 3,3,8
338     add r0, r2
339     add r1, r2
340     neg r2
341     %define src r1+r2
342     pxor m0, m0
343 .loop:
344     movh       m1, [src-2]
345     movh       m2, [src-1]
346     movh       m3, [src  ]
347     movh       m4, [src+1]
348     movh       m5, [src+2]
349     movh       m6, [src+3]
350     punpcklbw  m1, m0
351     punpcklbw  m2, m0
352     punpcklbw  m3, m0
353     punpcklbw  m4, m0
354     punpcklbw  m5, m0
355     punpcklbw  m6, m0
356     paddw      m3, m4 ; c0
357     paddw      m2, m5 ; b0
358     paddw      m1, m6 ; a0
359     movh       m4, [src+6]
360     movh       m5, [src+7]
361     movh       m6, [src+10]
362     movh       m7, [src+11]
363     punpcklbw  m4, m0
364     punpcklbw  m5, m0
365     punpcklbw  m6, m0
366     punpcklbw  m7, m0
367     paddw      m5, m6 ; b1
368     paddw      m4, m7 ; a1
369     movh       m6, [src+8]
370     movh       m7, [src+9]
371     punpcklbw  m6, m0
372     punpcklbw  m7, m0
373     paddw      m6, m7 ; c1
374     mova       m7, [pw_1] ; FIXME xmm8
375     FILT_H2 m1, m2, m3, m4, m5, m6
376     FILT_PACK m1, m4, 1, m7
377     movntps    [r0+r2], m1
378     add r2, 16
379     jl .loop
380     REP_RET
381
382 %ifndef ARCH_X86_64
383 ;-----------------------------------------------------------------------------
384 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, int width );
385 ;-----------------------------------------------------------------------------
386 cglobal hpel_filter_h_ssse3, 3,3
387     add r0, r2
388     add r1, r2
389     neg r2
390     %define src r1+r2
391     mova      m0, [src-16]
392     mova      m1, [src]
393     mova      m7, [pw_16]
394 .loop:
395     mova      m2, [src+16]
396     mova      m3, m1
397     palignr   m3, m0, 14
398     mova      m4, m1
399     palignr   m4, m0, 15
400     mova      m0, m2
401     palignr   m0, m1, 2
402     pmaddubsw m3, [filt_mul15]
403     pmaddubsw m4, [filt_mul15]
404     pmaddubsw m0, [filt_mul51]
405     mova      m5, m2
406     palignr   m5, m1, 1
407     mova      m6, m2
408     palignr   m6, m1, 3
409     paddw     m3, m0
410     mova      m0, m1
411     pmaddubsw m1, [filt_mul20]
412     pmaddubsw m5, [filt_mul20]
413     pmaddubsw m6, [filt_mul51]
414     paddw     m3, m1
415     paddw     m4, m5
416     paddw     m4, m6
417     FILT_PACK m3, m4, 5, m7
418     pshufb    m3, [hpel_shuf]
419     mova      m1, m2
420     movntps [r0+r2], m3
421     add r2, 16
422     jl .loop
423     RET
424 %endif
425
426 %define PALIGNR PALIGNR_MMX
427 %ifndef ARCH_X86_64
428 HPEL_C sse2
429 %endif
430 HPEL_V sse2, 8
431 HPEL_C sse2_misalign
432 %define PALIGNR PALIGNR_SSSE3
433 HPEL_C ssse3
434 HPEL_V ssse3
435
436 %ifdef ARCH_X86_64
437
438 %macro DO_FILT_V 6
439     ;The optimum prefetch distance is difficult to determine in checkasm:
440     ;any prefetch seems slower than not prefetching.
441     ;In real use, the prefetch seems to be a slight win.
442     ;+16 is picked somewhat arbitrarily here based on the fact that even one
443     ;loop iteration is going to take longer than the prefetch.
444     prefetcht0 [r1+r2*2+16]
445 %ifidn %6, ssse3
446     mova m1, [r3]
447     mova m2, [r3+r2]
448     mova %3, [r3+r2*2]
449     mova m3, [r1]
450     mova %1, [r1+r2]
451     mova %2, [r1+r2*2]
452     mova m4, m1
453     punpcklbw m1, m2
454     punpckhbw m4, m2
455     mova m2, %1
456     punpcklbw %1, %2
457     punpckhbw m2, %2
458     mova %2, m3
459     punpcklbw m3, %3
460     punpckhbw %2, %3
461
462     pmaddubsw m1, m12
463     pmaddubsw m4, m12
464     pmaddubsw %1, m0
465     pmaddubsw m2, m0
466     pmaddubsw m3, m14
467     pmaddubsw %2, m14
468
469     paddw m1, %1
470     paddw m4, m2
471     paddw m1, m3
472     paddw m4, %2
473 %else
474     LOAD_ADD_2 m1, m4, [r3     ], [r1+r2*2], m2, m5            ; a0 / a1
475     LOAD_ADD_2 m2, m5, [r3+r2  ], [r1+r2  ], m3, m6            ; b0 / b1
476     LOAD_ADD_2 m3, m6, [r3+r2*2], [r1     ], %3, %4            ; c0 / c1
477     packuswb %3, %4
478     FILT_V2 m1, m2, m3, m4, m5, m6
479 %endif
480     add       r3, 16
481     add       r1, 16
482     mova      %1, m1
483     mova      %2, m4
484     FILT_PACK m1, m4, 5, m15
485     movntps  [r11+r4+%5], m1
486 %endmacro
487
488 %macro FILT_C 4
489     mova      m1, %2
490     PALIGNR   m1, %1, 12, m2
491     mova      m2, %2
492     PALIGNR   m2, %1, 14, %1
493     mova      m3, %3
494     PALIGNR   m3, %2, 4, %1
495     mova      m4, %3
496     PALIGNR   m4, %2, 2, %1
497     paddw     m3, m2
498     mova      %1, %3
499     PALIGNR   %3, %2, 6, m2
500     paddw     m4, %2
501     paddw     %3, m1
502     FILT_H    %3, m3, m4
503 %endmacro
504
505 %macro DO_FILT_C 4
506     FILT_C %1, %2, %3, 6
507     FILT_C %2, %1, %4, 6
508     FILT_PACK %3, %4, 6, m15
509     movntps   [r5+r4], %3
510 %endmacro
511
512 %macro ADD8TO16 5
513     mova      %3, %1
514     mova      %4, %2
515     punpcklbw %1, %5
516     punpckhbw %2, %5
517     punpckhbw %3, %5
518     punpcklbw %4, %5
519     paddw     %2, %3
520     paddw     %1, %4
521 %endmacro
522
523 %macro DO_FILT_H 4
524     mova      m1, %2
525     PALIGNR   m1, %1, 14, m3
526     mova      m2, %2
527     PALIGNR   m2, %1, 15, m3
528     mova      m4, %3
529     PALIGNR   m4, %2, 1 , m3
530     mova      m5, %3
531     PALIGNR   m5, %2, 2 , m3
532     mova      m6, %3
533     PALIGNR   m6, %2, 3 , m3
534     mova      %1, %2
535 %ifidn %4, sse2
536     ADD8TO16  m1, m6, m12, m3, m0 ; a
537     ADD8TO16  m2, m5, m12, m3, m0 ; b
538     ADD8TO16  %2, m4, m12, m3, m0 ; c
539     FILT_V2   m1, m2, %2, m6, m5, m4
540     FILT_PACK m1, m6, 5, m15
541 %else ; ssse3
542     pmaddubsw m1, m12
543     pmaddubsw m2, m12
544     pmaddubsw %2, m14
545     pmaddubsw m4, m14
546     pmaddubsw m5, m0
547     pmaddubsw m6, m0
548     paddw     m1, %2
549     paddw     m2, m4
550     paddw     m1, m5
551     paddw     m2, m6
552     FILT_PACK m1, m2, 5, m15
553     pshufb    m1, [hpel_shuf]
554 %endif
555     movntps [r0+r4], m1
556     mova      %2, %3
557 %endmacro
558
559 %macro HPEL 1
560 ;-----------------------------------------------------------------------------
561 ; void hpel_filter( uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
562 ;                   uint8_t *src, int stride, int width, int height)
563 ;-----------------------------------------------------------------------------
564 cglobal hpel_filter_%1, 7,7,16
565 %ifdef WIN64
566     movsxd   r4, r4d
567     movsxd   r5, r5d
568 %endif
569     mov      r10, r3
570     sub       r5, 16
571     mov      r11, r1
572     and      r10, 15
573     sub       r3, r10
574     add       r0, r5
575     add      r11, r5
576     add      r10, r5
577     add       r5, r2
578     mov       r2, r4
579     neg      r10
580     lea       r1, [r3+r2]
581     sub       r3, r2
582     sub       r3, r2
583     mov       r4, r10
584     mova     m15, [pw_16]
585 %ifidn %1, sse2
586     pxor      m0, m0
587 %else ; ssse3
588     mova      m0, [filt_mul51]
589     mova     m12, [filt_mul15]
590     mova     m14, [filt_mul20]
591 %endif
592 ;ALIGN 16
593 .loopy:
594 ; first filter_v
595     DO_FILT_V m8, m7, m13, m12, 0, %1
596 ;ALIGN 16
597 .loopx:
598     DO_FILT_V m6, m5, m11, m12, 16, %1
599 .lastx:
600     paddw   m15, m15 ; pw_32
601     DO_FILT_C m9, m8, m7, m6
602     psrlw   m15, 1 ; pw_16
603     movdqa   m7, m5
604     DO_FILT_H m10, m13, m11, %1
605     add      r4, 16
606     jl .loopx
607     cmp      r4, 16
608     jl .lastx
609 ; setup regs for next y
610     sub      r4, r10
611     sub      r4, r2
612     sub      r1, r4
613     sub      r3, r4
614     add      r0, r2
615     add     r11, r2
616     add      r5, r2
617     mov      r4, r10
618     sub     r6d, 1
619     jg .loopy
620     sfence
621     RET
622 %endmacro
623
624 %define PALIGNR PALIGNR_MMX
625 HPEL sse2
626 %define PALIGNR PALIGNR_SSSE3
627 HPEL ssse3
628 %endif
629
630 %undef movntq
631 %undef movntps
632 %undef sfence
633
634 ;-----------------------------------------------------------------------------
635 ; void plane_copy_core( uint8_t *dst, int i_dst,
636 ;                       uint8_t *src, int i_src, int w, int h)
637 ;-----------------------------------------------------------------------------
638 ; assumes i_dst and w are multiples of 16, and i_dst>w
639 cglobal plane_copy_core_mmxext, 6,7
640     movsxdifnidn r1, r1d
641     movsxdifnidn r3, r3d
642     movsxdifnidn r4, r4d
643     sub    r1,  r4
644     sub    r3,  r4
645 .loopy:
646     mov    r6d, r4d
647     sub    r6d, 63
648 .loopx:
649     prefetchnta [r2+256]
650     movq   mm0, [r2   ]
651     movq   mm1, [r2+ 8]
652     movntq [r0   ], mm0
653     movntq [r0+ 8], mm1
654     movq   mm2, [r2+16]
655     movq   mm3, [r2+24]
656     movntq [r0+16], mm2
657     movntq [r0+24], mm3
658     movq   mm4, [r2+32]
659     movq   mm5, [r2+40]
660     movntq [r0+32], mm4
661     movntq [r0+40], mm5
662     movq   mm6, [r2+48]
663     movq   mm7, [r2+56]
664     movntq [r0+48], mm6
665     movntq [r0+56], mm7
666     add    r2,  64
667     add    r0,  64
668     sub    r6d, 64
669     jg .loopx
670     prefetchnta [r2+256]
671     add    r6d, 63
672     jle .end16
673 .loop16:
674     movq   mm0, [r2  ]
675     movq   mm1, [r2+8]
676     movntq [r0  ], mm0
677     movntq [r0+8], mm1
678     add    r2,  16
679     add    r0,  16
680     sub    r6d, 16
681     jg .loop16
682 .end16:
683     add    r0, r1
684     add    r2, r3
685     dec    r5d
686     jg .loopy
687     sfence
688     emms
689     RET
690
691
692
693 ; These functions are not general-use; not only do the SSE ones require aligned input,
694 ; but they also will fail if given a non-mod16 size or a size less than 64.
695 ; memzero SSE will fail for non-mod128.
696
697 ;-----------------------------------------------------------------------------
698 ; void *memcpy_aligned( void *dst, const void *src, size_t n );
699 ;-----------------------------------------------------------------------------
700 cglobal memcpy_aligned_mmx, 3,3
701     test r2d, 16
702     jz .copy32
703     sub r2d, 16
704     movq mm0, [r1 + r2 + 0]
705     movq mm1, [r1 + r2 + 8]
706     movq [r0 + r2 + 0], mm0
707     movq [r0 + r2 + 8], mm1
708 .copy32:
709     sub r2d, 32
710     movq mm0, [r1 + r2 +  0]
711     movq mm1, [r1 + r2 +  8]
712     movq mm2, [r1 + r2 + 16]
713     movq mm3, [r1 + r2 + 24]
714     movq [r0 + r2 +  0], mm0
715     movq [r0 + r2 +  8], mm1
716     movq [r0 + r2 + 16], mm2
717     movq [r0 + r2 + 24], mm3
718     jg .copy32
719     REP_RET
720
721 ;-----------------------------------------------------------------------------
722 ; void *memcpy_aligned( void *dst, const void *src, size_t n );
723 ;-----------------------------------------------------------------------------
724 cglobal memcpy_aligned_sse2, 3,3
725     test r2d, 16
726     jz .copy32
727     sub r2d, 16
728     movdqa xmm0, [r1 + r2]
729     movdqa [r0 + r2], xmm0
730 .copy32:
731     test r2d, 32
732     jz .copy64
733     sub r2d, 32
734     movdqa xmm0, [r1 + r2 +  0]
735     movdqa [r0 + r2 +  0], xmm0
736     movdqa xmm1, [r1 + r2 + 16]
737     movdqa [r0 + r2 + 16], xmm1
738 .copy64:
739     sub r2d, 64
740     movdqa xmm0, [r1 + r2 +  0]
741     movdqa [r0 + r2 +  0], xmm0
742     movdqa xmm1, [r1 + r2 + 16]
743     movdqa [r0 + r2 + 16], xmm1
744     movdqa xmm2, [r1 + r2 + 32]
745     movdqa [r0 + r2 + 32], xmm2
746     movdqa xmm3, [r1 + r2 + 48]
747     movdqa [r0 + r2 + 48], xmm3
748     jg .copy64
749     REP_RET
750
751 ;-----------------------------------------------------------------------------
752 ; void *memzero_aligned( void *dst, size_t n );
753 ;-----------------------------------------------------------------------------
754 %macro MEMZERO 1
755 cglobal memzero_aligned_%1, 2,2
756     add  r0, r1
757     neg  r1
758     pxor m0, m0
759 .loop:
760 %assign i 0
761 %rep 8
762     mova [r0 + r1 + i], m0
763 %assign i i+mmsize
764 %endrep
765     add r1, mmsize*8
766     jl .loop
767     REP_RET
768 %endmacro
769
770 INIT_MMX
771 MEMZERO mmx
772 INIT_XMM
773 MEMZERO sse2
774
775
776
777 ;-----------------------------------------------------------------------------
778 ; void integral_init4h( uint16_t *sum, uint8_t *pix, int stride )
779 ;-----------------------------------------------------------------------------
780 cglobal integral_init4h_sse4, 3,4
781     lea     r3, [r0+r2*2]
782     add     r1, r2
783     neg     r2
784     pxor    m4, m4
785 .loop:
786     movdqa  m0, [r1+r2]
787     movdqa  m1, [r1+r2+16]
788     palignr m1, m0, 8
789     mpsadbw m0, m4, 0
790     mpsadbw m1, m4, 0
791     paddw   m0, [r0+r2*2]
792     paddw   m1, [r0+r2*2+16]
793     movdqa  [r3+r2*2   ], m0
794     movdqa  [r3+r2*2+16], m1
795     add     r2, 16
796     jl .loop
797     REP_RET
798
799 cglobal integral_init8h_sse4, 3,4
800     lea     r3, [r0+r2*2]
801     add     r1, r2
802     neg     r2
803     pxor    m4, m4
804 .loop:
805     movdqa  m0, [r1+r2]
806     movdqa  m1, [r1+r2+16]
807     palignr m1, m0, 8
808     movdqa  m2, m0
809     movdqa  m3, m1
810     mpsadbw m0, m4, 0
811     mpsadbw m1, m4, 0
812     mpsadbw m2, m4, 4
813     mpsadbw m3, m4, 4
814     paddw   m0, [r0+r2*2]
815     paddw   m1, [r0+r2*2+16]
816     paddw   m0, m2
817     paddw   m1, m3
818     movdqa  [r3+r2*2   ], m0
819     movdqa  [r3+r2*2+16], m1
820     add     r2, 16
821     jl .loop
822     REP_RET
823
824 %macro INTEGRAL_INIT_8V 1
825 ;-----------------------------------------------------------------------------
826 ; void integral_init8v( uint16_t *sum8, int stride )
827 ;-----------------------------------------------------------------------------
828 cglobal integral_init8v_%1, 3,3
829     shl   r1, 1
830     add   r0, r1
831     lea   r2, [r0+r1*8]
832     neg   r1
833 .loop:
834     mova  m0, [r2+r1]
835     mova  m1, [r2+r1+mmsize]
836     psubw m0, [r0+r1]
837     psubw m1, [r0+r1+mmsize]
838     mova  [r0+r1], m0
839     mova  [r0+r1+mmsize], m1
840     add   r1, 2*mmsize
841     jl .loop
842     REP_RET
843 %endmacro
844
845 INIT_MMX
846 INTEGRAL_INIT_8V mmx
847 INIT_XMM
848 INTEGRAL_INIT_8V sse2
849
850 ;-----------------------------------------------------------------------------
851 ; void integral_init4v( uint16_t *sum8, uint16_t *sum4, int stride )
852 ;-----------------------------------------------------------------------------
853 INIT_MMX
854 cglobal integral_init4v_mmx, 3,5
855     shl   r2, 1
856     lea   r3, [r0+r2*4]
857     lea   r4, [r0+r2*8]
858     mova  m0, [r0+r2]
859     mova  m4, [r4+r2]
860 .loop:
861     sub   r2, 8
862     mova  m1, m4
863     psubw m1, m0
864     mova  m4, [r4+r2]
865     mova  m0, [r0+r2]
866     paddw m1, m4
867     mova  m3, [r3+r2]
868     psubw m1, m0
869     psubw m3, m0
870     mova  [r0+r2], m1
871     mova  [r1+r2], m3
872     jge .loop
873     REP_RET
874
875 INIT_XMM
876 cglobal integral_init4v_sse2, 3,5
877     shl     r2, 1
878     add     r0, r2
879     add     r1, r2
880     lea     r3, [r0+r2*4]
881     lea     r4, [r0+r2*8]
882     neg     r2
883 .loop:
884     mova    m0, [r0+r2]
885     mova    m1, [r4+r2]
886     mova    m2, m0
887     mova    m4, m1
888     shufpd  m0, [r0+r2+16], 1
889     shufpd  m1, [r4+r2+16], 1
890     paddw   m0, m2
891     paddw   m1, m4
892     mova    m3, [r3+r2]
893     psubw   m1, m0
894     psubw   m3, m2
895     mova  [r0+r2], m1
896     mova  [r1+r2], m3
897     add     r2, 16
898     jl .loop
899     REP_RET
900
901 cglobal integral_init4v_ssse3, 3,5
902     shl     r2, 1
903     add     r0, r2
904     add     r1, r2
905     lea     r3, [r0+r2*4]
906     lea     r4, [r0+r2*8]
907     neg     r2
908 .loop:
909     mova    m2, [r0+r2]
910     mova    m0, [r0+r2+16]
911     mova    m4, [r4+r2]
912     mova    m1, [r4+r2+16]
913     palignr m0, m2, 8
914     palignr m1, m4, 8
915     paddw   m0, m2
916     paddw   m1, m4
917     mova    m3, [r3+r2]
918     psubw   m1, m0
919     psubw   m3, m2
920     mova  [r0+r2], m1
921     mova  [r1+r2], m3
922     add     r2, 16
923     jl .loop
924     REP_RET
925
926 %macro FILT8x4 7
927     mova      %3, [r0+%7]
928     mova      %4, [r0+r5+%7]
929     pavgb     %3, %4
930     pavgb     %4, [r0+r5*2+%7]
931     PALIGNR   %1, %3, 1, m6
932     PALIGNR   %2, %4, 1, m6
933     pavgb     %1, %3
934     pavgb     %2, %4
935     mova      %5, %1
936     mova      %6, %2
937     pand      %1, m7
938     pand      %2, m7
939     psrlw     %5, 8
940     psrlw     %6, 8
941 %endmacro
942
943 %macro FILT16x2 4
944     mova      m3, [r0+%4+mmsize]
945     mova      m2, [r0+%4]
946     pavgb     m3, [r0+%4+r5+mmsize]
947     pavgb     m2, [r0+%4+r5]
948     PALIGNR   %1, m3, 1, m6
949     pavgb     %1, m3
950     PALIGNR   m3, m2, 1, m6
951     pavgb     m3, m2
952     mova      m5, m3
953     mova      m4, %1
954     pand      m3, m7
955     pand      %1, m7
956     psrlw     m5, 8
957     psrlw     m4, 8
958     packuswb  m3, %1
959     packuswb  m5, m4
960     mova    [%2], m3
961     mova    [%3], m5
962     mova      %1, m2
963 %endmacro
964
965 %macro FILT8x2U 3
966     mova      m3, [r0+%3+8]
967     mova      m2, [r0+%3]
968     pavgb     m3, [r0+%3+r5+8]
969     pavgb     m2, [r0+%3+r5]
970     mova      m1, [r0+%3+9]
971     mova      m0, [r0+%3+1]
972     pavgb     m1, [r0+%3+r5+9]
973     pavgb     m0, [r0+%3+r5+1]
974     pavgb     m1, m3
975     pavgb     m0, m2
976     mova      m3, m1
977     mova      m2, m0
978     pand      m1, m7
979     pand      m0, m7
980     psrlw     m3, 8
981     psrlw     m2, 8
982     packuswb  m0, m1
983     packuswb  m2, m3
984     mova    [%1], m0
985     mova    [%2], m2
986 %endmacro
987
988 ;-----------------------------------------------------------------------------
989 ; void frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
990 ;                              int src_stride, int dst_stride, int width, int height )
991 ;-----------------------------------------------------------------------------
992 %macro FRAME_INIT_LOWRES 1-2 0 ; FIXME
993 cglobal frame_init_lowres_core_%1, 6,7,%2
994 %ifdef WIN64
995     movsxd   r5, r5d
996 %endif
997     ; src += 2*(height-1)*stride + 2*width
998     mov      r6d, r8m
999     dec      r6d
1000     imul     r6d, r5d
1001     add      r6d, r7m
1002     lea       r0, [r0+r6*2]
1003     ; dst += (height-1)*stride + width
1004     mov      r6d, r8m
1005     dec      r6d
1006     imul     r6d, r6m
1007     add      r6d, r7m
1008     add       r1, r6
1009     add       r2, r6
1010     add       r3, r6
1011     add       r4, r6
1012     ; gap = stride - width
1013     mov      r6d, r6m
1014     sub      r6d, r7m
1015     PUSH      r6
1016     %define dst_gap [rsp+gprsize]
1017     mov      r6d, r5d
1018     sub      r6d, r7m
1019     shl      r6d, 1
1020     PUSH      r6
1021     %define src_gap [rsp]
1022 %if mmsize == 16
1023     ; adjust for the odd end case
1024     mov      r6d, r7m
1025     and      r6d, 8
1026     sub       r1, r6
1027     sub       r2, r6
1028     sub       r3, r6
1029     sub       r4, r6
1030     add  dst_gap, r6d
1031 %endif ; mmsize
1032     pcmpeqb   m7, m7
1033     psrlw     m7, 8
1034 .vloop:
1035     mov      r6d, r7m
1036 %ifnidn %1, mmxext
1037     mova      m0, [r0]
1038     mova      m1, [r0+r5]
1039     pavgb     m0, m1
1040     pavgb     m1, [r0+r5*2]
1041 %endif
1042 %if mmsize == 16
1043     test     r6d, 8
1044     jz .hloop
1045     sub       r0, 16
1046     FILT8x4   m0, m1, m2, m3, m4, m5, 0
1047     packuswb  m0, m4
1048     packuswb  m1, m5
1049     movq    [r1], m0
1050     movhps  [r2], m0
1051     movq    [r3], m1
1052     movhps  [r4], m1
1053     mova      m0, m2
1054     mova      m1, m3
1055     sub      r6d, 8
1056 %endif ; mmsize
1057 .hloop:
1058     sub       r0, mmsize*2
1059     sub       r1, mmsize
1060     sub       r2, mmsize
1061     sub       r3, mmsize
1062     sub       r4, mmsize
1063 %ifdef m8
1064     FILT8x4   m0, m1, m2, m3, m10, m11, mmsize
1065     mova      m8, m0
1066     mova      m9, m1
1067     FILT8x4   m2, m3, m0, m1, m4, m5, 0
1068     packuswb  m2, m8
1069     packuswb  m3, m9
1070     packuswb  m4, m10
1071     packuswb  m5, m11
1072     mova    [r1], m2
1073     mova    [r2], m4
1074     mova    [r3], m3
1075     mova    [r4], m5
1076 %elifidn %1, mmxext
1077     FILT8x2U  r1, r2, 0
1078     FILT8x2U  r3, r4, r5
1079 %else
1080     FILT16x2  m0, r1, r2, 0
1081     FILT16x2  m1, r3, r4, r5
1082 %endif
1083     sub      r6d, mmsize
1084     jg .hloop
1085 .skip:
1086     mov       r6, dst_gap
1087     sub       r0, src_gap
1088     sub       r1, r6
1089     sub       r2, r6
1090     sub       r3, r6
1091     sub       r4, r6
1092     dec    dword r8m
1093     jg .vloop
1094     ADD      rsp, 2*gprsize
1095     emms
1096     RET
1097 %endmacro ; FRAME_INIT_LOWRES
1098
1099 INIT_MMX
1100 %define PALIGNR PALIGNR_MMX
1101 FRAME_INIT_LOWRES mmxext
1102 %ifndef ARCH_X86_64
1103 FRAME_INIT_LOWRES cache32_mmxext
1104 %endif
1105 INIT_XMM
1106 FRAME_INIT_LOWRES sse2, 12
1107 %define PALIGNR PALIGNR_SSSE3
1108 FRAME_INIT_LOWRES ssse3, 12
1109
1110 ;-----------------------------------------------------------------------------
1111 ; void mbtree_propagate_cost( int *dst, uint16_t *propagate_in, uint16_t *intra_costs,
1112 ;                             uint16_t *inter_costs, uint16_t *inv_qscales, int len )
1113 ;-----------------------------------------------------------------------------
1114 cglobal mbtree_propagate_cost_sse2, 6,6
1115     shl r5d, 1
1116     lea r0, [r0+r5*2]
1117     add r1, r5
1118     add r2, r5
1119     add r3, r5
1120     add r4, r5
1121     neg r5
1122     pxor      xmm5, xmm5
1123     movdqa    xmm4, [pd_128]
1124 .loop:
1125     movq      xmm2, [r2+r5] ; intra
1126     movq      xmm0, [r4+r5] ; invq
1127     punpcklwd xmm2, xmm5
1128     punpcklwd xmm0, xmm5
1129     pmaddwd   xmm0, xmm2
1130     paddd     xmm0, xmm4
1131     psrld     xmm0, 8       ; intra*invq>>8
1132     movq      xmm3, [r3+r5] ; inter
1133     movq      xmm1, [r1+r5] ; prop
1134     pand      xmm3, [pw_3fff]
1135     punpcklwd xmm1, xmm5
1136     punpcklwd xmm3, xmm5
1137     paddd     xmm0, xmm1    ; prop + (intra*invq>>8)
1138     cvtdq2ps  xmm1, xmm2    ; intra
1139     psubd     xmm2, xmm3    ; intra - inter
1140     cvtdq2ps  xmm0, xmm0
1141     cvtdq2ps  xmm2, xmm2
1142     mulps     xmm0, xmm2    ; (prop + (intra*invq>>8)) * (intra - inter)
1143     divps     xmm0, xmm1    ; / intra
1144     cvttps2dq xmm0, xmm0    ; truncation isn't really desired, but matches the integer implementation
1145     movdqa [r0+r5*2], xmm0
1146     add r5, 8
1147     jl .loop
1148     REP_RET
1149