tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mc.S (119794B)


      1 /*
      2 * Copyright © 2018, VideoLAN and dav1d authors
      3 * Copyright © 2018, Janne Grunau
      4 * Copyright © 2018, Martin Storsjo
      5 * All rights reserved.
      6 *
      7 * Redistribution and use in source and binary forms, with or without
      8 * modification, are permitted provided that the following conditions are met:
      9 *
     10 * 1. Redistributions of source code must retain the above copyright notice, this
     11 *    list of conditions and the following disclaimer.
     12 *
     13 * 2. Redistributions in binary form must reproduce the above copyright notice,
     14 *    this list of conditions and the following disclaimer in the documentation
     15 *    and/or other materials provided with the distribution.
     16 *
     17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 */
     28 
     29 #include "src/arm/asm.S"
     30 #include "util.S"
     31 
     32 .macro avg dst0, dst1, t0, t1, t2, t3
     33        vld1.16         {\t0,\t1},   [r2, :128]!
     34        vld1.16         {\t2,\t3},   [r3, :128]!
     35        vadd.i16        \t0,   \t0,  \t2
     36        vadd.i16        \t1,   \t1,  \t3
     37        vqrshrun.s16    \dst0, \t0,  #5
     38        vqrshrun.s16    \dst1, \t1,  #5
     39 .endm
     40 
     41 .macro w_avg dst0, dst1, t0, t1, t2, t3
     42        vld1.16         {\t0,\t1},   [r2, :128]!
     43        vld1.16         {\t2,\t3},   [r3, :128]!
     44        vsub.i16        \t0,   \t2,  \t0
     45        vsub.i16        \t1,   \t3,  \t1
     46        vqdmulh.s16     \t0,   \t0,  q15
     47        vqdmulh.s16     \t1,   \t1,  q15
     48        vadd.i16        \t0,   \t2,  \t0
     49        vadd.i16        \t1,   \t3,  \t1
     50        vqrshrun.s16    \dst0, \t0,  #4
     51        vqrshrun.s16    \dst1, \t1,  #4
     52 .endm
     53 
     54 .macro mask dst0, dst1, t0, t1, t2, t3
     55        vld1.8          {q14}, [lr, :128]!
     56        vld1.16         {\t0,\t1},   [r2, :128]!
     57        vmul.i8         q14,   q14,  q15
     58        vld1.16         {\t2,\t3},   [r3, :128]!
     59        vshll.i8        q13,   d28,  #8
     60        vshll.i8        q14,   d29,  #8
     61        vsub.i16        \t0,   \t2,  \t0
     62        vsub.i16        \t1,   \t3,  \t1
     63        vqdmulh.s16     \t0,   \t0,  q13
     64        vqdmulh.s16     \t1,   \t1,  q14
     65        vadd.i16        \t0,   \t2,  \t0
     66        vadd.i16        \t1,   \t3,  \t1
     67        vqrshrun.s16    \dst0, \t0,  #4
     68        vqrshrun.s16    \dst1, \t1,  #4
     69 .endm
     70 
     71 .macro bidir_fn type
     72 function \type\()_8bpc_neon, export=1
     73        push            {r4-r6,lr}
     74        ldrd            r4,  r5,  [sp, #16]
     75        clz             r4,  r4
     76 .ifnc \type, avg
     77        ldr             lr, [sp, #24]
     78 .endif
     79 .ifc \type, w_avg
     80        vdup.s16        q15, lr
     81        vneg.s16        q15, q15
     82        vshl.i16        q15, q15, #11
     83 .endif
     84 .ifc \type, mask
     85        vmov.i8         q15, #256-2
     86 .endif
     87        adr             r12, L(\type\()_tbl)
     88        sub             r4,  r4,  #24
     89        ldr             r4,  [r12, r4, lsl #2]
     90        \type           d16, d17, q0,  q1,  q2,  q3
     91        add             r12, r12, r4
     92        bx              r12
     93 
     94        .align 2
     95 L(\type\()_tbl):
     96        .word 1280f - L(\type\()_tbl) + CONFIG_THUMB
     97        .word 640f  - L(\type\()_tbl) + CONFIG_THUMB
     98        .word 320f  - L(\type\()_tbl) + CONFIG_THUMB
     99        .word 160f  - L(\type\()_tbl) + CONFIG_THUMB
    100        .word 80f   - L(\type\()_tbl) + CONFIG_THUMB
    101        .word 4f    - L(\type\()_tbl) + CONFIG_THUMB
    102 
    103 4:
    104        add             r6,  r0,  r1
    105        lsl             r1,  r1,  #1
    106        cmp             r5,  #4
    107        vst1.32         {d16[0]},  [r0, :32], r1
    108        vst1.32         {d16[1]},  [r6, :32], r1
    109        vst1.32         {d17[0]},  [r0, :32], r1
    110        vst1.32         {d17[1]},  [r6, :32], r1
    111        beq             0f
    112        \type           d18, d19,  q0,  q1,  q2,  q3
    113        cmp             r5,  #8
    114        vst1.32         {d18[0]},  [r0, :32], r1
    115        vst1.32         {d18[1]},  [r6, :32], r1
    116        vst1.32         {d19[0]},  [r0, :32], r1
    117        vst1.32         {d19[1]},  [r6, :32], r1
    118        beq             0f
    119        \type           d16, d17, q0,  q1,  q2,  q3
    120        vst1.32         {d16[0]},  [r0, :32], r1
    121        vst1.32         {d16[1]},  [r6, :32], r1
    122        \type           d18, d19,  q0,  q1,  q2,  q3
    123        vst1.32         {d17[0]},  [r0, :32], r1
    124        vst1.32         {d17[1]},  [r6, :32], r1
    125        vst1.32         {d18[0]},  [r0, :32], r1
    126        vst1.32         {d18[1]},  [r6, :32], r1
    127        vst1.32         {d19[0]},  [r0, :32], r1
    128        vst1.32         {d19[1]},  [r6, :32], r1
    129        pop             {r4-r6,pc}
    130 80:
    131        add             r6,  r0,  r1
    132        lsl             r1,  r1,  #1
    133 8:
    134        vst1.8          {d16},  [r0, :64], r1
    135        \type           d18, d19, q0,  q1,  q2,  q3
    136        vst1.8          {d17},  [r6, :64], r1
    137        vst1.8          {d18},  [r0, :64], r1
    138        subs            r5,  r5,  #4
    139        vst1.8          {d19},  [r6, :64], r1
    140        ble             0f
    141        \type           d16, d17, q0,  q1,  q2,  q3
    142        b               8b
    143 160:
    144        add             r6,  r0,  r1
    145        lsl             r1,  r1,  #1
    146 16:
    147        \type           d18, d19, q0, q1, q2, q3
    148        vst1.8          {q8},  [r0, :128], r1
    149        \type           d20, d21, q0, q1, q2, q3
    150        vst1.8          {q9},  [r6, :128], r1
    151        \type           d22, d23, q0, q1, q2, q3
    152        vst1.8          {q10}, [r0, :128], r1
    153        subs            r5,  r5,  #4
    154        vst1.8          {q11}, [r6, :128], r1
    155        ble             0f
    156        \type           d16, d17, q0, q1, q2, q3
    157        b               16b
    158 320:
    159        add             r6,  r0,  r1
    160        lsl             r1,  r1,  #1
    161 32:
    162        \type           d18, d19, q0, q1, q2, q3
    163        \type           d20, d21, q0, q1, q2, q3
    164        vst1.8          {q8,  q9},  [r0, :128], r1
    165        \type           d22, d23, q0, q1, q2, q3
    166        subs            r5,  r5,  #2
    167        vst1.8          {q10, q11}, [r6, :128], r1
    168        ble             0f
    169        \type           d16, d17, q0, q1, q2, q3
    170        b               32b
    171 640:
    172        add             r6,  r0,  #32
    173 64:
    174        \type           d18, d19, q0, q1, q2, q3
    175        \type           d20, d21, q0, q1, q2, q3
    176        \type           d22, d23, q0, q1, q2, q3
    177        vst1.8          {q8,  q9},  [r0, :128], r1
    178        \type           d16, d17, q0, q1, q2, q3
    179        vst1.8          {q10, q11}, [r6, :128], r1
    180        \type           d18, d19, q0, q1, q2, q3
    181        \type           d20, d21, q0, q1, q2, q3
    182        vst1.8          {q8,  q9},  [r0, :128], r1
    183        \type           d22, d23, q0, q1, q2, q3
    184        subs            r5,  r5,  #2
    185        vst1.8          {q10, q11}, [r6, :128], r1
    186        ble             0f
    187        \type           d16, d17, q0, q1, q2, q3
    188        b               64b
    189 1280:
    190        sub             r1,  r1,  #32
    191        add             r6,  r0,  #64
    192 128:
    193        \type           d18, d19, q0, q1, q2, q3
    194        \type           d20, d21, q0, q1, q2, q3
    195        \type           d22, d23, q0, q1, q2, q3
    196        vst1.8          {q8,  q9},  [r0, :128]!
    197        \type           d16, d17, q0, q1, q2, q3
    198        vst1.8          {q10, q11}, [r0, :128], r1
    199        \type           d18, d19, q0, q1, q2, q3
    200        \type           d20, d21, q0, q1, q2, q3
    201        vst1.8          {q8,  q9},  [r6, :128]!
    202        \type           d22, d23, q0, q1, q2, q3
    203        subs            r5,  r5,  #1
    204        vst1.8          {q10, q11}, [r6, :128], r1
    205        ble             0f
    206        \type           d16, d17, q0, q1, q2, q3
    207        b               128b
    208 
    209 0:
    210        pop             {r4-r6,pc}
    211 endfunc
    212 .endm
    213 
    214 bidir_fn avg
    215 bidir_fn w_avg
    216 bidir_fn mask
    217 
    218 
    219 .macro w_mask_fn type
    220 function w_mask_\type\()_8bpc_neon, export=1
    221        push            {r4-r9,lr}
    222        ldrd            r4,  r5,  [sp, #28]
    223        ldrd            r6,  r7,  [sp, #36]
    224        clz             r8,  r4
    225        adr             r9,  L(w_mask_\type\()_tbl)
    226        sub             r8,  r8,  #24
    227        ldr             r8,  [r9,  r8,  lsl #2]
    228        add             r9,  r9,  r8
    229        movw            r12, #6903
    230        vdup.16         q14, r12
    231 .if \type == 444
    232        vmov.i8         q15, #64
    233 .elseif \type == 422
    234        vdup.8          d0,  r7         // d0[] <- sign
    235        vmov.i8         d30, #129
    236        vsub.i8         d30, d30, d0    // 129 - sign
    237 .elseif \type == 420
    238        vdup.16         q0,  r7         // d0[] <- sign
    239        vmov.i16        q15, #256
    240        vsub.i16        q15, q15, q0    // 256 - sign
    241 .endif
    242        add             r12, r0,  r1
    243        lsl             r1,  r1,  #1
    244        bx              r9
    245 
    246        .align 2
    247 L(w_mask_\type\()_tbl):
    248        .word 1280f  - L(w_mask_\type\()_tbl) + CONFIG_THUMB
    249        .word 640f   - L(w_mask_\type\()_tbl) + CONFIG_THUMB
    250        .word 320f   - L(w_mask_\type\()_tbl) + CONFIG_THUMB
    251        .word 160f   - L(w_mask_\type\()_tbl) + CONFIG_THUMB
    252        .word 8f     - L(w_mask_\type\()_tbl) + CONFIG_THUMB
    253        .word 4f     - L(w_mask_\type\()_tbl) + CONFIG_THUMB
    254 
    255 4:
    256        vld1.16         {d0,  d1,  d2,  d3},  [r2,  :128]! // tmp1 (four rows at once)
    257        vld1.16         {d4,  d5,  d6,  d7},  [r3,  :128]! // tmp2 (four rows at once)
    258        subs            r5,  r5,  #4
    259        vsub.i16        q8,  q2,  q0    // tmp2-tmp1
    260        vsub.i16        q9,  q3,  q1
    261        vabd.s16        q10, q0,  q2    // (abs(tmp1[x] - tmp2[x]))
    262        vabd.s16        q11, q1,  q3
    263        vqsub.u16       q10, q14, q10   // 6903 - abs ()
    264        vqsub.u16       q11, q14, q11
    265        vshr.s16        q10, q10, #8    // 64-m = (6903 - abs()) >> 8
    266        vshr.s16        q11, q11, #8
    267        vshl.s16        q12, q10, #9    // (64-m)<<9
    268        vshl.s16        q13, q11, #9
    269        vqdmulh.s16     q12, q12, q8    // ((tmp2-tmp1)*(64-m)<<9)>>15
    270        vqdmulh.s16     q13, q13, q9
    271        vadd.i16        q12, q12, q0    // (((tmp2-tmp1)*(64-m)<<9)>>15) + tmp1
    272        vadd.i16        q13, q13, q1
    273        vqrshrun.s16    d24, q12, #4    // (((((tmp2-tmp1)*(64-m)<<9)>>15) + tmp1) + 8) >> 4
    274        vqrshrun.s16    d25, q13, #4
    275 .if \type == 444
    276        vmovn.u16       d20, q10        // 64 - m
    277        vmovn.u16       d21, q11
    278        vsub.i8         q10, q15, q10   // m
    279        vst1.8          {d20, d21}, [r6,  :128]!
    280 .elseif \type == 422
    281        vpadd.s16       d20, d20, d21   // (64 - m) + (64 - n) (column wise addition)
    282        vpadd.s16       d21, d22, d23
    283        vmovn.s16       d6,  q10
    284        vhsub.u8        d6,  d30, d6    // ((129 - sign) - ((64 - m) + (64 - n))) >> 1
    285        vst1.8          {d6},  [r6,  :64]!
    286 .elseif \type == 420
    287        vadd.s16        d20, d20, d21   // (64 - my1) + (64 - my2) (row wise addition)
    288        vadd.s16        d21, d22, d23
    289        vpadd.s16       d20, d20, d21   // (128 - m) + (128 - n) (column wise addition)
    290        vsub.s16        d20, d30, d20   // (256 - sign) - ((128 - m) + (128 - n))
    291        vrshrn.u16      d20, q10,  #2   // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
    292        vst1.32         {d20[0]}, [r6,  :32]!
    293 .endif
    294        vst1.32         {d24[0]}, [r0,  :32], r1
    295        vst1.32         {d24[1]}, [r12, :32], r1
    296        vst1.32         {d25[0]}, [r0,  :32], r1
    297        vst1.32         {d25[1]}, [r12, :32], r1
    298        bgt             4b
    299        pop             {r4-r9,pc}
    300 8:
    301        vld1.16         {d0,  d1,  d2,  d3},  [r2,  :128]! // tmp1y1, tmp1y2
    302        vld1.16         {d4,  d5,  d6,  d7},  [r3,  :128]! // tmp2y1, tmp2y2
    303        subs            r5,  r5,  #2
    304        vsub.i16        q8,  q2,  q0    // tmp2y1 - tmp1y1
    305        vsub.i16        q9,  q3,  q1    // tmp2y2 - tmp1y2
    306        vabd.s16        q10, q0,  q2    // abs(tmp1y1 - tmp2y1)
    307        vabd.s16        q11, q1,  q3    // abs(tmp1y2 - tmp2y2)
    308        vqsub.u16       q10, q14, q10   // 6903 - abs(tmp1y1 - tmp2y1)
    309        vqsub.u16       q11, q14, q11   // 6903 - abs(tmp1y2 - tmp2y2)
    310        vshr.s16        q10, q10, #8    // 64 - my1 = 6903 - abs(tmp1y1 - tmp2y1) >> 8
    311        vshr.s16        q11, q11, #8    // 64 - my2 = 6903 - abs(tmp1y2 - tmp2y2) >> 8
    312        vshl.s16        q12, q10, #9    // (64 - my1) << 9
    313        vshl.s16        q13, q11, #9    // (64 - my2) << 9
    314        vqdmulh.s16     q12, q12, q8    // ((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15
    315        vqdmulh.s16     q13, q13, q9    // ((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15
    316        vadd.s16        q12, q12, q0    // (((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15) + tmp1y1
    317        vadd.s16        q13, q13, q1    // (((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15) + tmp1y2
    318        vqrshrun.s16    d24, q12, #4    // (((((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15) + tmp1y1) + 8) >> 4
    319        vqrshrun.s16    d25, q13, #4    // (((((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15) + tmp1y2) + 8) >> 4
    320 .if \type == 444
    321        vmovn.u16       d20, q10        // 64 - m
    322        vmovn.u16       d21, q11
    323        vsub.i8         q10, q15, q10   // m
    324        vst1.8          {d20, d21}, [r6,  :128]!
    325 .elseif \type == 422
    326        vpadd.s16       d20, d20, d21   // (64 - my1) + (64 - ny1) (column wise addition)
    327        vpadd.s16       d21, d22, d23   // (64 - my2) + (64 - ny2)
    328        vmovn.s16       d20, q10
    329        vhsub.u8        d20, d30, d20   // ((129 - sign) - ((64 - my1/y2) + (64 - ny1/y2))) >> 1
    330        vst1.8          {d20}, [r6,  :64]!
    331 .elseif \type == 420
    332        vadd.s16        q10, q10, q11   // (64 - my1) + (64 - my2) (row wise addition)
    333        vpadd.s16       d20, d20, d21   // (128 - m) + (128 - n) (column wise addition)
    334        vsub.s16        d20, d30, d20   // (256 - sign) - ((128 - m) + (128 - n))
    335        vrshrn.u16      d20, q10, #2    // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
    336        vst1.32         {d20[0]}, [r6,  :32]!
    337 .endif
    338        vst1.16         {d24}, [r0,  :64], r1
    339        vst1.16         {d25}, [r12, :64], r1
    340        bgt             8b
    341        pop             {r4-r9,pc}
    342 1280:
    343 640:
    344 320:
    345 160:
    346        sub             r1,  r1,  r4
    347 .if \type == 444
    348        add             lr,  r6,  r4
    349 .elseif \type == 422
    350        add             lr,  r6,  r4,  lsr #1
    351 .endif
    352        add             r9,  r3,  r4,  lsl #1
    353        add             r7,  r2,  r4,  lsl #1
    354 161:
    355        mov             r8,  r4
    356 16:
    357        vld1.16         {d0,  d1,  d2,  d3},  [r2,  :128]! // tmp1y1
    358        vld1.16         {d4,  d5,  d6,  d7},  [r3,  :128]! // tmp2y1
    359        vld1.16         {d16, d17, d18, d19}, [r7,  :128]! // tmp1y2
    360        subs            r8,  r8,  #16
    361        vsub.i16        q2,  q2,  q0    // tmp2y1 - tmp1y1
    362        vsub.i16        q3,  q3,  q1
    363        vabs.s16        q10, q2         // abs(tm2y1 - tmp1y1)
    364        vabs.s16        q11, q3
    365        vqsub.u16       q10, q14, q10   // 6903 - abs(tmp1y1 - tmp2y1)
    366        vqsub.u16       q11, q14, q11
    367        vshr.s16        q10, q10, #8    // 64 - my1 = 6903 - abs(tmp1y1 - tmp2y1) >> 8
    368        vshr.s16        q11, q11, #8
    369        vshl.s16        q12, q10, #9    // (64 - my1) << 9
    370        vshl.s16        q13, q11, #9
    371        vqdmulh.s16     q12, q12, q2    // ((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15
    372        vqdmulh.s16     q13, q13, q3
    373        vadd.i16        q12, q12, q0    // (((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15) + tmp1y1
    374        vadd.i16        q13, q13, q1
    375        vld1.16         {d0,  d1,  d2,  d3},  [r9,  :128]! // tmp2h2
    376 .if \type == 444
    377        vmovn.u16       d20, q10        // 64 - my1
    378        vmovn.u16       d21, q11
    379        vsub.i8         q10, q15, q10   // my1
    380        vst1.8          {d20, d21}, [r6,  :128]!
    381 .elseif \type == 422
    382        vpadd.s16       d20, d20, d21   // (64 - my1) + (64 - ny1) (column wise addition)
    383        vpadd.s16       d21, d22, d23
    384        vmovn.s16       d20, q10
    385        vhsub.u8        d20, d30, d20   // ((129 - sign) - ((64 - my1) + (64 - ny1))) >> 1
    386        vst1.8          {d20}, [r6,  :64]!
    387 .endif
    388        vqrshrun.s16    d24, q12, #4    // (((((tmp2y1 - tmp1y1)*(64 - my1) << 9) >> 15) + tmp1y1) + 8) >> 4
    389        vqrshrun.s16    d25, q13, #4
    390        vsub.i16        q0,  q0,  q8    // tmp2y2 - tmp1y2
    391        vsub.i16        q1,  q1,  q9
    392        vst1.16         {d24, d25}, [r0,  :128]!    // store dsty1
    393        vabs.s16        q2,  q0         // abs(tmp2y2 - tmp1y2)
    394        vabs.s16        q3,  q1
    395        vqsub.u16       q2,  q14, q2    // 6903 - abs(tmp2y2 - tmp1y2)
    396        vqsub.u16       q3,  q14, q3
    397        vshr.s16        q2,  q2,  #8    // (6903 - abs(tmp2y2 - tmp1y2)) >> 8
    398        vshr.s16        q3,  q3,  #8
    399        vshl.s16        q12, q2,  #9    // (64 - my2) << 9
    400        vshl.s16        q13, q3,  #9
    401 .if \type == 444
    402        vmovn.u16       d4,  q2         // 64 - my2
    403        vmovn.u16       d5,  q3
    404        vsub.i8         q2,  q15, q2    // my2
    405        vst1.8          {d4,  d5},  [lr,  :128]!
    406 .elseif \type == 422
    407        vpadd.s16       d4,  d4,  d5    // (64 - my2) + (64 - ny2) (column wise addition)
    408        vpadd.s16       d5,  d6,  d7
    409        vmovn.s16       d4,  q2
    410        vhsub.u8        d4,  d30, d4    // ((129 - sign) - ((64 - my2) + (64 - ny2))) >> 1
    411        vst1.8          {d4},  [lr,  :64]!
    412 .elseif \type == 420
    413        vadd.s16        q10, q10, q2    // (64 - my1) + (64 - my2) (row wise addition)
    414        vadd.s16        q11, q11, q3
    415        vpadd.s16       d20, d20, d21   // (128 - m) + (128 - n) (column wise addition)
    416        vpadd.s16       d21, d22, d23
    417        vsub.s16        q10, q15, q10   // (256 - sign) - ((128 - m) + (128 - n))
    418        vrshrn.u16      d20, q10, #2    // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
    419        vst1.8          {d20}, [r6,  :64]!
    420 .endif
    421        vqdmulh.s16     q12, q12, q0    // ((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15
    422        vqdmulh.s16     q13, q13, q1
    423        vadd.i16        q12, q12, q8    // (((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15) + tmp1y2
    424        vadd.i16        q13, q13, q9
    425        vqrshrun.s16    d24, q12, #4    // (((((tmp2y2 - tmp1y2)*(64 - my2) << 9) >> 15) + tmp1y2) + 8) >> 4
    426        vqrshrun.s16    d25, q13, #4
    427        vst1.16         {d24, d25}, [r12, :128]!   // store dsty2
    428        bgt             16b
    429        subs            r5,  r5,  #2
    430        add             r2,  r2,  r4,  lsl #1
    431        add             r3,  r3,  r4,  lsl #1
    432        add             r7,  r7,  r4,  lsl #1
    433        add             r9,  r9,  r4,  lsl #1
    434 .if \type == 444
    435        add             r6,  r6,  r4
    436        add             lr,  lr,  r4
    437 .elseif \type == 422
    438        add             r6,  r6,  r4,  lsr #1
    439        add             lr,  lr,  r4,  lsr #1
    440 .endif
    441        add             r0,  r0,  r1
    442        add             r12, r12, r1
    443        bgt             161b
    444        pop             {r4-r9,pc}
    445 endfunc
    446 .endm
    447 
    448 w_mask_fn 444
    449 w_mask_fn 422
    450 w_mask_fn 420
    451 
    452 
    453 function blend_8bpc_neon, export=1
    454        push            {r4-r5,lr}
    455        ldrd            r4,  r5,  [sp, #12]
    456        clz             lr,  r3
    457        adr             r3,  L(blend_tbl)
    458        sub             lr,  lr,  #26
    459        ldr             lr,  [r3, lr, lsl #2]
    460        add             r3,  r3,  lr
    461        bx              r3
    462 
    463        .align 2
    464 L(blend_tbl):
    465        .word 320f  - L(blend_tbl) + CONFIG_THUMB
    466        .word 160f  - L(blend_tbl) + CONFIG_THUMB
    467        .word 80f   - L(blend_tbl) + CONFIG_THUMB
    468        .word 40f   - L(blend_tbl) + CONFIG_THUMB
    469 
    470 40:
    471        vmov.i8         d22, #64
    472        add             r12, r0,  r1
    473        lsl             r1,  r1,  #1
    474 4:
    475        vld1.u8         {d2},     [r5,  :64]!
    476        vld1.u8         {d1},     [r2,  :64]!
    477        vld1.32         {d0[]},   [r0,  :32]
    478        subs            r4,  r4,  #2
    479        vld1.32         {d0[1]},  [r12, :32]
    480        vsub.i8         d3,  d22, d2
    481        vmull.u8        q8,  d1,  d2
    482        vmlal.u8        q8,  d0,  d3
    483        vrshrn.i16      d20, q8,  #6
    484        vst1.32         {d20[0]}, [r0,  :32], r1
    485        vst1.32         {d20[1]}, [r12, :32], r1
    486        bgt             4b
    487        pop             {r4-r5,pc}
    488 80:
    489        vmov.i8         d16, #64
    490        add             r12, r0,  r1
    491        lsl             r1,  r1,  #1
    492 8:
    493        vld1.u8         {q1},  [r5,  :128]!
    494        vld1.u8         {q2},  [r2,  :128]!
    495        vld1.u8         {d0},  [r0,  :64]
    496        vsub.i8         d17, d16, d2
    497        vld1.u8         {d1},  [r12, :64]
    498        subs            r4,  r4,  #2
    499        vsub.i8         d18, d16, d3
    500        vmull.u8        q3,  d2,  d4
    501        vmlal.u8        q3,  d0,  d17
    502        vmull.u8        q10, d3,  d5
    503        vmlal.u8        q10, d1,  d18
    504        vrshrn.i16      d22, q3,  #6
    505        vrshrn.i16      d23, q10, #6
    506        vst1.u8         {d22}, [r0,  :64], r1
    507        vst1.u8         {d23}, [r12, :64], r1
    508        bgt             8b
    509        pop             {r4-r5,pc}
    510 160:
    511        vmov.i8         q12, #64
    512        add             r12, r0,  r1
    513        lsl             r1,  r1,  #1
    514 16:
    515        vld1.u8         {q1,  q2},  [r5,  :128]!
    516        vld1.u8         {q8,  q9},  [r2,  :128]!
    517        vld1.u8         {q0},  [r0,  :128]
    518        subs            r4,  r4,  #2
    519        vsub.i8         q15, q12, q1
    520        vld1.u8         {q13}, [r12, :128]
    521        vmull.u8        q3,  d16, d2
    522        vmlal.u8        q3,  d0,  d30
    523        vmull.u8        q14, d17, d3
    524        vmlal.u8        q14, d1,  d31
    525        vsub.i8         q15, q12, q2
    526        vrshrn.i16      d20, q3,  #6
    527        vrshrn.i16      d21, q14, #6
    528        vmull.u8        q3,  d18, d4
    529        vmlal.u8        q3,  d26, d30
    530        vmull.u8        q14, d19, d5
    531        vmlal.u8        q14, d27, d31
    532        vrshrn.i16      d22, q3,  #6
    533        vrshrn.i16      d23, q14, #6
    534        vst1.u8         {q10}, [r0,  :128], r1
    535        vst1.u8         {q11}, [r12, :128], r1
    536        bgt             16b
    537        pop             {r4-r5,pc}
    538 320:
    539        vmov.i8         q10, #64
    540 32:
    541        vld1.u8         {q2,  q3},  [r5,  :128]!
    542        vld1.u8         {q8,  q9},  [r2,  :128]!
    543        vld1.u8         {q0,  q1},  [r0,  :128]
    544        subs            r4,  r4,  #1
    545        vsub.i8         q11, q10, q2
    546        vmull.u8        q15, d16, d4
    547        vmlal.u8        q15, d0,  d22
    548        vmull.u8        q14, d17, d5
    549        vmlal.u8        q14, d1,  d23
    550        vsub.i8         q11, q10, q3
    551        vrshrn.i16      d24, q15, #6
    552        vrshrn.i16      d25, q14, #6
    553        vmull.u8        q15, d18, d6
    554        vmlal.u8        q15, d2,  d22
    555        vmull.u8        q14, d19, d7
    556        vmlal.u8        q14, d3,  d23
    557        vrshrn.i16      d26, q15, #6
    558        vrshrn.i16      d27, q14, #6
    559        vst1.u8         {q12, q13}, [r0,  :128],  r1
    560        bgt             32b
    561        pop             {r4-r5,pc}
    562 endfunc
    563 
    564 function blend_h_8bpc_neon, export=1
    565        push            {r4-r5,lr}
    566        ldr             r4,  [sp, #12]
    567        movrel          r5,  X(obmc_masks)
    568        add             r5,  r5,  r4
    569        sub             r4,  r4,  r4,  lsr #2
    570        clz             lr,  r3
    571        adr             r12, L(blend_h_tbl)
    572        sub             lr,  lr,  #24
    573        ldr             lr,  [r12, lr, lsl #2]
    574        add             r12, r12, lr
    575        bx              r12
    576 
    577        .align 2
    578 L(blend_h_tbl):
    579        .word 1280f  - L(blend_h_tbl) + CONFIG_THUMB
    580        .word 640f   - L(blend_h_tbl) + CONFIG_THUMB
    581        .word 320f   - L(blend_h_tbl) + CONFIG_THUMB
    582        .word 160f   - L(blend_h_tbl) + CONFIG_THUMB
    583        .word 80f    - L(blend_h_tbl) + CONFIG_THUMB
    584        .word 40f    - L(blend_h_tbl) + CONFIG_THUMB
    585        .word 20f    - L(blend_h_tbl) + CONFIG_THUMB
    586 
    587 20:
    588        vmov.i8         d22, #64
    589        add             r12, r0,  r1
    590        lsl             r1,  r1,  #1
    591 2:
    592        vld1.16         {d2[], d3[]},  [r5,  :16]!
    593        vld1.32         {d1[]},  [r2,  :32]!
    594        subs            r4,  r4,  #2
    595        vld1.16         {d0[]},   [r0,  :16]
    596        vzip.8          d2,  d3
    597        vsub.i8         d4,  d22, d2
    598        vld1.16         {d0[1]},  [r12, :16]
    599        vmull.u8        q8,  d1,  d2
    600        vmlal.u8        q8,  d0,  d4
    601        vrshrn.i16      d20, q8,  #6
    602        vst1.16         {d20[0]}, [r0,  :16], r1
    603        vst1.16         {d20[1]}, [r12, :16], r1
    604        bgt             2b
    605        pop             {r4-r5,pc}
    606 40:
    607        vmov.i8         d22, #64
    608        add             r12, r0,  r1
    609        lsl             r1,  r1,  #1
    610 4:
    611        vld2.u8         {d2[],  d3[]},   [r5,  :16]!
    612        vld1.u8         {d1},     [r2,  :64]!
    613        subs            r4,  r4,  #2
    614        vext.u8         d2,  d2,  d3,   #4
    615        vld1.32         {d0[]},   [r0,  :32]
    616        vsub.i8         d6,  d22, d2
    617        vld1.32         {d0[1]},  [r12, :32]
    618        vmull.u8        q8,  d1,  d2
    619        vmlal.u8        q8,  d0,  d6
    620        vrshrn.i16      d20, q8,  #6
    621        vst1.32         {d20[0]}, [r0,  :32], r1
    622        vst1.32         {d20[1]}, [r12, :32], r1
    623        bgt             4b
    624        pop             {r4-r5,pc}
    625 80:
    626        vmov.i8         q8, #64
    627        add             r12, r0,  r1
    628        lsl             r1,  r1,  #1
    629 8:
    630        vld2.u8         {d2[],  d3[]},  [r5,  :16]!
    631        vld1.u8         {d4,  d5},  [r2,  :128]!
    632        vld1.u8         {d0},   [r0,  :64]
    633        vsub.i8         q9,  q8,  q1
    634        vld1.u8         {d1},   [r12, :64]
    635        subs            r4,  r4,  #2
    636        vmull.u8        q3,  d2,  d4
    637        vmlal.u8        q3,  d0,  d18
    638        vmull.u8        q10, d3,  d5
    639        vmlal.u8        q10, d1,  d19
    640        vrshrn.i16      d22, q3,  #6
    641        vrshrn.i16      d23, q10, #6
    642        vst1.u8         {d22}, [r0,  :64], r1
    643        vst1.u8         {d23}, [r12, :64], r1
    644        bgt             8b
    645        pop             {r4-r5,pc}
    646 160:
    647        vmov.i8         q12, #64
    648        add             r12, r0,  r1
    649        lsl             r1,  r1,  #1
    650 16:
    651        vld2.u8         {d28[], d29[]}, [r5,  :16]!
    652        vld1.u8         {d2,  d3,  d4,  d5},  [r2,  :128]!
    653        vsub.i8         q15, q12, q14
    654        vld1.u8         {q0},  [r0,  :128]
    655        subs            r4,  r4,  #2
    656        vld1.u8         {q13}, [r12, :128]
    657        vmull.u8        q3,  d2,  d28
    658        vmlal.u8        q3,  d0,  d30
    659        vmull.u8        q8,  d3,  d28
    660        vmlal.u8        q8,  d1,  d30
    661        vrshrn.i16      d18, q3,  #6
    662        vrshrn.i16      d19, q8,  #6
    663        vmull.u8        q3,  d4,  d29
    664        vmlal.u8        q3,  d26, d31
    665        vmull.u8        q8,  d5,  d29
    666        vmlal.u8        q8,  d27, d31
    667        vrshrn.i16      d20, q3,  #6
    668        vrshrn.i16      d21, q8,  #6
    669        vst1.u8         {q9},  [r0,  :128], r1
    670        vst1.u8         {q10}, [r12, :128], r1
    671        bgt             16b
    672        pop             {r4-r5,pc}
    673 320:
    674 640:
    675 1280:
    676        vmov.i8         d20, #64
    677        sub             r1,  r1,  r3
    678 321:
    679        vld1.u8         {d6[]},  [r5]!
    680        vsub.i8         d7,  d20, d6
    681        mov             r12, r3
    682 32:
    683        vld1.u8         {q8,  q9},  [r2,  :128]!
    684        vld1.u8         {q0,  q1},  [r0,  :128]
    685        vmull.u8        q15, d16, d6
    686        vmlal.u8        q15, d0,  d7
    687        vmull.u8        q14, d17, d6
    688        vmlal.u8        q14, d1,  d7
    689        vrshrn.i16      d0,  q15, #6
    690        vrshrn.i16      d1,  q14, #6
    691        vmull.u8        q15, d18, d6
    692        vmlal.u8        q15, d2,  d7
    693        vmull.u8        q14, d19, d6
    694        vmlal.u8        q14, d3,  d7
    695        vrshrn.i16      d2,  q15, #6
    696        vrshrn.i16      d3,  q14, #6
    697        subs            r12, r12, #32
    698        vst1.u8         {q0,  q1},  [r0,  :128]!
    699        bgt             32b
    700        add             r0,  r0,  r1
    701        subs            r4,  r4,  #1
    702        bgt             321b
    703        pop             {r4-r5,pc}
    704 endfunc
    705 
    706 function blend_v_8bpc_neon, export=1
    707        push            {r4,lr}
    708        ldr             r4,  [sp, #8]
    709        movrel          lr,  X(obmc_masks)
    710        add             lr,  lr,  r3
    711        clz             r12, r3
    712        adr             r3,  L(blend_v_tbl)
    713        sub             r12, r12, #26
    714        ldr             r12, [r3, r12, lsl #2]
    715        add             r3,  r3,  r12
    716        bx              r3
    717 
    718        .align 2
    719 L(blend_v_tbl):
    720        .word 320f  - L(blend_v_tbl) + CONFIG_THUMB
    721        .word 160f  - L(blend_v_tbl) + CONFIG_THUMB
    722        .word 80f   - L(blend_v_tbl) + CONFIG_THUMB
    723        .word 40f   - L(blend_v_tbl) + CONFIG_THUMB
    724        .word 20f   - L(blend_v_tbl) + CONFIG_THUMB
    725 
    726 20:
    727        vmov.i8         d22, #64
    728        vld1.8          {d2[]},   [lr]
    729        add             r12, r0,  r1
    730        lsl             r1,  r1,  #1
    731        vsub.i8         d3,  d22, d2
    732 2:
    733        vld1.16         {d1[0]},  [r2,  :16]!
    734        vld1.8          {d0[]},   [r0]
    735        subs            r4,  r4,  #2
    736        vld1.8          {d1[1]},  [r2]
    737        vld1.8          {d0[1]},  [r12]
    738        vmull.u8        q2,  d1,  d2
    739        vmlal.u8        q2,  d0,  d3
    740        vrshrn.i16      d6,  q2,  #6
    741        add             r2,  r2,  #2
    742        vst1.8          {d6[0]},  [r0],  r1
    743        vst1.8          {d6[1]},  [r12], r1
    744        bgt             2b
    745        pop             {r4,pc}
    746 40:
    747        vmov.i8         d22, #64
    748        vld1.32         {d4[]},   [lr,  :32]
    749        add             r12, r0,  r1
    750        lsl             r1,  r1,  #1
    751        vsub.i8         d5,  d22, d4
    752        sub             r1,  r1,  #2
    753 4:
    754        vld1.u8         {d2},     [r2,  :64]!
    755        vld1.32         {d0[]},   [r0,  :32]
    756        vld1.32         {d0[1]},  [r12, :32]
    757        subs            r4,  r4,  #2
    758        vmull.u8        q3,  d2,  d4
    759        vmlal.u8        q3,  d0,  d5
    760        vrshrn.i16      d20, q3,  #6
    761        vst1.16         {d20[0]}, [r0,  :16]!
    762        vst1.16         {d20[2]}, [r12, :16]!
    763        vst1.8          {d20[2]}, [r0],  r1
    764        vst1.8          {d20[6]}, [r12], r1
    765        bgt             4b
    766        pop             {r4,pc}
    767 80:
    768        vmov.i8         d16, #64
    769        vld1.u8         {d2},  [lr,  :64]
    770        add             r12, r0,  r1
    771        lsl             r1,  r1,  #1
    772        vsub.i8         d17, d16, d2
    773        sub             r1,  r1,  #4
    774 8:
    775        vld1.u8         {d4,  d5},  [r2,  :128]!
    776        vld1.u8         {d0},  [r0,  :64]
    777        vld1.u8         {d1},  [r12, :64]
    778        subs            r4,  r4,  #2
    779        vmull.u8        q3,  d2,  d4
    780        vmlal.u8        q3,  d0,  d17
    781        vmull.u8        q10, d2,  d5
    782        vmlal.u8        q10, d1,  d17
    783        vrshrn.i16      d22, q3,  #6
    784        vrshrn.i16      d23, q10, #6
    785        vst1.32         {d22[0]}, [r0,  :32]!
    786        vst1.32         {d23[0]}, [r12, :32]!
    787        vst1.16         {d22[2]}, [r0,  :16], r1
    788        vst1.16         {d23[2]}, [r12, :16], r1
    789        bgt             8b
    790        pop             {r4,pc}
    791 160:
    792        vmov.i8         q12, #64
    793        vld1.u8         {q14}, [lr,  :128]
    794        add             r12, r0,  r1
    795        lsl             r1,  r1,  #1
    796        vsub.i8         q11, q12, q14
    797        sub             r1,  r1,  #8
    798 16:
    799        vld1.u8         {q1,  q2},  [r2,  :128]!
    800        vld1.u8         {q0},  [r0,  :128]
    801        subs            r4,  r4,  #2
    802        vld1.u8         {q13}, [r12, :128]
    803        vmull.u8        q3,  d2,  d28
    804        vmlal.u8        q3,  d0,  d22
    805        vmull.u8        q8,  d3,  d29
    806        vmlal.u8        q8,  d1,  d23
    807        vrshrn.i16      d18, q3,  #6
    808        vrshrn.i16      d19, q8,  #6
    809        vmull.u8        q3,  d4,  d28
    810        vmlal.u8        q3,  d26, d22
    811        vmull.u8        q8,  d5,  d29
    812        vmlal.u8        q8,  d27, d23
    813        vrshrn.i16      d20, q3,  #6
    814        vrshrn.i16      d21, q8,  #6
    815        vst1.u8         {d18},    [r0,  :64]!
    816        vst1.u8         {d20},    [r12, :64]!
    817        vst1.32         {d19[0]}, [r0,  :32], r1
    818        vst1.32         {d21[0]}, [r12, :32], r1
    819        bgt             16b
    820        pop             {r4,pc}
    821 320:
    822        vmov.i8         q10, #64
    823        vld1.u8         {q2,  q3},  [lr,  :128]
    824        vsub.i8         q11, q10, q2
    825        vsub.i8         d24, d20, d6
    826 32:
    827        vld1.u8         {q8,  q9},  [r2,  :128]!
    828        vld1.u8         {d0,  d1,  d2},  [r0,  :64]
    829        subs            r4,  r4,  #1
    830        vmull.u8        q15, d16, d4
    831        vmlal.u8        q15, d0,  d22
    832        vmull.u8        q14, d17, d5
    833        vmlal.u8        q14, d1,  d23
    834        vrshrn.i16      d0,  q15, #6
    835        vrshrn.i16      d1,  q14, #6
    836        vmull.u8        q15, d18, d6
    837        vmlal.u8        q15, d2,  d24
    838        vrshrn.i16      d2,  q15, #6
    839        vst1.u8         {d0,  d1,  d2},  [r0,  :64],  r1
    840        bgt             32b
    841        pop             {r4,pc}
    842 endfunc
    843 
    844 
    845 // This has got the same signature as the put_8tap functions,
    846 // assumes that the caller has loaded the h argument into r5,
    847 // and assumes that r8 is set to (clz(w)-24).
    848 function put_neon
    849        adr             r9,  L(put_tbl)
    850        ldr             r8,  [r9, r8, lsl #2]
    851        add             r9,  r9,  r8
    852        bx              r9
    853 
    854        .align 2
    855 L(put_tbl):
    856        .word 1280f - L(put_tbl) + CONFIG_THUMB
    857        .word 640f  - L(put_tbl) + CONFIG_THUMB
    858        .word 32f   - L(put_tbl) + CONFIG_THUMB
    859        .word 160f  - L(put_tbl) + CONFIG_THUMB
    860        .word 8f    - L(put_tbl) + CONFIG_THUMB
    861        .word 4f    - L(put_tbl) + CONFIG_THUMB
    862        .word 2f    - L(put_tbl) + CONFIG_THUMB
    863 
    864 2:
    865        vld1.16         {d0[]}, [r2], r3
    866        vld1.16         {d1[]}, [r2], r3
    867        subs            r5,  r5,  #2
    868        vst1.16         {d0[0]}, [r0, :16], r1
    869        vst1.16         {d1[0]}, [r0, :16], r1
    870        bgt             2b
    871        pop             {r4-r11,pc}
    872 4:
    873        vld1.32         {d0[]}, [r2], r3
    874        vld1.32         {d1[]}, [r2], r3
    875        subs            r5,  r5,  #2
    876        vst1.32         {d0[0]}, [r0, :32], r1
    877        vst1.32         {d1[0]}, [r0, :32], r1
    878        bgt             4b
    879        pop             {r4-r11,pc}
    880 8:
    881        vld1.8          {d0}, [r2], r3
    882        vld1.8          {d1}, [r2], r3
    883        subs            r5,  r5,  #2
    884        vst1.8          {d0}, [r0, :64], r1
    885        vst1.8          {d1}, [r0, :64], r1
    886        bgt             8b
    887        pop             {r4-r11,pc}
    888 160:
    889        add             r8,  r0,  r1
    890        lsl             r1,  r1,  #1
    891        add             r9,  r2,  r3
    892        lsl             r3,  r3,  #1
    893 16:
    894        vld1.8          {q0}, [r2], r3
    895        vld1.8          {q1}, [r9], r3
    896        subs            r5,  r5,  #2
    897        vst1.8          {q0}, [r0, :128], r1
    898        vst1.8          {q1}, [r8, :128], r1
    899        bgt             16b
    900        pop             {r4-r11,pc}
    901 32:
    902        vld1.8          {q0,  q1},  [r2], r3
    903        subs            r5,  r5,  #1
    904        vst1.8          {q0,  q1},  [r0, :128], r1
    905        bgt             32b
    906        pop             {r4-r11,pc}
    907 640:
    908        sub             r1,  r1,  #32
    909        sub             r3,  r3,  #32
    910 64:
    911        vld1.8          {q0,  q1},  [r2]!
    912        vst1.8          {q0,  q1},  [r0, :128]!
    913        vld1.8          {q2,  q3},  [r2], r3
    914        subs            r5,  r5,  #1
    915        vst1.8          {q2,  q3},  [r0, :128], r1
    916        bgt             64b
    917        pop             {r4-r11,pc}
    918 1280:
    919        sub             r1,  r1,  #96
    920        sub             r3,  r3,  #96
    921 128:
    922        vld1.8          {q8,  q9},  [r2]!
    923        vst1.8          {q8,  q9},  [r0, :128]!
    924        vld1.8          {q10, q11}, [r2]!
    925        vst1.8          {q10, q11}, [r0, :128]!
    926        vld1.8          {q12, q13}, [r2]!
    927        vst1.8          {q12, q13}, [r0, :128]!
    928        vld1.8          {q14, q15}, [r2], r3
    929        subs            r5,  r5,  #1
    930        vst1.8          {q14, q15}, [r0, :128], r1
    931        bgt             128b
    932        pop             {r4-r11,pc}
    933 endfunc
    934 
    935 
    936 // This has got the same signature as the put_8tap functions,
    937 // assumes that the caller has loaded the h argument into r4,
    938 // and assumes that r8 is set to (clz(w)-24), and r7 to w*2.
    939 function prep_neon
    940        adr             r9,  L(prep_tbl)
    941        ldr             r8,  [r9, r8, lsl #2]
    942        add             r9,  r9,  r8
    943        bx              r9
    944 
    945        .align 2
    946 L(prep_tbl):
    947        .word 1280f - L(prep_tbl) + CONFIG_THUMB
    948        .word 640f  - L(prep_tbl) + CONFIG_THUMB
    949        .word 320f  - L(prep_tbl) + CONFIG_THUMB
    950        .word 160f  - L(prep_tbl) + CONFIG_THUMB
    951        .word 8f    - L(prep_tbl) + CONFIG_THUMB
    952        .word 4f    - L(prep_tbl) + CONFIG_THUMB
    953 
    954 4:
    955        vld1.32         {d0[]}, [r1], r2
    956        vld1.32         {d2[]}, [r1], r2
    957        subs            r4,  r4,  #2
    958        vshll.u8        q0,  d0,  #4
    959        vshll.u8        q1,  d2,  #4
    960        vst1.16         {d1, d2}, [r0, :64]!
    961        bgt             4b
    962        pop             {r4-r11,pc}
    963 8:
    964        vld1.8          {d0}, [r1], r2
    965        vld1.8          {d2}, [r1], r2
    966        subs            r4,  r4,  #2
    967        vshll.u8        q0,  d0,  #4
    968        vshll.u8        q1,  d2,  #4
    969        vst1.16         {q0, q1}, [r0, :128]!
    970        bgt             8b
    971        pop             {r4-r11,pc}
    972 160:
    973        add             r9,  r1,  r2
    974        lsl             r2,  r2,  #1
    975        add             r8,  r0,  r7
    976        lsl             r7,  r7,  #1
    977 16:
    978        vld1.8          {q2}, [r1], r2
    979        vld1.8          {q3}, [r9], r2
    980        subs            r4,  r4,  #2
    981        vshll.u8        q0,  d4,  #4
    982        vshll.u8        q1,  d5,  #4
    983        vshll.u8        q2,  d6,  #4
    984        vshll.u8        q3,  d7,  #4
    985        vst1.16         {q0, q1}, [r0, :128], r7
    986        vst1.16         {q2, q3}, [r8, :128], r7
    987        bgt             16b
    988        pop             {r4-r11,pc}
    989 320:
    990        add             r8,  r0,  r3
    991 32:
    992        vld1.8          {q0,  q1},  [r1], r2
    993        subs            r4,  r4,  #2
    994        vshll.u8        q8,  d0,  #4
    995        vshll.u8        q9,  d1,  #4
    996        vld1.8          {q2,  q3},  [r1], r2
    997        vshll.u8        q10, d2,  #4
    998        vshll.u8        q11, d3,  #4
    999        vshll.u8        q12, d4,  #4
   1000        vst1.16         {q8,  q9},  [r0, :128], r7
   1001        vshll.u8        q13, d5,  #4
   1002        vst1.16         {q10, q11}, [r8, :128], r7
   1003        vshll.u8        q14, d6,  #4
   1004        vst1.16         {q12, q13}, [r0, :128], r7
   1005        vshll.u8        q15, d7,  #4
   1006        vst1.16         {q14, q15}, [r8, :128], r7
   1007        bgt             32b
   1008        pop             {r4-r11,pc}
   1009 640:
   1010        sub             r2,  r2,  #32
   1011        add             r8,  r0,  #32
   1012        mov             r6,  #64
   1013 64:
   1014        vld1.8          {q0,  q1},  [r1]!
   1015        subs            r4,  r4,  #1
   1016        vshll.u8        q8,  d0,  #4
   1017        vshll.u8        q9,  d1,  #4
   1018        vld1.8          {q2,  q3},  [r1], r2
   1019        vshll.u8        q10, d2,  #4
   1020        vshll.u8        q11, d3,  #4
   1021        vshll.u8        q12, d4,  #4
   1022        vst1.16         {q8,  q9},  [r0, :128], r6
   1023        vshll.u8        q13, d5,  #4
   1024        vshll.u8        q14, d6,  #4
   1025        vst1.16         {q10, q11}, [r8, :128], r6
   1026        vshll.u8        q15, d7,  #4
   1027        vst1.16         {q12, q13}, [r0, :128], r6
   1028        vst1.16         {q14, q15}, [r8, :128], r6
   1029        bgt             64b
   1030        pop             {r4-r11,pc}
   1031 1280:
   1032        sub             r2,  r2,  #96
   1033        add             r8,  r0,  #32
   1034        mov             r6,  #64
   1035 128:
   1036        vld1.8          {q0,  q1},  [r1]!
   1037        vld1.8          {q2,  q3},  [r1]!
   1038        vshll.u8        q10, d0,  #4
   1039        vshll.u8        q11, d1,  #4
   1040        vshll.u8        q12, d2,  #4
   1041        vshll.u8        q13, d3,  #4
   1042        vshll.u8        q14, d4,  #4
   1043        vshll.u8        q15, d5,  #4
   1044        vld1.8          {q8,  q9},  [r1]!
   1045        vst1.16         {q10, q11}, [r0, :128], r6
   1046        vst1.16         {q12, q13}, [r8, :128], r6
   1047        vshll.u8        q0,  d6,  #4
   1048        vshll.u8        q1,  d7,  #4
   1049        vshll.u8        q2,  d16, #4
   1050        vshll.u8        q3,  d17, #4
   1051        vshll.u8        q8,  d18, #4
   1052        vshll.u8        q9,  d19, #4
   1053        vld1.8          {q10, q11}, [r1], r2
   1054        vst1.16         {q14, q15}, [r0, :128], r6
   1055        vst1.16         {q0,  q1},  [r8, :128], r6
   1056        vshll.u8        q12, d20, #4
   1057        vshll.u8        q13, d21, #4
   1058        vshll.u8        q14, d22, #4
   1059        vshll.u8        q15, d23, #4
   1060        subs            r4,  r4,  #1
   1061        vst1.16         {q2,  q3},  [r0, :128], r6
   1062        vst1.16         {q8,  q9},  [r8, :128], r6
   1063        vst1.16         {q12, q13}, [r0, :128], r6
   1064        vst1.16         {q14, q15}, [r8, :128], r6
   1065        bgt             128b
   1066        pop             {r4-r11,pc}
   1067 endfunc
   1068 
   1069 
   1070 .macro load_slice s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6
   1071        vld1.\wd        {\d0[]}, [\s0], \strd
   1072        vld1.\wd        {\d1[]}, [\s1], \strd
   1073 .ifnb \d2
   1074        vld1.\wd        {\d2[]}, [\s0], \strd
   1075        vld1.\wd        {\d3[]}, [\s1], \strd
   1076 .endif
   1077 .ifnb \d4
   1078        vld1.\wd        {\d4[]}, [\s0], \strd
   1079 .endif
   1080 .ifnb \d5
   1081        vld1.\wd        {\d5[]}, [\s1], \strd
   1082 .endif
   1083 .ifnb \d6
   1084        vld1.\wd        {\d6[]}, [\s0], \strd
   1085 .endif
   1086 .endm
   1087 .macro load_reg s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
   1088        vld1.8          {\d0}, [\s0], \strd
   1089        vld1.8          {\d1}, [\s1], \strd
   1090 .ifnb \d2
   1091        vld1.8          {\d2}, [\s0], \strd
   1092        vld1.8          {\d3}, [\s1], \strd
   1093 .endif
   1094 .ifnb \d4
   1095        vld1.8          {\d4}, [\s0], \strd
   1096 .endif
   1097 .ifnb \d5
   1098        vld1.8          {\d5}, [\s1], \strd
   1099 .endif
   1100 .ifnb \d6
   1101        vld1.8          {\d6}, [\s0], \strd
   1102 .endif
   1103 .endm
   1104 .macro load_16 s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
   1105        load_slice      \s0, \s1, \strd, 16, \d0, \d1, \d2, \d3, \d4, \d5, \d6
   1106 .endm
   1107 .macro load_32 s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
   1108        load_slice      \s0, \s1, \strd, 32, \d0, \d1, \d2, \d3, \d4, \d5, \d6
   1109 .endm
   1110 .macro interleave_1_16 r0, r1, r2, r3, r4
   1111        vext.8          \r0, \r0, \r1, #6
   1112        vext.8          \r1, \r1, \r2, #6
   1113 .ifnb \r3
   1114        vext.8          \r2, \r2, \r3, #6
   1115        vext.8          \r3, \r3, \r4, #6
   1116 .endif
   1117 .endm
   1118 .macro interleave_1_32 r0, r1, r2, r3, r4
   1119        vext.8          \r0, \r0, \r1, #4
   1120        vext.8          \r1, \r1, \r2, #4
   1121 .ifnb \r3
   1122        vext.8          \r2, \r2, \r3, #4
   1123        vext.8          \r3, \r3, \r4, #4
   1124 .endif
   1125 .endm
   1126 .macro vmovl_u8 q0, d0, q1, d1, q2, d2, q3, d3, q4, d4, q5, d5, q6, d6
   1127        vmovl.u8        \q0, \d0
   1128        vmovl.u8        \q1, \d1
   1129 .ifnb \q2
   1130        vmovl.u8        \q2, \d2
   1131        vmovl.u8        \q3, \d3
   1132 .endif
   1133 .ifnb \q4
   1134        vmovl.u8        \q4, \d4
   1135 .endif
   1136 .ifnb \q5
   1137        vmovl.u8        \q5, \d5
   1138 .endif
   1139 .ifnb \q6
   1140        vmovl.u8        \q6, \d6
   1141 .endif
   1142 .endm
   1143 .macro mul_mla_4 d, s0, s1, s2, s3
   1144        vmul.s16        \d,  \s0,  d0[0]
   1145        vmla.s16        \d,  \s1,  d0[1]
   1146        vmla.s16        \d,  \s2,  d0[2]
   1147        vmla.s16        \d,  \s3,  d0[3]
   1148 .endm
   1149 .macro mul_mla_8_0 d0, s0, s1, s2, s3, s4, s5, s6, s7
   1150        vmul.s16        \d0, \s0,  d0[0]
   1151        vmla.s16        \d0, \s1,  d0[1]
   1152        vmla.s16        \d0, \s2,  d0[2]
   1153        vmla.s16        \d0, \s3,  d0[3]
   1154        vmla.s16        \d0, \s4,  d1[0]
   1155        vmla.s16        \d0, \s5,  d1[1]
   1156        vmla.s16        \d0, \s6,  d1[2]
   1157        vmla.s16        \d0, \s7,  d1[3]
   1158 .endm
   1159 .macro mul_mla_8_1 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8
   1160        vmul.s16        \d0, \s0, d0[0]
   1161        vmla.s16        \d0, \s1, d0[1]
   1162        vmla.s16        \d0, \s2, d0[2]
   1163        vmla.s16        \d0, \s3, d0[3]
   1164        vmla.s16        \d0, \s4, d1[0]
   1165        vmla.s16        \d0, \s5, d1[1]
   1166        vmla.s16        \d0, \s6, d1[2]
   1167        vmla.s16        \d0, \s7, d1[3]
   1168        vmul.s16        \d1, \s1, d0[0]
   1169        vmla.s16        \d1, \s2, d0[1]
   1170        vmla.s16        \d1, \s3, d0[2]
   1171        vmla.s16        \d1, \s4, d0[3]
   1172        vmla.s16        \d1, \s5, d1[0]
   1173        vmla.s16        \d1, \s6, d1[1]
   1174        vmla.s16        \d1, \s7, d1[2]
   1175        vmla.s16        \d1, \s8, d1[3]
   1176 .endm
   1177 .macro mul_mla_8_2 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9
   1178        vmul.s16        \d0, \s0, d0[0]
   1179        vmla.s16        \d0, \s1, d0[1]
   1180        vmla.s16        \d0, \s2, d0[2]
   1181        vmla.s16        \d0, \s3, d0[3]
   1182        vmla.s16        \d0, \s4, d1[0]
   1183        vmla.s16        \d0, \s5, d1[1]
   1184        vmla.s16        \d0, \s6, d1[2]
   1185        vmla.s16        \d0, \s7, d1[3]
   1186        vmul.s16        \d1, \s2, d0[0]
   1187        vmla.s16        \d1, \s3, d0[1]
   1188        vmla.s16        \d1, \s4, d0[2]
   1189        vmla.s16        \d1, \s5, d0[3]
   1190        vmla.s16        \d1, \s6, d1[0]
   1191        vmla.s16        \d1, \s7, d1[1]
   1192        vmla.s16        \d1, \s8, d1[2]
   1193        vmla.s16        \d1, \s9, d1[3]
   1194 .endm
   1195 .macro vqrshrun_s16 shift, q0, d0, q1, d1, q2, d2, q3, d3
   1196        vqrshrun.s16    \d0, \q0, #\shift
   1197 .ifnb \q1
   1198        vqrshrun.s16    \d1, \q1, #\shift
   1199 .endif
   1200 .ifnb \q2
   1201        vqrshrun.s16    \d2, \q2, #\shift
   1202        vqrshrun.s16    \d3, \q3, #\shift
   1203 .endif
   1204 .endm
   1205 .macro vrshr_s16 shift, r0, r1, r2, r3
   1206        vrshr.s16       \r0, \r0, #\shift
   1207 .ifnb \r1
   1208        vrshr.s16       \r1, \r1, #\shift
   1209 .endif
   1210 .ifnb \r2
   1211        vrshr.s16       \r2, \r2, #\shift
   1212        vrshr.s16       \r3, \r3, #\shift
   1213 .endif
   1214 .endm
   1215 .macro st_16 strd, reg, lanes
   1216        vst1.16         {\reg[0]}, [r0, :16], \strd
   1217        vst1.16         {\reg[1]}, [r8, :16], \strd
   1218 .if \lanes > 2
   1219        vst1.16         {\reg[2]}, [r0, :16], \strd
   1220        vst1.16         {\reg[3]}, [r8, :16], \strd
   1221 .endif
   1222 .endm
   1223 .macro st_32 strd, r0, r1
   1224        vst1.32         {\r0[0]}, [r0, :32], \strd
   1225        vst1.32         {\r0[1]}, [r8, :32], \strd
   1226 .ifnb \r1
   1227        vst1.32         {\r1[0]}, [r0, :32], \strd
   1228        vst1.32         {\r1[1]}, [r8, :32], \strd
   1229 .endif
   1230 .endm
   1231 .macro st_reg strd, align, r0, r1, r2, r3, r4, r5, r6, r7
   1232        vst1.8          {\r0}, [r0, \align], \strd
   1233        vst1.8          {\r1}, [r8, \align], \strd
   1234 .ifnb \r2
   1235        vst1.8          {\r2}, [r0, \align], \strd
   1236        vst1.8          {\r3}, [r8, \align], \strd
   1237 .endif
   1238 .ifnb \r4
   1239        vst1.8          {\r4}, [r0, \align], \strd
   1240        vst1.8          {\r5}, [r8, \align], \strd
   1241        vst1.8          {\r6}, [r0, \align], \strd
   1242        vst1.8          {\r7}, [r8, \align], \strd
   1243 .endif
   1244 .endm
   1245 .macro shift_store_4 type, strd, q0, d0, d1, q1, d2, d3
   1246 .ifc \type, put
   1247        vqrshrun_s16    6,     \q0, \d0, \q1, \d2
   1248        st_32           \strd, \d0, \d2
   1249 .else
   1250        vrshr_s16       2,          \q0, \q1
   1251        st_reg          \strd, :64, \d0, \d1, \d2, \d3
   1252 .endif
   1253 .endm
   1254 .macro shift_store_8 type, strd, q0, d0, q1, d1, q2, d2, q3, d3
   1255 .ifc \type, put
   1256        vqrshrun_s16    6,          \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3
   1257        st_reg          \strd, :64, \d0, \d1, \d2, \d3
   1258 .else
   1259        vrshr_s16       2,          \q0, \q1, \q2, \q3
   1260        st_reg          \strd, :128,\q0, \q1, \q2, \q3
   1261 .endif
   1262 .endm
   1263 .macro shift_store_16 type, strd, q0, d0, d1, q1, q2, d4, d5, q3
   1264 .ifc \type, put
   1265        vqrshrun.s16    \d0,   \q0, #6
   1266        vqrshrun.s16    \d1,   \q1, #6
   1267        vqrshrun.s16    \d4,   \q2, #6
   1268        vqrshrun.s16    \d5,   \q3, #6
   1269        st_reg          \strd, :128, \q0, \q2
   1270 .else
   1271        vrshr_s16       2,     \q0, \q1, \q2, \q3
   1272        vst1.16         {\q0, \q1}, [r0, :128], \strd
   1273        vst1.16         {\q2, \q3}, [r8, :128], \strd
   1274 .endif
   1275 .endm
   1276 
   1277 .macro make_8tap_fn op, type, type_h, type_v
   1278 function \op\()_8tap_\type\()_8bpc_neon, export=1
   1279        push            {r4-r11,lr}
   1280        movw            r8,  \type_h
   1281        movw            r9,  \type_v
   1282        b               \op\()_8tap_neon
   1283 endfunc
   1284 .endm
   1285 
   1286 // No spaces in these expressions, due to gas-preprocessor.
   1287 #define REGULAR ((0*15<<7)|3*15)
   1288 #define SMOOTH  ((1*15<<7)|4*15)
   1289 #define SHARP   ((2*15<<7)|3*15)
   1290 
   1291 .macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, my, ds2, sr2, shift_hv
   1292 make_8tap_fn \type, regular,        REGULAR, REGULAR
   1293 make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH
   1294 make_8tap_fn \type, regular_sharp,  REGULAR, SHARP
   1295 make_8tap_fn \type, smooth,         SMOOTH,  SMOOTH
   1296 make_8tap_fn \type, smooth_regular, SMOOTH,  REGULAR
   1297 make_8tap_fn \type, smooth_sharp,   SMOOTH,  SHARP
   1298 make_8tap_fn \type, sharp,          SHARP,   SHARP
   1299 make_8tap_fn \type, sharp_regular,  SHARP,   REGULAR
   1300 make_8tap_fn \type, sharp_smooth,   SHARP,   SMOOTH
   1301 
   1302 function \type\()_8tap_neon
   1303        ldrd            r4,  r5,  [sp, #36]
   1304        ldrd            r6,  r7,  [sp, #44]
   1305        movw            r10,  #0x4081  // (1 << 14) | (1 << 7) | (1 << 0)
   1306        mul             \mx,  \mx, r10
   1307        mul             \my,  \my, r10
   1308        add             \mx,  \mx, r8 // mx, 8tap_h, 4tap_h
   1309        add             \my,  \my, r9 // my, 8tap_v, 4tap_v
   1310 .ifc \type, prep
   1311        lsl             \d_strd, \w, #1
   1312 .endif
   1313 
   1314        clz             r8,  \w
   1315        tst             \mx, #(0x7f << 14)
   1316        sub             r8,  r8,  #24
   1317        movrel          r10, X(mc_subpel_filters), -8
   1318        bne             L(\type\()_8tap_h)
   1319        tst             \my, #(0x7f << 14)
   1320        bne             L(\type\()_8tap_v)
   1321        b               \type\()_neon
   1322 
   1323 L(\type\()_8tap_h):
   1324        cmp             \w,  #4
   1325        ubfx            r9,  \mx, #7, #7
   1326        and             \mx, \mx, #0x7f
   1327        it              gt
   1328        movgt           \mx,  r9
   1329        tst             \my,  #(0x7f << 14)
   1330        add             \mx, r10, \mx, lsl #3
   1331        bne             L(\type\()_8tap_hv)
   1332 
   1333        adr             r9,  L(\type\()_8tap_h_tbl)
   1334        ldr             r8,  [r9, r8, lsl #2]
   1335        add             r9,  r9,  r8
   1336        bx              r9
   1337 
   1338        .align 2
   1339 L(\type\()_8tap_h_tbl):
   1340        .word 1280f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
   1341        .word 640f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
   1342        .word 320f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
   1343        .word 160f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
   1344        .word 80f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
   1345        .word 40f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
   1346        .word 20f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
   1347 
   1348 20:     // 2xN h
   1349 .ifc \type, put
   1350        add             \mx,  \mx,  #2
   1351        vld1.32         {d0[]}, [\mx]
   1352        sub             \src,  \src,  #1
   1353        add             \ds2,  \dst,  \d_strd
   1354        add             \sr2,  \src,  \s_strd
   1355        lsl             \d_strd,  \d_strd,  #1
   1356        lsl             \s_strd,  \s_strd,  #1
   1357        vmovl.s8        q0,  d0
   1358 2:
   1359        vld1.8          {d4},  [\src], \s_strd
   1360        vld1.8          {d6},  [\sr2], \s_strd
   1361        vmovl.u8        q2,  d4
   1362        vmovl.u8        q3,  d6
   1363        vext.8          d5,  d4,  d5,  #2
   1364        vext.8          d7,  d6,  d7,  #2
   1365        subs            \h,  \h,  #2
   1366        vtrn.32         d4,  d6
   1367        vtrn.32         d5,  d7
   1368        vmul.s16        d2,  d4,  d0[0]
   1369        vmla.s16        d2,  d5,  d0[1]
   1370        vmla.s16        d2,  d6,  d0[2]
   1371        vmla.s16        d2,  d7,  d0[3]
   1372        vrshr.s16       d2,  d2,  #2
   1373        vqrshrun.s16    d2,  q1,  #4
   1374        vst1.16         {d2[0]}, [\dst, :16], \d_strd
   1375        vst1.16         {d2[1]}, [\ds2, :16], \d_strd
   1376        bgt             2b
   1377        pop             {r4-r11,pc}
   1378 .endif
   1379 
   1380 40:     // 4xN h
   1381        add             \mx,  \mx,  #2
   1382        vld1.32         {d0[]}, [\mx]
   1383        sub             \src,  \src,  #1
   1384        add             \ds2,  \dst,  \d_strd
   1385        add             \sr2,  \src,  \s_strd
   1386        lsl             \d_strd,  \d_strd,  #1
   1387        lsl             \s_strd,  \s_strd,  #1
   1388        vmovl.s8        q0,  d0
   1389 4:
   1390        vld1.8          {d16}, [\src], \s_strd
   1391        vld1.8          {d24}, [\sr2], \s_strd
   1392        vmovl.u8        q8,  d16
   1393        vmovl.u8        q12, d24
   1394        vext.8          d18, d16, d17, #2
   1395        vext.8          d20, d16, d17, #4
   1396        vext.8          d22, d16, d17, #6
   1397        vext.8          d26, d24, d25, #2
   1398        vext.8          d28, d24, d25, #4
   1399        vext.8          d30, d24, d25, #6
   1400        subs            \h,  \h,  #2
   1401        vmul.s16        d4,  d16, d0[0]
   1402        vmla.s16        d4,  d18, d0[1]
   1403        vmla.s16        d4,  d20, d0[2]
   1404        vmla.s16        d4,  d22, d0[3]
   1405        vmul.s16        d5,  d24, d0[0]
   1406        vmla.s16        d5,  d26, d0[1]
   1407        vmla.s16        d5,  d28, d0[2]
   1408        vmla.s16        d5,  d30, d0[3]
   1409        vrshr.s16       q2,  q2,  #2
   1410 .ifc \type, put
   1411        vqrshrun.s16    d4,  q2,  #4
   1412        vst1.32         {d4[0]}, [\dst, :32], \d_strd
   1413        vst1.32         {d4[1]}, [\ds2, :32], \d_strd
   1414 .else
   1415        vst1.16         {d4}, [\dst, :64], \d_strd
   1416        vst1.16         {d5}, [\ds2, :64], \d_strd
   1417 .endif
   1418        bgt             4b
   1419        pop             {r4-r11,pc}
   1420 
   1421 80:     // 8xN h
   1422        vld1.8          {d0}, [\mx, :64]
   1423        sub             \src,  \src,  #3
   1424        add             \ds2,  \dst,  \d_strd
   1425        add             \sr2,  \src,  \s_strd
   1426        lsl             \d_strd,  \d_strd,  #1
   1427        lsl             \s_strd,  \s_strd,  #1
   1428        vmovl.s8        q0,  d0
   1429 8:
   1430        vld1.8          {q8},  [\src], \s_strd
   1431        vld1.8          {q12}, [\sr2], \s_strd
   1432        vmovl.u8        q9,  d17
   1433        vmovl.u8        q8,  d16
   1434        vmovl.u8        q13, d25
   1435        vmovl.u8        q12, d24
   1436 
   1437        vmul.s16        q10, q8,  d0[0]
   1438        vmul.s16        q14, q12, d0[0]
   1439 .irpc i, 1234567
   1440        vext.8          q11, q8,  q9,  #(2*\i)
   1441        vext.8          q15, q12, q13, #(2*\i)
   1442 .if \i < 4
   1443        vmla.s16        q10, q11, d0[\i]
   1444        vmla.s16        q14, q15, d0[\i]
   1445 .else
   1446        vmla.s16        q10, q11, d1[\i-4]
   1447        vmla.s16        q14, q15, d1[\i-4]
   1448 .endif
   1449 .endr
   1450        subs            \h,  \h,  #2
   1451        vrshr.s16       q10, q10, #2
   1452        vrshr.s16       q14, q14, #2
   1453 .ifc \type, put
   1454        vqrshrun.s16    d20, q10, #4
   1455        vqrshrun.s16    d28, q14, #4
   1456        vst1.8          {d20}, [\dst, :64], \d_strd
   1457        vst1.8          {d28}, [\ds2, :64], \d_strd
   1458 .else
   1459        vst1.16         {q10}, [\dst, :128], \d_strd
   1460        vst1.16         {q14}, [\ds2, :128], \d_strd
   1461 .endif
   1462        bgt             8b
   1463        pop             {r4-r11,pc}
   1464 
   1465 160:
   1466 320:
   1467 640:
   1468 1280:   // 16xN, 32xN, ... h
   1469        // This could be done without touching q4-q6, by using only
   1470        // one temporary for vext in the loop. That's slower on A7 and A53,
   1471        // (but surprisingly, marginally faster on A8 and A73).
   1472        vpush           {q4-q6}
   1473        vld1.8          {d0}, [\mx, :64]
   1474        sub             \src,  \src,  #3
   1475        add             \ds2,  \dst,  \d_strd
   1476        add             \sr2,  \src,  \s_strd
   1477        lsl             \s_strd,  \s_strd,  #1
   1478        vmovl.s8        q0,  d0
   1479 
   1480        sub             \s_strd,  \s_strd,  \w
   1481        sub             \s_strd,  \s_strd,  #8
   1482 .ifc \type, put
   1483        lsl             \d_strd,  \d_strd,  #1
   1484        sub             \d_strd,  \d_strd,  \w
   1485 .endif
   1486 161:
   1487        vld1.8          {d16, d17, d18},  [\src]!
   1488        vld1.8          {d24, d25, d26},  [\sr2]!
   1489        mov             \mx, \w
   1490        vmovl.u8        q10, d18
   1491        vmovl.u8        q9,  d17
   1492        vmovl.u8        q8,  d16
   1493        vmovl.u8        q14, d26
   1494        vmovl.u8        q13, d25
   1495        vmovl.u8        q12, d24
   1496 
   1497 16:
   1498        vmul.s16        q1,  q8,  d0[0]
   1499        vmul.s16        q2,  q9,  d0[0]
   1500        vmul.s16        q3,  q12, d0[0]
   1501        vmul.s16        q4,  q13, d0[0]
   1502 .irpc i, 1234567
   1503        vext.8          q5,  q8,  q9,  #(2*\i)
   1504        vext.8          q6,  q9,  q10, #(2*\i)
   1505        vext.8          q11, q12, q13, #(2*\i)
   1506        vext.8          q15, q13, q14, #(2*\i)
   1507 .if \i < 4
   1508        vmla.s16        q1,  q5,  d0[\i]
   1509        vmla.s16        q2,  q6,  d0[\i]
   1510        vmla.s16        q3,  q11, d0[\i]
   1511        vmla.s16        q4,  q15, d0[\i]
   1512 .else
   1513        vmla.s16        q1,  q5,  d1[\i-4]
   1514        vmla.s16        q2,  q6,  d1[\i-4]
   1515        vmla.s16        q3,  q11, d1[\i-4]
   1516        vmla.s16        q4,  q15, d1[\i-4]
   1517 .endif
   1518 .endr
   1519        vrshr.s16       q1,  q1,  #2
   1520        vrshr.s16       q2,  q2,  #2
   1521        vrshr.s16       q3,  q3,  #2
   1522        vrshr.s16       q4,  q4,  #2
   1523        subs            \mx, \mx, #16
   1524 .ifc \type, put
   1525        vqrshrun.s16    d2,  q1,  #4
   1526        vqrshrun.s16    d3,  q2,  #4
   1527        vqrshrun.s16    d4,  q3,  #4
   1528        vqrshrun.s16    d5,  q4,  #4
   1529        vst1.8          {q1}, [\dst, :128]!
   1530        vst1.8          {q2}, [\ds2, :128]!
   1531 .else
   1532        vst1.16         {q1, q2}, [\dst, :128]!
   1533        vst1.16         {q3, q4}, [\ds2, :128]!
   1534 .endif
   1535        ble             9f
   1536 
   1537        vmov            q8,  q10
   1538        vmov            q12, q14
   1539        vld1.8          {d18, d19}, [\src]!
   1540        vld1.8          {d26, d27}, [\sr2]!
   1541        vmovl.u8        q10, d19
   1542        vmovl.u8        q9,  d18
   1543        vmovl.u8        q14, d27
   1544        vmovl.u8        q13, d26
   1545        b               16b
   1546 
   1547 9:
   1548        add             \dst,  \dst,  \d_strd
   1549        add             \ds2,  \ds2,  \d_strd
   1550        add             \src,  \src,  \s_strd
   1551        add             \sr2,  \sr2,  \s_strd
   1552 
   1553        subs            \h,  \h,  #2
   1554        bgt             161b
   1555        vpop            {q4-q6}
   1556        pop             {r4-r11,pc}
   1557 
   1558 L(\type\()_8tap_v):
   1559        cmp             \h,  #4
   1560        ubfx            r9,  \my, #7, #7
   1561        and             \my, \my, #0x7f
   1562        it              gt
   1563        movgt           \my, r9
   1564        add             \my, r10, \my, lsl #3
   1565 
   1566        adr             r9,  L(\type\()_8tap_v_tbl)
   1567        ldr             r8,  [r9, r8, lsl #2]
   1568        add             r9,  r9,  r8
   1569        bx              r9
   1570 
   1571        .align 2
   1572 L(\type\()_8tap_v_tbl):
   1573        .word 1280f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
   1574        .word 640f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
   1575        .word 320f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
   1576        .word 160f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
   1577        .word 80f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
   1578        .word 40f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
   1579        .word 20f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
   1580 
   1581 20:     // 2xN v
   1582 .ifc \type, put
   1583        bgt             28f
   1584 
   1585        cmp             \h,  #2
   1586        add             \my, \my, #2
   1587        vld1.32         {d0[]}, [\my]
   1588        sub             \src,  \src,  \s_strd
   1589        add             \ds2,  \dst,  \d_strd
   1590        add             \sr2,  \src,  \s_strd
   1591        lsl             \s_strd,  \s_strd,  #1
   1592        lsl             \d_strd,  \d_strd,  #1
   1593        vmovl.s8        q0,  d0
   1594 
   1595        // 2x2 v
   1596        load_16         \src, \sr2, \s_strd, d1, d2, d3, d4, d5
   1597        interleave_1_16 d1, d2, d3, d4, d5
   1598        bgt             24f
   1599        vmovl_u8        q8, d1, q9, d2, q10, d3, q11, d4
   1600        mul_mla_4       d6, d16, d18, d20, d22
   1601        vqrshrun_s16    6,   q3,  d6
   1602        st_16           \d_strd, d6, 2
   1603        pop             {r4-r11,pc}
   1604 
   1605 24:     // 2x4 v
   1606        load_16         \sr2, \src, \s_strd, d6, d7
   1607        interleave_1_16 d5, d6, d7
   1608        vmovl_u8        q8, d1, q9, d2, q10, d3, q11, d4, q12, d5, q13, d6
   1609        vmov            d17, d20
   1610        vmov            d19, d22
   1611        vmov            d21, d24
   1612        vmov            d23, d26
   1613        mul_mla_4       q3, q8, q9, q10, q11
   1614        vqrshrun_s16    6,   q3,  d6
   1615        st_16           \d_strd, d6, 4
   1616        pop             {r4-r11,pc}
   1617 
   1618 28:     // 2x6, 2x8, 2x12, 2x16 v
   1619        vpush           {q4-q7}
   1620        vld1.8          {d0}, [\my, :64]
   1621        sub             \sr2,  \src,  \s_strd, lsl #1
   1622        add             \ds2,  \dst,  \d_strd
   1623        sub             \src,  \sr2,  \s_strd
   1624        lsl             \d_strd,  \d_strd,  #1
   1625        lsl             \s_strd,  \s_strd,  #1
   1626        vmovl.s8        q0,  d0
   1627 
   1628        load_16         \src, \sr2, \s_strd, d2,  d4,  d6,  d8,  d10, d12, d14
   1629        interleave_1_16 d2,  d4,  d6,  d8,  d10
   1630        interleave_1_16 d10, d12, d14
   1631        vmovl_u8        q1,  d2,  q2,  d4,  q3,  d6,  q4,  d8,  q5,  d10, q6,  d12
   1632        vmov            d3,  d6
   1633        vmov            d5,  d8
   1634        vmov            d7,  d10
   1635        vmov            d9,  d12
   1636 216:
   1637        subs            \h,  \h,  #4
   1638        load_16         \sr2, \src, \s_strd, d16, d18, d20, d22
   1639        interleave_1_16 d14, d16, d18, d20, d22
   1640        vmovl_u8        q7,  d14, q8,  d16, q9,  d18, q10, d20
   1641        vmov            d11, d14
   1642        vmov            d13, d16
   1643        vmov            d15, d18
   1644        vmov            d17, d20
   1645        mul_mla_8_0     q1,  q1,  q2,  q3,  q4,  q5,  q6,  q7, q8
   1646        vqrshrun_s16    6,   q1,  d2
   1647        st_16           \d_strd, d2, 4
   1648        ble             0f
   1649        cmp             \h,  #2
   1650        vmov            q1,  q5
   1651        vmov            q2,  q6
   1652        vmov            q3,  q7
   1653        vmov            q4,  q8
   1654        vmov            q5,  q9
   1655        vmov            q6,  q10
   1656        vmov            d14, d22
   1657        beq             26f
   1658        b               216b
   1659 26:
   1660        load_16         \sr2, \src, \s_strd, d16, d18
   1661        interleave_1_16 d14, d16, d18
   1662        vmovl_u8        q7,  d14, q8,  d16
   1663        vmov            d11, d14
   1664        vmov            d13, d16
   1665        mul_mla_8_0     d2,  d2,  d4,  d6,  d8,  d10, d12, d14, d16
   1666        vqrshrun_s16    6,   q1,  d2
   1667        st_16           \d_strd, d2, 2
   1668 0:
   1669        vpop            {q4-q7}
   1670        pop             {r4-r11,pc}
   1671 .endif
   1672 
   1673 40:
   1674        bgt            480f
   1675 
   1676        // 4x2, 4x4 v
   1677        cmp             \h,  #2
   1678        add             \my, \my, #2
   1679        vld1.32         {d0[]}, [\my]
   1680        sub             \src, \src, \s_strd
   1681        add             \ds2, \dst, \d_strd
   1682        add             \sr2, \src, \s_strd
   1683        lsl             \s_strd, \s_strd, #1
   1684        lsl             \d_strd, \d_strd, #1
   1685        vmovl.s8        q0,  d0
   1686 
   1687        load_32         \src, \sr2, \s_strd, d1, d2, d3, d4, d5
   1688        interleave_1_32 d1,  d2,  d3,  d4,  d5
   1689        vmovl_u8        q8,  d1,  q9,  d2,  q10, d3,  q11, d4
   1690        mul_mla_4       q3,  q8,  q9,  q10, q11
   1691        shift_store_4   \type, \d_strd, q3, d6, d7
   1692        ble             0f
   1693        load_32         \sr2, \src, \s_strd, d6, d7
   1694        interleave_1_32 d5,  d6,  d7
   1695        vmovl_u8        q12, d5,  q13, d6
   1696        mul_mla_4       q3,  q10, q11, q12, q13
   1697        shift_store_4   \type, \d_strd, q3, d6, d7
   1698 0:
   1699        pop             {r4-r11,pc}
   1700 
   1701 480:    // 4x6, 4x8, 4x12, 4x16 v
   1702        vpush           {q4}
   1703        vld1.8          {d0}, [\my, :64]
   1704        sub             \sr2, \src, \s_strd, lsl #1
   1705        add             \ds2, \dst, \d_strd
   1706        sub             \src, \sr2, \s_strd
   1707        lsl             \s_strd, \s_strd, #1
   1708        lsl             \d_strd, \d_strd, #1
   1709        vmovl.s8        q0,  d0
   1710 
   1711        load_32         \src, \sr2, \s_strd, d2,  d4,  d6,  d8,  d16, d18, d20
   1712        interleave_1_32 d2,  d4,  d6
   1713        interleave_1_32 d6,  d8,  d16, d18, d20
   1714        vmovl_u8        q1,  d2,  q2,  d4,  q3,  d6,  q4,  d8,  q8,  d16, q9,  d18
   1715 
   1716 48:
   1717        subs            \h,  \h,  #4
   1718        load_32         \sr2, \src, \s_strd, d22, d24, d26, d28
   1719        interleave_1_32 d20, d22, d24, d26, d28
   1720        vmovl_u8        q10, d20, q11, d22, q12, d24, q13, d26
   1721        mul_mla_8_2     q1,  q2,  q1,  q2,  q3,  q4,  q8,  q9,  q10, q11, q12, q13
   1722        shift_store_4   \type, \d_strd, q1,  d2,  d3,  q2,  d4,  d5
   1723        ble             0f
   1724        load_32         \sr2,  \src, \s_strd, d30, d2
   1725        subs            \h,  \h,  #2
   1726        interleave_1_32 d28, d30, d2
   1727        vmovl_u8        q14, d28, q15, d30
   1728        mul_mla_8_0     q8,  q8,  q9,  q10, q11, q12, q13, q14, q15
   1729        shift_store_4   \type, \d_strd, q8,  d16, d17
   1730        ble             0f
   1731        load_32         \sr2,  \src, \s_strd, d4,  d6
   1732        subs            \h,  \h,  #2
   1733        interleave_1_32 d2,  d4,  d6
   1734        vmovl_u8        q1,  d2,  q2,  d4
   1735        mul_mla_8_0     q9,  q10, q11, q12, q13, q14, q15, q1,  q2
   1736        shift_store_4   \type, \d_strd, q9,  d18, d19
   1737        ble             0f
   1738        subs            \h,  \h,  #4
   1739        load_32         \sr2, \src, \s_strd, d8,  d16, d18, d20
   1740        interleave_1_32 d6,  d8,  d16, d18, d20
   1741        vmovl_u8        q3,  d6,  q4,  d8,  q8,  d16, q9, d18
   1742        mul_mla_8_2     q12, q13, q12, q13, q14, q15, q1,  q2,  q3,  q4,  q8,  q9
   1743        shift_store_4   \type, \d_strd, q12, d24, d25, q13, d26, d27
   1744        bgt             48b
   1745 0:
   1746        vpop            {q4}
   1747        pop             {r4-r11,pc}
   1748 
   1749 80:
   1750        bgt             880f
   1751 
   1752        // 8x2, 8x4 v
   1753        cmp             \h,  #2
   1754        add             \my, \my, #2
   1755        vld1.32         {d0[]}, [\my]
   1756        sub             \src, \src, \s_strd
   1757        add             \ds2, \dst, \d_strd
   1758        add             \sr2, \src, \s_strd
   1759        lsl             \s_strd, \s_strd, #1
   1760        lsl             \d_strd, \d_strd, #1
   1761        vmovl.s8        q0,  d0
   1762 
   1763        load_reg        \src, \sr2, \s_strd, d1, d2, d3, d4, d5
   1764        vmovl_u8        q8,  d1,  q9,  d2,  q10, d3,  q11, d4,  q12, d5
   1765        mul_mla_4       q1,  q8,  q9,  q10, q11
   1766        mul_mla_4       q2,  q9,  q10, q11, q12
   1767        shift_store_8   \type, \d_strd, q1, d2, q2, d4
   1768        ble             0f
   1769        load_reg        \sr2, \src, \s_strd, d6, d7
   1770        vmovl_u8        q13, d6,  q14, d7
   1771        mul_mla_4       q1,  q10, q11, q12, q13
   1772        mul_mla_4       q2,  q11, q12, q13, q14
   1773        shift_store_8   \type, \d_strd, q1, d2, q2, d4
   1774 0:
   1775        pop             {r4-r11,pc}
   1776 
   1777 880:    // 8x6, 8x8, 8x16, 8x32 v
   1778 1680:   // 16x8, 16x16, ...
   1779 320:    // 32x8, 32x16, ...
   1780 640:
   1781 1280:
   1782        vpush           {q4}
   1783        vld1.8          {d0}, [\my, :64]
   1784        sub             \src, \src, \s_strd
   1785        sub             \src, \src, \s_strd, lsl #1
   1786        vmovl.s8        q0,  d0
   1787        mov             \my, \h
   1788 168:
   1789        add             \ds2, \dst, \d_strd
   1790        add             \sr2, \src, \s_strd
   1791        lsl             \s_strd, \s_strd, #1
   1792        lsl             \d_strd, \d_strd, #1
   1793 
   1794        load_reg        \src, \sr2, \s_strd, d2,  d4,  d6,  d8,  d16, d18, d20
   1795        vmovl_u8        q1,  d2,  q2,  d4,  q3,  d6,  q4,  d8,  q8,  d16, q9,  d18, q10, d20
   1796 
   1797 88:
   1798        subs            \h,  \h,  #2
   1799        load_reg        \sr2, \src, \s_strd, d22, d24
   1800        vmovl_u8        q11, d22, q12, d24
   1801        mul_mla_8_1     q1,  q2,  q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12
   1802        shift_store_8   \type, \d_strd, q1,  d2,  q2,  d4
   1803        ble             9f
   1804        subs            \h,  \h,  #2
   1805        load_reg        \sr2, \src, \s_strd, d26, d28
   1806        vmovl_u8        q13, d26, q14, d28
   1807        mul_mla_8_1     q3,  q4,  q3,  q4,  q8,  q9,  q10, q11, q12, q13, q14
   1808        shift_store_8   \type, \d_strd, q3,  d6,  q4,  d8
   1809        ble             9f
   1810        subs            \h,  \h,  #2
   1811        load_reg        \sr2, \src, \s_strd, d30, d2
   1812        vmovl_u8        q15, d30, q1,  d2
   1813        mul_mla_8_1     q8,  q9,  q8,  q9,  q10, q11, q12, q13, q14, q15, q1
   1814        shift_store_8   \type, \d_strd, q8,  d16, q9,  d18
   1815        ble             9f
   1816        subs            \h,  \h,  #2
   1817        load_reg        \sr2, \src, \s_strd, d4,  d6
   1818        vmovl_u8        q2,  d4,  q3,  d6
   1819        mul_mla_8_1     q10, q11, q10, q11, q12, q13, q14, q15, q1,  q2,  q3
   1820        shift_store_8   \type, \d_strd, q10, d20, q11, d22
   1821        ble             9f
   1822        subs            \h,  \h,  #4
   1823        load_reg        \sr2, \src, \s_strd, d8,  d16, d18, d20
   1824        vmovl_u8        q4,  d8,  q8,  d16, q9,  d18, q10, d20
   1825        mul_mla_8_1     q12, q13, q12, q13, q14, q15, q1,  q2,  q3,  q4,  q8
   1826        mul_mla_8_1     q14, q15, q14, q15, q1,  q2,  q3,  q4,  q8,  q9,  q10
   1827        shift_store_8   \type, \d_strd, q12, d24, q13, d26, q14, d28, q15, d30
   1828        bgt             88b
   1829 9:
   1830        subs            \w,  \w,  #8
   1831        ble             0f
   1832        asr             \s_strd, \s_strd, #1
   1833        asr             \d_strd, \d_strd, #1
   1834        mls             \src, \s_strd, \my, \src
   1835        mls             \dst, \d_strd, \my, \dst
   1836        sub             \src, \src, \s_strd, lsl #3
   1837        mov             \h,  \my
   1838        add             \src, \src, #8
   1839 .ifc \type, put
   1840        add             \dst, \dst, #8
   1841 .else
   1842        add             \dst, \dst, #16
   1843 .endif
   1844        b               168b
   1845 0:
   1846        vpop            {q4}
   1847        pop             {r4-r11,pc}
   1848 
   1849 160:
   1850        bgt             1680b
   1851 
   1852        // 16x2, 16x4 v
   1853        add             \my, \my, #2
   1854        vld1.32         {d0[]}, [\my]
   1855        sub             \src, \src, \s_strd
   1856        add             \ds2, \dst, \d_strd
   1857        add             \sr2, \src, \s_strd
   1858        lsl             \s_strd, \s_strd, #1
   1859        lsl             \d_strd, \d_strd, #1
   1860        vmovl.s8        q0,  d0
   1861 
   1862        cmp             \h,  #2
   1863        load_reg        \src, \sr2, \s_strd, q11, q12, q13, q14, q15
   1864        vmovl.u8        q1,  d22
   1865        vmovl.u8        q2,  d24
   1866        vmovl.u8        q3,  d26
   1867        vmovl.u8        q8,  d28
   1868        vmovl.u8        q9,  d30
   1869        vmovl.u8        q11, d23
   1870        vmovl.u8        q12, d25
   1871        vmovl.u8        q13, d27
   1872        vmovl.u8        q14, d29
   1873        vmovl.u8        q15, d31
   1874        mul_mla_4       q1,  q1,  q2,  q3,  q8
   1875        mul_mla_4       q10, q2,  q3,  q8,  q9
   1876        mul_mla_4       q2,  q11, q12, q13, q14
   1877        mul_mla_4       q11, q12, q13, q14, q15
   1878        shift_store_16  \type, \d_strd, q1, d2, d3, q2, q10, d20, d21, q11
   1879        ble             0f
   1880        load_reg        \sr2, \src, \s_strd, q10, q11
   1881        vmovl.u8        q1,  d20
   1882        vmovl.u8        q10, d21
   1883        vmovl.u8        q12, d22
   1884        vmovl.u8        q11, d23
   1885        mul_mla_4       q2,  q3,  q8,  q9,  q1
   1886        mul_mla_4       q3,  q13, q14, q15, q10
   1887        mul_mla_4       q13, q8,  q9,  q1,  q12
   1888        mul_mla_4       q14, q14, q15, q10, q11
   1889        shift_store_16  \type, \d_strd, q2, d4, d5, q3, q13, d26, d27, q14
   1890 0:
   1891        pop             {r4-r11,pc}
   1892 
   1893 L(\type\()_8tap_hv):
   1894        cmp             \h,  #4
   1895        ubfx            r9,  \my, #7, #7
   1896        and             \my, \my, #0x7f
   1897        it              gt
   1898        movgt           \my, r9
   1899        add             \my,  r10, \my, lsl #3
   1900 
   1901        adr             r9,  L(\type\()_8tap_hv_tbl)
   1902        ldr             r8,  [r9, r8, lsl #2]
   1903        add             r9,  r9,  r8
   1904        bx              r9
   1905 
   1906        .align 2
   1907 L(\type\()_8tap_hv_tbl):
   1908        .word 1280f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
   1909        .word 640f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
   1910        .word 320f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
   1911        .word 160f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
   1912        .word 80f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
   1913        .word 40f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
   1914        .word 20f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
   1915 
   1916 20:
   1917 .ifc \type, put
   1918        add             \mx,  \mx,  #2
   1919        vld1.32         {d0[]},  [\mx]
   1920        bgt             280f
   1921        add             \my,  \my,  #2
   1922        vld1.32         {d2[]},  [\my]
   1923 
   1924        // 2x2, 2x4 hv
   1925        sub             \sr2, \src, #1
   1926        sub             \src, \sr2, \s_strd
   1927        add             \ds2, \dst, \d_strd
   1928        lsl             \s_strd, \s_strd, #1
   1929        lsl             \d_strd, \d_strd, #1
   1930        vmovl.s8        q0,  d0
   1931        vmovl.s8        q1,  d2
   1932 
   1933 
   1934        vld1.8          {d26}, [\src], \s_strd
   1935        vmovl.u8        q13, d26
   1936        vext.8          q14, q13, q13, #2
   1937        vmul.s16        d26, d26, d0
   1938        vmul.s16        d28, d28, d0
   1939        vpadd.s16       d26, d26, d28
   1940        vpadd.s16       d26, d26, d26
   1941        vrshr.s16       d16, d26, #2
   1942        bl              L(\type\()_8tap_filter_2)
   1943 
   1944        vext.8          d16, d16, d16, #4
   1945        vmov            d17, d26
   1946        vext.8          d16, d16, d26, #4
   1947 
   1948 2:
   1949        bl              L(\type\()_8tap_filter_2)
   1950 
   1951        vext.8          d18, d17, d26, #4
   1952        vmull.s16       q2,  d16, d2[0]
   1953        vmlal.s16       q2,  d17, d2[1]
   1954        vmlal.s16       q2,  d18, d2[2]
   1955        vmlal.s16       q2,  d26, d2[3]
   1956 
   1957        vqrshrn.s32     d4,  q2,  #\shift_hv
   1958        vqmovun.s16     d4,  q2
   1959        subs            \h,  \h,  #2
   1960        vst1.16         {d4[0]}, [\dst, :16], \d_strd
   1961        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
   1962        ble             0f
   1963        vmov            d16, d18
   1964        vmov            d17, d26
   1965        b               2b
   1966 
   1967 280:    // 2x8, 2x16, 2x32 hv
   1968        vld1.8          {d2},  [\my, :64]
   1969        sub             \src, \src, #1
   1970        sub             \sr2, \src, \s_strd, lsl #1
   1971        sub             \src, \sr2, \s_strd
   1972        add             \ds2, \dst, \d_strd
   1973        lsl             \s_strd, \s_strd, #1
   1974        lsl             \d_strd, \d_strd, #1
   1975        vmovl.s8        q0,  d0
   1976        vmovl.s8        q1,  d2
   1977 
   1978        vld1.8          {d26}, [\src], \s_strd
   1979        vmovl.u8        q13, d26
   1980        vext.8          q14, q13, q13, #2
   1981        vmul.s16        d26, d26, d0
   1982        vmul.s16        d28, d28, d0
   1983        vpadd.s16       d26, d26, d28
   1984        vpadd.s16       d26, d26, d26
   1985        vrshr.s16       d16, d26, #2
   1986 
   1987        bl              L(\type\()_8tap_filter_2)
   1988        vext.8          d16, d16, d16, #4
   1989        vmov            d17, d26
   1990        vext.8          d16, d16, d26, #4
   1991        bl              L(\type\()_8tap_filter_2)
   1992        vext.8          d18, d17, d26, #4
   1993        vmov            d19, d26
   1994        bl              L(\type\()_8tap_filter_2)
   1995        vext.8          d20, d19, d26, #4
   1996        vmov            d21, d26
   1997 
   1998 28:
   1999        bl              L(\type\()_8tap_filter_2)
   2000        vext.8          d22, d21, d26, #4
   2001        vmull.s16       q2,  d16, d2[0]
   2002        vmlal.s16       q2,  d17, d2[1]
   2003        vmlal.s16       q2,  d18, d2[2]
   2004        vmlal.s16       q2,  d19, d2[3]
   2005        vmlal.s16       q2,  d20, d3[0]
   2006        vmlal.s16       q2,  d21, d3[1]
   2007        vmlal.s16       q2,  d22, d3[2]
   2008        vmlal.s16       q2,  d26, d3[3]
   2009 
   2010        vqrshrn.s32     d4,  q2,  #\shift_hv
   2011        vqmovun.s16     d4,  q2
   2012        subs            \h,  \h,  #2
   2013        vst1.16         {d4[0]}, [\dst, :16], \d_strd
   2014        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
   2015        ble             0f
   2016        vmov            d16, d18
   2017        vmov            d17, d19
   2018        vmov            d18, d20
   2019        vmov            d19, d21
   2020        vmov            d20, d22
   2021        vmov            d21, d26
   2022        b               28b
   2023 
   2024 0:
   2025        pop             {r4-r11,pc}
   2026 
   2027 L(\type\()_8tap_filter_2):
   2028        vld1.8          {d28},  [\sr2], \s_strd
   2029        vld1.8          {d30},  [\src], \s_strd
   2030        vext.8          d29, d28, d28, #1
   2031        vext.8          d31, d30, d30, #1
   2032        vmovl.u8        q13, d28
   2033        vmovl.u8        q14, d29
   2034        vmov            d27, d28
   2035        vmovl.u8        q14, d30
   2036        vmovl.u8        q15, d31
   2037        vtrn.32         d26, d28
   2038        vtrn.32         d27, d30
   2039        vmul.s16        d26, d26, d0[0]
   2040        vmla.s16        d26, d27, d0[1]
   2041        vmla.s16        d26, d28, d0[2]
   2042        vmla.s16        d26, d30, d0[3]
   2043        vrshr.s16       d26, d26, #2
   2044        vext.8          d27, d26, d26, #4
   2045        bx              lr
   2046 .endif
   2047 
   2048 40:
   2049        add             \mx, \mx, #2
   2050        vld1.32         {d0[]},  [\mx]
   2051        bgt             480f
   2052        add             \my, \my,  #2
   2053        vld1.32         {d2[]},  [\my]
   2054        sub             \sr2, \src, #1
   2055        sub             \src, \sr2, \s_strd
   2056        add             \ds2, \dst, \d_strd
   2057        lsl             \s_strd, \s_strd, #1
   2058        lsl             \d_strd, \d_strd, #1
   2059        vmovl.s8        q0,  d0
   2060        vmovl.s8        q1,  d2
   2061 
   2062        // 4x2, 4x4 hv
   2063        vld1.8          {d30}, [\src], \s_strd
   2064        vmovl.u8        q14, d30
   2065        vext.8          d27, d28, d29, #2
   2066        vext.8          d30, d28, d29, #4
   2067        vext.8          d31, d28, d29, #6
   2068        vmul.s16        d26, d28, d0[0]
   2069        vmla.s16        d26, d27, d0[1]
   2070        vmla.s16        d26, d30, d0[2]
   2071        vmla.s16        d26, d31, d0[3]
   2072        vrshr.s16       d16, d26, #2
   2073 
   2074        bl              L(\type\()_8tap_filter_4)
   2075        vmov            d17, d26
   2076        vmov            d18, d27
   2077 
   2078 4:
   2079        bl              L(\type\()_8tap_filter_4)
   2080        vmull.s16       q2,  d16, d2[0]
   2081        vmlal.s16       q2,  d17, d2[1]
   2082        vmlal.s16       q2,  d18, d2[2]
   2083        vmlal.s16       q2,  d26, d2[3]
   2084        vmull.s16       q3,  d17, d2[0]
   2085        vmlal.s16       q3,  d18, d2[1]
   2086        vmlal.s16       q3,  d26, d2[2]
   2087        vmlal.s16       q3,  d27, d2[3]
   2088        vqrshrn.s32     d4,  q2,  #\shift_hv
   2089        vqrshrn.s32     d6,  q3,  #\shift_hv
   2090        subs            \h,  \h,  #2
   2091 .ifc \type, put
   2092        vqmovun.s16     d4,  q2
   2093        vqmovun.s16     d6,  q3
   2094        vst1.32         {d4[0]}, [\dst, :32], \d_strd
   2095        vst1.32         {d6[0]}, [\ds2, :32], \d_strd
   2096 .else
   2097        vst1.16         {d4}, [\dst, :64], \d_strd
   2098        vst1.16         {d6}, [\ds2, :64], \d_strd
   2099 .endif
   2100        ble             0f
   2101        vmov            d16, d18
   2102        vmov            d17, d26
   2103        vmov            d18, d27
   2104        b               4b
   2105 
   2106 480:    // 4x8, 4x16, 4x32 hv
   2107        vld1.8          {d2},  [\my, :64]
   2108        sub             \src, \src, #1
   2109        sub             \sr2, \src, \s_strd, lsl #1
   2110        sub             \src, \sr2, \s_strd
   2111        add             \ds2, \dst, \d_strd
   2112        lsl             \s_strd, \s_strd, #1
   2113        lsl             \d_strd, \d_strd, #1
   2114        vmovl.s8        q0,  d0
   2115        vmovl.s8        q1,  d2
   2116 
   2117        vld1.8          {d30}, [\src], \s_strd
   2118        vmovl.u8        q14, d30
   2119        vext.8          d27, d28, d29, #2
   2120        vext.8          d30, d28, d29, #4
   2121        vext.8          d31, d28, d29, #6
   2122        vmul.s16        d26, d28, d0[0]
   2123        vmla.s16        d26, d27, d0[1]
   2124        vmla.s16        d26, d30, d0[2]
   2125        vmla.s16        d26, d31, d0[3]
   2126        vrshr.s16       d16, d26, #2
   2127 
   2128        bl              L(\type\()_8tap_filter_4)
   2129        vmov            d17, d26
   2130        vmov            d18, d27
   2131        bl              L(\type\()_8tap_filter_4)
   2132        vmov            d19, d26
   2133        vmov            d20, d27
   2134        bl              L(\type\()_8tap_filter_4)
   2135        vmov            d21, d26
   2136        vmov            d22, d27
   2137 
   2138 48:
   2139        bl              L(\type\()_8tap_filter_4)
   2140        vmull.s16       q2,  d16, d2[0]
   2141        vmlal.s16       q2,  d17, d2[1]
   2142        vmlal.s16       q2,  d18, d2[2]
   2143        vmlal.s16       q2,  d19, d2[3]
   2144        vmlal.s16       q2,  d20, d3[0]
   2145        vmlal.s16       q2,  d21, d3[1]
   2146        vmlal.s16       q2,  d22, d3[2]
   2147        vmlal.s16       q2,  d26, d3[3]
   2148        vmull.s16       q3,  d17, d2[0]
   2149        vmlal.s16       q3,  d18, d2[1]
   2150        vmlal.s16       q3,  d19, d2[2]
   2151        vmlal.s16       q3,  d20, d2[3]
   2152        vmlal.s16       q3,  d21, d3[0]
   2153        vmlal.s16       q3,  d22, d3[1]
   2154        vmlal.s16       q3,  d26, d3[2]
   2155        vmlal.s16       q3,  d27, d3[3]
   2156        vqrshrn.s32     d4,  q2,  #\shift_hv
   2157        vqrshrn.s32     d6,  q3,  #\shift_hv
   2158        subs            \h,  \h,  #2
   2159 .ifc \type, put
   2160        vqmovun.s16     d4,  q2
   2161        vqmovun.s16     d6,  q3
   2162        vst1.32         {d4[0]}, [\dst, :32], \d_strd
   2163        vst1.32         {d6[0]}, [\ds2, :32], \d_strd
   2164 .else
   2165        vst1.16         {d4}, [\dst, :64], \d_strd
   2166        vst1.16         {d6}, [\ds2, :64], \d_strd
   2167 .endif
   2168        ble             0f
   2169        vmov            d16, d18
   2170        vmov            d17, d19
   2171        vmov            d18, d20
   2172        vmov            d19, d21
   2173        vmov            d20, d22
   2174        vmov            d21, d26
   2175        vmov            d22, d27
   2176        b               48b
   2177 0:
   2178        pop             {r4-r11,pc}
   2179 
   2180 L(\type\()_8tap_filter_4):
   2181        vld1.8          {d30}, [\sr2], \s_strd
   2182        vld1.8          {d31}, [\src], \s_strd
   2183        vmovl.u8        q14, d30
   2184        vext.8          d27, d28, d29, #2
   2185        vext.8          d30, d28, d29, #4
   2186        vext.8          d1,  d28, d29, #6
   2187        vmul.s16        d26, d28, d0[0]
   2188        vmla.s16        d26, d27, d0[1]
   2189        vmla.s16        d26, d30, d0[2]
   2190        vmla.s16        d26, d1,  d0[3]
   2191 
   2192        vmovl.u8        q14, d31
   2193        vext.8          d30, d28, d29, #2
   2194        vext.8          d31, d28, d29, #4
   2195        vext.8          d1,  d28, d29, #6
   2196        vmul.s16        d27, d28, d0[0]
   2197        vmla.s16        d27, d30, d0[1]
   2198        vmla.s16        d27, d31, d0[2]
   2199        vmla.s16        d27, d1,  d0[3]
   2200        vrshr.s16       d26, d26, #2
   2201        vrshr.s16       d27, d27, #2
   2202        bx              lr
   2203 
   2204 80:
   2205 160:
   2206 320:
   2207        bgt             880f
   2208        vpush           {q4-q7}
   2209        add             \my,  \my,  #2
   2210        vld1.8          {d0},  [\mx, :64]
   2211        vld1.32         {d2[]},  [\my]
   2212        sub             \src,  \src,  #3
   2213        sub             \src,  \src,  \s_strd
   2214        vmovl.s8        q0,  d0
   2215        vmovl.s8        q1,  d2
   2216        mov             \my, \h
   2217 
   2218 164:    // 8x2, 8x4, 16x2, 16x4, 32x2, 32x4 hv
   2219        add             \ds2,  \dst,  \d_strd
   2220        add             \sr2,  \src,  \s_strd
   2221        lsl             \d_strd, \d_strd, #1
   2222        lsl             \s_strd, \s_strd, #1
   2223 
   2224        vld1.8          {q14},  [\src], \s_strd
   2225        vmovl.u8        q12, d28
   2226        vmovl.u8        q13, d29
   2227        vmul.s16        q10, q12, d0[0]
   2228 .irpc i, 123
   2229        vext.8          q14, q12, q13, #(2*\i)
   2230        vmla.s16        q10, q14, d0[\i]
   2231 .endr
   2232 .irpc i, 4567
   2233        vext.8          q14, q12, q13, #(2*\i)
   2234        vmla.s16        q10, q14, d1[\i-4]
   2235 .endr
   2236        vrshr.s16       q3,  q10, #2
   2237 
   2238        bl              L(\type\()_8tap_filter_8)
   2239        vmov            q4,  q10
   2240        vmov            q5,  q11
   2241 
   2242 8:
   2243        bl              L(\type\()_8tap_filter_8)
   2244        vmull.s16       q12, d6,  d2[0]
   2245        vmull.s16       q13, d7,  d2[0]
   2246        vmull.s16       q14, d8,  d2[0]
   2247        vmull.s16       q15, d9,  d2[0]
   2248        vmlal.s16       q12, d8,  d2[1]
   2249        vmlal.s16       q13, d9,  d2[1]
   2250        vmlal.s16       q14, d10, d2[1]
   2251        vmlal.s16       q15, d11, d2[1]
   2252        vmlal.s16       q12, d10, d2[2]
   2253        vmlal.s16       q13, d11, d2[2]
   2254        vmlal.s16       q14, d20, d2[2]
   2255        vmlal.s16       q15, d21, d2[2]
   2256        vmlal.s16       q12, d20, d2[3]
   2257        vmlal.s16       q13, d21, d2[3]
   2258        vmlal.s16       q14, d22, d2[3]
   2259        vmlal.s16       q15, d23, d2[3]
   2260        vqrshrn.s32     d24, q12, #\shift_hv
   2261        vqrshrn.s32     d25, q13, #\shift_hv
   2262        vqrshrn.s32     d28, q14, #\shift_hv
   2263        vqrshrn.s32     d29, q15, #\shift_hv
   2264        subs            \h,  \h,  #2
   2265 .ifc \type, put
   2266        vqmovun.s16     d24, q12
   2267        vqmovun.s16     d28, q14
   2268        vst1.8          {d24}, [\dst, :64], \d_strd
   2269        vst1.8          {d28}, [\ds2, :64], \d_strd
   2270 .else
   2271        vst1.16         {q12}, [\dst, :128], \d_strd
   2272        vst1.16         {q14}, [\ds2, :128], \d_strd
   2273 .endif
   2274        ble             9f
   2275        vmov            q3,  q5
   2276        vmov            q4,  q10
   2277        vmov            q5,  q11
   2278        b               8b
   2279 9:
   2280        subs            \w,  \w,  #8
   2281        ble             0f
   2282        asr             \s_strd,  \s_strd,  #1
   2283        asr             \d_strd,  \d_strd,  #1
   2284        mls             \src,  \s_strd,  \my,  \src
   2285        mls             \dst,  \d_strd,  \my,  \dst
   2286        sub             \src,  \src,  \s_strd,  lsl #2
   2287        mov             \h,  \my
   2288        add             \src,  \src,  #8
   2289 .ifc \type, put
   2290        add             \dst,  \dst,  #8
   2291 .else
   2292        add             \dst,  \dst,  #16
   2293 .endif
   2294        b               164b
   2295 
   2296 880:    // 8x8, 8x16, ..., 16x8, ..., 32x8, ... hv
   2297 640:
   2298 1280:
   2299        vpush           {q4-q7}
   2300        vld1.8          {d0},  [\mx, :64]
   2301        vld1.8          {d2},  [\my, :64]
   2302        sub             \src,  \src,  #3
   2303        sub             \src,  \src,  \s_strd
   2304        sub             \src,  \src,  \s_strd, lsl #1
   2305        vmovl.s8        q0,  d0
   2306        vmovl.s8        q1,  d2
   2307        mov             \my, \h
   2308 
   2309 168:
   2310        add             \ds2,  \dst,  \d_strd
   2311        add             \sr2,  \src,  \s_strd
   2312        lsl             \d_strd, \d_strd, #1
   2313        lsl             \s_strd, \s_strd, #1
   2314 
   2315        vld1.8          {q14},  [\src], \s_strd
   2316        vmovl.u8        q12, d28
   2317        vmovl.u8        q13, d29
   2318        vmul.s16        q10, q12, d0[0]
   2319 .irpc i, 123
   2320        vext.8          q14, q12, q13, #(2*\i)
   2321        vmla.s16        q10, q14, d0[\i]
   2322 .endr
   2323 .irpc i, 4567
   2324        vext.8          q14, q12, q13, #(2*\i)
   2325        vmla.s16        q10, q14, d1[\i-4]
   2326 .endr
   2327        vrshr.s16       q3,  q10, #2
   2328 
   2329        bl              L(\type\()_8tap_filter_8)
   2330        vmov            q4,  q10
   2331        vmov            q5,  q11
   2332        bl              L(\type\()_8tap_filter_8)
   2333        vmov            q6,  q10
   2334        vmov            q7,  q11
   2335        bl              L(\type\()_8tap_filter_8)
   2336        vmov            q8,  q10
   2337        vmov            q9,  q11
   2338 
   2339 88:
   2340        bl              L(\type\()_8tap_filter_8)
   2341        vmull.s16       q12, d6,  d2[0]
   2342        vmull.s16       q13, d7,  d2[0]
   2343        vmull.s16       q14, d8,  d2[0]
   2344        vmull.s16       q15, d9,  d2[0]
   2345        vmlal.s16       q12, d8,  d2[1]
   2346        vmlal.s16       q13, d9,  d2[1]
   2347        vmlal.s16       q14, d10, d2[1]
   2348        vmlal.s16       q15, d11, d2[1]
   2349        vmlal.s16       q12, d10, d2[2]
   2350        vmlal.s16       q13, d11, d2[2]
   2351        vmlal.s16       q14, d12, d2[2]
   2352        vmlal.s16       q15, d13, d2[2]
   2353        vmlal.s16       q12, d12, d2[3]
   2354        vmlal.s16       q13, d13, d2[3]
   2355        vmlal.s16       q14, d14, d2[3]
   2356        vmlal.s16       q15, d15, d2[3]
   2357        vmlal.s16       q12, d14, d3[0]
   2358        vmlal.s16       q13, d15, d3[0]
   2359        vmlal.s16       q14, d16, d3[0]
   2360        vmlal.s16       q15, d17, d3[0]
   2361        vmlal.s16       q12, d16, d3[1]
   2362        vmlal.s16       q13, d17, d3[1]
   2363        vmlal.s16       q14, d18, d3[1]
   2364        vmlal.s16       q15, d19, d3[1]
   2365        vmlal.s16       q12, d18, d3[2]
   2366        vmlal.s16       q13, d19, d3[2]
   2367        vmlal.s16       q14, d20, d3[2]
   2368        vmlal.s16       q15, d21, d3[2]
   2369        vmlal.s16       q12, d20, d3[3]
   2370        vmlal.s16       q13, d21, d3[3]
   2371        vmlal.s16       q14, d22, d3[3]
   2372        vmlal.s16       q15, d23, d3[3]
   2373        vqrshrn.s32     d24, q12, #\shift_hv
   2374        vqrshrn.s32     d25, q13, #\shift_hv
   2375        vqrshrn.s32     d28, q14, #\shift_hv
   2376        vqrshrn.s32     d29, q15, #\shift_hv
   2377        subs            \h,  \h,  #2
   2378 .ifc \type, put
   2379        vqmovun.s16     d24, q12
   2380        vqmovun.s16     d28, q14
   2381        vst1.8          {d24}, [\dst, :64], \d_strd
   2382        vst1.8          {d28}, [\ds2, :64], \d_strd
   2383 .else
   2384        vst1.16         {q12}, [\dst, :128], \d_strd
   2385        vst1.16         {q14}, [\ds2, :128], \d_strd
   2386 .endif
   2387        ble             9f
   2388        vmov            q3,  q5
   2389        vmov            q4,  q6
   2390        vmov            q5,  q7
   2391        vmov            q6,  q8
   2392        vmov            q7,  q9
   2393        vmov            q8,  q10
   2394        vmov            q9,  q11
   2395        b               88b
   2396 9:
   2397        subs            \w,  \w,  #8
   2398        ble             0f
   2399        asr             \s_strd,  \s_strd,  #1
   2400        asr             \d_strd,  \d_strd,  #1
   2401        mls             \src,  \s_strd,  \my,  \src
   2402        mls             \dst,  \d_strd,  \my,  \dst
   2403        sub             \src,  \src,  \s_strd,  lsl #3
   2404        mov             \h,  \my
   2405        add             \src,  \src,  #8
   2406 .ifc \type, put
   2407        add             \dst,  \dst,  #8
   2408 .else
   2409        add             \dst,  \dst,  #16
   2410 .endif
   2411        b               168b
   2412 0:
   2413        vpop            {q4-q7}
   2414        pop             {r4-r11,pc}
   2415 
   2416 L(\type\()_8tap_filter_8):
   2417        vld1.8          {q14},  [\sr2], \s_strd
   2418        vld1.8          {q15},  [\src], \s_strd
   2419        vmovl.u8        q12, d28
   2420        vmovl.u8        q13, d29
   2421        vmul.s16        q10, q12, d0[0]
   2422 .irpc i, 123
   2423        vext.8          q14, q12, q13, #(2*\i)
   2424        vmla.s16        q10, q14, d0[\i]
   2425 .endr
   2426 .irpc i, 4567
   2427        vext.8          q14, q12, q13, #(2*\i)
   2428        vmla.s16        q10, q14, d1[\i-4]
   2429 .endr
   2430        vmovl.u8        q12, d30
   2431        vmovl.u8        q13, d31
   2432        vmul.s16        q11, q12, d0[0]
   2433 .irpc i, 123
   2434        vext.8          q14, q12, q13, #(2*\i)
   2435        vmla.s16        q11, q14, d0[\i]
   2436 .endr
   2437 .irpc i, 4567
   2438        vext.8          q14, q12, q13, #(2*\i)
   2439        vmla.s16        q11, q14, d1[\i-4]
   2440 .endr
   2441        vrshr.s16       q10, q10, #2
   2442        vrshr.s16       q11, q11, #2
   2443        bx              lr
   2444 endfunc
   2445 
   2446 
   2447 function \type\()_bilin_8bpc_neon, export=1
   2448        push            {r4-r11,lr}
   2449        ldrd            r4,  r5,  [sp, #36]
   2450        ldrd            r6,  r7,  [sp, #44]
   2451        vdup.8          d1,  \mx
   2452        vdup.8          d3,  \my
   2453        rsb             r8,  \mx, #16
   2454        rsb             r9,  \my, #16
   2455        vdup.8          d0,  r8
   2456        vdup.8          d2,  r9
   2457 .ifc \type, prep
   2458        lsl             \d_strd, \w, #1
   2459 .endif
   2460        clz             r8,  \w
   2461        cmp             \mx, #0
   2462        sub             r8,  r8,  #24
   2463        bne             L(\type\()_bilin_h)
   2464        cmp             \my, #0
   2465        bne             L(\type\()_bilin_v)
   2466        b               \type\()_neon
   2467 
   2468 L(\type\()_bilin_h):
   2469        cmp             \my, #0
   2470        bne             L(\type\()_bilin_hv)
   2471 
   2472        adr             r9,  L(\type\()_bilin_h_tbl)
   2473        ldr             r8,  [r9, r8, lsl #2]
   2474        add             r9,  r9,  r8
   2475        bx              r9
   2476 
   2477        .align 2
   2478 L(\type\()_bilin_h_tbl):
   2479        .word 1280f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
   2480        .word 640f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
   2481        .word 320f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
   2482        .word 160f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
   2483        .word 80f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
   2484        .word 40f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
   2485        .word 20f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
   2486 
   2487 20:     // 2xN h
   2488 .ifc \type, put
   2489        add             \ds2,  \dst,  \d_strd
   2490        add             \sr2,  \src,  \s_strd
   2491        lsl             \d_strd,  \d_strd,  #1
   2492        lsl             \s_strd,  \s_strd,  #1
   2493 2:
   2494        vld1.32         {d4[]},  [\src], \s_strd
   2495        vld1.32         {d6[]},  [\sr2], \s_strd
   2496        vext.8          d5,  d4,  d4, #1
   2497        vext.8          d7,  d6,  d6, #1
   2498        vtrn.16         q2,  q3
   2499        subs            \h,  \h,  #2
   2500        vmull.u8        q3,  d4,  d0
   2501        vmlal.u8        q3,  d5,  d1
   2502        vqrshrn.u16     d4,  q3,  #4
   2503        vst1.16         {d4[0]}, [\dst, :16], \d_strd
   2504        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
   2505        bgt             2b
   2506        pop             {r4-r11,pc}
   2507 .endif
   2508 
   2509 40:     // 4xN h
   2510        add             \ds2,  \dst,  \d_strd
   2511        add             \sr2,  \src,  \s_strd
   2512        lsl             \d_strd,  \d_strd,  #1
   2513        lsl             \s_strd,  \s_strd,  #1
   2514 4:
   2515        vld1.8          {d4}, [\src], \s_strd
   2516        vld1.8          {d6}, [\sr2], \s_strd
   2517        vext.8          d5,  d4,  d4, #1
   2518        vext.8          d7,  d6,  d6, #1
   2519        vtrn.32         q2,  q3
   2520        subs            \h,  \h,  #2
   2521        vmull.u8        q3,  d4,  d0
   2522        vmlal.u8        q3,  d5,  d1
   2523 .ifc \type, put
   2524        vqrshrn.u16     d4,  q3,  #4
   2525        vst1.32         {d4[0]}, [\dst, :32], \d_strd
   2526        vst1.32         {d4[1]}, [\ds2, :32], \d_strd
   2527 .else
   2528        vst1.16         {d6}, [\dst, :64], \d_strd
   2529        vst1.16         {d7}, [\ds2, :64], \d_strd
   2530 .endif
   2531        bgt             4b
   2532        pop             {r4-r11,pc}
   2533 
   2534 80:     // 8xN h
   2535        add             \ds2,  \dst,  \d_strd
   2536        add             \sr2,  \src,  \s_strd
   2537        lsl             \d_strd,  \d_strd,  #1
   2538        lsl             \s_strd,  \s_strd,  #1
   2539 8:
   2540        vld1.8          {q8},  [\src], \s_strd
   2541        vld1.8          {q10}, [\sr2], \s_strd
   2542        vext.8          q9,  q8,  q8,  #1
   2543        vext.8          q11, q10, q10, #1
   2544        subs            \h,  \h,  #2
   2545        vmull.u8        q8,  d16, d0
   2546        vmull.u8        q10, d20, d0
   2547        vmlal.u8        q8,  d18, d1
   2548        vmlal.u8        q10, d22, d1
   2549 .ifc \type, put
   2550        vqrshrn.u16     d16,  q8,  #4
   2551        vqrshrn.u16     d18,  q10, #4
   2552        vst1.8          {d16}, [\dst, :64], \d_strd
   2553        vst1.8          {d18}, [\ds2, :64], \d_strd
   2554 .else
   2555        vst1.16         {q8},  [\dst, :128], \d_strd
   2556        vst1.16         {q10}, [\ds2, :128], \d_strd
   2557 .endif
   2558        bgt             8b
   2559        pop             {r4-r11,pc}
   2560 160:
   2561 320:
   2562 640:
   2563 1280:   // 16xN, 32xN, ... h
   2564        add             \ds2,  \dst,  \d_strd
   2565        add             \sr2,  \src,  \s_strd
   2566        lsl             \s_strd,  \s_strd,  #1
   2567 
   2568        sub             \s_strd,  \s_strd,  \w
   2569        sub             \s_strd,  \s_strd,  #8
   2570 .ifc \type, put
   2571        lsl             \d_strd,  \d_strd,  #1
   2572        sub             \d_strd,  \d_strd,  \w
   2573 .endif
   2574 161:
   2575        vld1.8          {d16},  [\src]!
   2576        vld1.8          {d22},  [\sr2]!
   2577        mov             \mx, \w
   2578 
   2579 16:
   2580        vld1.8          {d17,d18},  [\src]!
   2581        vld1.8          {d23,d24},  [\sr2]!
   2582        vext.8          q10, q8,  q9,  #1
   2583        vext.8          q13, q11, q12, #1
   2584        vmull.u8        q2,  d16, d0
   2585        vmull.u8        q3,  d17, d0
   2586        vmull.u8        q14, d22, d0
   2587        vmull.u8        q15, d23, d0
   2588        vmlal.u8        q2,  d20, d1
   2589        vmlal.u8        q3,  d21, d1
   2590        vmlal.u8        q14, d26, d1
   2591        vmlal.u8        q15, d27, d1
   2592        subs            \mx, \mx, #16
   2593 .ifc \type, put
   2594        vqrshrn.u16     d4,  q2,  #4
   2595        vqrshrn.u16     d5,  q3,  #4
   2596        vqrshrn.u16     d28, q14, #4
   2597        vqrshrn.u16     d29, q15, #4
   2598        vst1.8          {q2},  [\dst, :128]!
   2599        vst1.8          {q14}, [\ds2, :128]!
   2600 .else
   2601        vst1.16         {q2,  q3},  [\dst, :128]!
   2602        vst1.16         {q14, q15}, [\ds2, :128]!
   2603 .endif
   2604        ble             9f
   2605 
   2606        vmov            d16, d18
   2607        vmov            d22, d24
   2608        b               16b
   2609 
   2610 9:
   2611        add             \dst,  \dst,  \d_strd
   2612        add             \ds2,  \ds2,  \d_strd
   2613        add             \src,  \src,  \s_strd
   2614        add             \sr2,  \sr2,  \s_strd
   2615 
   2616        subs            \h,  \h,  #2
   2617        bgt             161b
   2618        pop             {r4-r11,pc}
   2619 
   2620 L(\type\()_bilin_v):
   2621        cmp             \h,  #4
   2622        adr             r9,  L(\type\()_bilin_v_tbl)
   2623        ldr             r8,  [r9, r8, lsl #2]
   2624        add             r9,  r9,  r8
   2625        bx              r9
   2626 
   2627        .align 2
   2628 L(\type\()_bilin_v_tbl):
   2629        .word 1280f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
   2630        .word 640f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
   2631        .word 320f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
   2632        .word 160f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
   2633        .word 80f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
   2634        .word 40f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
   2635        .word 20f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
   2636 
   2637 20:     // 2xN v
   2638 .ifc \type, put
   2639        cmp             \h,  #2
   2640        add             \ds2,  \dst,  \d_strd
   2641        add             \sr2,  \src,  \s_strd
   2642        lsl             \s_strd,  \s_strd,  #1
   2643        lsl             \d_strd,  \d_strd,  #1
   2644 
   2645        // 2x2 v
   2646        vld1.16         {d16[]}, [\src], \s_strd
   2647        bgt             24f
   2648 22:
   2649        vld1.16         {d17[]}, [\sr2], \s_strd
   2650        vld1.16         {d18[]}, [\src], \s_strd
   2651        vext.8          d16, d16, d17, #6
   2652        vext.8          d17, d17, d18, #6
   2653        vmull.u8        q2,  d16, d2
   2654        vmlal.u8        q2,  d17, d3
   2655        vqrshrn.u16     d4,  q2,  #4
   2656        vst1.16         {d4[0]}, [\dst, :16]
   2657        vst1.16         {d4[1]}, [\ds2, :16]
   2658        pop             {r4-r11,pc}
   2659 24:     // 2x4, 2x6, 2x8, ... v
   2660        vld1.16         {d17[]}, [\sr2], \s_strd
   2661        vld1.16         {d18[]}, [\src], \s_strd
   2662        vld1.16         {d19[]}, [\sr2], \s_strd
   2663        vld1.16         {d20[]}, [\src], \s_strd
   2664        sub             \h,  \h,  #4
   2665        vext.8          d16, d16, d17, #6
   2666        vext.8          d17, d17, d18, #6
   2667        vext.8          d18, d18, d19, #6
   2668        vext.8          d19, d19, d20, #6
   2669        vtrn.32         d16, d18
   2670        vtrn.32         d17, d19
   2671        vmull.u8        q2,  d16, d2
   2672        vmlal.u8        q2,  d17, d3
   2673        cmp             \h,  #2
   2674        vqrshrn.u16     d4,  q2,  #4
   2675        vst1.16         {d4[0]}, [\dst, :16], \d_strd
   2676        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
   2677        vst1.16         {d4[2]}, [\dst, :16], \d_strd
   2678        vst1.16         {d4[3]}, [\ds2, :16], \d_strd
   2679        blt             0f
   2680        vmov            d16, d20
   2681        beq             22b
   2682        b               24b
   2683 0:
   2684        pop             {r4-r11,pc}
   2685 .endif
   2686 
   2687 40:     // 4xN v
   2688        add             \ds2,  \dst,  \d_strd
   2689        add             \sr2,  \src,  \s_strd
   2690        lsl             \s_strd,  \s_strd,  #1
   2691        lsl             \d_strd,  \d_strd,  #1
   2692        vld1.32         {d16[]}, [\src], \s_strd
   2693 4:
   2694        vld1.32         {d17[]}, [\sr2], \s_strd
   2695        vld1.32         {d18[]}, [\src], \s_strd
   2696        vext.8          d16, d16, d17, #4
   2697        vext.8          d17, d17, d18, #4
   2698        vmull.u8        q2,  d16, d2
   2699        vmlal.u8        q2,  d17, d3
   2700        subs            \h,  \h,  #2
   2701 .ifc \type, put
   2702        vqrshrn.u16     d4,  q2,  #4
   2703        vst1.32         {d4[0]}, [\dst, :32], \d_strd
   2704        vst1.32         {d4[1]}, [\ds2, :32], \d_strd
   2705 .else
   2706        vst1.16         {d4}, [\dst, :64], \d_strd
   2707        vst1.16         {d5}, [\ds2, :64], \d_strd
   2708 .endif
   2709        ble             0f
   2710        vmov            d16,  d18
   2711        b               4b
   2712 0:
   2713        pop             {r4-r11,pc}
   2714 
   2715 80:     // 8xN v
   2716        add             \ds2,  \dst,  \d_strd
   2717        add             \sr2,  \src,  \s_strd
   2718        lsl             \s_strd,  \s_strd,  #1
   2719        lsl             \d_strd,  \d_strd,  #1
   2720        vld1.8          {d16}, [\src], \s_strd
   2721 8:
   2722        vld1.8          {d17}, [\sr2], \s_strd
   2723        vld1.8          {d18}, [\src], \s_strd
   2724        vmull.u8        q2,  d16, d2
   2725        vmull.u8        q3,  d17, d2
   2726        vmlal.u8        q2,  d17, d3
   2727        vmlal.u8        q3,  d18, d3
   2728        subs            \h,  \h,  #2
   2729 .ifc \type, put
   2730        vqrshrn.u16     d4,  q2,  #4
   2731        vqrshrn.u16     d6,  q3,  #4
   2732        vst1.8          {d4}, [\dst, :64], \d_strd
   2733        vst1.8          {d6}, [\ds2, :64], \d_strd
   2734 .else
   2735        vst1.16         {q2}, [\dst, :128], \d_strd
   2736        vst1.16         {q3}, [\ds2, :128], \d_strd
   2737 .endif
   2738        ble             0f
   2739        vmov            d16, d18
   2740        b               8b
   2741 0:
   2742        pop             {r4-r11,pc}
   2743 
   2744 160:    // 16xN, 32xN, ...
   2745 320:
   2746 640:
   2747 1280:
   2748        mov             \my, \h
   2749 1:
   2750        add             \ds2, \dst, \d_strd
   2751        add             \sr2, \src, \s_strd
   2752        lsl             \s_strd, \s_strd, #1
   2753        lsl             \d_strd, \d_strd, #1
   2754 
   2755        vld1.8          {q8},  [\src], \s_strd
   2756 2:
   2757        vld1.8          {q9},  [\sr2], \s_strd
   2758        vld1.8          {q10}, [\src], \s_strd
   2759        vmull.u8        q12, d16, d2
   2760        vmull.u8        q13, d17, d2
   2761        vmull.u8        q14, d18, d2
   2762        vmull.u8        q15, d19, d2
   2763        vmlal.u8        q12, d18, d3
   2764        vmlal.u8        q13, d19, d3
   2765        vmlal.u8        q14, d20, d3
   2766        vmlal.u8        q15, d21, d3
   2767        subs            \h,  \h,  #2
   2768 .ifc \type, put
   2769        vqrshrn.u16     d24, q12, #4
   2770        vqrshrn.u16     d25, q13, #4
   2771        vqrshrn.u16     d28, q14, #4
   2772        vqrshrn.u16     d29, q15, #4
   2773        vst1.8          {q12}, [\dst, :128], \d_strd
   2774        vst1.8          {q14}, [\ds2, :128], \d_strd
   2775 .else
   2776        vst1.16         {q12, q13}, [\dst, :128], \d_strd
   2777        vst1.16         {q14, q15}, [\ds2, :128], \d_strd
   2778 .endif
   2779        ble             9f
   2780        vmov            q8,  q10
   2781        b               2b
   2782 9:
   2783        subs            \w,  \w,  #16
   2784        ble             0f
   2785        asr             \s_strd, \s_strd, #1
   2786        asr             \d_strd, \d_strd, #1
   2787        mls             \src, \s_strd, \my, \src
   2788        mls             \dst, \d_strd, \my, \dst
   2789        sub             \src, \src, \s_strd, lsl #1
   2790        mov             \h,  \my
   2791        add             \src, \src, #16
   2792 .ifc \type, put
   2793        add             \dst, \dst, #16
   2794 .else
   2795        add             \dst, \dst, #32
   2796 .endif
   2797        b               1b
   2798 0:
   2799        pop             {r4-r11,pc}
   2800 
   2801 L(\type\()_bilin_hv):
   2802        vmovl.u8        q2,  d2
   2803        vmovl.u8        q3,  d3
   2804        adr             r9,  L(\type\()_bilin_hv_tbl)
   2805        ldr             r8,  [r9, r8, lsl #2]
   2806        add             r9,  r9,  r8
   2807        bx              r9
   2808 
   2809        .align 2
   2810 L(\type\()_bilin_hv_tbl):
   2811        .word 1280f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
   2812        .word 640f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
   2813        .word 320f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
   2814        .word 160f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
   2815        .word 80f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
   2816        .word 40f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
   2817        .word 20f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
   2818 
   2819 20:     // 2xN hv
   2820 .ifc \type, put
   2821        add             \sr2, \src, \s_strd
   2822        add             \ds2, \dst, \d_strd
   2823        lsl             \s_strd, \s_strd, #1
   2824        lsl             \d_strd, \d_strd, #1
   2825 
   2826        vld1.32         {d28[]},  [\src], \s_strd
   2827        vext.8          d29, d28, d28, #1
   2828        vmull.u8        q8,  d28, d0
   2829        vmlal.u8        q8,  d29, d1
   2830 
   2831 2:
   2832        vld1.32         {d28[]},  [\sr2], \s_strd
   2833        vld1.32         {d30[]},  [\src], \s_strd
   2834        vext.8          d29, d28, d28, #1
   2835        vext.8          d31, d30, d30, #1
   2836        vtrn.16         d28, d30
   2837        vtrn.16         d29, d31
   2838        vmull.u8        q9,  d28, d0
   2839        vmlal.u8        q9,  d29, d1
   2840 
   2841        vtrn.32         d16, d18
   2842 
   2843        vmul.u16        d20, d16, d4
   2844        vmla.u16        d20, d19, d6
   2845        vqrshrn.u16     d20, q10, #8
   2846        subs            \h,  \h,  #2
   2847        vst1.16         {d20[0]}, [\dst, :16], \d_strd
   2848        vst1.16         {d20[1]}, [\ds2, :16], \d_strd
   2849        ble             0f
   2850        vtrn.32         d19, d16
   2851        b               2b
   2852 0:
   2853        pop             {r4-r11,pc}
   2854 .endif
   2855 
   2856 40:     // 4xN hv
   2857        add             \sr2, \src, \s_strd
   2858        add             \ds2, \dst, \d_strd
   2859        lsl             \s_strd, \s_strd, #1
   2860        lsl             \d_strd, \d_strd, #1
   2861 
   2862        vld1.8          {d28},  [\src], \s_strd
   2863        vext.8          d29, d28, d28, #1
   2864        vmull.u8        q8,  d28, d0
   2865        vmlal.u8        q8,  d29, d1
   2866 
   2867 4:
   2868        vld1.8          {d28},  [\sr2], \s_strd
   2869        vld1.8          {d30},  [\src], \s_strd
   2870        vext.8          d29, d28, d28, #1
   2871        vext.8          d31, d30, d30, #1
   2872        vtrn.32         d28, d30
   2873        vtrn.32         d29, d31
   2874        vmull.u8        q9,  d28, d0
   2875        vmlal.u8        q9,  d29, d1
   2876 
   2877        vmov            d17, d18
   2878 
   2879        vmul.u16        q10, q8, q2
   2880        vmla.u16        q10, q9, q3
   2881        subs            \h,  \h,  #2
   2882 .ifc \type, put
   2883        vqrshrn.u16     d20, q10, #8
   2884        vst1.32         {d20[0]}, [\dst, :32], \d_strd
   2885        vst1.32         {d20[1]}, [\ds2, :32], \d_strd
   2886 .else
   2887        vrshr.u16       q10, q10, #4
   2888        vst1.16         {d20}, [\dst, :64], \d_strd
   2889        vst1.16         {d21}, [\ds2, :64], \d_strd
   2890 .endif
   2891        ble             0f
   2892        vmov            d16, d19
   2893        b               4b
   2894 0:
   2895        pop             {r4-r11,pc}
   2896 
   2897 80:     // 8xN, 16xN, ... hv
   2898 160:
   2899 320:
   2900 640:
   2901 1280:
   2902        mov             \my, \h
   2903 
   2904 1:
   2905        add             \sr2, \src, \s_strd
   2906        add             \ds2, \dst, \d_strd
   2907        lsl             \s_strd, \s_strd, #1
   2908        lsl             \d_strd, \d_strd, #1
   2909 
   2910        vld1.8          {q12},  [\src], \s_strd
   2911        vext.8          q13, q12, q12, #1
   2912        vmull.u8        q8,  d24, d0
   2913        vmlal.u8        q8,  d26, d1
   2914 
   2915 2:
   2916        vld1.8          {q12},  [\sr2], \s_strd
   2917        vld1.8          {q14},  [\src], \s_strd
   2918        vext.8          q13, q12, q12, #1
   2919        vext.8          q15, q14, q14, #1
   2920        vmull.u8        q9,  d24, d0
   2921        vmlal.u8        q9,  d26, d1
   2922        vmull.u8        q10, d28, d0
   2923        vmlal.u8        q10, d30, d1
   2924 
   2925        vmul.u16        q8,  q8,  q2
   2926        vmla.u16        q8,  q9,  q3
   2927        vmul.u16        q9,  q9,  q2
   2928        vmla.u16        q9,  q10, q3
   2929        subs            \h,  \h,  #2
   2930 .ifc \type, put
   2931        vqrshrn.u16     d16, q8,  #8
   2932        vqrshrn.u16     d18, q9,  #8
   2933        vst1.8          {d16}, [\dst, :64], \d_strd
   2934        vst1.8          {d18}, [\ds2, :64], \d_strd
   2935 .else
   2936        vrshr.u16       q8,  q8,  #4
   2937        vrshr.u16       q9,  q9,  #4
   2938        vst1.16         {q8}, [\dst, :128], \d_strd
   2939        vst1.16         {q9}, [\ds2, :128], \d_strd
   2940 .endif
   2941        ble             9f
   2942        vmov            q8,  q10
   2943        b               2b
   2944 9:
   2945        subs            \w,  \w,  #8
   2946        ble             0f
   2947        asr             \s_strd,  \s_strd,  #1
   2948        asr             \d_strd,  \d_strd,  #1
   2949        mls             \src,  \s_strd,  \my,  \src
   2950        mls             \dst,  \d_strd,  \my,  \dst
   2951        sub             \src,  \src,  \s_strd,  lsl #1
   2952        mov             \h,  \my
   2953        add             \src,  \src,  #8
   2954 .ifc \type, put
   2955        add             \dst,  \dst,  #8
   2956 .else
   2957        add             \dst,  \dst,  #16
   2958 .endif
   2959        b               1b
   2960 0:
   2961        pop             {r4-r11,pc}
   2962 endfunc
   2963 .endm
   2964 
   2965 filter_fn put,  r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, 10
   2966 filter_fn prep, r0, r7, r1, r2, r3, r4, r5, r6, r8, r9, 6
   2967 
   2968 .macro load_filter_ptr src
   2969        asr             r12, \src, #10
   2970        add             r12, r11, r12, lsl #3
   2971 .endm
   2972 
   2973 .macro load_filter_coef dst, src, inc
   2974        add             \src, \src, \inc
   2975        vld1.8          {\dst}, [r12, :64]
   2976 .endm
   2977 
   2978 .macro load_filter_row dst, src, inc
   2979        load_filter_ptr \src
   2980        load_filter_coef \dst, \src, \inc
   2981 .endm
   2982 
   2983 function warp_filter_horz_neon
   2984        load_filter_ptr r5                  // filter 0
   2985        vld1.16         {q7}, [r2], r3
   2986        vmov.i8         q6,  #128
   2987 
   2988        load_filter_coef d0, r5,  r7        // filter 0
   2989        load_filter_row d1,  r5,  r7        // filter 1
   2990        load_filter_row d2,  r5,  r7        // filter 2
   2991        load_filter_ptr r5                  // filter 3
   2992        veor            q7,  q7,  q6        // subtract by 128 to allow using vmull
   2993        load_filter_coef d3, r5,  r7        // filter 3
   2994        vext.8          d12, d14, d15, #1   // filter 1 pixels
   2995        vext.8          d13, d14, d15, #2   // filter 2 pixels
   2996        load_filter_ptr r5                  // filter 4
   2997        vmull.s8        q2,  d14, d0        // filter 0 output
   2998        vmull.s8        q3,  d12, d1        // filter 1 output
   2999        load_filter_coef d0, r5,  r7        // filter 4
   3000        load_filter_ptr r5                  // filter 5
   3001        vext.8          d12, d14, d15, #3   // filter 3 pixels
   3002        vmull.s8        q4,  d13, d2        // filter 2 output
   3003        vext.8          d13, d14, d15, #4   // filter 4 pixels
   3004        vpadd.i16       d4,  d4,  d5        // pixel 0 (4x16)
   3005        vpadd.i16       d5,  d6,  d7        // pixel 1 (4x16)
   3006        load_filter_coef d1, r5,  r7        // filter 5
   3007        load_filter_ptr r5                  // filter 6
   3008        vmull.s8        q5,  d12, d3        // filter 3 output
   3009        vext.8          d12, d14, d15, #5   // filter 5 pixels
   3010        vmull.s8        q3,  d13, d0        // filter 4 output
   3011        load_filter_coef d0, r5,  r7        // filter 6
   3012        vext.8          d13, d14, d15, #6   // filter 6 pixels
   3013        load_filter_ptr r5                  // filter 7
   3014        vpadd.i16       d8,  d8,  d9        // pixel 2 (4x16)
   3015        vpadd.i16       d9,  d10, d11       // pixel 3 (4x16)
   3016        vmull.s8        q5,  d12, d1        // filter 5 output
   3017        load_filter_coef d1, r5,  r7        // filter 7
   3018        vext.8          d14, d14, d15, #7   // filter 7 pixels
   3019        vpadd.i16       d6,  d6,  d7        // pixel 4 (4x16)
   3020        vpadd.i16       d10, d10, d11       // pixel 5 (4x16)
   3021        vmull.s8        q6,  d13, d0        // filter 6 output
   3022        vmull.s8        q7,  d14, d1        // filter 7 output
   3023 
   3024        sub             r5,  r5,  r7, lsl #3
   3025 
   3026        vpadd.i16       d4,  d4,  d5        // pixel 0,1 (2x16)
   3027        vpadd.i16       d5,  d8,  d9        // pixel 2,3 (2x16)
   3028        vpadd.i16       d12, d12, d13       // pixel 6 (4x16)
   3029        vpadd.i16       d14, d14, d15       // pixel 7 (4x16)
   3030        vpadd.i16       d6,  d6,  d10       // pixel 4,5 (2x16)
   3031        vpadd.i16       d10, d12, d14       // pixel 6,7 (2x16)
   3032        vpadd.i16       d4,  d4,  d5        // pixel 0-3
   3033        vpadd.i16       d5,  d6,  d10       // pixel 4-7
   3034 
   3035        add             r5,  r5,  r8
   3036 
   3037        bx              lr
   3038 endfunc
   3039 
   3040 // void dav1d_warp_affine_8x8_8bpc_neon(
   3041 //         pixel *dst, const ptrdiff_t dst_stride,
   3042 //         const pixel *src, const ptrdiff_t src_stride,
   3043 //         const int16_t *const abcd, int mx, int my)
   3044 .macro warp t, shift
   3045 function warp_affine_8x8\t\()_8bpc_neon, export=1
   3046        push            {r4-r11,lr}
   3047        vpush           {q4-q7}
   3048        ldrd            r4,  r5,  [sp, #100]
   3049        ldr             r6,  [sp, #108]
   3050        ldrd            r8,  r9,  [r4]
   3051        sxth            r7,  r8
   3052        asr             r8,  r8, #16
   3053        asr             r4,  r9, #16
   3054        sxth            r9,  r9
   3055        mov             r10, #8
   3056        sub             r2,  r2,  r3, lsl #1
   3057        sub             r2,  r2,  r3
   3058        sub             r2,  r2,  #3
   3059        movrel          r11, X(mc_warp_filter), 64*8
   3060 .ifnb \t
   3061        lsl             r1,  r1,  #1
   3062 .endif
   3063        add             r5,  r5,  #512
   3064        add             r6,  r6,  #512
   3065 
   3066        bl              warp_filter_horz_neon
   3067        vrshr.s16       q8,  q2,  #3
   3068        bl              warp_filter_horz_neon
   3069        vrshr.s16       q9,  q2,  #3
   3070        bl              warp_filter_horz_neon
   3071        vrshr.s16       q10, q2,  #3
   3072        bl              warp_filter_horz_neon
   3073        vrshr.s16       q11, q2,  #3
   3074        bl              warp_filter_horz_neon
   3075        vrshr.s16       q12, q2,  #3
   3076        bl              warp_filter_horz_neon
   3077        vrshr.s16       q13, q2,  #3
   3078        bl              warp_filter_horz_neon
   3079        vrshr.s16       q14, q2,  #3
   3080 
   3081 1:
   3082        bl              warp_filter_horz_neon
   3083        vrshr.s16       q15, q2,  #3
   3084 
   3085        load_filter_row d8,  r6,  r9
   3086        load_filter_row d9,  r6,  r9
   3087        load_filter_row d10, r6,  r9
   3088        load_filter_row d11, r6,  r9
   3089        load_filter_row d12, r6,  r9
   3090        load_filter_row d13, r6,  r9
   3091        load_filter_row d14, r6,  r9
   3092        load_filter_row d15, r6,  r9
   3093        transpose_8x8b  q4,  q5,  q6,  q7,  d8,  d9,  d10, d11, d12, d13, d14, d15
   3094        vmovl.s8        q1,  d8
   3095        vmovl.s8        q2,  d9
   3096        vmovl.s8        q3,  d10
   3097        vmovl.s8        q4,  d11
   3098        vmovl.s8        q5,  d12
   3099        vmovl.s8        q6,  d13
   3100 
   3101        sub             r6,  r6,  r9, lsl #3
   3102 
   3103        // This ordering of vmull/vmlal is highly beneficial for
   3104        // Cortex A8/A9/A53 here, but harmful for Cortex A7.
   3105        vmull.s16       q0,  d16,  d2
   3106        vmlal.s16       q0,  d18,  d4
   3107        vmlal.s16       q0,  d20,  d6
   3108        vmlal.s16       q0,  d22,  d8
   3109        vmlal.s16       q0,  d24,  d10
   3110        vmlal.s16       q0,  d26,  d12
   3111        vmull.s16       q1,  d17,  d3
   3112        vmlal.s16       q1,  d19,  d5
   3113        vmlal.s16       q1,  d21,  d7
   3114        vmlal.s16       q1,  d23,  d9
   3115        vmlal.s16       q1,  d25,  d11
   3116        vmlal.s16       q1,  d27,  d13
   3117 
   3118        vmovl.s8        q2,  d14
   3119        vmovl.s8        q3,  d15
   3120 
   3121        vmlal.s16       q0,  d28,  d4
   3122        vmlal.s16       q0,  d30,  d6
   3123        vmlal.s16       q1,  d29,  d5
   3124        vmlal.s16       q1,  d31,  d7
   3125 
   3126 .ifb \t
   3127        vmov.i16        q7,  #128
   3128 .else
   3129        vmov.i16        q7,  #0x800
   3130 .endif
   3131 
   3132        vmov            q8,  q9
   3133        vmov            q9,  q10
   3134        vqrshrn.s32     d0,  q0,  #\shift
   3135        vmov            q10, q11
   3136        vqrshrn.s32     d1,  q1,  #\shift
   3137        vmov            q11, q12
   3138        vadd.i16        q0,  q0,  q7
   3139        vmov            q12, q13
   3140 .ifb \t
   3141        vqmovun.s16     d0,  q0
   3142 .endif
   3143        vmov            q13, q14
   3144        vmov            q14, q15
   3145        subs            r10, r10, #1
   3146 .ifnb \t
   3147        vst1.16         {q0}, [r0, :128], r1
   3148 .else
   3149        vst1.8          {d0}, [r0, :64], r1
   3150 .endif
   3151 
   3152        add             r6,  r6,  r4
   3153        bgt             1b
   3154 
   3155        vpop            {q4-q7}
   3156        pop             {r4-r11,pc}
   3157 endfunc
   3158 .endm
   3159 
   3160 warp  , 11
   3161 warp t, 7
   3162 
   3163 // void dav1d_emu_edge_8bpc_neon(
   3164 //         const intptr_t bw, const intptr_t bh,
   3165 //         const intptr_t iw, const intptr_t ih,
   3166 //         const intptr_t x, const intptr_t y,
   3167 //         pixel *dst, const ptrdiff_t dst_stride,
   3168 //         const pixel *ref, const ptrdiff_t ref_stride)
   3169 function emu_edge_8bpc_neon, export=1
   3170        push            {r4-r11,lr}
   3171        ldrd            r4,  r5,  [sp, #36]
   3172        ldrd            r6,  r7,  [sp, #44]
   3173        ldrd            r8,  r9,  [sp, #52]
   3174 
   3175        // ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride)
   3176        // ref += iclip(x, 0, iw - 1)
   3177        sub             r12, r3,  #1           // ih - 1
   3178        cmp             r5,  r3
   3179        sub             lr,  r2,  #1           // iw - 1
   3180        it              lt
   3181        movlt           r12, r5                // min(y, ih - 1)
   3182        cmp             r4,  r2
   3183        bic             r12, r12, r12, asr #31 // max(min(y, ih - 1), 0)
   3184        it              lt
   3185        movlt           lr,  r4                // min(x, iw - 1)
   3186        bic             lr,  lr,  lr,  asr #31 // max(min(x, iw - 1), 0)
   3187        mla             r8,  r12, r9,  r8      // ref += iclip() * stride
   3188        add             r8,  r8,  lr           // ref += iclip()
   3189 
   3190        // bottom_ext = iclip(y + bh - ih, 0, bh - 1)
   3191        // top_ext = iclip(-y, 0, bh - 1)
   3192        add             r10, r5,  r1           // y + bh
   3193        neg             r5,  r5                // -y
   3194        sub             r10, r10, r3           // y + bh - ih
   3195        sub             r12, r1,  #1           // bh - 1
   3196        cmp             r10, r1
   3197        bic             r5,  r5,  r5,  asr #31 // max(-y, 0)
   3198        it              ge
   3199        movge           r10, r12               // min(y + bh - ih, bh-1)
   3200        cmp             r5,  r1
   3201        bic             r10, r10, r10, asr #31 // max(min(y + bh - ih, bh-1), 0)
   3202        it              ge
   3203        movge           r5,  r12               // min(max(-y, 0), bh-1)
   3204 
   3205        // right_ext = iclip(x + bw - iw, 0, bw - 1)
   3206        // left_ext = iclip(-x, 0, bw - 1)
   3207        add             r11, r4,  r0           // x + bw
   3208        neg             r4,  r4                // -x
   3209        sub             r11, r11, r2           // x + bw - iw
   3210        sub             lr,  r0,  #1           // bw - 1
   3211        cmp             r11, r0
   3212        bic             r4,  r4,  r4,  asr #31 // max(-x, 0)
   3213        it              ge
   3214        movge           r11, lr                // min(x + bw - iw, bw-1)
   3215        cmp             r4,  r0
   3216        bic             r11, r11, r11, asr #31 // max(min(x + bw - iw, bw-1), 0)
   3217        it              ge
   3218        movge           r4,  lr                // min(max(-x, 0), bw - 1)
   3219 
   3220        // center_h = bh - top_ext - bottom_ext
   3221        // dst += top_ext * PXSTRIDE(dst_stride)
   3222        // center_w = bw - left_ext - right_ext
   3223        sub             r1,  r1,  r5           // bh - top_ext
   3224        mla             r6,  r5,  r7,  r6
   3225        sub             r2,  r0,  r4           // bw - left_ext
   3226        sub             r1,  r1,  r10          // center_h = bh - top_ext - bottom_ext
   3227        sub             r2,  r2,  r11          // center_w = bw - left_ext - right_ext
   3228 
   3229        mov             r0,  r6                // backup of dst
   3230 
   3231 .macro v_loop need_left, need_right
   3232 0:
   3233 .if \need_left
   3234        vld1.8          {d0[], d1[]}, [r8]
   3235        mov             r12, r6                // out = dst
   3236        mov             r3,  r4
   3237 1:
   3238        subs            r3,  r3,  #16
   3239        vst1.8          {q0}, [r12, :128]!
   3240        bgt             1b
   3241 .endif
   3242        mov             lr,  r8
   3243        add             r12, r6,  r4           // out = dst + left_ext
   3244        mov             r3,  r2
   3245 1:
   3246        vld1.8          {q0, q1}, [lr]!
   3247        subs            r3,  r3,  #32
   3248 .if \need_left
   3249        vst1.8          {q0, q1}, [r12]!
   3250 .else
   3251        vst1.8          {q0, q1}, [r12, :128]!
   3252 .endif
   3253        bgt             1b
   3254 .if \need_right
   3255        add             r3,  r8,  r2           // in + center_w
   3256        sub             r3,  r3,  #1           // in + center_w - 1
   3257        add             r12, r6,  r4           // dst + left_ext
   3258        vld1.8          {d0[], d1[]}, [r3]
   3259        add             r12, r12, r2           // out = dst + left_ext + center_w
   3260        mov             r3,  r11
   3261 1:
   3262        subs            r3,  r3,  #16
   3263        vst1.8          {q0}, [r12]!
   3264        bgt             1b
   3265 .endif
   3266 
   3267        subs            r1,  r1,  #1           // center_h--
   3268        add             r6,  r6,  r7
   3269        add             r8,  r8,  r9
   3270        bgt             0b
   3271 .endm
   3272 
   3273        cmp             r4,  #0
   3274        beq             2f
   3275        // need_left
   3276        cmp             r11, #0
   3277        beq             3f
   3278        // need_left + need_right
   3279        v_loop          1,   1
   3280        b               5f
   3281 
   3282 2:
   3283        // !need_left
   3284        cmp             r11, #0
   3285        beq             4f
   3286        // !need_left + need_right
   3287        v_loop          0,   1
   3288        b               5f
   3289 
   3290 3:
   3291        // need_left + !need_right
   3292        v_loop          1,   0
   3293        b               5f
   3294 
   3295 4:
   3296        // !need_left + !need_right
   3297        v_loop          0,   0
   3298 
   3299 5:
   3300        cmp             r10, #0
   3301        // Storing the original dst in r0 overwrote bw, recalculate it here
   3302        add             r2,  r2,  r4           // center_w + left_ext
   3303        add             r2,  r2,  r11          // bw = center_w + left_ext + right_ext
   3304 
   3305        beq             3f
   3306        // need_bottom
   3307        sub             r8,  r6,  r7           // ref = dst - stride
   3308        mov             r4,  r2
   3309 1:
   3310        vld1.8          {q0, q1}, [r8, :128]!
   3311        mov             r3,  r10
   3312 2:
   3313        subs            r3,  r3,  #1
   3314        vst1.8          {q0, q1}, [r6, :128], r7
   3315        bgt             2b
   3316        mls             r6,  r7,  r10,  r6     // dst -= bottom_ext * stride
   3317        subs            r4,  r4,  #32          // bw -= 32
   3318        add             r6,  r6,  #32          // dst += 32
   3319        bgt             1b
   3320 
   3321 3:
   3322        cmp             r5,  #0
   3323        beq             3f
   3324        // need_top
   3325        mls             r6,  r7,  r5,  r0      // dst = stored_dst - top_ext * stride
   3326 1:
   3327        vld1.8          {q0, q1}, [r0, :128]!
   3328        mov             r3,  r5
   3329 2:
   3330        subs            r3,  r3,  #1
   3331        vst1.8          {q0, q1}, [r6, :128], r7
   3332        bgt             2b
   3333        mls             r6,  r7,  r5,  r6      // dst -= top_ext * stride
   3334        subs            r2,  r2,  #32          // bw -= 32
   3335        add             r6,  r6,  #32          // dst += 32
   3336        bgt             1b
   3337 
   3338 3:
   3339        pop             {r4-r11,pc}
   3340 endfunc