| 
							- ;******************************************************************************
 - ;* x86-optimized vertical line scaling functions
 - ;* Copyright (c) 2011 Ronald S. Bultje <rsbultje@gmail.com>
 - ;*                    Kieran Kunhya <kieran@kunhya.com>
 - ;*
 - ;* This file is part of FFmpeg.
 - ;*
 - ;* FFmpeg is free software; you can redistribute it and/or
 - ;* modify it under the terms of the GNU Lesser General Public
 - ;* License as published by the Free Software Foundation; either
 - ;* version 2.1 of the License, or (at your option) any later version.
 - ;*
 - ;* FFmpeg is distributed in the hope that it will be useful,
 - ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
 - ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 - ;* Lesser General Public License for more details.
 - ;*
 - ;* You should have received a copy of the GNU Lesser General Public
 - ;* License along with FFmpeg; if not, write to the Free Software
 - ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 - ;******************************************************************************
 - 
 - %include "libavutil/x86/x86util.asm"
 - 
 - SECTION_RODATA
 - 
 - minshort:      times 8 dw 0x8000
 - yuv2yuvX_16_start:  times 4 dd 0x4000 - 0x40000000
 - yuv2yuvX_10_start:  times 4 dd 0x10000
 - yuv2yuvX_9_start:   times 4 dd 0x20000
 - yuv2yuvX_10_upper:  times 8 dw 0x3ff
 - yuv2yuvX_9_upper:   times 8 dw 0x1ff
 - pd_4:          times 4 dd 4
 - pd_4min0x40000:times 4 dd 4 - (0x40000)
 - pw_16:         times 8 dw 16
 - pw_32:         times 8 dw 32
 - pw_512:        times 8 dw 512
 - pw_1024:       times 8 dw 1024
 - 
 - SECTION .text
 - 
 - ;-----------------------------------------------------------------------------
 - ; vertical line scaling
 - ;
 - ; void yuv2plane1_<output_size>_<opt>(const int16_t *src, uint8_t *dst, int dstW,
 - ;                                     const uint8_t *dither, int offset)
 - ; and
 - ; void yuv2planeX_<output_size>_<opt>(const int16_t *filter, int filterSize,
 - ;                                     const int16_t **src, uint8_t *dst, int dstW,
 - ;                                     const uint8_t *dither, int offset)
 - ;
 - ; Scale one or $filterSize lines of source data to generate one line of output
 - ; data. The input is 15-bit in int16_t if $output_size is [8,10] and 19-bit in
 - ; int32_t if $output_size is 16. $filter is 12-bits. $filterSize is a multiple
 - ; of 2. $offset is either 0 or 3. $dither holds 8 values.
 - ;-----------------------------------------------------------------------------
 - 
 - %macro yuv2planeX_fn 3
 - 
 - %if ARCH_X86_32
 - %define cntr_reg fltsizeq
 - %define movsx mov
 - %else
 - %define cntr_reg r7
 - %define movsx movsxd
 - %endif
 - 
 - cglobal yuv2planeX_%1, %3, 8, %2, filter, fltsize, src, dst, w, dither, offset
 - %if %1 == 8 || %1 == 9 || %1 == 10
 -     pxor            m6,  m6
 - %endif ; %1 == 8/9/10
 - 
 - %if %1 == 8
 - %if ARCH_X86_32
 - %assign pad 0x2c - (stack_offset & 15)
 -     SUB             rsp, pad
 - %define m_dith m7
 - %else ; x86-64
 - %define m_dith m9
 - %endif ; x86-32
 - 
 -     ; create registers holding dither
 -     movq        m_dith, [ditherq]        ; dither
 -     test        offsetd, offsetd
 -     jz              .no_rot
 - %if mmsize == 16
 -     punpcklqdq  m_dith,  m_dith
 - %endif ; mmsize == 16
 -     PALIGNR     m_dith,  m_dith,  3,  m0
 - .no_rot:
 - %if mmsize == 16
 -     punpcklbw   m_dith,  m6
 - %if ARCH_X86_64
 -     punpcklwd       m8,  m_dith,  m6
 -     pslld           m8,  12
 - %else ; x86-32
 -     punpcklwd       m5,  m_dith,  m6
 -     pslld           m5,  12
 - %endif ; x86-32/64
 -     punpckhwd   m_dith,  m6
 -     pslld       m_dith,  12
 - %if ARCH_X86_32
 -     mova      [rsp+ 0],  m5
 -     mova      [rsp+16],  m_dith
 - %endif
 - %else ; mmsize == 8
 -     punpcklbw       m5,  m_dith,  m6
 -     punpckhbw   m_dith,  m6
 -     punpcklwd       m4,  m5,  m6
 -     punpckhwd       m5,  m6
 -     punpcklwd       m3,  m_dith,  m6
 -     punpckhwd   m_dith,  m6
 -     pslld           m4,  12
 -     pslld           m5,  12
 -     pslld           m3,  12
 -     pslld       m_dith,  12
 -     mova      [rsp+ 0],  m4
 -     mova      [rsp+ 8],  m5
 -     mova      [rsp+16],  m3
 -     mova      [rsp+24],  m_dith
 - %endif ; mmsize == 8/16
 - %endif ; %1 == 8
 - 
 -     xor             r5,  r5
 - 
 - .pixelloop:
 - %assign %%i 0
 -     ; the rep here is for the 8bit output mmx case, where dither covers
 -     ; 8 pixels but we can only handle 2 pixels per register, and thus 4
 -     ; pixels per iteration. In order to not have to keep track of where
 -     ; we are w.r.t. dithering, we unroll the mmx/8bit loop x2.
 - %if %1 == 8
 - %assign %%repcnt 16/mmsize
 - %else
 - %assign %%repcnt 1
 - %endif
 - 
 - %rep %%repcnt
 - 
 - %if %1 == 8
 - %if ARCH_X86_32
 -     mova            m2, [rsp+mmsize*(0+%%i)]
 -     mova            m1, [rsp+mmsize*(1+%%i)]
 - %else ; x86-64
 -     mova            m2,  m8
 -     mova            m1,  m_dith
 - %endif ; x86-32/64
 - %else ; %1 == 9/10/16
 -     mova            m1, [yuv2yuvX_%1_start]
 -     mova            m2,  m1
 - %endif ; %1 == 8/9/10/16
 -     movsx     cntr_reg,  fltsizem
 - .filterloop_ %+ %%i:
 -     ; input pixels
 -     mov             r6, [srcq+gprsize*cntr_reg-2*gprsize]
 - %if %1 == 16
 -     mova            m3, [r6+r5*4]
 -     mova            m5, [r6+r5*4+mmsize]
 - %else ; %1 == 8/9/10
 -     mova            m3, [r6+r5*2]
 - %endif ; %1 == 8/9/10/16
 -     mov             r6, [srcq+gprsize*cntr_reg-gprsize]
 - %if %1 == 16
 -     mova            m4, [r6+r5*4]
 -     mova            m6, [r6+r5*4+mmsize]
 - %else ; %1 == 8/9/10
 -     mova            m4, [r6+r5*2]
 - %endif ; %1 == 8/9/10/16
 - 
 -     ; coefficients
 -     movd            m0, [filterq+2*cntr_reg-4] ; coeff[0], coeff[1]
 - %if %1 == 16
 -     pshuflw         m7,  m0,  0          ; coeff[0]
 -     pshuflw         m0,  m0,  0x55       ; coeff[1]
 -     pmovsxwd        m7,  m7              ; word -> dword
 -     pmovsxwd        m0,  m0              ; word -> dword
 - 
 -     pmulld          m3,  m7
 -     pmulld          m5,  m7
 -     pmulld          m4,  m0
 -     pmulld          m6,  m0
 - 
 -     paddd           m2,  m3
 -     paddd           m1,  m5
 -     paddd           m2,  m4
 -     paddd           m1,  m6
 - %else ; %1 == 10/9/8
 -     punpcklwd       m5,  m3,  m4
 -     punpckhwd       m3,  m4
 -     SPLATD          m0
 - 
 -     pmaddwd         m5,  m0
 -     pmaddwd         m3,  m0
 - 
 -     paddd           m2,  m5
 -     paddd           m1,  m3
 - %endif ; %1 == 8/9/10/16
 - 
 -     sub       cntr_reg,  2
 -     jg .filterloop_ %+ %%i
 - 
 - %if %1 == 16
 -     psrad           m2,  31 - %1
 -     psrad           m1,  31 - %1
 - %else ; %1 == 10/9/8
 -     psrad           m2,  27 - %1
 -     psrad           m1,  27 - %1
 - %endif ; %1 == 8/9/10/16
 - 
 - %if %1 == 8
 -     packssdw        m2,  m1
 -     packuswb        m2,  m2
 -     movh   [dstq+r5*1],  m2
 - %else ; %1 == 9/10/16
 - %if %1 == 16
 -     packssdw        m2,  m1
 -     paddw           m2, [minshort]
 - %else ; %1 == 9/10
 - %if cpuflag(sse4)
 -     packusdw        m2,  m1
 - %else ; mmxext/sse2
 -     packssdw        m2,  m1
 -     pmaxsw          m2,  m6
 - %endif ; mmxext/sse2/sse4/avx
 -     pminsw          m2, [yuv2yuvX_%1_upper]
 - %endif ; %1 == 9/10/16
 -     mova   [dstq+r5*2],  m2
 - %endif ; %1 == 8/9/10/16
 - 
 -     add             r5,  mmsize/2
 -     sub             wd,  mmsize/2
 - 
 - %assign %%i %%i+2
 - %endrep
 -     jg .pixelloop
 - 
 - %if %1 == 8
 - %if ARCH_X86_32
 -     ADD             rsp, pad
 -     RET
 - %else ; x86-64
 -     REP_RET
 - %endif ; x86-32/64
 - %else ; %1 == 9/10/16
 -     REP_RET
 - %endif ; %1 == 8/9/10/16
 - %endmacro
 - 
 - %if ARCH_X86_32
 - INIT_MMX mmxext
 - yuv2planeX_fn  8,  0, 7
 - yuv2planeX_fn  9,  0, 5
 - yuv2planeX_fn 10,  0, 5
 - %endif
 - 
 - INIT_XMM sse2
 - yuv2planeX_fn  8, 10, 7
 - yuv2planeX_fn  9,  7, 5
 - yuv2planeX_fn 10,  7, 5
 - 
 - INIT_XMM sse4
 - yuv2planeX_fn  8, 10, 7
 - yuv2planeX_fn  9,  7, 5
 - yuv2planeX_fn 10,  7, 5
 - yuv2planeX_fn 16,  8, 5
 - 
 - %if HAVE_AVX_EXTERNAL
 - INIT_XMM avx
 - yuv2planeX_fn  8, 10, 7
 - yuv2planeX_fn  9,  7, 5
 - yuv2planeX_fn 10,  7, 5
 - %endif
 - 
 - ; %1=outout-bpc, %2=alignment (u/a)
 - %macro yuv2plane1_mainloop 2
 - .loop_%2:
 - %if %1 == 8
 -     paddsw          m0, m2, [srcq+wq*2+mmsize*0]
 -     paddsw          m1, m3, [srcq+wq*2+mmsize*1]
 -     psraw           m0, 7
 -     psraw           m1, 7
 -     packuswb        m0, m1
 -     mov%2    [dstq+wq], m0
 - %elif %1 == 16
 -     paddd           m0, m4, [srcq+wq*4+mmsize*0]
 -     paddd           m1, m4, [srcq+wq*4+mmsize*1]
 -     paddd           m2, m4, [srcq+wq*4+mmsize*2]
 -     paddd           m3, m4, [srcq+wq*4+mmsize*3]
 -     psrad           m0, 3
 -     psrad           m1, 3
 -     psrad           m2, 3
 -     psrad           m3, 3
 - %if cpuflag(sse4) ; avx/sse4
 -     packusdw        m0, m1
 -     packusdw        m2, m3
 - %else ; mmx/sse2
 -     packssdw        m0, m1
 -     packssdw        m2, m3
 -     paddw           m0, m5
 -     paddw           m2, m5
 - %endif ; mmx/sse2/sse4/avx
 -     mov%2    [dstq+wq*2+mmsize*0], m0
 -     mov%2    [dstq+wq*2+mmsize*1], m2
 - %else ; %1 == 9/10
 -     paddsw          m0, m2, [srcq+wq*2+mmsize*0]
 -     paddsw          m1, m2, [srcq+wq*2+mmsize*1]
 -     psraw           m0, 15 - %1
 -     psraw           m1, 15 - %1
 -     pmaxsw          m0, m4
 -     pmaxsw          m1, m4
 -     pminsw          m0, m3
 -     pminsw          m1, m3
 -     mov%2    [dstq+wq*2+mmsize*0], m0
 -     mov%2    [dstq+wq*2+mmsize*1], m1
 - %endif
 -     add             wq, mmsize
 -     jl .loop_%2
 - %endmacro
 - 
 - %macro yuv2plane1_fn 3
 - cglobal yuv2plane1_%1, %3, %3, %2, src, dst, w, dither, offset
 -     movsxdifnidn    wq, wd
 -     add             wq, mmsize - 1
 -     and             wq, ~(mmsize - 1)
 - %if %1 == 8
 -     add           dstq, wq
 - %else ; %1 != 8
 -     lea           dstq, [dstq+wq*2]
 - %endif ; %1 == 8
 - %if %1 == 16
 -     lea           srcq, [srcq+wq*4]
 - %else ; %1 != 16
 -     lea           srcq, [srcq+wq*2]
 - %endif ; %1 == 16
 -     neg             wq
 - 
 - %if %1 == 8
 -     pxor            m4, m4               ; zero
 - 
 -     ; create registers holding dither
 -     movq            m3, [ditherq]        ; dither
 -     test       offsetd, offsetd
 -     jz              .no_rot
 - %if mmsize == 16
 -     punpcklqdq      m3, m3
 - %endif ; mmsize == 16
 -     PALIGNR         m3, m3, 3, m2
 - .no_rot:
 - %if mmsize == 8
 -     mova            m2, m3
 -     punpckhbw       m3, m4               ; byte->word
 -     punpcklbw       m2, m4               ; byte->word
 - %else
 -     punpcklbw       m3, m4
 -     mova            m2, m3
 - %endif
 - %elif %1 == 9
 -     pxor            m4, m4
 -     mova            m3, [pw_512]
 -     mova            m2, [pw_32]
 - %elif %1 == 10
 -     pxor            m4, m4
 -     mova            m3, [pw_1024]
 -     mova            m2, [pw_16]
 - %else ; %1 == 16
 - %if cpuflag(sse4) ; sse4/avx
 -     mova            m4, [pd_4]
 - %else ; mmx/sse2
 -     mova            m4, [pd_4min0x40000]
 -     mova            m5, [minshort]
 - %endif ; mmx/sse2/sse4/avx
 - %endif ; %1 == ..
 - 
 -     ; actual pixel scaling
 - %if mmsize == 8
 -     yuv2plane1_mainloop %1, a
 - %else ; mmsize == 16
 -     test          dstq, 15
 -     jnz .unaligned
 -     yuv2plane1_mainloop %1, a
 -     REP_RET
 - .unaligned:
 -     yuv2plane1_mainloop %1, u
 - %endif ; mmsize == 8/16
 -     REP_RET
 - %endmacro
 - 
 - %if ARCH_X86_32
 - INIT_MMX mmx
 - yuv2plane1_fn  8, 0, 5
 - yuv2plane1_fn 16, 0, 3
 - 
 - INIT_MMX mmxext
 - yuv2plane1_fn  9, 0, 3
 - yuv2plane1_fn 10, 0, 3
 - %endif
 - 
 - INIT_XMM sse2
 - yuv2plane1_fn  8, 5, 5
 - yuv2plane1_fn  9, 5, 3
 - yuv2plane1_fn 10, 5, 3
 - yuv2plane1_fn 16, 6, 3
 - 
 - INIT_XMM sse4
 - yuv2plane1_fn 16, 5, 3
 - 
 - %if HAVE_AVX_EXTERNAL
 - INIT_XMM avx
 - yuv2plane1_fn  8, 5, 5
 - yuv2plane1_fn  9, 5, 3
 - yuv2plane1_fn 10, 5, 3
 - yuv2plane1_fn 16, 5, 3
 - %endif
 
 
  |