shithub: openh264

ref: 7c6debbef650c8a39e56673e8b4f26df1adcaa9e
dir: /codec/common/arm/mc_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"

#ifdef __APPLE__
.macro	AVERAGE_TWO_8BITS
//	{	// input:dst_d, src_d A and B; working: q13
    vaddl.u8	q13, $2, $1
    vrshrn.u16		$0, q13, #1
//	}
.endm

.macro	FILTER_6TAG_8BITS
//	{	// input:src[-2], src[-1], src[0], src[1], src[2], src[3], dst_d, multiplier a/b; working: q12, q13
    vaddl.u8	q12, $0, $5	//q12=src[-2]+src[3]
    vaddl.u8	q13, $2, $3	//src[0]+src[1]
    vmla.u16	q12, q13, $7	//q12 += 20*(src[0]+src[1]), 2 cycles
    vaddl.u8	q13, $1, $4	//src[-1]+src[2]
    vmls.s16	q12, q13, $8	//q12 -= 5*(src[-1]+src[2]), 2 cycles
    vqrshrun.s16		$6, q12, #5
//	}
.endm

.macro	FILTER_SINGLE_TAG_8BITS		// when width=17/9, used
//	{	// input: src_d{Y[0][1][2][3][4][5]X, the even of working_q2},
    vrev64.8	$2, $0				// X[5][4][3][2][1][0]O
    vaddl.u8	$3, $0, $2			// each 16bits, *[50][41][32][23][14][05]*
    vmul.s16	$0, $2, $1			// 0+1*[50]-5*[41]+20[32]
    vpadd.s16	$0, $0, $0
    vpadd.s16	$0, $0, $0
    vqrshrun.s16	$0, $4, #5
//	}
.endm

.macro	FILTER_6TAG_8BITS_AVERAGE_WITH_0
//	{	// input:src[-2], src[-1], src[0], src[1], src[2], src[3], dst_d, multiplier a/b; working: q12, q13
    vaddl.u8	q12, $0, $5	//q12=src[-2]+src[3]
    vaddl.u8	q13, $2, $3	//src[0]+src[1]
    vmla.u16	q12, q13, $7	//q12 += 20*(src[0]+src[1]), 2 cycles
    vaddl.u8	q13, $1, $4	//src[-1]+src[2]
    vmls.s16	q12, q13, $8	//q12 -= 5*(src[-1]+src[2]), 2 cycles
    vqrshrun.s16		$6, q12, #5
    vaddl.u8	q13, $2, $6
    vrshrn.u16		$6, q13, #1
//	}
.endm

.macro	FILTER_6TAG_8BITS_AVERAGE_WITH_1
//	{	// input:src[-2], src[-1], src[0], src[1], src[2], src[3], dst_d, multiplier a/b; working: q12, q13
    vaddl.u8	q12, $0, $5	//q12=src[-2]+src[3]
    vaddl.u8	q13, $2, $3	//src[0]+src[1]
    vmla.u16	q12, q13, $7	//q12 += 20*(src[0]+src[1]), 2 cycles
    vaddl.u8	q13, $1, $4	//src[-1]+src[2]
    vmls.s16	q12, q13, $8	//q12 -= 5*(src[-1]+src[2]), 2 cycles
    vqrshrun.s16		$6, q12, #5
    vaddl.u8	q13, $3, $6
    vrshrn.u16		$6, q13, #1
//	}
.endm

.macro	FILTER_6TAG_8BITS_TO_16BITS
//	{	// input:d_src[-2], d_src[-1], d_src[0], d_src[1], d_src[2], d_src[3], dst_q, multiplier a/b; working:q13
    vaddl.u8	$6, $0, $5		//dst_q=src[-2]+src[3]
    vaddl.u8	q13, $2, $3	//src[0]+src[1]
    vmla.u16	$6, q13, $7	//dst_q += 20*(src[0]+src[1]), 2 cycles
    vaddl.u8	q13, $1, $4	//src[-1]+src[2]
    vmls.s16	$6, q13, $8	//dst_q -= 5*(src[-1]+src[2]), 2 cycles
//	}
.endm

.macro	FILTER_3_IN_16BITS_TO_8BITS
//	{	// input:a, b, c, dst_d;
    vsub.s16	$0, $0, $1			//a-b
    vshr.s16	$0, $0, #2			//(a-b)/4
    vsub.s16	$0, $0, $1			//(a-b)/4-b
    vadd.s16	$0, $0, $2			//(a-b)/4-b+c
    vshr.s16	$0, $0, #2			//((a-b)/4-b+c)/4
    vadd.s16	$0, $0, $2			//((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
    vqrshrun.s16	$3, $0, #6		//(+32)>>6
//	}
.endm

.macro	UNPACK_2_16BITS_TO_ABC
//	{	// input:q_src[-2:5], q_src[6:13](avail 8+5)/q_src[6:**](avail 4+5), dst_a, dst_b, dst_c;
    vext.16	$4, $0, $1, #2		//src[0]
    vext.16	$3, $0, $1, #3		//src[1]
    vadd.s16	$4, $3					//c=src[0]+src[1]

    vext.16	$3, $0, $1, #1		//src[-1]
    vext.16	$2, $0, $1, #4		//src[2]
    vadd.s16	$3, $2					//b=src[-1]+src[2]

    vext.16	$2, $0, $1, #5		//src[3]
    vadd.s16	$2, $0					//a=src[-2]+src[3]
//	}
.endm

.macro	UNPACK_1_IN_8x16BITS_TO_8BITS
//	{	// each 16bits; input: d_dst, d_src[0:3] (even), d_src[4:5]+%% (odd)
    vext.16	$3, $3, $3, #7	// 0x????, [0][1][2][3][4][5],
    vrev64.16	$1, $1
    vadd.u16	$2, $1				// C[2+3],B[1+4],A[0+5],
    vshr.s64	$1, $2, #16
    vshr.s64	$0, $2, #32		// Output: C $2, B $1, A $0

    vsub.s16	$0, $0, $1			//a-b
    vshr.s16	$0, $0, #2			//(a-b)/4
    vsub.s16	$0, $0, $1			//(a-b)/4-b
    vadd.s16	$0, $0, $2			//(a-b)/4-b+c
    vshr.s16	$0, $0, #2			//((a-b)/4-b+c)/4
    vadd.s16	$1, $0, $2			//((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
    vqrshrun.s16	$0, $3, #6		//(+32)>>6
//	}
.endm
#else
.macro	AVERAGE_TWO_8BITS arg0, arg1, arg2
//	{	// input:dst_d, src_d A and B; working: q13
    vaddl.u8	q13, \arg2, \arg1
    vrshrn.u16		\arg0, q13, #1
//	}
.endm

.macro	FILTER_6TAG_8BITS arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
//	{	// input:src[-2], src[-1], src[0], src[1], src[2], src[3], dst_d, multiplier a/b; working: q12, q13
    vaddl.u8	q12, \arg0, \arg5	//q12=src[-2]+src[3]
    vaddl.u8	q13, \arg2, \arg3	//src[0]+src[1]
    vmla.u16	q12, q13, \arg7	//q12 += 20*(src[0]+src[1]), 2 cycles
    vaddl.u8	q13, \arg1, \arg4	//src[-1]+src[2]
    vmls.s16	q12, q13, \arg8	//q12 -= 5*(src[-1]+src[2]), 2 cycles
    vqrshrun.s16		\arg6, q12, #5
//	}
.endm

.macro	FILTER_SINGLE_TAG_8BITS arg0, arg1,arg2, arg3, arg4,arg5		// when width=17/9, used
//	{	// input: src_d{Y[0][1][2][3][4][5]X, the even of working_q2}
    vrev64.8	\arg2, \arg0				// X[5][4][3][2][1][0]O
    vaddl.u8	\arg3, \arg0, \arg2			// each 16bits, *[50][41][32][23][14][05]*
    vmul.s16	\arg0, \arg2, \arg1			// 0+1*[50]-5*[41]+20[32]
    vpadd.s16	\arg0, \arg0, \arg0
    vpadd.s16	\arg0, \arg0, \arg0
    vqrshrun.s16	\arg0, \arg4, #5
//	}
.endm

.macro	FILTER_6TAG_8BITS_AVERAGE_WITH_0 arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
//	{	// input:src[-2], src[-1], src[0], src[1], src[2], src[3], dst_d, multiplier a/b; working: q12, q13
    vaddl.u8	q12, \arg0, \arg5	//q12=src[-2]+src[3]
    vaddl.u8	q13, \arg2, \arg3	//src[0]+src[1]
    vmla.u16	q12, q13, \arg7	//q12 += 20*(src[0]+src[1]), 2 cycles
    vaddl.u8	q13, \arg1, \arg4	//src[-1]+src[2]
    vmls.s16	q12, q13, \arg8	//q12 -= 5*(src[-1]+src[2]), 2 cycles
    vqrshrun.s16		\arg6, q12, #5
    vaddl.u8	q13, \arg2, \arg6
    vrshrn.u16		\arg6, q13, #1
//	}
.endm

.macro	FILTER_6TAG_8BITS_AVERAGE_WITH_1 arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
//	{	// input:src[-2], src[-1], src[0], src[1], src[2], src[3], dst_d, multiplier a/b; working: q12, q13
    vaddl.u8	q12, \arg0, \arg5	//q12=src[-2]+src[3]
    vaddl.u8	q13, \arg2, \arg3	//src[0]+src[1]
    vmla.u16	q12, q13, \arg7	//q12 += 20*(src[0]+src[1]), 2 cycles
    vaddl.u8	q13, \arg1, \arg4	//src[-1]+src[2]
    vmls.s16	q12, q13, \arg8	//q12 -= 5*(src[-1]+src[2]), 2 cycles
    vqrshrun.s16		\arg6, q12, #5
    vaddl.u8	q13, \arg3, \arg6
    vrshrn.u16		\arg6, q13, #1
//	}
.endm

.macro	FILTER_6TAG_8BITS_TO_16BITS arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
//	{	// input:d_src[-2], d_src[-1], d_src[0], d_src[1], d_src[2], d_src[3], dst_q, multiplier a/b; working:q13
    vaddl.u8	\arg6, \arg0, \arg5		//dst_q=src[-2]+src[3]
    vaddl.u8	q13, \arg2, \arg3	//src[0]+src[1]
    vmla.u16	\arg6, q13, \arg7	//dst_q += 20*(src[0]+src[1]), 2 cycles
    vaddl.u8	q13, \arg1, \arg4	//src[-1]+src[2]
    vmls.s16	\arg6, q13, \arg8	//dst_q -= 5*(src[-1]+src[2]), 2 cycles
//	}
.endm

.macro	FILTER_3_IN_16BITS_TO_8BITS arg0, arg1, arg2, arg3
//	{	// input:a, b, c, dst_d;
    vsub.s16	\arg0, \arg0, \arg1			//a-b
    vshr.s16	\arg0, \arg0, #2			//(a-b)/4
    vsub.s16	\arg0, \arg0, \arg1			//(a-b)/4-b
    vadd.s16	\arg0, \arg0, \arg2			//(a-b)/4-b+c
    vshr.s16	\arg0, \arg0, #2			//((a-b)/4-b+c)/4
    vadd.s16	\arg0, \arg0, \arg2			//((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
    vqrshrun.s16	\arg3, \arg0, #6		//(+32)>>6
//	}
.endm

.macro	UNPACK_2_16BITS_TO_ABC arg0, arg1, arg2, arg3, arg4
//	{	// input:q_src[-2:5], q_src[6:13](avail 8+5)/q_src[6:**](avail 4+5), dst_a, dst_b, dst_c;
    vext.16	\arg4, \arg0, \arg1, #2		//src[0]
    vext.16	\arg3, \arg0, \arg1, #3		//src[1]
    vadd.s16	\arg4, \arg3					//c=src[0]+src[1]

    vext.16	\arg3, \arg0, \arg1, #1		//src[-1]
    vext.16	\arg2, \arg0, \arg1, #4		//src[2]
    vadd.s16	\arg3,\arg2					//b=src[-1]+src[2]

    vext.16	\arg2, \arg0, \arg1, #5		//src[3]
    vadd.s16	\arg2, \arg0					//a=src[-2]+src[3]
//	}
.endm

.macro	UNPACK_1_IN_8x16BITS_TO_8BITS arg0, arg1,arg2, arg3
//	{	// each 16bits; input: d_dst, d_src[0:3] (even), d_src[4:5]+%% (odd)
    vext.16	\arg3, \arg3, \arg3, #7	// 0x????, [0][1][2][3][4][5]
    vrev64.16	\arg1, \arg1
    vadd.u16	\arg2, \arg1				// C[2+3],B[1+4],A[0+5]
    vshr.s64	\arg1, \arg2, #16
    vshr.s64	\arg0, \arg2, #32		// Output: C \arg2, B \arg1, A \arg0

    vsub.s16	\arg0, \arg0, \arg1			//a-b
    vshr.s16	\arg0, \arg0, #2			//(a-b)/4
    vsub.s16	\arg0, \arg0, \arg1			//(a-b)/4-b
    vadd.s16	\arg0, \arg0, \arg2			//(a-b)/4-b+c
    vshr.s16	\arg0, \arg0, #2			//((a-b)/4-b+c)/4
    vadd.s16	\arg1, \arg0, \arg2			//((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
    vqrshrun.s16	\arg0, \arg3, #6		//(+32)>>6
//	}
.endm
#endif

WELS_ASM_FUNC_BEGIN McHorVer20WidthEq16_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, #2
	vmov.u16	q14, #0x0014				// 20
	vshr.u16	q15, q14, #2				// 5

w16_h_mc_luma_loop:
	vld1.u8	{d0,d1,d2}, [r0], r1	//only use 21(16+5); q0=src[-2]
	pld			[r0]
	pld			[r0, #16]

	vext.8		q2, q0, q1, #1		//q2=src[-1]
	vext.8		q3, q0, q1, #2		//q3=src[0]
	vext.8		q8, q0, q1, #3		//q8=src[1]
	vext.8		q9, q0, q1, #4		//q9=src[2]
	vext.8		q10, q0, q1, #5		//q10=src[3]

	FILTER_6TAG_8BITS 	d0, d4, d6, d16, d18, d20, d2, q14, q15

	FILTER_6TAG_8BITS 	d1, d5, d7, d17, d19, d21, d3, q14, q15

	sub		r4, #1
	vst1.u8	{d2, d3}, [r2], r3		//write 16Byte

	cmp		r4, #0
	bne		w16_h_mc_luma_loop
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer20WidthEq8_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, #2
	vmov.u16	q14, #0x0014				// 20
	vshr.u16	q15, q14, #2				// 5

w8_h_mc_luma_loop:
	vld1.u8	{d0,d1}, [r0], r1	//only use 13(8+5); q0=src[-2]
	pld			[r0]

	vext.8		d2, d0, d1, #1		//d2=src[-1]
	vext.8		d3, d0, d1, #2		//d3=src[0]
	vext.8		d4, d0, d1, #3		//d4=src[1]
	vext.8		d5, d0, d1, #4		//d5=src[2]
	vext.8		d6, d0, d1, #5		//d6=src[3]

	FILTER_6TAG_8BITS 	d0, d2, d3, d4, d5, d6, d1, q14, q15

	sub		r4, #1
	vst1.u8	{d1}, [r2], r3

	cmp		r4, #0
	bne		w8_h_mc_luma_loop
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer20WidthEq4_neon
	push		{r4, r5, r6}
	ldr			r6, [sp, #12]

	sub			r0, #2
	vmov.u16	q14, #0x0014				// 20
	vshr.u16	q15, q14, #2				// 5

w4_h_mc_luma_loop:
	vld1.u8	{d0, d1}, [r0], r1	//only use 9(4+5);d0: 1st row src[-2:5]
	pld			[r0]
	vld1.u8	{d2, d3}, [r0], r1	//d2: 2nd row src[-2:5]
	pld			[r0]

	vext.8		d4, d0, d1, #1		//d4: 1st row src[-1:6]
	vext.8		d5, d2, d3, #1		//d5: 2nd row src[-1:6]
	vext.8		q3, q2, q2, #1		//src[0:6 *]
	vext.8		q8, q2, q2, #2		//src[1:6 * *]

	vtrn.32	q3, q8					//q3::d6:1st row [0:3]+[1:4]; d7:2nd row [0:3]+[1:4]
	vtrn.32	d6, d7					//d6:[0:3]; d7[1:4]
	vtrn.32		d0, d2				//d0:[-2:1]; d2[2:5]
	vtrn.32		d4, d5				//d4:[-1:2]; d5[3:6]

	FILTER_6TAG_8BITS 	d0, d4, d6, d7, d2, d5, d1, q14, q15

	vmov		r4, r5, d1
	str	r4, [r2], r3
	str	r5, [r2], r3

	sub		r6, #2
	cmp		r6, #0
	bne		w4_h_mc_luma_loop

	pop		{r4, r5, r6}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer10WidthEq16_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, #2
	vmov.u16	q14, #0x0014				// 20
	vshr.u16	q15, q14, #2				// 5

w16_xy_10_mc_luma_loop:
	vld1.u8	{d0,d1,d2}, [r0], r1	//only use 21(16+5); q0=src[-2]
	pld			[r0]
	pld			[r0, #16]

	vext.8		q2, q0, q1, #1		//q2=src[-1]
	vext.8		q3, q0, q1, #2		//q3=src[0]
	vext.8		q8, q0, q1, #3		//q8=src[1]
	vext.8		q9, q0, q1, #4		//q9=src[2]
	vext.8		q10, q0, q1, #5		//q10=src[3]

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d0, d4, d6, d16, d18, d20, d2, q14, q15

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d1, d5, d7, d17, d19, d21, d3, q14, q15

	sub		r4, #1
	vst1.u8	{d2, d3}, [r2], r3		//write 16Byte

	cmp		r4, #0
	bne		w16_xy_10_mc_luma_loop
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer10WidthEq8_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, #2
	vmov.u16	q14, #0x0014				// 20
	vshr.u16	q15, q14, #2				// 5

w8_xy_10_mc_luma_loop:
	vld1.u8	{d0,d1}, [r0], r1	//only use 13(8+5); q0=src[-2]
	pld			[r0]

	vext.8		d2, d0, d1, #1		//d2=src[-1]
	vext.8		d3, d0, d1, #2		//d3=src[0]
	vext.8		d4, d0, d1, #3		//d4=src[1]
	vext.8		d5, d0, d1, #4		//d5=src[2]
	vext.8		d6, d0, d1, #5		//d6=src[3]

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d0, d2, d3, d4, d5, d6, d1, q14, q15

	sub		r4, #1
	vst1.u8	{d1}, [r2], r3

	cmp		r4, #0
	bne		w8_xy_10_mc_luma_loop
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer10WidthEq4_neon
	push		{r4, r5, r6}
	ldr			r6, [sp, #12]

	sub			r0, #2
	vmov.u16	q14, #0x0014				// 20
	vshr.u16	q15, q14, #2				// 5

w4_xy_10_mc_luma_loop:
	vld1.u8	{d0, d1}, [r0], r1	//only use 9(4+5);d0: 1st row src[-2:5]
	pld			[r0]
	vld1.u8	{d2, d3}, [r0], r1	//d2: 2nd row src[-2:5]
	pld			[r0]

	vext.8		d4, d0, d1, #1		//d4: 1st row src[-1:6]
	vext.8		d5, d2, d3, #1		//d5: 2nd row src[-1:6]
	vext.8		q3, q2, q2, #1		//src[0:6 *]
	vext.8		q8, q2, q2, #2		//src[1:6 * *]

	vtrn.32	q3, q8					//q3::d6:1st row [0:3]+[1:4]; d7:2nd row [0:3]+[1:4]
	vtrn.32	d6, d7					//d6:[0:3]; d7[1:4]
	vtrn.32		d0, d2				//d0:[-2:1]; d2[2:5]
	vtrn.32		d4, d5				//d4:[-1:2]; d5[3:6]

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d0, d4, d6, d7, d2, d5, d1, q14, q15

	vmov		r4, r5, d1
	str	r4, [r2], r3
	str	r5, [r2], r3

	sub		r6, #2
	cmp		r6, #0
	bne		w4_xy_10_mc_luma_loop

	pop		{r4, r5, r6}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer30WidthEq16_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, #2
	vmov.u16	q14, #0x0014				// 20
	vshr.u16	q15, q14, #2				// 5

w16_xy_30_mc_luma_loop:
	vld1.u8	{d0,d1,d2}, [r0], r1	//only use 21(16+5); q0=src[-2]
	pld			[r0]
	pld			[r0, #16]

	vext.8		q2, q0, q1, #1		//q2=src[-1]
	vext.8		q3, q0, q1, #2		//q3=src[0]
	vext.8		q8, q0, q1, #3		//q8=src[1]
	vext.8		q9, q0, q1, #4		//q9=src[2]
	vext.8		q10, q0, q1, #5		//q10=src[3]

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d0, d4, d6, d16, d18, d20, d2, q14, q15

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d1, d5, d7, d17, d19, d21, d3, q14, q15

	sub		r4, #1
	vst1.u8	{d2, d3}, [r2], r3		//write 16Byte

	cmp		r4, #0
	bne		w16_xy_30_mc_luma_loop
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer30WidthEq8_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, #2
	vmov.u16	q14, #0x0014				// 20
	vshr.u16	q15, q14, #2				// 5

w8_xy_30_mc_luma_loop:
	vld1.u8	{d0,d1}, [r0], r1	//only use 13(8+5); q0=src[-2]
	pld			[r0]

	vext.8		d2, d0, d1, #1		//d2=src[-1]
	vext.8		d3, d0, d1, #2		//d3=src[0]
	vext.8		d4, d0, d1, #3		//d4=src[1]
	vext.8		d5, d0, d1, #4		//d5=src[2]
	vext.8		d6, d0, d1, #5		//d6=src[3]

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d0, d2, d3, d4, d5, d6, d1, q14, q15

	sub		r4, #1
	vst1.u8	{d1}, [r2], r3

	cmp		r4, #0
	bne		w8_xy_30_mc_luma_loop
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer30WidthEq4_neon
	push		{r4, r5, r6}
	ldr			r6, [sp, #12]

	sub			r0, #2
	vmov.u16	q14, #0x0014				// 20
	vshr.u16	q15, q14, #2				// 5

w4_xy_30_mc_luma_loop:
	vld1.u8	{d0, d1}, [r0], r1	//only use 9(4+5);d0: 1st row src[-2:5]
	pld			[r0]
	vld1.u8	{d2, d3}, [r0], r1	//d2: 2nd row src[-2:5]
	pld			[r0]

	vext.8		d4, d0, d1, #1		//d4: 1st row src[-1:6]
	vext.8		d5, d2, d3, #1		//d5: 2nd row src[-1:6]
	vext.8		q3, q2, q2, #1		//src[0:6 *]
	vext.8		q8, q2, q2, #2		//src[1:6 * *]

	vtrn.32	q3, q8					//q3::d6:1st row [0:3]+[1:4]; d7:2nd row [0:3]+[1:4]
	vtrn.32	d6, d7					//d6:[0:3]; d7[1:4]
	vtrn.32		d0, d2				//d0:[-2:1]; d2[2:5]
	vtrn.32		d4, d5				//d4:[-1:2]; d5[3:6]

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d0, d4, d6, d7, d2, d5, d1, q14, q15

	vmov		r4, r5, d1
	str	r4, [r2], r3
	str	r5, [r2], r3

	sub		r6, #2
	cmp		r6, #0
	bne		w4_xy_30_mc_luma_loop

	pop		{r4, r5, r6}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer01WidthEq16_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, r0, r1, lsl #1		//src[-2*src_stride]
	pld			[r0]
	pld			[r0, r1]
	vmov.u16	q14, #0x0014			// 20
	vld1.u8	{q0}, [r0], r1		//q0=src[-2]
	vld1.u8	{q1}, [r0], r1		//q1=src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5
	vld1.u8	{q2}, [r0], r1		//q2=src[0]
	vld1.u8	{q3}, [r0], r1		//q3=src[1]
	vld1.u8	{q8}, [r0], r1		//q8=src[2]

w16_xy_01_luma_loop:

	vld1.u8	{q9}, [r0], r1		//q9=src[3]

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d0, d2, d4, d6, d16, d18, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d1, d3, d5, d7, d17, d19, d21, q14, q15
	vld1.u8	{q0}, [r0], r1		//read 2nd row
	vst1.u8	{q10}, [r2], r3			//write 1st 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d2, d4, d6, d16, d18, d0, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d3, d5, d7, d17, d19, d1, d21, q14, q15
	vld1.u8	{q1}, [r0], r1		//read 3rd row
	vst1.u8	{q10}, [r2], r3			//write 2nd 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d4, d6, d16, d18, d0, d2, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d5, d7, d17, d19, d1, d3, d21, q14, q15
	vld1.u8	{q2}, [r0], r1		//read 4th row
	vst1.u8	{q10}, [r2], r3			//write 3rd 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d6, d16, d18, d0, d2, d4, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d7, d17, d19, d1, d3, d5, d21, q14, q15
	vld1.u8	{q3}, [r0], r1		//read 5th row
	vst1.u8	{q10}, [r2], r3			//write 4th 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d16, d18, d0, d2, d4, d6, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d17, d19, d1, d3, d5, d7, d21, q14, q15
	vld1.u8	{q8}, [r0], r1		//read 6th row
	vst1.u8	{q10}, [r2], r3			//write 5th 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d18, d0, d2, d4, d6, d16, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d19, d1, d3, d5, d7, d17, d21, q14, q15
	vld1.u8	{q9}, [r0], r1		//read 7th row
	vst1.u8	{q10}, [r2], r3			//write 6th 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d0, d2, d4, d6, d16, d18, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d1, d3, d5, d7, d17, d19, d21, q14, q15
	vld1.u8	{q0}, [r0], r1		//read 8th row
	vst1.u8	{q10}, [r2], r3			//write 7th 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d2, d4, d6, d16, d18, d0, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d3, d5, d7, d17, d19, d1, d21, q14, q15
	vst1.u8	{q10}, [r2], r3			//write 8th 16Byte

	//q2, q3, q4, q5, q0 --> q0~q4
	vswp	q0, q8
	vswp	q0, q2
	vmov	q1, q3
	vmov	q3, q9						//q0~q4

	sub		r4, #8
	cmp		r4, #0
	bne		w16_xy_01_luma_loop
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer01WidthEq8_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, r0, r1, lsl #1		//src[-2*src_stride]
	pld			[r0]
	pld			[r0, r1]
	vmov.u16	q14, #0x0014			// 20
	vld1.u8	{d0}, [r0], r1		//d0=src[-2]
	vld1.u8	{d1}, [r0], r1		//d1=src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5
	vld1.u8	{d2}, [r0], r1		//d2=src[0]
	vld1.u8	{d3}, [r0], r1		//d3=src[1]

	vld1.u8	{d4}, [r0], r1		//d4=src[2]
	vld1.u8	{d5}, [r0], r1		//d5=src[3]

w8_xy_01_mc_luma_loop:

	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d0, d1, d2, d3, d4, d5, d16, q14, q15
	vld1.u8	{d0}, [r0], r1		//read 2nd row
	vst1.u8	{d16}, [r2], r3		//write 1st 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d1, d2, d3, d4, d5, d0, d16, q14, q15
	vld1.u8	{d1}, [r0], r1		//read 3rd row
	vst1.u8	{d16}, [r2], r3		//write 2nd 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d2, d3, d4, d5, d0, d1, d16, q14, q15
	vld1.u8	{d2}, [r0], r1		//read 4th row
	vst1.u8	{d16}, [r2], r3		//write 3rd 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d3, d4, d5, d0, d1, d2, d16, q14, q15
	vld1.u8	{d3}, [r0], r1		//read 5th row
	vst1.u8	{d16}, [r2], r3		//write 4th 8Byte

	//d4, d5, d0, d1, d2, d3 --> d0, d1, d2, d3, d4, d5
	vswp	q0, q2
	vswp	q1, q2

	sub		r4, #4
	cmp		r4, #0
	bne		w8_xy_01_mc_luma_loop

	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer01WidthEq4_neon
	push		{r4, r5, r6, r7}
	sub			r0, r0, r1, lsl #1		//src[-2*src_stride]
	pld			[r0]
	pld			[r0, r1]
	vmov.u16	q14, #0x0014			// 20
	ldr		r4, [r0], r1		//r4=src[-2]
	ldr		r5, [r0], r1		//r5=src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5
	ldr		r6, [r0], r1		//r6=src[0]
	ldr		r7, [r0], r1		//r7=src[1]

	vmov		d0, r4, r5
	vmov		d1, r5, r6
	vmov		d2, r6, r7

	ldr		r4, [r0], r1		//r4=src[2]
	vmov		d3, r7, r4
	ldr			r7, [sp, #16]

w4_xy_01_mc_luma_loop:

//	pld			[r0]
	//using reserving r4
	ldr		r5, [r0], r1		//r5=src[3]
	ldr		r6, [r0], r1		//r6=src[0]
	vmov		d4, r4, r5
	vmov		d5, r5, r6			//reserved r6

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d0, d1, d2, d3, d4, d5, d16, q14, q15
	vmov		r4, r5, d16
	str	r4, [r2], r3			//write 1st 4Byte
	str	r5, [r2], r3			//write 2nd 4Byte

	ldr		r5, [r0], r1		//r5=src[1]
	ldr		r4, [r0], r1		//r4=src[2]
	vmov		d0, r6, r5
	vmov		d1, r5, r4			//reserved r4

	FILTER_6TAG_8BITS_AVERAGE_WITH_0 	d2, d3, d4, d5, d0, d1, d16, q14, q15
	vmov		r5, r6, d16
	str	r5, [r2], r3			//write 3rd 4Byte
	str	r6, [r2], r3			//write 4th 4Byte

	//d4, d5, d0, d1 --> d0, d1, d2, d3
	vmov	q1, q0
	vmov	q0, q2

	sub		r7, #4
	cmp		r7, #0
	bne		w4_xy_01_mc_luma_loop

	pop		{r4, r5, r6, r7}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer03WidthEq16_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, r0, r1, lsl #1		//src[-2*src_stride]
	pld			[r0]
	pld			[r0, r1]
	vmov.u16	q14, #0x0014			// 20
	vld1.u8	{q0}, [r0], r1		//q0=src[-2]
	vld1.u8	{q1}, [r0], r1		//q1=src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5
	vld1.u8	{q2}, [r0], r1		//q2=src[0]
	vld1.u8	{q3}, [r0], r1		//q3=src[1]
	vld1.u8	{q8}, [r0], r1		//q8=src[2]

w16_xy_03_luma_loop:

	vld1.u8	{q9}, [r0], r1		//q9=src[3]

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d0, d2, d4, d6, d16, d18, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d1, d3, d5, d7, d17, d19, d21, q14, q15
	vld1.u8	{q0}, [r0], r1		//read 2nd row
	vst1.u8	{q10}, [r2], r3			//write 1st 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d2, d4, d6, d16, d18, d0, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d3, d5, d7, d17, d19, d1, d21, q14, q15
	vld1.u8	{q1}, [r0], r1		//read 3rd row
	vst1.u8	{q10}, [r2], r3			//write 2nd 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d4, d6, d16, d18, d0, d2, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d5, d7, d17, d19, d1, d3, d21, q14, q15
	vld1.u8	{q2}, [r0], r1		//read 4th row
	vst1.u8	{q10}, [r2], r3			//write 3rd 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d6, d16, d18, d0, d2, d4, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d7, d17, d19, d1, d3, d5, d21, q14, q15
	vld1.u8	{q3}, [r0], r1		//read 5th row
	vst1.u8	{q10}, [r2], r3			//write 4th 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d16, d18, d0, d2, d4, d6, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d17, d19, d1, d3, d5, d7, d21, q14, q15
	vld1.u8	{q8}, [r0], r1		//read 6th row
	vst1.u8	{q10}, [r2], r3			//write 5th 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d18, d0, d2, d4, d6, d16, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d19, d1, d3, d5, d7, d17, d21, q14, q15
	vld1.u8	{q9}, [r0], r1		//read 7th row
	vst1.u8	{q10}, [r2], r3			//write 6th 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d0, d2, d4, d6, d16, d18, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d1, d3, d5, d7, d17, d19, d21, q14, q15
	vld1.u8	{q0}, [r0], r1		//read 8th row
	vst1.u8	{q10}, [r2], r3			//write 7th 16Byte

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d2, d4, d6, d16, d18, d0, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d3, d5, d7, d17, d19, d1, d21, q14, q15
	vst1.u8	{q10}, [r2], r3			//write 8th 16Byte

	//q2, q3, q8, q9, q0 --> q0~q8
	vswp	q0, q8
	vswp	q0, q2
	vmov	q1, q3
	vmov	q3, q9						//q0~q8

	sub		r4, #8
	cmp		r4, #0
	bne		w16_xy_03_luma_loop
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer03WidthEq8_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, r0, r1, lsl #1		//src[-2*src_stride]
	pld			[r0]
	pld			[r0, r1]
	vmov.u16	q14, #0x0014			// 20
	vld1.u8	{d0}, [r0], r1		//d0=src[-2]
	vld1.u8	{d1}, [r0], r1		//d1=src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5
	vld1.u8	{d2}, [r0], r1		//d2=src[0]
	vld1.u8	{d3}, [r0], r1		//d3=src[1]

	vld1.u8	{d4}, [r0], r1		//d4=src[2]
	vld1.u8	{d5}, [r0], r1		//d5=src[3]

w8_xy_03_mc_luma_loop:

	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d0, d1, d2, d3, d4, d5, d16, q14, q15
	vld1.u8	{d0}, [r0], r1		//read 2nd row
	vst1.u8	{d16}, [r2], r3		//write 1st 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d1, d2, d3, d4, d5, d0, d16, q14, q15
	vld1.u8	{d1}, [r0], r1		//read 3rd row
	vst1.u8	{d16}, [r2], r3		//write 2nd 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d2, d3, d4, d5, d0, d1, d16, q14, q15
	vld1.u8	{d2}, [r0], r1		//read 4th row
	vst1.u8	{d16}, [r2], r3		//write 3rd 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d3, d4, d5, d0, d1, d2, d16, q14, q15
	vld1.u8	{d3}, [r0], r1		//read 5th row
	vst1.u8	{d16}, [r2], r3		//write 4th 8Byte

	//d4, d5, d0, d1, d2, d3 --> d0, d1, d2, d3, d4, d5
	vswp	q0, q2
	vswp	q1, q2

	sub		r4, #4
	cmp		r4, #0
	bne		w8_xy_03_mc_luma_loop

	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer03WidthEq4_neon
	push		{r4, r5, r6, r7}
	sub			r0, r0, r1, lsl #1		//src[-2*src_stride]
	pld			[r0]
	pld			[r0, r1]
	vmov.u16	q14, #0x0014			// 20
	ldr		r4, [r0], r1		//r4=src[-2]
	ldr		r5, [r0], r1		//r5=src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5
	ldr		r6, [r0], r1		//r6=src[0]
	ldr		r7, [r0], r1		//r7=src[1]

	vmov		d0, r4, r5
	vmov		d1, r5, r6
	vmov		d2, r6, r7

	ldr		r4, [r0], r1		//r4=src[2]
	vmov		d3, r7, r4
	ldr			r7, [sp, #16]

w4_xy_03_mc_luma_loop:

//	pld			[r0]
	//using reserving r4
	ldr		r5, [r0], r1		//r5=src[3]
	ldr		r6, [r0], r1		//r6=src[0]
	vmov		d4, r4, r5
	vmov		d5, r5, r6			//reserved r6

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d0, d1, d2, d3, d4, d5, d16, q14, q15
	vmov		r4, r5, d16
	str	r4, [r2], r3			//write 1st 4Byte
	str	r5, [r2], r3			//write 2nd 4Byte

	ldr		r5, [r0], r1		//r5=src[1]
	ldr		r4, [r0], r1		//r4=src[2]
	vmov		d0, r6, r5
	vmov		d1, r5, r4			//reserved r4

	FILTER_6TAG_8BITS_AVERAGE_WITH_1 	d2, d3, d4, d5, d0, d1, d16, q14, q15
	vmov		r5, r6, d16
	str	r5, [r2], r3			//write 3rd 4Byte
	str	r6, [r2], r3			//write 4th 4Byte

	//d4, d5, d0, d1 --> d0, d1, d2, d3
	vmov	q1, q0
	vmov	q0, q2

	sub		r7, #4
	cmp		r7, #0
	bne		w4_xy_03_mc_luma_loop

	pop		{r4, r5, r6, r7}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer02WidthEq16_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, r0, r1, lsl #1		//src[-2*src_stride]
	pld			[r0]
	pld			[r0, r1]
	vmov.u16	q14, #0x0014			// 20
	vld1.u8	{q0}, [r0], r1		//q0=src[-2]
	vld1.u8	{q1}, [r0], r1		//q1=src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5
	vld1.u8	{q2}, [r0], r1		//q2=src[0]
	vld1.u8	{q3}, [r0], r1		//q3=src[1]
	vld1.u8	{q8}, [r0], r1		//q8=src[2]

w16_v_mc_luma_loop:

	vld1.u8	{q9}, [r0], r1		//q9=src[3]

	FILTER_6TAG_8BITS 	d0, d2, d4, d6, d16, d18, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d1, d3, d5, d7, d17, d19, d21, q14, q15
	vld1.u8	{q0}, [r0], r1		//read 2nd row
	vst1.u8	{q10}, [r2], r3			//write 1st 16Byte

	FILTER_6TAG_8BITS 	d2, d4, d6, d16, d18, d0, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d3, d5, d7, d17, d19, d1, d21, q14, q15
	vld1.u8	{q1}, [r0], r1		//read 3rd row
	vst1.u8	{q10}, [r2], r3			//write 2nd 16Byte

	FILTER_6TAG_8BITS 	d4, d6, d16, d18, d0, d2, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d5, d7, d17, d19, d1, d3, d21, q14, q15
	vld1.u8	{q2}, [r0], r1		//read 4th row
	vst1.u8	{q10}, [r2], r3			//write 3rd 16Byte

	FILTER_6TAG_8BITS 	d6, d16, d18, d0, d2, d4, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d7, d17, d19, d1, d3, d5, d21, q14, q15
	vld1.u8	{q3}, [r0], r1		//read 5th row
	vst1.u8	{q10}, [r2], r3			//write 4th 16Byte

	FILTER_6TAG_8BITS 	d16, d18, d0, d2, d4, d6, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d17, d19, d1, d3, d5, d7, d21, q14, q15
	vld1.u8	{q8}, [r0], r1		//read 6th row
	vst1.u8	{q10}, [r2], r3			//write 5th 16Byte

	FILTER_6TAG_8BITS 	d18, d0, d2, d4, d6, d16, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d19, d1, d3, d5, d7, d17, d21, q14, q15
	vld1.u8	{q9}, [r0], r1		//read 7th row
	vst1.u8	{q10}, [r2], r3			//write 6th 16Byte

	FILTER_6TAG_8BITS 	d0, d2, d4, d6, d16, d18, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d1, d3, d5, d7, d17, d19, d21, q14, q15
	vld1.u8	{q0}, [r0], r1		//read 8th row
	vst1.u8	{q10}, [r2], r3			//write 7th 16Byte

	FILTER_6TAG_8BITS 	d2, d4, d6, d16, d18, d0, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d3, d5, d7, d17, d19, d1, d21, q14, q15
	vst1.u8	{q10}, [r2], r3			//write 8th 16Byte

	//q2, q3, q8, q9, q0 --> q0~q8
	vswp	q0, q8
	vswp	q0, q2
	vmov	q1, q3
	vmov	q3, q9						//q0~q8

	sub		r4, #8
	cmp		r4, #0
	bne		w16_v_mc_luma_loop
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer02WidthEq8_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, r0, r1, lsl #1		//src[-2*src_stride]
	pld			[r0]
	pld			[r0, r1]
	vmov.u16	q14, #0x0014			// 20
	vld1.u8	{d0}, [r0], r1		//d0=src[-2]
	vld1.u8	{d1}, [r0], r1		//d1=src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5
	vld1.u8	{d2}, [r0], r1		//d2=src[0]
	vld1.u8	{d3}, [r0], r1		//d3=src[1]

	vld1.u8	{d4}, [r0], r1		//d4=src[2]
	vld1.u8	{d5}, [r0], r1		//d5=src[3]

w8_v_mc_luma_loop:

	pld			[r0]
	FILTER_6TAG_8BITS 	d0, d1, d2, d3, d4, d5, d16, q14, q15
	vld1.u8	{d0}, [r0], r1		//read 2nd row
	vst1.u8	{d16}, [r2], r3		//write 1st 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS 	d1, d2, d3, d4, d5, d0, d16, q14, q15
	vld1.u8	{d1}, [r0], r1		//read 3rd row
	vst1.u8	{d16}, [r2], r3		//write 2nd 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS 	d2, d3, d4, d5, d0, d1, d16, q14, q15
	vld1.u8	{d2}, [r0], r1		//read 4th row
	vst1.u8	{d16}, [r2], r3		//write 3rd 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS 	d3, d4, d5, d0, d1, d2, d16, q14, q15
	vld1.u8	{d3}, [r0], r1		//read 5th row
	vst1.u8	{d16}, [r2], r3		//write 4th 8Byte

	//d4, d5, d0, d1, d2, d3 --> d0, d1, d2, d3, d4, d5
	vswp	q0, q2
	vswp	q1, q2

	sub		r4, #4
	cmp		r4, #0
	bne		w8_v_mc_luma_loop

	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer02WidthEq4_neon
	push		{r4, r5, r6, r7}
	sub			r0, r0, r1, lsl #1		//src[-2*src_stride]
	pld			[r0]
	pld			[r0, r1]
	vmov.u16	q14, #0x0014			// 20
	ldr		r4, [r0], r1		//r4=src[-2]
	ldr		r5, [r0], r1		//r5=src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5
	ldr		r6, [r0], r1		//r6=src[0]
	ldr		r7, [r0], r1		//r7=src[1]

	vmov		d0, r4, r5
	vmov		d1, r5, r6
	vmov		d2, r6, r7

	ldr		r4, [r0], r1		//r4=src[2]
	vmov		d3, r7, r4
	ldr			r7, [sp, #16]

w4_v_mc_luma_loop:

//	pld			[r0]
	//using reserving r4
	ldr		r5, [r0], r1		//r5=src[3]
	ldr		r6, [r0], r1		//r6=src[0]
	vmov		d4, r4, r5
	vmov		d5, r5, r6			//reserved r6

	FILTER_6TAG_8BITS 	d0, d1, d2, d3, d4, d5, d16, q14, q15
	vmov		r4, r5, d16
	str	r4, [r2], r3			//write 1st 4Byte
	str	r5, [r2], r3			//write 2nd 4Byte

	ldr		r5, [r0], r1		//r5=src[1]
	ldr		r4, [r0], r1		//r4=src[2]
	vmov		d0, r6, r5
	vmov		d1, r5, r4			//reserved r4

	FILTER_6TAG_8BITS 	d2, d3, d4, d5, d0, d1, d16, q14, q15
	vmov		r5, r6, d16
	str	r5, [r2], r3			//write 3rd 4Byte
	str	r6, [r2], r3			//write 4th 4Byte

	//d4, d5, d0, d1 --> d0, d1, d2, d3
	vmov	q1, q0
	vmov	q0, q2

	sub		r7, #4
	cmp		r7, #0
	bne		w4_v_mc_luma_loop

	pop		{r4, r5, r6, r7}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer22WidthEq16_neon
	push		{r4}
	vpush		{q4-q7}
	ldr			r4, [sp, #68]

	sub			r0, #2					//src[-2]
	sub			r0, r0, r1, lsl #1		//src[-2*src_stride-2]
	pld			[r0]
	pld			[r0, r1]

	vmov.u16	q14, #0x0014			// 20
	vld1.u8	{d0-d2}, [r0], r1		//use 21(16+5), =src[-2]
	vld1.u8	{d3-d5}, [r0], r1		//use 21(16+5), =src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5

	vld1.u8	{d6-d8}, [r0], r1		//use 21(16+5), =src[0]
	vld1.u8	{d9-d11}, [r0], r1	//use 21(16+5), =src[1]
	pld			[r0]
	pld			[r0, r1]
	vld1.u8	{d12-d14}, [r0], r1	//use 21(16+5), =src[2]

w16_hv_mc_luma_loop:

	vld1.u8	{d15-d17}, [r0], r1	//use 21(16+5), =src[3]
	//the 1st row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d0, d3, d6, d9, d12, d15, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d1, d4, d7,d10, d13, d16,q10, q14, q15	// 8 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d0	//output to q0[0]

	// vertical filtered into q10/q11
	FILTER_6TAG_8BITS_TO_16BITS 	d2, d5, d8,d11, d14, d17,q11, q14, q15	// only 5 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q10, q11, q9, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q9, q12, q13, d1	//output to q0[1]
	vst1.u8	{q0}, [r2], r3		//write 16Byte


	vld1.u8	{d0-d2}, [r0], r1		//read 2nd row
	//the 2nd row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d3, d6, d9, d12, d15, d0, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d4, d7,d10, d13, d16, d1,q10, q14, q15	// 8 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d3	//output to d3

	// vertical filtered into q10/q11
	FILTER_6TAG_8BITS_TO_16BITS 	d5, d8,d11, d14, d17, d2,q11, q14, q15	// only 5 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q10, q11, q9, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q9, q12, q13, d4	//output to d4

	vst1.u8	{d3, d4}, [r2], r3		//write 16Byte

	vld1.u8	{d3-d5}, [r0], r1		//read 3rd row
	//the 3rd row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d6, d9, d12, d15, d0, d3, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d7,d10, d13, d16, d1, d4,q10, q14, q15	// 8 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d6	//output to d6

	// vertical filtered into q10/q11
	FILTER_6TAG_8BITS_TO_16BITS 	d8,d11, d14, d17, d2, d5,q11, q14, q15	// only 5 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q10, q11, q9, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q9, q12, q13, d7	//output to d7
	vst1.u8	{d6, d7}, [r2], r3		//write 16Byte

	vld1.u8	{d6-d8}, [r0], r1		//read 4th row
	//the 4th row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	 d9, d12, d15, d0, d3, d6, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS		d10, d13, d16, d1, d4, d7,q10, q14, q15	// 8 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d9	//output to d9
	// vertical filtered into q10/q11
	FILTER_6TAG_8BITS_TO_16BITS 	d11, d14, d17, d2, d5, d8,q11, q14, q15	// only 5 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q10, q11, q9, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q9, q12, q13, d10	//output to d10
	vst1.u8	{d9, d10}, [r2], r3		//write 16Byte

	//d12~d17(q6~q8), d0~d8(q0~q3+d8), --> d0~d14
	vswp	q0, q6
	vswp	q6, q3
	vmov	q5, q2
	vmov	q2, q8

	vmov	d20,d8
	vmov	q4, q1
	vmov	q1, q7
	vmov	d14,d20

	sub		r4, #4
	cmp		r4, #0
	bne		w16_hv_mc_luma_loop
	vpop		{q4-q7}
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer22WidthEq8_neon
	push		{r4}
	vpush		{q4}
	ldr			r4, [sp, #20]

	sub			r0, #2				//src[-2]
	sub			r0, r0, r1, lsl #1	//src[-2*src_stride-2]
	pld			[r0]
	pld			[r0, r1]

	vmov.u16	q14, #0x0014		// 20
	vld1.u8	{q0}, [r0], r1	//use 13(8+5), =src[-2]
	vld1.u8	{q1}, [r0], r1	//use 13(8+5), =src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2		// 5

	vld1.u8	{q2}, [r0], r1	//use 13(8+5), =src[0]
	vld1.u8	{q3}, [r0], r1	//use 13(8+5), =src[1]
	pld			[r0]
	pld			[r0, r1]
	vld1.u8	{q4}, [r0], r1	//use 13(8+5), =src[2]

w8_hv_mc_luma_loop:

	vld1.u8	{q8}, [r0], r1	//use 13(8+5), =src[3]
	//the 1st row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d0, d2, d4, d6, d8, d16, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d1, d3, d5, d7, d9, d17, q10, q14, q15	// 5 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d18	//output to q9[0]
	vst1.u8	d18, [r2], r3			//write 8Byte

	vld1.u8	{q0}, [r0], r1		//read 2nd row
	//the 2nd row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d2, d4, d6, d8, d16, d0, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d3, d5, d7, d9, d17, d1, q10, q14, q15	// 5 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d18	//output to q9[0]
	vst1.u8	d18, [r2], r3		//write 8Byte

	vld1.u8	{q1}, [r0], r1		//read 3rd row
	//the 3rd row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d4, d6, d8, d16, d0, d2, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d5, d7, d9, d17, d1, d3, q10, q14, q15	// 5 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d18	//output to q9[0]
	vst1.u8	d18, [r2], r3			//write 8Byte

	vld1.u8	{q2}, [r0], r1		//read 4th row
	//the 4th row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d6, d8, d16, d0, d2, d4, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d7, d9, d17, d1, d3, d5, q10, q14, q15	// 5 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d18	//output to q9[0]
	vst1.u8	d18, [r2], r3			//write 8Byte

	//q4~q5, q0~q2, --> q0~q4
	vswp	q0, q4
	vswp	q2, q4
	vmov	q3, q1
	vmov	q1, q8

	sub		r4, #4
	cmp		r4, #0
	bne		w8_hv_mc_luma_loop
	vpop		{q4}
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer22WidthEq4_neon
	push		{r4 ,r5, r6}
	vpush		{q4-q7}
	ldr			r6, [sp, #76]

	sub			r0, #2				//src[-2]
	sub			r0, r0, r1, lsl #1	//src[-2*src_stride-2]
	pld			[r0]
	pld			[r0, r1]

	vmov.u16	q14, #0x0014		// 20
	vld1.u8	{q0}, [r0], r1	//use 9(4+5), =src[-2]
	vld1.u8	{q1}, [r0], r1	//use 9(4+5), =src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2		// 5

	vld1.u8	{q2}, [r0], r1	//use 9(4+5), =src[0]
	vld1.u8	{q3}, [r0], r1	//use 9(4+5), =src[1]
	pld			[r0]
	pld			[r0, r1]
	vld1.u8	{q4}, [r0], r1	//use 9(4+5), =src[2]

w4_hv_mc_luma_loop:

	vld1.u8	{q5}, [r0], r1	//use 9(4+5), =src[3]
	vld1.u8	{q6}, [r0], r1	//use 9(4+5), =src[4]

	//the 1st&2nd row
	pld			[r0]
	pld			[r0, r1]
	// vertical filtered
	FILTER_6TAG_8BITS_TO_16BITS 	d0, d2, d4, d6, d8, d10, q7, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d1, d3, d5, d7, d9, d11, q8, q14, q15	// 1 avail

	FILTER_6TAG_8BITS_TO_16BITS 	d2, d4, d6, d8,d10, d12, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d3, d5, d7, d9,d11, d13,q10, q14, q15	// 1 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q7, q8, q11, q12, q13	//4 avail
	UNPACK_2_16BITS_TO_ABC	q9,q10, q0, q7, q8		//4 avail

	vmov	d23, d0
	vmov	d25, d14
	vmov	d27, d16

	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d22	//output to q11[0]
	vmov		r4 ,r5, d22
	str		r4, [r2], r3				//write 4Byte
	str		r5, [r2], r3				//write 4Byte

	//the 3rd&4th row
	vld1.u8	{q0}, [r0], r1	//use 9(4+5), =src[3]
	vld1.u8	{q1}, [r0], r1	//use 9(4+5), =src[4]
	pld			[r0]
	pld			[r0, r1]
	// vertical filtered
	FILTER_6TAG_8BITS_TO_16BITS 	d4, d6, d8, d10, d12, d0, q7, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d5, d7, d9, d11, d13, d1, q8, q14, q15	// 1 avail

	FILTER_6TAG_8BITS_TO_16BITS 	d6, d8,d10, d12, d0, d2, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d7, d9,d11, d13, d1, d3,q10, q14, q15	// 1 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q7, q8, q11, q12, q13	//4 avail
	UNPACK_2_16BITS_TO_ABC	q9,q10, q2, q7, q8		//4 avail

	vmov	d23, d4
	vmov	d25, d14
	vmov	d27, d16

	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d22	//output to q11[0]
	vmov		r4 ,r5, d22
	str		r4, [r2], r3				//write 4Byte
	str		r5, [r2], r3				//write 4Byte

	//q4~q6, q0~q1, --> q0~q4
	vswp	q4, q0
	vmov	q3, q4
	vmov	q4, q1
	vmov	q1, q5
	vmov	q2, q6

	sub		r6, #4
	cmp		r6, #0
	bne		w4_hv_mc_luma_loop

	vpop		{q4-q7}
	pop		{r4, r5, r6}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McCopyWidthEq16_neon
	push		{r4}
	ldr			r4, [sp, #4]
w16_copy_loop:
	vld1.u8		{q0}, [r0], r1
	sub			r4, #2
	vld1.u8		{q1}, [r0], r1
	vst1.u8		{q0}, [r2], r3
	cmp			r4, #0
	vst1.u8		{q1}, [r2], r3
	bne			w16_copy_loop

	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McCopyWidthEq8_neon
	push		{r4}
	ldr			r4, [sp, #4]
w8_copy_loop:
	vld1.u8		{d0}, [r0], r1
	vld1.u8		{d1}, [r0], r1
	vst1.u8		{d0}, [r2], r3
	vst1.u8		{d1}, [r2], r3
	sub			r4, #2
	cmp			r4, #0
	bne			w8_copy_loop

	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McCopyWidthEq4_neon
	push		{r4, r5, r6}
	ldr			r4, [sp, #12]
w4_copy_loop:
	ldr		r5, [r0], r1
	ldr		r6, [r0], r1
	str		r5, [r2], r3
	str		r6, [r2], r3

	sub			r4, #2
	cmp			r4, #0
	bne			w4_copy_loop

	pop		{r4, r5, r6}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN PixelAvgWidthEq16_neon
	push		{r4}
	ldr			r4, [sp, #4]
w16_pix_avg_loop:
	vld1.u8		{q0}, [r2]!
	vld1.u8		{q1}, [r3]!
	vld1.u8		{q2}, [r2]!
	vld1.u8		{q3}, [r3]!

	vld1.u8		{q8}, [r2]!
	vld1.u8		{q9}, [r3]!
	vld1.u8		{q10}, [r2]!
	vld1.u8		{q11}, [r3]!

	AVERAGE_TWO_8BITS		d0, d0, d2
	AVERAGE_TWO_8BITS		d1, d1, d3
	vst1.u8		{q0}, [r0], r1

	AVERAGE_TWO_8BITS		d4, d4, d6
	AVERAGE_TWO_8BITS		d5, d5, d7
	vst1.u8		{q2}, [r0], r1

	AVERAGE_TWO_8BITS		d16, d16, d18
	AVERAGE_TWO_8BITS		d17, d17, d19
	vst1.u8		{q8}, [r0], r1

	AVERAGE_TWO_8BITS		d20, d20, d22
	AVERAGE_TWO_8BITS		d21, d21, d23
	vst1.u8		{q10}, [r0], r1

	sub			r4, #4
	cmp			r4, #0
	bne			w16_pix_avg_loop

	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN PixelAvgWidthEq8_neon
	push		{r4, r5}
	ldr			r4, [sp, #8]
	mov			r5, #16
w8_pix_avg_loop:

	vld1.u8		{d0}, [r2], r5
	vld1.u8		{d2}, [r3], r5
	vld1.u8		{d1}, [r2], r5
	vld1.u8		{d3}, [r3], r5

	AVERAGE_TWO_8BITS		d0, d0, d2
	AVERAGE_TWO_8BITS		d1, d1, d3
	vst1.u8		{d0}, [r0], r1
	vst1.u8		{d1}, [r0], r1

	vld1.u8		{d4}, [r2], r5
	vld1.u8		{d6}, [r3], r5
	vld1.u8		{d5}, [r2], r5
	vld1.u8		{d7}, [r3], r5

	AVERAGE_TWO_8BITS		d4, d4, d6
	AVERAGE_TWO_8BITS		d5, d5, d7
	vst1.u8		{d4}, [r0], r1
	vst1.u8		{d5}, [r0], r1

	sub			r4, #4
	cmp			r4, #0
	bne			w8_pix_avg_loop

	pop		{r4, r5}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN PixelAvgWidthEq4_neon
	push		{r4-r8}
	ldr			r4, [sp, #20]
w4_pix_avg_loop:

	ldr		r5, [r2]
	ldr		r6, [r2, #16]
	ldr		r7, [r3]
	ldr		r8, [r3, #16]
	add		r2, #32
	add		r3, #32

	vmov		d0, r5, r6
	vmov		d1, r7, r8
	AVERAGE_TWO_8BITS		d0, d0, d1
	vmov		r5, r6, d0

	str		r5, [r0], r1
	str		r6, [r0], r1

	sub			r4, #2
	cmp			r4, #0
	bne			w4_pix_avg_loop

	pop		{r4-r8}
WELS_ASM_FUNC_END

WELS_ASM_FUNC_BEGIN McChromaWidthEq8_neon
	push		{r4, r5}
	ldr			r4, [sp, #8]
	ldr			r5, [sp, #12]
//	normal case: {cA*src[x]  + cB*src[x+1]} + {cC*src[x+stride] + cD*srcp[x+stride+1]}
//	we can opti it by adding vert only/ hori only cases, to be continue
	vld1.u8	{d31}, [r4]		//load A/B/C/D
	vld1.u8		{q0}, [r0], r1	//src[x]

	vdup.u8	d28, d31[0]			//A
	vdup.u8	d29, d31[1]			//B
	vdup.u8	d30, d31[2]			//C
	vdup.u8	d31, d31[3]			//D

	vext.u8		d1, d0, d1, #1		//src[x+1]

w8_mc_chroma_loop:	// each two pxl row
	vld1.u8		{q1}, [r0], r1	//src[x+stride]
	vld1.u8		{q2}, [r0], r1	//src[x+2*stride]
	vext.u8		d3, d2, d3, #1		//src[x+stride+1]
	vext.u8		d5, d4, d5, #1		//src[x+2*stride+1]

	vmull.u8		q3, d0, d28			//(src[x] * A)
	vmlal.u8		q3, d1, d29			//+=(src[x+1] * B)
	vmlal.u8		q3, d2, d30			//+=(src[x+stride] * C)
	vmlal.u8		q3, d3, d31			//+=(src[x+stride+1] * D)
	vrshrn.u16		d6, q3, #6
	vst1.u8	d6, [r2], r3

	vmull.u8		q3, d2, d28			//(src[x] * A)
	vmlal.u8		q3, d3, d29			//+=(src[x+1] * B)
	vmlal.u8		q3, d4, d30			//+=(src[x+stride] * C)
	vmlal.u8		q3, d5, d31			//+=(src[x+stride+1] * D)
	vrshrn.u16		d6, q3, #6
	vst1.u8	d6, [r2], r3

	vmov		q0, q2
	sub			r5, #2
	cmp			r5, #0
	bne			w8_mc_chroma_loop

	pop		{r4, r5}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McChromaWidthEq4_neon

	push		{r4, r5, r6}
	ldr			r4, [sp, #12]
	ldr			r6, [sp, #16]
//	normal case: {cA*src[x]  + cB*src[x+1]} + {cC*src[x+stride] + cD*srcp[x+stride+1]}
//	we can opti it by adding vert only/ hori only cases, to be continue
	vld1.u8	{d31}, [r4]		//load A/B/C/D

	vdup.u8	d28, d31[0]			//A
	vdup.u8	d29, d31[1]			//B
	vdup.u8	d30, d31[2]			//C
	vdup.u8	d31, d31[3]			//D

w4_mc_chroma_loop:	// each two pxl row
	vld1.u8		{d0}, [r0], r1	//a::src[x]
	vld1.u8		{d2}, [r0], r1	//b::src[x+stride]
	vld1.u8		{d4}, [r0]			//c::src[x+2*stride]

	vshr.u64		d1, d0, #8
	vshr.u64		d3, d2, #8
	vshr.u64		d5, d4, #8

	vmov			q3, q1				//b::[0:7]+b::[1~8]
	vtrn.32		q0, q1				//d0{a::[0:3]+b::[0:3]}; d1{a::[1:4]+b::[1:4]}
	vtrn.32		q3, q2				//d6{b::[0:3]+c::[0:3]}; d7{b::[1:4]+c::[1:4]}

	vmull.u8		q1, d0, d28			//(src[x] * A)
	vmlal.u8		q1, d1, d29			//+=(src[x+1] * B)
	vmlal.u8		q1, d6, d30			//+=(src[x+stride] * C)
	vmlal.u8		q1, d7, d31			//+=(src[x+stride+1] * D)

	vrshrn.u16		d2, q1, #6
	vmov		r4, r5, d2
	str	r4, [r2], r3
	str	r5, [r2], r3

	sub			r6, #2
	cmp			r6, #0
	bne			w4_mc_chroma_loop

	pop		{r4, r5, r6}
WELS_ASM_FUNC_END

WELS_ASM_FUNC_BEGIN McHorVer20Width17_neon
	push		{r4-r5}
	mov			r4, #20
	mov			r5, #1
	sub			r4, r4, r4, lsl #(16-2)
	lsl			r5, #16
	ror			r4, #16
	vmov		d3, r5, r4					// 0x0014FFFB00010000

	sub			r3, #16
	ldr			r4, [sp, #8]

	sub			r0, #2
	vmov.u16	q14, #0x0014				// 20
	vshr.u16	q15, q14, #2				// 5

w17_h_mc_luma_loop:
	vld1.u8	{d0,d1,d2}, [r0], r1	//only use 22(17+5); q0=src[-2]

	vext.8		q2, q0, q1, #1		//q2=src[-1]
	vext.8		q3, q0, q1, #2		//q3=src[0]
	vext.8		q8, q0, q1, #3		//q8=src[1]
	vext.8		q9, q0, q1, #4		//q9=src[2]
	vext.8		q10, q0, q1, #5		//q10=src[3]

	FILTER_6TAG_8BITS 	d0, d4, d6, d16, d18, d20, d22, q14, q15

	FILTER_6TAG_8BITS 	d1, d5, d7, d17, d19, d21, d23, q14, q15

	vst1.u8	{d22, d23}, [r2]!		//write [0:15] Byte

	vsli.64	d2, d2, #8				// [0][1][2][3][4][5]XO-->O[0][1][2][3][4][5]X
	FILTER_SINGLE_TAG_8BITS	d2, d3, d22, q11, q1

	vst1.u8	{d2[0]}, [r2], r3		//write 16th Byte

	sub		r4, #1
	cmp		r4, #0
	bne		w17_h_mc_luma_loop
	pop		{r4-r5}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer20Width9_neon
	push		{r4-r5}
	mov			r4, #20
	mov			r5, #1
	sub			r4, r4, r4, lsl #(16-2)
	lsl			r5, #16
	ror			r4, #16
	vmov		d7, r5, r4					// 0x0014FFFB00010000

	sub			r3, #8
	ldr			r4, [sp, #8]

	sub			r0, #2
	vmov.u16	q14, #0x0014				// 20
	vshr.u16	q15, q14, #2				// 5

w9_h_mc_luma_loop:
	vld1.u8	{d0,d1}, [r0], r1	//only use 14(9+5); q0=src[-2]
	pld			[r0]

	vext.8		d2, d0, d1, #1		//d2=src[-1]
	vext.8		d3, d0, d1, #2		//d3=src[0]
	vext.8		d4, d0, d1, #3		//d4=src[1]
	vext.8		d5, d0, d1, #4		//d5=src[2]
	vext.8		d6, d0, d1, #5		//d6=src[3]

	FILTER_6TAG_8BITS 	d0, d2, d3, d4, d5, d6, d16, q14, q15

	sub		r4, #1
	vst1.u8	{d16}, [r2]!		//write [0:7] Byte

	vsli.64	d2, d1, #8				// [0][1][2][3][4][5]XO-->O[0][1][2][3][4][5]X
	FILTER_SINGLE_TAG_8BITS	d2, d7, d18, q9, q1
	vst1.u8	{d2[0]}, [r2], r3		//write 8th Byte

	cmp		r4, #0
	bne		w9_h_mc_luma_loop
	pop		{r4-r5}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer02Height17_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, r0, r1, lsl #1		//src[-2*src_stride]
	pld			[r0]
	pld			[r0, r1]
	vmov.u16	q14, #0x0014			// 20
	vld1.u8	{q0}, [r0], r1		//q0=src[-2]
	vld1.u8	{q1}, [r0], r1		//q1=src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5
	vld1.u8	{q2}, [r0], r1		//q2=src[0]
	vld1.u8	{q3}, [r0], r1		//q3=src[1]
	vld1.u8	{q8}, [r0], r1		//q8=src[2]

w17_v_mc_luma_loop:

	vld1.u8	{q9}, [r0], r1		//q9=src[3]

	FILTER_6TAG_8BITS 	d0, d2, d4, d6, d16, d18, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d1, d3, d5, d7, d17, d19, d21, q14, q15
	vld1.u8	{q0}, [r0], r1		//read 2nd row
	vst1.u8	{q10}, [r2], r3			//write 1st 16Byte

	FILTER_6TAG_8BITS 	d2, d4, d6, d16, d18, d0, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d3, d5, d7, d17, d19, d1, d21, q14, q15
	vld1.u8	{q1}, [r0], r1		//read 3rd row
	vst1.u8	{q10}, [r2], r3			//write 2nd 16Byte

	FILTER_6TAG_8BITS 	d4, d6, d16, d18, d0, d2, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d5, d7, d17, d19, d1, d3, d21, q14, q15
	vld1.u8	{q2}, [r0], r1		//read 4th row
	vst1.u8	{q10}, [r2], r3			//write 3rd 16Byte

	FILTER_6TAG_8BITS 	d6, d16, d18, d0, d2, d4, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d7, d17, d19, d1, d3, d5, d21, q14, q15
	vld1.u8	{q3}, [r0], r1		//read 5th row
	vst1.u8	{q10}, [r2], r3			//write 4th 16Byte

	FILTER_6TAG_8BITS 	d16, d18, d0, d2, d4, d6, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d17, d19, d1, d3, d5, d7, d21, q14, q15
	vld1.u8	{q8}, [r0], r1		//read 6th row
	vst1.u8	{q10}, [r2], r3			//write 5th 16Byte

	FILTER_6TAG_8BITS 	d18, d0, d2, d4, d6, d16, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d19, d1, d3, d5, d7, d17, d21, q14, q15
	vld1.u8	{q9}, [r0], r1		//read 7th row
	vst1.u8	{q10}, [r2], r3			//write 6th 16Byte

	FILTER_6TAG_8BITS 	d0, d2, d4, d6, d16, d18, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d1, d3, d5, d7, d17, d19, d21, q14, q15
	vld1.u8	{q0}, [r0], r1		//read 8th row
	vst1.u8	{q10}, [r2], r3			//write 7th 16Byte

	FILTER_6TAG_8BITS 	d2, d4, d6, d16, d18, d0, d20, q14, q15
	pld			[r0]
	FILTER_6TAG_8BITS 	d3, d5, d7, d17, d19, d1, d21, q14, q15
	vst1.u8	{q10}, [r2], r3			//write 8th 16Byte

	//q2, q3, q8, q9, q0 --> q0~q8
	vswp	q0, q8
	vswp	q0, q2
	vmov	q1, q3
	vmov	q3, q9						//q0~q8

	sub		r4, #8
	cmp		r4, #1
	bne		w17_v_mc_luma_loop
	// the last 16Bytes
	vld1.u8	{q9}, [r0], r1		//q9=src[3]
	FILTER_6TAG_8BITS 	d0, d2, d4, d6, d16, d18, d20, q14, q15
	FILTER_6TAG_8BITS 	d1, d3, d5, d7, d17, d19, d21, q14, q15
	vst1.u8	{q10}, [r2], r3			//write 1st 16Byte

	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer02Height9_neon
	push		{r4}
	ldr			r4, [sp, #4]

	sub			r0, r0, r1, lsl #1		//src[-2*src_stride]
	pld			[r0]
	pld			[r0, r1]
	vmov.u16	q14, #0x0014			// 20
	vld1.u8	{d0}, [r0], r1		//d0=src[-2]
	vld1.u8	{d1}, [r0], r1		//d1=src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5
	vld1.u8	{d2}, [r0], r1		//d2=src[0]
	vld1.u8	{d3}, [r0], r1		//d3=src[1]

	vld1.u8	{d4}, [r0], r1		//d4=src[2]
	vld1.u8	{d5}, [r0], r1		//d5=src[3]

w9_v_mc_luma_loop:

	pld			[r0]
	FILTER_6TAG_8BITS 	d0, d1, d2, d3, d4, d5, d16, q14, q15
	vld1.u8	{d0}, [r0], r1		//read 2nd row
	vst1.u8	{d16}, [r2], r3		//write 1st 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS 	d1, d2, d3, d4, d5, d0, d16, q14, q15
	vld1.u8	{d1}, [r0], r1		//read 3rd row
	vst1.u8	{d16}, [r2], r3		//write 2nd 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS 	d2, d3, d4, d5, d0, d1, d16, q14, q15
	vld1.u8	{d2}, [r0], r1		//read 4th row
	vst1.u8	{d16}, [r2], r3		//write 3rd 8Byte

	pld			[r0]
	FILTER_6TAG_8BITS 	d3, d4, d5, d0, d1, d2, d16, q14, q15
	vld1.u8	{d3}, [r0], r1		//read 5th row
	vst1.u8	{d16}, [r2], r3		//write 4th 8Byte

	//d4, d5, d0, d1, d2, d3 --> d0, d1, d2, d3, d4, d5
	vswp	q0, q2
	vswp	q1, q2

	sub		r4, #4
	cmp		r4, #1
	bne		w9_v_mc_luma_loop

	FILTER_6TAG_8BITS 	d0, d1, d2, d3, d4, d5, d16, q14, q15
	vst1.u8	{d16}, [r2], r3		//write last 8Byte

	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer22Width17_neon
	push		{r4}
	vpush		{q4-q7}
	ldr			r4, [sp, #68]

	sub			r0, #2					//src[-2]
	sub			r0, r0, r1, lsl #1		//src[-2*src_stride-2]
	pld			[r0]
	pld			[r0, r1]

	vmov.u16	q14, #0x0014			// 20
	vld1.u8	{d0-d2}, [r0], r1		//use 21(17+5), =src[-2]
	vld1.u8	{d3-d5}, [r0], r1		//use 21(17+5), =src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2			// 5

	vld1.u8	{d6-d8}, [r0], r1		//use 21(17+5), =src[0]
	vld1.u8	{d9-d11}, [r0], r1	//use 21(17+5), =src[1]
	pld			[r0]
	pld			[r0, r1]
	vld1.u8	{d12-d14}, [r0], r1	//use 21(17+5), =src[2]
	sub			r3, #16

w17_hv_mc_luma_loop:

	vld1.u8	{d15-d17}, [r0], r1	//use 21(17+5), =src[3]
	//the 1st row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d0, d3, d6, d9, d12, d15, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d1, d4, d7,d10, d13, d16,q10, q14, q15	// 8 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d0	//output to q0[0]
	// vertical filtered into q10/q11
	FILTER_6TAG_8BITS_TO_16BITS 	d2, d5, d8,d11, d14, d17,q11, q14, q15	// only 6 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q10, q11, q9, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q9, q12, q13, d1	//output to q0[1]
	vst1.u8	{d0, d1}, [r2]!			//write 16Byte
	UNPACK_1_IN_8x16BITS_TO_8BITS	d2, d22, d23, q11 //output to d2[0]
	vst1.u8	{d2[0]}, [r2], r3		//write 16th Byte

	vld1.u8	{d0-d2}, [r0], r1		//read 2nd row
	//the 2nd row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d3, d6, d9, d12, d15, d0, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d4, d7,d10, d13, d16, d1,q10, q14, q15	// 8 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d3	//output to d3
	// vertical filtered into q10/q11
	FILTER_6TAG_8BITS_TO_16BITS 	d5, d8,d11, d14, d17, d2,q11, q14, q15	// only 6 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q10, q11, q9, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q9, q12, q13, d4	//output to d4
	vst1.u8	{d3, d4}, [r2]!		//write 16Byte
	UNPACK_1_IN_8x16BITS_TO_8BITS	d5, d22, d23, q11 //output to d5[0]
	vst1.u8	{d5[0]}, [r2], r3		//write 16th Byte

	vld1.u8	{d3-d5}, [r0], r1		//read 3rd row
	//the 3rd row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d6, d9, d12, d15, d0, d3, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d7,d10, d13, d16, d1, d4,q10, q14, q15	// 8 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d6	//output to d6
	// vertical filtered into q10/q11
	FILTER_6TAG_8BITS_TO_16BITS 	d8,d11, d14, d17, d2, d5,q11, q14, q15	// only 6 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q10, q11, q9, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q9, q12, q13, d7	//output to d7
	vst1.u8	{d6, d7}, [r2]!		//write 16Byte
	UNPACK_1_IN_8x16BITS_TO_8BITS	d8, d22, d23, q11 //output to d8[0]
	vst1.u8	{d8[0]}, [r2], r3		//write 16th Byte

	vld1.u8	{d6-d8}, [r0], r1		//read 4th row
	//the 4th row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	 d9, d12, d15, d0, d3, d6, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS		d10, d13, d16, d1, d4, d7,q10, q14, q15	// 8 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d9	//output to d9
	// vertical filtered into q10/q11
	FILTER_6TAG_8BITS_TO_16BITS 	d11, d14, d17, d2, d5, d8,q11, q14, q15	// only 6 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q10, q11, q9, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q9, q12, q13, d10	//output to d10
	vst1.u8	{d9, d10}, [r2]!		//write 16Byte
	UNPACK_1_IN_8x16BITS_TO_8BITS	d11, d22, d23, q11 //output to d11[0]
	vst1.u8	{d11[0]}, [r2], r3		//write 16th Byte

	//d12~d17(q6~q8), d0~d8(q0~q3+d8), --> d0~d14
	vswp	q0, q6
	vswp	q6, q3
	vmov	q5, q2
	vmov	q2, q8

	vmov	d20,d8
	vmov	q4, q1
	vmov	q1, q7
	vmov	d14,d20

	sub		r4, #4
	cmp		r4, #1
	bne		w17_hv_mc_luma_loop
	//the last row
	vld1.u8	{d15-d17}, [r0], r1	//use 21(17+5), =src[3]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d0, d3, d6, d9, d12, d15, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d1, d4, d7,d10, d13, d16,q10, q14, q15	// 8 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d0	//output to q0[0]
	// vertical filtered into q10/q11
	FILTER_6TAG_8BITS_TO_16BITS 	d2, d5, d8,d11, d14, d17,q11, q14, q15	// only 6 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q10, q11, q9, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q9, q12, q13, d1	//output to q0[1]
	vst1.u8	{q0}, [r2]!			//write 16Byte
	UNPACK_1_IN_8x16BITS_TO_8BITS	d2, d22, d23, q11 //output to d2[0]
	vst1.u8	{d2[0]}, [r2], r3		//write 16th Byte

	vpop		{q4-q7}
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN McHorVer22Width9_neon
	push		{r4}
	vpush		{q4}
	ldr			r4, [sp, #20]

	sub			r0, #2				//src[-2]
	sub			r0, r0, r1, lsl #1	//src[-2*src_stride-2]
	pld			[r0]
	pld			[r0, r1]

	vmov.u16	q14, #0x0014		// 20
	vld1.u8	{q0}, [r0], r1	//use 14(9+5), =src[-2]
	vld1.u8	{q1}, [r0], r1	//use 14(9+5), =src[-1]

	pld			[r0]
	pld			[r0, r1]
	vshr.u16	q15, q14, #2		// 5

	vld1.u8	{q2}, [r0], r1	//use 14(9+5), =src[0]
	vld1.u8	{q3}, [r0], r1	//use 14(9+5), =src[1]
	pld			[r0]
	pld			[r0, r1]
	vld1.u8	{q4}, [r0], r1	//use 14(9+5), =src[2]
	sub			r3, #8

w9_hv_mc_luma_loop:

	vld1.u8	{q8}, [r0], r1	//use 14(9+5), =src[3]
	//the 1st row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d0, d2, d4, d6, d8, d16, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d1, d3, d5, d7, d9, d17, q10, q14, q15	// 6 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d18	//output to q9[0]
	vst1.u8	d18, [r2]!				//write 8Byte
	UNPACK_1_IN_8x16BITS_TO_8BITS	d19, d20, d21, q10 //output to d19[0]
	vst1.u8	{d19[0]}, [r2], r3	//write 8th Byte

	vld1.u8	{q0}, [r0], r1		//read 2nd row
	//the 2nd row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d2, d4, d6, d8, d16, d0, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d3, d5, d7, d9, d17, d1, q10, q14, q15	// 6 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d18	//output to q9[0]
	vst1.u8	d18, [r2]!				//write 8Byte
	UNPACK_1_IN_8x16BITS_TO_8BITS	d19, d20, d21, q10 //output to d19[0]
	vst1.u8	{d19[0]}, [r2], r3	//write 8th Byte

	vld1.u8	{q1}, [r0], r1		//read 3rd row
	//the 3rd row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d4, d6, d8, d16, d0, d2, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d5, d7, d9, d17, d1, d3, q10, q14, q15	// 6 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d18	//output to q9[0]
	vst1.u8	d18, [r2]!				//write 8Byte
	UNPACK_1_IN_8x16BITS_TO_8BITS	d19, d20, d21, q10 //output to d19[0]
	vst1.u8	{d19[0]}, [r2], r3	//write 8th Byte

	vld1.u8	{q2}, [r0], r1		//read 4th row
	//the 4th row
	pld			[r0]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d6, d8, d16, d0, d2, d4, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d7, d9, d17, d1, d3, d5, q10, q14, q15	// 6 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d18	//output to q9[0]
	vst1.u8	d18, [r2]!			//write 8Byte
	UNPACK_1_IN_8x16BITS_TO_8BITS	d19, d20, d21, q10 //output to d19[0]
	vst1.u8	{d19[0]}, [r2], r3	//write 8th Byte

	//q4~q8, q0~q2, --> q0~q4
	vswp	q0, q4
	vswp	q2, q4
	vmov	q3, q1
	vmov	q1, q8

	sub		r4, #4
	cmp		r4, #1
	bne		w9_hv_mc_luma_loop
	//the last row
	vld1.u8	{q8}, [r0], r1	//use 14(9+5), =src[3]
	// vertical filtered into q9/q10
	FILTER_6TAG_8BITS_TO_16BITS 	d0, d2, d4, d6, d8, d16, q9, q14, q15	// 8 avail
	FILTER_6TAG_8BITS_TO_16BITS 	d1, d3, d5, d7, d9, d17, q10, q14, q15	// 6 avail
	// horizon filtered
	UNPACK_2_16BITS_TO_ABC	q9, q10, q11, q12, q13
	FILTER_3_IN_16BITS_TO_8BITS q11, q12, q13, d18	//output to q9[0]
	vst1.u8	d18, [r2]!				//write 8Byte
	UNPACK_1_IN_8x16BITS_TO_8BITS	d19, d20, d21, q10 //output to d19[0]
	vst1.u8	{d19[0]}, [r2], r3	//write 8th Byte
	vpop		{q4}
	pop		{r4}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN PixStrideAvgWidthEq16_neon
	push		{r4, r5, r6}
	ldr			r4, [sp, #12]
	ldr			r5, [sp, #16]
	ldr			r6, [sp, #20]

enc_w16_pix_avg_loop:
	vld1.u8		{q0}, [r2], r3
	vld1.u8		{q1}, [r4], r5
	vld1.u8		{q2}, [r2], r3
	vld1.u8		{q3}, [r4], r5

	vld1.u8		{q8}, [r2], r3
	vld1.u8		{q9}, [r4], r5
	vld1.u8		{q10}, [r2], r3
	vld1.u8		{q11}, [r4], r5

	AVERAGE_TWO_8BITS		d0, d0, d2
	AVERAGE_TWO_8BITS		d1, d1, d3
	vst1.u8		{q0}, [r0], r1

	AVERAGE_TWO_8BITS		d4, d4, d6
	AVERAGE_TWO_8BITS		d5, d5, d7
	vst1.u8		{q2}, [r0], r1

	AVERAGE_TWO_8BITS		d16, d16, d18
	AVERAGE_TWO_8BITS		d17, d17, d19
	vst1.u8		{q8}, [r0], r1

	AVERAGE_TWO_8BITS		d20, d20, d22
	AVERAGE_TWO_8BITS		d21, d21, d23
	vst1.u8		{q10}, [r0], r1

	sub			r6, #4
	cmp			r6, #0
	bne			enc_w16_pix_avg_loop

	pop		{r4, r5, r6}
WELS_ASM_FUNC_END


WELS_ASM_FUNC_BEGIN PixStrideAvgWidthEq8_neon
	push		{r4, r5, r6}
	ldr			r4, [sp, #12]
	ldr			r5, [sp, #16]
	ldr			r6, [sp, #20]
enc_w8_pix_avg_loop:

	vld1.u8		{d0}, [r2], r3
	vld1.u8		{d2}, [r4], r5
	vld1.u8		{d1}, [r2], r3
	vld1.u8		{d3}, [r4], r5

	AVERAGE_TWO_8BITS		d0, d0, d2
	AVERAGE_TWO_8BITS		d1, d1, d3
	vst1.u8		{d0}, [r0], r1
	vst1.u8		{d1}, [r0], r1

	vld1.u8		{d4}, [r2], r3
	vld1.u8		{d6}, [r4], r5
	vld1.u8		{d5}, [r2], r3
	vld1.u8		{d7}, [r4], r5

	AVERAGE_TWO_8BITS		d4, d4, d6
	AVERAGE_TWO_8BITS		d5, d5, d7
	vst1.u8		{d4}, [r0], r1
	vst1.u8		{d5}, [r0], r1

	sub			r6, #4
	cmp			r6, #0
	bne			enc_w8_pix_avg_loop

	pop		{r4, r5, r6}
WELS_ASM_FUNC_END

#endif