]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/dsputil.asm
ansi: remove an extra return
[ffmpeg] / libavcodec / x86 / dsputil.asm
1 ;******************************************************************************
2 ;* MMX optimized DSP utils
3 ;* Copyright (c) 2008 Loren Merritt
4 ;*
5 ;* This file is part of Libav.
6 ;*
7 ;* Libav is free software; you can redistribute it and/or
8 ;* modify it under the terms of the GNU Lesser General Public
9 ;* License as published by the Free Software Foundation; either
10 ;* version 2.1 of the License, or (at your option) any later version.
11 ;*
12 ;* Libav is distributed in the hope that it will be useful,
13 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;* Lesser General Public License for more details.
16 ;*
17 ;* You should have received a copy of the GNU Lesser General Public
18 ;* License along with Libav; if not, write to the Free Software
19 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 ;******************************************************************************
21
22 %include "libavutil/x86/x86util.asm"
23
24 SECTION_RODATA
25 pb_f: times 16 db 15
26 pb_zzzzzzzz77777777: times 8 db -1
27 pb_7: times 8 db 7
28 pb_zzzz3333zzzzbbbb: db -1,-1,-1,-1,3,3,3,3,-1,-1,-1,-1,11,11,11,11
29 pb_zz11zz55zz99zzdd: db -1,-1,1,1,-1,-1,5,5,-1,-1,9,9,-1,-1,13,13
30 pb_revwords: SHUFFLE_MASK_W 7, 6, 5, 4, 3, 2, 1, 0
31 pd_16384: times 4 dd 16384
32 pb_bswap32: db 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
33
34 SECTION_TEXT
35
36 %macro SCALARPRODUCT 0
37 ; int scalarproduct_int16(int16_t *v1, int16_t *v2, int order)
38 cglobal scalarproduct_int16, 3,3,3, v1, v2, order
39     shl orderq, 1
40     add v1q, orderq
41     add v2q, orderq
42     neg orderq
43     pxor    m2, m2
44 .loop:
45     movu    m0, [v1q + orderq]
46     movu    m1, [v1q + orderq + mmsize]
47     pmaddwd m0, [v2q + orderq]
48     pmaddwd m1, [v2q + orderq + mmsize]
49     paddd   m2, m0
50     paddd   m2, m1
51     add     orderq, mmsize*2
52     jl .loop
53 %if mmsize == 16
54     movhlps m0, m2
55     paddd   m2, m0
56     pshuflw m0, m2, 0x4e
57 %else
58     pshufw  m0, m2, 0x4e
59 %endif
60     paddd   m2, m0
61     movd   eax, m2
62     RET
63
64 ; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul)
65 cglobal scalarproduct_and_madd_int16, 4,4,8, v1, v2, v3, order, mul
66     shl orderq, 1
67     movd    m7, mulm
68 %if mmsize == 16
69     pshuflw m7, m7, 0
70     punpcklqdq m7, m7
71 %else
72     pshufw  m7, m7, 0
73 %endif
74     pxor    m6, m6
75     add v1q, orderq
76     add v2q, orderq
77     add v3q, orderq
78     neg orderq
79 .loop:
80     movu    m0, [v2q + orderq]
81     movu    m1, [v2q + orderq + mmsize]
82     mova    m4, [v1q + orderq]
83     mova    m5, [v1q + orderq + mmsize]
84     movu    m2, [v3q + orderq]
85     movu    m3, [v3q + orderq + mmsize]
86     pmaddwd m0, m4
87     pmaddwd m1, m5
88     pmullw  m2, m7
89     pmullw  m3, m7
90     paddd   m6, m0
91     paddd   m6, m1
92     paddw   m2, m4
93     paddw   m3, m5
94     mova    [v1q + orderq], m2
95     mova    [v1q + orderq + mmsize], m3
96     add     orderq, mmsize*2
97     jl .loop
98 %if mmsize == 16
99     movhlps m0, m6
100     paddd   m6, m0
101     pshuflw m0, m6, 0x4e
102 %else
103     pshufw  m0, m6, 0x4e
104 %endif
105     paddd   m6, m0
106     movd   eax, m6
107     RET
108 %endmacro
109
110 INIT_MMX mmxext
111 SCALARPRODUCT
112 INIT_XMM sse2
113 SCALARPRODUCT
114
115 %macro SCALARPRODUCT_LOOP 1
116 align 16
117 .loop%1:
118     sub     orderq, mmsize*2
119 %if %1
120     mova    m1, m4
121     mova    m4, [v2q + orderq]
122     mova    m0, [v2q + orderq + mmsize]
123     palignr m1, m0, %1
124     palignr m0, m4, %1
125     mova    m3, m5
126     mova    m5, [v3q + orderq]
127     mova    m2, [v3q + orderq + mmsize]
128     palignr m3, m2, %1
129     palignr m2, m5, %1
130 %else
131     mova    m0, [v2q + orderq]
132     mova    m1, [v2q + orderq + mmsize]
133     mova    m2, [v3q + orderq]
134     mova    m3, [v3q + orderq + mmsize]
135 %endif
136     %define t0  [v1q + orderq]
137     %define t1  [v1q + orderq + mmsize]
138 %if ARCH_X86_64
139     mova    m8, t0
140     mova    m9, t1
141     %define t0  m8
142     %define t1  m9
143 %endif
144     pmaddwd m0, t0
145     pmaddwd m1, t1
146     pmullw  m2, m7
147     pmullw  m3, m7
148     paddw   m2, t0
149     paddw   m3, t1
150     paddd   m6, m0
151     paddd   m6, m1
152     mova    [v1q + orderq], m2
153     mova    [v1q + orderq + mmsize], m3
154     jg .loop%1
155 %if %1
156     jmp .end
157 %endif
158 %endmacro
159
160 ; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul)
161 INIT_XMM ssse3
162 cglobal scalarproduct_and_madd_int16, 4,5,10, v1, v2, v3, order, mul
163     shl orderq, 1
164     movd    m7, mulm
165     pshuflw m7, m7, 0
166     punpcklqdq m7, m7
167     pxor    m6, m6
168     mov    r4d, v2d
169     and    r4d, 15
170     and    v2q, ~15
171     and    v3q, ~15
172     mova    m4, [v2q + orderq]
173     mova    m5, [v3q + orderq]
174     ; linear is faster than branch tree or jump table, because the branches taken are cyclic (i.e. predictable)
175     cmp    r4d, 0
176     je .loop0
177     cmp    r4d, 2
178     je .loop2
179     cmp    r4d, 4
180     je .loop4
181     cmp    r4d, 6
182     je .loop6
183     cmp    r4d, 8
184     je .loop8
185     cmp    r4d, 10
186     je .loop10
187     cmp    r4d, 12
188     je .loop12
189 SCALARPRODUCT_LOOP 14
190 SCALARPRODUCT_LOOP 12
191 SCALARPRODUCT_LOOP 10
192 SCALARPRODUCT_LOOP 8
193 SCALARPRODUCT_LOOP 6
194 SCALARPRODUCT_LOOP 4
195 SCALARPRODUCT_LOOP 2
196 SCALARPRODUCT_LOOP 0
197 .end:
198     movhlps m0, m6
199     paddd   m6, m0
200     pshuflw m0, m6, 0x4e
201     paddd   m6, m0
202     movd   eax, m6
203     RET
204
205
206 ;-----------------------------------------------------------------------------
207 ; void ff_apply_window_int16(int16_t *output, const int16_t *input,
208 ;                            const int16_t *window, unsigned int len)
209 ;-----------------------------------------------------------------------------
210
211 %macro REVERSE_WORDS 1-2
212 %if cpuflag(ssse3) && notcpuflag(atom)
213     pshufb  %1, %2
214 %elif cpuflag(sse2)
215     pshuflw  %1, %1, 0x1B
216     pshufhw  %1, %1, 0x1B
217     pshufd   %1, %1, 0x4E
218 %elif cpuflag(mmxext)
219     pshufw   %1, %1, 0x1B
220 %endif
221 %endmacro
222
223 %macro MUL16FIXED 3
224 %if cpuflag(ssse3) ; dst, src, unused
225 ; dst = ((dst * src) + (1<<14)) >> 15
226     pmulhrsw   %1, %2
227 %elif cpuflag(mmxext) ; dst, src, temp
228 ; dst = (dst * src) >> 15
229 ; pmulhw cuts off the bottom bit, so we have to lshift by 1 and add it back
230 ; in from the pmullw result.
231     mova    %3, %1
232     pmulhw  %1, %2
233     pmullw  %3, %2
234     psrlw   %3, 15
235     psllw   %1, 1
236     por     %1, %3
237 %endif
238 %endmacro
239
240 %macro APPLY_WINDOW_INT16 1 ; %1 bitexact version
241 %if %1
242 cglobal apply_window_int16, 4,5,6, output, input, window, offset, offset2
243 %else
244 cglobal apply_window_int16_round, 4,5,6, output, input, window, offset, offset2
245 %endif
246     lea     offset2q, [offsetq-mmsize]
247 %if cpuflag(ssse3) && notcpuflag(atom)
248     mova          m5, [pb_revwords]
249     ALIGN 16
250 %elif %1
251     mova          m5, [pd_16384]
252 %endif
253 .loop:
254 %if cpuflag(ssse3)
255     ; This version does the 16x16->16 multiplication in-place without expanding
256     ; to 32-bit. The ssse3 version is bit-identical.
257     mova          m0, [windowq+offset2q]
258     mova          m1, [ inputq+offset2q]
259     pmulhrsw      m1, m0
260     REVERSE_WORDS m0, m5
261     pmulhrsw      m0, [ inputq+offsetq ]
262     mova  [outputq+offset2q], m1
263     mova  [outputq+offsetq ], m0
264 %elif %1
265     ; This version expands 16-bit to 32-bit, multiplies by the window,
266     ; adds 16384 for rounding, right shifts 15, then repacks back to words to
267     ; save to the output. The window is reversed for the second half.
268     mova          m3, [windowq+offset2q]
269     mova          m4, [ inputq+offset2q]
270     pxor          m0, m0
271     punpcklwd     m0, m3
272     punpcklwd     m1, m4
273     pmaddwd       m0, m1
274     paddd         m0, m5
275     psrad         m0, 15
276     pxor          m2, m2
277     punpckhwd     m2, m3
278     punpckhwd     m1, m4
279     pmaddwd       m2, m1
280     paddd         m2, m5
281     psrad         m2, 15
282     packssdw      m0, m2
283     mova  [outputq+offset2q], m0
284     REVERSE_WORDS m3
285     mova          m4, [ inputq+offsetq]
286     pxor          m0, m0
287     punpcklwd     m0, m3
288     punpcklwd     m1, m4
289     pmaddwd       m0, m1
290     paddd         m0, m5
291     psrad         m0, 15
292     pxor          m2, m2
293     punpckhwd     m2, m3
294     punpckhwd     m1, m4
295     pmaddwd       m2, m1
296     paddd         m2, m5
297     psrad         m2, 15
298     packssdw      m0, m2
299     mova  [outputq+offsetq], m0
300 %else
301     ; This version does the 16x16->16 multiplication in-place without expanding
302     ; to 32-bit. The mmxext and sse2 versions do not use rounding, and
303     ; therefore are not bit-identical to the C version.
304     mova          m0, [windowq+offset2q]
305     mova          m1, [ inputq+offset2q]
306     mova          m2, [ inputq+offsetq ]
307     MUL16FIXED    m1, m0, m3
308     REVERSE_WORDS m0
309     MUL16FIXED    m2, m0, m3
310     mova  [outputq+offset2q], m1
311     mova  [outputq+offsetq ], m2
312 %endif
313     add      offsetd, mmsize
314     sub     offset2d, mmsize
315     jae .loop
316     REP_RET
317 %endmacro
318
319 INIT_MMX mmxext
320 APPLY_WINDOW_INT16 0
321 INIT_XMM sse2
322 APPLY_WINDOW_INT16 0
323
324 INIT_MMX mmxext
325 APPLY_WINDOW_INT16 1
326 INIT_XMM sse2
327 APPLY_WINDOW_INT16 1
328 INIT_XMM ssse3
329 APPLY_WINDOW_INT16 1
330 INIT_XMM ssse3, atom
331 APPLY_WINDOW_INT16 1
332
333
334 ; void add_hfyu_median_prediction_mmxext(uint8_t *dst, const uint8_t *top, const uint8_t *diff, int w, int *left, int *left_top)
335 INIT_MMX mmxext
336 cglobal add_hfyu_median_prediction, 6,6,0, dst, top, diff, w, left, left_top
337     movq    mm0, [topq]
338     movq    mm2, mm0
339     movd    mm4, [left_topq]
340     psllq   mm2, 8
341     movq    mm1, mm0
342     por     mm4, mm2
343     movd    mm3, [leftq]
344     psubb   mm0, mm4 ; t-tl
345     add    dstq, wq
346     add    topq, wq
347     add   diffq, wq
348     neg      wq
349     jmp .skip
350 .loop:
351     movq    mm4, [topq+wq]
352     movq    mm0, mm4
353     psllq   mm4, 8
354     por     mm4, mm1
355     movq    mm1, mm0 ; t
356     psubb   mm0, mm4 ; t-tl
357 .skip:
358     movq    mm2, [diffq+wq]
359 %assign i 0
360 %rep 8
361     movq    mm4, mm0
362     paddb   mm4, mm3 ; t-tl+l
363     movq    mm5, mm3
364     pmaxub  mm3, mm1
365     pminub  mm5, mm1
366     pminub  mm3, mm4
367     pmaxub  mm3, mm5 ; median
368     paddb   mm3, mm2 ; +residual
369 %if i==0
370     movq    mm7, mm3
371     psllq   mm7, 56
372 %else
373     movq    mm6, mm3
374     psrlq   mm7, 8
375     psllq   mm6, 56
376     por     mm7, mm6
377 %endif
378 %if i<7
379     psrlq   mm0, 8
380     psrlq   mm1, 8
381     psrlq   mm2, 8
382 %endif
383 %assign i i+1
384 %endrep
385     movq [dstq+wq], mm7
386     add      wq, 8
387     jl .loop
388     movzx   r2d, byte [dstq-1]
389     mov [leftq], r2d
390     movzx   r2d, byte [topq-1]
391     mov [left_topq], r2d
392     RET
393
394
395 %macro ADD_HFYU_LEFT_LOOP 2 ; %1 = dst_is_aligned, %2 = src_is_aligned
396     add     srcq, wq
397     add     dstq, wq
398     neg     wq
399 %%.loop:
400 %if %2
401     mova    m1, [srcq+wq]
402 %else
403     movu    m1, [srcq+wq]
404 %endif
405     mova    m2, m1
406     psllw   m1, 8
407     paddb   m1, m2
408     mova    m2, m1
409     pshufb  m1, m3
410     paddb   m1, m2
411     pshufb  m0, m5
412     mova    m2, m1
413     pshufb  m1, m4
414     paddb   m1, m2
415 %if mmsize == 16
416     mova    m2, m1
417     pshufb  m1, m6
418     paddb   m1, m2
419 %endif
420     paddb   m0, m1
421 %if %1
422     mova    [dstq+wq], m0
423 %else
424     movq    [dstq+wq], m0
425     movhps  [dstq+wq+8], m0
426 %endif
427     add     wq, mmsize
428     jl %%.loop
429     mov     eax, mmsize-1
430     sub     eax, wd
431     movd    m1, eax
432     pshufb  m0, m1
433     movd    eax, m0
434     RET
435 %endmacro
436
437 ; int add_hfyu_left_prediction(uint8_t *dst, const uint8_t *src, int w, int left)
438 INIT_MMX ssse3
439 cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left
440 .skip_prologue:
441     mova    m5, [pb_7]
442     mova    m4, [pb_zzzz3333zzzzbbbb]
443     mova    m3, [pb_zz11zz55zz99zzdd]
444     movd    m0, leftm
445     psllq   m0, 56
446     ADD_HFYU_LEFT_LOOP 1, 1
447
448 INIT_XMM sse4
449 cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left
450     mova    m5, [pb_f]
451     mova    m6, [pb_zzzzzzzz77777777]
452     mova    m4, [pb_zzzz3333zzzzbbbb]
453     mova    m3, [pb_zz11zz55zz99zzdd]
454     movd    m0, leftm
455     pslldq  m0, 15
456     test    srcq, 15
457     jnz .src_unaligned
458     test    dstq, 15
459     jnz .dst_unaligned
460     ADD_HFYU_LEFT_LOOP 1, 1
461 .dst_unaligned:
462     ADD_HFYU_LEFT_LOOP 0, 1
463 .src_unaligned:
464     ADD_HFYU_LEFT_LOOP 0, 0
465
466
467 ; float scalarproduct_float_sse(const float *v1, const float *v2, int len)
468 INIT_XMM sse
469 cglobal scalarproduct_float, 3,3,2, v1, v2, offset
470     neg offsetq
471     shl offsetq, 2
472     sub v1q, offsetq
473     sub v2q, offsetq
474     xorps xmm0, xmm0
475     .loop:
476         movaps   xmm1, [v1q+offsetq]
477         mulps    xmm1, [v2q+offsetq]
478         addps    xmm0, xmm1
479         add      offsetq, 16
480         js       .loop
481     movhlps xmm1, xmm0
482     addps   xmm0, xmm1
483     movss   xmm1, xmm0
484     shufps  xmm0, xmm0, 1
485     addss   xmm0, xmm1
486 %if ARCH_X86_64 == 0
487     movss   r0m,  xmm0
488     fld     dword r0m
489 %endif
490     RET
491
492 ;-----------------------------------------------------------------------------
493 ; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min,
494 ;                           int32_t max, unsigned int len)
495 ;-----------------------------------------------------------------------------
496
497 ; %1 = number of xmm registers used
498 ; %2 = number of inline load/process/store loops per asm loop
499 ; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop
500 ; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2)
501 ; %5 = suffix
502 %macro VECTOR_CLIP_INT32 4-5
503 cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len
504 %if %4
505     cvtsi2ss  m4, minm
506     cvtsi2ss  m5, maxm
507 %else
508     movd      m4, minm
509     movd      m5, maxm
510 %endif
511     SPLATD    m4
512     SPLATD    m5
513 .loop:
514 %assign %%i 1
515 %rep %2
516     mova      m0,  [srcq+mmsize*0*%%i]
517     mova      m1,  [srcq+mmsize*1*%%i]
518     mova      m2,  [srcq+mmsize*2*%%i]
519     mova      m3,  [srcq+mmsize*3*%%i]
520 %if %3
521     mova      m7,  [srcq+mmsize*4*%%i]
522     mova      m8,  [srcq+mmsize*5*%%i]
523     mova      m9,  [srcq+mmsize*6*%%i]
524     mova      m10, [srcq+mmsize*7*%%i]
525 %endif
526     CLIPD  m0,  m4, m5, m6
527     CLIPD  m1,  m4, m5, m6
528     CLIPD  m2,  m4, m5, m6
529     CLIPD  m3,  m4, m5, m6
530 %if %3
531     CLIPD  m7,  m4, m5, m6
532     CLIPD  m8,  m4, m5, m6
533     CLIPD  m9,  m4, m5, m6
534     CLIPD  m10, m4, m5, m6
535 %endif
536     mova  [dstq+mmsize*0*%%i], m0
537     mova  [dstq+mmsize*1*%%i], m1
538     mova  [dstq+mmsize*2*%%i], m2
539     mova  [dstq+mmsize*3*%%i], m3
540 %if %3
541     mova  [dstq+mmsize*4*%%i], m7
542     mova  [dstq+mmsize*5*%%i], m8
543     mova  [dstq+mmsize*6*%%i], m9
544     mova  [dstq+mmsize*7*%%i], m10
545 %endif
546 %assign %%i %%i+1
547 %endrep
548     add     srcq, mmsize*4*(%2+%3)
549     add     dstq, mmsize*4*(%2+%3)
550     sub     lend, mmsize*(%2+%3)
551     jg .loop
552     REP_RET
553 %endmacro
554
555 INIT_MMX mmx
556 %define CLIPD CLIPD_MMX
557 VECTOR_CLIP_INT32 0, 1, 0, 0
558 INIT_XMM sse2
559 VECTOR_CLIP_INT32 6, 1, 0, 0, _int
560 %define CLIPD CLIPD_SSE2
561 VECTOR_CLIP_INT32 6, 2, 0, 1
562 INIT_XMM sse4
563 %define CLIPD CLIPD_SSE41
564 %ifdef m8
565 VECTOR_CLIP_INT32 11, 1, 1, 0
566 %else
567 VECTOR_CLIP_INT32 6, 1, 0, 0
568 %endif
569
570 ;-----------------------------------------------------------------------------
571 ; void vector_fmul_reverse(float *dst, const float *src0, const float *src1,
572 ;                          int len)
573 ;-----------------------------------------------------------------------------
574 %macro VECTOR_FMUL_REVERSE 0
575 cglobal vector_fmul_reverse, 4,4,2, dst, src0, src1, len
576     lea       lenq, [lend*4 - 2*mmsize]
577 ALIGN 16
578 .loop:
579 %if cpuflag(avx)
580     vmovaps     xmm0, [src1q + 16]
581     vinsertf128 m0, m0, [src1q], 1
582     vshufps     m0, m0, m0, q0123
583     vmovaps     xmm1, [src1q + mmsize + 16]
584     vinsertf128 m1, m1, [src1q + mmsize], 1
585     vshufps     m1, m1, m1, q0123
586 %else
587     mova    m0, [src1q]
588     mova    m1, [src1q + mmsize]
589     shufps  m0, m0, q0123
590     shufps  m1, m1, q0123
591 %endif
592     mulps   m0, m0, [src0q + lenq + mmsize]
593     mulps   m1, m1, [src0q + lenq]
594     mova    [dstq + lenq + mmsize], m0
595     mova    [dstq + lenq], m1
596     add     src1q, 2*mmsize
597     sub     lenq,  2*mmsize
598     jge     .loop
599     REP_RET
600 %endmacro
601
602 INIT_XMM sse
603 VECTOR_FMUL_REVERSE
604 INIT_YMM avx
605 VECTOR_FMUL_REVERSE
606
607 ;-----------------------------------------------------------------------------
608 ; vector_fmul_add(float *dst, const float *src0, const float *src1,
609 ;                 const float *src2, int len)
610 ;-----------------------------------------------------------------------------
611 %macro VECTOR_FMUL_ADD 0
612 cglobal vector_fmul_add, 5,5,2, dst, src0, src1, src2, len
613     lea       lenq, [lend*4 - 2*mmsize]
614 ALIGN 16
615 .loop:
616     mova    m0,   [src0q + lenq]
617     mova    m1,   [src0q + lenq + mmsize]
618     mulps   m0, m0, [src1q + lenq]
619     mulps   m1, m1, [src1q + lenq + mmsize]
620     addps   m0, m0, [src2q + lenq]
621     addps   m1, m1, [src2q + lenq + mmsize]
622     mova    [dstq + lenq], m0
623     mova    [dstq + lenq + mmsize], m1
624
625     sub     lenq,   2*mmsize
626     jge     .loop
627     REP_RET
628 %endmacro
629
630 INIT_XMM sse
631 VECTOR_FMUL_ADD
632 INIT_YMM avx
633 VECTOR_FMUL_ADD
634
635 ;-----------------------------------------------------------------------------
636 ; void ff_butterflies_float_interleave(float *dst, const float *src0,
637 ;                                      const float *src1, int len);
638 ;-----------------------------------------------------------------------------
639
640 %macro BUTTERFLIES_FLOAT_INTERLEAVE 0
641 cglobal butterflies_float_interleave, 4,4,3, dst, src0, src1, len
642 %if ARCH_X86_64
643     movsxd    lenq, lend
644 %endif
645     test      lenq, lenq
646     jz .end
647     shl       lenq, 2
648     lea      src0q, [src0q +   lenq]
649     lea      src1q, [src1q +   lenq]
650     lea       dstq, [ dstq + 2*lenq]
651     neg       lenq
652 .loop:
653     mova        m0, [src0q + lenq]
654     mova        m1, [src1q + lenq]
655     subps       m2, m0, m1
656     addps       m0, m0, m1
657     unpcklps    m1, m0, m2
658     unpckhps    m0, m0, m2
659 %if cpuflag(avx)
660     vextractf128 [dstq + 2*lenq     ], m1, 0
661     vextractf128 [dstq + 2*lenq + 16], m0, 0
662     vextractf128 [dstq + 2*lenq + 32], m1, 1
663     vextractf128 [dstq + 2*lenq + 48], m0, 1
664 %else
665     mova [dstq + 2*lenq         ], m1
666     mova [dstq + 2*lenq + mmsize], m0
667 %endif
668     add       lenq, mmsize
669     jl .loop
670 .end:
671     REP_RET
672 %endmacro
673
674 INIT_XMM sse
675 BUTTERFLIES_FLOAT_INTERLEAVE
676 INIT_YMM avx
677 BUTTERFLIES_FLOAT_INTERLEAVE
678
679 ; %1 = aligned/unaligned
680 %macro BSWAP_LOOPS  1
681     mov      r3, r2
682     sar      r2, 3
683     jz       .left4_%1
684 .loop8_%1:
685     mov%1    m0, [r1 +  0]
686     mov%1    m1, [r1 + 16]
687 %if cpuflag(ssse3)
688     pshufb   m0, m2
689     pshufb   m1, m2
690     mova     [r0 +  0], m0
691     mova     [r0 + 16], m1
692 %else
693     pshuflw  m0, m0, 10110001b
694     pshuflw  m1, m1, 10110001b
695     pshufhw  m0, m0, 10110001b
696     pshufhw  m1, m1, 10110001b
697     mova     m2, m0
698     mova     m3, m1
699     psllw    m0, 8
700     psllw    m1, 8
701     psrlw    m2, 8
702     psrlw    m3, 8
703     por      m2, m0
704     por      m3, m1
705     mova     [r0 +  0], m2
706     mova     [r0 + 16], m3
707 %endif
708     add      r0, 32
709     add      r1, 32
710     dec      r2
711     jnz      .loop8_%1
712 .left4_%1:
713     mov      r2, r3
714     and      r3, 4
715     jz       .left
716     mov%1    m0, [r1]
717 %if cpuflag(ssse3)
718     pshufb   m0, m2
719     mova     [r0], m0
720 %else
721     pshuflw  m0, m0, 10110001b
722     pshufhw  m0, m0, 10110001b
723     mova     m2, m0
724     psllw    m0, 8
725     psrlw    m2, 8
726     por      m2, m0
727     mova     [r0], m2
728 %endif
729     add      r1, 16
730     add      r0, 16
731 %endmacro
732
733 ; void bswap_buf(uint32_t *dst, const uint32_t *src, int w);
734 %macro BSWAP32_BUF 0
735 %if cpuflag(ssse3)
736 cglobal bswap32_buf, 3,4,3
737     mov      r3, r1
738     mova     m2, [pb_bswap32]
739 %else
740 cglobal bswap32_buf, 3,4,5
741     mov      r3, r1
742 %endif
743     and      r3, 15
744     jz       .start_align
745     BSWAP_LOOPS  u
746     jmp      .left
747 .start_align:
748     BSWAP_LOOPS  a
749 .left:
750 %if cpuflag(ssse3)
751     mov      r3, r2
752     and      r2, 2
753     jz       .left1
754     movq     m0, [r1]
755     pshufb   m0, m2
756     movq     [r0], m0
757     add      r1, 8
758     add      r0, 8
759 .left1:
760     and      r3, 1
761     jz       .end
762     mov      r2d, [r1]
763     bswap    r2d
764     mov      [r0], r2d
765 %else
766     and      r2, 3
767     jz       .end
768 .loop2:
769     mov      r3d, [r1]
770     bswap    r3d
771     mov      [r0], r3d
772     add      r1, 4
773     add      r0, 4
774     dec      r2
775     jnz      .loop2
776 %endif
777 .end:
778     RET
779 %endmacro
780
781 INIT_XMM sse2
782 BSWAP32_BUF
783
784 INIT_XMM ssse3
785 BSWAP32_BUF
786
787 %macro op_avgh 3
788     movh   %3, %2
789     pavgb  %1, %3
790     movh   %2, %1
791 %endmacro
792
793 %macro op_avg 2
794     pavgb  %1, %2
795     mova   %2, %1
796 %endmacro
797
798 %macro op_puth 2-3
799     movh   %2, %1
800 %endmacro
801
802 %macro op_put 2
803     mova   %2, %1
804 %endmacro
805
806 ; void pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
807 %macro PIXELS4_L2 1
808 %define OP op_%1h
809 cglobal %1_pixels4_l2, 6,6
810     movsxdifnidn r3, r3d
811     movsxdifnidn r4, r4d
812     test        r5d, 1
813     je        .loop
814     movd         m0, [r1]
815     movd         m1, [r2]
816     add          r1, r4
817     add          r2, 4
818     pavgb        m0, m1
819     OP           m0, [r0], m3
820     add          r0, r3
821     dec         r5d
822 .loop:
823     mova         m0, [r1]
824     mova         m1, [r1+r4]
825     lea          r1, [r1+2*r4]
826     pavgb        m0, [r2]
827     pavgb        m1, [r2+4]
828     OP           m0, [r0], m3
829     OP           m1, [r0+r3], m3
830     lea          r0, [r0+2*r3]
831     mova         m0, [r1]
832     mova         m1, [r1+r4]
833     lea          r1, [r1+2*r4]
834     pavgb        m0, [r2+8]
835     pavgb        m1, [r2+12]
836     OP           m0, [r0], m3
837     OP           m1, [r0+r3], m3
838     lea          r0, [r0+2*r3]
839     add          r2, 16
840     sub         r5d, 4
841     jne       .loop
842     REP_RET
843 %endmacro
844
845 INIT_MMX mmxext
846 PIXELS4_L2 put
847 PIXELS4_L2 avg
848
849 ; void pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
850 %macro PIXELS8_L2 1
851 %define OP op_%1
852 cglobal %1_pixels8_l2, 6,6
853     movsxdifnidn r3, r3d
854     movsxdifnidn r4, r4d
855     test        r5d, 1
856     je        .loop
857     mova         m0, [r1]
858     mova         m1, [r2]
859     add          r1, r4
860     add          r2, 8
861     pavgb        m0, m1
862     OP           m0, [r0]
863     add          r0, r3
864     dec         r5d
865 .loop:
866     mova         m0, [r1]
867     mova         m1, [r1+r4]
868     lea          r1, [r1+2*r4]
869     pavgb        m0, [r2]
870     pavgb        m1, [r2+8]
871     OP           m0, [r0]
872     OP           m1, [r0+r3]
873     lea          r0, [r0+2*r3]
874     mova         m0, [r1]
875     mova         m1, [r1+r4]
876     lea          r1, [r1+2*r4]
877     pavgb        m0, [r2+16]
878     pavgb        m1, [r2+24]
879     OP           m0, [r0]
880     OP           m1, [r0+r3]
881     lea          r0, [r0+2*r3]
882     add          r2, 32
883     sub         r5d, 4
884     jne       .loop
885     REP_RET
886 %endmacro
887
888 INIT_MMX mmxext
889 PIXELS8_L2 put
890 PIXELS8_L2 avg
891
892 ; void pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
893 %macro PIXELS16_L2 1
894 %define OP op_%1
895 cglobal %1_pixels16_l2, 6,6
896     movsxdifnidn r3, r3d
897     movsxdifnidn r4, r4d
898     test        r5d, 1
899     je        .loop
900     mova         m0, [r1]
901     mova         m1, [r1+8]
902     pavgb        m0, [r2]
903     pavgb        m1, [r2+8]
904     add          r1, r4
905     add          r2, 16
906     OP           m0, [r0]
907     OP           m1, [r0+8]
908     add          r0, r3
909     dec         r5d
910 .loop:
911     mova         m0, [r1]
912     mova         m1, [r1+8]
913     add          r1, r4
914     pavgb        m0, [r2]
915     pavgb        m1, [r2+8]
916     OP           m0, [r0]
917     OP           m1, [r0+8]
918     add          r0, r3
919     mova         m0, [r1]
920     mova         m1, [r1+8]
921     add          r1, r4
922     pavgb        m0, [r2+16]
923     pavgb        m1, [r2+24]
924     OP           m0, [r0]
925     OP           m1, [r0+8]
926     add          r0, r3
927     add          r2, 32
928     sub         r5d, 2
929     jne       .loop
930     REP_RET
931 %endmacro
932
933 INIT_MMX mmxext
934 PIXELS16_L2 put
935 PIXELS16_L2 avg
936
937 INIT_MMX mmxext
938 ; void pixels(uint8_t *block, const uint8_t *pixels, int line_size, int h)
939 %macro PIXELS48 2
940 %if %2 == 4
941 %define OP movh
942 %else
943 %define OP mova
944 %endif
945 cglobal %1_pixels%2, 4,5
946     movsxdifnidn r2, r2d
947     lea          r4, [r2*3]
948 .loop:
949     OP           m0, [r1]
950     OP           m1, [r1+r2]
951     OP           m2, [r1+r2*2]
952     OP           m3, [r1+r4]
953     lea          r1, [r1+r2*4]
954 %ifidn %1, avg
955     pavgb        m0, [r0]
956     pavgb        m1, [r0+r2]
957     pavgb        m2, [r0+r2*2]
958     pavgb        m3, [r0+r4]
959 %endif
960     OP         [r0], m0
961     OP      [r0+r2], m1
962     OP    [r0+r2*2], m2
963     OP      [r0+r4], m3
964     sub         r3d, 4
965     lea          r0, [r0+r2*4]
966     jne       .loop
967     RET
968 %endmacro
969
970 PIXELS48 put, 4
971 PIXELS48 avg, 4
972 PIXELS48 put, 8
973 PIXELS48 avg, 8
974
975 INIT_XMM sse2
976 ; void put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
977 cglobal put_pixels16, 4,5,4
978     movsxdifnidn r2, r2d
979     lea          r4, [r2*3]
980 .loop:
981     movu         m0, [r1]
982     movu         m1, [r1+r2]
983     movu         m2, [r1+r2*2]
984     movu         m3, [r1+r4]
985     lea          r1, [r1+r2*4]
986     mova       [r0], m0
987     mova    [r0+r2], m1
988     mova  [r0+r2*2], m2
989     mova    [r0+r4], m3
990     sub         r3d, 4
991     lea          r0, [r0+r2*4]
992     jnz       .loop
993     REP_RET
994
995 ; void avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
996 cglobal avg_pixels16, 4,5,4
997     movsxdifnidn r2, r2d
998     lea          r4, [r2*3]
999 .loop:
1000     movu         m0, [r1]
1001     movu         m1, [r1+r2]
1002     movu         m2, [r1+r2*2]
1003     movu         m3, [r1+r4]
1004     lea          r1, [r1+r2*4]
1005     pavgb        m0, [r0]
1006     pavgb        m1, [r0+r2]
1007     pavgb        m2, [r0+r2*2]
1008     pavgb        m3, [r0+r4]
1009     mova       [r0], m0
1010     mova    [r0+r2], m1
1011     mova  [r0+r2*2], m2
1012     mova    [r0+r4], m3
1013     sub         r3d, 4
1014     lea          r0, [r0+r2*4]
1015     jnz       .loop
1016     REP_RET