add M-HT's neon scalers
[fceu.git] / drivers / arm / neon_normalxx.Sinc
diff --git a/drivers/arm/neon_normalxx.Sinc b/drivers/arm/neon_normalxx.Sinc
new file mode 100644 (file)
index 0000000..fcbcfd4
--- /dev/null
@@ -0,0 +1,665 @@
+@@\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
+\r
+.macro _neon_normalxx_8_16_line_middle src, dst, pal, counter, reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8, reg9, dststride, dA, dB\r
+        ldr \reg1, [\src]                   @ reg1 = src[0-3]\r
+\r
+        ldr \reg2, [\src, #4]               @ reg2 = src[4-7]\r
+\r
+        ldr \reg3, [\src, #8]               @ reg3 = src[8-11]\r
+\r
+        ldr \reg4, [\src, #12]              @ reg4 = src[12-15]\r
+        ubfx \reg5, \reg1, #0, #8           @ reg5 = src[0]\r
+\r
+        ldr \reg5, [\pal, \reg5, lsl #2]    @ reg5 = pal[src[0]]\r
+        ubfx \reg6, \reg1, #8, #8           @ reg6 = src[1]\r
+\r
+        ldr \reg6, [\pal, \reg6, lsl #2]    @ reg6 = pal[src[1]]\r
+        ubfx \reg7, \reg1, #16, #8          @ reg7 = src[2]\r
+\r
+        ldr \reg7, [\pal, \reg7, lsl #2]    @ reg7 = pal[src[2]]\r
+        lsr    \reg1, \reg1, #24               @ reg1 = src[3]\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[3]]\r
+        ubfx \reg8, \reg2, #0, #8           @ reg8 = src[4]\r
+\r
+        ldr \reg8, [\pal, \reg8, lsl #2]    @ reg8 = pal[src[4]]\r
+        ubfx \reg9, \reg2, #8, #8           @ reg9 = src[5]\r
+\r
+        ldr \reg9, [\pal, \reg9, lsl #2]    @ reg9 = pal[src[5]]\r
+        bfi \reg5, \reg6, #16, #16          @ reg5 = pal[src[0]] | pal[src[1]] << 16\r
+\r
+        bfi \reg7, \reg1, #16, #16          @ reg7 = pal[src[2]] | pal[src[3]] << 16\r
+        ubfx \reg6, \reg2, #16, #8          @ reg6 = src[6]\r
+\r
+        vmov d16, \reg5, \reg7              @ d16 = pal[src[0-3]]\r
+        lsr    \reg2, \reg2, #24               @ reg2 = src[7]\r
+\r
+        ldr \reg6, [\pal, \reg6, lsl #2]    @ reg6 = pal[src[6]]\r
+        bfi \reg8, \reg9, #16, #16          @ reg8 = pal[src[4]] | pal[src[5]] << 16\r
+\r
+        ldr \reg2, [\pal, \reg2, lsl #2]    @ reg2 = pal[src[7]]\r
+        ubfx \reg1, \reg3, #0, #8           @ reg1 = src[8]\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[8]]\r
+        ubfx \reg5, \reg3, #8, #8           @ reg5 = src[9]\r
+\r
+        ldr \reg5, [\pal, \reg5, lsl #2]    @ reg5 = pal[src[9]]\r
+        ubfx \reg7, \reg3, #16, #8          @ reg7 = src[10]\r
+\r
+        ldr \reg7, [\pal, \reg7, lsl #2]    @ reg7 = pal[src[10]]\r
+        bfi \reg6, \reg2, #16, #16          @ reg6 = pal[src[6]] | pal[src[7]] << 16\r
+\r
+        vmov d17, \reg8, \reg6              @ d17 = pal[src[4-7]]\r
+        lsr    \reg3, \reg3, #24               @ reg3 = src[11]\r
+\r
+        ldr \reg3, [\pal, \reg3, lsl #2]    @ reg3 = pal[src[11]]\r
+        ubfx \reg2, \reg4, #0, #8           @ reg2 = src[12]\r
+\r
+        ldr \reg2, [\pal, \reg2, lsl #2]    @ reg2 = pal[src[12]]\r
+        ubfx \reg6, \reg4, #8, #8           @ reg6 = src[13]\r
+\r
+        ldr \reg6, [\pal, \reg6, lsl #2]    @ reg6 = pal[src[13]]\r
+        ubfx \reg8, \reg4, #16, #8          @ reg8 = src[14]\r
+\r
+        ldr \reg8, [\pal, \reg8, lsl #2]    @ reg8 = pal[src[14]]\r
+        lsr    \reg4, \reg4, #24               @ reg4 = src[15]\r
+\r
+        ldr \reg4, [\pal, \reg4, lsl #2]    @ reg4 = pal[src[15]]\r
+        bfi \reg1, \reg5, #16, #16          @ reg1 = pal[src[8]] | pal[src[9]] << 16\r
+\r
+        bfi \reg7, \reg3, #16, #16          @ reg7 = pal[src[10]] | pal[src[11]] << 16\r
+        bfi \reg2, \reg6, #16, #16          @ reg2 = pal[src[12]] | pal[src[13]] << 16\r
+\r
+        vmov \dA, \reg1, \reg7              @ dA = pal[src[8-11]]\r
+        sub \counter, \counter, #16         @ counter -= 16\r
+\r
+        bfi \reg8, \reg4, #16, #16          @ reg8 = pal[src[14]] | pal[src[15]] << 16\r
+        add \src, \src, #16                 @ src += 16\r
+\r
+        vmov \dB, \reg2, \reg8              @ dB = pal[src[12-15]]\r
+        cmp \counter, #16\r
+.endm\r
+\r
+.macro neon_normal1x_8_16_line src, dst, pal, counter, reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8, reg9\r
+    @ align src to 4 bytes\r
+        andS \reg5, \src, #3                @ reg5 = src & 3\r
+        beq 10f\r
+\r
+    @ first 1-3 pixels\r
+        ldr \reg1, [\src]                   @ reg1 = src[0-3]\r
+        rsb \reg5, \reg5, #4                @ reg5 = 4 - (src & 3)\r
+\r
+        add \src, \src, \reg5               @ src += reg5\r
+        sub \counter, \counter, \reg5       @ counter -= reg5\r
+\r
+        subS \reg5, \reg5, #1               @ reg5--\r
+\r
+        ubfx \reg2, \reg1, #0, #8           @ reg2 = src[0]\r
+        ubfxne \reg3, \reg1, #8, #8         @ reg3 = src[1]\r
+\r
+        ldr \reg2, [\pal, \reg2, lsl #2]    @ reg2 = pal[reg2]\r
+\r
+        ldrne \reg3, [\pal, \reg3, lsl #2]  @ reg3 = pal[reg3]\r
+\r
+        strh \reg2, [\dst]                  @ dst[0] = reg2\r
+\r
+        strneh \reg3, [\dst, #2]!           @ dst[1] = reg3; dst++\r
+        subneS \reg5, \reg5, #1             @ reg5--\r
+\r
+        ubfxne \reg4, \reg1, #16, #8        @ reg4 = src[2]\r
+        add \dst, \dst, #2                  @ dst++\r
+\r
+        ldrne \reg4, [\pal, \reg4, lsl #2]  @ reg4 = pal[reg4]\r
+\r
+        strneh \reg4, [\dst], #2            @ dst[2] = reg4; dst++\r
+\r
+    @ middle pixels (16 per iteration)\r
+    10:\r
+        _neon_normalxx_8_16_line_middle \src, \dst, \pal, \counter, \reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8, \reg9, , d18, d19\r
+\r
+        vst1.16 {d16-d19}, [\dst]!          @ dst[0-15] = d16-d19; dst += 2*16\r
+        bhs 10b\r
+\r
+    @ last 0-15 bytes\r
+\r
+        cmp \counter, #0\r
+        beq 40f\r
+\r
+        cmp \counter, #4\r
+        blo 30f\r
+\r
+    @ 4-12 pixels (4 pre iteration)\r
+    20:\r
+        ldr \reg1, [\src]                   @ reg1 = src[0-3]\r
+        sub \counter, \counter, #4          @ counter -= 4\r
+\r
+        add \src, \src, #4                  @ src += 4\r
+        add \dst, \dst, #(2*4)              @ dst += 4\r
+\r
+        ubfx \reg2, \reg1, #0, #8           @ reg2 = src[0]\r
+        cmp \counter, #4\r
+\r
+        ldr \reg2, [\pal, \reg2, lsl #2]    @ reg2 = pal[src[0]]\r
+        ubfx \reg3, \reg1, #8, #8           @ reg3 = src[1]\r
+\r
+        ldr \reg3, [\pal, \reg3, lsl #2]    @ reg3 = pal[src[1]]\r
+        ubfx \reg4, \reg1, #16, #8          @ reg4 = src[2]\r
+\r
+        ldr \reg4, [\pal, \reg4, lsl #2]    @ reg4 = pal[src[2]]\r
+        lsr    \reg1, \reg1, #24               @ reg1 = src[3]\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[3]]\r
+\r
+        strh \reg2, [\dst, #-8]             @ dst[0] = reg2\r
+\r
+        strh \reg3, [\dst, #-6]             @ dst[1] = reg3\r
+\r
+        strh \reg4, [\dst, #-4]             @ dst[2] = reg4\r
+\r
+        strh \reg1, [\dst, #-2]             @ dst[3] = reg1\r
+        bhs 20b\r
+\r
+        cmp \counter, #0\r
+        beq 40f\r
+\r
+    @ last 1-3 pixels\r
+    30:\r
+        ldrb \reg1, [\src]                  @ reg1 = src[0]\r
+        subS \counter, \counter, #1         @ counter--\r
+\r
+        ldrneb \reg2, [\src, #1]!           @ reg2 = src[1]; src++\r
+\r
+        add \src, \src, #1                  @ src++\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[0]]\r
+\r
+        ldrne \reg2, [\pal, \reg2, lsl #2]  @ reg2 = pal[src[1]]\r
+\r
+        strh \reg1, [\dst]                  @ dst[0] = reg1\r
+\r
+        strneh \reg2, [\dst, #2]!           @ dst[1] = reg2; dst++\r
+        subneS \counter, \counter, #1       @ counter--\r
+\r
+        ldrneb \reg3, [\src], #1            @ reg3 = src[2]; src++\r
+        add \dst, \dst, #2                  @ dst++\r
+\r
+        ldrne \reg3, [\pal, \reg3, lsl #2]  @ reg3 = pal[src[2]]\r
+\r
+        strneh \reg3, [\dst], #2            @ dst[2] = reg3; dst++\r
+\r
+    40:\r
+.endm\r
+\r
+.macro neon_normal2x_8_16_line src, dst, pal, counter, reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8, reg9, dststride\r
+    @ align src to 4 bytes\r
+        andS \reg5, \src, #3                @ reg5 = src & 3\r
+        beq 10f\r
+\r
+    @ first 1-3 pixels\r
+        rsb \reg5, \reg5, #4                @ reg5 = 4 - (src & 3)\r
+    1:\r
+        ldrb \reg1, [\src], #1              @ reg1 = src[0]; src++\r
+        add \reg2, \dst, \dststride\r
+\r
+        add \dst, \dst, #4                  @ dst += 2*2\r
+        sub \counter, \counter, #1          @ counter--\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[0]]\r
+        subS \reg5, \reg5, #1               @ reg5--\r
+\r
+        strh \reg1, [\dst, #-4]             @ dst[0] = reg1\r
+\r
+        strh \reg1, [\dst, #-2]             @ dst[1] = reg1\r
+\r
+        strh \reg1, [\reg2]                 @ dst1[0] = reg1\r
+\r
+        strh \reg1, [\reg2, #2]             @ dst1[1] = reg1\r
+        bne 1b\r
+\r
+    @ middle pixels (16 per iteration)\r
+    10:\r
+        _neon_normalxx_8_16_line_middle \src, \dst, \pal, \counter, \reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8, \reg9, \dststride, d20, d21\r
+\r
+        vmov q9, q8\r
+        add \reg1, \dst, \dststride         @ reg1 = dst + dststride\r
+\r
+        vmov q11, q10\r
+        vst2.16 {q8,q9}, [\dst]!            @ dst[0-7] = q8-q9; dst += 2*2*8\r
+\r
+        vst2.16 {q10,q11}, [\dst]!          @ dst[8-15] = q10-q11; dst += 2*2*8\r
+\r
+        vst2.16 {q8,q9}, [\reg1]!           @ dst1[0-7] = q8-q9; dst1 += 2*2*8\r
+\r
+        vst2.16 {q10,q11}, [\reg1]!         @ dst1[8-15] = q10-q11; dst1 += 2*2*8\r
+        bhs 10b\r
+\r
+    @ last 0-15 bytes\r
+\r
+        cmp \counter, #0\r
+        beq 40f\r
+\r
+        cmp \counter, #4\r
+        blo 30f\r
+\r
+    @ 4-12 pixels (4 pre iteration)\r
+    20:\r
+        ldr \reg1, [\src]                   @ reg1 = src[0-3]\r
+        sub \counter, \counter, #4          @ counter -= 4\r
+\r
+        add \src, \src, #4                  @ src += 4\r
+\r
+        ubfx \reg2, \reg1, #0, #8           @ reg2 = src[0]\r
+        cmp \counter, #4\r
+\r
+        ldr \reg2, [\pal, \reg2, lsl #2]    @ reg2 = pal[src[0]]\r
+        ubfx \reg3, \reg1, #8, #8           @ reg3 = src[1]\r
+\r
+        ldr \reg3, [\pal, \reg3, lsl #2]    @ reg3 = pal[src[1]]\r
+        ubfx \reg4, \reg1, #16, #8          @ reg4 = src[2]\r
+\r
+        ldr \reg4, [\pal, \reg4, lsl #2]    @ reg4 = pal[src[2]]\r
+        lsr    \reg1, \reg1, #24               @ reg1 = src[3]\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[3]]\r
+\r
+        add \reg5, \dst, \dststride\r
+        bfi \reg2, \reg3, #16, #16          @ reg2 = reg2 | reg3 << 16\r
+\r
+        vmov.32 d16[0], \reg2\r
+\r
+        bfi \reg4, \reg1, #16, #16          @ reg4 = reg4 | reg1 << 16\r
+\r
+        vmov.32 d16[1], \reg4\r
+\r
+        vmov d17, d16\r
+\r
+        vst2.16 {d16,d17}, [\dst]!          @ dst[0-7] = d16-d17; dst += 2*2*4\r
+\r
+        vst2.16 {d16,d17}, [\reg5]          @ dst1[0-7] = d16-d17\r
+        bhs 20b\r
+\r
+        cmp \counter, #0\r
+        beq 40f\r
+\r
+    @ last 1-3 pixels\r
+    30:\r
+        ldrb \reg1, [\src], #1              @ reg1 = src[0]; src++\r
+        add \reg2, \dst, \dststride\r
+\r
+        add \dst, \dst, #4                  @ dst += 2*2\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[0]]\r
+        subS \counter, \counter, #1         @ counter--\r
+\r
+        strh \reg1, [\dst, #-4]             @ dst[0] = reg1\r
+\r
+        strh \reg1, [\dst, #-2]             @ dst[1] = reg1\r
+\r
+        strh \reg1, [\reg2]                 @ dst1[0] = reg1\r
+\r
+        strh \reg1, [\reg2, #2]             @ dst1[1] = reg1\r
+        bne 30b\r
+\r
+    40:\r
+.endm\r
+\r
+.macro neon_normal3x_8_16_line src, dst, pal, counter, reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8, reg9, dststride\r
+    @ align src to 4 bytes\r
+        andS \reg5, \src, #3                @ reg5 = src & 3\r
+        beq 10f\r
+\r
+    @ first 1-3 pixels\r
+        rsb \reg5, \reg5, #4                @ reg5 = 4 - (src & 3)\r
+    1:\r
+        ldrb \reg1, [\src], #1              @ reg1 = src[0]; src++\r
+        add \reg2, \dst, \dststride\r
+\r
+        add \reg3, \reg2, \dststride\r
+        add \dst, \dst, #6                  @ dst += 3*2\r
+\r
+        sub \counter, \counter, #1          @ counter--\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[0]]\r
+        subS \reg5, \reg5, #1               @ reg5--\r
+\r
+        strh \reg1, [\dst, #-6]             @ dst[0] = reg1\r
+\r
+        strh \reg1, [\dst, #-4]             @ dst[1] = reg1\r
+\r
+        strh \reg1, [\dst, #-2]             @ dst[2] = reg1\r
+        bfi \reg1, \reg1, #16, #16          @ reg1 = reg1 | reg1 << 16\r
+\r
+        strh \reg1, [\reg2]                 @ dst1[0] = reg1\r
+\r
+        str \reg1, [\reg2, #2]              @ dst1[1-2] = reg1\r
+\r
+        strh \reg1, [\reg3]                 @ dst2[0] = reg1\r
+\r
+        str \reg1, [\reg3, #2]              @ dst2[1-2] = reg1\r
+        bne 1b\r
+\r
+    @ middle pixels (16 per iteration)\r
+    10:\r
+        _neon_normalxx_8_16_line_middle \src, \dst, \pal, \counter, \reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8, \reg9, \dststride, d22, d23\r
+\r
+        vmov q9, q8\r
+        add \reg1, \dst, \dststride         @ reg1 = dst + dststride\r
+\r
+        vmov q10, q8\r
+        add \reg2, \dst, \dststride, lsl #1 @ reg1 = dst + 2 * dststride\r
+\r
+        vmov q12, q11\r
+        vst3.16 {d16,d18,d20}, [\dst]!      @ dst[0-3] = q8-q10[0]; dst += 3*2*4\r
+\r
+        vmov q13, q11\r
+        vst3.16 {d17,d19,d21}, [\dst]!      @ dst[4-7] = q8-q10[1]; dst += 3*2*4\r
+\r
+        vst3.16 {d22,d24,d26}, [\dst]!      @ dst[8-11] = q11-q13[0]; dst += 3*2*4\r
+\r
+        vst3.16 {d23,d25,d27}, [\dst]!      @ dst[12-15] = q11-q13[1]; dst += 3*2*4\r
+\r
+        vst3.16 {d16,d18,d20}, [\reg1]!     @ dst1[0-3] = q8-q10[0]; dst1 += 3*2*4\r
+\r
+        vst3.16 {d17,d19,d21}, [\reg1]!     @ dst1[4-7] = q8-q10[1]; dst1 += 3*2*4\r
+\r
+        vst3.16 {d22,d24,d26}, [\reg1]!     @ dst1[8-11] = q11-q13[0]; dst1 += 3*2*4\r
+\r
+        vst3.16 {d23,d25,d27}, [\reg1]!     @ dst1[12-15] = q11-q13[1]; dst1 += 3*2*4\r
+\r
+        vst3.16 {d16,d18,d20}, [\reg2]!     @ dst2[0-3] = q8-q10[0]; dst2 += 3*2*4\r
+\r
+        vst3.16 {d17,d19,d21}, [\reg2]!     @ dst2[4-7] = q8-q10[1]; dst2 += 3*2*4\r
+\r
+        vst3.16 {d22,d24,d26}, [\reg2]!     @ dst2[8-11] = q11-q13[0]; dst2 += 3*2*4\r
+\r
+        vst3.16 {d23,d25,d27}, [\reg2]!     @ dst2[12-15] = q11-q13[1]; dst2 += 3*2*4\r
+        bhs 10b\r
+\r
+    @ last 0-15 bytes\r
+\r
+        cmp \counter, #0\r
+        beq 40f\r
+\r
+        cmp \counter, #4\r
+        blo 30f\r
+\r
+    @ 4-12 pixels (4 pre iteration)\r
+    20:\r
+        ldr \reg1, [\src]                   @ reg1 = src[0-3]\r
+        sub \counter, \counter, #4          @ counter -= 4\r
+\r
+        add \src, \src, #4                  @ src += 4\r
+\r
+        ubfx \reg2, \reg1, #0, #8           @ reg2 = src[0]\r
+        cmp \counter, #4\r
+\r
+        ldr \reg2, [\pal, \reg2, lsl #2]    @ reg2 = pal[src[0]]\r
+        ubfx \reg3, \reg1, #8, #8           @ reg3 = src[1]\r
+\r
+        ldr \reg3, [\pal, \reg3, lsl #2]    @ reg3 = pal[src[1]]\r
+        ubfx \reg4, \reg1, #16, #8          @ reg4 = src[2]\r
+\r
+        ldr \reg4, [\pal, \reg4, lsl #2]    @ reg4 = pal[src[2]]\r
+        lsr    \reg1, \reg1, #24               @ reg1 = src[3]\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[3]]\r
+\r
+        add \reg5, \dst, \dststride\r
+        bfi \reg2, \reg3, #16, #16          @ reg2 = reg2 | reg3 << 16\r
+\r
+        vmov.32 d16[0], \reg2\r
+        add \reg6, \reg5, \dststride\r
+\r
+        bfi \reg4, \reg1, #16, #16          @ reg4 = reg4 | reg1 << 16\r
+\r
+        vmov.32 d16[1], \reg4\r
+\r
+        vmov d17, d16\r
+\r
+        vmov d18, d16\r
+\r
+        vst3.16 {d16,d17,d18}, [\dst]!      @ dst[0-11] = d16-d18; dst += 3*2*4\r
+\r
+        vst3.16 {d16,d17,d18}, [\reg5]      @ dst1[0-11] = d16-d18\r
+\r
+        vst3.16 {d16,d17,d18}, [\reg6]      @ dst2[0-11] = d16-d18\r
+        bhs 20b\r
+\r
+        cmp \counter, #0\r
+        beq 40f\r
+\r
+    @ last 1-3 pixels\r
+    30:\r
+        ldrb \reg1, [\src], #1              @ reg1 = src[0]; src++\r
+        add \reg2, \dst, \dststride\r
+\r
+        add \reg3, \reg2, \dststride\r
+        add \dst, \dst, #6                  @ dst += 3*2\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[0]]\r
+        subS \counter, \counter, #1         @ counter--\r
+\r
+        strh \reg1, [\dst, #-6]             @ dst[0] = reg1\r
+\r
+        strh \reg1, [\dst, #-4]             @ dst[1] = reg1\r
+\r
+        strh \reg1, [\dst, #-2]             @ dst[2] = reg1\r
+        bfi \reg1, \reg1, #16, #16          @ reg1 = reg1 | reg1 << 16\r
+\r
+        strh \reg1, [\reg2]                 @ dst1[0] = reg1\r
+\r
+        str \reg1, [\reg2, #2]              @ dst1[1-2] = reg1\r
+\r
+        strh \reg1, [\reg3]                 @ dst2[0] = reg1\r
+\r
+        str \reg1, [\reg3, #2]              @ dst2[1-2] = reg1\r
+        bne 30b\r
+\r
+    40:\r
+.endm\r
+\r
+.macro neon_normal4x_8_16_line src, dst, pal, counter, reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8, reg9, dststride\r
+    @ align src to 4 bytes\r
+        andS \reg5, \src, #3                @ reg5 = src & 3\r
+        beq 10f\r
+\r
+    @ first 1-3 pixels\r
+        rsb \reg5, \reg5, #4                @ reg5 = 4 - (src & 3)\r
+    1:\r
+        ldrb \reg1, [\src], #1              @ reg1 = src[0]; src++\r
+        add \reg2, \dst, \dststride\r
+\r
+        add \reg3, \reg2, \dststride\r
+        add \dst, \dst, #8                  @ dst += 4*2\r
+\r
+        sub \counter, \counter, #1          @ counter--\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[0]]\r
+        add \reg4, \reg3, \dststride\r
+\r
+        strh \reg1, [\dst, #-8]             @ dst[0] = reg1\r
+        subS \reg5, \reg5, #1               @ reg5--\r
+\r
+        strh \reg1, [\dst, #-6]             @ dst[1] = reg1\r
+\r
+        bfi \reg1, \reg1, #16, #16          @ reg1 = reg1 | reg1 << 16\r
+        str \reg1, [\dst, #-4]              @ dst[2-3] = reg1\r
+\r
+        str \reg1, [\reg2]                  @ dst1[0-1] = reg1\r
+\r
+        str \reg1, [\reg2, #4]              @ dst1[2-3] = reg1\r
+\r
+        str \reg1, [\reg3]                  @ dst2[0-1] = reg1\r
+\r
+        str \reg1, [\reg3, #4]              @ dst2[2-3] = reg1\r
+\r
+        str \reg1, [\reg4]                  @ dst3[0-1] = reg1\r
+\r
+        str \reg1, [\reg4, #4]              @ dst3[2-3] = reg1\r
+        bne 1b\r
+\r
+    @ middle pixels (16 per iteration)\r
+    10:\r
+        _neon_normalxx_8_16_line_middle \src, \dst, \pal, \counter, \reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8, \reg9, \dststride, d24, d25\r
+\r
+        vmov q9, q8\r
+        add \reg1, \dst, \dststride         @ reg1 = dst + dststride\r
+\r
+        vmov q10, q8\r
+        add \reg2, \dst, \dststride, lsl #1 @ reg2 = dst + 2 * dststride\r
+\r
+        vmov q11, q8\r
+        add \reg3, \reg1, \dststride,lsl #1 @ reg3 = dst + 3 * dststride\r
+\r
+        vmov q13, q12\r
+        vst4.16 {d16,d18,d20,d22}, [\dst]!  @ dst[0-3] = q8-q11[0]; dst += 4*2*4\r
+\r
+        vmov q14, q12\r
+\r
+        vmov q15, q12\r
+        vst4.16 {d17,d19,d21,d23}, [\dst]!  @ dst[4-7] = q8-q11[1]; dst += 4*2*4\r
+\r
+        vst4.16 {d24,d26,d28,d30}, [\dst]!  @ dst[8-11] = q12-q15[0]; dst += 4*2*4\r
+\r
+        vst4.16 {d25,d27,d29,d31}, [\dst]!  @ dst[12-15] = q12-q15[1]; dst += 4*2*4\r
+\r
+        vst4.16 {d16,d18,d20,d22}, [\reg1]! @ dst1[0-3] = q8-q11[0]; dst1 += 4*2*4\r
+\r
+        vst4.16 {d17,d19,d21,d23}, [\reg1]! @ dst1[4-7] = q8-q11[1]; dst1 += 4*2*4\r
+\r
+        vst4.16 {d24,d26,d28,d30}, [\reg1]! @ dst1[8-11] = q12-q15[0]; dst1 += 4*2*4\r
+\r
+        vst4.16 {d25,d27,d29,d31}, [\reg1]! @ dst1[12-15] = q12-q15[1]; dst1 += 4*2*4\r
+\r
+        vst4.16 {d16,d18,d20,d22}, [\reg2]! @ dst2[0-3] = q8-q11[0]; dst2 += 4*2*4\r
+\r
+        vst4.16 {d17,d19,d21,d23}, [\reg2]! @ dst2[4-7] = q8-q11[1]; dst2 += 4*2*4\r
+\r
+        vst4.16 {d24,d26,d28,d30}, [\reg2]! @ dst2[8-11] = q12-q15[0]; dst2 += 4*2*4\r
+\r
+        vst4.16 {d25,d27,d29,d31}, [\reg2]! @ dst2[12-15] = q12-q15[1]; dst2 += 4*2*4\r
+\r
+        vst4.16 {d16,d18,d20,d22}, [\reg3]! @ dst3[0-3] = q8-q11[0]; dst3 += 4*2*4\r
+\r
+        vst4.16 {d17,d19,d21,d23}, [\reg3]! @ dst3[4-7] = q8-q11[1]; dst3 += 4*2*4\r
+\r
+        vst4.16 {d24,d26,d28,d30}, [\reg3]! @ dst3[8-11] = q12-q15[0]; dst3 += 4*2*4\r
+\r
+        vst4.16 {d25,d27,d29,d31}, [\reg3]! @ dst3[12-15] = q12-q15[1]; dst3 += 4*2*4\r
+        bhs 10b\r
+\r
+    @ last 0-15 bytes\r
+\r
+        cmp \counter, #0\r
+        beq 40f\r
+\r
+        cmp \counter, #4\r
+        blo 30f\r
+\r
+    @ 4-12 pixels (4 pre iteration)\r
+    20:\r
+        ldr \reg1, [\src]                   @ reg1 = src[0-3]\r
+        sub \counter, \counter, #4          @ counter -= 4\r
+\r
+        add \src, \src, #4                  @ src += 4\r
+\r
+        ubfx \reg2, \reg1, #0, #8           @ reg2 = src[0]\r
+        cmp \counter, #4\r
+\r
+        ldr \reg2, [\pal, \reg2, lsl #2]    @ reg2 = pal[src[0]]\r
+        ubfx \reg3, \reg1, #8, #8           @ reg3 = src[1]\r
+\r
+        ldr \reg3, [\pal, \reg3, lsl #2]    @ reg3 = pal[src[1]]\r
+        ubfx \reg4, \reg1, #16, #8          @ reg4 = src[2]\r
+\r
+        ldr \reg4, [\pal, \reg4, lsl #2]    @ reg4 = pal[src[2]]\r
+        lsr    \reg1, \reg1, #24               @ reg1 = src[3]\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[3]]\r
+\r
+        add \reg5, \dst, \dststride\r
+        bfi \reg2, \reg3, #16, #16          @ reg2 = reg2 | reg3 << 16\r
+\r
+        vmov.32 d16[0], \reg2\r
+        add \reg6, \reg5, \dststride\r
+\r
+        bfi \reg4, \reg1, #16, #16          @ reg4 = reg4 | reg1 << 16\r
+        add \reg7, \reg6, \dststride\r
+\r
+        vmov.32 d16[1], \reg4\r
+\r
+        vmov d17, d16\r
+\r
+        vmov d18, d16\r
+\r
+        vmov d19, d16\r
+\r
+        vst4.16 {d16,d17,d18,d19}, [\dst]!  @ dst[0-15] = d16-d19; dst += 4*2*4\r
+\r
+        vst4.16 {d16,d17,d18,d19}, [\reg5]  @ dst1[0-15] = d16-d19\r
+\r
+        vst4.16 {d16,d17,d18,d19}, [\reg6]  @ dst2[0-15] = d16-d19\r
+\r
+        vst4.16 {d16,d17,d18,d19}, [\reg7]  @ dst3[0-15] = d16-d19\r
+        bhs 20b\r
+\r
+        cmp \counter, #0\r
+        beq 40f\r
+\r
+    @ last 1-3 pixels\r
+    30:\r
+        ldrb \reg1, [\src], #1              @ reg1 = src[0]; src++\r
+        add \reg2, \dst, \dststride\r
+\r
+        add \reg3, \reg2, \dststride\r
+        add \dst, \dst, #8                  @ dst += 4*2\r
+\r
+        ldr \reg1, [\pal, \reg1, lsl #2]    @ reg1 = pal[src[0]]\r
+        add \reg4, \reg3, \dststride\r
+\r
+        strh \reg1, [\dst, #-8]             @ dst[0] = reg1\r
+        subS \counter, \counter, #1         @ counter--\r
+\r
+        strh \reg1, [\dst, #-6]             @ dst[1] = reg1\r
+\r
+        bfi \reg1, \reg1, #16, #16          @ reg1 = reg1 | reg1 << 16\r
+        str \reg1, [\dst, #-4]              @ dst[2-3] = reg1\r
+\r
+        str \reg1, [\reg2]                  @ dst1[0-1] = reg1\r
+\r
+        str \reg1, [\reg2, #4]              @ dst1[2-3] = reg1\r
+\r
+        str \reg1, [\reg3]                  @ dst2[0-1] = reg1\r
+\r
+        str \reg1, [\reg3, #4]              @ dst2[2-3] = reg1\r
+\r
+        str \reg1, [\reg4]                  @ dst3[0-1] = reg1\r
+\r
+        str \reg1, [\reg4, #4]              @ dst3[2-3] = reg1\r
+        bne 30b\r
+\r
+    40:\r
+.endm\r
+\r