Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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