]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/dsputil.asm
lavf: move ff_codec_get_tag() and ff_codec_get_id() definitions to internal.h
[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 ; extern void ff_emu_edge_core(uint8_t *buf, const uint8_t *src, x86_reg linesize,
493 ;                              x86_reg start_y, x86_reg end_y, x86_reg block_h,
494 ;                              x86_reg start_x, x86_reg end_x, x86_reg block_w);
495 ;
496 ; The actual function itself is below. It basically wraps a very simple
497 ; w = end_x - start_x
498 ; if (w) {
499 ;   if (w > 22) {
500 ;     jump to the slow loop functions
501 ;   } else {
502 ;     jump to the fast loop functions
503 ;   }
504 ; }
505 ;
506 ; ... and then the same for left/right extend also. See below for loop
507 ; function implementations. Fast are fixed-width, slow is variable-width
508
509 %macro EMU_EDGE_FUNC 0
510 %if ARCH_X86_64
511 %define w_reg r7
512 cglobal emu_edge_core, 6, 9, 1
513     mov         r8, r5          ; save block_h
514 %else
515 %define w_reg r6
516 cglobal emu_edge_core, 2, 7, 0
517     mov         r4, r4m         ; end_y
518     mov         r5, r5m         ; block_h
519 %endif
520
521     ; start with vertical extend (top/bottom) and body pixel copy
522     mov      w_reg, r7m
523     sub      w_reg, r6m         ; w = start_x - end_x
524     sub         r5, r4
525 %if ARCH_X86_64
526     sub         r4, r3
527 %else
528     sub         r4, dword r3m
529 %endif
530     cmp      w_reg, 22
531     jg .slow_v_extend_loop
532 %if ARCH_X86_32
533     mov         r2, r2m         ; linesize
534 %endif
535     sal      w_reg, 7           ; w * 128
536 %ifdef PIC
537     lea        rax, [.emuedge_v_extend_1 - (.emuedge_v_extend_2 - .emuedge_v_extend_1)]
538     add      w_reg, rax
539 %else
540     lea      w_reg, [.emuedge_v_extend_1 - (.emuedge_v_extend_2 - .emuedge_v_extend_1)+w_reg]
541 %endif
542     call     w_reg              ; fast top extend, body copy and bottom extend
543 .v_extend_end:
544
545     ; horizontal extend (left/right)
546     mov      w_reg, r6m         ; start_x
547     sub         r0, w_reg
548 %if ARCH_X86_64
549     mov         r3, r0          ; backup of buf+block_h*linesize
550     mov         r5, r8
551 %else
552     mov        r0m, r0          ; backup of buf+block_h*linesize
553     mov         r5, r5m
554 %endif
555     test     w_reg, w_reg
556     jz .right_extend
557     cmp      w_reg, 22
558     jg .slow_left_extend_loop
559     mov         r1, w_reg
560     dec      w_reg
561     ; FIXME we can do a if size == 1 here if that makes any speed difference, test me
562     sar      w_reg, 1
563     sal      w_reg, 6
564     ; r0=buf+block_h*linesize,r7(64)/r6(32)=start_x offset for funcs
565     ; r6(rax)/r3(ebx)=val,r2=linesize,r1=start_x,r5=block_h
566 %ifdef PIC
567     lea        rax, [.emuedge_extend_left_2]
568     add      w_reg, rax
569 %else
570     lea      w_reg, [.emuedge_extend_left_2+w_reg]
571 %endif
572     call     w_reg
573
574     ; now r3(64)/r0(32)=buf,r2=linesize,r8/r5=block_h,r6/r3=val, r7/r6=end_x, r1=block_w
575 .right_extend:
576 %if ARCH_X86_32
577     mov         r0, r0m
578     mov         r5, r5m
579 %endif
580     mov      w_reg, r7m         ; end_x
581     mov         r1, r8m         ; block_w
582     mov         r4, r1
583     sub         r1, w_reg
584     jz .h_extend_end            ; if (end_x == block_w) goto h_extend_end
585     cmp         r1, 22
586     jg .slow_right_extend_loop
587     dec         r1
588     ; FIXME we can do a if size == 1 here if that makes any speed difference, test me
589     sar         r1, 1
590     sal         r1, 6
591 %ifdef PIC
592     lea        rax, [.emuedge_extend_right_2]
593     add         r1, rax
594 %else
595     lea         r1, [.emuedge_extend_right_2+r1]
596 %endif
597     call        r1
598 .h_extend_end:
599     RET
600
601 %if ARCH_X86_64
602 %define vall  al
603 %define valh  ah
604 %define valw  ax
605 %define valw2 r7w
606 %define valw3 r3w
607 %if WIN64
608 %define valw4 r7w
609 %else ; unix64
610 %define valw4 r3w
611 %endif
612 %define vald eax
613 %else
614 %define vall  bl
615 %define valh  bh
616 %define valw  bx
617 %define valw2 r6w
618 %define valw3 valw2
619 %define valw4 valw3
620 %define vald ebx
621 %define stack_offset 0x14
622 %endif
623
624 %endmacro
625
626 ; macro to read/write a horizontal number of pixels (%2) to/from registers
627 ; on x86-64, - fills xmm0-15 for consecutive sets of 16 pixels
628 ;            - if (%2 & 15 == 8) fills the last 8 bytes into rax
629 ;            - else if (%2 & 8)  fills 8 bytes into mm0
630 ;            - if (%2 & 7 == 4)  fills the last 4 bytes into rax
631 ;            - else if (%2 & 4)  fills 4 bytes into mm0-1
632 ;            - if (%2 & 3 == 3)  fills 2 bytes into r7/r3, and 1 into eax
633 ;              (note that we're using r3 for body/bottom because it's a shorter
634 ;               opcode, and then the loop fits in 128 bytes)
635 ;            - else              fills remaining bytes into rax
636 ; on x86-32, - fills mm0-7 for consecutive sets of 8 pixels
637 ;            - if (%2 & 7 == 4)  fills 4 bytes into ebx
638 ;            - else if (%2 & 4)  fills 4 bytes into mm0-7
639 ;            - if (%2 & 3 == 3)  fills 2 bytes into r6, and 1 into ebx
640 ;            - else              fills remaining bytes into ebx
641 ; writing data out is in the same way
642 %macro READ_NUM_BYTES 2
643 %assign %%src_off 0 ; offset in source buffer
644 %assign %%smidx   0 ; mmx register idx
645 %assign %%sxidx   0 ; xmm register idx
646
647 %if cpuflag(sse)
648 %rep %2/16
649     movups xmm %+ %%sxidx, [r1+%%src_off]
650 %assign %%src_off %%src_off+16
651 %assign %%sxidx   %%sxidx+1
652 %endrep ; %2/16
653 %endif
654
655 %if ARCH_X86_64
656 %if (%2-%%src_off) == 8
657     mov           rax, [r1+%%src_off]
658 %assign %%src_off %%src_off+8
659 %endif ; (%2-%%src_off) == 8
660 %endif ; x86-64
661
662 %rep (%2-%%src_off)/8
663     movq    mm %+ %%smidx, [r1+%%src_off]
664 %assign %%src_off %%src_off+8
665 %assign %%smidx   %%smidx+1
666 %endrep ; (%2-%%dst_off)/8
667
668 %if (%2-%%src_off) == 4
669     mov          vald, [r1+%%src_off]
670 %elif (%2-%%src_off) & 4
671     movd    mm %+ %%smidx, [r1+%%src_off]
672 %assign %%src_off %%src_off+4
673 %endif ; (%2-%%src_off) ==/& 4
674
675 %if (%2-%%src_off) == 1
676     mov          vall, [r1+%%src_off]
677 %elif (%2-%%src_off) == 2
678     mov          valw, [r1+%%src_off]
679 %elif (%2-%%src_off) == 3
680 %ifidn %1, top
681     mov         valw2, [r1+%%src_off]
682 %elifidn %1, body
683     mov         valw3, [r1+%%src_off]
684 %elifidn %1, bottom
685     mov         valw4, [r1+%%src_off]
686 %endif ; %1 ==/!= top
687     mov          vall, [r1+%%src_off+2]
688 %endif ; (%2-%%src_off) == 1/2/3
689 %endmacro ; READ_NUM_BYTES
690
691 %macro WRITE_NUM_BYTES 2
692 %assign %%dst_off 0 ; offset in destination buffer
693 %assign %%dmidx   0 ; mmx register idx
694 %assign %%dxidx   0 ; xmm register idx
695
696 %if cpuflag(sse)
697 %rep %2/16
698     movups [r0+%%dst_off], xmm %+ %%dxidx
699 %assign %%dst_off %%dst_off+16
700 %assign %%dxidx   %%dxidx+1
701 %endrep ; %2/16
702 %endif
703
704 %if ARCH_X86_64
705 %if (%2-%%dst_off) == 8
706     mov    [r0+%%dst_off], rax
707 %assign %%dst_off %%dst_off+8
708 %endif ; (%2-%%dst_off) == 8
709 %endif ; x86-64
710
711 %rep (%2-%%dst_off)/8
712     movq   [r0+%%dst_off], mm %+ %%dmidx
713 %assign %%dst_off %%dst_off+8
714 %assign %%dmidx   %%dmidx+1
715 %endrep ; (%2-%%dst_off)/8
716
717 %if (%2-%%dst_off) == 4
718     mov    [r0+%%dst_off], vald
719 %elif (%2-%%dst_off) & 4
720     movd   [r0+%%dst_off], mm %+ %%dmidx
721 %assign %%dst_off %%dst_off+4
722 %endif ; (%2-%%dst_off) ==/& 4
723
724 %if (%2-%%dst_off) == 1
725     mov    [r0+%%dst_off], vall
726 %elif (%2-%%dst_off) == 2
727     mov    [r0+%%dst_off], valw
728 %elif (%2-%%dst_off) == 3
729 %ifidn %1, top
730     mov    [r0+%%dst_off], valw2
731 %elifidn %1, body
732     mov    [r0+%%dst_off], valw3
733 %elifidn %1, bottom
734     mov    [r0+%%dst_off], valw4
735 %endif ; %1 ==/!= top
736     mov  [r0+%%dst_off+2], vall
737 %endif ; (%2-%%dst_off) == 1/2/3
738 %endmacro ; WRITE_NUM_BYTES
739
740 ; vertical top/bottom extend and body copy fast loops
741 ; these are function pointers to set-width line copy functions, i.e.
742 ; they read a fixed number of pixels into set registers, and write
743 ; those out into the destination buffer
744 ; r0=buf,r1=src,r2=linesize,r3(64)/r3m(32)=start_x,r4=end_y,r5=block_h
745 ; r6(eax/64)/r3(ebx/32)=val_reg
746 %macro VERTICAL_EXTEND 0
747 %assign %%n 1
748 %rep 22
749 ALIGN 128
750 .emuedge_v_extend_ %+ %%n:
751     ; extend pixels above body
752 %if ARCH_X86_64
753     test           r3 , r3                   ; if (!start_y)
754     jz .emuedge_copy_body_ %+ %%n %+ _loop   ;   goto body
755 %else ; ARCH_X86_32
756     cmp      dword r3m, 0
757     je .emuedge_copy_body_ %+ %%n %+ _loop
758 %endif ; ARCH_X86_64/32
759     READ_NUM_BYTES  top,    %%n              ; read bytes
760 .emuedge_extend_top_ %+ %%n %+ _loop:        ; do {
761     WRITE_NUM_BYTES top,    %%n              ;   write bytes
762     add            r0 , r2                   ;   dst += linesize
763 %if ARCH_X86_64
764     dec            r3d
765 %else ; ARCH_X86_32
766     dec      dword r3m
767 %endif ; ARCH_X86_64/32
768     jnz .emuedge_extend_top_ %+ %%n %+ _loop ; } while (--start_y)
769
770     ; copy body pixels
771 .emuedge_copy_body_ %+ %%n %+ _loop:         ; do {
772     READ_NUM_BYTES  body,   %%n              ;   read bytes
773     WRITE_NUM_BYTES body,   %%n              ;   write bytes
774     add            r0 , r2                   ;   dst += linesize
775     add            r1 , r2                   ;   src += linesize
776     dec            r4d
777     jnz .emuedge_copy_body_ %+ %%n %+ _loop  ; } while (--end_y)
778
779     ; copy bottom pixels
780     test           r5 , r5                   ; if (!block_h)
781     jz .emuedge_v_extend_end_ %+ %%n         ;   goto end
782     sub            r1 , r2                   ; src -= linesize
783     READ_NUM_BYTES  bottom, %%n              ; read bytes
784 .emuedge_extend_bottom_ %+ %%n %+ _loop:     ; do {
785     WRITE_NUM_BYTES bottom, %%n              ;   write bytes
786     add            r0 , r2                   ;   dst += linesize
787     dec            r5d
788     jnz .emuedge_extend_bottom_ %+ %%n %+ _loop ; } while (--block_h)
789
790 .emuedge_v_extend_end_ %+ %%n:
791 %if ARCH_X86_64
792     ret
793 %else ; ARCH_X86_32
794     rep ret
795 %endif ; ARCH_X86_64/32
796 %assign %%n %%n+1
797 %endrep
798 %endmacro VERTICAL_EXTEND
799
800 ; left/right (horizontal) fast extend functions
801 ; these are essentially identical to the vertical extend ones above,
802 ; just left/right separated because number of pixels to extend is
803 ; obviously not the same on both sides.
804 ; for reading, pixels are placed in eax (x86-64) or ebx (x86-64) in the
805 ; lowest two bytes of the register (so val*0x0101), and are splatted
806 ; into each byte of mm0 as well if n_pixels >= 8
807
808 %macro READ_V_PIXEL 2
809     mov        vall, %2
810     mov        valh, vall
811 %if %1 >= 8
812     movd        mm0, vald
813 %if cpuflag(mmxext)
814     pshufw      mm0, mm0, 0
815 %else ; mmx
816     punpcklwd   mm0, mm0
817     punpckldq   mm0, mm0
818 %endif ; sse
819 %endif ; %1 >= 8
820 %endmacro
821
822 %macro WRITE_V_PIXEL 2
823 %assign %%dst_off 0
824 %rep %1/8
825     movq [%2+%%dst_off], mm0
826 %assign %%dst_off %%dst_off+8
827 %endrep
828 %if %1 & 4
829 %if %1 >= 8
830     movd [%2+%%dst_off], mm0
831 %else ; %1 < 8
832     mov  [%2+%%dst_off]  , valw
833     mov  [%2+%%dst_off+2], valw
834 %endif ; %1 >=/< 8
835 %assign %%dst_off %%dst_off+4
836 %endif ; %1 & 4
837 %if %1&2
838     mov  [%2+%%dst_off], valw
839 %endif ; %1 & 2
840 %endmacro
841
842 ; r0=buf+block_h*linesize, r1=start_x, r2=linesize, r5=block_h, r6/r3=val
843 %macro LEFT_EXTEND 0
844 %assign %%n 2
845 %rep 11
846 ALIGN 64
847 .emuedge_extend_left_ %+ %%n:          ; do {
848     sub         r0, r2                 ;   dst -= linesize
849     READ_V_PIXEL  %%n, [r0+r1]         ;   read pixels
850     WRITE_V_PIXEL %%n, r0              ;   write pixels
851     dec         r5
852     jnz .emuedge_extend_left_ %+ %%n   ; } while (--block_h)
853 %if ARCH_X86_64
854     ret
855 %else ; ARCH_X86_32
856     rep ret
857 %endif ; ARCH_X86_64/32
858 %assign %%n %%n+2
859 %endrep
860 %endmacro ; LEFT_EXTEND
861
862 ; r3/r0=buf+block_h*linesize, r2=linesize, r8/r5=block_h, r0/r6=end_x, r6/r3=val
863 %macro RIGHT_EXTEND 0
864 %assign %%n 2
865 %rep 11
866 ALIGN 64
867 .emuedge_extend_right_ %+ %%n:          ; do {
868 %if ARCH_X86_64
869     sub        r3, r2                   ;   dst -= linesize
870     READ_V_PIXEL  %%n, [r3+w_reg-1]     ;   read pixels
871     WRITE_V_PIXEL %%n, r3+r4-%%n        ;   write pixels
872     dec       r8
873 %else ; ARCH_X86_32
874     sub        r0, r2                   ;   dst -= linesize
875     READ_V_PIXEL  %%n, [r0+w_reg-1]     ;   read pixels
876     WRITE_V_PIXEL %%n, r0+r4-%%n        ;   write pixels
877     dec     r5
878 %endif ; ARCH_X86_64/32
879     jnz .emuedge_extend_right_ %+ %%n   ; } while (--block_h)
880 %if ARCH_X86_64
881     ret
882 %else ; ARCH_X86_32
883     rep ret
884 %endif ; ARCH_X86_64/32
885 %assign %%n %%n+2
886 %endrep
887
888 %if ARCH_X86_32
889 %define stack_offset 0x10
890 %endif
891 %endmacro ; RIGHT_EXTEND
892
893 ; below follow the "slow" copy/extend functions, these act on a non-fixed
894 ; width specified in a register, and run a loop to copy the full amount
895 ; of bytes. They are optimized for copying of large amounts of pixels per
896 ; line, so they unconditionally splat data into mm registers to copy 8
897 ; bytes per loop iteration. It could be considered to use xmm for x86-64
898 ; also, but I haven't optimized this as much (i.e. FIXME)
899 %macro V_COPY_NPX 4-5
900 %if %0 == 4
901     test     w_reg, %4
902     jz .%1_skip_%4_px
903 %else ; %0 == 5
904 .%1_%4_px_loop:
905 %endif
906     %3          %2, [r1+cnt_reg]
907     %3 [r0+cnt_reg], %2
908     add    cnt_reg, %4
909 %if %0 == 5
910     sub      w_reg, %4
911     test     w_reg, %5
912     jnz .%1_%4_px_loop
913 %endif
914 .%1_skip_%4_px:
915 %endmacro
916
917 %macro V_COPY_ROW 2
918 %ifidn %1, bottom
919     sub         r1, linesize
920 %endif
921 .%1_copy_loop:
922     xor    cnt_reg, cnt_reg
923 %if notcpuflag(sse)
924 %define linesize r2m
925     V_COPY_NPX %1,  mm0, movq,    8, 0xFFFFFFF8
926 %else ; sse
927     V_COPY_NPX %1, xmm0, movups, 16, 0xFFFFFFF0
928 %if ARCH_X86_64
929 %define linesize r2
930     V_COPY_NPX %1, rax , mov,     8
931 %else ; ARCH_X86_32
932 %define linesize r2m
933     V_COPY_NPX %1,  mm0, movq,    8
934 %endif ; ARCH_X86_64/32
935 %endif ; sse
936     V_COPY_NPX %1, vald, mov,     4
937     V_COPY_NPX %1, valw, mov,     2
938     V_COPY_NPX %1, vall, mov,     1
939     mov      w_reg, cnt_reg
940 %ifidn %1, body
941     add         r1, linesize
942 %endif
943     add         r0, linesize
944     dec         %2
945     jnz .%1_copy_loop
946 %endmacro
947
948 %macro SLOW_V_EXTEND 0
949 .slow_v_extend_loop:
950 ; r0=buf,r1=src,r2(64)/r2m(32)=linesize,r3(64)/r3m(32)=start_x,r4=end_y,r5=block_h
951 ; r8(64)/r3(later-64)/r2(32)=cnt_reg,r6(64)/r3(32)=val_reg,r7(64)/r6(32)=w=end_x-start_x
952 %if ARCH_X86_64
953     push        r8              ; save old value of block_h
954     test        r3, r3
955 %define cnt_reg r8
956     jz .do_body_copy            ; if (!start_y) goto do_body_copy
957     V_COPY_ROW top, r3
958 %else
959     cmp  dword r3m, 0
960 %define cnt_reg r2
961     je .do_body_copy            ; if (!start_y) goto do_body_copy
962     V_COPY_ROW top, dword r3m
963 %endif
964
965 .do_body_copy:
966     V_COPY_ROW body, r4
967
968 %if ARCH_X86_64
969     pop         r8              ; restore old value of block_h
970 %define cnt_reg r3
971 %endif
972     test        r5, r5
973 %if ARCH_X86_64
974     jz .v_extend_end
975 %else
976     jz .skip_bottom_extend
977 %endif
978     V_COPY_ROW bottom, r5
979 %if ARCH_X86_32
980 .skip_bottom_extend:
981     mov         r2, r2m
982 %endif
983     jmp .v_extend_end
984 %endmacro
985
986 %macro SLOW_LEFT_EXTEND 0
987 .slow_left_extend_loop:
988 ; r0=buf+block_h*linesize,r2=linesize,r6(64)/r3(32)=val,r5=block_h,r4=cntr,r7/r6=start_x
989     mov         r4, 8
990     sub         r0, linesize
991     READ_V_PIXEL 8, [r0+w_reg]
992 .left_extend_8px_loop:
993     movq [r0+r4-8], mm0
994     add         r4, 8
995     cmp         r4, w_reg
996     jle .left_extend_8px_loop
997     sub         r4, 8
998     cmp         r4, w_reg
999     jge .left_extend_loop_end
1000 .left_extend_2px_loop:
1001     mov    [r0+r4], valw
1002     add         r4, 2
1003     cmp         r4, w_reg
1004     jl .left_extend_2px_loop
1005 .left_extend_loop_end:
1006     dec         r5
1007     jnz .slow_left_extend_loop
1008 %if ARCH_X86_32
1009     mov         r2, r2m
1010 %endif
1011     jmp .right_extend
1012 %endmacro
1013
1014 %macro SLOW_RIGHT_EXTEND 0
1015 .slow_right_extend_loop:
1016 ; r3(64)/r0(32)=buf+block_h*linesize,r2=linesize,r4=block_w,r8(64)/r5(32)=block_h,
1017 ; r7(64)/r6(32)=end_x,r6/r3=val,r1=cntr
1018 %if ARCH_X86_64
1019 %define buf_reg r3
1020 %define bh_reg r8
1021 %else
1022 %define buf_reg r0
1023 %define bh_reg r5
1024 %endif
1025     lea         r1, [r4-8]
1026     sub    buf_reg, linesize
1027     READ_V_PIXEL 8, [buf_reg+w_reg-1]
1028 .right_extend_8px_loop:
1029     movq [buf_reg+r1], mm0
1030     sub         r1, 8
1031     cmp         r1, w_reg
1032     jge .right_extend_8px_loop
1033     add         r1, 8
1034     cmp         r1, w_reg
1035     je .right_extend_loop_end
1036 .right_extend_2px_loop:
1037     sub         r1, 2
1038     mov [buf_reg+r1], valw
1039     cmp         r1, w_reg
1040     jg .right_extend_2px_loop
1041 .right_extend_loop_end:
1042     dec         bh_reg
1043     jnz .slow_right_extend_loop
1044     jmp .h_extend_end
1045 %endmacro
1046
1047 %macro emu_edge 1
1048 INIT_XMM %1
1049 EMU_EDGE_FUNC
1050 VERTICAL_EXTEND
1051 LEFT_EXTEND
1052 RIGHT_EXTEND
1053 SLOW_V_EXTEND
1054 SLOW_LEFT_EXTEND
1055 SLOW_RIGHT_EXTEND
1056 %endmacro
1057
1058 emu_edge sse
1059 %if ARCH_X86_32
1060 emu_edge mmx
1061 %endif
1062
1063 ;-----------------------------------------------------------------------------
1064 ; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min,
1065 ;                           int32_t max, unsigned int len)
1066 ;-----------------------------------------------------------------------------
1067
1068 ; %1 = number of xmm registers used
1069 ; %2 = number of inline load/process/store loops per asm loop
1070 ; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop
1071 ; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2)
1072 ; %5 = suffix
1073 %macro VECTOR_CLIP_INT32 4-5
1074 cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len
1075 %if %4
1076     cvtsi2ss  m4, minm
1077     cvtsi2ss  m5, maxm
1078 %else
1079     movd      m4, minm
1080     movd      m5, maxm
1081 %endif
1082     SPLATD    m4
1083     SPLATD    m5
1084 .loop:
1085 %assign %%i 1
1086 %rep %2
1087     mova      m0,  [srcq+mmsize*0*%%i]
1088     mova      m1,  [srcq+mmsize*1*%%i]
1089     mova      m2,  [srcq+mmsize*2*%%i]
1090     mova      m3,  [srcq+mmsize*3*%%i]
1091 %if %3
1092     mova      m7,  [srcq+mmsize*4*%%i]
1093     mova      m8,  [srcq+mmsize*5*%%i]
1094     mova      m9,  [srcq+mmsize*6*%%i]
1095     mova      m10, [srcq+mmsize*7*%%i]
1096 %endif
1097     CLIPD  m0,  m4, m5, m6
1098     CLIPD  m1,  m4, m5, m6
1099     CLIPD  m2,  m4, m5, m6
1100     CLIPD  m3,  m4, m5, m6
1101 %if %3
1102     CLIPD  m7,  m4, m5, m6
1103     CLIPD  m8,  m4, m5, m6
1104     CLIPD  m9,  m4, m5, m6
1105     CLIPD  m10, m4, m5, m6
1106 %endif
1107     mova  [dstq+mmsize*0*%%i], m0
1108     mova  [dstq+mmsize*1*%%i], m1
1109     mova  [dstq+mmsize*2*%%i], m2
1110     mova  [dstq+mmsize*3*%%i], m3
1111 %if %3
1112     mova  [dstq+mmsize*4*%%i], m7
1113     mova  [dstq+mmsize*5*%%i], m8
1114     mova  [dstq+mmsize*6*%%i], m9
1115     mova  [dstq+mmsize*7*%%i], m10
1116 %endif
1117 %assign %%i %%i+1
1118 %endrep
1119     add     srcq, mmsize*4*(%2+%3)
1120     add     dstq, mmsize*4*(%2+%3)
1121     sub     lend, mmsize*(%2+%3)
1122     jg .loop
1123     REP_RET
1124 %endmacro
1125
1126 INIT_MMX mmx
1127 %define CLIPD CLIPD_MMX
1128 VECTOR_CLIP_INT32 0, 1, 0, 0
1129 INIT_XMM sse2
1130 VECTOR_CLIP_INT32 6, 1, 0, 0, _int
1131 %define CLIPD CLIPD_SSE2
1132 VECTOR_CLIP_INT32 6, 2, 0, 1
1133 INIT_XMM sse4
1134 %define CLIPD CLIPD_SSE41
1135 %ifdef m8
1136 VECTOR_CLIP_INT32 11, 1, 1, 0
1137 %else
1138 VECTOR_CLIP_INT32 6, 1, 0, 0
1139 %endif
1140
1141 ;-----------------------------------------------------------------------------
1142 ; void vector_fmul_reverse(float *dst, const float *src0, const float *src1,
1143 ;                          int len)
1144 ;-----------------------------------------------------------------------------
1145 %macro VECTOR_FMUL_REVERSE 0
1146 cglobal vector_fmul_reverse, 4,4,2, dst, src0, src1, len
1147     lea       lenq, [lend*4 - 2*mmsize]
1148 ALIGN 16
1149 .loop:
1150 %if cpuflag(avx)
1151     vmovaps     xmm0, [src1q + 16]
1152     vinsertf128 m0, m0, [src1q], 1
1153     vshufps     m0, m0, m0, q0123
1154     vmovaps     xmm1, [src1q + mmsize + 16]
1155     vinsertf128 m1, m1, [src1q + mmsize], 1
1156     vshufps     m1, m1, m1, q0123
1157 %else
1158     mova    m0, [src1q]
1159     mova    m1, [src1q + mmsize]
1160     shufps  m0, m0, q0123
1161     shufps  m1, m1, q0123
1162 %endif
1163     mulps   m0, m0, [src0q + lenq + mmsize]
1164     mulps   m1, m1, [src0q + lenq]
1165     mova    [dstq + lenq + mmsize], m0
1166     mova    [dstq + lenq], m1
1167     add     src1q, 2*mmsize
1168     sub     lenq,  2*mmsize
1169     jge     .loop
1170     REP_RET
1171 %endmacro
1172
1173 INIT_XMM sse
1174 VECTOR_FMUL_REVERSE
1175 INIT_YMM avx
1176 VECTOR_FMUL_REVERSE
1177
1178 ;-----------------------------------------------------------------------------
1179 ; vector_fmul_add(float *dst, const float *src0, const float *src1,
1180 ;                 const float *src2, int len)
1181 ;-----------------------------------------------------------------------------
1182 %macro VECTOR_FMUL_ADD 0
1183 cglobal vector_fmul_add, 5,5,2, dst, src0, src1, src2, len
1184     lea       lenq, [lend*4 - 2*mmsize]
1185 ALIGN 16
1186 .loop:
1187     mova    m0,   [src0q + lenq]
1188     mova    m1,   [src0q + lenq + mmsize]
1189     mulps   m0, m0, [src1q + lenq]
1190     mulps   m1, m1, [src1q + lenq + mmsize]
1191     addps   m0, m0, [src2q + lenq]
1192     addps   m1, m1, [src2q + lenq + mmsize]
1193     mova    [dstq + lenq], m0
1194     mova    [dstq + lenq + mmsize], m1
1195
1196     sub     lenq,   2*mmsize
1197     jge     .loop
1198     REP_RET
1199 %endmacro
1200
1201 INIT_XMM sse
1202 VECTOR_FMUL_ADD
1203 INIT_YMM avx
1204 VECTOR_FMUL_ADD
1205
1206 ;-----------------------------------------------------------------------------
1207 ; void ff_butterflies_float_interleave(float *dst, const float *src0,
1208 ;                                      const float *src1, int len);
1209 ;-----------------------------------------------------------------------------
1210
1211 %macro BUTTERFLIES_FLOAT_INTERLEAVE 0
1212 cglobal butterflies_float_interleave, 4,4,3, dst, src0, src1, len
1213 %if ARCH_X86_64
1214     movsxd    lenq, lend
1215 %endif
1216     test      lenq, lenq
1217     jz .end
1218     shl       lenq, 2
1219     lea      src0q, [src0q +   lenq]
1220     lea      src1q, [src1q +   lenq]
1221     lea       dstq, [ dstq + 2*lenq]
1222     neg       lenq
1223 .loop:
1224     mova        m0, [src0q + lenq]
1225     mova        m1, [src1q + lenq]
1226     subps       m2, m0, m1
1227     addps       m0, m0, m1
1228     unpcklps    m1, m0, m2
1229     unpckhps    m0, m0, m2
1230 %if cpuflag(avx)
1231     vextractf128 [dstq + 2*lenq     ], m1, 0
1232     vextractf128 [dstq + 2*lenq + 16], m0, 0
1233     vextractf128 [dstq + 2*lenq + 32], m1, 1
1234     vextractf128 [dstq + 2*lenq + 48], m0, 1
1235 %else
1236     mova [dstq + 2*lenq         ], m1
1237     mova [dstq + 2*lenq + mmsize], m0
1238 %endif
1239     add       lenq, mmsize
1240     jl .loop
1241 .end:
1242     REP_RET
1243 %endmacro
1244
1245 INIT_XMM sse
1246 BUTTERFLIES_FLOAT_INTERLEAVE
1247 INIT_YMM avx
1248 BUTTERFLIES_FLOAT_INTERLEAVE
1249
1250 ; %1 = aligned/unaligned
1251 %macro BSWAP_LOOPS  1
1252     mov      r3, r2
1253     sar      r2, 3
1254     jz       .left4_%1
1255 .loop8_%1:
1256     mov%1    m0, [r1 +  0]
1257     mov%1    m1, [r1 + 16]
1258 %if cpuflag(ssse3)
1259     pshufb   m0, m2
1260     pshufb   m1, m2
1261     mova     [r0 +  0], m0
1262     mova     [r0 + 16], m1
1263 %else
1264     pshuflw  m0, m0, 10110001b
1265     pshuflw  m1, m1, 10110001b
1266     pshufhw  m0, m0, 10110001b
1267     pshufhw  m1, m1, 10110001b
1268     mova     m2, m0
1269     mova     m3, m1
1270     psllw    m0, 8
1271     psllw    m1, 8
1272     psrlw    m2, 8
1273     psrlw    m3, 8
1274     por      m2, m0
1275     por      m3, m1
1276     mova     [r0 +  0], m2
1277     mova     [r0 + 16], m3
1278 %endif
1279     add      r0, 32
1280     add      r1, 32
1281     dec      r2
1282     jnz      .loop8_%1
1283 .left4_%1:
1284     mov      r2, r3
1285     and      r3, 4
1286     jz       .left
1287     mov%1    m0, [r1]
1288 %if cpuflag(ssse3)
1289     pshufb   m0, m2
1290     mova     [r0], m0
1291 %else
1292     pshuflw  m0, m0, 10110001b
1293     pshufhw  m0, m0, 10110001b
1294     mova     m2, m0
1295     psllw    m0, 8
1296     psrlw    m2, 8
1297     por      m2, m0
1298     mova     [r0], m2
1299 %endif
1300     add      r1, 16
1301     add      r0, 16
1302 %endmacro
1303
1304 ; void bswap_buf(uint32_t *dst, const uint32_t *src, int w);
1305 %macro BSWAP32_BUF 0
1306 %if cpuflag(ssse3)
1307 cglobal bswap32_buf, 3,4,3
1308     mov      r3, r1
1309     mova     m2, [pb_bswap32]
1310 %else
1311 cglobal bswap32_buf, 3,4,5
1312     mov      r3, r1
1313 %endif
1314     and      r3, 15
1315     jz       .start_align
1316     BSWAP_LOOPS  u
1317     jmp      .left
1318 .start_align:
1319     BSWAP_LOOPS  a
1320 .left:
1321 %if cpuflag(ssse3)
1322     mov      r3, r2
1323     and      r2, 2
1324     jz       .left1
1325     movq     m0, [r1]
1326     pshufb   m0, m2
1327     movq     [r0], m0
1328     add      r1, 8
1329     add      r0, 8
1330 .left1:
1331     and      r3, 1
1332     jz       .end
1333     mov      r2d, [r1]
1334     bswap    r2d
1335     mov      [r0], r2d
1336 %else
1337     and      r2, 3
1338     jz       .end
1339 .loop2:
1340     mov      r3d, [r1]
1341     bswap    r3d
1342     mov      [r0], r3d
1343     add      r1, 4
1344     add      r0, 4
1345     dec      r2
1346     jnz      .loop2
1347 %endif
1348 .end:
1349     RET
1350 %endmacro
1351
1352 INIT_XMM sse2
1353 BSWAP32_BUF
1354
1355 INIT_XMM ssse3
1356 BSWAP32_BUF
1357
1358 %macro op_avgh 3
1359     movh   %3, %2
1360     pavgb  %1, %3
1361     movh   %2, %1
1362 %endmacro
1363
1364 %macro op_avg 2
1365     pavgb  %1, %2
1366     mova   %2, %1
1367 %endmacro
1368
1369 %macro op_puth 2-3
1370     movh   %2, %1
1371 %endmacro
1372
1373 %macro op_put 2
1374     mova   %2, %1
1375 %endmacro
1376
1377 ; void pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
1378 %macro PIXELS4_L2 1
1379 %define OP op_%1h
1380 cglobal %1_pixels4_l2, 6,6
1381     movsxdifnidn r3, r3d
1382     movsxdifnidn r4, r4d
1383     test        r5d, 1
1384     je        .loop
1385     movd         m0, [r1]
1386     movd         m1, [r2]
1387     add          r1, r4
1388     add          r2, 4
1389     pavgb        m0, m1
1390     OP           m0, [r0], m3
1391     add          r0, r3
1392     dec         r5d
1393 .loop:
1394     mova         m0, [r1]
1395     mova         m1, [r1+r4]
1396     lea          r1, [r1+2*r4]
1397     pavgb        m0, [r2]
1398     pavgb        m1, [r2+4]
1399     OP           m0, [r0], m3
1400     OP           m1, [r0+r3], m3
1401     lea          r0, [r0+2*r3]
1402     mova         m0, [r1]
1403     mova         m1, [r1+r4]
1404     lea          r1, [r1+2*r4]
1405     pavgb        m0, [r2+8]
1406     pavgb        m1, [r2+12]
1407     OP           m0, [r0], m3
1408     OP           m1, [r0+r3], m3
1409     lea          r0, [r0+2*r3]
1410     add          r2, 16
1411     sub         r5d, 4
1412     jne       .loop
1413     REP_RET
1414 %endmacro
1415
1416 INIT_MMX mmxext
1417 PIXELS4_L2 put
1418 PIXELS4_L2 avg
1419
1420 ; void pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
1421 %macro PIXELS8_L2 1
1422 %define OP op_%1
1423 cglobal %1_pixels8_l2, 6,6
1424     movsxdifnidn r3, r3d
1425     movsxdifnidn r4, r4d
1426     test        r5d, 1
1427     je        .loop
1428     mova         m0, [r1]
1429     mova         m1, [r2]
1430     add          r1, r4
1431     add          r2, 8
1432     pavgb        m0, m1
1433     OP           m0, [r0]
1434     add          r0, r3
1435     dec         r5d
1436 .loop:
1437     mova         m0, [r1]
1438     mova         m1, [r1+r4]
1439     lea          r1, [r1+2*r4]
1440     pavgb        m0, [r2]
1441     pavgb        m1, [r2+8]
1442     OP           m0, [r0]
1443     OP           m1, [r0+r3]
1444     lea          r0, [r0+2*r3]
1445     mova         m0, [r1]
1446     mova         m1, [r1+r4]
1447     lea          r1, [r1+2*r4]
1448     pavgb        m0, [r2+16]
1449     pavgb        m1, [r2+24]
1450     OP           m0, [r0]
1451     OP           m1, [r0+r3]
1452     lea          r0, [r0+2*r3]
1453     add          r2, 32
1454     sub         r5d, 4
1455     jne       .loop
1456     REP_RET
1457 %endmacro
1458
1459 INIT_MMX mmxext
1460 PIXELS8_L2 put
1461 PIXELS8_L2 avg
1462
1463 ; void pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
1464 %macro PIXELS16_L2 1
1465 %define OP op_%1
1466 cglobal %1_pixels16_l2, 6,6
1467     movsxdifnidn r3, r3d
1468     movsxdifnidn r4, r4d
1469     test        r5d, 1
1470     je        .loop
1471     mova         m0, [r1]
1472     mova         m1, [r1+8]
1473     pavgb        m0, [r2]
1474     pavgb        m1, [r2+8]
1475     add          r1, r4
1476     add          r2, 16
1477     OP           m0, [r0]
1478     OP           m1, [r0+8]
1479     add          r0, r3
1480     dec         r5d
1481 .loop:
1482     mova         m0, [r1]
1483     mova         m1, [r1+8]
1484     add          r1, r4
1485     pavgb        m0, [r2]
1486     pavgb        m1, [r2+8]
1487     OP           m0, [r0]
1488     OP           m1, [r0+8]
1489     add          r0, r3
1490     mova         m0, [r1]
1491     mova         m1, [r1+8]
1492     add          r1, r4
1493     pavgb        m0, [r2+16]
1494     pavgb        m1, [r2+24]
1495     OP           m0, [r0]
1496     OP           m1, [r0+8]
1497     add          r0, r3
1498     add          r2, 32
1499     sub         r5d, 2
1500     jne       .loop
1501     REP_RET
1502 %endmacro
1503
1504 INIT_MMX mmxext
1505 PIXELS16_L2 put
1506 PIXELS16_L2 avg
1507
1508 INIT_MMX mmxext
1509 ; void pixels(uint8_t *block, const uint8_t *pixels, int line_size, int h)
1510 %macro PIXELS48 2
1511 %if %2 == 4
1512 %define OP movh
1513 %else
1514 %define OP mova
1515 %endif
1516 cglobal %1_pixels%2, 4,5
1517     movsxdifnidn r2, r2d
1518     lea          r4, [r2*3]
1519 .loop:
1520     OP           m0, [r1]
1521     OP           m1, [r1+r2]
1522     OP           m2, [r1+r2*2]
1523     OP           m3, [r1+r4]
1524     lea          r1, [r1+r2*4]
1525 %ifidn %1, avg
1526     pavgb        m0, [r0]
1527     pavgb        m1, [r0+r2]
1528     pavgb        m2, [r0+r2*2]
1529     pavgb        m3, [r0+r4]
1530 %endif
1531     OP         [r0], m0
1532     OP      [r0+r2], m1
1533     OP    [r0+r2*2], m2
1534     OP      [r0+r4], m3
1535     sub         r3d, 4
1536     lea          r0, [r0+r2*4]
1537     jne       .loop
1538     RET
1539 %endmacro
1540
1541 PIXELS48 put, 4
1542 PIXELS48 avg, 4
1543 PIXELS48 put, 8
1544 PIXELS48 avg, 8
1545
1546 INIT_XMM sse2
1547 ; void put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
1548 cglobal put_pixels16, 4,5,4
1549     movsxdifnidn r2, r2d
1550     lea          r4, [r2*3]
1551 .loop:
1552     movu         m0, [r1]
1553     movu         m1, [r1+r2]
1554     movu         m2, [r1+r2*2]
1555     movu         m3, [r1+r4]
1556     lea          r1, [r1+r2*4]
1557     mova       [r0], m0
1558     mova    [r0+r2], m1
1559     mova  [r0+r2*2], m2
1560     mova    [r0+r4], m3
1561     sub         r3d, 4
1562     lea          r0, [r0+r2*4]
1563     jnz       .loop
1564     REP_RET
1565
1566 ; void avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
1567 cglobal avg_pixels16, 4,5,4
1568     movsxdifnidn r2, r2d
1569     lea          r4, [r2*3]
1570 .loop:
1571     movu         m0, [r1]
1572     movu         m1, [r1+r2]
1573     movu         m2, [r1+r2*2]
1574     movu         m3, [r1+r4]
1575     lea          r1, [r1+r2*4]
1576     pavgb        m0, [r0]
1577     pavgb        m1, [r0+r2]
1578     pavgb        m2, [r0+r2*2]
1579     pavgb        m3, [r0+r4]
1580     mova       [r0], m0
1581     mova    [r0+r2], m1
1582     mova  [r0+r2*2], m2
1583     mova    [r0+r4], m3
1584     sub         r3d, 4
1585     lea          r0, [r0+r2*4]
1586     jnz       .loop
1587     REP_RET