tor-browser

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

mc16.S (131896B)


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