Merge remote-tracking branch 'qatar/master'
[ffmpeg.git] / libavcodec / x86 / dsputil_yasm.asm
1 ;******************************************************************************
2 ;* MMX optimized DSP utils
3 ;* Copyright (c) 2008 Loren Merritt
4 ;*
5 ;* This file is part of FFmpeg.
6 ;*
7 ;* FFmpeg 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 ;* FFmpeg 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 FFmpeg; 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/x86inc.asm"
23 %include "x86util.asm"
24
25 SECTION_RODATA
26 pb_f: times 16 db 15
27 pb_zzzzzzzz77777777: times 8 db -1
28 pb_7: times 8 db 7
29 pb_zzzz3333zzzzbbbb: db -1,-1,-1,-1,3,3,3,3,-1,-1,-1,-1,11,11,11,11
30 pb_zz11zz55zz99zzdd: db -1,-1,1,1,-1,-1,5,5,-1,-1,9,9,-1,-1,13,13
31 pb_revwords: db 14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1
32 pd_16384: times 4 dd 16384
33 pb_bswap32: db 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
34
35 SECTION_TEXT
36
37 %macro SCALARPRODUCT 1
38 ; int scalarproduct_int16(int16_t *v1, int16_t *v2, int order)
39 cglobal scalarproduct_int16_%1, 3,3,3, v1, v2, order
40     shl orderq, 1
41     add v1q, orderq
42     add v2q, orderq
43     neg orderq
44     pxor    m2, m2
45 .loop:
46     movu    m0, [v1q + orderq]
47     movu    m1, [v1q + orderq + mmsize]
48     pmaddwd m0, [v2q + orderq]
49     pmaddwd m1, [v2q + orderq + mmsize]
50     paddd   m2, m0
51     paddd   m2, m1
52     add     orderq, mmsize*2
53     jl .loop
54 %if mmsize == 16
55     movhlps m0, m2
56     paddd   m2, m0
57     pshuflw m0, m2, 0x4e
58 %else
59     pshufw  m0, m2, 0x4e
60 %endif
61     paddd   m2, m0
62     movd   eax, m2
63     RET
64
65 ; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul)
66 cglobal scalarproduct_and_madd_int16_%1, 4,4,8, v1, v2, v3, order, mul
67     shl orderq, 1
68     movd    m7, mulm
69 %if mmsize == 16
70     pshuflw m7, m7, 0
71     punpcklqdq m7, m7
72 %else
73     pshufw  m7, m7, 0
74 %endif
75     pxor    m6, m6
76     add v1q, orderq
77     add v2q, orderq
78     add v3q, orderq
79     neg orderq
80 .loop:
81     movu    m0, [v2q + orderq]
82     movu    m1, [v2q + orderq + mmsize]
83     mova    m4, [v1q + orderq]
84     mova    m5, [v1q + orderq + mmsize]
85     movu    m2, [v3q + orderq]
86     movu    m3, [v3q + orderq + mmsize]
87     pmaddwd m0, m4
88     pmaddwd m1, m5
89     pmullw  m2, m7
90     pmullw  m3, m7
91     paddd   m6, m0
92     paddd   m6, m1
93     paddw   m2, m4
94     paddw   m3, m5
95     mova    [v1q + orderq], m2
96     mova    [v1q + orderq + mmsize], m3
97     add     orderq, mmsize*2
98     jl .loop
99 %if mmsize == 16
100     movhlps m0, m6
101     paddd   m6, m0
102     pshuflw m0, m6, 0x4e
103 %else
104     pshufw  m0, m6, 0x4e
105 %endif
106     paddd   m6, m0
107     movd   eax, m6
108     RET
109 %endmacro
110
111 INIT_MMX
112 SCALARPRODUCT mmx2
113 INIT_XMM
114 SCALARPRODUCT sse2
115
116 %macro SCALARPRODUCT_LOOP 1
117 align 16
118 .loop%1:
119     sub     orderq, mmsize*2
120 %if %1
121     mova    m1, m4
122     mova    m4, [v2q + orderq]
123     mova    m0, [v2q + orderq + mmsize]
124     palignr m1, m0, %1
125     palignr m0, m4, %1
126     mova    m3, m5
127     mova    m5, [v3q + orderq]
128     mova    m2, [v3q + orderq + mmsize]
129     palignr m3, m2, %1
130     palignr m2, m5, %1
131 %else
132     mova    m0, [v2q + orderq]
133     mova    m1, [v2q + orderq + mmsize]
134     mova    m2, [v3q + orderq]
135     mova    m3, [v3q + orderq + mmsize]
136 %endif
137     %define t0  [v1q + orderq]
138     %define t1  [v1q + orderq + mmsize]
139 %if ARCH_X86_64
140     mova    m8, t0
141     mova    m9, t1
142     %define t0  m8
143     %define t1  m9
144 %endif
145     pmaddwd m0, t0
146     pmaddwd m1, t1
147     pmullw  m2, m7
148     pmullw  m3, m7
149     paddw   m2, t0
150     paddw   m3, t1
151     paddd   m6, m0
152     paddd   m6, m1
153     mova    [v1q + orderq], m2
154     mova    [v1q + orderq + mmsize], m3
155     jg .loop%1
156 %if %1
157     jmp .end
158 %endif
159 %endmacro
160
161 ; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul)
162 cglobal scalarproduct_and_madd_int16_ssse3, 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_MMXEXT 1-2
212     pshufw   %1, %1, 0x1B
213 %endmacro
214
215 %macro REVERSE_WORDS_SSE2 1-2
216     pshuflw  %1, %1, 0x1B
217     pshufhw  %1, %1, 0x1B
218     pshufd   %1, %1, 0x4E
219 %endmacro
220
221 %macro REVERSE_WORDS_SSSE3 2
222     pshufb  %1, %2
223 %endmacro
224
225 ; dst = (dst * src) >> 15
226 ; pmulhw cuts off the bottom bit, so we have to lshift by 1 and add it back
227 ; in from the pmullw result.
228 %macro MUL16FIXED_MMXEXT 3 ; dst, src, temp
229     mova    %3, %1
230     pmulhw  %1, %2
231     pmullw  %3, %2
232     psrlw   %3, 15
233     psllw   %1, 1
234     por     %1, %3
235 %endmacro
236
237 ; dst = ((dst * src) + (1<<14)) >> 15
238 %macro MUL16FIXED_SSSE3 3 ; dst, src, unused
239     pmulhrsw   %1, %2
240 %endmacro
241
242 %macro APPLY_WINDOW_INT16 3 ; %1=instruction set, %2=mmxext/sse2 bit exact version, %3=has_ssse3
243 cglobal apply_window_int16_%1, 4,5,6, output, input, window, offset, offset2
244     lea     offset2q, [offsetq-mmsize]
245 %if %2
246     mova          m5, [pd_16384]
247 %elifidn %1, ssse3
248     mova          m5, [pb_revwords]
249     ALIGN 16
250 %endif
251 .loop:
252 %if %2
253     ; This version expands 16-bit to 32-bit, multiplies by the window,
254     ; adds 16384 for rounding, right shifts 15, then repacks back to words to
255     ; save to the output. The window is reversed for the second half.
256     mova          m3, [windowq+offset2q]
257     mova          m4, [ inputq+offset2q]
258     pxor          m0, m0
259     punpcklwd     m0, m3
260     punpcklwd     m1, m4
261     pmaddwd       m0, m1
262     paddd         m0, m5
263     psrad         m0, 15
264     pxor          m2, m2
265     punpckhwd     m2, m3
266     punpckhwd     m1, m4
267     pmaddwd       m2, m1
268     paddd         m2, m5
269     psrad         m2, 15
270     packssdw      m0, m2
271     mova  [outputq+offset2q], m0
272     REVERSE_WORDS m3
273     mova          m4, [ inputq+offsetq]
274     pxor          m0, m0
275     punpcklwd     m0, m3
276     punpcklwd     m1, m4
277     pmaddwd       m0, m1
278     paddd         m0, m5
279     psrad         m0, 15
280     pxor          m2, m2
281     punpckhwd     m2, m3
282     punpckhwd     m1, m4
283     pmaddwd       m2, m1
284     paddd         m2, m5
285     psrad         m2, 15
286     packssdw      m0, m2
287     mova  [outputq+offsetq], m0
288 %elif %3
289     ; This version does the 16x16->16 multiplication in-place without expanding
290     ; to 32-bit. The ssse3 version is bit-identical.
291     mova          m0, [windowq+offset2q]
292     mova          m1, [ inputq+offset2q]
293     pmulhrsw      m1, m0
294     REVERSE_WORDS m0, m5
295     pmulhrsw      m0, [ inputq+offsetq ]
296     mova  [outputq+offset2q], m1
297     mova  [outputq+offsetq ], m0
298 %else
299     ; This version does the 16x16->16 multiplication in-place without expanding
300     ; to 32-bit. The mmxext and sse2 versions do not use rounding, and
301     ; therefore are not bit-identical to the C version.
302     mova          m0, [windowq+offset2q]
303     mova          m1, [ inputq+offset2q]
304     mova          m2, [ inputq+offsetq ]
305     MUL16FIXED    m1, m0, m3
306     REVERSE_WORDS m0
307     MUL16FIXED    m2, m0, m3
308     mova  [outputq+offset2q], m1
309     mova  [outputq+offsetq ], m2
310 %endif
311     add      offsetd, mmsize
312     sub     offset2d, mmsize
313     jae .loop
314     REP_RET
315 %endmacro
316
317 INIT_MMX
318 %define REVERSE_WORDS REVERSE_WORDS_MMXEXT
319 %define MUL16FIXED MUL16FIXED_MMXEXT
320 APPLY_WINDOW_INT16 mmxext,     0, 0
321 APPLY_WINDOW_INT16 mmxext_ba,  1, 0
322 INIT_XMM
323 %define REVERSE_WORDS REVERSE_WORDS_SSE2
324 APPLY_WINDOW_INT16 sse2,       0, 0
325 APPLY_WINDOW_INT16 sse2_ba,    1, 0
326 APPLY_WINDOW_INT16 ssse3_atom, 0, 1
327 %define REVERSE_WORDS REVERSE_WORDS_SSSE3
328 APPLY_WINDOW_INT16 ssse3,      0, 1
329
330
331 ; void add_hfyu_median_prediction_mmx2(uint8_t *dst, const uint8_t *top, const uint8_t *diff, int w, int *left, int *left_top)
332 cglobal add_hfyu_median_prediction_mmx2, 6,6,0, dst, top, diff, w, left, left_top
333     movq    mm0, [topq]
334     movq    mm2, mm0
335     movd    mm4, [left_topq]
336     psllq   mm2, 8
337     movq    mm1, mm0
338     por     mm4, mm2
339     movd    mm3, [leftq]
340     psubb   mm0, mm4 ; t-tl
341     add    dstq, wq
342     add    topq, wq
343     add   diffq, wq
344     neg      wq
345     jmp .skip
346 .loop:
347     movq    mm4, [topq+wq]
348     movq    mm0, mm4
349     psllq   mm4, 8
350     por     mm4, mm1
351     movq    mm1, mm0 ; t
352     psubb   mm0, mm4 ; t-tl
353 .skip:
354     movq    mm2, [diffq+wq]
355 %assign i 0
356 %rep 8
357     movq    mm4, mm0
358     paddb   mm4, mm3 ; t-tl+l
359     movq    mm5, mm3
360     pmaxub  mm3, mm1
361     pminub  mm5, mm1
362     pminub  mm3, mm4
363     pmaxub  mm3, mm5 ; median
364     paddb   mm3, mm2 ; +residual
365 %if i==0
366     movq    mm7, mm3
367     psllq   mm7, 56
368 %else
369     movq    mm6, mm3
370     psrlq   mm7, 8
371     psllq   mm6, 56
372     por     mm7, mm6
373 %endif
374 %if i<7
375     psrlq   mm0, 8
376     psrlq   mm1, 8
377     psrlq   mm2, 8
378 %endif
379 %assign i i+1
380 %endrep
381     movq [dstq+wq], mm7
382     add      wq, 8
383     jl .loop
384     movzx   r2d, byte [dstq-1]
385     mov [leftq], r2d
386     movzx   r2d, byte [topq-1]
387     mov [left_topq], r2d
388     RET
389
390
391 %macro ADD_HFYU_LEFT_LOOP 1 ; %1 = is_aligned
392     add     srcq, wq
393     add     dstq, wq
394     neg     wq
395 %%.loop:
396     mova    m1, [srcq+wq]
397     mova    m2, m1
398     psllw   m1, 8
399     paddb   m1, m2
400     mova    m2, m1
401     pshufb  m1, m3
402     paddb   m1, m2
403     pshufb  m0, m5
404     mova    m2, m1
405     pshufb  m1, m4
406     paddb   m1, m2
407 %if mmsize == 16
408     mova    m2, m1
409     pshufb  m1, m6
410     paddb   m1, m2
411 %endif
412     paddb   m0, m1
413 %if %1
414     mova    [dstq+wq], m0
415 %else
416     movq    [dstq+wq], m0
417     movhps  [dstq+wq+8], m0
418 %endif
419     add     wq, mmsize
420     jl %%.loop
421     mov     eax, mmsize-1
422     sub     eax, wd
423     movd    m1, eax
424     pshufb  m0, m1
425     movd    eax, m0
426     RET
427 %endmacro
428
429 ; int add_hfyu_left_prediction(uint8_t *dst, const uint8_t *src, int w, int left)
430 INIT_MMX
431 cglobal add_hfyu_left_prediction_ssse3, 3,3,7, dst, src, w, left
432 .skip_prologue:
433     mova    m5, [pb_7]
434     mova    m4, [pb_zzzz3333zzzzbbbb]
435     mova    m3, [pb_zz11zz55zz99zzdd]
436     movd    m0, leftm
437     psllq   m0, 56
438     ADD_HFYU_LEFT_LOOP 1
439
440 INIT_XMM
441 cglobal add_hfyu_left_prediction_sse4, 3,3,7, dst, src, w, left
442     mova    m5, [pb_f]
443     mova    m6, [pb_zzzzzzzz77777777]
444     mova    m4, [pb_zzzz3333zzzzbbbb]
445     mova    m3, [pb_zz11zz55zz99zzdd]
446     movd    m0, leftm
447     pslldq  m0, 15
448     test    srcq, 15
449     jnz add_hfyu_left_prediction_ssse3.skip_prologue
450     test    dstq, 15
451     jnz .unaligned
452     ADD_HFYU_LEFT_LOOP 1
453 .unaligned:
454     ADD_HFYU_LEFT_LOOP 0
455
456
457 ; float scalarproduct_float_sse(const float *v1, const float *v2, int len)
458 cglobal scalarproduct_float_sse, 3,3,2, v1, v2, offset
459     neg offsetq
460     shl offsetq, 2
461     sub v1q, offsetq
462     sub v2q, offsetq
463     xorps xmm0, xmm0
464     .loop:
465         movaps   xmm1, [v1q+offsetq]
466         mulps    xmm1, [v2q+offsetq]
467         addps    xmm0, xmm1
468         add      offsetq, 16
469         js       .loop
470     movhlps xmm1, xmm0
471     addps   xmm0, xmm1
472     movss   xmm1, xmm0
473     shufps  xmm0, xmm0, 1
474     addss   xmm0, xmm1
475 %if ARCH_X86_64 == 0
476     movd    r0m,  xmm0
477     fld     dword r0m
478 %endif
479     RET
480
481 ; extern void ff_emu_edge_core(uint8_t *buf, const uint8_t *src, x86_reg linesize,
482 ;                              x86_reg start_y, x86_reg end_y, x86_reg block_h,
483 ;                              x86_reg start_x, x86_reg end_x, x86_reg block_w);
484 ;
485 ; The actual function itself is below. It basically wraps a very simple
486 ; w = end_x - start_x
487 ; if (w) {
488 ;   if (w > 22) {
489 ;     jump to the slow loop functions
490 ;   } else {
491 ;     jump to the fast loop functions
492 ;   }
493 ; }
494 ;
495 ; ... and then the same for left/right extend also. See below for loop
496 ; function implementations. Fast are fixed-width, slow is variable-width
497
498 %macro EMU_EDGE_FUNC 0
499 %if ARCH_X86_64
500 %define w_reg r10
501 cglobal emu_edge_core, 6, 7, 1
502     mov        r11, r5          ; save block_h
503 %else
504 %define w_reg r6
505 cglobal emu_edge_core, 2, 7, 0
506     mov         r4, r4m         ; end_y
507     mov         r5, r5m         ; block_h
508 %endif
509
510     ; start with vertical extend (top/bottom) and body pixel copy
511     mov      w_reg, r7m
512     sub      w_reg, r6m         ; w = start_x - end_x
513     sub         r5, r4
514 %if ARCH_X86_64
515     sub         r4, r3
516 %else
517     sub         r4, dword r3m
518 %endif
519     cmp      w_reg, 22
520     jg .slow_v_extend_loop
521 %if ARCH_X86_32
522     mov         r2, r2m         ; linesize
523 %endif
524     sal      w_reg, 7           ; w * 128
525 %ifdef PIC
526     lea        rax, [.emuedge_v_extend_1 - (.emuedge_v_extend_2 - .emuedge_v_extend_1)]
527     add      w_reg, rax
528 %else
529     lea      w_reg, [.emuedge_v_extend_1 - (.emuedge_v_extend_2 - .emuedge_v_extend_1)+w_reg]
530 %endif
531     call     w_reg              ; fast top extend, body copy and bottom extend
532 .v_extend_end:
533
534     ; horizontal extend (left/right)
535     mov      w_reg, r6m         ; start_x
536     sub         r0, w_reg
537 %if ARCH_X86_64
538     mov         r3, r0          ; backup of buf+block_h*linesize
539     mov         r5, r11
540 %else
541     mov        r0m, r0          ; backup of buf+block_h*linesize
542     mov         r5, r5m
543 %endif
544     test     w_reg, w_reg
545     jz .right_extend
546     cmp      w_reg, 22
547     jg .slow_left_extend_loop
548     mov         r1, w_reg
549     dec      w_reg
550     ; FIXME we can do a if size == 1 here if that makes any speed difference, test me
551     sar      w_reg, 1
552     sal      w_reg, 6
553     ; r0=buf+block_h*linesize,r10(64)/r6(32)=start_x offset for funcs
554     ; r6(rax)/r3(ebx)=val,r2=linesize,r1=start_x,r5=block_h
555 %ifdef PIC
556     lea        rax, [.emuedge_extend_left_2]
557     add      w_reg, rax
558 %else
559     lea      w_reg, [.emuedge_extend_left_2+w_reg]
560 %endif
561     call     w_reg
562
563     ; now r3(64)/r0(32)=buf,r2=linesize,r11/r5=block_h,r6/r3=val, r10/r6=end_x, r1=block_w
564 .right_extend:
565 %if ARCH_X86_32
566     mov         r0, r0m
567     mov         r5, r5m
568 %endif
569     mov      w_reg, r7m         ; end_x
570     mov         r1, r8m         ; block_w
571     mov         r4, r1
572     sub         r1, w_reg
573     jz .h_extend_end            ; if (end_x == block_w) goto h_extend_end
574     cmp         r1, 22
575     jg .slow_right_extend_loop
576     dec         r1
577     ; FIXME we can do a if size == 1 here if that makes any speed difference, test me
578     sar         r1, 1
579     sal         r1, 6
580 %ifdef PIC
581     lea        rax, [.emuedge_extend_right_2]
582     add         r1, rax
583 %else
584     lea         r1, [.emuedge_extend_right_2+r1]
585 %endif
586     call        r1
587 .h_extend_end:
588     RET
589
590 %if ARCH_X86_64
591 %define vall  al
592 %define valh  ah
593 %define valw  ax
594 %define valw2 r10w
595 %define valw3 r3w
596 %if WIN64
597 %define valw4 r4w
598 %else ; unix64
599 %define valw4 r3w
600 %endif
601 %define vald eax
602 %else
603 %define vall  bl
604 %define valh  bh
605 %define valw  bx
606 %define valw2 r6w
607 %define valw3 valw2
608 %define valw4 valw3
609 %define vald ebx
610 %define stack_offset 0x14
611 %endif
612
613 %endmacro
614
615 ; macro to read/write a horizontal number of pixels (%2) to/from registers
616 ; on x86-64, - fills xmm0-15 for consecutive sets of 16 pixels
617 ;            - if (%2 & 15 == 8) fills the last 8 bytes into rax
618 ;            - else if (%2 & 8)  fills 8 bytes into mm0
619 ;            - if (%2 & 7 == 4)  fills the last 4 bytes into rax
620 ;            - else if (%2 & 4)  fills 4 bytes into mm0-1
621 ;            - if (%2 & 3 == 3)  fills 2 bytes into r10/r3, and 1 into eax
622 ;              (note that we're using r3 for body/bottom because it's a shorter
623 ;               opcode, and then the loop fits in 128 bytes)
624 ;            - else              fills remaining bytes into rax
625 ; on x86-32, - fills mm0-7 for consecutive sets of 8 pixels
626 ;            - if (%2 & 7 == 4)  fills 4 bytes into ebx
627 ;            - else if (%2 & 4)  fills 4 bytes into mm0-7
628 ;            - if (%2 & 3 == 3)  fills 2 bytes into r6, and 1 into ebx
629 ;            - else              fills remaining bytes into ebx
630 ; writing data out is in the same way
631 %macro READ_NUM_BYTES 2
632 %assign %%src_off 0 ; offset in source buffer
633 %assign %%smidx   0 ; mmx register idx
634 %assign %%sxidx   0 ; xmm register idx
635
636 %if cpuflag(sse)
637 %rep %2/16
638     movups xmm %+ %%sxidx, [r1+%%src_off]
639 %assign %%src_off %%src_off+16
640 %assign %%sxidx   %%sxidx+1
641 %endrep ; %2/16
642 %endif
643
644 %if ARCH_X86_64
645 %if (%2-%%src_off) == 8
646     mov           rax, [r1+%%src_off]
647 %assign %%src_off %%src_off+8
648 %endif ; (%2-%%src_off) == 8
649 %endif ; x86-64
650
651 %rep (%2-%%src_off)/8
652     movq    mm %+ %%smidx, [r1+%%src_off]
653 %assign %%src_off %%src_off+8
654 %assign %%smidx   %%smidx+1
655 %endrep ; (%2-%%dst_off)/8
656
657 %if (%2-%%src_off) == 4
658     mov          vald, [r1+%%src_off]
659 %elif (%2-%%src_off) & 4
660     movd    mm %+ %%smidx, [r1+%%src_off]
661 %assign %%src_off %%src_off+4
662 %endif ; (%2-%%src_off) ==/& 4
663
664 %if (%2-%%src_off) == 1
665     mov          vall, [r1+%%src_off]
666 %elif (%2-%%src_off) == 2
667     mov          valw, [r1+%%src_off]
668 %elif (%2-%%src_off) == 3
669 %ifidn %1, top
670     mov         valw2, [r1+%%src_off]
671 %elifidn %1, body
672     mov         valw3, [r1+%%src_off]
673 %elifidn %1, bottom
674     mov         valw4, [r1+%%src_off]
675 %endif ; %1 ==/!= top
676     mov          vall, [r1+%%src_off+2]
677 %endif ; (%2-%%src_off) == 1/2/3
678 %endmacro ; READ_NUM_BYTES
679
680 %macro WRITE_NUM_BYTES 2
681 %assign %%dst_off 0 ; offset in destination buffer
682 %assign %%dmidx   0 ; mmx register idx
683 %assign %%dxidx   0 ; xmm register idx
684
685 %if cpuflag(sse)
686 %rep %2/16
687     movups [r0+%%dst_off], xmm %+ %%dxidx
688 %assign %%dst_off %%dst_off+16
689 %assign %%dxidx   %%dxidx+1
690 %endrep ; %2/16
691 %endif
692
693 %if ARCH_X86_64
694 %if (%2-%%dst_off) == 8
695     mov    [r0+%%dst_off], rax
696 %assign %%dst_off %%dst_off+8
697 %endif ; (%2-%%dst_off) == 8
698 %endif ; x86-64
699
700 %rep (%2-%%dst_off)/8
701     movq   [r0+%%dst_off], mm %+ %%dmidx
702 %assign %%dst_off %%dst_off+8
703 %assign %%dmidx   %%dmidx+1
704 %endrep ; (%2-%%dst_off)/8
705
706 %if (%2-%%dst_off) == 4
707     mov    [r0+%%dst_off], vald
708 %elif (%2-%%dst_off) & 4
709     movd   [r0+%%dst_off], mm %+ %%dmidx
710 %assign %%dst_off %%dst_off+4
711 %endif ; (%2-%%dst_off) ==/& 4
712
713 %if (%2-%%dst_off) == 1
714     mov    [r0+%%dst_off], vall
715 %elif (%2-%%dst_off) == 2
716     mov    [r0+%%dst_off], valw
717 %elif (%2-%%dst_off) == 3
718 %ifidn %1, top
719     mov    [r0+%%dst_off], valw2
720 %elifidn %1, body
721     mov    [r0+%%dst_off], valw3
722 %elifidn %1, bottom
723     mov    [r0+%%dst_off], valw4
724 %endif ; %1 ==/!= top
725     mov  [r0+%%dst_off+2], vall
726 %endif ; (%2-%%dst_off) == 1/2/3
727 %endmacro ; WRITE_NUM_BYTES
728
729 ; vertical top/bottom extend and body copy fast loops
730 ; these are function pointers to set-width line copy functions, i.e.
731 ; they read a fixed number of pixels into set registers, and write
732 ; those out into the destination buffer
733 ; r0=buf,r1=src,r2=linesize,r3(64)/r3m(32)=start_x,r4=end_y,r5=block_h
734 ; r6(eax/64)/r3(ebx/32)=val_reg
735 %macro VERTICAL_EXTEND 0
736 %assign %%n 1
737 %rep 22
738 ALIGN 128
739 .emuedge_v_extend_ %+ %%n:
740     ; extend pixels above body
741 %if ARCH_X86_64
742     test           r3 , r3                   ; if (!start_y)
743     jz .emuedge_copy_body_ %+ %%n %+ _loop   ;   goto body
744 %else ; ARCH_X86_32
745     cmp      dword r3m, 0
746     je .emuedge_copy_body_ %+ %%n %+ _loop
747 %endif ; ARCH_X86_64/32
748     READ_NUM_BYTES  top,    %%n              ; read bytes
749 .emuedge_extend_top_ %+ %%n %+ _loop:        ; do {
750     WRITE_NUM_BYTES top,    %%n              ;   write bytes
751     add            r0 , r2                   ;   dst += linesize
752 %if ARCH_X86_64
753     dec            r3d
754 %else ; ARCH_X86_32
755     dec      dword r3m
756 %endif ; ARCH_X86_64/32
757     jnz .emuedge_extend_top_ %+ %%n %+ _loop ; } while (--start_y)
758
759     ; copy body pixels
760 .emuedge_copy_body_ %+ %%n %+ _loop:         ; do {
761     READ_NUM_BYTES  body,   %%n              ;   read bytes
762     WRITE_NUM_BYTES body,   %%n              ;   write bytes
763     add            r0 , r2                   ;   dst += linesize
764     add            r1 , r2                   ;   src += linesize
765     dec            r4d
766     jnz .emuedge_copy_body_ %+ %%n %+ _loop  ; } while (--end_y)
767
768     ; copy bottom pixels
769     test           r5 , r5                   ; if (!block_h)
770     jz .emuedge_v_extend_end_ %+ %%n         ;   goto end
771     sub            r1 , r2                   ; src -= linesize
772     READ_NUM_BYTES  bottom, %%n              ; read bytes
773 .emuedge_extend_bottom_ %+ %%n %+ _loop:     ; do {
774     WRITE_NUM_BYTES bottom, %%n              ;   write bytes
775     add            r0 , r2                   ;   dst += linesize
776     dec            r5d
777     jnz .emuedge_extend_bottom_ %+ %%n %+ _loop ; } while (--block_h)
778
779 .emuedge_v_extend_end_ %+ %%n:
780 %if ARCH_X86_64
781     ret
782 %else ; ARCH_X86_32
783     rep ret
784 %endif ; ARCH_X86_64/32
785 %assign %%n %%n+1
786 %endrep
787 %endmacro VERTICAL_EXTEND
788
789 ; left/right (horizontal) fast extend functions
790 ; these are essentially identical to the vertical extend ones above,
791 ; just left/right separated because number of pixels to extend is
792 ; obviously not the same on both sides.
793 ; for reading, pixels are placed in eax (x86-64) or ebx (x86-64) in the
794 ; lowest two bytes of the register (so val*0x0101), and are splatted
795 ; into each byte of mm0 as well if n_pixels >= 8
796
797 %macro READ_V_PIXEL 2
798     mov        vall, %2
799     mov        valh, vall
800 %if %1 >= 8
801     movd        mm0, vald
802 %if cpuflag(mmx2)
803     pshufw      mm0, mm0, 0
804 %else ; mmx
805     punpcklwd   mm0, mm0
806     punpckldq   mm0, mm0
807 %endif ; sse
808 %endif ; %1 >= 8
809 %endmacro
810
811 %macro WRITE_V_PIXEL 2
812 %assign %%dst_off 0
813 %rep %1/8
814     movq [%2+%%dst_off], mm0
815 %assign %%dst_off %%dst_off+8
816 %endrep
817 %if %1 & 4
818 %if %1 >= 8
819     movd [%2+%%dst_off], mm0
820 %else ; %1 < 8
821     mov  [%2+%%dst_off]  , valw
822     mov  [%2+%%dst_off+2], valw
823 %endif ; %1 >=/< 8
824 %assign %%dst_off %%dst_off+4
825 %endif ; %1 & 4
826 %if %1&2
827     mov  [%2+%%dst_off], valw
828 %endif ; %1 & 2
829 %endmacro
830
831 ; r0=buf+block_h*linesize, r1=start_x, r2=linesize, r5=block_h, r6/r3=val
832 %macro LEFT_EXTEND 0
833 %assign %%n 2
834 %rep 11
835 ALIGN 64
836 .emuedge_extend_left_ %+ %%n:          ; do {
837     sub         r0, r2                 ;   dst -= linesize
838     READ_V_PIXEL  %%n, [r0+r1]         ;   read pixels
839     WRITE_V_PIXEL %%n, r0              ;   write pixels
840     dec         r5
841     jnz .emuedge_extend_left_ %+ %%n   ; } while (--block_h)
842 %if ARCH_X86_64
843     ret
844 %else ; ARCH_X86_32
845     rep ret
846 %endif ; ARCH_X86_64/32
847 %assign %%n %%n+2
848 %endrep
849 %endmacro ; LEFT_EXTEND
850
851 ; r3/r0=buf+block_h*linesize, r2=linesize, r11/r5=block_h, r0/r6=end_x, r6/r3=val
852 %macro RIGHT_EXTEND 0
853 %assign %%n 2
854 %rep 11
855 ALIGN 64
856 .emuedge_extend_right_ %+ %%n:          ; do {
857 %if ARCH_X86_64
858     sub        r3, r2                   ;   dst -= linesize
859     READ_V_PIXEL  %%n, [r3+w_reg-1]     ;   read pixels
860     WRITE_V_PIXEL %%n, r3+r4-%%n        ;   write pixels
861     dec       r11
862 %else ; ARCH_X86_32
863     sub        r0, r2                   ;   dst -= linesize
864     READ_V_PIXEL  %%n, [r0+w_reg-1]     ;   read pixels
865     WRITE_V_PIXEL %%n, r0+r4-%%n        ;   write pixels
866     dec     r5
867 %endif ; ARCH_X86_64/32
868     jnz .emuedge_extend_right_ %+ %%n   ; } while (--block_h)
869 %if ARCH_X86_64
870     ret
871 %else ; ARCH_X86_32
872     rep ret
873 %endif ; ARCH_X86_64/32
874 %assign %%n %%n+2
875 %endrep
876
877 %if ARCH_X86_32
878 %define stack_offset 0x10
879 %endif
880 %endmacro ; RIGHT_EXTEND
881
882 ; below follow the "slow" copy/extend functions, these act on a non-fixed
883 ; width specified in a register, and run a loop to copy the full amount
884 ; of bytes. They are optimized for copying of large amounts of pixels per
885 ; line, so they unconditionally splat data into mm registers to copy 8
886 ; bytes per loop iteration. It could be considered to use xmm for x86-64
887 ; also, but I haven't optimized this as much (i.e. FIXME)
888 %macro V_COPY_NPX 4-5
889 %if %0 == 4
890     test     w_reg, %4
891     jz .%1_skip_%4_px
892 %else ; %0 == 5
893 .%1_%4_px_loop:
894 %endif
895     %3          %2, [r1+cnt_reg]
896     %3 [r0+cnt_reg], %2
897     add    cnt_reg, %4
898 %if %0 == 5
899     sub      w_reg, %4
900     test     w_reg, %5
901     jnz .%1_%4_px_loop
902 %endif
903 .%1_skip_%4_px:
904 %endmacro
905
906 %macro V_COPY_ROW 2
907 %ifidn %1, bottom
908     sub         r1, linesize
909 %endif
910 .%1_copy_loop:
911     xor    cnt_reg, cnt_reg
912 %if notcpuflag(sse)
913 %define linesize r2m
914     V_COPY_NPX %1,  mm0, movq,    8, 0xFFFFFFF8
915 %else ; sse
916     V_COPY_NPX %1, xmm0, movups, 16, 0xFFFFFFF0
917 %if ARCH_X86_64
918 %define linesize r2
919     V_COPY_NPX %1, rax , mov,     8
920 %else ; ARCH_X86_32
921 %define linesize r2m
922     V_COPY_NPX %1,  mm0, movq,    8
923 %endif ; ARCH_X86_64/32
924 %endif ; sse
925     V_COPY_NPX %1, vald, mov,     4
926     V_COPY_NPX %1, valw, mov,     2
927     V_COPY_NPX %1, vall, mov,     1
928     mov      w_reg, cnt_reg
929 %ifidn %1, body
930     add         r1, linesize
931 %endif
932     add         r0, linesize
933     dec         %2
934     jnz .%1_copy_loop
935 %endmacro
936
937 %macro SLOW_V_EXTEND 0
938 .slow_v_extend_loop:
939 ; r0=buf,r1=src,r2(64)/r2m(32)=linesize,r3(64)/r3m(32)=start_x,r4=end_y,r5=block_h
940 ; r11(64)/r3(later-64)/r2(32)=cnt_reg,r6(64)/r3(32)=val_reg,r10(64)/r6(32)=w=end_x-start_x
941 %if ARCH_X86_64
942     push       r11              ; save old value of block_h
943     test        r3, r3
944 %define cnt_reg r11
945     jz .do_body_copy            ; if (!start_y) goto do_body_copy
946     V_COPY_ROW top, r3
947 %else
948     cmp  dword r3m, 0
949 %define cnt_reg r2
950     je .do_body_copy            ; if (!start_y) goto do_body_copy
951     V_COPY_ROW top, dword r3m
952 %endif
953
954 .do_body_copy:
955     V_COPY_ROW body, r4
956
957 %if ARCH_X86_64
958     pop        r11              ; restore old value of block_h
959 %define cnt_reg r3
960 %endif
961     test        r5, r5
962 %if ARCH_X86_64
963     jz .v_extend_end
964 %else
965     jz .skip_bottom_extend
966 %endif
967     V_COPY_ROW bottom, r5
968 %if ARCH_X86_32
969 .skip_bottom_extend:
970     mov         r2, r2m
971 %endif
972     jmp .v_extend_end
973 %endmacro
974
975 %macro SLOW_LEFT_EXTEND 0
976 .slow_left_extend_loop:
977 ; r0=buf+block_h*linesize,r2=linesize,r6(64)/r3(32)=val,r5=block_h,r4=cntr,r10/r6=start_x
978     mov         r4, 8
979     sub         r0, linesize
980     READ_V_PIXEL 8, [r0+w_reg]
981 .left_extend_8px_loop:
982     movq [r0+r4-8], mm0
983     add         r4, 8
984     cmp         r4, w_reg
985     jle .left_extend_8px_loop
986     sub         r4, 8
987     cmp         r4, w_reg
988     jge .left_extend_loop_end
989 .left_extend_2px_loop:
990     mov    [r0+r4], valw
991     add         r4, 2
992     cmp         r4, w_reg
993     jl .left_extend_2px_loop
994 .left_extend_loop_end:
995     dec         r5
996     jnz .slow_left_extend_loop
997 %if ARCH_X86_32
998     mov         r2, r2m
999 %endif
1000     jmp .right_extend
1001 %endmacro
1002
1003 %macro SLOW_RIGHT_EXTEND 0
1004 .slow_right_extend_loop:
1005 ; r3(64)/r0(32)=buf+block_h*linesize,r2=linesize,r4=block_w,r11(64)/r5(32)=block_h,
1006 ; r10(64)/r6(32)=end_x,r6/r3=val,r1=cntr
1007 %if ARCH_X86_64
1008 %define buf_reg r3
1009 %define bh_reg r11
1010 %else
1011 %define buf_reg r0
1012 %define bh_reg r5
1013 %endif
1014     lea         r1, [r4-8]
1015     sub    buf_reg, linesize
1016     READ_V_PIXEL 8, [buf_reg+w_reg-1]
1017 .right_extend_8px_loop:
1018     movq [buf_reg+r1], mm0
1019     sub         r1, 8
1020     cmp         r1, w_reg
1021     jge .right_extend_8px_loop
1022     add         r1, 8
1023     cmp         r1, w_reg
1024     je .right_extend_loop_end
1025 .right_extend_2px_loop:
1026     sub         r1, 2
1027     mov [buf_reg+r1], valw
1028     cmp         r1, w_reg
1029     jg .right_extend_2px_loop
1030 .right_extend_loop_end:
1031     dec         bh_reg
1032     jnz .slow_right_extend_loop
1033     jmp .h_extend_end
1034 %endmacro
1035
1036 %macro emu_edge 1
1037 INIT_XMM %1
1038 EMU_EDGE_FUNC
1039 VERTICAL_EXTEND
1040 LEFT_EXTEND
1041 RIGHT_EXTEND
1042 SLOW_V_EXTEND
1043 SLOW_LEFT_EXTEND
1044 SLOW_RIGHT_EXTEND
1045 %endmacro
1046
1047 emu_edge sse
1048 %if ARCH_X86_32
1049 emu_edge mmx
1050 %endif
1051
1052 ;-----------------------------------------------------------------------------
1053 ; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min,
1054 ;                           int32_t max, unsigned int len)
1055 ;-----------------------------------------------------------------------------
1056
1057 ; %1 = number of xmm registers used
1058 ; %2 = number of inline load/process/store loops per asm loop
1059 ; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop
1060 ; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2)
1061 ; %5 = suffix
1062 %macro VECTOR_CLIP_INT32 4-5
1063 cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len
1064 %if %4
1065     cvtsi2ss  m4, minm
1066     cvtsi2ss  m5, maxm
1067 %else
1068     movd      m4, minm
1069     movd      m5, maxm
1070 %endif
1071     SPLATD    m4
1072     SPLATD    m5
1073 .loop:
1074 %assign %%i 1
1075 %rep %2
1076     mova      m0,  [srcq+mmsize*0*%%i]
1077     mova      m1,  [srcq+mmsize*1*%%i]
1078     mova      m2,  [srcq+mmsize*2*%%i]
1079     mova      m3,  [srcq+mmsize*3*%%i]
1080 %if %3
1081     mova      m7,  [srcq+mmsize*4*%%i]
1082     mova      m8,  [srcq+mmsize*5*%%i]
1083     mova      m9,  [srcq+mmsize*6*%%i]
1084     mova      m10, [srcq+mmsize*7*%%i]
1085 %endif
1086     CLIPD  m0,  m4, m5, m6
1087     CLIPD  m1,  m4, m5, m6
1088     CLIPD  m2,  m4, m5, m6
1089     CLIPD  m3,  m4, m5, m6
1090 %if %3
1091     CLIPD  m7,  m4, m5, m6
1092     CLIPD  m8,  m4, m5, m6
1093     CLIPD  m9,  m4, m5, m6
1094     CLIPD  m10, m4, m5, m6
1095 %endif
1096     mova  [dstq+mmsize*0*%%i], m0
1097     mova  [dstq+mmsize*1*%%i], m1
1098     mova  [dstq+mmsize*2*%%i], m2
1099     mova  [dstq+mmsize*3*%%i], m3
1100 %if %3
1101     mova  [dstq+mmsize*4*%%i], m7
1102     mova  [dstq+mmsize*5*%%i], m8
1103     mova  [dstq+mmsize*6*%%i], m9
1104     mova  [dstq+mmsize*7*%%i], m10
1105 %endif
1106 %assign %%i %%i+1
1107 %endrep
1108     add     srcq, mmsize*4*(%2+%3)
1109     add     dstq, mmsize*4*(%2+%3)
1110     sub     lend, mmsize*(%2+%3)
1111     jg .loop
1112     REP_RET
1113 %endmacro
1114
1115 INIT_MMX mmx
1116 %define SPLATD SPLATD_MMX
1117 %define CLIPD CLIPD_MMX
1118 VECTOR_CLIP_INT32 0, 1, 0, 0
1119 INIT_XMM sse2
1120 %define SPLATD SPLATD_SSE2
1121 VECTOR_CLIP_INT32 6, 1, 0, 0, _int
1122 %define CLIPD CLIPD_SSE2
1123 VECTOR_CLIP_INT32 6, 2, 0, 1
1124 INIT_XMM sse4
1125 %define CLIPD CLIPD_SSE41
1126 %ifdef m8
1127 VECTOR_CLIP_INT32 11, 1, 1, 0
1128 %else
1129 VECTOR_CLIP_INT32 6, 1, 0, 0
1130 %endif
1131
1132 ;-----------------------------------------------------------------------------
1133 ; void ff_butterflies_float_interleave(float *dst, const float *src0,
1134 ;                                      const float *src1, int len);
1135 ;-----------------------------------------------------------------------------
1136
1137 %macro BUTTERFLIES_FLOAT_INTERLEAVE 0
1138 cglobal butterflies_float_interleave, 4,4,3, dst, src0, src1, len
1139 %if ARCH_X86_64
1140     movsxd    lenq, lend
1141 %endif
1142     test      lenq, lenq
1143     jz .end
1144     shl       lenq, 2
1145     lea      src0q, [src0q +   lenq]
1146     lea      src1q, [src1q +   lenq]
1147     lea       dstq, [ dstq + 2*lenq]
1148     neg       lenq
1149 .loop:
1150     mova        m0, [src0q + lenq]
1151     mova        m1, [src1q + lenq]
1152     subps       m2, m0, m1
1153     addps       m0, m0, m1
1154     unpcklps    m1, m0, m2
1155     unpckhps    m0, m0, m2
1156 %if cpuflag(avx)
1157     vextractf128 [dstq + 2*lenq     ], m1, 0
1158     vextractf128 [dstq + 2*lenq + 16], m0, 0
1159     vextractf128 [dstq + 2*lenq + 32], m1, 1
1160     vextractf128 [dstq + 2*lenq + 48], m0, 1
1161 %else
1162     mova [dstq + 2*lenq         ], m1
1163     mova [dstq + 2*lenq + mmsize], m0
1164 %endif
1165     add       lenq, mmsize
1166     jl .loop
1167 %if mmsize == 32
1168     vzeroupper
1169     RET
1170 %endif
1171 .end:
1172     REP_RET
1173 %endmacro
1174
1175 INIT_XMM sse
1176 BUTTERFLIES_FLOAT_INTERLEAVE
1177 %if HAVE_AVX
1178 INIT_YMM avx
1179 BUTTERFLIES_FLOAT_INTERLEAVE
1180 %endif
1181
1182 INIT_XMM sse2
1183 ; %1 = aligned/unaligned
1184 %macro BSWAP_LOOPS_SSE2  1
1185     mov      r3, r2
1186     sar      r2, 3
1187     jz       .left4_%1
1188 .loop8_%1:
1189     mov%1    m0, [r1 +  0]
1190     mov%1    m1, [r1 + 16]
1191     pshuflw  m0, m0, 10110001b
1192     pshuflw  m1, m1, 10110001b
1193     pshufhw  m0, m0, 10110001b
1194     pshufhw  m1, m1, 10110001b
1195     mova     m2, m0
1196     mova     m3, m1
1197     psllw    m0, 8
1198     psllw    m1, 8
1199     psrlw    m2, 8
1200     psrlw    m3, 8
1201     por      m2, m0
1202     por      m3, m1
1203     mova     [r0 +  0], m2
1204     mova     [r0 + 16], m3
1205     add      r1, 32
1206     add      r0, 32
1207     dec      r2
1208     jnz      .loop8_%1
1209 .left4_%1:
1210     mov      r2, r3
1211     and      r3, 4
1212     jz       .left
1213     mov%1    m0, [r1]
1214     pshuflw  m0, m0, 10110001b
1215     pshufhw  m0, m0, 10110001b
1216     mova     m2, m0
1217     psllw    m0, 8
1218     psrlw    m2, 8
1219     por      m2, m0
1220     mova     [r0], m2
1221     add      r1, 16
1222     add      r0, 16
1223 %endmacro
1224
1225 ; void bswap_buf(uint32_t *dst, const uint32_t *src, int w);
1226 cglobal bswap32_buf, 3,4,5
1227     mov      r3, r1
1228     and      r3, 15
1229     jz       .start_align
1230     BSWAP_LOOPS_SSE2  u
1231     jmp      .left
1232 .start_align:
1233     BSWAP_LOOPS_SSE2  a
1234 .left:
1235     and      r2, 3
1236     jz       .end
1237 .loop2:
1238     mov      r3d, [r1]
1239     bswap    r3d
1240     mov      [r0], r3d
1241     add      r1, 4
1242     add      r0, 4
1243     dec      r2
1244     jnz      .loop2
1245 .end
1246     RET
1247
1248 ; %1 = aligned/unaligned
1249 %macro BSWAP_LOOPS_SSSE3  1
1250     mov      r3, r2
1251     sar      r2, 3
1252     jz       .left4_%1
1253 .loop8_%1:
1254     mov%1    m0, [r1 +  0]
1255     mov%1    m1, [r1 + 16]
1256     pshufb   m0, m2
1257     pshufb   m1, m2
1258     mova     [r0 +  0], m0
1259     mova     [r0 + 16], m1
1260     add      r0, 32
1261     add      r1, 32
1262     dec      r2
1263     jnz      .loop8_%1
1264 .left4_%1:
1265     mov      r2, r3
1266     and      r3, 4
1267     jz       .left2
1268     mov%1    m0, [r1]
1269     pshufb   m0, m2
1270     mova     [r0], m0
1271     add      r1, 16
1272     add      r0, 16
1273 %endmacro
1274
1275 INIT_XMM ssse3
1276 ; void bswap_buf(uint32_t *dst, const uint32_t *src, int w);
1277 cglobal bswap32_buf, 3,4,3
1278     mov      r3, r1
1279     mova     m2, [pb_bswap32]
1280     and      r3, 15
1281     jz       .start_align
1282     BSWAP_LOOPS_SSSE3  u
1283     jmp      .left2
1284 .start_align:
1285     BSWAP_LOOPS_SSSE3  a
1286 .left2:
1287     mov      r3, r2
1288     and      r2, 2
1289     jz       .left1
1290     movq     m0, [r1]
1291     pshufb   m0, m2
1292     movq     [r0], m0
1293     add      r1, 8
1294     add      r0, 8
1295 .left1:
1296     and      r3, 1
1297     jz       .end
1298     mov      r2d, [r1]
1299     bswap    r2d
1300     mov      [r0], r2d
1301 .end:
1302     RET
1303