x86/dsputil: add emms to ff_scalarproduct_int16_mmxext()
[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 ;-----------------------------------------------------------------------------
473 ; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min,
474 ;                           int32_t max, unsigned int len)
475 ;-----------------------------------------------------------------------------
476
477 ; %1 = number of xmm registers used
478 ; %2 = number of inline load/process/store loops per asm loop
479 ; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop
480 ; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2)
481 ; %5 = suffix
482 %macro VECTOR_CLIP_INT32 4-5
483 cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len
484 %if %4
485     cvtsi2ss  m4, minm
486     cvtsi2ss  m5, maxm
487 %else
488     movd      m4, minm
489     movd      m5, maxm
490 %endif
491     SPLATD    m4
492     SPLATD    m5
493 .loop:
494 %assign %%i 1
495 %rep %2
496     mova      m0,  [srcq+mmsize*0*%%i]
497     mova      m1,  [srcq+mmsize*1*%%i]
498     mova      m2,  [srcq+mmsize*2*%%i]
499     mova      m3,  [srcq+mmsize*3*%%i]
500 %if %3
501     mova      m7,  [srcq+mmsize*4*%%i]
502     mova      m8,  [srcq+mmsize*5*%%i]
503     mova      m9,  [srcq+mmsize*6*%%i]
504     mova      m10, [srcq+mmsize*7*%%i]
505 %endif
506     CLIPD  m0,  m4, m5, m6
507     CLIPD  m1,  m4, m5, m6
508     CLIPD  m2,  m4, m5, m6
509     CLIPD  m3,  m4, m5, m6
510 %if %3
511     CLIPD  m7,  m4, m5, m6
512     CLIPD  m8,  m4, m5, m6
513     CLIPD  m9,  m4, m5, m6
514     CLIPD  m10, m4, m5, m6
515 %endif
516     mova  [dstq+mmsize*0*%%i], m0
517     mova  [dstq+mmsize*1*%%i], m1
518     mova  [dstq+mmsize*2*%%i], m2
519     mova  [dstq+mmsize*3*%%i], m3
520 %if %3
521     mova  [dstq+mmsize*4*%%i], m7
522     mova  [dstq+mmsize*5*%%i], m8
523     mova  [dstq+mmsize*6*%%i], m9
524     mova  [dstq+mmsize*7*%%i], m10
525 %endif
526 %assign %%i %%i+1
527 %endrep
528     add     srcq, mmsize*4*(%2+%3)
529     add     dstq, mmsize*4*(%2+%3)
530     sub     lend, mmsize*(%2+%3)
531     jg .loop
532     REP_RET
533 %endmacro
534
535 INIT_MMX mmx
536 %define CLIPD CLIPD_MMX
537 VECTOR_CLIP_INT32 0, 1, 0, 0
538 INIT_XMM sse2
539 VECTOR_CLIP_INT32 6, 1, 0, 0, _int
540 %define CLIPD CLIPD_SSE2
541 VECTOR_CLIP_INT32 6, 2, 0, 1
542 INIT_XMM sse4
543 %define CLIPD CLIPD_SSE41
544 %ifdef m8
545 VECTOR_CLIP_INT32 11, 1, 1, 0
546 %else
547 VECTOR_CLIP_INT32 6, 1, 0, 0
548 %endif
549
550 ; %1 = aligned/unaligned
551 %macro BSWAP_LOOPS  1
552     mov      r3, r2
553     sar      r2, 3
554     jz       .left4_%1
555 .loop8_%1:
556     mov%1    m0, [r1 +  0]
557     mov%1    m1, [r1 + 16]
558 %if cpuflag(ssse3)
559     pshufb   m0, m2
560     pshufb   m1, m2
561     mov%1    [r0 +  0], m0
562     mov%1    [r0 + 16], m1
563 %else
564     pshuflw  m0, m0, 10110001b
565     pshuflw  m1, m1, 10110001b
566     pshufhw  m0, m0, 10110001b
567     pshufhw  m1, m1, 10110001b
568     mova     m2, m0
569     mova     m3, m1
570     psllw    m0, 8
571     psllw    m1, 8
572     psrlw    m2, 8
573     psrlw    m3, 8
574     por      m2, m0
575     por      m3, m1
576     mov%1    [r0 +  0], m2
577     mov%1    [r0 + 16], m3
578 %endif
579     add      r0, 32
580     add      r1, 32
581     dec      r2
582     jnz      .loop8_%1
583 .left4_%1:
584     mov      r2, r3
585     and      r3, 4
586     jz       .left
587     mov%1    m0, [r1]
588 %if cpuflag(ssse3)
589     pshufb   m0, m2
590     mov%1    [r0], m0
591 %else
592     pshuflw  m0, m0, 10110001b
593     pshufhw  m0, m0, 10110001b
594     mova     m2, m0
595     psllw    m0, 8
596     psrlw    m2, 8
597     por      m2, m0
598     mov%1    [r0], m2
599 %endif
600     add      r1, 16
601     add      r0, 16
602 %endmacro
603
604 ; void bswap_buf(uint32_t *dst, const uint32_t *src, int w);
605 %macro BSWAP32_BUF 0
606 %if cpuflag(ssse3)
607 cglobal bswap32_buf, 3,4,3
608     mov      r3, r1
609     mova     m2, [pb_bswap32]
610 %else
611 cglobal bswap32_buf, 3,4,5
612     mov      r3, r1
613 %endif
614     or       r3, r0
615     and      r3, 15
616     jz       .start_align
617     BSWAP_LOOPS  u
618     jmp      .left
619 .start_align:
620     BSWAP_LOOPS  a
621 .left:
622 %if cpuflag(ssse3)
623     mov      r3, r2
624     and      r2, 2
625     jz       .left1
626     movq     m0, [r1]
627     pshufb   m0, m2
628     movq     [r0], m0
629     add      r1, 8
630     add      r0, 8
631 .left1:
632     and      r3, 1
633     jz       .end
634     mov      r2d, [r1]
635     bswap    r2d
636     mov      [r0], r2d
637 %else
638     and      r2, 3
639     jz       .end
640 .loop2:
641     mov      r3d, [r1]
642     bswap    r3d
643     mov      [r0], r3d
644     add      r1, 4
645     add      r0, 4
646     dec      r2
647     jnz      .loop2
648 %endif
649 .end:
650     RET
651 %endmacro
652
653 INIT_XMM sse2
654 BSWAP32_BUF
655
656 INIT_XMM ssse3
657 BSWAP32_BUF