OSDN Git Service

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