]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/dsputil.asm
Merge commit 'ed61f3ca8a0664a697782253b354055136c5d303'
[ffmpeg] / libavcodec / x86 / dsputil.asm
1 ;******************************************************************************
2 ;* MMX optimized DSP utils
3 ;* Copyright (c) 2008 Loren Merritt
4 ;* Copyright (c) 2003-2013 Michael Niedermayer
5 ;* Copyright (c) 2013 Daniel Kang
6 ;*
7 ;* This file is part of FFmpeg.
8 ;*
9 ;* FFmpeg is free software; you can redistribute it and/or
10 ;* modify it under the terms of the GNU Lesser General Public
11 ;* License as published by the Free Software Foundation; either
12 ;* version 2.1 of the License, or (at your option) any later version.
13 ;*
14 ;* FFmpeg is distributed in the hope that it will be useful,
15 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 ;* Lesser General Public License for more details.
18 ;*
19 ;* You should have received a copy of the GNU Lesser General Public
20 ;* License along with FFmpeg; if not, write to the Free Software
21 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 ;******************************************************************************
23
24 %include "libavutil/x86/x86util.asm"
25
26 SECTION_RODATA
27 pb_f: times 16 db 15
28 pb_zzzzzzzz77777777: times 8 db -1
29 pb_7: times 8 db 7
30 pb_zzzz3333zzzzbbbb: db -1,-1,-1,-1,3,3,3,3,-1,-1,-1,-1,11,11,11,11
31 pb_zz11zz55zz99zzdd: db -1,-1,1,1,-1,-1,5,5,-1,-1,9,9,-1,-1,13,13
32 pb_revwords: SHUFFLE_MASK_W 7, 6, 5, 4, 3, 2, 1, 0
33 pd_16384: times 4 dd 16384
34 pb_bswap32: db 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
35
36 SECTION_TEXT
37
38 %macro SCALARPRODUCT 0
39 ; int scalarproduct_int16(int16_t *v1, int16_t *v2, int order)
40 cglobal scalarproduct_int16, 3,3,3, v1, v2, order
41     shl orderq, 1
42     add v1q, orderq
43     add v2q, orderq
44     neg orderq
45     pxor    m2, m2
46 .loop:
47     movu    m0, [v1q + orderq]
48     movu    m1, [v1q + orderq + mmsize]
49     pmaddwd m0, [v2q + orderq]
50     pmaddwd m1, [v2q + orderq + mmsize]
51     paddd   m2, m0
52     paddd   m2, m1
53     add     orderq, mmsize*2
54     jl .loop
55 %if mmsize == 16
56     movhlps m0, m2
57     paddd   m2, m0
58     pshuflw m0, m2, 0x4e
59 %else
60     pshufw  m0, m2, 0x4e
61 %endif
62     paddd   m2, m0
63     movd   eax, m2
64     RET
65
66 ; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul)
67 cglobal scalarproduct_and_madd_int16, 4,4,8, v1, v2, v3, order, mul
68     shl orderq, 1
69     movd    m7, mulm
70 %if mmsize == 16
71     pshuflw m7, m7, 0
72     punpcklqdq m7, m7
73 %else
74     pshufw  m7, m7, 0
75 %endif
76     pxor    m6, m6
77     add v1q, orderq
78     add v2q, orderq
79     add v3q, orderq
80     neg orderq
81 .loop:
82     movu    m0, [v2q + orderq]
83     movu    m1, [v2q + orderq + mmsize]
84     mova    m4, [v1q + orderq]
85     mova    m5, [v1q + orderq + mmsize]
86     movu    m2, [v3q + orderq]
87     movu    m3, [v3q + orderq + mmsize]
88     pmaddwd m0, m4
89     pmaddwd m1, m5
90     pmullw  m2, m7
91     pmullw  m3, m7
92     paddd   m6, m0
93     paddd   m6, m1
94     paddw   m2, m4
95     paddw   m3, m5
96     mova    [v1q + orderq], m2
97     mova    [v1q + orderq + mmsize], m3
98     add     orderq, mmsize*2
99     jl .loop
100 %if mmsize == 16
101     movhlps m0, m6
102     paddd   m6, m0
103     pshuflw m0, m6, 0x4e
104 %else
105     pshufw  m0, m6, 0x4e
106 %endif
107     paddd   m6, m0
108     movd   eax, m6
109     RET
110 %endmacro
111
112 INIT_MMX mmxext
113 SCALARPRODUCT
114 INIT_XMM sse2
115 SCALARPRODUCT
116
117 %macro SCALARPRODUCT_LOOP 1
118 align 16
119 .loop%1:
120     sub     orderq, mmsize*2
121 %if %1
122     mova    m1, m4
123     mova    m4, [v2q + orderq]
124     mova    m0, [v2q + orderq + mmsize]
125     palignr m1, m0, %1
126     palignr m0, m4, %1
127     mova    m3, m5
128     mova    m5, [v3q + orderq]
129     mova    m2, [v3q + orderq + mmsize]
130     palignr m3, m2, %1
131     palignr m2, m5, %1
132 %else
133     mova    m0, [v2q + orderq]
134     mova    m1, [v2q + orderq + mmsize]
135     mova    m2, [v3q + orderq]
136     mova    m3, [v3q + orderq + mmsize]
137 %endif
138     %define t0  [v1q + orderq]
139     %define t1  [v1q + orderq + mmsize]
140 %if ARCH_X86_64
141     mova    m8, t0
142     mova    m9, t1
143     %define t0  m8
144     %define t1  m9
145 %endif
146     pmaddwd m0, t0
147     pmaddwd m1, t1
148     pmullw  m2, m7
149     pmullw  m3, m7
150     paddw   m2, t0
151     paddw   m3, t1
152     paddd   m6, m0
153     paddd   m6, m1
154     mova    [v1q + orderq], m2
155     mova    [v1q + orderq + mmsize], m3
156     jg .loop%1
157 %if %1
158     jmp .end
159 %endif
160 %endmacro
161
162 ; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul)
163 INIT_XMM ssse3
164 cglobal scalarproduct_and_madd_int16, 4,5,10, v1, v2, v3, order, mul
165     shl orderq, 1
166     movd    m7, mulm
167     pshuflw m7, m7, 0
168     punpcklqdq m7, m7
169     pxor    m6, m6
170     mov    r4d, v2d
171     and    r4d, 15
172     and    v2q, ~15
173     and    v3q, ~15
174     mova    m4, [v2q + orderq]
175     mova    m5, [v3q + orderq]
176     ; linear is faster than branch tree or jump table, because the branches taken are cyclic (i.e. predictable)
177     cmp    r4d, 0
178     je .loop0
179     cmp    r4d, 2
180     je .loop2
181     cmp    r4d, 4
182     je .loop4
183     cmp    r4d, 6
184     je .loop6
185     cmp    r4d, 8
186     je .loop8
187     cmp    r4d, 10
188     je .loop10
189     cmp    r4d, 12
190     je .loop12
191 SCALARPRODUCT_LOOP 14
192 SCALARPRODUCT_LOOP 12
193 SCALARPRODUCT_LOOP 10
194 SCALARPRODUCT_LOOP 8
195 SCALARPRODUCT_LOOP 6
196 SCALARPRODUCT_LOOP 4
197 SCALARPRODUCT_LOOP 2
198 SCALARPRODUCT_LOOP 0
199 .end:
200     movhlps m0, m6
201     paddd   m6, m0
202     pshuflw m0, m6, 0x4e
203     paddd   m6, m0
204     movd   eax, m6
205     RET
206
207
208 ;-----------------------------------------------------------------------------
209 ; void ff_apply_window_int16(int16_t *output, const int16_t *input,
210 ;                            const int16_t *window, unsigned int len)
211 ;-----------------------------------------------------------------------------
212
213 %macro REVERSE_WORDS 1-2
214 %if cpuflag(ssse3) && notcpuflag(atom)
215     pshufb  %1, %2
216 %elif cpuflag(sse2)
217     pshuflw  %1, %1, 0x1B
218     pshufhw  %1, %1, 0x1B
219     pshufd   %1, %1, 0x4E
220 %elif cpuflag(mmxext)
221     pshufw   %1, %1, 0x1B
222 %endif
223 %endmacro
224
225 %macro MUL16FIXED 3
226 %if cpuflag(ssse3) ; dst, src, unused
227 ; dst = ((dst * src) + (1<<14)) >> 15
228     pmulhrsw   %1, %2
229 %elif cpuflag(mmxext) ; dst, src, temp
230 ; dst = (dst * src) >> 15
231 ; pmulhw cuts off the bottom bit, so we have to lshift by 1 and add it back
232 ; in from the pmullw result.
233     mova    %3, %1
234     pmulhw  %1, %2
235     pmullw  %3, %2
236     psrlw   %3, 15
237     psllw   %1, 1
238     por     %1, %3
239 %endif
240 %endmacro
241
242 %macro APPLY_WINDOW_INT16 1 ; %1 bitexact version
243 %if %1
244 cglobal apply_window_int16, 4,5,6, output, input, window, offset, offset2
245 %else
246 cglobal apply_window_int16_round, 4,5,6, output, input, window, offset, offset2
247 %endif
248     lea     offset2q, [offsetq-mmsize]
249 %if cpuflag(ssse3) && notcpuflag(atom)
250     mova          m5, [pb_revwords]
251     ALIGN 16
252 %elif %1
253     mova          m5, [pd_16384]
254 %endif
255 .loop:
256 %if cpuflag(ssse3)
257     ; This version does the 16x16->16 multiplication in-place without expanding
258     ; to 32-bit. The ssse3 version is bit-identical.
259     mova          m0, [windowq+offset2q]
260     mova          m1, [ inputq+offset2q]
261     pmulhrsw      m1, m0
262     REVERSE_WORDS m0, m5
263     pmulhrsw      m0, [ inputq+offsetq ]
264     mova  [outputq+offset2q], m1
265     mova  [outputq+offsetq ], m0
266 %elif %1
267     ; This version expands 16-bit to 32-bit, multiplies by the window,
268     ; adds 16384 for rounding, right shifts 15, then repacks back to words to
269     ; save to the output. The window is reversed for the second half.
270     mova          m3, [windowq+offset2q]
271     mova          m4, [ inputq+offset2q]
272     pxor          m0, m0
273     punpcklwd     m0, m3
274     punpcklwd     m1, m4
275     pmaddwd       m0, m1
276     paddd         m0, m5
277     psrad         m0, 15
278     pxor          m2, m2
279     punpckhwd     m2, m3
280     punpckhwd     m1, m4
281     pmaddwd       m2, m1
282     paddd         m2, m5
283     psrad         m2, 15
284     packssdw      m0, m2
285     mova  [outputq+offset2q], m0
286     REVERSE_WORDS m3
287     mova          m4, [ inputq+offsetq]
288     pxor          m0, m0
289     punpcklwd     m0, m3
290     punpcklwd     m1, m4
291     pmaddwd       m0, m1
292     paddd         m0, m5
293     psrad         m0, 15
294     pxor          m2, m2
295     punpckhwd     m2, m3
296     punpckhwd     m1, m4
297     pmaddwd       m2, m1
298     paddd         m2, m5
299     psrad         m2, 15
300     packssdw      m0, m2
301     mova  [outputq+offsetq], m0
302 %else
303     ; This version does the 16x16->16 multiplication in-place without expanding
304     ; to 32-bit. The mmxext and sse2 versions do not use rounding, and
305     ; therefore are not bit-identical to the C version.
306     mova          m0, [windowq+offset2q]
307     mova          m1, [ inputq+offset2q]
308     mova          m2, [ inputq+offsetq ]
309     MUL16FIXED    m1, m0, m3
310     REVERSE_WORDS m0
311     MUL16FIXED    m2, m0, m3
312     mova  [outputq+offset2q], m1
313     mova  [outputq+offsetq ], m2
314 %endif
315     add      offsetd, mmsize
316     sub     offset2d, mmsize
317     jae .loop
318     REP_RET
319 %endmacro
320
321 INIT_MMX mmxext
322 APPLY_WINDOW_INT16 0
323 INIT_XMM sse2
324 APPLY_WINDOW_INT16 0
325
326 INIT_MMX mmxext
327 APPLY_WINDOW_INT16 1
328 INIT_XMM sse2
329 APPLY_WINDOW_INT16 1
330 INIT_XMM ssse3
331 APPLY_WINDOW_INT16 1
332 INIT_XMM ssse3, atom
333 APPLY_WINDOW_INT16 1
334
335
336 ; void add_hfyu_median_prediction_mmxext(uint8_t *dst, const uint8_t *top, const uint8_t *diff, int w, int *left, int *left_top)
337 INIT_MMX mmxext
338 cglobal add_hfyu_median_prediction, 6,6,0, dst, top, diff, w, left, left_top
339     movq    mm0, [topq]
340     movq    mm2, mm0
341     movd    mm4, [left_topq]
342     psllq   mm2, 8
343     movq    mm1, mm0
344     por     mm4, mm2
345     movd    mm3, [leftq]
346     psubb   mm0, mm4 ; t-tl
347     add    dstq, wq
348     add    topq, wq
349     add   diffq, wq
350     neg      wq
351     jmp .skip
352 .loop:
353     movq    mm4, [topq+wq]
354     movq    mm0, mm4
355     psllq   mm4, 8
356     por     mm4, mm1
357     movq    mm1, mm0 ; t
358     psubb   mm0, mm4 ; t-tl
359 .skip:
360     movq    mm2, [diffq+wq]
361 %assign i 0
362 %rep 8
363     movq    mm4, mm0
364     paddb   mm4, mm3 ; t-tl+l
365     movq    mm5, mm3
366     pmaxub  mm3, mm1
367     pminub  mm5, mm1
368     pminub  mm3, mm4
369     pmaxub  mm3, mm5 ; median
370     paddb   mm3, mm2 ; +residual
371 %if i==0
372     movq    mm7, mm3
373     psllq   mm7, 56
374 %else
375     movq    mm6, mm3
376     psrlq   mm7, 8
377     psllq   mm6, 56
378     por     mm7, mm6
379 %endif
380 %if i<7
381     psrlq   mm0, 8
382     psrlq   mm1, 8
383     psrlq   mm2, 8
384 %endif
385 %assign i i+1
386 %endrep
387     movq [dstq+wq], mm7
388     add      wq, 8
389     jl .loop
390     movzx   r2d, byte [dstq-1]
391     mov [leftq], r2d
392     movzx   r2d, byte [topq-1]
393     mov [left_topq], r2d
394     RET
395
396
397 %macro ADD_HFYU_LEFT_LOOP 2 ; %1 = dst_is_aligned, %2 = src_is_aligned
398     add     srcq, wq
399     add     dstq, wq
400     neg     wq
401 %%.loop:
402 %if %2
403     mova    m1, [srcq+wq]
404 %else
405     movu    m1, [srcq+wq]
406 %endif
407     mova    m2, m1
408     psllw   m1, 8
409     paddb   m1, m2
410     mova    m2, m1
411     pshufb  m1, m3
412     paddb   m1, m2
413     pshufb  m0, m5
414     mova    m2, m1
415     pshufb  m1, m4
416     paddb   m1, m2
417 %if mmsize == 16
418     mova    m2, m1
419     pshufb  m1, m6
420     paddb   m1, m2
421 %endif
422     paddb   m0, m1
423 %if %1
424     mova    [dstq+wq], m0
425 %else
426     movq    [dstq+wq], m0
427     movhps  [dstq+wq+8], m0
428 %endif
429     add     wq, mmsize
430     jl %%.loop
431     mov     eax, mmsize-1
432     sub     eax, wd
433     movd    m1, eax
434     pshufb  m0, m1
435     movd    eax, m0
436     RET
437 %endmacro
438
439 ; int add_hfyu_left_prediction(uint8_t *dst, const uint8_t *src, int w, int left)
440 INIT_MMX ssse3
441 cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left
442 .skip_prologue:
443     mova    m5, [pb_7]
444     mova    m4, [pb_zzzz3333zzzzbbbb]
445     mova    m3, [pb_zz11zz55zz99zzdd]
446     movd    m0, leftm
447     psllq   m0, 56
448     ADD_HFYU_LEFT_LOOP 1, 1
449
450 INIT_XMM sse4
451 cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left
452     mova    m5, [pb_f]
453     mova    m6, [pb_zzzzzzzz77777777]
454     mova    m4, [pb_zzzz3333zzzzbbbb]
455     mova    m3, [pb_zz11zz55zz99zzdd]
456     movd    m0, leftm
457     pslldq  m0, 15
458     test    srcq, 15
459     jnz .src_unaligned
460     test    dstq, 15
461     jnz .dst_unaligned
462     ADD_HFYU_LEFT_LOOP 1, 1
463 .dst_unaligned:
464     ADD_HFYU_LEFT_LOOP 0, 1
465 .src_unaligned:
466     ADD_HFYU_LEFT_LOOP 0, 0
467
468
469 ;-----------------------------------------------------------------------------
470 ; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min,
471 ;                           int32_t max, unsigned int len)
472 ;-----------------------------------------------------------------------------
473
474 ; %1 = number of xmm registers used
475 ; %2 = number of inline load/process/store loops per asm loop
476 ; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop
477 ; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2)
478 ; %5 = suffix
479 %macro VECTOR_CLIP_INT32 4-5
480 cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len
481 %if %4
482     cvtsi2ss  m4, minm
483     cvtsi2ss  m5, maxm
484 %else
485     movd      m4, minm
486     movd      m5, maxm
487 %endif
488     SPLATD    m4
489     SPLATD    m5
490 .loop:
491 %assign %%i 1
492 %rep %2
493     mova      m0,  [srcq+mmsize*0*%%i]
494     mova      m1,  [srcq+mmsize*1*%%i]
495     mova      m2,  [srcq+mmsize*2*%%i]
496     mova      m3,  [srcq+mmsize*3*%%i]
497 %if %3
498     mova      m7,  [srcq+mmsize*4*%%i]
499     mova      m8,  [srcq+mmsize*5*%%i]
500     mova      m9,  [srcq+mmsize*6*%%i]
501     mova      m10, [srcq+mmsize*7*%%i]
502 %endif
503     CLIPD  m0,  m4, m5, m6
504     CLIPD  m1,  m4, m5, m6
505     CLIPD  m2,  m4, m5, m6
506     CLIPD  m3,  m4, m5, m6
507 %if %3
508     CLIPD  m7,  m4, m5, m6
509     CLIPD  m8,  m4, m5, m6
510     CLIPD  m9,  m4, m5, m6
511     CLIPD  m10, m4, m5, m6
512 %endif
513     mova  [dstq+mmsize*0*%%i], m0
514     mova  [dstq+mmsize*1*%%i], m1
515     mova  [dstq+mmsize*2*%%i], m2
516     mova  [dstq+mmsize*3*%%i], m3
517 %if %3
518     mova  [dstq+mmsize*4*%%i], m7
519     mova  [dstq+mmsize*5*%%i], m8
520     mova  [dstq+mmsize*6*%%i], m9
521     mova  [dstq+mmsize*7*%%i], m10
522 %endif
523 %assign %%i %%i+1
524 %endrep
525     add     srcq, mmsize*4*(%2+%3)
526     add     dstq, mmsize*4*(%2+%3)
527     sub     lend, mmsize*(%2+%3)
528     jg .loop
529     REP_RET
530 %endmacro
531
532 INIT_MMX mmx
533 %define CLIPD CLIPD_MMX
534 VECTOR_CLIP_INT32 0, 1, 0, 0
535 INIT_XMM sse2
536 VECTOR_CLIP_INT32 6, 1, 0, 0, _int
537 %define CLIPD CLIPD_SSE2
538 VECTOR_CLIP_INT32 6, 2, 0, 1
539 INIT_XMM sse4
540 %define CLIPD CLIPD_SSE41
541 %ifdef m8
542 VECTOR_CLIP_INT32 11, 1, 1, 0
543 %else
544 VECTOR_CLIP_INT32 6, 1, 0, 0
545 %endif
546
547 ; %1 = aligned/unaligned
548 %macro BSWAP_LOOPS  1
549     mov      r3, r2
550     sar      r2, 3
551     jz       .left4_%1
552 .loop8_%1:
553     mov%1    m0, [r1 +  0]
554     mov%1    m1, [r1 + 16]
555 %if cpuflag(ssse3)
556     pshufb   m0, m2
557     pshufb   m1, m2
558     mov%1    [r0 +  0], m0
559     mov%1    [r0 + 16], m1
560 %else
561     pshuflw  m0, m0, 10110001b
562     pshuflw  m1, m1, 10110001b
563     pshufhw  m0, m0, 10110001b
564     pshufhw  m1, m1, 10110001b
565     mova     m2, m0
566     mova     m3, m1
567     psllw    m0, 8
568     psllw    m1, 8
569     psrlw    m2, 8
570     psrlw    m3, 8
571     por      m2, m0
572     por      m3, m1
573     mov%1    [r0 +  0], m2
574     mov%1    [r0 + 16], m3
575 %endif
576     add      r0, 32
577     add      r1, 32
578     dec      r2
579     jnz      .loop8_%1
580 .left4_%1:
581     mov      r2, r3
582     and      r3, 4
583     jz       .left
584     mov%1    m0, [r1]
585 %if cpuflag(ssse3)
586     pshufb   m0, m2
587     mov%1    [r0], m0
588 %else
589     pshuflw  m0, m0, 10110001b
590     pshufhw  m0, m0, 10110001b
591     mova     m2, m0
592     psllw    m0, 8
593     psrlw    m2, 8
594     por      m2, m0
595     mov%1    [r0], m2
596 %endif
597     add      r1, 16
598     add      r0, 16
599 %endmacro
600
601 ; void bswap_buf(uint32_t *dst, const uint32_t *src, int w);
602 %macro BSWAP32_BUF 0
603 %if cpuflag(ssse3)
604 cglobal bswap32_buf, 3,4,3
605     mov      r3, r1
606     mova     m2, [pb_bswap32]
607 %else
608 cglobal bswap32_buf, 3,4,5
609     mov      r3, r1
610 %endif
611     or       r3, r0
612     and      r3, 15
613     jz       .start_align
614     BSWAP_LOOPS  u
615     jmp      .left
616 .start_align:
617     BSWAP_LOOPS  a
618 .left:
619 %if cpuflag(ssse3)
620     mov      r3, r2
621     and      r2, 2
622     jz       .left1
623     movq     m0, [r1]
624     pshufb   m0, m2
625     movq     [r0], m0
626     add      r1, 8
627     add      r0, 8
628 .left1:
629     and      r3, 1
630     jz       .end
631     mov      r2d, [r1]
632     bswap    r2d
633     mov      [r0], r2d
634 %else
635     and      r2, 3
636     jz       .end
637 .loop2:
638     mov      r3d, [r1]
639     bswap    r3d
640     mov      [r0], r3d
641     add      r1, 4
642     add      r0, 4
643     dec      r2
644     jnz      .loop2
645 %endif
646 .end:
647     RET
648 %endmacro
649
650 INIT_XMM sse2
651 BSWAP32_BUF
652
653 INIT_XMM ssse3
654 BSWAP32_BUF