add M-HT's neon scalers
[fceu.git] / drivers / arm / neon_scale2x.Sinc
diff --git a/drivers/arm/neon_scale2x.Sinc b/drivers/arm/neon_scale2x.Sinc
new file mode 100644 (file)
index 0000000..e9a80ff
--- /dev/null
@@ -0,0 +1,474 @@
+@@\r
+@@  Copyright (C) 2012 Roman Pauer\r
+@@\r
+@@  Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+@@  this software and associated documentation files (the "Software"), to deal in\r
+@@  the Software without restriction, including without limitation the rights to\r
+@@  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\r
+@@  of the Software, and to permit persons to whom the Software is furnished to do\r
+@@  so, subject to the following conditions:\r
+@@\r
+@@  The above copyright notice and this permission notice shall be included in all\r
+@@  copies or substantial portions of the Software.\r
+@@\r
+@@  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+@@  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+@@  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+@@  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+@@  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+@@  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+@@  SOFTWARE.\r
+@@\r
+\r
+\r
+@ A B C  --\ E0 E1\r
+@ D E F  --/ E2 E3\r
+@ G H I\r
+\r
+@ q0    = E0 (tmp0)\r
+@ q1    = E1 (tmp1)\r
+@ q2    = E2 (tmp2)\r
+@ q3    = E3 (tmp3)\r
+@ q8    = S2prev\r
+@ q9    = S2next\r
+@ q10   = C0        < B == H || D == F >\r
+@ q11   = S1        < B >\r
+@ q12   = S2        < E >\r
+@ q13   = S3        < H >\r
+@ q14   = S2sl      < D >\r
+@ q15   = S2sr      < F >\r
+\r
+\r
+.macro __neon_scale2x_8_8_line src1, src2, src3, counter, dst1, dst2, reg1, qB, qH, alsrc1, alsrc2, alsrc3, aldst1, aldst2\r
+\r
+        vld1.8 {d17[7]}, [\src2]        @ S2prev[15] = src[0]\r
+        andS \reg1, \counter, #15       @ reg1 = counter & 15\r
+\r
+    .ifnes "\qB", "q11"\r
+        add \src1, \src1, \counter      @ src1 += counter\r
+    .endif\r
+    .ifnes "\qH", "q13"\r
+        add \src3, \src3, \counter      @ src3 += counter\r
+    .endif\r
+        beq 1f\r
+\r
+    @ first 1-15 pixels - align counter to 16 bytes\r
+        vld1.8 {q12}, [\src2], \reg1    @ S2 = [src]    < E >; src2 += counter & 15\r
+\r
+    .ifeqs "\qB", "q11"\r
+        vld1.8 {\qB}, [\src1], \reg1    @ S1 = [src - srcstride]    < B >; src1 += counter & 15\r
+    .endif\r
+\r
+    .ifeqs "\qH", "q13"\r
+        vld1.8 {\qH}, [\src3], \reg1    @ S3 = [src + srcstride]    < H >; src3 += counter & 15\r
+    .endif\r
+        vext.8 q14, q8, q12, #15        @ S2sl = S2prev[15] | (S2 << 8)     < D >\r
+\r
+        vceq.i8 q2, \qB, \qH            @ tmp2 = < B == H >\r
+\r
+        vmov.8 d17[7], \reg1            @ S2prev[15] = reg1\r
+        vext.8 q15, q12, q9, #1         @ S2sr = (S2 >> 8) | ...            < F >\r
+\r
+        vceq.i8 q0, q14, \qB            @ tmp0 = < D == B >\r
+\r
+        vceq.i8 q3, q14, q15            @ tmp3 = < D == F >\r
+\r
+        vceq.i8 q1, \qB, q15            @ tmp1 = < B == F >\r
+        vtbl.8 d17, {d28, d29}, d17     @ S2prev[15] = src[reg1 - 1]\r
+\r
+        lsl \reg1, #1\r
+        vorr q10, q2, q3                @ C0 = < B == H || D == F >\r
+\r
+        vceq.i8 q2, q14, \qH            @ tmp2 = < D == H >\r
+\r
+        vceq.i8 q3, \qH, q15            @ tmp3 = < H == F >\r
+\r
+        vorn q0, q10, q0                @ tmp0 = < C0 || !(D == B) >\r
+\r
+        vorn q1, q10, q1                @ tmp1 = < C0 || !(B == F) >\r
+\r
+        vbsl q0, q12, q14               @ E0 = < (C0 || !(D == B)) ? E : D >\r
+\r
+        vbsl q1, q12, q15               @ E1 = < (C0 || !(B == F)) ? E : F >\r
+\r
+        vorn q2, q10, q2                @ tmp2 = < C0 || !(D == H) >\r
+\r
+        vorn q3, q10, q3                @ tmp3 = < C0 || !(H == F) >\r
+\r
+        vbsl q2, q12, q14               @ E2 = < (C0 || !(D == H)) ? E : D >\r
+        vst2.8 {q0-q1}, [\dst1], \reg1  @ [dst] = E0,E1; dst1 += reg1\r
+\r
+        vbsl q3, q12, q15               @ E3 = < (C0 || !(H == F)) ? E : F >\r
+        bic \counter, \counter, #15\r
+\r
+        vst2.8 {q2-q3}, [\dst2], \reg1  @ [dst + dststride] = E2,E3; dst2 += reg1\r
+\r
+    @ counter is aligned to 16 bytes\r
+\r
+    1:\r
+        vld1.8 {q9}, [\alsrc2]!         @ S2next = [src]; src2 += 16\r
+\r
+    @ inner loop (16 pixels per iteration)\r
+    2:\r
+\r
+        vmov q12, q9                    @ S2 = S2next           < E >\r
+    .ifeqs "\qB", "q11"\r
+        vld1.8 {\qB}, [\alsrc1]!        @ S1 = [src - srcstride]    < B >; src1 += 16\r
+    .endif\r
+\r
+    .ifeqs "\qH", "q13"\r
+        vld1.8 {\qH}, [\alsrc3]!        @ S3 = [src + srcstride]    < H >; src3 += 16\r
+    .endif\r
+\r
+        vext.8 q14, q8, q12, #15        @ S2sl = S2prev[15] | (S2 << 8)     < D >\r
+        vld1.8 {q9}, [\alsrc2]!         @ S2next = [src]; src2 += 16\r
+\r
+        vceq.i8 q2, \qB, \qH            @ tmp2 = < B == H >\r
+\r
+        vmov q8, q12                    @ S2prev = S2\r
+        vext.8 q15, q12, q9, #1         @ S2sr = (S2 >> 8) | S2next[0]      < F >\r
+\r
+        vceq.i8 q0, q14, \qB            @ tmp0 = < D == B >\r
+\r
+        vceq.i8 q3, q14, q15            @ tmp3 = < D == F >\r
+\r
+        vceq.i8 q1, \qB, q15            @ tmp1 = < B == F >\r
+\r
+        sub \counter, \counter, #16     @ counter -= 16\r
+\r
+        vorr q10, q2, q3                @ C0 = < B == H || D == F >\r
+\r
+        vceq.i8 q2, q14, \qH            @ tmp2 = < D == H >\r
+\r
+        vceq.i8 q3, \qH, q15            @ tmp3 = < H == F >\r
+\r
+        vorn q0, q10, q0                @ tmp0 = < C0 || !(D == B) >\r
+\r
+        vorn q1, q10, q1                @ tmp1 = < C0 || !(B == F) >\r
+\r
+        vbsl q0, q12, q14               @ E0 = < (C0 || !(D == B)) ? E : D >\r
+\r
+        vbsl q1, q12, q15               @ E1 = < (C0 || !(B == F)) ? E : F >\r
+\r
+        vorn q2, q10, q2                @ tmp2 = < C0 || !(D == H) >\r
+\r
+        vorn q3, q10, q3                @ tmp3 = < C0 || !(H == F) >\r
+\r
+        vbsl q2, q12, q14               @ E2 = < (C0 || !(D == H)) ? E : D >\r
+        vst2.8 {q0-q1}, [\aldst1]!      @ [dst] = E0,E1; dst1 += 2*16\r
+\r
+        cmp \counter, #16\r
+\r
+        vbsl q3, q12, q15               @ E3 = < (C0 || !(H == F)) ? E : F >\r
+\r
+        vst2.8 {q2-q3}, [\aldst2]!      @ [dst + dststride] = E2,E3; dst2 += 2*16\r
+\r
+        bhi 2b\r
+\r
+    @ last 16 pixels\r
+\r
+        vmov q12, q9                    @ S2 = S2next           < E >\r
+\r
+        vshr.u64 d18, d19, #(64-8)      @ S2next[0] = S2[15] | ...\r
+    .ifeqs "\qB", "q11"\r
+        vld1.8 {\qB}, [\alsrc1]!        @ S1 = [src - srcstride]    < B >; src1 += 16\r
+    .endif\r
+\r
+        vext.8 q14, q8, q12, #15        @ S2sl = S2prev[15] | (S2 << 8)     < D >\r
+\r
+        vext.8 q15, q12, q9, #1         @ S2sr = (S2 >> 8) | S2next[0]      < F >\r
+    .ifeqs "\qH", "q13"\r
+        vld1.8 {\qH}, [\alsrc3]!        @ S3 = [src + srcstride]    < H >; src3 += 16\r
+    .endif\r
+\r
+        vceq.i8 q0, q14, \qB            @ tmp0 = < D == B >\r
+\r
+        vceq.i8 q2, \qB, \qH            @ tmp2 = < B == H >\r
+\r
+        vceq.i8 q3, q14, q15            @ tmp3 = < D == F >\r
+\r
+        vceq.i8 q1, \qB, q15            @ tmp1 = < B == F >\r
+\r
+        vorr q10, q2, q3                @ C0 = < B == H || D == F >\r
+\r
+        vceq.i8 q2, q14, \qH            @ tmp2 = < D == H >\r
+\r
+        vceq.i8 q3, \qH, q15            @ tmp3 = < H == F >\r
+\r
+        vorn q0, q10, q0                @ tmp0 = < C0 || !(D == B) >\r
+\r
+        vorn q1, q10, q1                @ tmp1 = < C0 || !(B == F) >\r
+\r
+        vbsl q0, q12, q14               @ E0 = < (C0 || !(D == B)) ? E : D >\r
+\r
+        vbsl q1, q12, q15               @ E1 = < (C0 || !(B == F)) ? E : F >\r
+\r
+        vorn q2, q10, q2                @ tmp2 = < C0 || !(D == H) >\r
+\r
+        vorn q3, q10, q3                @ tmp3 = < C0 || !(H == F) >\r
+\r
+        vbsl q2, q12, q14               @ E2 = < (C0 || !(D == H)) ? E : D >\r
+        vst2.8 {q0-q1}, [\aldst1]!      @ [dst] = E0,E1; dst1 += 2*16\r
+\r
+        vbsl q3, q12, q15               @ E3 = < (C0 || !(H == F)) ? E : F >\r
+\r
+        vst2.8 {q2-q3}, [\aldst2]!      @ [dst + dststride] = E2,E3; dst2 += 2*16\r
+\r
+.endm\r
+\r
+.macro _neon_scale2x_8_8_line_first src1, src2, src3, counter, dst1, dst2, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2\r
+        __neon_scale2x_8_8_line \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, q12, q13, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2\r
+.endm\r
+\r
+.macro _neon_scale2x_8_8_line_middle src1, src2, src3, counter, dst1, dst2, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2\r
+        __neon_scale2x_8_8_line \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, q11, q13, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2\r
+.endm\r
+\r
+.macro _neon_scale2x_8_8_line_last src1, src2, src3, counter, dst1, dst2, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2\r
+        __neon_scale2x_8_8_line \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, q11, q12, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2\r
+.endm\r
+\r
+.macro neon_scale2x_8_8_line part, src1, src2, src3, counter, dst1, dst2, reg1, srcalign16, dstalign32\r
+    .ifeq \srcalign16\r
+\r
+    .ifeq \dstalign32\r
+        _neon_scale2x_8_8_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, \src1, \src2, \src3, \dst1, \dst2\r
+    .else\r
+        _neon_scale2x_8_8_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, \src1, \src2, \src3, \dst1:256, \dst2:256\r
+    .endif\r
+\r
+    .else\r
+\r
+    .ifeq \dstalign32\r
+        _neon_scale2x_8_8_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, \src1:128, \src2:128, \src3:128, \dst1, \dst2\r
+    .else\r
+        _neon_scale2x_8_8_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, \src1:128, \src2:128, \src3:128, \dst1:256, \dst2:256\r
+    .endif\r
+\r
+    .endif\r
+.endm\r
+\r
+\r
+.macro __neon_scale2x_16_16_line src1, src2, src3, counter, dst1, dst2, reg1, qB, qH, alsrc1, alsrc2, alsrc3, aldst1, aldst2\r
+\r
+        vld1.16 {d17[3]}, [\src2]       @ S2prev[7] = src[0]\r
+        andS \reg1, \counter, #7        @ reg1 = counter & 7\r
+\r
+    .ifnes "\qB", "q11"\r
+        add \src1, \src1, \counter, lsl #1  @ src1 += 2 * counter\r
+    .endif\r
+    .ifnes "\qH", "q13"\r
+        add \src3, \src3, \counter, lsl #1  @ src3 += 2 * counter\r
+    .endif\r
+        beq 1f\r
+\r
+    @ first 1-7 pixels - align counter to 16 bytes\r
+        vld1.16 {q12}, [\src2]          @ S2 = [src]    < E >\r
+        lsl \reg1, #1\r
+\r
+    .ifeqs "\qB", "q11"\r
+        vld1.16 {\qB}, [\src1]          @ S1 = [src - srcstride]    < B >\r
+    .endif\r
+        bfi \reg1, \reg1, #8, #8\r
+\r
+    .ifeqs "\qH", "q13"\r
+        vld1.16 {\qH}, [\src3]          @ S3 = [src + srcstride]    < H >\r
+    .endif\r
+        vext.8 q14, q8, q12, #14        @ S2sl = S2prev[7] | (S2 << 16)     < D >\r
+\r
+        add \reg1, \reg1, #256\r
+        vceq.i16 q2, \qB, \qH           @ tmp2 = < B == H >\r
+\r
+        vmov.16 d17[3], \reg1           @ S2prev[7] = reg1\r
+        vext.8 q15, q12, q9, #2         @ S2sr = (S2 >> 16) | ...            < F >\r
+\r
+        vceq.i16 q0, q14, \qB           @ tmp0 = < D == B >\r
+\r
+        vceq.i16 q3, q14, q15           @ tmp3 = < D == F >\r
+\r
+        vceq.i16 q1, \qB, q15           @ tmp1 = < B == F >\r
+        vtbl.8 d17, {d28, d29}, d17     @ S2prev[7] = src[reg1 - 1]\r
+\r
+        vorr q10, q2, q3                @ C0 = < B == H || D == F >\r
+        and \reg1, \counter, #7\r
+\r
+        vceq.i16 q2, q14, \qH           @ tmp2 = < D == H >\r
+\r
+        vceq.i16 q3, \qH, q15           @ tmp3 = < H == F >\r
+\r
+        vorn q0, q10, q0                @ tmp0 = < C0 || !(D == B) >\r
+\r
+        vorn q1, q10, q1                @ tmp1 = < C0 || !(B == F) >\r
+\r
+        vbsl q0, q12, q14               @ E0 = < (C0 || !(D == B)) ? E : D >\r
+\r
+        vbsl q1, q12, q15               @ E1 = < (C0 || !(B == F)) ? E : F >\r
+\r
+        vorn q2, q10, q2                @ tmp2 = < C0 || !(D == H) >\r
+\r
+        vorn q3, q10, q3                @ tmp3 = < C0 || !(H == F) >\r
+\r
+        vbsl q2, q12, q14               @ E2 = < (C0 || !(D == H)) ? E : D >\r
+        vst2.16 {q0-q1}, [\dst1]        @ [dst] = E0,E1\r
+\r
+        vbsl q3, q12, q15               @ E3 = < (C0 || !(H == F)) ? E : F >\r
+\r
+        bic \counter, \counter, #7\r
+    .ifeqs "\qB", "q11"\r
+        add \src1, \src1, \reg1, lsl #1\r
+    .endif\r
+        add \src2, \src2, \reg1, lsl #1\r
+    .ifeqs "\qH", "q13"\r
+        add \src3, \src3, \reg1, lsl #1\r
+    .endif\r
+\r
+        vst2.16 {q2-q3}, [\dst2]        @ [dst + dststride] = E2,E3\r
+\r
+        add \dst1, \dst1, \reg1, lsl #2\r
+        add \dst2, \dst2, \reg1, lsl #2\r
+\r
+    @ counter is aligned to 16 bytes\r
+\r
+    1:\r
+        vld1.16 {q9}, [\alsrc2]!        @ S2next = [src]; src2 += 2*8\r
+\r
+    @ inner loop (8 pixels per iteration)\r
+    2:\r
+\r
+        vmov q12, q9                    @ S2 = S2next           < E >\r
+    .ifeqs "\qB", "q11"\r
+        vld1.16 {\qB}, [\alsrc1]!       @ S1 = [src - srcstride]    < B >; src1 += 2*8\r
+    .endif\r
+\r
+    .ifeqs "\qH", "q13"\r
+        vld1.16 {\qH}, [\alsrc3]!       @ S3 = [src + srcstride]    < H >; src3 += 2*8\r
+    .endif\r
+\r
+        vext.8 q14, q8, q12, #14        @ S2sl = S2prev[7] | (S2 << 16)     < D >\r
+        vld1.16 {q9}, [\alsrc2]!        @ S2next = [src]; src2 += 2*8\r
+\r
+        vceq.i16 q2, \qB, \qH           @ tmp2 = < B == H >\r
+\r
+        vmov q8, q12                    @ S2prev = S2\r
+        vext.8 q15, q12, q9, #2         @ S2sr = (S2 >> 16) | S2next[0]      < F >\r
+\r
+        vceq.i16 q0, q14, \qB           @ tmp0 = < D == B >\r
+\r
+        vceq.i16 q3, q14, q15           @ tmp3 = < D == F >\r
+\r
+        vceq.i16 q1, \qB, q15           @ tmp1 = < B == F >\r
+\r
+        sub \counter, \counter, #8      @ counter -= 8\r
+\r
+        vorr q10, q2, q3                @ C0 = < B == H || D == F >\r
+\r
+        vceq.i16 q2, q14, \qH           @ tmp2 = < D == H >\r
+\r
+        vceq.i16 q3, \qH, q15           @ tmp3 = < H == F >\r
+\r
+        vorn q0, q10, q0                @ tmp0 = < C0 || !(D == B) >\r
+\r
+        vorn q1, q10, q1                @ tmp1 = < C0 || !(B == F) >\r
+\r
+        vbsl q0, q12, q14               @ E0 = < (C0 || !(D == B)) ? E : D >\r
+\r
+        vbsl q1, q12, q15               @ E1 = < (C0 || !(B == F)) ? E : F >\r
+\r
+        vorn q2, q10, q2                @ tmp2 = < C0 || !(D == H) >\r
+\r
+        vorn q3, q10, q3                @ tmp3 = < C0 || !(H == F) >\r
+\r
+        vbsl q2, q12, q14               @ E2 = < (C0 || !(D == H)) ? E : D >\r
+        vst2.16 {q0-q1}, [\aldst1]!     @ [dst] = E0,E1; dst1 += 2*2*8\r
+\r
+        cmp \counter, #8\r
+\r
+        vbsl q3, q12, q15               @ E3 = < (C0 || !(H == F)) ? E : F >\r
+\r
+        vst2.16 {q2-q3}, [\aldst2]!     @ [dst + dststride] = E2,E3; dst2 += 2*2*8\r
+\r
+        bhi 2b\r
+\r
+    @ last 8 pixels\r
+\r
+        vmov q12, q9                    @ S2 = S2next           < E >\r
+\r
+        vshr.u64 d18, d19, #(64-16)     @ S2next[0] = S2[7] | ...\r
+    .ifeqs "\qB", "q11"\r
+        vld1.16 {\qB}, [\alsrc1]!       @ S1 = [src - srcstride]    < B >; src1 += 2*8\r
+    .endif\r
+\r
+        vext.8 q14, q8, q12, #14        @ S2sl = S2prev[7] | (S2 << 16)     < D >\r
+\r
+        vext.8 q15, q12, q9, #2         @ S2sr = (S2 >> 16) | S2next[0]      < F >\r
+    .ifeqs "\qH", "q13"\r
+        vld1.16 {\qH}, [\alsrc3]!       @ S3 = [src + srcstride]    < H >; src3 += 2*8\r
+    .endif\r
+\r
+        vceq.i16 q0, q14, \qB           @ tmp0 = < D == B >\r
+\r
+        vceq.i16 q2, \qB, \qH           @ tmp2 = < B == H >\r
+\r
+        vceq.i16 q3, q14, q15           @ tmp3 = < D == F >\r
+\r
+        vceq.i16 q1, \qB, q15           @ tmp1 = < B == F >\r
+\r
+        vorr q10, q2, q3                @ C0 = < B == H || D == F >\r
+\r
+        vceq.i16 q2, q14, \qH           @ tmp2 = < D == H >\r
+\r
+        vceq.i16 q3, \qH, q15           @ tmp3 = < H == F >\r
+\r
+        vorn q0, q10, q0                @ tmp0 = < C0 || !(D == B) >\r
+\r
+        vorn q1, q10, q1                @ tmp1 = < C0 || !(B == F) >\r
+\r
+        vbsl q0, q12, q14               @ E0 = < (C0 || !(D == B)) ? E : D >\r
+\r
+        vbsl q1, q12, q15               @ E1 = < (C0 || !(B == F)) ? E : F >\r
+\r
+        vorn q2, q10, q2                @ tmp2 = < C0 || !(D == H) >\r
+\r
+        vorn q3, q10, q3                @ tmp3 = < C0 || !(H == F) >\r
+\r
+        vbsl q2, q12, q14               @ E2 = < (C0 || !(D == H)) ? E : D >\r
+        vst2.16 {q0-q1}, [\aldst1]!     @ [dst] = E0,E1; dst1 += 2*2*8\r
+\r
+        vbsl q3, q12, q15               @ E3 = < (C0 || !(H == F)) ? E : F >\r
+\r
+        vst2.16 {q2-q3}, [\aldst2]!     @ [dst + dststride] = E2,E3; dst2 += 2*2*8\r
+\r
+.endm\r
+\r
+.macro _neon_scale2x_16_16_line_first src1, src2, src3, counter, dst1, dst2, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2\r
+        __neon_scale2x_16_16_line \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, q12, q13, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2\r
+.endm\r
+\r
+.macro _neon_scale2x_16_16_line_middle src1, src2, src3, counter, dst1, dst2, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2\r
+        __neon_scale2x_16_16_line \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, q11, q13, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2\r
+.endm\r
+\r
+.macro _neon_scale2x_16_16_line_last src1, src2, src3, counter, dst1, dst2, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2\r
+        __neon_scale2x_16_16_line \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, q11, q12, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2\r
+.endm\r
+\r
+.macro neon_scale2x_16_16_line part, src1, src2, src3, counter, dst1, dst2, reg1, srcalign16, dstalign32\r
+    .ifeq \srcalign16\r
+\r
+    .ifeq \dstalign32\r
+        _neon_scale2x_16_16_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, \src1, \src2, \src3, \dst1, \dst2\r
+    .else\r
+        _neon_scale2x_16_16_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, \src1, \src2, \src3, \dst1:256, \dst2:256\r
+    .endif\r
+\r
+    .else\r
+\r
+    .ifeq \dstalign32\r
+        _neon_scale2x_16_16_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, \src1:128, \src2:128, \src3:128, \dst1, \dst2\r
+    .else\r
+        _neon_scale2x_16_16_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \reg1, \src1:128, \src2:128, \src3:128, \dst1:256, \dst2:256\r
+    .endif\r
+\r
+    .endif\r
+.endm\r
+\r