integrate M-HT's neon scalers
[gpsp.git] / arm / neon_scale3x.Sinc
diff --git a/arm/neon_scale3x.Sinc b/arm/neon_scale3x.Sinc
new file mode 100644 (file)
index 0000000..fc72d31
--- /dev/null
@@ -0,0 +1,976 @@
+@@\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 E2\r
+@ D E F  --/ E3 E4 E5\r
+@ G H I      E6 E7 E8\r
+\r
+@ q0  = S1sl    < A >\r
+@ q1  = S2sl    < D >\r
+@ q2  = S3sl    < G >\r
+@ q3  = S1sr    < C >\r
+@ q4  = S2sr    < F >\r
+@ q5  = S3sr    < I >\r
+@ q6  =\r
+@ q7  =\r
+@ q8  = S1\r
+@ q9  = S2\r
+@ q10 = S3\r
+@ q11 =\r
+@ q12 = S2prev  < E >\r
+@ q13 =\r
+@ q14 = S1prev  < B >\r
+@ q15 = S3prev  < H >\r
+\r
+\r
+.macro ___neon_scale3x_8_8_slice counter, dst1, dst2, dst3, reg1, dB0, dB1, dH0, dH1, first15, last16\r
+\r
+@ d12 = E0[0]\r
+@ d13 = E1[0]\r
+@ d14 = E2[0]\r
+@ d15 = tmp0[0]\r
+@ d22 = E3[0]\r
+@ d23 = tmp1[0]\r
+@ d24 = E4[0]\r
+@ d25 = E4[1]\r
+@ d26 = E5[0]\r
+@ d27 = C0[0]\r
+\r
+@ q0  = tmp2\r
+@ q3  = tmp3\r
+@ q2  = tmp4\r
+@ q5  = tmp5\r
+\r
+        vceq.i8 d15, \dB0, \dH0         @ tmp0[0] = < B == H >\r
+\r
+        vceq.i8 d23, d2, d8             @ tmp1[0] = < D == F >\r
+\r
+    .if \first15\r
+        cmp \reg1, #8\r
+    .endif\r
+\r
+        vceq.i8 q0, q12, q0             @ tmp2 = < E == A >\r
+\r
+        vceq.i8 q3, q12, q3             @ tmp3 = < E == C >\r
+\r
+    .if \first15\r
+        add \reg1, \reg1, \reg1, lsl #1 @ reg1 = 3 * (counter & 15)\r
+    .endif\r
+\r
+        vorr d27, d15, d23              @ C0[0] = < B == H || D == F >\r
+\r
+        vceq.i8 d22, d2, \dB0           @ E3[0] = < D == B >\r
+\r
+        vceq.i8 d26, \dB0, d8           @ E5[0] = < B == F >\r
+\r
+        vceq.i8 q2, q12, q2             @ tmp4 = < E == G >\r
+\r
+        vceq.i8 q5, q12, q5             @ tmp5 = < E == I >\r
+\r
+    .if \first15\r
+        sub \reg1, \reg1, #(3*8)        @ reg1 -= 3*8\r
+    .endif\r
+\r
+        vorn d15, d6, d22               @ tmp0[0] = < (E == C) || !(D == B) >\r
+\r
+        vorn d23, d0, d26               @ tmp1[0] = < (E == A) || !(B == F) >\r
+\r
+        vorn d12, d27, d22              @ E0[0] = < C0 || !(D == B) >\r
+\r
+        vand d13, d15, d23              @ E1[0] = < ((E == C) || !(D == B)) && ((E == A) || !(B == F)) >\r
+\r
+        vorn d14, d27, d26              @ E2[0] = < C0 || !(B == F) >\r
+\r
+        vorr d13, d27, d13              @ E1[0] = < C0 || (((E == C) || !(D == B)) && ((E == A) || !(B == F))) >\r
+\r
+        vbsl d12, d24, d2               @ E0[0] = < (C0 || !(D == B)) ? E : D >\r
+\r
+        vbsl d14, d24, d8               @ E2[0] = < (C0 || !(B == F)) ? E : F >\r
+\r
+        vbsl d13, d24, \dB0             @ E1[0] = < (C0 || (((E == C) || !(D == B)) && ((E == A) || !(B == F)))) ? E : B >\r
+\r
+        vceq.i8 d15, d2, \dH0           @ tmp0[0] = < D == H >\r
+\r
+        vceq.i8 d23, \dH0, d8           @ tmp1[0] = < H == F >\r
+\r
+        vorn d22, d4, d22               @ E3[0] = < (E == G) || !(D == B) >\r
+        vst3.8 {d12-d14}, [\dst1]!      @ [dst] = E0,E1,E2; dst1 += 3*8\r
+\r
+    .if \first15\r
+        addls \dst1, \dst1, \reg1       @ dst1 += reg1\r
+    .endif\r
+\r
+        vorn d26, d10, d26              @ E5[0] = < (E == I) || !(B == F) >\r
+\r
+@ d12 = tmp6[0]\r
+@ d13 = tmp7[0]\r
+\r
+        vorn d12, d0, d15               @ tmp6[0] = < (E == A) || !(D == H) >\r
+\r
+        vorn d13, d6, d23               @ tmp7[0] = < (E == C) || !(H == F) >\r
+\r
+        vand d22, d22, d12              @ E3[0] = < ((E == G) || !(D == B)) && ((E == A) || !(D == H)) >\r
+\r
+        vand d26, d26, d13              @ E5[0] = < ((E == I) || !(B == F)) && ((E == C) || !(H == F)) >\r
+\r
+@ d12 = E6[0]\r
+@ d13 = E7[0]\r
+@ d14 = E8[0]\r
+\r
+        vorr d22, d27, d22              @ E3[0] = < C0 || (((E == G) || !(D == B)) && ((E == A) || !(D == H))) >\r
+\r
+        vorr d26, d27, d26              @ E5[0] = < C0 || (((E == I) || !(B == F)) && ((E == C) || !(H == F))) >\r
+\r
+        vbsl d22, d24, d2               @ E3[0] = < (C0 || (((E == G) || !(D == B)) && ((E == A) || !(D == H)))) ? E : D >\r
+\r
+        vbsl d26, d24, d8               @ E5[0] = < (C0 || (((E == I) || !(B == F)) && ((E == C) || !(H == F)))) ? E : F >\r
+\r
+        vorn d13, d10, d15              @ E7[0] = < (E == I) || !(D == H) >\r
+\r
+        vorn d12, d27, d15              @ E6[0] = < C0 || !(D == H) >\r
+        vst3.8 {d22,d24,d26}, [\dst2]!  @ [dst + dststride] = E3,E4,E5; dst2 += 3*8\r
+\r
+    .if \first15\r
+        addls \dst2, \dst2, \reg1       @ dst2 += reg1\r
+    .endif\r
+\r
+        vorn d15, d4, d23               @ tmp0[0] = < (E == G) || !(H == F) >\r
+\r
+        vorn d14, d27, d23              @ E8[0] = < C0 || !(H == F) >\r
+\r
+        vand d13, d13, d15              @ E7[0] = < ((E == I) || !(D == H)) && ((E == G) || !(H == F)) >\r
+\r
+        vbsl d12, d24, d2               @ E6[0] = < (C0 || !(D == H)) ? E : D >\r
+\r
+        vorr d13, d27, d13              @ E7[0] = < C0 || (((E == I) || !(D == H)) && ((E == G) || !(H == F))) >\r
+\r
+        vbsl d14, d24, d8               @ E8[0] = < (C0 || !(H == F)) ? E : F >\r
+\r
+        vbsl d13, d24, \dH0             @ E7[0] = < (C0 || (((E == I) || !(D == H)) && ((E == G) || !(H == F)))) ? E : H >\r
+\r
+@ d15 = tmp0[1]\r
+@ d22 = tmp1[1]\r
+@ d23 = E3[1]\r
+@ d24 = E4[0]\r
+@ d25 = E4[1]\r
+@ d26 = C0[1]\r
+@ d27 = E5[1]\r
+\r
+        vceq.i8 d15, \dB1, \dH1         @ tmp0[1] = < B == H >\r
+\r
+        vceq.i8 d22, d3, d9             @ tmp1[1] = < D == F >\r
+\r
+        vceq.i8 d23, d3, \dB1           @ E3[1] = < D == B >\r
+        vst3.8 {d12-d14}, [\dst3]!      @ [dst + 2 * dststride] = E6,E7,E8; dst3 += 3*8\r
+\r
+    .if \first15\r
+        addls \dst3, \dst3, \reg1       @ dst3 += reg1\r
+        bls 0f\r
+    .endif\r
+\r
+@ d12 = E0[1]\r
+@ d13 = E1[1]\r
+@ d14 = E2[1]\r
+\r
+        vorr d26, d15, d22              @ C0[1] = < B == H || D == F >\r
+\r
+        vceq.i8 d27, \dB1, d9           @ E5[1] = < B == F >\r
+\r
+        vorn d15, d7, d23               @ tmp0[1] = < (E == C) || !(D == B) >\r
+\r
+        vorn d22, d1, d27               @ tmp1[1] = < (E == A) || !(B == F) >\r
+\r
+        vorn d12, d26, d23              @ E0[1] = < C0 || !(D == B) >\r
+\r
+        vand d13, d15, d22              @ E1[1] = < ((E == C) || !(D == B)) && ((E == A) || !(B == F)) >\r
+\r
+        vorn d14, d26, d27              @ E2[1] = < C0 || !(B == F) >\r
+\r
+        vorr d13, d26, d13              @ E1[1] = < C0 || (((E == C) || !(D == B)) && ((E == A) || !(B == F))) >\r
+\r
+        vbsl d12, d25, d3               @ E0[1] = < (C0 || !(D == B)) ? E : D >\r
+\r
+        vbsl d14, d25, d9               @ E2[1] = < (C0 || !(B == F)) ? E : F >\r
+\r
+        vbsl d13, d25, \dB1             @ E1[1] = < (C0 || (((E == C) || !(D == B)) && ((E == A) || !(B == F)))) ? E : B >\r
+\r
+        vceq.i8 d15, d3, \dH1           @ tmp0[1] = < D == H >\r
+\r
+        vceq.i8 d22, \dH1, d9           @ tmp1[1] = < H == F >\r
+\r
+        vorn d23, d5, d23               @ E3[1] = < (E == G) || !(D == B) >\r
+    .ifeq \first15\r
+        vst3.8 {d12-d14}, [\dst1]!      @ [dst] = E0,E1,E2; dst1 += 3*8\r
+    .else\r
+        vst3.8 {d12-d14}, [\dst1],\reg1 @ [dst] = E0,E1,E2; dst1 += reg1\r
+    .endif\r
+\r
+        vorn d27, d11, d27              @ E5[1] = < (E == I) || !(B == F) >\r
+\r
+@ d12 = tmp6[1]\r
+@ d13 = tmp7[1]\r
+\r
+        vorn d12, d1, d15               @ tmp6[1] = < (E == A) || !(D == H) >\r
+\r
+        vorn d13, d7, d22               @ tmp7[1] = < (E == C) || !(H == F) >\r
+\r
+        vand d23, d23, d12              @ E3[1] = < ((E == G) || !(D == B)) && ((E == A) || !(D == H)) >\r
+\r
+        vand d27, d27, d13              @ E5[1] = < ((E == I) || !(B == F)) && ((E == C) || !(H == F)) >\r
+\r
+@ d12 = E6[1]\r
+@ d13 = E7[1]\r
+@ d14 = E8[1]\r
+\r
+        vorr d23, d26, d23              @ E3[1] = < C0 || (((E == G) || !(D == B)) && ((E == A) || !(D == H))) >\r
+\r
+        vorr d27, d26, d27              @ E5[1] = < C0 || (((E == I) || !(B == F)) && ((E == C) || !(H == F))) >\r
+\r
+        vbsl d23, d25, d3               @ E3[1] = < (C0 || (((E == G) || !(D == B)) && ((E == A) || !(D == H)))) ? E : D >\r
+\r
+        vbsl d27, d25, d9               @ E5[1] = < (C0 || (((E == I) || !(B == F)) && ((E == C) || !(H == F)))) ? E : F >\r
+\r
+        vorn d13, d11, d15              @ E7[1] = < (E == I) || !(D == H) >\r
+\r
+        vorn d12, d26, d15              @ E6[1] = < C0 || !(D == H) >\r
+    .ifeq \first15\r
+        vst3.8 {d23,d25,d27}, [\dst2]!  @ [dst + dststride] = E3,E4,E5; dst2 += 3*8\r
+    .else\r
+        vst3.8 {d23,d25,d27}, [\dst2],\reg1 @ [dst + dststride] = E3,E4,E5; dst2 += reg1\r
+    .endif\r
+\r
+        vorn d15, d5, d22               @ tmp0[1] = < (E == G) || !(H == F) >\r
+\r
+        vorn d14, d26, d22              @ E8[1] = < C0 || !(H == F) >\r
+\r
+        vand d13, d13, d15              @ E7[1] = < ((E == I) || !(D == H)) && ((E == G) || !(H == F)) >\r
+\r
+        vbsl d12, d25, d3               @ E6[1] = < (C0 || !(D == H)) ? E : D >\r
+\r
+        vorr d13, d26, d13              @ E7[1] = < C0 || (((E == I) || !(D == H)) && ((E == G) || !(H == F))) >\r
+\r
+        vbsl d14, d25, d9               @ E8[1] = < (C0 || !(H == F)) ? E : F >\r
+\r
+        vbsl d13, d25, \dH1             @ E7[1] = < (C0 || (((E == I) || !(D == H)) && ((E == G) || !(H == F)))) ? E : H >\r
+\r
+    .ifeq \first15\r
+\r
+    .ifeq \last16\r
+        sub \counter, \counter, #16     @ counter -= 16\r
+        cmp \counter, #16\r
+    .endif\r
+\r
+        vst3.8 {d12-d14}, [\dst3]!      @ [dst + 2 * dststride] = E6,E7,E8; dst3 += 3*8\r
+    .else\r
+        vst3.8 {d12-d14}, [\dst3],\reg1 @ [dst + 2 * dststride] = E6,E7,E8; dst3 += reg1\r
+\r
+    0:\r
+    .endif\r
+\r
+.endm\r
+\r
+.macro __neon_scale3x_8_8_line src1, src2, src3, counter, dst1, dst2, dst3, reg1, qB, qH, dB0, dB1, dH0, dH1, alsrc1, alsrc2, alsrc3, aldst1, aldst2, aldst3\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vld1.8 {d29[7]}, [\src1]        @ S1prev[15] = src[-srcstride]\r
+    .endif\r
+        vld1.8 {d25[7]}, [\src2]        @ S2prev[15] = src[0]\r
+    .ifeqs "\qH", "q15"\r
+        vld1.8 {d31[7]}, [\src3]        @ S3prev[15] = src[srcstride]\r
+    .endif\r
+        andS \reg1, \counter, #15       @ reg1 = counter & 15\r
+\r
+    .ifnes "\qB", "q14"\r
+        add \src1, \src1, \counter      @ src1 += counter\r
+    .endif\r
+    .ifnes "\qH", "q15"\r
+        add \src3, \src3, \counter      @ src3 += counter\r
+    .endif\r
+        beq 1f\r
+\r
+    @ first 1-15 pixels - align counter to 16 bytes\r
+\r
+        sub \reg1, \reg1, #1            @ reg1 = (counter & 15) - 1\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vld1.8 {q8}, [\src1]            @ S1 = [src - srcstride]\r
+        add \src1, \src1, \reg1         @ src1 += (counter & 15) - 1\r
+    .endif\r
+\r
+        vld1.8 {q9}, [\src2]            @ S2 = [src            ]\r
+        add \src2, \src2, \reg1         @ src2 += (counter & 15) - 1\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vld1.8 {q10}, [\src3]           @ S3 = [src + srcstride]\r
+        add \src3, \src3, \reg1         @ src3 += (counter & 15) - 1\r
+    .endif\r
+    .ifeqs "\qB", "q14"\r
+        vext.8 q0, \qB, q8, #15         @ S1sl = S1prev[15] | (S1 << 8)     < S >\r
+\r
+        vmov \qB, q8                    @ S1prev = S1       < T >\r
+    .endif\r
+        vext.8 q1, q12, q9, #15         @ S2sl = S2prev[15] | (S2 << 8)     < V >\r
+\r
+        vmov q12, q9                    @ S2prev = S2       < C >\r
+    .ifeqs "\qH", "q15"\r
+        vext.8 q2, \qH, q10, #15        @ S3sl = S3prev[15] | (S3 << 8)     < X >\r
+\r
+        vmov \qH, q10                   @ S3prev = S3       < Y >\r
+    .endif\r
+    .ifeqs "\qB", "q14"\r
+        vext.8 q3, \qB, q8, #1          @ S1sr = (S1prev >> 8) | ...        < U >\r
+    .endif\r
+\r
+        vext.8 q4, q12, q9, #1          @ S2sr = (S2prev >> 8) | ...        < W >\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vext.8 q5, \qH, q10, #1         @ S3sr = (S3prev >> 8) | ...        < Z >\r
+    .else\r
+        vmov q2, q1                     @ S3sl = S2sl       < X >\r
+\r
+        vmov q5, q4                     @ S3sr = S2sr       < Z >\r
+    .endif\r
+\r
+    .ifnes "\qB", "q14"\r
+        vmov q0, q1                     @ S1sl = S2sl       < S >\r
+\r
+        vmov q3, q4                     @ S1sr = S2sr       < U >\r
+    .else\r
+        vld1.8 {d29[7]}, [\src1]!       @ S1prev[15] = src[counter & 15 - 1 - srcstride]; src1++\r
+    .endif\r
+\r
+        add \reg1, \reg1, #1            @ reg1 = counter & 15\r
+\r
+        vld1.8 {d25[7]}, [\src2]!       @ S2prev[15] = src[counter & 15 - 1]; src2++\r
+\r
+        bic \counter, \counter, #15\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vld1.8 {d31[7]}, [\src3]!       @ S3prev[15] = src[counter & 15 - 1 + srcstride]; src3++\r
+    .endif\r
+\r
+        ___neon_scale3x_8_8_slice \counter, \dst1, \dst2, \dst3, \reg1, \dB0, \dB1, \dH0, \dH1, 1, 0\r
+\r
+\r
+    @ counter is aligned to 16 bytes\r
+\r
+    1:\r
+    .ifeqs "\qB", "q14"\r
+        vld1.8 {q8}, [\alsrc1]!         @ S1 = [src - srcstride]; src1 += 16\r
+    .endif\r
+        vld1.8 {q9}, [\alsrc2]!         @ S2 = [src            ]; src2 += 16\r
+    .ifeqs "\qH", "q15"\r
+        vld1.8 {q10}, [\alsrc3]!        @ S3 = [src + srcstride]; src3 += 16\r
+    .endif\r
+\r
+    @ inner loop (16 pixels per iteration)\r
+    2:\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vext.8 q0, \qB, q8, #15         @ S1sl = S1prev[15] | (S1 << 8)     < A >\r
+        vmov \qB, q8                    @ S1prev = S1       < B >\r
+    .endif\r
+\r
+        vext.8 q1, q12, q9, #15         @ S2sl = S2prev[15] | (S2 << 8)     < D >\r
+        vmov q12, q9                    @ S2prev = S2       < E >\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vext.8 q2, \qH, q10, #15        @ S3sl = S3prev[15] | (S3 << 8)     < G >\r
+        vmov \qH, q10                   @ S3prev = S3       < H >\r
+    .endif\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vld1.8 {q8}, [\alsrc1]!         @ S1 = [src - srcstride]; src1 += 16\r
+        vext.8 q3, \qB, q8, #1          @ S1sr = (S1prev >> 8) | S1[0]      < C >\r
+    .endif\r
+\r
+        vld1.8 {q9}, [\alsrc2]!         @ S2 = [src            ]; src2 += 16\r
+        vext.8 q4, q12, q9, #1          @ S2sr = (S2prev >> 8) | S2[0]      < F >\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vld1.8 {q10}, [\alsrc3]!        @ S3 = [src + srcstride]; src3 += 16\r
+        vext.8 q5, \qH, q10, #1         @ S3sr = (S3prev >> 8) | S3[0]      < I >\r
+    .else\r
+        vmov q2, q1                     @ S3sl = S2sl       < G >\r
+\r
+        vmov q5, q4                     @ S3sr = S2sr       < I >\r
+    .endif\r
+\r
+    .ifnes "\qB", "q14"\r
+        vmov q0, q1                     @ S1sl = S2sl       < A >\r
+\r
+        vmov q3, q4                     @ S1sr = S2sr       < C >\r
+    .endif\r
+\r
+        ___neon_scale3x_8_8_slice \counter, \aldst1, \aldst2, \aldst3, \reg1, \dB0, \dB1, \dH0, \dH1, 0, 0\r
+\r
+        bhi 2b\r
+\r
+    @ last 16 pixels\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vext.8 q0, \qB, q8, #15         @ S1sl = S1prev[15] | (S1 << 8)     < A >\r
+        vmov \qB, q8                    @ S1prev = S1       < B >\r
+    .endif\r
+\r
+        vext.8 q1, q12, q9, #15         @ S2sl = S2prev[15] | (S2 << 8)     < D >\r
+        vmov q12, q9                    @ S2prev = S2       < E >\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vext.8 q2, \qH, q10, #15        @ S3sl = S3prev[15] | (S3 << 8)     < G >\r
+        vmov \qH, q10                   @ S3prev = S3       < H >\r
+    .endif\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vshr.u64 d16, d17, #(64-8)      @ S1[0] = S1[15] | ...\r
+    .endif\r
+\r
+        vshr.u64 d18, d19, #(64-8)      @ S2[0] = S2[15] | ...\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vshr.u64 d20, d21, #(64-8)      @ S3[0] = S3[15] | ...\r
+    .endif\r
+    .ifeqs "\qB", "q14"\r
+        vext.8 q3, \qB, q8, #1          @ S1sr = (S1prev >> 8) | S1[0]      < C >\r
+    .endif\r
+\r
+        vext.8 q4, q12, q9, #1          @ S2sr = (S2prev >> 8) | S2[0]      < F >\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vext.8 q5, \qH, q10, #1         @ S3sr = (S3prev >> 8) | S3[0]      < I >\r
+    .else\r
+        vmov q2, q1                     @ S3sl = S2sl       < G >\r
+\r
+        vmov q5, q4                     @ S3sr = S2sr       < I >\r
+    .endif\r
+\r
+    .ifnes "\qB", "q14"\r
+        vmov q0, q1                     @ S1sl = S2sl       < A >\r
+\r
+        vmov q3, q4                     @ S1sr = S2sr       < C >\r
+    .endif\r
+\r
+        ___neon_scale3x_8_8_slice \counter, \aldst1, \aldst2, \aldst3, \reg1, \dB0, \dB1, \dH0, \dH1, 0, 1\r
+\r
+.endm\r
+\r
+.macro _neon_scale3x_8_8_line_first src1, src2, src3, counter, dst1, dst2, dst3, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2, aldst3\r
+        __neon_scale3x_8_8_line \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, q12, q15, d24, d25, d30, d31, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2, \aldst3\r
+.endm\r
+\r
+.macro _neon_scale3x_8_8_line_middle src1, src2, src3, counter, dst1, dst2, dst3, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2, aldst3\r
+        __neon_scale3x_8_8_line \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, q14, q15, d28, d29, d30, d31, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2, \aldst3\r
+.endm\r
+\r
+.macro _neon_scale3x_8_8_line_last src1, src2, src3, counter, dst1, dst2, dst3, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2, aldst3\r
+        __neon_scale3x_8_8_line \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, q14, q12, d28, d29, d24, d25, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2, \aldst3\r
+.endm\r
+\r
+.macro neon_scale3x_8_8_line part, src1, src2, src3, counter, dst1, dst2, dst3, reg1, srcalign16, dstalign8\r
+    .ifeq \srcalign16\r
+\r
+    .ifeq \dstalign8\r
+        _neon_scale3x_8_8_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, \src1, \src2, \src3, \dst1, \dst2, \dst3\r
+    .else\r
+        _neon_scale3x_8_8_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, \src1, \src2, \src3, \dst1:64, \dst2:64, \dst3:64\r
+    .endif\r
+\r
+    .else\r
+\r
+    .ifeq \dstalign8\r
+        _neon_scale3x_8_8_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, \src1:128, \src2:128, \src3:128, \dst1, \dst2, \dst3\r
+    .else\r
+        _neon_scale3x_8_8_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, \src1:128, \src2:128, \src3:128, \dst1:64, \dst2:64, \dst3:64\r
+    .endif\r
+\r
+    .endif\r
+.endm\r
+\r
+\r
+.macro ___neon_scale3x_16_16_slice counter, dst1, dst2, dst3, reg1, dB0, dB1, dH0, dH1, first7, last8\r
+\r
+@ d12 = E0[0]\r
+@ d13 = E1[0]\r
+@ d14 = E2[0]\r
+@ d15 = tmp0[0]\r
+@ d22 = E3[0]\r
+@ d23 = tmp1[0]\r
+@ d24 = E4[0]\r
+@ d25 = E4[1]\r
+@ d26 = E5[0]\r
+@ d27 = C0[0]\r
+\r
+@ q0  = tmp2\r
+@ q3  = tmp3\r
+@ q2  = tmp4\r
+@ q5  = tmp5\r
+\r
+        vceq.i16 d15, \dB0, \dH0        @ tmp0[0] = < B == H >\r
+\r
+        vceq.i16 d23, d2, d8            @ tmp1[0] = < D == F >\r
+\r
+    .if \first7\r
+        cmp \reg1, #4\r
+    .endif\r
+\r
+        vceq.i16 q0, q12, q0            @ tmp2 = < E == A >\r
+\r
+        vceq.i16 q3, q12, q3            @ tmp3 = < E == C >\r
+\r
+    .if \first7\r
+        lsl \reg1, #1                   @ reg1 = 2 * (counter & 7)\r
+    .endif\r
+\r
+        vorr d27, d15, d23              @ C0[0] = < B == H || D == F >\r
+\r
+        vceq.i16 d22, d2, \dB0          @ E3[0] = < D == B >\r
+\r
+        vceq.i16 d26, \dB0, d8          @ E5[0] = < B == F >\r
+\r
+        vceq.i16 q2, q12, q2            @ tmp4 = < E == G >\r
+\r
+        vceq.i16 q5, q12, q5            @ tmp5 = < E == I >\r
+\r
+    .if \first7\r
+        add \reg1, \reg1, \reg1, lsl #1 @ reg1 = 2 * 3 * (counter & 7)\r
+    .endif\r
+\r
+        vorn d15, d6, d22               @ tmp0[0] = < (E == C) || !(D == B) >\r
+\r
+        vorn d23, d0, d26               @ tmp1[0] = < (E == A) || !(B == F) >\r
+\r
+        vorn d12, d27, d22              @ E0[0] = < C0 || !(D == B) >\r
+\r
+    .if \first7\r
+        sub \reg1, \reg1, #(3*2*4)      @ reg1 -= 3*2*4\r
+    .endif\r
+\r
+        vand d13, d15, d23              @ E1[0] = < ((E == C) || !(D == B)) && ((E == A) || !(B == F)) >\r
+\r
+        vorn d14, d27, d26              @ E2[0] = < C0 || !(B == F) >\r
+\r
+        vorr d13, d27, d13              @ E1[0] = < C0 || (((E == C) || !(D == B)) && ((E == A) || !(B == F))) >\r
+\r
+        vbsl d12, d24, d2               @ E0[0] = < (C0 || !(D == B)) ? E : D >\r
+\r
+        vbsl d14, d24, d8               @ E2[0] = < (C0 || !(B == F)) ? E : F >\r
+\r
+        vbsl d13, d24, \dB0             @ E1[0] = < (C0 || (((E == C) || !(D == B)) && ((E == A) || !(B == F)))) ? E : B >\r
+\r
+        vceq.i16 d15, d2, \dH0          @ tmp0[0] = < D == H >\r
+\r
+        vceq.i16 d23, \dH0, d8          @ tmp1[0] = < H == F >\r
+\r
+        vorn d22, d4, d22               @ E3[0] = < (E == G) || !(D == B) >\r
+        vst3.16 {d12-d14}, [\dst1]!     @ [dst] = E0,E1,E2; dst1 += 3*2*4\r
+\r
+    .if \first7\r
+        addls \dst1, \dst1, \reg1       @ dst1 += reg1\r
+    .endif\r
+\r
+        vorn d26, d10, d26              @ E5[0] = < (E == I) || !(B == F) >\r
+\r
+@ d12 = tmp6[0]\r
+@ d13 = tmp7[0]\r
+\r
+        vorn d12, d0, d15               @ tmp6[0] = < (E == A) || !(D == H) >\r
+\r
+        vorn d13, d6, d23               @ tmp7[0] = < (E == C) || !(H == F) >\r
+\r
+        vand d22, d22, d12              @ E3[0] = < ((E == G) || !(D == B)) && ((E == A) || !(D == H)) >\r
+\r
+        vand d26, d26, d13              @ E5[0] = < ((E == I) || !(B == F)) && ((E == C) || !(H == F)) >\r
+\r
+@ d12 = E6[0]\r
+@ d13 = E7[0]\r
+@ d14 = E8[0]\r
+\r
+        vorr d22, d27, d22              @ E3[0] = < C0 || (((E == G) || !(D == B)) && ((E == A) || !(D == H))) >\r
+\r
+        vorr d26, d27, d26              @ E5[0] = < C0 || (((E == I) || !(B == F)) && ((E == C) || !(H == F))) >\r
+\r
+        vbsl d22, d24, d2               @ E3[0] = < (C0 || (((E == G) || !(D == B)) && ((E == A) || !(D == H)))) ? E : D >\r
+\r
+        vbsl d26, d24, d8               @ E5[0] = < (C0 || (((E == I) || !(B == F)) && ((E == C) || !(H == F)))) ? E : F >\r
+\r
+        vorn d13, d10, d15              @ E7[0] = < (E == I) || !(D == H) >\r
+\r
+        vorn d12, d27, d15              @ E6[0] = < C0 || !(D == H) >\r
+        vst3.16 {d22,d24,d26}, [\dst2]! @ [dst + dststride] = E3,E4,E5; dst2 += 3*2*4\r
+\r
+    .if \first7\r
+        addls \dst2, \dst2, \reg1       @ dst2 += reg1\r
+    .endif\r
+\r
+        vorn d15, d4, d23               @ tmp0[0] = < (E == G) || !(H == F) >\r
+\r
+        vorn d14, d27, d23              @ E8[0] = < C0 || !(H == F) >\r
+\r
+        vand d13, d13, d15              @ E7[0] = < ((E == I) || !(D == H)) && ((E == G) || !(H == F)) >\r
+\r
+        vbsl d12, d24, d2               @ E6[0] = < (C0 || !(D == H)) ? E : D >\r
+\r
+        vorr d13, d27, d13              @ E7[0] = < C0 || (((E == I) || !(D == H)) && ((E == G) || !(H == F))) >\r
+\r
+        vbsl d14, d24, d8               @ E8[0] = < (C0 || !(H == F)) ? E : F >\r
+\r
+        vbsl d13, d24, \dH0             @ E7[0] = < (C0 || (((E == I) || !(D == H)) && ((E == G) || !(H == F)))) ? E : H >\r
+\r
+@ d15 = tmp0[1]\r
+@ d22 = tmp1[1]\r
+@ d23 = E3[1]\r
+@ d24 = E4[0]\r
+@ d25 = E4[1]\r
+@ d26 = C0[1]\r
+@ d27 = E5[1]\r
+\r
+        vceq.i16 d15, \dB1, \dH1        @ tmp0[1] = < B == H >\r
+\r
+        vceq.i16 d22, d3, d9            @ tmp1[1] = < D == F >\r
+\r
+        vceq.i16 d23, d3, \dB1          @ E3[1] = < D == B >\r
+        vst3.16 {d12-d14}, [\dst3]!     @ [dst + 2 * dststride] = E6,E7,E8; dst3 += 3*2*4\r
+\r
+    .if \first7\r
+        addls \dst3, \dst3, \reg1       @ dst3 += reg1\r
+        bls 0f\r
+    .endif\r
+\r
+@ d12 = E0[1]\r
+@ d13 = E1[1]\r
+@ d14 = E2[1]\r
+\r
+        vorr d26, d15, d22              @ C0[1] = < B == H || D == F >\r
+\r
+        vceq.i16 d27, \dB1, d9          @ E5[1] = < B == F >\r
+\r
+        vorn d15, d7, d23               @ tmp0[1] = < (E == C) || !(D == B) >\r
+\r
+        vorn d22, d1, d27               @ tmp1[1] = < (E == A) || !(B == F) >\r
+\r
+        vorn d12, d26, d23              @ E0[1] = < C0 || !(D == B) >\r
+\r
+        vand d13, d15, d22              @ E1[1] = < ((E == C) || !(D == B)) && ((E == A) || !(B == F)) >\r
+\r
+        vorn d14, d26, d27              @ E2[1] = < C0 || !(B == F) >\r
+\r
+        vorr d13, d26, d13              @ E1[1] = < C0 || (((E == C) || !(D == B)) && ((E == A) || !(B == F))) >\r
+\r
+        vbsl d12, d25, d3               @ E0[1] = < (C0 || !(D == B)) ? E : D >\r
+\r
+        vbsl d14, d25, d9               @ E2[1] = < (C0 || !(B == F)) ? E : F >\r
+\r
+        vbsl d13, d25, \dB1             @ E1[1] = < (C0 || (((E == C) || !(D == B)) && ((E == A) || !(B == F)))) ? E : B >\r
+\r
+        vceq.i16 d15, d3, \dH1          @ tmp0[1] = < D == H >\r
+\r
+        vceq.i16 d22, \dH1, d9          @ tmp1[1] = < H == F >\r
+\r
+        vorn d23, d5, d23               @ E3[1] = < (E == G) || !(D == B) >\r
+    .ifeq \first7\r
+        vst3.16 {d12-d14}, [\dst1]!     @ [dst] = E0,E1,E2; dst1 += 3*2*4\r
+    .else\r
+        vst3.16 {d12-d14}, [\dst1], \reg1   @ [dst] = E0,E1,E2; dst1 += reg1\r
+    .endif\r
+\r
+        vorn d27, d11, d27              @ E5[1] = < (E == I) || !(B == F) >\r
+\r
+@ d12 = tmp6[1]\r
+@ d13 = tmp7[1]\r
+\r
+        vorn d12, d1, d15               @ tmp6[1] = < (E == A) || !(D == H) >\r
+\r
+        vorn d13, d7, d22               @ tmp7[1] = < (E == C) || !(H == F) >\r
+\r
+        vand d23, d23, d12              @ E3[1] = < ((E == G) || !(D == B)) && ((E == A) || !(D == H)) >\r
+\r
+        vand d27, d27, d13              @ E5[1] = < ((E == I) || !(B == F)) && ((E == C) || !(H == F)) >\r
+\r
+@ d12 = E6[1]\r
+@ d13 = E7[1]\r
+@ d14 = E8[1]\r
+\r
+        vorr d23, d26, d23              @ E3[1] = < C0 || (((E == G) || !(D == B)) && ((E == A) || !(D == H))) >\r
+\r
+        vorr d27, d26, d27              @ E5[1] = < C0 || (((E == I) || !(B == F)) && ((E == C) || !(H == F))) >\r
+\r
+        vbsl d23, d25, d3               @ E3[1] = < (C0 || (((E == G) || !(D == B)) && ((E == A) || !(D == H)))) ? E : D >\r
+\r
+        vbsl d27, d25, d9               @ E5[1] = < (C0 || (((E == I) || !(B == F)) && ((E == C) || !(H == F)))) ? E : F >\r
+\r
+        vorn d13, d11, d15              @ E7[1] = < (E == I) || !(D == H) >\r
+\r
+        vorn d12, d26, d15              @ E6[1] = < C0 || !(D == H) >\r
+    .ifeq \first7\r
+        vst3.16 {d23,d25,d27}, [\dst2]! @ [dst + dststride] = E3,E4,E5; dst2 += 3*2*4\r
+    .else\r
+        vst3.16 {d23,d25,d27}, [\dst2], \reg1   @ [dst + dststride] = E3,E4,E5; dst2 += reg1\r
+    .endif\r
+\r
+        vorn d15, d5, d22               @ tmp0[1] = < (E == G) || !(H == F) >\r
+\r
+        vorn d14, d26, d22              @ E8[1] = < C0 || !(H == F) >\r
+\r
+        vand d13, d13, d15              @ E7[1] = < ((E == I) || !(D == H)) && ((E == G) || !(H == F)) >\r
+\r
+        vbsl d12, d25, d3               @ E6[1] = < (C0 || !(D == H)) ? E : D >\r
+\r
+        vorr d13, d26, d13              @ E7[1] = < C0 || (((E == I) || !(D == H)) && ((E == G) || !(H == F))) >\r
+\r
+        vbsl d14, d25, d9               @ E8[1] = < (C0 || !(H == F)) ? E : F >\r
+\r
+        vbsl d13, d25, \dH1             @ E7[1] = < (C0 || (((E == I) || !(D == H)) && ((E == G) || !(H == F)))) ? E : H >\r
+\r
+    .ifeq \first7\r
+\r
+    .ifeq \last8\r
+        sub \counter, \counter, #8      @ counter -= 8\r
+        cmp \counter, #8\r
+    .endif\r
+\r
+        vst3.16 {d12-d14}, [\dst3]!     @ [dst + 2 * dststride] = E6,E7,E8; dst3 += 3*2*4\r
+    .else\r
+        vst3.16 {d12-d14}, [\dst3], \reg1   @ [dst + 2 * dststride] = E6,E7,E8; dst3 += reg1\r
+\r
+    0:\r
+    .endif\r
+\r
+.endm\r
+\r
+.macro __neon_scale3x_16_16_line src1, src2, src3, counter, dst1, dst2, dst3, reg1, qB, qH, dB0, dB1, dH0, dH1, alsrc1, alsrc2, alsrc3, aldst1, aldst2, aldst3\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vld1.16 {d29[3]}, [\src1]       @ S1prev[7] = src[-srcstride]\r
+    .endif\r
+        vld1.16 {d25[3]}, [\src2]       @ S2prev[7] = src[0]\r
+    .ifeqs "\qH", "q15"\r
+        vld1.16 {d31[3]}, [\src3]       @ S3prev[7] = src[srcstride]\r
+    .endif\r
+        andS \reg1, \counter, #7        @ reg1 = counter & 7\r
+\r
+    .ifnes "\qB", "q14"\r
+        add \src1, \src1, \counter, lsl #1  @ src1 += 2 * counter\r
+    .endif\r
+    .ifnes "\qH", "q15"\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
+\r
+        sub \reg1, \reg1, #1            @ reg1 = (counter & 7) - 1\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vld1.16 {q8}, [\src1]           @ S1 = [src - srcstride]\r
+        add \src1, \src1, \reg1, lsl #1 @ src1 += 2 * ((counter & 7) - 1)\r
+    .endif\r
+\r
+        vld1.16 {q9}, [\src2]           @ S2 = [src            ]\r
+        add \src2, \src2, \reg1, lsl #1 @ src2 += 2 * ((counter & 7) - 1)\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vld1.16 {q10}, [\src3]          @ S3 = [src + srcstride]\r
+        add \src3, \src3, \reg1, lsl #1 @ src3 += 2 * ((counter & 7) - 1)\r
+    .endif\r
+    .ifeqs "\qB", "q14"\r
+        vext.8 q0, \qB, q8, #14         @ S1sl = S1prev[7] | (S1 << 16)     < S >\r
+\r
+        vmov \qB, q8                    @ S1prev = S1       < T >\r
+    .endif\r
+        vext.8 q1, q12, q9, #14         @ S2sl = S2prev[7] | (S2 << 16)     < V >\r
+\r
+        vmov q12, q9                    @ S2prev = S2       < C >\r
+    .ifeqs "\qH", "q15"\r
+        vext.8 q2, \qH, q10, #14        @ S3sl = S3prev[7] | (S3 << 16)     < X >\r
+\r
+        vmov \qH, q10                   @ S3prev = S3       < Y >\r
+    .endif\r
+    .ifeqs "\qB", "q14"\r
+        vext.8 q3, \qB, q8, #2          @ S1sr = (S1prev >> 16) | ...        < U >\r
+    .endif\r
+\r
+        vext.8 q4, q12, q9, #2          @ S2sr = (S2prev >> 16) | ...        < W >\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vext.8 q5, \qH, q10, #2         @ S3sr = (S3prev >> 16) | ...        < Z >\r
+    .else\r
+        vmov q2, q1                     @ S3sl = S2sl       < X >\r
+\r
+        vmov q5, q4                     @ S3sr = S2sr       < Z >\r
+    .endif\r
+\r
+    .ifnes "\qB", "q14"\r
+        vmov q0, q1                     @ S1sl = S2sl       < S >\r
+\r
+        vmov q3, q4                     @ S1sr = S2sr       < U >\r
+    .else\r
+        vld1.16 {d29[3]}, [\src1]!      @ S1prev[7] = src[counter & 7 - 1 - srcstride]; src1 += 2\r
+    .endif\r
+\r
+        add \reg1, \reg1, #1            @ reg1 = counter & 7\r
+\r
+        vld1.16 {d25[3]}, [\src2]!      @ S2prev[7] = src[counter & 7 - 1]; src2 += 2\r
+\r
+        bic \counter, \counter, #7\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vld1.16 {d31[3]}, [\src3]!      @ S3prev[7] = src[counter & 7 - 1 + srcstride]; src3 += 2\r
+    .endif\r
+\r
+        ___neon_scale3x_16_16_slice \counter, \dst1, \dst2, \dst3, \reg1, \dB0, \dB1, \dH0, \dH1, 1, 0\r
+\r
+\r
+    @ counter is aligned to 16 bytes\r
+\r
+    1:\r
+    .ifeqs "\qB", "q14"\r
+        vld1.16 {q8}, [\alsrc1]!        @ S1 = [src - srcstride]; src1 += 2*8\r
+    .endif\r
+        vld1.16 {q9}, [\alsrc2]!        @ S2 = [src            ]; src2 += 2*8\r
+    .ifeqs "\qH", "q15"\r
+        vld1.16 {q10}, [\alsrc3]!       @ S3 = [src + srcstride]; src3 += 2*8\r
+    .endif\r
+\r
+    @ inner loop (8 pixels per iteration)\r
+    2:\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vext.8 q0, \qB, q8, #14         @ S1sl = S1prev[7] | (S1 << 16)     < A >\r
+        vmov \qB, q8                    @ S1prev = S1       < B >\r
+    .endif\r
+\r
+        vext.8 q1, q12, q9, #14         @ S2sl = S2prev[7] | (S2 << 16)     < D >\r
+        vmov q12, q9                    @ S2prev = S2       < E >\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vext.8 q2, \qH, q10, #14        @ S3sl = S3prev[7] | (S3 << 16)     < G >\r
+        vmov \qH, q10                   @ S3prev = S3       < H >\r
+    .endif\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vld1.16 {q8}, [\alsrc1]!        @ S1 = [src - srcstride]; src1 += 2*8\r
+        vext.8 q3, \qB, q8, #2          @ S1sr = (S1prev >> 16) | S1[0]      < C >\r
+    .endif\r
+\r
+        vld1.16 {q9}, [\alsrc2]!        @ S2 = [src            ]; src2 += 2*8\r
+        vext.8 q4, q12, q9, #2          @ S2sr = (S2prev >> 16) | S2[0]      < F >\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vld1.16 {q10}, [\alsrc3]!       @ S3 = [src + srcstride]; src3 += 2*8\r
+        vext.8 q5, \qH, q10, #2         @ S3sr = (S3prev >> 16) | S3[0]      < I >\r
+    .else\r
+        vmov q2, q1                     @ S3sl = S2sl       < G >\r
+\r
+        vmov q5, q4                     @ S3sr = S2sr       < I >\r
+    .endif\r
+\r
+    .ifnes "\qB", "q14"\r
+        vmov q0, q1                     @ S1sl = S2sl       < A >\r
+\r
+        vmov q3, q4                     @ S1sr = S2sr       < C >\r
+    .endif\r
+\r
+        ___neon_scale3x_16_16_slice \counter, \aldst1, \aldst2, \aldst3, \reg1, \dB0, \dB1, \dH0, \dH1, 0, 0\r
+\r
+        bhi 2b\r
+\r
+    @ last 8 pixels\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vext.8 q0, \qB, q8, #14         @ S1sl = S1prev[7] | (S1 << 16)     < A >\r
+        vmov \qB, q8                    @ S1prev = S1       < B >\r
+    .endif\r
+\r
+        vext.8 q1, q12, q9, #14         @ S2sl = S2prev[7] | (S2 << 16)     < D >\r
+        vmov q12, q9                    @ S2prev = S2       < E >\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vext.8 q2, \qH, q10, #14        @ S3sl = S3prev[7] | (S3 << 16)     < G >\r
+        vmov \qH, q10                   @ S3prev = S3       < H >\r
+    .endif\r
+\r
+    .ifeqs "\qB", "q14"\r
+        vshr.u64 d16, d17, #(64-16)     @ S1[0] = S1[7] | ...\r
+    .endif\r
+\r
+        vshr.u64 d18, d19, #(64-16)     @ S2[0] = S2[7] | ...\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vshr.u64 d20, d21, #(64-16)     @ S3[0] = S3[7] | ...\r
+    .endif\r
+    .ifeqs "\qB", "q14"\r
+        vext.8 q3, \qB, q8, #2          @ S1sr = (S1prev >> 16) | S1[0]      < C >\r
+    .endif\r
+\r
+        vext.8 q4, q12, q9, #2          @ S2sr = (S2prev >> 16) | S2[0]      < F >\r
+\r
+    .ifeqs "\qH", "q15"\r
+        vext.8 q5, \qH, q10, #2         @ S3sr = (S3prev >> 16) | S3[0]      < I >\r
+    .else\r
+        vmov q2, q1                     @ S3sl = S2sl       < G >\r
+\r
+        vmov q5, q4                     @ S3sr = S2sr       < I >\r
+    .endif\r
+\r
+    .ifnes "\qB", "q14"\r
+        vmov q0, q1                     @ S1sl = S2sl       < A >\r
+\r
+        vmov q3, q4                     @ S1sr = S2sr       < C >\r
+    .endif\r
+\r
+        ___neon_scale3x_16_16_slice \counter, \aldst1, \aldst2, \aldst3, \reg1, \dB0, \dB1, \dH0, \dH1, 0, 1\r
+\r
+.endm\r
+\r
+.macro _neon_scale3x_16_16_line_first src1, src2, src3, counter, dst1, dst2, dst3, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2, aldst3\r
+        __neon_scale3x_16_16_line \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, q12, q15, d24, d25, d30, d31, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2, \aldst3\r
+.endm\r
+\r
+.macro _neon_scale3x_16_16_line_middle src1, src2, src3, counter, dst1, dst2, dst3, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2, aldst3\r
+        __neon_scale3x_16_16_line \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, q14, q15, d28, d29, d30, d31, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2, \aldst3\r
+.endm\r
+\r
+.macro _neon_scale3x_16_16_line_last src1, src2, src3, counter, dst1, dst2, dst3, reg1, alsrc1, alsrc2, alsrc3, aldst1, aldst2, aldst3\r
+        __neon_scale3x_16_16_line \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, q14, q12, d28, d29, d24, d25, \alsrc1, \alsrc2, \alsrc3, \aldst1, \aldst2, \aldst3\r
+.endm\r
+\r
+.macro neon_scale3x_16_16_line part, src1, src2, src3, counter, dst1, dst2, dst3, reg1, srcalign16, dstalign8\r
+    .ifeq \srcalign16\r
+\r
+    .ifeq \dstalign8\r
+        _neon_scale3x_16_16_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, \src1, \src2, \src3, \dst1, \dst2, \dst3\r
+    .else\r
+        _neon_scale3x_16_16_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, \src1, \src2, \src3, \dst1:64, \dst2:64, \dst3:64\r
+    .endif\r
+\r
+    .else\r
+\r
+    .ifeq \dstalign8\r
+        _neon_scale3x_16_16_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, \src1:128, \src2:128, \src3:128, \dst1, \dst2, \dst3\r
+    .else\r
+        _neon_scale3x_16_16_line_\part \src1, \src2, \src3, \counter, \dst1, \dst2, \dst3, \reg1, \src1:128, \src2:128, \src3:128, \dst1:64, \dst2:64, \dst3:64\r
+    .endif\r
+\r
+    .endif\r
+.endm\r
+\r