shithub: openh264

ref: bb244d736b3db516a9068f1682bcb82ee4200970
dir: /codec/encoder/core/arm/pixel_neon.S/

View raw version
/*!
 * \copy
 *     Copyright (c)  2013, Cisco Systems
 *     All rights reserved.
 *
 *     Redistribution and use in source and binary forms, with or without
 *     modification, are permitted provided that the following conditions
 *     are met:
 *
 *        * Redistributions of source code must retain the above copyright
 *          notice, this list of conditions and the following disclaimer.
 *
 *        * Redistributions in binary form must reproduce the above copyright
 *          notice, this list of conditions and the following disclaimer in
 *          the documentation and/or other materials provided with the
 *          distribution.
 *
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *     POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifdef HAVE_NEON
.text
#include "arm_arch_common_macro.S"

.macro SATD_16x4
    vld1.64     {q0}, [r0,:128], r1   
    vld1.64     {q1}, [r2], r3   

    vsubl.u8    q4,  d0,  d2        
    vld1.64     {q2}, [r0,:128], r1  

    vsubl.u8    q6, d1,  d3       
    vld1.64     {q3}, [r2], r3   

    vsubl.u8    q5,  d4,  d6        
    vld1.64     {q0}, [r0,:128], r1  

    vsubl.u8    q7, d5,  d7	
    vld1.64     {q1}, [r2], r3

    vsubl.u8    q8, d0,  d2
    vld1.64     {q2}, [r0,:128], r1 

    vsubl.u8    q10, d1,  d3
    vadd.s16    q0,  q4,  q5  

    vld1.64     {q3}, [r2], r3  
    vsub.s16    q1,  q4,  q5     

    vsubl.u8    q9, d4,  d6     
    vsubl.u8    q11, d5,  d7    

    vadd.s16    q2, q8, q9       
    vsub.s16    q3, q8, q9		

    vadd.s16    q4, q6, q7			
    vsub.s16	q5, q6, q7

    vadd.s16    q6, q10, q11	
    vsub.s16	q7, q10, q11	

    vadd.s16    q8, q0, q2      
    vsub.s16    q10, q0, q2 

    vadd.s16    q9, q4, q6  
    vsub.s16    q11, q4, q6 	

    vsub.s16    q0, q1, q3		
    vadd.s16    q2, q1, q3     

    vsub.s16    q1, q5, q7		
    vadd.s16    q3, q5, q7    

    vtrn.16 q8, q10  
    vtrn.16 q9, q11	

    vadd.s16 q4, q8, q10		
    vabd.s16 q6, q8, q10	

    vadd.s16 q5, q9, q11		
    vabd.s16 q7, q9, q11	

    vabs.s16 q4, q4
    vabs.s16 q5, q5

    vtrn.16 q0, q2			
    vtrn.16 q1, q3			

    vadd.s16 q8, q0, q2			  
    vabd.s16 q10, q0, q2		 

    vadd.s16 q9, q1, q3			  
    vabd.s16 q11, q1, q3

    vabs.s16 q8, q8
    vabs.s16 q9, q9

    vtrn.32 q4, q6
    vtrn.32 q5, q7

    vtrn.32 q8, q10
    vtrn.32 q9, q11

    vmax.s16    q0, q4,  q6
    vmax.s16    q1, q5,  q7
    vmax.s16    q2, q8,  q10
    vmax.s16    q3, q9,  q11

    vadd.u16 q0, q0, q1
    vadd.u16 q2, q2, q3
.endm

.macro SATD_8x4

    vld1.64     {d0}, [r0,:64], r1
    vld1.64     {d1}, [r2], r3

    vld1.64     {d2}, [r0,:64], r1
    vsubl.u8    q4, d0, d1            

    vld1.64     {d3}, [r2], r3
    vsubl.u8    q5, d2, d3         

    vld1.64     {d4}, [r0,:64], r1
    vld1.64     {d5}, [r2], r3

    vadd.s16    q8, q4, q5                 
    vsubl.u8    q6, d4, d5             

    vld1.64     {d6}, [r0,:64], r1
    vld1.64     {d7}, [r2], r3

    vsubl.u8    q7, d6,  d7               
    vsub.s16    q9, q4, q5       

    vadd.s16    q10, q6, q7         
    vsub.s16    q11, q6, q7         

    vadd.s16    q0, q8, q10               
    vsub.s16    q1, q8, q10      

    vsub.s16    q2, q9, q11            
    vadd.s16    q3, q9, q11        

    vtrn.16     q0, q1
    vtrn.16     q2, q3

    vadd.s16    q4, q0, q1
    vabd.s16    q5, q0, q1

    vabs.s16    q4, q4
    vadd.s16    q6, q2, q3

    vabd.s16    q7, q2, q3
    vabs.s16    q6, q6

    vtrn.32     q4, q5
    vtrn.32     q6, q7

    vmax.s16    q0, q4, q5
    vmax.s16    q1, q6, q7
.endm

.macro SAD_16x4
    vld1.64 {q6}, [r0, :128], r1
    vabal.u8 q10, d8, d10

    vld1.64 {q7}, [r2], r3
    vabal.u8 q11, d9, d11

    vld1.64 {q0}, [r0, :128], r1
    vabal.u8 q12, d12, d14

    vld1.64 {q1}, [r2], r3
    vabal.u8 q13, d13, d15

    vld1.64 {q2}, [r0, :128], r1
    vabal.u8 q10, d0, d2

    vld1.64 {q3}, [r2], r3
    vabal.u8 q11, d1, d3

    vld1.64 {q4}, [r0, :128], r1
    vabal.u8 q12, d4, d6

    vld1.64 {q5}, [r2], r3
    vabal.u8 q13, d5, d7
.endm

.macro SAD_8x4
    vld1.64 {d0}, [r0, :64], r1
    vld1.64 {d1}, [r2], r3

    vabal.u8 q10, d0, d1
    vld1.64 {d2}, [r0, :64], r1

    vld1.64 {d3}, [r2], r3
    vabal.u8 q11, d2, d3

    vld1.64 {d4}, [r0, :64], r1
    vld1.64 {d5}, [r2], r3

    vabal.u8 q12, d4, d5
    vld1.64 {d6}, [r0, :64], r1

    vld1.64 {d7}, [r2], r3
    vabal.u8 q13, d6, d7
.endm


WELS_ASM_FUNC_BEGIN pixel_sad_16x16_neon

    vld1.64 {q0}, [r0, :128], r1
    vld1.64 {q1}, [r2], r3

    vabdl.u8 q10, d0, d2
    vld1.64 {q2}, [r0, :128], r1

    vabdl.u8 q11, d1, d3
    vld1.64 {q3}, [r2], r3

    vld1.64 {q4}, [r0, :128], r1
    vabdl.u8 q12, d4, d6
    vld1.64 {q5}, [r2], r3
    vabdl.u8 q13, d5, d7

    SAD_16x4
    SAD_16x4
    SAD_16x4

    vld1.64 {q6}, [r0, :128], r1
    vabal.u8 q10, d8, d10

    vld1.64 {q7}, [r2], r3
    vabal.u8 q11, d9, d11

    vabal.u8 q12, d12, d14
    vabal.u8 q13, d13, d15

    vadd.u16 q14, q10, q11
    vadd.u16 q15, q12, q13

    vadd.u16 q15, q14, q15
    vadd.u16 d0, d30, d31
    vpaddl.u16 d0, d0
    vpaddl.u32 d0, d0
    vmov.u32   r0, d0[0]
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_sad_16x8_neon

    vld1.64 {q0}, [r0, :128], r1
    vld1.64 {q1}, [r2], r3

    vabdl.u8 q10, d0, d2
    vld1.64 {q2}, [r0, :128], r1

    vabdl.u8 q11, d1, d3
    vld1.64 {q3}, [r2], r3

    vld1.64 {q4}, [r0, :128], r1
    vabdl.u8 q12, d4, d6
    vld1.64 {q5}, [r2], r3
    vabdl.u8 q13, d5, d7

    SAD_16x4

    vld1.64 {q6}, [r0, :128], r1
    vabal.u8 q10, d8, d10

    vld1.64 {q7}, [r2], r3
    vabal.u8 q11, d9, d11

    vabal.u8 q12, d12, d14
    vabal.u8 q13, d13, d15

    vadd.u16 q14, q10, q11
    vadd.u16 q15, q12, q13

    vadd.u16 q15, q14, q15
    vadd.u16 d0, d30, d31
    vpaddl.u16 d0, d0
    vpaddl.u32 d0, d0
    vmov.u32   r0, d0[0]
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_sad_8x16_neon

    vld1.64 {d0}, [r0, :64], r1
    vld1.64 {d1}, [r2], r3

    vabdl.u8 q10, d0, d1
    vld1.64 {d2}, [r0, :64], r1

    vld1.64 {d3}, [r2], r3
    vabdl.u8 q11, d2, d3

    vld1.64 {d4}, [r0, :64], r1
    vld1.64 {d5}, [r2], r3

    vabdl.u8 q12, d4, d5
    vld1.64 {d6}, [r0, :64], r1

    vld1.64 {d7}, [r2], r3
    vabdl.u8 q13, d6, d7

    SAD_8x4
    SAD_8x4
    SAD_8x4

    vadd.u16 q14, q10, q11
    vadd.u16 q15, q12, q13
    vadd.u16 q15, q15, q14
    vadd.u16 d0, d30, d31
    vpaddl.u16 d0, d0
    vpaddl.u32 d0, d0
    vmov.u32   r0, d0[0]
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_sad_8x8_neon

    vld1.64 {d0}, [r0, :64], r1
    vld1.64 {d1}, [r2], r3

    vabdl.u8 q10, d0, d1
    vld1.64 {d2}, [r0, :64], r1

    vld1.64 {d3}, [r2], r3
    vabdl.u8 q11, d2, d3

    vld1.64 {d4}, [r0, :64], r1
    vld1.64 {d5}, [r2], r3

    vabdl.u8 q12, d4, d5
    vld1.64 {d6}, [r0, :64], r1

    vld1.64 {d7}, [r2], r3
    vabdl.u8 q13, d6, d7

    SAD_8x4

    vadd.u16 q14, q10, q11
    vadd.u16 q15, q12, q13
    vadd.u16 q15, q15, q14
    vadd.u16 d0, d30, d31
    vpaddl.u16 d0, d0
    vpaddl.u32 d0, d0
    vmov.u32   r0, d0[0]
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_sad_4x4_neon
    stmdb sp!, {r4-r5, lr}

	//Loading a horizontal line data (4 bytes)
	//line 0
	ldr r4, [r0], r1
	ldr r5, [r2], r3
	usad8  lr, r4, r5

    //line 1
	ldr r4, [r0], r1
	ldr r5, [r2], r3
	usada8  lr, r4, r5, lr	

    //line 2	
	ldr r4, [r0], r1
	ldr r5, [r2], r3
	usada8  lr, r4, r5, lr	
	
	//line 3
	ldr r4, [r0]
	ldr r5, [r2]
	usada8  r0, r4, r5, lr	

	ldmia sp!, {r4-r5, lr}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_sad_4_16x16_neon

    stmdb sp!, {r4-r5, lr}

	//Generate the pix2 start addr
	sub   r4, r2, #1
	add   r5, r2, #1
	sub   r2, r3
			
    //Loading a horizontal line data (16 bytes)
	vld1.8 {q0}, [r0], r1 //save pix1
	
	vld1.8 {q1}, [r2], r3 //save pix2 - stride
	vld1.8 {q6}, [r2], r3 //save pix2
	vld1.8 {q2}, [r2], r3 //save pix2 + stride
	
	vld1.8 {q3}, [r4], r3 //save pix2 - 1
	vld1.8 {q4}, [r5], r3 //save pix2 + 1	
		    
	//Do the SAD for 16 bytes
	vabdl.u8  q15, d0, d2
	vabal.u8  q15, d1, d3
	
	vabdl.u8  q13, d0, d4
	vabal.u8  q13, d1, d5
	
	vabdl.u8  q11, d0, d6
	vabal.u8  q11, d1, d7
	
	vabdl.u8  q9, d0, d8
	vabal.u8  q9, d1, d9			
	
	mov lr, #15
pixel_sad_4_16x16_loop_0:

    //Loading a horizontal line data (16 bytes)
	vld1.8 {q0}, [r0], r1 //save pix1
	vmov.8 q1,   q6       //save pix2 - stride
	vmov.8 q6,   q2
	vabal.u8  q15, d0, d2
	vld1.8 {q2}, [r2], r3 //save pix2 + stride
	vabal.u8  q15, d1, d3
	vld1.8 {q3}, [r4], r3 //save pix2 - 1
	vabal.u8  q13, d0, d4
	vld1.8 {q4}, [r5], r3 //save pix2 + 1	
    vabal.u8  q13, d1, d5
	subs lr, #1

	vabal.u8  q11, d0, d6
	vabal.u8  q11, d1, d7
	
	vabal.u8  q9, d0, d8
	vabal.u8  q9, d1, d9

	bne pixel_sad_4_16x16_loop_0


    //Save SAD to 'r0'
	ldr   r0, [sp, #12]
	
	vadd.u16   d0, d30, d31
	vadd.u16   d1, d26, d27
	vadd.u16   d2, d22, d23
	vadd.u16   d3, d18, d19
	
	vpaddl.u16 q0, q0
	vpaddl.u16 q1, q1
	
	vpaddl.u32 q0, q0
	vpaddl.u32 q1, q1
		
	vshl.u32   q0, #4
	vshl.u32   q1, #4
	vst4.32    {d0[0],d1[0],d2[0],d3[0]}, [r0]

	ldmia sp!, {r4-r5, lr}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_sad_4_16x8_neon
    stmdb sp!, {r4-r5, lr}
	
	//Generate the pix2 start addr
	sub   r4, r2, #1
	add   r5, r2, #1
	sub   r2, r3
			
    //Loading a horizontal line data (16 bytes)
	vld1.8 {q0}, [r0], r1 //save pix1
	
	vld1.8 {q1}, [r2], r3 //save pix2 - stride
	vld1.8 {q6}, [r2], r3 //save pix2
	vld1.8 {q2}, [r2], r3 //save pix2 + stride
	
	vld1.8 {q3}, [r4], r3 //save pix2 - 1
	vld1.8 {q4}, [r5], r3 //save pix2 + 1	
		    
	//Do the SAD for 16 bytes
	vabdl.u8  q15, d0, d2
	vabal.u8  q15, d1, d3
	
	vabdl.u8  q13, d0, d4
	vabal.u8  q13, d1, d5
	
	vabdl.u8  q11, d0, d6
	vabal.u8  q11, d1, d7
	
	vabdl.u8  q9, d0, d8
	vabal.u8  q9, d1, d9			
	
	mov lr, #7
pixel_sad_4_16x8_loop_0:

    //Loading a horizontal line data (16 bytes)
	vld1.8 {q0}, [r0], r1 //save pix1
	vmov.8 q1,   q6       //save pix2 - stride
	vmov.8 q6,   q2
	vabal.u8  q15, d0, d2
	vld1.8 {q2}, [r2], r3 //save pix2 + stride
	vabal.u8  q15, d1, d3
	vld1.8 {q3}, [r4], r3 //save pix2 - 1
	vabal.u8  q13, d0, d4
	vld1.8 {q4}, [r5], r3 //save pix2 + 1	
    vabal.u8  q13, d1, d5
	subs lr, #1

	vabal.u8  q11, d0, d6
	vabal.u8  q11, d1, d7
	
	vabal.u8  q9, d0, d8
	vabal.u8  q9, d1, d9
	
	bne pixel_sad_4_16x8_loop_0

    //Save SAD to 'r0'
	ldr   r0, [sp, #12]
	
	vadd.u16   d0, d30, d31
	vadd.u16   d1, d26, d27
	vadd.u16   d2, d22, d23
	vadd.u16   d3, d18, d19
	
	vpaddl.u16 q0, q0
	vpaddl.u16 q1, q1
	
	vpaddl.u32 q0, q0
	vpaddl.u32 q1, q1
		
	vshl.u32   q0, #4
	vshl.u32   q1, #4
	vst4.32    {d0[0],d1[0],d2[0],d3[0]}, [r0]
	
	ldmia sp!, {r4-r5, lr}
WELS_ASM_FUNC_END

 
WELS_ASM_FUNC_BEGIN pixel_sad_4_8x16_neon
    stmdb sp!, {r4-r5, lr}
	
	//Generate the pix2 start addr
	sub   r4, r2, #1
	add   r5, r2, #1
	sub   r2, r3
			
    //Loading a horizontal line data (8 bytes)
	vld1.8 {d0}, [r0], r1 //save pix1
	
	vld1.8 {d1}, [r2], r3 //save pix2 - stride
	vld1.8 {d6}, [r2], r3 //save pix2
	vld1.8 {d2}, [r2], r3 //save pix2 + stride
	
	vld1.8 {d3}, [r4], r3 //save pix2 - 1
	vld1.8 {d4}, [r5], r3 //save pix2 + 1	
		    
	//Do the SAD for 8 bytes
	vabdl.u8  q15, d0, d1
	vabdl.u8  q14, d0, d2
	vabdl.u8  q13, d0, d3
	vabdl.u8  q12, d0, d4		
	
	mov lr, #15
pixel_sad_4_8x16_loop_0:
	
    //Loading a horizontal line data (8 bytes)
	vld1.8 {d0}, [r0], r1 //save pix1
	vmov.8 d1,   d6       //save pix2 - stride
	vmov.8 d6,   d2
	vld1.8 {d2}, [r2], r3 //save pix2 + stride
	vld1.8 {d3}, [r4], r3 //save pix2 - 1
	vabal.u8  q15, d0, d1
	
	vld1.8 {d4}, [r5], r3 //save pix2 + 1
	//Do the SAD for 8 bytes
	vabal.u8  q14, d0, d2
	vabal.u8  q13, d0, d3
	vabal.u8  q12, d0, d4
    subs lr, #1

	bne pixel_sad_4_8x16_loop_0

    //Save SAD to 'r0'
	ldr   r0, [sp, #12]
	
	vadd.u16   d0, d30, d31
	vadd.u16   d1, d28, d29
	vadd.u16   d2, d26, d27
	vadd.u16   d3, d24, d25
	
	vpaddl.u16 q0, q0
	vpaddl.u16 q1, q1
	
	vpaddl.u32 q0, q0
	vpaddl.u32 q1, q1
		
	vshl.u32   q0, #4
	vshl.u32   q1, #4
	vst4.32    {d0[0],d1[0],d2[0],d3[0]}, [r0]
	
	ldmia sp!, {r4-r5, lr}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_sad_4_8x8_neon
	stmdb sp!, {r4-r5, lr}
	
	//Generate the pix2 start addr
	sub   r4, r2, #1
	add   r5, r2, #1
	sub   r2, r3
			
    //Loading a horizontal line data (8 bytes)
	vld1.8 {d0}, [r0], r1 //save pix1
	
	vld1.8 {d1}, [r2], r3 //save pix2 - stride
	vld1.8 {d6}, [r2], r3 //save pix2
	vld1.8 {d2}, [r2], r3 //save pix2 + stride
	
	vld1.8 {d3}, [r4], r3 //save pix2 - 1
	vld1.8 {d4}, [r5], r3 //save pix2 + 1	
		    
	//Do the SAD for 8 bytes
	vabdl.u8  q15, d0, d1
	vabdl.u8  q14, d0, d2
	vabdl.u8  q13, d0, d3
	vabdl.u8  q12, d0, d4		
	
	mov lr, #7
pixel_sad_4_8x8_loop_0:

    //Loading a horizontal line data (8 bytes)
	vld1.8 {d0}, [r0], r1 //save pix1
	vmov.8 d1,   d6       //save pix2 - stride
	vmov.8 d6,   d2
	vld1.8 {d2}, [r2], r3 //save pix2 + stride
	vld1.8 {d3}, [r4], r3 //save pix2 - 1
	vabal.u8  q15, d0, d1
	
	vld1.8 {d4}, [r5], r3 //save pix2 + 1
	//Do the SAD for 8 bytes
	vabal.u8  q14, d0, d2
	vabal.u8  q13, d0, d3
	vabal.u8  q12, d0, d4
    subs lr, #1
	bne pixel_sad_4_8x8_loop_0

    //Save SAD to 'r0'
	ldr   r0, [sp, #12]
	
	vadd.u16   d0, d30, d31
	vadd.u16   d1, d28, d29
	vadd.u16   d2, d26, d27
	vadd.u16   d3, d24, d25
	
	vpaddl.u16 q0, q0
	vpaddl.u16 q1, q1
	
	vpaddl.u32 q0, q0
	vpaddl.u32 q1, q1
		
	vshl.u32   q0, #4
	vshl.u32   q1, #4
	vst4.32    {d0[0],d1[0],d2[0],d3[0]}, [r0]
	
	ldmia sp!, {r4-r5, lr}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_sad_4_4x4_neon

	vld1.32  {d0[0]}, [r0], r1
	vld1.32  {d0[1]}, [r0], r1
	vld1.32  {d1[0]}, [r0], r1
	vld1.32  {d1[1]}, [r0]
	
	
	sub   r0, r2, r3
	vld1.32  {d2[0]}, [r0], r3
	vld1.32  {d2[1]}, [r0], r3
	vld1.32  {d3[0]}, [r0], r3
	vld1.32  {d3[1]}, [r0], r3
	vld1.32  {d4[0]}, [r0], r3
	vld1.32  {d4[1]}, [r0]		
					
	sub   r0,  r2, #1				
	vld1.32  {d5[0]}, [r0], r3
	vld1.32  {d5[1]}, [r0], r3
	vld1.32  {d6[0]}, [r0], r3
	vld1.32  {d6[1]}, [r0]	
	
	add   r0,  r2, #1				
	vld1.32  {d7[0]}, [r0], r3
	vld1.32  {d7[1]}, [r0], r3
	vld1.32  {d8[0]}, [r0], r3
	vld1.32  {d8[1]}, [r0]
	
	vabdl.u8  q15, d0, d2
	vabdl.u8  q14, d1, d3
	
	vabdl.u8  q13, d0, d3
	vabdl.u8  q12, d1, d4
	
	vabdl.u8  q11, d0, d5
	vabdl.u8  q10, d1, d6
	
	vabdl.u8  q9, d0, d7
	vabdl.u8  q8, d1, d8
	
	//Save SAD to 'r4'
	ldr   r0, [sp]
	vadd.u16   q0, q14, q15
	vadd.u16   q1, q12, q13
	vadd.u16   q2, q10, q11
	vadd.u16   q3, q8 , q9
	
	vadd.u16   d0, d1
	vadd.u16   d1, d2, d3
	vadd.u16   d2, d4, d5
	vadd.u16   d3, d6, d7
	
	vpaddl.u16 q0, q0
	vpaddl.u16 q1, q1
	
	vpaddl.u32 q0, q0
	vpaddl.u32 q1, q1
		
	vshl.u32   q0, #4
	vshl.u32   q1, #4
	vst4.32    {d0[0],d1[0],d2[0],d3[0]}, [r0]

WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_satd_16x16_neon

    SATD_16x4
    vadd.u16    q15,  q0, q2

    SATD_16x4
    vadd.u16    q15,  q15, q0
    vadd.u16    q15,  q15, q2

    SATD_16x4
    vadd.u16    q15,  q15, q0
    vadd.u16    q15,  q15, q2

    SATD_16x4
    vadd.u16    q15,  q15, q0
    vadd.u16    q15,  q15, q2

    vadd.u16  d0, d30, d31
    vpaddl.u16  d0, d0
    vpaddl.u32  d0, d0

    vmov.32     r0,  d0[0]
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_satd_16x8_neon

    SATD_16x4
    vadd.u16    q15,  q0, q2

    SATD_16x4
    vadd.u16    q15,  q15, q0
    vadd.u16    q15,  q15, q2

    vadd.u16  d0, d30, d31
    vpaddl.u16  d0, d0
    vpaddl.u32  d0, d0

    vmov.32     r0,  d0[0]
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_satd_8x16_neon

    SATD_8x4
    vadd.u16    q15,  q0, q1

    SATD_8x4
    vadd.u16    q15,  q15, q0
    vadd.u16    q15,  q15, q1

    SATD_8x4
    vadd.u16    q15,  q15, q0
    vadd.u16    q15,  q15, q1

    SATD_8x4
    vadd.u16    q15,  q15, q0
    vadd.u16    q15,  q15, q1

    vadd.u16  d0, d30, d31
    vpaddl.u16  d0, d0
    vpaddl.u32  d0, d0

    vmov.32     r0,  d0[0]
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_satd_8x8_neon

    SATD_8x4
    vadd.u16    q15,  q0, q1

    SATD_8x4
    vadd.u16    q15,  q15, q0
    vadd.u16    q15,  q15, q1

    vadd.u16  d0, d30, d31
    vpaddl.u16  d0, d0
    vpaddl.u32  d0, d0

    vmov.32     r0,  d0[0]
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN pixel_satd_4x4_neon

    //Load the pix1 data --- 16 bytes
	vld1.32  {d0[0]}, [r0], r1
	vld1.32  {d0[1]}, [r0], r1
	vld1.32  {d1[0]}, [r0], r1
	vld1.32  {d1[1]}, [r0]

    //Load the pix2 data --- 16 bytes	
	vld1.32  {d2[0]}, [r2], r3
	vld1.32  {d2[1]}, [r2], r3
	vld1.32  {d3[0]}, [r2], r3
	vld1.32  {d3[1]}, [r2]	

    //Get the difference
    vsubl.u8 q15, d0, d2 //{0,1,2,3,4,5,6,7}
    vsubl.u8 q14, d1, d3 //{8,9,10,11,12,13,14,15}

    //Do the vertical transform
    vadd.s16 q13, q15, q14 //{0,4,8,12,1,5,9,13}
    vsub.s16 q12, q15, q14 //{2,6,10,14,3,7,11,15}
    vswp  d27, d24
    vadd.s16 q15, q13, q12 //{0,1,2,3,4,5,6,7}
    vsub.s16 q14, q13, q12 //{12,13,14,15,8,9,10,11}

    //Do the horizontal transform
    vtrn.32 q15, q14
    vadd.s16 q13, q15, q14
    vsub.s16 q12, q15, q14

    vtrn.16 q13, q12
    vadd.s16 q15, q13, q12

    //Do the SAD	
    vabs.s16 q15, q15	
    vabd.s16 q14, q13, q12

    vadd.u16 q0, q15, q14

    vrhadd.u16 d0, d1
	vpaddl.u16 d0, d0
	vpaddl.u32 d0, d0

	vmov.u32   r0, d0[0]

WELS_ASM_FUNC_END

#endif