tor-browser

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

ipred.S (115269B)


      1 /*
      2 * Copyright © 2018, VideoLAN and dav1d authors
      3 * Copyright © 2020, Martin Storsjo
      4 * Copyright © 2019, B Krishnan Iyer
      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 // void ipred_dc_128_8bpc_neon(pixel *dst, const ptrdiff_t stride,
     33 //                             const pixel *const topleft,
     34 //                             const int width, const int height, const int a,
     35 //                             const int max_width, const int max_height);
     36 function ipred_dc_128_8bpc_neon, export=1
     37        push            {r4, lr}
     38        ldr             r4,  [sp, #8]
     39        clz             r3,  r3
     40        adr             r2,  L(ipred_dc_128_tbl)
     41        sub             r3,  r3,  #25
     42        ldr             r3,  [r2,  r3,  lsl #2]
     43        vmov.i8         q0,  #128
     44        add             r2,  r2,  r3
     45        add             r12, r0,  r1
     46        lsl             r1,  r1,  #1
     47        bx              r2
     48 
     49        .align 2
     50 L(ipred_dc_128_tbl):
     51        .word 640f - L(ipred_dc_128_tbl) + CONFIG_THUMB
     52        .word 320f - L(ipred_dc_128_tbl) + CONFIG_THUMB
     53        .word 16f  - L(ipred_dc_128_tbl) + CONFIG_THUMB
     54        .word 8f   - L(ipred_dc_128_tbl) + CONFIG_THUMB
     55        .word 4f   - L(ipred_dc_128_tbl) + CONFIG_THUMB
     56 4:
     57        vst1.32         {d0[0]},  [r0,  :32], r1
     58        vst1.32         {d0[0]},  [r12, :32], r1
     59        subs            r4,  r4,  #4
     60        vst1.32         {d0[0]},  [r0,  :32], r1
     61        vst1.32         {d0[0]},  [r12, :32], r1
     62        bgt             4b
     63        pop             {r4, pc}
     64 8:
     65        vst1.8          {d0},  [r0,  :64], r1
     66        vst1.8          {d0},  [r12, :64], r1
     67        subs            r4,  r4,  #4
     68        vst1.8          {d0},  [r0,  :64], r1
     69        vst1.8          {d0},  [r12, :64], r1
     70        bgt             8b
     71        pop             {r4, pc}
     72 16:
     73        vst1.8          {d0,  d1}, [r0,  :128], r1
     74        vst1.8          {d0,  d1}, [r12, :128], r1
     75        subs            r4,  r4,  #4
     76        vst1.8          {d0,  d1}, [r0,  :128], r1
     77        vst1.8          {d0,  d1}, [r12, :128], r1
     78        bgt             16b
     79        pop             {r4, pc}
     80 320:
     81        vmov.i8         q1,  #128
     82 32:
     83        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
     84        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
     85        subs            r4,  r4,  #4
     86        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
     87        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
     88        bgt             32b
     89        pop             {r4, pc}
     90 640:
     91        vmov.i8         q1,  #128
     92        sub             r1,  r1,  #32
     93 64:
     94        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
     95        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
     96        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
     97        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
     98        subs            r4,  r4,  #4
     99        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
    100        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
    101        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    102        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    103        bgt             64b
    104        pop             {r4, pc}
    105 endfunc
    106 
    107 // void ipred_v_8bpc_neon(pixel *dst, const ptrdiff_t stride,
    108 //                        const pixel *const topleft,
    109 //                        const int width, const int height, const int a,
    110 //                        const int max_width, const int max_height);
    111 function ipred_v_8bpc_neon, export=1
    112        push            {r4, lr}
    113        ldr             lr,  [sp, #8]
    114        clz             r3,  r3
    115        adr             r4,  L(ipred_v_tbl)
    116        sub             r3,  r3,  #25
    117        ldr             r3,  [r4,  r3,  lsl #2]
    118        add             r2,  r2,  #1
    119        add             r4,  r4,  r3
    120        add             r12, r0,  r1
    121        lsl             r1,  r1,  #1
    122        bx              r4
    123 
    124        .align 2
    125 L(ipred_v_tbl):
    126        .word 640f - L(ipred_v_tbl) + CONFIG_THUMB
    127        .word 320f - L(ipred_v_tbl) + CONFIG_THUMB
    128        .word 160f - L(ipred_v_tbl) + CONFIG_THUMB
    129        .word 80f  - L(ipred_v_tbl) + CONFIG_THUMB
    130        .word 40f  - L(ipred_v_tbl) + CONFIG_THUMB
    131 40:
    132        vld1.32         {d0[]},   [r2]
    133 4:
    134        vst1.32         {d0[0]},  [r0,  :32], r1
    135        vst1.32         {d0[0]},  [r12, :32], r1
    136        subs            lr,  lr,  #4
    137        vst1.32         {d0[0]},  [r0,  :32], r1
    138        vst1.32         {d0[0]},  [r12, :32], r1
    139        bgt             4b
    140        pop             {r4, pc}
    141 80:
    142        vld1.8          {d0}, [r2]
    143 8:
    144        vst1.8          {d0},  [r0,  :64], r1
    145        vst1.8          {d0},  [r12, :64], r1
    146        subs            lr,  lr,  #4
    147        vst1.8          {d0},  [r0,  :64], r1
    148        vst1.8          {d0},  [r12, :64], r1
    149        bgt             8b
    150        pop             {r4, pc}
    151 160:
    152        vld1.8          {q0},  [r2]
    153 16:
    154        vst1.8          {d0,  d1},  [r0,  :128], r1
    155        vst1.8          {d0,  d1},  [r12, :128], r1
    156        subs            lr,  lr,  #4
    157        vst1.8          {d0,  d1},  [r0,  :128], r1
    158        vst1.8          {d0,  d1},  [r12, :128], r1
    159        bgt             16b
    160        pop             {r4, pc}
    161 320:
    162        vld1.8          {q0,  q1},  [r2]
    163 32:
    164        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    165        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    166        subs            lr,  lr,  #4
    167        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    168        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    169        bgt             32b
    170        pop             {r4, pc}
    171 640:
    172        vld1.8          {q0,  q1},  [r2]!
    173        sub             r1,  r1,  #32
    174        vld1.8          {q2,  q3},  [r2]
    175 64:
    176        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
    177        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
    178        vst1.8          {d4,  d5,  d6,  d7},  [r0,  :128], r1
    179        vst1.8          {d4,  d5,  d6,  d7},  [r12, :128], r1
    180        subs            lr,  lr,  #4
    181        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
    182        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
    183        vst1.8          {d4,  d5,  d6,  d7},  [r0,  :128], r1
    184        vst1.8          {d4,  d5,  d6,  d7},  [r12, :128], r1
    185        bgt             64b
    186        pop             {r4, pc}
    187 endfunc
    188 
    189 // void ipred_h_8bpc_neon(pixel *dst, const ptrdiff_t stride,
    190 //                        const pixel *const topleft,
    191 //                        const int width, const int height, const int a,
    192 //                        const int max_width, const int max_height);
    193 function ipred_h_8bpc_neon, export=1
    194        push            {r4-r5, lr}
    195        ldr             r4,  [sp, #12]
    196        clz             r3,  r3
    197        adr             r5,  L(ipred_h_tbl)
    198        sub             r3,  r3,  #25
    199        ldr             r3,  [r5,  r3,  lsl #2]
    200        sub             r2,  r2,  #4
    201        mov             lr,  #-4
    202        add             r5,  r5,  r3
    203        add             r12, r0,  r1
    204        lsl             r1,  r1,  #1
    205        bx              r5
    206 
    207        .align 2
    208 L(ipred_h_tbl):
    209        .word 640f - L(ipred_h_tbl) + CONFIG_THUMB
    210        .word 320f - L(ipred_h_tbl) + CONFIG_THUMB
    211        .word 160f - L(ipred_h_tbl) + CONFIG_THUMB
    212        .word 8f   - L(ipred_h_tbl) + CONFIG_THUMB
    213        .word 4f   - L(ipred_h_tbl) + CONFIG_THUMB
    214 4:
    215        vld4.8          {d0[],  d1[],  d2[],  d3[]},  [r2, :32],  lr
    216        vst1.32         {d3[0]},  [r0,  :32], r1
    217        vst1.32         {d2[0]},  [r12, :32], r1
    218        subs            r4,  r4,  #4
    219        vst1.32         {d1[0]},  [r0,  :32], r1
    220        vst1.32         {d0[0]},  [r12, :32], r1
    221        bgt             4b
    222        pop             {r4-r5, pc}
    223 8:
    224        vld4.8          {d0[],  d1[],  d2[],  d3[]},  [r2, :32],  lr
    225        vst1.8          {d3},  [r0,  :64], r1
    226        vst1.8          {d2},  [r12, :64], r1
    227        subs            r4,  r4,  #4
    228        vst1.8          {d1},  [r0,  :64], r1
    229        vst1.8          {d0},  [r12, :64], r1
    230        bgt             8b
    231        pop             {r4-r5, pc}
    232 160:
    233        add             r2,  r2,  #3
    234        mov             lr,  #-1
    235 16:
    236        vld1.8          {d0[],  d1[]},  [r2],  lr
    237        subs            r4,  r4,  #4
    238        vld1.8          {d2[],  d3[]},  [r2],  lr
    239        vst1.8          {q0},  [r0,    :128],  r1
    240        vld1.8          {d4[],  d5[]},  [r2],  lr
    241        vst1.8          {q1},  [r12,   :128],  r1
    242        vld1.8          {d6[],  d7[]},  [r2],  lr
    243        vst1.8          {q2},  [r0,    :128],  r1
    244        vst1.8          {q3},  [r12,   :128],  r1
    245        bgt             16b
    246        pop             {r4-r5, pc}
    247 320:
    248        add             r2,  r2,  #3
    249        mov             lr,  #-1
    250        sub             r1,  r1,  #16
    251 32:
    252        vld1.8          {d0[],  d1[]}, [r2],  lr
    253        subs            r4,  r4,  #4
    254        vld1.8          {d2[],  d3[]}, [r2],  lr
    255        vst1.8          {q0},  [r0,   :128]!
    256        vld1.8          {d4[],  d5[]}, [r2],  lr
    257        vst1.8          {q1},  [r12,  :128]!
    258        vld1.8          {d6[],  d7[]}, [r2],  lr
    259        vst1.8          {q0},  [r0,   :128],  r1
    260        vst1.8          {q1},  [r12,  :128],  r1
    261        vst1.8          {q2},  [r0,   :128]!
    262        vst1.8          {q3},  [r12,  :128]!
    263        vst1.8          {q2},  [r0,   :128],  r1
    264        vst1.8          {q3},  [r12,  :128],  r1
    265        bgt             32b
    266        pop             {r4-r5, pc}
    267 640:
    268        add             r2,  r2,  #3
    269        mov             lr,  #-1
    270        sub             r1,  r1,  #48
    271 64:
    272        vld1.8          {d0[],  d1[]},  [r2],  lr
    273        subs            r4,  r4,  #4
    274        vld1.8          {d2[],  d3[]},  [r2],  lr
    275        vst1.8          {q0},  [r0,    :128]!
    276        vld1.8          {d4[],  d5[]},  [r2],  lr
    277        vst1.8          {q1},  [r12,   :128]!
    278        vld1.8          {d6[],  d7[]},  [r2],  lr
    279        vst1.8          {q0},  [r0,    :128]!
    280        vst1.8          {q1},  [r12,   :128]!
    281        vst1.8          {q0},  [r0,    :128]!
    282        vst1.8          {q1},  [r12,   :128]!
    283        vst1.8          {q0},  [r0,    :128],  r1
    284        vst1.8          {q1},  [r12,   :128],  r1
    285        vst1.8          {q2},  [r0,    :128]!
    286        vst1.8          {q3},  [r12,   :128]!
    287        vst1.8          {q2},  [r0,    :128]!
    288        vst1.8          {q3},  [r12,   :128]!
    289        vst1.8          {q2},  [r0,    :128]!
    290        vst1.8          {q3},  [r12,   :128]!
    291        vst1.8          {q2},  [r0,    :128],  r1
    292        vst1.8          {q3},  [r12,   :128],  r1
    293        bgt             64b
    294        pop             {r4-r5, pc}
    295 endfunc
    296 
    297 // void ipred_dc_top_8bpc_neon(pixel *dst, const ptrdiff_t stride,
    298 //                             const pixel *const topleft,
    299 //                             const int width, const int height, const int a,
    300 //                             const int max_width, const int max_height);
    301 function ipred_dc_top_8bpc_neon, export=1
    302        push            {r4-r5, lr}
    303        ldr             r4,  [sp, #12]
    304        clz             r3,  r3
    305        adr             r5,  L(ipred_dc_top_tbl)
    306        sub             r3,  r3,  #25
    307        ldr             r3,  [r5,  r3,  lsl #2]
    308        add             r2,  r2,  #1
    309        add             r5,  r5,  r3
    310        add             r12, r0,  r1
    311        lsl             r1,  r1,  #1
    312        bx              r5
    313 
    314        .align 2
    315 L(ipred_dc_top_tbl):
    316        .word 640f - L(ipred_dc_top_tbl) + CONFIG_THUMB
    317        .word 320f - L(ipred_dc_top_tbl) + CONFIG_THUMB
    318        .word 160f - L(ipred_dc_top_tbl) + CONFIG_THUMB
    319        .word 80f  - L(ipred_dc_top_tbl) + CONFIG_THUMB
    320        .word 40f  - L(ipred_dc_top_tbl) + CONFIG_THUMB
    321 40:
    322        vld1.32         {d0[]},  [r2]
    323        vpaddl.u8       d0,  d0
    324        vpadd.u16       d0,  d0
    325        vrshrn.u16      d0,  q0,  #2
    326        vdup.8          d0,  d0[0]
    327 4:
    328        vst1.32         {d0[0]},  [r0,  :32], r1
    329        vst1.32         {d0[0]},  [r12, :32], r1
    330        subs            r4,  r4,  #4
    331        vst1.32         {d0[0]},  [r0,  :32], r1
    332        vst1.32         {d0[0]},  [r12, :32], r1
    333        bgt             4b
    334        pop             {r4-r5, pc}
    335 80:
    336        vld1.8          {d0},  [r2]
    337        vpaddl.u8       d0,  d0
    338        vpadd.u16       d0,  d0
    339        vpadd.u16       d0,  d0
    340        vrshrn.u16      d0,  q0,  #3
    341        vdup.8          d0,  d0[0]
    342 8:
    343        vst1.8          {d0},  [r0,  :64], r1
    344        vst1.8          {d0},  [r12, :64], r1
    345        subs            r4,  r4,  #4
    346        vst1.8          {d0},  [r0,  :64], r1
    347        vst1.8          {d0},  [r12, :64], r1
    348        bgt             8b
    349        pop             {r4-r5, pc}
    350 160:
    351        vld1.8          {d0,  d1},  [r2]
    352        vaddl.u8        q0,  d0,  d1
    353        vadd.u16        d0,  d0,  d1
    354        vpadd.u16       d0,  d0
    355        vpadd.u16       d0,  d0
    356        vrshrn.u16      d0,  q0,  #4
    357        vdup.8          q0,  d0[0]
    358 16:
    359        vst1.8          {d0,  d1},  [r0,  :128], r1
    360        vst1.8          {d0,  d1},  [r12, :128], r1
    361        subs            r4,  r4,  #4
    362        vst1.8          {d0,  d1},  [r0,  :128], r1
    363        vst1.8          {d0,  d1},  [r12, :128], r1
    364        bgt             16b
    365        pop             {r4-r5, pc}
    366 320:
    367        vld1.8          {d0,  d1,  d2,  d3},  [r2]
    368        vaddl.u8        q0,  d0,  d1
    369        vaddl.u8        q1,  d2,  d3
    370        vadd.u16        q0,  q0,  q1
    371        vadd.u16        d0,  d0,  d1
    372        vpadd.u16       d0,  d0
    373        vpadd.u16       d0,  d0
    374        vrshrn.u16      d4,  q0,  #5
    375        vdup.8          q0,  d4[0]
    376        vdup.8          q1,  d4[0]
    377 32:
    378        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    379        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    380        subs            r4,  r4,  #4
    381        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    382        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    383        bgt             32b
    384        pop             {r4-r5, pc}
    385 640:
    386        vld1.8          {d0,  d1,  d2,  d3},  [r2]!
    387        vaddl.u8        q0,  d0,  d1
    388        vld1.8          {d4,  d5,  d6,  d7},  [r2]
    389        vaddl.u8        q1,  d2,  d3
    390        vaddl.u8        q2,  d4,  d5
    391        vaddl.u8        q3,  d6,  d7
    392        vadd.u16        q0,  q0,  q1
    393        vadd.u16        q1,  q2,  q3
    394        vadd.u16        q0,  q0,  q1
    395        vadd.u16        d0,  d0,  d1
    396        vpadd.u16       d0,  d0
    397        vpadd.u16       d0,  d0
    398        vrshrn.u16      d18, q0,  #6
    399        vdup.8          q0,  d18[0]
    400        vdup.8          q1,  d18[0]
    401        sub             r1,  r1,  #32
    402 64:
    403        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
    404        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
    405        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    406        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    407        subs            r4,  r4,  #4
    408        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
    409        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
    410        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    411        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    412        bgt             64b
    413        pop             {r4-r5, pc}
    414 endfunc
    415 
    416 // void ipred_dc_left_8bpc_neon(pixel *dst, const ptrdiff_t stride,
    417 //                              const pixel *const topleft,
    418 //                              const int width, const int height, const int a,
    419 //                              const int max_width, const int max_height);
    420 function ipred_dc_left_8bpc_neon, export=1
    421        push            {r4-r5, lr}
    422        ldr             r4,  [sp, #12]
    423        sub             r2,  r2,  r4
    424        clz             r3,  r3
    425        clz             lr,  r4
    426        sub             lr,  lr,  #25
    427        adr             r5,  L(ipred_dc_left_tbl)
    428        sub             r3,  r3,  #20
    429        ldr             r3,  [r5,  r3,  lsl #2]
    430        ldr             lr,  [r5,  lr,  lsl #2]
    431        add             r3,  r5,  r3
    432        add             r5,  r5,  lr
    433        add             r12, r0,  r1
    434        lsl             r1,  r1,  #1
    435        bx              r5
    436 
    437        .align 2
    438 L(ipred_dc_left_tbl):
    439        .word L(ipred_dc_left_h64) - L(ipred_dc_left_tbl) + CONFIG_THUMB
    440        .word L(ipred_dc_left_h32) - L(ipred_dc_left_tbl) + CONFIG_THUMB
    441        .word L(ipred_dc_left_h16) - L(ipred_dc_left_tbl) + CONFIG_THUMB
    442        .word L(ipred_dc_left_h8)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
    443        .word L(ipred_dc_left_h4)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
    444        .word L(ipred_dc_left_w64) - L(ipred_dc_left_tbl) + CONFIG_THUMB
    445        .word L(ipred_dc_left_w32) - L(ipred_dc_left_tbl) + CONFIG_THUMB
    446        .word L(ipred_dc_left_w16) - L(ipred_dc_left_tbl) + CONFIG_THUMB
    447        .word L(ipred_dc_left_w8)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
    448        .word L(ipred_dc_left_w4)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
    449 
    450 L(ipred_dc_left_h4):
    451        vld1.32         {d0[]},  [r2, :32]
    452        vpaddl.u8       d0,  d0
    453        vpadd.u16       d0,  d0
    454        vrshrn.u16      d0,  q0,  #2
    455        vdup.8          q0,  d0[0]
    456        bx              r3
    457 L(ipred_dc_left_w4):
    458        vst1.32         {d0[0]},  [r0,  :32], r1
    459        vst1.32         {d0[0]},  [r12, :32], r1
    460        subs            r4,  r4,  #4
    461        vst1.32         {d0[0]},  [r0,  :32], r1
    462        vst1.32         {d0[0]},  [r12, :32], r1
    463        bgt             L(ipred_dc_left_w4)
    464        pop             {r4-r5, pc}
    465 L(ipred_dc_left_h8):
    466        vld1.8          {d0},  [r2, :64]
    467        vpaddl.u8       d0,  d0
    468        vpadd.u16       d0,  d0
    469        vpadd.u16       d0,  d0
    470        vrshrn.u16      d0,  q0,  #3
    471        vdup.8          q0,  d0[0]
    472        bx              r3
    473 L(ipred_dc_left_w8):
    474        vst1.8          {d0},  [r0,  :64], r1
    475        vst1.8          {d0},  [r12, :64], r1
    476        subs            r4,  r4,  #4
    477        vst1.8          {d0},  [r0,  :64], r1
    478        vst1.8          {d0},  [r12, :64], r1
    479        bgt             L(ipred_dc_left_w8)
    480        pop             {r4-r5, pc}
    481 L(ipred_dc_left_h16):
    482        vld1.8          {d0,  d1},  [r2, :128]
    483        vaddl.u8        q0,  d0,  d1
    484        vadd.u16        d0,  d0,  d1
    485        vpadd.u16       d0,  d0
    486        vpadd.u16       d0,  d0
    487        vrshrn.u16      d0,  q0,  #4
    488        vdup.8          q0,  d0[0]
    489        bx              r3
    490 L(ipred_dc_left_w16):
    491        vst1.8          {d0,  d1},  [r0,  :128], r1
    492        vst1.8          {d0,  d1},  [r12, :128], r1
    493        subs            r4,  r4,  #4
    494        vst1.8          {d0,  d1},  [r0,  :128], r1
    495        vst1.8          {d0,  d1},  [r12, :128], r1
    496        bgt             L(ipred_dc_left_w16)
    497        pop             {r4-r5, pc}
    498 L(ipred_dc_left_h32):
    499        vld1.8          {d0,  d1,  d2,  d3},  [r2, :128]
    500        vaddl.u8        q0,  d0,  d1
    501        vaddl.u8        q1,  d2,  d3
    502        vadd.u16        q0,  q0,  q1
    503        vadd.u16        d0,  d0,  d1
    504        vpadd.u16       d0,  d0
    505        vpadd.u16       d0,  d0
    506        vrshrn.u16      d0,  q0,  #5
    507        vdup.8          q0,  d0[0]
    508        bx              r3
    509 L(ipred_dc_left_w32):
    510        vmov.8          q1,  q0
    511 1:
    512        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    513        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    514        subs            r4,  r4,  #4
    515        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    516        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    517        bgt             1b
    518        pop             {r4-r5, pc}
    519 L(ipred_dc_left_h64):
    520        vld1.8          {d0,  d1,  d2,  d3},  [r2, :128]!
    521        vld1.8          {d4,  d5,  d6,  d7},  [r2, :128]
    522        vaddl.u8        q0,  d0,  d1
    523        vaddl.u8        q1,  d2,  d3
    524        vaddl.u8        q2,  d4,  d5
    525        vaddl.u8        q3,  d6,  d7
    526        vadd.u16        q0,  q0,  q1
    527        vadd.u16        q1,  q2,  q3
    528        vadd.u16        q0,  q0,  q1
    529        vadd.u16        d0,  d0,  d1
    530        vpadd.u16       d0,  d0
    531        vpadd.u16       d0,  d0
    532        vrshrn.u16      d0,  q0,  #6
    533        vdup.8          q0,  d0[0]
    534        bx              r3
    535 L(ipred_dc_left_w64):
    536        vmov.8          q1,  q0
    537        sub             r1,  r1,  #32
    538 1:
    539        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
    540        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
    541        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    542        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    543        subs            r4,  r4, #4
    544        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
    545        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
    546        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    547        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    548        bgt             1b
    549        pop             {r4-r5, pc}
    550 endfunc
    551 
    552 // void ipred_dc_8bpc_neon(pixel *dst, const ptrdiff_t stride,
    553 //                         const pixel *const topleft,
    554 //                         const int width, const int height, const int a,
    555 //                         const int max_width, const int max_height);
    556 function ipred_dc_8bpc_neon, export=1
    557        push            {r4-r6, lr}
    558        ldr             r4,  [sp, #16]
    559        sub             r2,  r2,  r4
    560        add             lr,  r3,  r4        // width + height
    561        clz             r3,  r3
    562        clz             r12, r4
    563        vdup.16         q15, lr             // width + height
    564        adr             r5,  L(ipred_dc_tbl)
    565        rbit            lr,  lr             // rbit(width + height)
    566        sub             r3,  r3,  #20       // 25 leading bits, minus table offset 5
    567        sub             r12, r12, #25
    568        clz             lr,  lr             // ctz(width + height)
    569        ldr             r3,  [r5,  r3,  lsl #2]
    570        ldr             r12, [r5,  r12, lsl #2]
    571        neg             lr,  lr             // -ctz(width + height)
    572        add             r3,  r5,  r3
    573        add             r5,  r5,  r12
    574        vshr.u16        q15, q15, #1        // (width + height) >> 1
    575        vdup.16         q14, lr             // -ctz(width + height)
    576        add             r12, r0,  r1
    577        lsl             r1,  r1,  #1
    578        bx              r5
    579 
    580        .align 2
    581 L(ipred_dc_tbl):
    582        .word L(ipred_dc_h64) - L(ipred_dc_tbl) + CONFIG_THUMB
    583        .word L(ipred_dc_h32) - L(ipred_dc_tbl) + CONFIG_THUMB
    584        .word L(ipred_dc_h16) - L(ipred_dc_tbl) + CONFIG_THUMB
    585        .word L(ipred_dc_h8)  - L(ipred_dc_tbl) + CONFIG_THUMB
    586        .word L(ipred_dc_h4)  - L(ipred_dc_tbl) + CONFIG_THUMB
    587        .word L(ipred_dc_w64) - L(ipred_dc_tbl) + CONFIG_THUMB
    588        .word L(ipred_dc_w32) - L(ipred_dc_tbl) + CONFIG_THUMB
    589        .word L(ipred_dc_w16) - L(ipred_dc_tbl) + CONFIG_THUMB
    590        .word L(ipred_dc_w8)  - L(ipred_dc_tbl) + CONFIG_THUMB
    591        .word L(ipred_dc_w4)  - L(ipred_dc_tbl) + CONFIG_THUMB
    592 
    593 L(ipred_dc_h4):
    594        vld1.32         {d0[]},  [r2, :32]!
    595        vpaddl.u8       d0,  d0
    596        add             r2,  r2,  #1
    597        vpadd.u16       d0,  d0
    598        bx              r3
    599 L(ipred_dc_w4):
    600        vld1.32         {d1[]},  [r2]
    601        vadd.s16        d0,  d0,  d30
    602        vpaddl.u8       d1,  d1
    603        vpadd.u16       d1,  d1
    604        cmp             r4,  #4
    605        vadd.s16        d0,  d0,  d1
    606        vshl.u16        d0,  d0,  d28
    607        beq             1f
    608        // h = 8/16
    609        movw            lr,  #(0x3334/2)
    610        movw            r5,  #(0x5556/2)
    611        cmp             r4,  #16
    612        it              ne
    613        movne           lr,  r5
    614        vdup.16         d30, lr
    615        vqdmulh.s16     d0,  d0,  d30
    616 1:
    617        vdup.8          d0,  d0[0]
    618 2:
    619        vst1.32         {d0[0]},  [r0,  :32], r1
    620        vst1.32         {d0[0]},  [r12, :32], r1
    621        subs            r4,  r4,  #4
    622        vst1.32         {d0[0]},  [r0,  :32], r1
    623        vst1.32         {d0[0]},  [r12, :32], r1
    624        bgt             2b
    625        pop             {r4-r6, pc}
    626 
    627 L(ipred_dc_h8):
    628        vld1.8          {d0},  [r2, :64]!
    629        vpaddl.u8       d0,  d0
    630        vpadd.u16       d0,  d0
    631        add             r2,  r2,  #1
    632        vpadd.u16       d0,  d0
    633        bx              r3
    634 L(ipred_dc_w8):
    635        vld1.8          {d2},  [r2]
    636        vadd.s16        d0,  d0,  d30
    637        vpaddl.u8       d2,  d2
    638        vpadd.u16       d2,  d2
    639        vpadd.u16       d2,  d2
    640        cmp             r4,  #8
    641        vadd.s16        d0,  d0,  d2
    642        vshl.u16        d0,  d0,  d28
    643        beq             1f
    644        // h = 4/16/32
    645        cmp             r4,  #32
    646        movw            lr,  #(0x3334/2)
    647        movw            r5,  #(0x5556/2)
    648        it              ne
    649        movne           lr,  r5
    650        vdup.16         d24, lr
    651        vqdmulh.s16     d0,  d0,  d24
    652 1:
    653        vdup.8          d0,  d0[0]
    654 2:
    655        vst1.8          {d0},  [r0,  :64], r1
    656        vst1.8          {d0},  [r12, :64], r1
    657        subs            r4,  r4,  #4
    658        vst1.8          {d0},  [r0,  :64], r1
    659        vst1.8          {d0},  [r12, :64], r1
    660        bgt             2b
    661        pop             {r4-r6, pc}
    662 
    663 L(ipred_dc_h16):
    664        vld1.8          {d0,  d1},  [r2, :128]!
    665        vaddl.u8        q0,  d0,  d1
    666        vadd.u16        d0,  d0,  d1
    667        vpadd.u16       d0,  d0
    668        add             r2,  r2,  #1
    669        vpadd.u16       d0,  d0
    670        bx              r3
    671 L(ipred_dc_w16):
    672        vld1.8          {d2,  d3},  [r2]
    673        vadd.s16        d0,  d0,  d30
    674        vaddl.u8        q1,  d2,  d3
    675        vadd.u16        d2,  d2,  d3
    676        vpadd.u16       d2,  d2
    677        vpadd.u16       d2,  d2
    678        cmp             r4,  #16
    679        vadd.s16        d0,  d0,  d2
    680        vshl.u16        d0,  d0,  d28
    681        beq             1f
    682        // h = 4/8/32/64
    683        tst             r4,  #(32+16+8)     // 16 added to make a consecutive bitmask
    684        movw            lr,  #(0x3334/2)
    685        movw            r5,  #(0x5556/2)
    686        it              ne
    687        movne           lr,  r5
    688        vdup.16         d24, lr
    689        vqdmulh.s16     d0,  d0,  d24
    690 1:
    691        vdup.8          q0,  d0[0]
    692 2:
    693        vst1.8          {d0,  d1},  [r0,  :128], r1
    694        vst1.8          {d0,  d1},  [r12, :128], r1
    695        subs            r4,  r4, #4
    696        vst1.8          {d0,  d1},  [r0,  :128], r1
    697        vst1.8          {d0,  d1},  [r12, :128], r1
    698        bgt             2b
    699        pop             {r4-r6, pc}
    700 
    701 L(ipred_dc_h32):
    702        vld1.8          {d0,  d1,  d2,  d3},  [r2, :128]!
    703        vaddl.u8        q0,  d0,  d1
    704        vaddl.u8        q1,  d2,  d3
    705        vadd.u16        q0,  q0,  q1
    706        vadd.u16        d0,  d0,  d1
    707        vpadd.u16       d0,  d0
    708        add             r2,  r2,  #1
    709        vpadd.u16       d0,  d0
    710        bx              r3
    711 L(ipred_dc_w32):
    712        vld1.8          {d2,  d3,  d4,  d5},  [r2]
    713        vadd.s16        d0,  d0,  d30
    714        vaddl.u8        q1,  d2,  d3
    715        vaddl.u8        q2,  d4,  d5
    716        vadd.u16        q1,  q1,  q2
    717        vadd.u16        d2,  d2,  d3
    718        vpadd.u16       d2,  d2
    719        vpadd.u16       d2,  d2
    720        cmp             r4,  #32
    721        vadd.s16        d0,  d0,  d2
    722        vshl.u16        d4,  d0,  d28
    723        beq             1f
    724        // h = 8/16/64
    725        cmp             r4,  #8
    726        movw            lr,  #(0x3334/2)
    727        movw            r5,  #(0x5556/2)
    728        it              ne
    729        movne           lr,  r5
    730        vdup.16         d24, lr
    731        vqdmulh.s16     d4,  d4,  d24
    732 1:
    733        vdup.8          q0,  d4[0]
    734        vdup.8          q1,  d4[0]
    735 2:
    736        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    737        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    738        subs            r4,  r4,  #4
    739        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    740        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    741        bgt             2b
    742        pop             {r4-r6, pc}
    743 
    744 L(ipred_dc_h64):
    745        vld1.8          {d0,  d1,  d2,  d3},  [r2, :128]!
    746        vaddl.u8        q0,  d0,  d1
    747        vld1.8          {d4,  d5,  d6,  d7},  [r2, :128]!
    748        vaddl.u8        q1,  d2,  d3
    749        vaddl.u8        q2,  d4,  d5
    750        vaddl.u8        q3,  d6,  d7
    751        vadd.u16        q0,  q0,  q1
    752        vadd.u16        q1,  q2,  q3
    753        vadd.u16        q0,  q0,  q1
    754        vadd.u16        d0,  d0,  d1
    755        vpadd.u16       d0,  d0
    756        add             r2,  r2,  #1
    757        vpadd.u16       d0,  d0
    758        bx              r3
    759 L(ipred_dc_w64):
    760        vld1.8          {d2,  d3,  d4,  d5},  [r2]!
    761        vadd.s16        d0,  d0,  d30
    762        vaddl.u8        q2,  d4,  d5
    763        vaddl.u8        q1,  d2,  d3
    764        vadd.u16        d4,  d4,  d5
    765        vadd.u16        d2,  d2,  d3
    766        vld1.8          {d16, d17, d18, d19}, [r2]
    767        vpadd.u16       d4,  d4
    768        vpadd.u16       d2,  d2
    769        vpadd.u16       d4,  d4
    770        vpadd.u16       d2,  d2
    771        vaddl.u8        q8,  d16, d17
    772        vaddl.u8        q9,  d18, d19
    773        vadd.u16        d16, d16, d17
    774        vadd.u16        d18, d18, d19
    775        vpadd.u16       d16, d16
    776        vpadd.u16       d18, d18
    777        vpadd.u16       d16, d16
    778        vpadd.u16       d18, d18
    779        vadd.u16        d2,  d2,  d4
    780        vadd.u16        d3,  d16, d18
    781        cmp             r4,  #64
    782        vadd.s16        d0,  d0,  d2
    783        vadd.s16        d0,  d0,  d3
    784        vshl.u16        d18, d0,  d28
    785        beq             1f
    786        // h = 16/32
    787        movw            lr,  #(0x5556/2)
    788        movt            lr,  #(0x3334/2)
    789        and             r5,  r4,  #31
    790        lsr             lr,  lr,  r5
    791        vdup.16         d30, lr
    792        vqdmulh.s16     d18, d18, d30
    793 1:
    794        sub             r1,  r1,  #32
    795        vdup.8          q0,  d18[0]
    796        vdup.8          q1,  d18[0]
    797 2:
    798        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
    799        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
    800        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    801        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    802        subs            r4,  r4,  #4
    803        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
    804        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
    805        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
    806        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
    807        bgt             2b
    808        pop             {r4-r6, pc}
    809 endfunc
    810 
    811 // void ipred_paeth_8bpc_neon(pixel *dst, const ptrdiff_t stride,
    812 //                            const pixel *const topleft,
    813 //                            const int width, const int height, const int a,
    814 //                            const int max_width, const int max_height);
    815 function ipred_paeth_8bpc_neon, export=1
    816        push            {r4-r8, lr}
    817        ldr             r4,  [sp, #24]
    818        clz             lr,  r3
    819        adr             r5,  L(ipred_paeth_tbl)
    820        sub             lr,  lr,  #25
    821        ldr             lr,  [r5, lr, lsl #2]
    822        vld1.8          {d4[], d5[]},  [r2]
    823        add             r8,  r2,  #1
    824        sub             r2,  r2,  #4
    825        add             r5,  r5,  lr
    826        mov             r7,  #-4
    827        add             r6,  r0,  r1
    828        lsl             r1,  r1,  #1
    829        bx              r5
    830 
    831        .align 2
    832 L(ipred_paeth_tbl):
    833        .word 640f - L(ipred_paeth_tbl) + CONFIG_THUMB
    834        .word 320f - L(ipred_paeth_tbl) + CONFIG_THUMB
    835        .word 160f - L(ipred_paeth_tbl) + CONFIG_THUMB
    836        .word 80f  - L(ipred_paeth_tbl) + CONFIG_THUMB
    837        .word 40f  - L(ipred_paeth_tbl) + CONFIG_THUMB
    838 
    839 40:
    840        vld1.32         {d6[], d7[]},  [r8]
    841        vsubl.u8        q8,  d6,  d4  // top - topleft
    842 4:
    843        vld4.8          {d0[], d1[], d2[], d3[]},  [r2, :32], r7
    844        vzip.32         d0,  d1
    845        vzip.32         d2,  d3
    846        vaddw.u8        q9,  q8,  d0
    847        vaddw.u8        q10, q8,  d2
    848        vqmovun.s16     d18, q9       // base
    849        vqmovun.s16     d19, q10
    850        vmov            d1,  d2
    851        vabd.u8         q10, q3,  q9  // tdiff
    852        vabd.u8         q11, q2,  q9  // tldiff
    853        vabd.u8         q9,  q0,  q9  // ldiff
    854        vmin.u8         q12, q10, q11 // min(tdiff, tldiff)
    855        vcge.u8         q10, q11, q10 // tldiff >= tdiff
    856        vcge.u8         q9,  q12, q9  // min(tdiff, tldiff) >= ldiff
    857        vbsl            q10, q3,  q2  // tdiff <= tldiff ? top : topleft
    858        vbit            q10, q0,  q9  // ldiff <= min ? left : ...
    859        vst1.32         {d21[1]}, [r0, :32], r1
    860        vst1.32         {d21[0]}, [r6, :32], r1
    861        subs            r4,  r4,  #4
    862        vst1.32         {d20[1]}, [r0, :32], r1
    863        vst1.32         {d20[0]}, [r6, :32], r1
    864        bgt             4b
    865        pop             {r4-r8, pc}
    866 80:
    867        vld1.8          {d6},  [r8]
    868        vsubl.u8        q8,  d6,  d4  // top - topleft
    869        vmov            d7,  d6
    870 8:
    871        vld4.8          {d0[], d1[], d2[], d3[]},  [r2, :32], r7
    872        vaddw.u8        q9,  q8,  d0
    873        vaddw.u8        q10, q8,  d1
    874        vaddw.u8        q11, q8,  d2
    875        vaddw.u8        q12, q8,  d3
    876        vqmovun.s16     d18, q9       // base
    877        vqmovun.s16     d19, q10
    878        vqmovun.s16     d20, q11
    879        vqmovun.s16     d21, q12
    880        vabd.u8         q11, q3,  q9  // tdiff
    881        vabd.u8         q12, q3,  q10
    882        vabd.u8         q13, q2,  q9  // tldiff
    883        vabd.u8         q14, q2,  q10
    884        vabd.u8         q10, q1,  q10 // ldiff
    885        vabd.u8         q9,  q0,  q9
    886        vmin.u8         q15, q12, q14 // min(tdiff, tldiff)
    887        vcge.u8         q12, q14, q12 // tldiff >= tdiff
    888        vmin.u8         q14, q11, q13 // min(tdiff, tldiff)
    889        vcge.u8         q11, q13, q11 // tldiff >= tdiff
    890        vcge.u8         q10, q15, q10 // min(tdiff, tldiff) >= ldiff
    891        vcge.u8         q9,  q14, q9
    892        vbsl            q12, q3,  q2  // tdiff <= tldiff ? top : topleft
    893        vbsl            q11, q3,  q2
    894        vbit            q12, q1,  q10 // ldiff <= min ? left : ...
    895        vbit            q11, q0,  q9
    896        vst1.8          {d25}, [r0, :64], r1
    897        vst1.8          {d24}, [r6, :64], r1
    898        subs            r4,  r4,  #4
    899        vst1.8          {d23}, [r0, :64], r1
    900        vst1.8          {d22}, [r6, :64], r1
    901        bgt             8b
    902        pop             {r4-r8, pc}
    903 160:
    904 320:
    905 640:
    906        vld1.8          {d6},  [r8]!
    907        mov             r12, r3
    908        // Set up pointers for four rows in parallel; r0, r6, r5, lr
    909        add             r5,  r0,  r1
    910        add             lr,  r6,  r1
    911        lsl             r1,  r1,  #1
    912        sub             r1,  r1,  r3
    913 1:
    914        vld4.8          {d0[], d1[], d2[], d3[]},  [r2, :32], r7
    915 2:
    916        vsubl.u8        q8,  d6,  d4  // top - topleft
    917        vmov            d7,  d6
    918        vaddw.u8        q9,  q8,  d0
    919        vaddw.u8        q10, q8,  d1
    920        vaddw.u8        q11, q8,  d2
    921        vaddw.u8        q12, q8,  d3
    922        vqmovun.s16     d18, q9       // base
    923        vqmovun.s16     d19, q10
    924        vqmovun.s16     d20, q11
    925        vqmovun.s16     d21, q12
    926        vabd.u8         q11, q3,  q9  // tdiff
    927        vabd.u8         q12, q3,  q10
    928        vabd.u8         q13, q2,  q9  // tldiff
    929        vabd.u8         q14, q2,  q10
    930        vabd.u8         q10, q1,  q10 // ldiff
    931        vabd.u8         q9,  q0,  q9
    932        vmin.u8         q15, q12, q14 // min(tdiff, tldiff)
    933        vcge.u8         q12, q14, q12 // tldiff >= tdiff
    934        vmin.u8         q14, q11, q13 // min(tdiff, tldiff)
    935        vcge.u8         q11, q13, q11 // tldiff >= tdiff
    936        vcge.u8         q10, q15, q10 // min(tdiff, tldiff) >= ldiff
    937        vcge.u8         q9,  q14, q9
    938        vbsl            q12, q3,  q2  // tdiff <= tldiff ? top : topleft
    939        vbsl            q11, q3,  q2
    940        vbit            q12, q1,  q10 // ldiff <= min ? left : ...
    941        vbit            q11, q0,  q9
    942        subs            r3,  r3,  #8
    943        vst1.8          {d25}, [r0, :64]!
    944        vst1.8          {d24}, [r6, :64]!
    945        vst1.8          {d23}, [r5, :64]!
    946        vst1.8          {d22}, [lr, :64]!
    947        ble             8f
    948        vld1.8          {d6},  [r8]!
    949        b               2b
    950 8:
    951        subs            r4,  r4,  #4
    952        ble             9f
    953        // End of horizontal loop, move pointers to next four rows
    954        sub             r8,  r8,  r12
    955        add             r0,  r0,  r1
    956        add             r6,  r6,  r1
    957        vld1.8          {d6},  [r8]!
    958        add             r5,  r5,  r1
    959        add             lr,  lr,  r1
    960        mov             r3,  r12
    961        b               1b
    962 9:
    963        pop             {r4-r8, pc}
    964 endfunc
    965 
    966 // void ipred_smooth_8bpc_neon(pixel *dst, const ptrdiff_t stride,
    967 //                             const pixel *const topleft,
    968 //                             const int width, const int height, const int a,
    969 //                             const int max_width, const int max_height);
    970 function ipred_smooth_8bpc_neon, export=1
    971        push            {r4-r10, lr}
    972        ldr             r4,  [sp, #32]
    973        movrel          r10, X(sm_weights)
    974        add             r12, r10, r4
    975        add             r10, r10, r3
    976        clz             r9,  r3
    977        adr             r5,  L(ipred_smooth_tbl)
    978        sub             lr,  r2,  r4
    979        sub             r9,  r9,  #25
    980        ldr             r9,  [r5, r9, lsl #2]
    981        vld1.8          {d4[]},  [lr] // bottom
    982        add             r8,  r2,  #1
    983        add             r5,  r5,  r9
    984        add             r6,  r0,  r1
    985        lsl             r1,  r1,  #1
    986        bx              r5
    987 
    988        .align 2
    989 L(ipred_smooth_tbl):
    990        .word 640f - L(ipred_smooth_tbl) + CONFIG_THUMB
    991        .word 320f - L(ipred_smooth_tbl) + CONFIG_THUMB
    992        .word 160f - L(ipred_smooth_tbl) + CONFIG_THUMB
    993        .word 80f  - L(ipred_smooth_tbl) + CONFIG_THUMB
    994        .word 40f  - L(ipred_smooth_tbl) + CONFIG_THUMB
    995 
    996 40:
    997        vld1.32         {d16[]}, [r8]       // top
    998        vld1.32         {d18[]}, [r10, :32] // weights_hor
    999        sub             r2,  r2,  #4
   1000        mov             r7,  #-4
   1001        vdup.8          q3,  d16[3]   // right
   1002        vsubl.u8        q8,  d16, d4  // top-bottom
   1003        vmovl.u8        q9,  d18      // weights_hor
   1004 4:
   1005        vld4.8          {d0[],  d1[],  d2[],  d3[]},  [r2,  :32], r7 // left
   1006        vld4.8          {d20[], d21[], d22[], d23[]}, [r12, :32]!    // weights_ver
   1007        vshll.i8        q12, d6,  #8  // right*256
   1008        vshll.i8        q13, d6,  #8
   1009        vzip.32         d1,  d0       // left, flipped
   1010        vzip.32         d3,  d2
   1011        vzip.32         d20, d21      // weights_ver
   1012        vzip.32         d22, d23
   1013        vshll.i8        q14, d4,  #8  // bottom*256
   1014        vshll.i8        q15, d4,  #8
   1015        vsubl.u8        q0,  d1,  d6  // left-right
   1016        vsubl.u8        q1,  d3,  d6
   1017        vmovl.u8        q10, d20      // weights_ver
   1018        vmovl.u8        q11, d22
   1019        vmla.i16        q12, q1,  q9  // right*256  + (left-right)*weights_hor
   1020        vmla.i16        q13, q0,  q9  // (left flipped)
   1021        vmla.i16        q14, q8,  q10 // bottom*256 + (top-bottom)*weights_ver
   1022        vmla.i16        q15, q8,  q11
   1023        vhadd.u16       q12, q12, q14
   1024        vhadd.u16       q13, q13, q15
   1025        vrshrn.i16      d24, q12, #8
   1026        vrshrn.i16      d25, q13, #8
   1027        vst1.32         {d24[0]}, [r0, :32], r1
   1028        vst1.32         {d24[1]}, [r6, :32], r1
   1029        subs            r4,  r4,  #4
   1030        vst1.32         {d25[0]}, [r0, :32], r1
   1031        vst1.32         {d25[1]}, [r6, :32], r1
   1032        bgt             4b
   1033        pop             {r4-r10, pc}
   1034 80:
   1035        vld1.8          {d16}, [r8]       // top
   1036        vld1.8          {d18}, [r10, :64] // weights_hor
   1037        sub             r2,  r2,  #2
   1038        mov             r7,  #-2
   1039        vdup.8          q3,  d16[7]   // right
   1040        vsubl.u8        q8,  d16, d4  // top-bottom
   1041        vmovl.u8        q9,  d18      // weights_hor
   1042 8:
   1043        vld2.8          {d0[],  d1[]},  [r2,  :16], r7 // left
   1044        vld2.8          {d20[], d22[]}, [r12, :16]!    // weights_ver
   1045        vshll.i8        q12, d6,  #8  // right*256
   1046        vshll.i8        q13, d6,  #8
   1047        vshll.i8        q14, d4,  #8  // bottom*256
   1048        vshll.i8        q15, d4,  #8
   1049        vsubl.u8        q1,  d0,  d6  // left-right (left flipped)
   1050        vsubl.u8        q0,  d1,  d6
   1051        vmovl.u8        q10, d20      // weights_ver
   1052        vmovl.u8        q11, d22
   1053        vmla.i16        q12, q0,  q9  // right*256  + (left-right)*weights_hor
   1054        vmla.i16        q13, q1,  q9
   1055        vmla.i16        q14, q8,  q10 // bottom*256 + (top-bottom)*weights_ver
   1056        vmla.i16        q15, q8,  q11
   1057        vhadd.u16       q12, q12, q14
   1058        vhadd.u16       q13, q13, q15
   1059        vrshrn.i16      d24, q12, #8
   1060        vrshrn.i16      d25, q13, #8
   1061        subs            r4,  r4,  #2
   1062        vst1.8          {d24}, [r0, :64], r1
   1063        vst1.8          {d25}, [r6, :64], r1
   1064        bgt             8b
   1065        pop             {r4-r10, pc}
   1066 160:
   1067 320:
   1068 640:
   1069        add             lr,  r2,  r3
   1070        sub             r2,  r2,  #2
   1071        mov             r7,  #-2
   1072        vld1.8          {d6[], d7[]}, [lr] // right
   1073        sub             r1,  r1,  r3
   1074        mov             r9,  r3
   1075 
   1076 1:
   1077        vld2.8          {d0[],  d1[]},  [r2,  :16], r7 // left
   1078        vld2.8          {d20[], d22[]}, [r12, :16]!    // weights_ver
   1079        vsubl.u8        q1,  d0,  d6  // left-right (left flipped)
   1080        vsubl.u8        q0,  d1,  d6
   1081        vmovl.u8        q10, d20      // weights_ver
   1082        vmovl.u8        q11, d22
   1083 2:
   1084        vld1.8          {d16}, [r8]!       // top
   1085        vld1.8          {d18}, [r10, :64]! // weights_hor
   1086        vshll.i8        q12, d6,  #8  // right*256
   1087        vshll.i8        q13, d6,  #8
   1088        vmovl.u8        q9,  d18      // weights_hor
   1089        vshll.i8        q14, d4,  #8  // bottom*256
   1090        vshll.i8        q15, d4,  #8
   1091        vsubl.u8        q8,  d16, d4  // top-bottom
   1092        vmla.i16        q12, q0,  q9  // right*256  + (left-right)*weights_hor
   1093        vmla.i16        q13, q1,  q9
   1094        vmla.i16        q14, q8,  q10 // bottom*256 + (top-bottom)*weights_ver
   1095        vmla.i16        q15, q8,  q11
   1096        vhadd.u16       q12, q12, q14
   1097        vhadd.u16       q13, q13, q15
   1098        vrshrn.i16      d24, q12, #8
   1099        vrshrn.i16      d25, q13, #8
   1100        subs            r3,  r3,  #8
   1101        vst1.8          {d24}, [r0, :64]!
   1102        vst1.8          {d25}, [r6, :64]!
   1103        bgt             2b
   1104        subs            r4,  r4,  #2
   1105        ble             9f
   1106        sub             r8,  r8,  r9
   1107        sub             r10, r10, r9
   1108        add             r0,  r0,  r1
   1109        add             r6,  r6,  r1
   1110        mov             r3,  r9
   1111        b               1b
   1112 9:
   1113        pop             {r4-r10, pc}
   1114 endfunc
   1115 
   1116 // void ipred_smooth_v_8bpc_neon(pixel *dst, const ptrdiff_t stride,
   1117 //                               const pixel *const topleft,
   1118 //                               const int width, const int height, const int a,
   1119 //                               const int max_width, const int max_height);
   1120 function ipred_smooth_v_8bpc_neon, export=1
   1121        push            {r4-r7, lr}
   1122        ldr             r4,  [sp, #20]
   1123        movrel          r7,  X(sm_weights)
   1124        add             r7,  r7,  r4
   1125        clz             lr,  r3
   1126        adr             r5,  L(ipred_smooth_v_tbl)
   1127        sub             r12, r2,  r4
   1128        sub             lr,  lr,  #25
   1129        ldr             lr,  [r5, lr, lsl #2]
   1130        vld1.8          {d4[]},  [r12] // bottom
   1131        add             r2,  r2,  #1
   1132        add             r5,  r5,  lr
   1133        add             r6,  r0,  r1
   1134        lsl             r1,  r1,  #1
   1135        bx              r5
   1136 
   1137        .align 2
   1138 L(ipred_smooth_v_tbl):
   1139        .word 640f - L(ipred_smooth_v_tbl) + CONFIG_THUMB
   1140        .word 320f - L(ipred_smooth_v_tbl) + CONFIG_THUMB
   1141        .word 160f - L(ipred_smooth_v_tbl) + CONFIG_THUMB
   1142        .word 80f  - L(ipred_smooth_v_tbl) + CONFIG_THUMB
   1143        .word 40f  - L(ipred_smooth_v_tbl) + CONFIG_THUMB
   1144 
   1145 40:
   1146        vld1.32         {d6[]}, [r2]  // top
   1147        vsubl.u8        q3,  d6,  d4  // top-bottom
   1148 4:
   1149        vld4.8          {d16[], d17[], d18[], d19[]}, [r7, :32]! // weights_ver
   1150        vshll.i8        q10, d4,  #8  // bottom*256
   1151        vshll.i8        q11, d4,  #8
   1152        vzip.32         d16, d17      // weights_ver
   1153        vzip.32         d18, d19
   1154        vmovl.u8        q8,  d16      // weights_ver
   1155        vmovl.u8        q9,  d18
   1156        subs            r4,  r4,  #4
   1157        vmla.i16        q10, q3,  q8  // bottom*256 + (top-bottom)*weights_ver
   1158        vmla.i16        q11, q3,  q9
   1159        vrshrn.i16      d20, q10, #8
   1160        vrshrn.i16      d21, q11, #8
   1161        vst1.32         {d20[0]}, [r0, :32], r1
   1162        vst1.32         {d20[1]}, [r6, :32], r1
   1163        vst1.32         {d21[0]}, [r0, :32], r1
   1164        vst1.32         {d21[1]}, [r6, :32], r1
   1165        bgt             4b
   1166        pop             {r4-r7, pc}
   1167 80:
   1168        vld1.8          {d6}, [r2]    // top
   1169        vsubl.u8        q3,  d6,  d4  // top-bottom
   1170 8:
   1171        vld4.8          {d16[], d18[], d20[], d22[]}, [r7, :32]! // weights_ver
   1172        vshll.i8        q12, d4,  #8  // bottom*256
   1173        vshll.i8        q13, d4,  #8
   1174        vshll.i8        q14, d4,  #8
   1175        vshll.i8        q15, d4,  #8
   1176        vmovl.u8        q8,  d16      // weights_ver
   1177        vmovl.u8        q9,  d18
   1178        vmovl.u8        q10, d20
   1179        vmovl.u8        q11, d22
   1180        vmla.i16        q12, q3,  q8  // bottom*256 + (top-bottom)*weights_ver
   1181        vmla.i16        q13, q3,  q9
   1182        vmla.i16        q14, q3,  q10
   1183        vmla.i16        q15, q3,  q11
   1184        vrshrn.i16      d24, q12, #8
   1185        vrshrn.i16      d25, q13, #8
   1186        vrshrn.i16      d26, q14, #8
   1187        vrshrn.i16      d27, q15, #8
   1188        vst1.8          {d24}, [r0, :64], r1
   1189        vst1.8          {d25}, [r6, :64], r1
   1190        subs            r4,  r4,  #4
   1191        vst1.8          {d26}, [r0, :64], r1
   1192        vst1.8          {d27}, [r6, :64], r1
   1193        bgt             8b
   1194        pop             {r4-r7, pc}
   1195 160:
   1196 320:
   1197 640:
   1198        vpush           {q4-q7}
   1199        // Set up pointers for four rows in parallel; r0, r6, r5, lr
   1200        add             r5,  r0,  r1
   1201        add             lr,  r6,  r1
   1202        lsl             r1,  r1,  #1
   1203        sub             r1,  r1,  r3
   1204        mov             r12, r3
   1205 
   1206 1:
   1207        vld4.8          {d8[], d10[], d12[], d14[]}, [r7, :32]! // weights_ver
   1208        vmovl.u8        q4,  d8       // weights_ver
   1209        vmovl.u8        q5,  d10
   1210        vmovl.u8        q6,  d12
   1211        vmovl.u8        q7,  d14
   1212 2:
   1213        vld1.8          {q3}, [r2]!   // top
   1214        vshll.i8        q8,  d4,  #8  // bottom*256
   1215        vshll.i8        q9,  d4,  #8
   1216        vshll.i8        q10, d4,  #8
   1217        vshll.i8        q11, d4,  #8
   1218        vsubl.u8        q0,  d6,  d4  // top-bottom
   1219        vsubl.u8        q1,  d7,  d4
   1220        vshll.i8        q12, d4,  #8
   1221        vshll.i8        q13, d4,  #8
   1222        vshll.i8        q14, d4,  #8
   1223        vshll.i8        q15, d4,  #8
   1224        vmla.i16        q8,  q0,  q4  // bottom*256 + (top-bottom)*weights_ver
   1225        vmla.i16        q9,  q1,  q4
   1226        vmla.i16        q10, q0,  q5
   1227        vmla.i16        q11, q1,  q5
   1228        vmla.i16        q12, q0,  q6  // bottom*256 + (top-bottom)*weights_ver
   1229        vmla.i16        q13, q1,  q6
   1230        vmla.i16        q14, q0,  q7
   1231        vmla.i16        q15, q1,  q7
   1232        vrshrn.i16      d16, q8,  #8
   1233        vrshrn.i16      d17, q9,  #8
   1234        vrshrn.i16      d18, q10, #8
   1235        vrshrn.i16      d19, q11, #8
   1236        vrshrn.i16      d20, q12, #8
   1237        vrshrn.i16      d21, q13, #8
   1238        vrshrn.i16      d22, q14, #8
   1239        vrshrn.i16      d23, q15, #8
   1240        subs            r3,  r3,  #16
   1241        vst1.8          {q8},  [r0, :128]!
   1242        vst1.8          {q9},  [r6, :128]!
   1243        vst1.8          {q10}, [r5, :128]!
   1244        vst1.8          {q11}, [lr, :128]!
   1245        bgt             2b
   1246        subs            r4,  r4,  #4
   1247        ble             9f
   1248        sub             r2,  r2,  r12
   1249        add             r0,  r0,  r1
   1250        add             r6,  r6,  r1
   1251        add             r5,  r5,  r1
   1252        add             lr,  lr,  r1
   1253        mov             r3,  r12
   1254        b               1b
   1255 9:
   1256        vpop            {q4-q7}
   1257        pop             {r4-r7, pc}
   1258 endfunc
   1259 
   1260 // void ipred_smooth_h_8bpc_neon(pixel *dst, const ptrdiff_t stride,
   1261 //                               const pixel *const topleft,
   1262 //                               const int width, const int height, const int a,
   1263 //                               const int max_width, const int max_height);
   1264 function ipred_smooth_h_8bpc_neon, export=1
   1265        push            {r4-r8, lr}
   1266        ldr             r4,  [sp, #24]
   1267        movrel          r8,  X(sm_weights)
   1268        add             r8,  r8,  r3
   1269        clz             lr,  r3
   1270        adr             r5,  L(ipred_smooth_h_tbl)
   1271        add             r12, r2,  r3
   1272        sub             lr,  lr,  #25
   1273        ldr             lr,  [r5, lr, lsl #2]
   1274        vld1.8          {d4[]},  [r12] // right
   1275        add             r5,  r5,  lr
   1276        add             r6,  r0,  r1
   1277        lsl             r1,  r1,  #1
   1278        bx              r5
   1279 
   1280        .align 2
   1281 L(ipred_smooth_h_tbl):
   1282        .word 640f - L(ipred_smooth_h_tbl) + CONFIG_THUMB
   1283        .word 320f - L(ipred_smooth_h_tbl) + CONFIG_THUMB
   1284        .word 160f - L(ipred_smooth_h_tbl) + CONFIG_THUMB
   1285        .word 80f  - L(ipred_smooth_h_tbl) + CONFIG_THUMB
   1286        .word 40f  - L(ipred_smooth_h_tbl) + CONFIG_THUMB
   1287 
   1288 40:
   1289        vld1.32         {d6[]}, [r8, :32] // weights_hor
   1290        sub             r2,  r2,  #4
   1291        mov             r7,  #-4
   1292        vmovl.u8        q3,  d6       // weights_hor
   1293 4:
   1294        vld4.8          {d0[], d1[], d2[], d3[]},  [r2, :32], r7 // left
   1295        vshll.i8        q8,  d4,  #8  // right*256
   1296        vshll.i8        q9,  d4,  #8
   1297        vzip.32         d3,  d2       // left, flipped
   1298        vzip.32         d1,  d0
   1299        vsubl.u8        q1,  d3,  d4  // left-right
   1300        vsubl.u8        q0,  d1,  d4
   1301        subs            r4,  r4,  #4
   1302        vmla.i16        q8,  q1,  q3  // right*256  + (left-right)*weights_hor
   1303        vmla.i16        q9,  q0,  q3
   1304        vrshrn.i16      d16, q8,  #8
   1305        vrshrn.i16      d17, q9,  #8
   1306        vst1.32         {d16[0]}, [r0, :32], r1
   1307        vst1.32         {d16[1]}, [r6, :32], r1
   1308        vst1.32         {d17[0]}, [r0, :32], r1
   1309        vst1.32         {d17[1]}, [r6, :32], r1
   1310        bgt             4b
   1311        pop             {r4-r8, pc}
   1312 80:
   1313        vld1.8          {d6}, [r8, :64] // weights_hor
   1314        sub             r2,  r2,  #4
   1315        mov             r7,  #-4
   1316        vmovl.u8        q3,  d6       // weights_hor
   1317 8:
   1318        vld4.8          {d16[], d18[], d20[], d22[]},  [r2, :32], r7 // left
   1319        vshll.i8        q12, d4,  #8  // right*256
   1320        vshll.i8        q13, d4,  #8
   1321        vshll.i8        q14, d4,  #8
   1322        vshll.i8        q15, d4,  #8
   1323        vsubl.u8        q11, d22, d4  // left-right
   1324        vsubl.u8        q10, d20, d4
   1325        vsubl.u8        q9,  d18, d4
   1326        vsubl.u8        q8,  d16, d4
   1327        vmla.i16        q12, q11, q3  // right*256  + (left-right)*weights_hor
   1328        vmla.i16        q13, q10, q3  // (left flipped)
   1329        vmla.i16        q14, q9,  q3
   1330        vmla.i16        q15, q8,  q3
   1331        vrshrn.i16      d24, q12, #8
   1332        vrshrn.i16      d25, q13, #8
   1333        vrshrn.i16      d26, q14, #8
   1334        vrshrn.i16      d27, q15, #8
   1335        vst1.8          {d24}, [r0, :64], r1
   1336        vst1.8          {d25}, [r6, :64], r1
   1337        subs            r4,  r4,  #4
   1338        vst1.8          {d26}, [r0, :64], r1
   1339        vst1.8          {d27}, [r6, :64], r1
   1340        bgt             8b
   1341        pop             {r4-r8, pc}
   1342 160:
   1343 320:
   1344 640:
   1345        vpush           {q4-q7}
   1346        sub             r2,  r2,  #4
   1347        mov             r7,  #-4
   1348        // Set up pointers for four rows in parallel; r0, r6, r5, lr
   1349        add             r5,  r0,  r1
   1350        add             lr,  r6,  r1
   1351        lsl             r1,  r1,  #1
   1352        sub             r1,  r1,  r3
   1353        mov             r12, r3
   1354 
   1355 1:
   1356        vld4.8          {d8[], d10[], d12[], d14[]},  [r2, :32], r7 // left
   1357        vsubl.u8        q4,  d8,  d4  // left-right
   1358        vsubl.u8        q5,  d10, d4
   1359        vsubl.u8        q6,  d12, d4
   1360        vsubl.u8        q7,  d14, d4
   1361 2:
   1362        vld1.8          {q1}, [r8, :128]! // weights_hor
   1363        vshll.i8        q8,  d4,  #8  // right*256
   1364        vshll.i8        q9,  d4,  #8
   1365        vshll.i8        q10, d4,  #8
   1366        vshll.i8        q11, d4,  #8
   1367        vmovl.u8        q0,  d2       // weights_hor
   1368        vmovl.u8        q1,  d3
   1369        vshll.i8        q12, d4,  #8
   1370        vshll.i8        q13, d4,  #8
   1371        vshll.i8        q14, d4,  #8
   1372        vshll.i8        q15, d4,  #8
   1373        vmla.i16        q8,  q7,  q0  // right*256  + (left-right)*weights_hor
   1374        vmla.i16        q9,  q7,  q1  // (left flipped)
   1375        vmla.i16        q10, q6,  q0
   1376        vmla.i16        q11, q6,  q1
   1377        vmla.i16        q12, q5,  q0
   1378        vmla.i16        q13, q5,  q1
   1379        vmla.i16        q14, q4,  q0
   1380        vmla.i16        q15, q4,  q1
   1381        vrshrn.i16      d16, q8,  #8
   1382        vrshrn.i16      d17, q9,  #8
   1383        vrshrn.i16      d18, q10, #8
   1384        vrshrn.i16      d19, q11, #8
   1385        vrshrn.i16      d20, q12, #8
   1386        vrshrn.i16      d21, q13, #8
   1387        vrshrn.i16      d22, q14, #8
   1388        vrshrn.i16      d23, q15, #8
   1389        subs            r3,  r3,  #16
   1390        vst1.8          {q8},  [r0, :128]!
   1391        vst1.8          {q9},  [r6, :128]!
   1392        vst1.8          {q10}, [r5, :128]!
   1393        vst1.8          {q11}, [lr, :128]!
   1394        bgt             2b
   1395        subs            r4,  r4,  #4
   1396        ble             9f
   1397        sub             r8,  r8,  r12
   1398        add             r0,  r0,  r1
   1399        add             r6,  r6,  r1
   1400        add             r5,  r5,  r1
   1401        add             lr,  lr,  r1
   1402        mov             r3,  r12
   1403        b               1b
   1404 9:
   1405        vpop            {q4-q7}
   1406        pop             {r4-r8, pc}
   1407 endfunc
   1408 
   1409 // void ipred_filter_8bpc_neon(pixel *dst, const ptrdiff_t stride,
   1410 //                             const pixel *const topleft,
   1411 //                             const int width, const int height, const int filt_idx,
   1412 //                             const int max_width, const int max_height);
   1413 function ipred_filter_8bpc_neon, export=1
   1414        push            {r4-r8, lr}
   1415        movw            r12, #511
   1416        ldrd            r4,  r5,  [sp, #24]
   1417        and             r5,  r5,  r12 // 511
   1418        movrel          r6,  X(filter_intra_taps)
   1419        lsl             r5,  r5,  #6
   1420        add             r6,  r6,  r5
   1421        vld1.8          {d20, d21, d22, d23}, [r6, :128]!
   1422        clz             lr,  r3
   1423        adr             r5,  L(ipred_filter_tbl)
   1424        vld1.8          {d27, d28, d29}, [r6, :64]
   1425        sub             lr,  lr,  #26
   1426        ldr             lr,  [r5, lr, lsl #2]
   1427        vmovl.s8        q8,  d20
   1428        vmovl.s8        q9,  d21
   1429        add             r5,  r5,  lr
   1430        vmovl.s8        q10, d22
   1431        vmovl.s8        q11, d23
   1432        add             r6,  r0,  r1
   1433        lsl             r1,  r1,  #1
   1434        vmovl.s8        q12, d27
   1435        vmovl.s8        q13, d28
   1436        vmovl.s8        q14, d29
   1437        add             r8,  r2,  #1
   1438        sub             r2,  r2,  #2
   1439        mov             r7,  #-2
   1440        bx              r5
   1441 
   1442        .align 2
   1443 L(ipred_filter_tbl):
   1444        .word 320f - L(ipred_filter_tbl) + CONFIG_THUMB
   1445        .word 160f - L(ipred_filter_tbl) + CONFIG_THUMB
   1446        .word 80f  - L(ipred_filter_tbl) + CONFIG_THUMB
   1447        .word 40f  - L(ipred_filter_tbl) + CONFIG_THUMB
   1448 
   1449 40:
   1450        vld1.32         {d0[]}, [r8]     // top (0-3)
   1451        vmovl.u8        q0,  d0          // top (0-3)
   1452 4:
   1453        vld1.32         {d2[]}, [r2], r7 // left (0-1) + topleft (2)
   1454        vmul.i16        q2,  q9,  d0[0]  // p1(top[0]) * filter(1)
   1455        vmla.i16        q2,  q10, d0[1]  // p2(top[1]) * filter(2)
   1456        vmla.i16        q2,  q11, d0[2]  // p3(top[2]) * filter(3)
   1457        vmovl.u8        q1,  d2          // left (0-1) + topleft (2)
   1458        vmla.i16        q2,  q12, d0[3]  // p4(top[3]) * filter(4)
   1459        vmla.i16        q2,  q8,  d2[2]  // p0(topleft) * filter(0)
   1460        vmla.i16        q2,  q13, d2[1]  // p5(left[0]) * filter(5)
   1461        vmla.i16        q2,  q14, d2[0]  // p6(left[1]) * filter(6)
   1462        vqrshrun.s16    d4,  q2,  #4
   1463        subs            r4,  r4,  #2
   1464        vst1.32         {d4[0]}, [r0, :32], r1
   1465        vmovl.u8        q0,  d4
   1466        vst1.32         {d4[1]}, [r6, :32], r1
   1467        vmov            d0,  d1          // move top from [4-7] to [0-3]
   1468        bgt             4b
   1469        pop             {r4-r8, pc}
   1470 80:
   1471        vld1.8          {d0},  [r8]      // top (0-7)
   1472        vmovl.u8        q0,  d0          // top (0-7)
   1473 8:
   1474        vld1.32         {d2[]}, [r2], r7 // left (0-1) + topleft (2)
   1475        vmul.i16        q2,  q9,  d0[0]  // p1(top[0]) * filter(1)
   1476        vmla.i16        q2,  q10, d0[1]  // p2(top[1]) * filter(2)
   1477        vmla.i16        q2,  q11, d0[2]  // p3(top[2]) * filter(3)
   1478        vmovl.u8        q1,  d2          // left (0-1) + topleft (2)
   1479        vmla.i16        q2,  q12, d0[3]  // p4(top[3]) * filter(4)
   1480        vmla.i16        q2,  q8,  d2[2]  // p0(topleft) * filter(0)
   1481        vmla.i16        q2,  q13, d2[1]  // p5(left[0]) * filter(5)
   1482        vmla.i16        q2,  q14, d2[0]  // p6(left[1]) * filter(6)
   1483        vmul.i16        q3,  q9,  d1[0]  // p1(top[0]) * filter(1)
   1484        vmla.i16        q3,  q10, d1[1]  // p2(top[1]) * filter(2)
   1485        vmla.i16        q3,  q11, d1[2]  // p3(top[2]) * filter(3)
   1486        vqrshrun.s16    d4,  q2,  #4
   1487        vmovl.u8        q1,  d4          // first block, in 16 bit
   1488        vmla.i16        q3,  q12, d1[3]  // p4(top[3]) * filter(4)
   1489        vmla.i16        q3,  q8,  d0[3]  // p0(topleft) * filter(0)
   1490        vmla.i16        q3,  q13, d2[3]  // p5(left[0]) * filter(5)
   1491        vmla.i16        q3,  q14, d3[3]  // p6(left[1]) * filter(6)
   1492        vqrshrun.s16    d5,  q3,  #4
   1493        vzip.32         d4,  d5
   1494        subs            r4,  r4,  #2
   1495        vst1.8          {d4}, [r0, :64], r1
   1496        vmovl.u8        q0,  d5
   1497        vst1.8          {d5}, [r6, :64], r1
   1498        bgt             8b
   1499        pop             {r4-r8, pc}
   1500 160:
   1501 320:
   1502        vpush           {q4-q5}
   1503        sub             r1,  r1,  r3
   1504        mov             lr,  r3
   1505 
   1506 1:
   1507        vld1.32         {d0[]}, [r2], r7 // left (0-1) + topleft (2)
   1508        vmovl.u8        q0,  d0          // left (0-1) + topleft (2)
   1509 2:
   1510        vld1.8          {q2}, [r8]!      // top(0-15)
   1511        vmul.i16        q3,  q8,  d0[2]  // p0(topleft) * filter(0)
   1512        vmla.i16        q3,  q13, d0[1]  // p5(left[0]) * filter(5)
   1513        vmovl.u8        q1,  d4          // top(0-7)
   1514        vmovl.u8        q2,  d5          // top(8-15)
   1515        vmla.i16        q3,  q14, d0[0]  // p6(left[1]) * filter(6)
   1516        vmla.i16        q3,  q9,  d2[0]  // p1(top[0]) * filter(1)
   1517        vmla.i16        q3,  q10, d2[1]  // p2(top[1]) * filter(2)
   1518        vmla.i16        q3,  q11, d2[2]  // p3(top[2]) * filter(3)
   1519        vmla.i16        q3,  q12, d2[3]  // p4(top[3]) * filter(4)
   1520 
   1521        vmul.i16        q4,  q9,  d3[0]  // p1(top[0]) * filter(1)
   1522        vmla.i16        q4,  q10, d3[1]  // p2(top[1]) * filter(2)
   1523        vmla.i16        q4,  q11, d3[2]  // p3(top[2]) * filter(3)
   1524        vqrshrun.s16    d6,  q3,  #4
   1525        vmovl.u8        q0,  d6          // first block, in 16 bit
   1526        vmla.i16        q4,  q12, d3[3]  // p4(top[3]) * filter(4)
   1527        vmla.i16        q4,  q8,  d2[3]  // p0(topleft) * filter(0)
   1528        vmla.i16        q4,  q13, d0[3]  // p5(left[0]) * filter(5)
   1529        vmla.i16        q4,  q14, d1[3]  // p6(left[1]) * filter(6)
   1530 
   1531        vmul.i16        q5,  q9,  d4[0]  // p1(top[0]) * filter(1)
   1532        vmla.i16        q5,  q10, d4[1]  // p2(top[1]) * filter(2)
   1533        vmla.i16        q5,  q11, d4[2]  // p3(top[2]) * filter(3)
   1534        vqrshrun.s16    d7,  q4,  #4
   1535        vmovl.u8        q0,  d7          // second block, in 16 bit
   1536        vmla.i16        q5,  q12, d4[3]  // p4(top[3]) * filter(4)
   1537        vmla.i16        q5,  q8,  d3[3]  // p0(topleft) * filter(0)
   1538        vmla.i16        q5,  q13, d0[3]  // p5(left[0]) * filter(5)
   1539        vmla.i16        q5,  q14, d1[3]  // p6(left[1]) * filter(6)
   1540 
   1541        vmul.i16        q15, q9,  d5[0]  // p1(top[0]) * filter(1)
   1542        vmla.i16        q15, q10, d5[1]  // p2(top[1]) * filter(2)
   1543        vmla.i16        q15, q11, d5[2]  // p3(top[2]) * filter(3)
   1544        vqrshrun.s16    d8,  q5,  #4
   1545        vmovl.u8        q0,  d8          // third block, in 16 bit
   1546        vmov.u8         r12, d5[6]
   1547        vmla.i16        q15, q12, d5[3]  // p4(top[3]) * filter(4)
   1548        vmla.i16        q15, q8,  d4[3]  // p0(topleft) * filter(0)
   1549        vmla.i16        q15, q13, d0[3]  // p5(left[0]) * filter(5)
   1550        vmla.i16        q15, q14, d1[3]  // p6(left[1]) * filter(6)
   1551        vmov.8          d0[4], r12
   1552 
   1553        subs            r3,  r3,  #16
   1554        vqrshrun.s16    d9,  q15, #4
   1555 
   1556        vst4.32         {d6[0], d7[0], d8[0], d9[0]}, [r0, :128]!
   1557        vst4.32         {d6[1], d7[1], d8[1], d9[1]}, [r6, :128]!
   1558        ble             8f
   1559        vmov.u8         r12, d9[7]
   1560        vmov.8          d0[0], r12
   1561        vmov.u8         r12, d9[3]
   1562        vmov.8          d0[2], r12
   1563        b               2b
   1564 8:
   1565        subs            r4,  r4,  #2
   1566 
   1567        ble             9f
   1568        sub             r8,  r6,  lr
   1569        add             r0,  r0,  r1
   1570        add             r6,  r6,  r1
   1571        mov             r3,  lr
   1572        b               1b
   1573 9:
   1574        vpop            {q4-q5}
   1575        pop             {r4-r8, pc}
   1576 endfunc
   1577 
   1578 // void pal_pred_8bpc_neon(pixel *dst, const ptrdiff_t stride,
   1579 //                         const pixel *const pal, const uint8_t *idx,
   1580 //                         const int w, const int h);
   1581 function pal_pred_8bpc_neon, export=1
   1582        push            {r4-r5, lr}
   1583        ldrd            r4,  r5,  [sp, #12]
   1584        vld1.8          {d0}, [r2, :64]
   1585        clz             lr,  r4
   1586        adr             r12, L(pal_pred_tbl)
   1587        sub             lr,  lr,  #25
   1588        vmov.i8         q15, #7
   1589        ldr             lr,  [r12, lr, lsl #2]
   1590        add             r12, r12, lr
   1591        add             r2,  r0,  r1
   1592        bx              r12
   1593 
   1594        .align 2
   1595 L(pal_pred_tbl):
   1596        .word 640f - L(pal_pred_tbl) + CONFIG_THUMB
   1597        .word 320f - L(pal_pred_tbl) + CONFIG_THUMB
   1598        .word 160f - L(pal_pred_tbl) + CONFIG_THUMB
   1599        .word 80f  - L(pal_pred_tbl) + CONFIG_THUMB
   1600        .word 40f  - L(pal_pred_tbl) + CONFIG_THUMB
   1601 
   1602 40:
   1603        lsl             r1,  r1,  #1
   1604 4:
   1605        vld1.8          {d2}, [r3, :64]!
   1606        subs            r5,  r5,  #4
   1607        vshr.u8         d3,  d2,  #4
   1608        vand.u8         d2,  d2,  d30
   1609        vzip.8          d2,  d3
   1610        vtbl.8          d2, {d0}, d2
   1611        vtbl.8          d3, {d0}, d3
   1612        vst1.32         {d2[0]}, [r0, :32], r1
   1613        vst1.32         {d2[1]}, [r2, :32], r1
   1614        vst1.32         {d3[0]}, [r0, :32], r1
   1615        vst1.32         {d3[1]}, [r2, :32], r1
   1616        bgt             4b
   1617        pop             {r4-r5, pc}
   1618 80:
   1619        lsl             r1,  r1,  #1
   1620 8:
   1621        vld1.8          {q1}, [r3, :64]!
   1622        subs            r5,  r5,  #4
   1623        vshr.u8         q2,  q1,  #4
   1624        vand.u8         q1,  q1,  q15
   1625        vzip.8          q1,  q2
   1626        vtbl.8          d2, {d0}, d2
   1627        vtbl.8          d3, {d0}, d3
   1628        vst1.8          {d2}, [r0, :64], r1
   1629        vtbl.8          d4, {d0}, d4
   1630        vst1.8          {d3}, [r2, :64], r1
   1631        vtbl.8          d5, {d0}, d5
   1632        vst1.8          {d4}, [r0, :64], r1
   1633        vst1.8          {d5}, [r2, :64], r1
   1634        bgt             8b
   1635        pop             {r4-r5, pc}
   1636 160:
   1637        lsl             r1,  r1,  #1
   1638 16:
   1639        vld1.8          {q10, q11}, [r3, :64]!
   1640        subs            r5,  r5,  #4
   1641        vand.u8         q8,  q10, q15
   1642        vshr.u8         q9,  q10, #4
   1643        vand.u8         q10, q11, q15
   1644        vshr.u8         q11, q11, #4
   1645        vzip.8          q8,  q9
   1646        vzip.8          q10, q11
   1647        vtbl.8          d16, {d0}, d16
   1648        vtbl.8          d17, {d0}, d17
   1649        vtbl.8          d18, {d0}, d18
   1650        vtbl.8          d19, {d0}, d19
   1651        vtbl.8          d20, {d0}, d20
   1652        vtbl.8          d21, {d0}, d21
   1653        vst1.8          {q8},  [r0, :128], r1
   1654        vtbl.8          d22, {d0}, d22
   1655        vst1.8          {q9},  [r2, :128], r1
   1656        vtbl.8          d23, {d0}, d23
   1657        vst1.8          {q10}, [r0, :128], r1
   1658        vst1.8          {q11}, [r2, :128], r1
   1659        bgt             16b
   1660        pop             {r4-r5, pc}
   1661 320:
   1662        lsl             r1,  r1,  #1
   1663 32:
   1664        vld1.8          {q10, q11}, [r3, :64]!
   1665        subs            r5,  r5,  #2
   1666        vand.u8         q8,  q10, q15
   1667        vshr.u8         q9,  q10, #4
   1668        vand.u8         q10, q11, q15
   1669        vshr.u8         q11, q11, #4
   1670        vzip.8          q8,  q9
   1671        vzip.8          q10, q11
   1672        vtbl.8          d16, {d0}, d16
   1673        vtbl.8          d17, {d0}, d17
   1674        vtbl.8          d18, {d0}, d18
   1675        vtbl.8          d19, {d0}, d19
   1676        vtbl.8          d20, {d0}, d20
   1677        vtbl.8          d21, {d0}, d21
   1678        vst1.8          {q8,  q9},  [r0, :128], r1
   1679        vtbl.8          d22, {d0}, d22
   1680        vtbl.8          d23, {d0}, d23
   1681        vst1.8          {q10, q11}, [r2, :128], r1
   1682        bgt             32b
   1683        pop             {r4-r5, pc}
   1684 640:
   1685        sub             r1,  r1,  #32
   1686 64:
   1687        vld1.8          {q10, q11}, [r3, :64]!
   1688        subs            r5,  r5,  #1
   1689        vand.u8         q8,  q10, q15
   1690        vshr.u8         q9,  q10, #4
   1691        vand.u8         q10, q11, q15
   1692        vshr.u8         q11, q11, #4
   1693        vzip.8          q8,  q9
   1694        vzip.8          q10, q11
   1695        vtbl.8          d16, {d0}, d16
   1696        vtbl.8          d17, {d0}, d17
   1697        vtbl.8          d18, {d0}, d18
   1698        vtbl.8          d19, {d0}, d19
   1699        vtbl.8          d20, {d0}, d20
   1700        vtbl.8          d21, {d0}, d21
   1701        vst1.8          {q8,  q9},  [r0, :128]!
   1702        vtbl.8          d22, {d0}, d22
   1703        vtbl.8          d23, {d0}, d23
   1704        vst1.8          {q10, q11}, [r0, :128], r1
   1705        bgt             64b
   1706        pop             {r4-r5, pc}
   1707 endfunc
   1708 
   1709 // void ipred_cfl_128_8bpc_neon(pixel *dst, const ptrdiff_t stride,
   1710 //                              const pixel *const topleft,
   1711 //                              const int width, const int height,
   1712 //                              const int16_t *ac, const int alpha);
   1713 function ipred_cfl_128_8bpc_neon, export=1
   1714        push            {r4-r8, lr}
   1715        ldrd            r4,  r5,  [sp, #24]
   1716        ldr             r6,  [sp, #32]
   1717        clz             lr,  r3
   1718        adr             r12, L(ipred_cfl_128_tbl)
   1719        sub             lr,  lr,  #26
   1720        ldr             lr,  [r12, lr, lsl #2]
   1721        vmov.i16        q0,  #128     // dc
   1722        vdup.i16        q1,  r6       // alpha
   1723        add             r12, r12, lr
   1724        add             r6,  r0,  r1
   1725        lsl             r1,  r1,  #1
   1726        bx              r12
   1727 
   1728        .align 2
   1729 L(ipred_cfl_128_tbl):
   1730 L(ipred_cfl_splat_tbl):
   1731        .word L(ipred_cfl_splat_w16) - L(ipred_cfl_128_tbl) + CONFIG_THUMB
   1732        .word L(ipred_cfl_splat_w16) - L(ipred_cfl_128_tbl) + CONFIG_THUMB
   1733        .word L(ipred_cfl_splat_w8)  - L(ipred_cfl_128_tbl) + CONFIG_THUMB
   1734        .word L(ipred_cfl_splat_w4)  - L(ipred_cfl_128_tbl) + CONFIG_THUMB
   1735 
   1736 L(ipred_cfl_splat_w4):
   1737        vld1.16         {q2, q3}, [r5, :128]!
   1738        vmul.i16        q2,  q2,  q1  // diff = ac * alpha
   1739        vmul.i16        q3,  q3,  q1
   1740        vshr.s16        q8,  q2,  #15 // sign = diff >> 15
   1741        vshr.s16        q9,  q3,  #15
   1742        vadd.i16        q2,  q2,  q8  // diff + sign
   1743        vadd.i16        q3,  q3,  q9
   1744        vrshr.s16       q2,  q2,  #6  // (diff + sign + 32) >> 6 = apply_sign()
   1745        vrshr.s16       q3,  q3,  #6
   1746        vadd.i16        q2,  q2,  q0  // dc + apply_sign()
   1747        vadd.i16        q3,  q3,  q0
   1748        vqmovun.s16     d4,  q2       // iclip_pixel(dc + apply_sign())
   1749        vqmovun.s16     d5,  q3
   1750        vst1.32         {d4[0]}, [r0, :32], r1
   1751        vst1.32         {d4[1]}, [r6, :32], r1
   1752        subs            r4,  r4,  #4
   1753        vst1.32         {d5[0]}, [r0, :32], r1
   1754        vst1.32         {d5[1]}, [r6, :32], r1
   1755        bgt             L(ipred_cfl_splat_w4)
   1756        pop             {r4-r8, pc}
   1757 L(ipred_cfl_splat_w8):
   1758        vld1.16         {q8, q9},   [r5, :128]!
   1759        vld1.16         {q10, q11}, [r5, :128]!
   1760        vmul.i16        q8,  q8,  q1  // diff = ac * alpha
   1761        vmul.i16        q9,  q9,  q1
   1762        vmul.i16        q10, q10, q1
   1763        vmul.i16        q11, q11, q1
   1764        vshr.s16        q12, q8,  #15 // sign = diff >> 15
   1765        vshr.s16        q13, q9,  #15
   1766        vshr.s16        q14, q10, #15
   1767        vshr.s16        q15, q11, #15
   1768        vadd.i16        q8,  q8,  q12 // diff + sign
   1769        vadd.i16        q9,  q9,  q13
   1770        vadd.i16        q10, q10, q14
   1771        vadd.i16        q11, q11, q15
   1772        vrshr.s16       q8,  q8,  #6  // (diff + sign + 32) >> 6 = apply_sign()
   1773        vrshr.s16       q9,  q9,  #6
   1774        vrshr.s16       q10, q10, #6
   1775        vrshr.s16       q11, q11, #6
   1776        vadd.i16        q8,  q8,  q0  // dc + apply_sign()
   1777        vadd.i16        q9,  q9,  q0
   1778        vadd.i16        q10, q10, q0
   1779        vadd.i16        q11, q11, q0
   1780        vqmovun.s16     d16, q8       // iclip_pixel(dc + apply_sign())
   1781        vqmovun.s16     d17, q9
   1782        vqmovun.s16     d18, q10
   1783        vqmovun.s16     d19, q11
   1784        vst1.8          {d16}, [r0, :64], r1
   1785        vst1.8          {d17}, [r6, :64], r1
   1786        subs            r4,  r4,  #4
   1787        vst1.8          {d18}, [r0, :64], r1
   1788        vst1.8          {d19}, [r6, :64], r1
   1789        bgt             L(ipred_cfl_splat_w8)
   1790        pop             {r4-r8, pc}
   1791 L(ipred_cfl_splat_w16):
   1792        add             r12, r5,  r3, lsl #1
   1793        sub             r1,  r1,  r3
   1794        mov             lr,  r3
   1795 1:
   1796        vld1.16         {q8, q9},   [r5, :128]!
   1797        vmul.i16        q8,  q8,  q1  // diff = ac * alpha
   1798        vld1.16         {q10, q11}, [r12, :128]!
   1799        vmul.i16        q9,  q9,  q1
   1800        vmul.i16        q10, q10, q1
   1801        vmul.i16        q11, q11, q1
   1802        vshr.s16        q12, q8,  #15 // sign = diff >> 15
   1803        vshr.s16        q13, q9,  #15
   1804        vshr.s16        q14, q10, #15
   1805        vshr.s16        q15, q11, #15
   1806        vadd.i16        q8,  q8,  q12 // diff + sign
   1807        vadd.i16        q9,  q9,  q13
   1808        vadd.i16        q10, q10, q14
   1809        vadd.i16        q11, q11, q15
   1810        vrshr.s16       q8,  q8,  #6  // (diff + sign + 32) >> 6 = apply_sign()
   1811        vrshr.s16       q9,  q9,  #6
   1812        vrshr.s16       q10, q10, #6
   1813        vrshr.s16       q11, q11, #6
   1814        vadd.i16        q8,  q8,  q0  // dc + apply_sign()
   1815        vadd.i16        q9,  q9,  q0
   1816        vadd.i16        q10, q10, q0
   1817        vadd.i16        q11, q11, q0
   1818        vqmovun.s16     d16, q8       // iclip_pixel(dc + apply_sign())
   1819        vqmovun.s16     d17, q9
   1820        vqmovun.s16     d18, q10
   1821        vqmovun.s16     d19, q11
   1822        subs            r3,  r3,  #16
   1823        vst1.16         {q8}, [r0, :128]!
   1824        vst1.16         {q9}, [r6, :128]!
   1825        bgt             1b
   1826        subs            r4,  r4,  #2
   1827        add             r5,  r5,  lr, lsl #1
   1828        add             r12, r12, lr, lsl #1
   1829        add             r0,  r0,  r1
   1830        add             r6,  r6,  r1
   1831        mov             r3,  lr
   1832        bgt             1b
   1833        pop             {r4-r8, pc}
   1834 endfunc
   1835 
   1836 // void ipred_cfl_top_8bpc_neon(pixel *dst, const ptrdiff_t stride,
   1837 //                              const pixel *const topleft,
   1838 //                              const int width, const int height,
   1839 //                              const int16_t *ac, const int alpha);
   1840 function ipred_cfl_top_8bpc_neon, export=1
   1841        push            {r4-r8, lr}
   1842        ldrd            r4,  r5,  [sp, #24]
   1843        ldr             r6,  [sp, #32]
   1844        clz             lr,  r3
   1845        adr             r12, L(ipred_cfl_top_tbl)
   1846        sub             lr,  lr,  #26
   1847        ldr             lr,  [r12, lr, lsl #2]
   1848        vdup.16         q1,  r6   // alpha
   1849        add             r2,  r2,  #1
   1850        add             r12, r12, lr
   1851        add             r6,  r0,  r1
   1852        lsl             r1,  r1,  #1
   1853        bx              r12
   1854 
   1855        .align 2
   1856 L(ipred_cfl_top_tbl):
   1857        .word 32f - L(ipred_cfl_top_tbl) + CONFIG_THUMB
   1858        .word 16f - L(ipred_cfl_top_tbl) + CONFIG_THUMB
   1859        .word 8f  - L(ipred_cfl_top_tbl) + CONFIG_THUMB
   1860        .word 4f  - L(ipred_cfl_top_tbl) + CONFIG_THUMB
   1861 
   1862 4:
   1863        vld1.32         {d0[]}, [r2]
   1864        vpaddl.u8       d0,  d0
   1865        vpadd.u16       d0,  d0
   1866        vrshr.u16       d0,  d0,  #2
   1867        vdup.16         q0,  d0[0]
   1868        b               L(ipred_cfl_splat_w4)
   1869 8:
   1870        vld1.8          {d0}, [r2]
   1871        vpaddl.u8       d0,  d0
   1872        vpadd.u16       d0,  d0
   1873        vpadd.u16       d0,  d0
   1874        vrshr.u16       d0,  d0,  #3
   1875        vdup.16         q0,  d0[0]
   1876        b               L(ipred_cfl_splat_w8)
   1877 16:
   1878        vld1.8          {q0}, [r2]
   1879        vaddl.u8        q0,  d0,  d1
   1880        vadd.u16        d0,  d0,  d1
   1881        vpadd.u16       d0,  d0
   1882        vpadd.u16       d0,  d0
   1883        vrshr.u16       d0,  d0,  #4
   1884        vdup.16         q0,  d0[0]
   1885        b               L(ipred_cfl_splat_w16)
   1886 32:
   1887        vld1.8          {q2, q3}, [r2]
   1888        vaddl.u8        q2,  d4,  d5
   1889        vaddl.u8        q3,  d6,  d7
   1890        vadd.u16        q0,  q2,  q3
   1891        vadd.u16        d0,  d0,  d1
   1892        vpadd.u16       d0,  d0
   1893        vpadd.u16       d0,  d0
   1894        vrshr.u16       d0,  d0,  #5
   1895        vdup.16         q0,  d0[0]
   1896        b               L(ipred_cfl_splat_w16)
   1897 endfunc
   1898 
   1899 // void ipred_cfl_left_8bpc_neon(pixel *dst, const ptrdiff_t stride,
   1900 //                               const pixel *const topleft,
   1901 //                               const int width, const int height,
   1902 //                               const int16_t *ac, const int alpha);
   1903 function ipred_cfl_left_8bpc_neon, export=1
   1904        push            {r4-r8, lr}
   1905        ldrd            r4,  r5,  [sp, #24]
   1906        ldr             r6,  [sp, #32]
   1907        sub             r2,  r2,  r4
   1908        clz             lr,  r3
   1909        clz             r8,  r4
   1910        adr             r12, L(ipred_cfl_splat_tbl)
   1911        adr             r7,  L(ipred_cfl_left_tbl)
   1912        sub             lr,  lr,  #26
   1913        sub             r8,  r8,  #26
   1914        ldr             lr,  [r12, lr, lsl #2]
   1915        ldr             r8,  [r7,  r8, lsl #2]
   1916        vdup.16         q1,  r6   // alpha
   1917        add             r12, r12, lr
   1918        add             r7,  r7,  r8
   1919        add             r6,  r0,  r1
   1920        lsl             r1,  r1,  #1
   1921        bx              r7
   1922 
   1923        .align 2
   1924 L(ipred_cfl_left_tbl):
   1925        .word L(ipred_cfl_left_h32) - L(ipred_cfl_left_tbl) + CONFIG_THUMB
   1926        .word L(ipred_cfl_left_h16) - L(ipred_cfl_left_tbl) + CONFIG_THUMB
   1927        .word L(ipred_cfl_left_h8)  - L(ipred_cfl_left_tbl) + CONFIG_THUMB
   1928        .word L(ipred_cfl_left_h4)  - L(ipred_cfl_left_tbl) + CONFIG_THUMB
   1929 
   1930 L(ipred_cfl_left_h4):
   1931        vld1.32         {d0[]}, [r2, :32]
   1932        vpaddl.u8       d0,  d0
   1933        vpadd.u16       d0,  d0
   1934        vrshr.u16       d0,  d0,  #2
   1935        vdup.16         q0,  d0[0]
   1936        bx              r12
   1937 
   1938 L(ipred_cfl_left_h8):
   1939        vld1.8          {d0}, [r2, :64]
   1940        vpaddl.u8       d0,  d0
   1941        vpadd.u16       d0,  d0
   1942        vpadd.u16       d0,  d0
   1943        vrshr.u16       d0,  d0,  #3
   1944        vdup.16         q0,  d0[0]
   1945        bx              r12
   1946 
   1947 L(ipred_cfl_left_h16):
   1948        vld1.8          {q0}, [r2, :128]
   1949        vaddl.u8        q0,  d0,  d1
   1950        vadd.u16        d0,  d0,  d1
   1951        vpadd.u16       d0,  d0
   1952        vpadd.u16       d0,  d0
   1953        vrshr.u16       d0,  d0,  #4
   1954        vdup.16         q0,  d0[0]
   1955        bx              r12
   1956 
   1957 L(ipred_cfl_left_h32):
   1958        vld1.8          {q2, q3}, [r2, :128]
   1959        vaddl.u8        q2,  d4,  d5
   1960        vaddl.u8        q3,  d6,  d7
   1961        vadd.u16        q0,  q2,  q3
   1962        vadd.u16        d0,  d0,  d1
   1963        vpadd.u16       d0,  d0
   1964        vpadd.u16       d0,  d0
   1965        vrshr.u16       d0,  d0,  #5
   1966        vdup.16         q0,  d0[0]
   1967        bx              r12
   1968 endfunc
   1969 
   1970 // void ipred_cfl_8bpc_neon(pixel *dst, const ptrdiff_t stride,
   1971 //                          const pixel *const topleft,
   1972 //                          const int width, const int height,
   1973 //                          const int16_t *ac, const int alpha);
   1974 function ipred_cfl_8bpc_neon, export=1
   1975        push            {r4-r8, lr}
   1976        ldrd            r4,  r5,  [sp, #24]
   1977        ldr             r6,  [sp, #32]
   1978        sub             r2,  r2,  r4
   1979        add             r8,  r3,  r4  // width + height
   1980        vdup.16         q1,  r6       // alpha
   1981        clz             lr,  r3
   1982        clz             r6,  r4
   1983        vdup.16         d16, r8       // width + height
   1984        adr             r7,  L(ipred_cfl_tbl)
   1985        rbit            r8,  r8       // rbit(width + height)
   1986        sub             lr,  lr,  #22 // 26 leading bits, minus table offset 4
   1987        sub             r6,  r6,  #26
   1988        clz             r8,  r8       // ctz(width + height)
   1989        ldr             lr,  [r7, lr, lsl #2]
   1990        ldr             r6,  [r7, r6, lsl #2]
   1991        neg             r8,  r8       // -ctz(width + height)
   1992        add             r12, r7,  lr
   1993        add             r7,  r7,  r6
   1994        vshr.u16        d16, d16, #1  // (width + height) >> 1
   1995        vdup.16         d17, r8       // -ctz(width + height)
   1996        add             r6,  r0,  r1
   1997        lsl             r1,  r1,  #1
   1998        bx              r7
   1999 
   2000        .align 2
   2001 L(ipred_cfl_tbl):
   2002        .word L(ipred_cfl_h32) - L(ipred_cfl_tbl) + CONFIG_THUMB
   2003        .word L(ipred_cfl_h16) - L(ipred_cfl_tbl) + CONFIG_THUMB
   2004        .word L(ipred_cfl_h8)  - L(ipred_cfl_tbl) + CONFIG_THUMB
   2005        .word L(ipred_cfl_h4)  - L(ipred_cfl_tbl) + CONFIG_THUMB
   2006        .word L(ipred_cfl_w32) - L(ipred_cfl_tbl) + CONFIG_THUMB
   2007        .word L(ipred_cfl_w16) - L(ipred_cfl_tbl) + CONFIG_THUMB
   2008        .word L(ipred_cfl_w8)  - L(ipred_cfl_tbl) + CONFIG_THUMB
   2009        .word L(ipred_cfl_w4)  - L(ipred_cfl_tbl) + CONFIG_THUMB
   2010 
   2011 L(ipred_cfl_h4):
   2012        vld1.32         {d0[]}, [r2, :32]!
   2013        vpaddl.u8       d0,  d0
   2014        add             r2,  r2,  #1
   2015        vpadd.i16       d0,  d0
   2016        bx              r12
   2017 L(ipred_cfl_w4):
   2018        vld1.32         {d1[]},  [r2]
   2019        vadd.i16        d0,  d0,  d16
   2020        vpaddl.u8       d1,  d1
   2021        vpadd.u16       d1,  d1
   2022        cmp             r4,  #4
   2023        vadd.i16        d0,  d0,  d1
   2024        vshl.u16        d0,  d0,  d17
   2025        beq             1f
   2026        // h = 8/16
   2027        movw            lr,  #(0x3334/2)
   2028        movw            r8,  #(0x5556/2)
   2029        cmp             r4,  #16
   2030        it              ne
   2031        movne           lr,  r8
   2032        vdup.16         d18, lr
   2033        vqdmulh.s16     d0,  d0,  d18
   2034 1:
   2035        vdup.16         q0,  d0[0]
   2036        b               L(ipred_cfl_splat_w4)
   2037 
   2038 L(ipred_cfl_h8):
   2039        vld1.8          {d0}, [r2, :64]!
   2040        vpaddl.u8       d0,  d0
   2041        vpadd.i16       d0,  d0
   2042        add             r2,  r2,  #1
   2043        vpadd.i16       d0,  d0
   2044        bx              r12
   2045 L(ipred_cfl_w8):
   2046        vld1.8          {d1}, [r2]
   2047        vadd.i16        d0,  d0,  d16
   2048        vpaddl.u8       d1,  d1
   2049        vpadd.i16       d1,  d1
   2050        vpadd.i16       d1,  d1
   2051        cmp             r4,  #8
   2052        vadd.i16        d0,  d0,  d1
   2053        vshl.u16        d0,  d0,  d17
   2054        beq             1f
   2055        // h = 4/16/32
   2056        cmp             r4,  #32
   2057        movw            lr,  #(0x3334/2)
   2058        movw            r8,  #(0x5556/2)
   2059        it              ne
   2060        movne           lr,  r8
   2061        vdup.16         d18, lr
   2062        vqdmulh.s16     d0,  d0,  d18
   2063 1:
   2064        vdup.16         q0,  d0[0]
   2065        b               L(ipred_cfl_splat_w8)
   2066 
   2067 L(ipred_cfl_h16):
   2068        vld1.8          {q0}, [r2, :128]!
   2069        vaddl.u8        q0,  d0,  d1
   2070        vadd.i16        d0,  d0,  d1
   2071        vpadd.i16       d0,  d0
   2072        add             r2,  r2,  #1
   2073        vpadd.i16       d0,  d0
   2074        bx              r12
   2075 L(ipred_cfl_w16):
   2076        vld1.8          {q2}, [r2]
   2077        vadd.i16        d0,  d0,  d16
   2078        vaddl.u8        q2,  d4,  d5
   2079        vadd.i16        d4,  d4,  d5
   2080        vpadd.i16       d4,  d4
   2081        vpadd.i16       d4,  d4
   2082        cmp             r4,  #16
   2083        vadd.i16        d0,  d0,  d4
   2084        vshl.u16        d0,  d0,  d17
   2085        beq             1f
   2086        // h = 4/8/32/64
   2087        tst             r4,  #(32+16+8)  // 16 added to make a consecutive bitmask
   2088        movw            lr,  #(0x3334/2)
   2089        movw            r8,  #(0x5556/2)
   2090        it              ne
   2091        movne           lr,  r8
   2092        vdup.16         d18, lr
   2093        vqdmulh.s16     d0,  d0,  d18
   2094 1:
   2095        vdup.16         q0,  d0[0]
   2096        b               L(ipred_cfl_splat_w16)
   2097 
   2098 L(ipred_cfl_h32):
   2099        vld1.8          {q2, q3}, [r2, :128]!
   2100        vaddl.u8        q2,  d4,  d5
   2101        vaddl.u8        q3,  d6,  d7
   2102        vadd.i16        q0,  q2,  q3
   2103        vadd.i16        d0,  d0,  d1
   2104        vpadd.i16       d0,  d0
   2105        add             r2,  r2,  #1
   2106        vpadd.i16       d0,  d0
   2107        bx              r12
   2108 L(ipred_cfl_w32):
   2109        vld1.8          {q2, q3},  [r2]
   2110        vadd.i16        d0,  d0,  d16
   2111        vaddl.u8        q2,  d4,  d5
   2112        vaddl.u8        q3,  d6,  d7
   2113        vadd.i16        q2,  q2,  q3
   2114        vadd.i16        d4,  d4,  d5
   2115        vpadd.i16       d4,  d4
   2116        vpadd.i16       d4,  d4
   2117        cmp             r4,  #32
   2118        vadd.i16        d0,  d0,  d4
   2119        vshl.u16        d0,  d0,  d17
   2120        beq             1f
   2121        // h = 8/16/64
   2122        cmp             r4,  #8
   2123        movw            lr,  #(0x3334/2)
   2124        movw            r8,  #(0x5556/2)
   2125        it              ne
   2126        movne           lr,  r8
   2127        vdup.16         d18, lr
   2128        vqdmulh.s16     d0,  d0,  d18
   2129 1:
   2130        vdup.16         q0,  d0[0]
   2131        b               L(ipred_cfl_splat_w16)
   2132 endfunc
   2133 
   2134 // void cfl_ac_420_8bpc_neon(int16_t *const ac, const pixel *const ypx,
   2135 //                           const ptrdiff_t stride, const int w_pad,
   2136 //                           const int h_pad, const int cw, const int ch);
   2137 function ipred_cfl_ac_420_8bpc_neon, export=1
   2138        push            {r4-r8,lr}
   2139        ldrd            r4,  r5,  [sp, #24]
   2140        ldr             r6,  [sp, #32]
   2141        clz             r8,  r5
   2142        lsl             r4,  r4,  #2
   2143        adr             r7,  L(ipred_cfl_ac_420_tbl)
   2144        sub             r8,  r8,  #27
   2145        ldr             r8,  [r7, r8, lsl #2]
   2146        vmov.i16        q8,  #0
   2147        vmov.i16        q9,  #0
   2148        vmov.i16        q10, #0
   2149        vmov.i16        q11, #0
   2150        add             r7,  r7,  r8
   2151        sub             r8,  r6,  r4  // height - h_pad
   2152        rbit            lr,  r5       // rbit(width)
   2153        rbit            r12, r6       // rbit(height)
   2154        clz             lr,  lr       // ctz(width)
   2155        clz             r12, r12      // ctz(height)
   2156        add             lr,  lr,  r12 // log2sz
   2157        add             r12, r1,  r2
   2158        vdup.32         d31, lr
   2159        lsl             r2,  r2,  #1
   2160        vneg.s32        d31, d31      // -log2sz
   2161        bx              r7
   2162 
   2163        .align 2
   2164 L(ipred_cfl_ac_420_tbl):
   2165        .word L(ipred_cfl_ac_420_w16) - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB
   2166        .word L(ipred_cfl_ac_420_w8)  - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB
   2167        .word L(ipred_cfl_ac_420_w4)  - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB
   2168 
   2169 L(ipred_cfl_ac_420_w4):
   2170 1:      // Copy and subsample input
   2171        vld1.8          {d0}, [r1,  :64], r2
   2172        vld1.8          {d2}, [r12, :64], r2
   2173        vld1.8          {d1}, [r1,  :64], r2
   2174        vld1.8          {d3}, [r12, :64], r2
   2175        vpaddl.u8       q0,  q0
   2176        vpaddl.u8       q1,  q1
   2177        vadd.i16        q0,  q0,  q1
   2178        vshl.i16        q0,  q0,  #1
   2179        subs            r8,  r8,  #2
   2180        vst1.16         {q0}, [r0, :128]!
   2181        vadd.i16        q8,  q8,  q0
   2182        bgt             1b
   2183        cmp             r4,  #0
   2184        vmov            d0,  d1
   2185        vmov            d2,  d1
   2186        vmov            d3,  d1
   2187 L(ipred_cfl_ac_420_w4_hpad):
   2188        beq             3f // This assumes that all callers already did "cmp r4, #0"
   2189 2:      // Vertical padding (h_pad > 0)
   2190        subs            r4,  r4,  #4
   2191        vst1.16         {q0, q1}, [r0, :128]!
   2192        vadd.i16        q8,  q8,  q0
   2193        vadd.i16        q8,  q8,  q1
   2194        bgt             2b
   2195 3:
   2196 L(ipred_cfl_ac_420_w4_calc_subtract_dc):
   2197        // Aggregate the sums
   2198        vadd.i16        q0,  q8,  q9
   2199        vadd.i16        q1,  q10, q11
   2200        vpaddl.u16      q0,  q0
   2201        vpaddl.u16      q1,  q1
   2202        vadd.i32        q0,  q1
   2203        vadd.i32        d0,  d0,  d1
   2204        vpadd.i32       d0,  d0,  d0  // sum
   2205        sub             r0,  r0,  r6, lsl #3
   2206        vrshl.u32       d16, d0,  d31 // (sum + (1 << (log2sz - 1))) >>= log2sz
   2207        vdup.16         q8,  d16[0]
   2208 L(ipred_cfl_ac_420_w4_subtract_dc):
   2209 6:      // Subtract dc from ac
   2210        vld1.16         {q0, q1}, [r0, :128]
   2211        subs            r6,  r6,  #4
   2212        vsub.i16        q0,  q0,  q8
   2213        vsub.i16        q1,  q1,  q8
   2214        vst1.16         {q0, q1}, [r0, :128]!
   2215        bgt             6b
   2216        pop             {r4-r8, pc}
   2217 
   2218 L(ipred_cfl_ac_420_w8):
   2219        cmp             r3,  #0
   2220        bne             L(ipred_cfl_ac_420_w8_wpad)
   2221 1:      // Copy and subsample input, without padding
   2222        vld1.8          {q0}, [r1,  :128], r2
   2223        vld1.8          {q1}, [r12, :128], r2
   2224        vld1.8          {q2}, [r1,  :128], r2
   2225        vpaddl.u8       q0,  q0
   2226        vld1.8          {q3}, [r12, :128], r2
   2227        vpaddl.u8       q1,  q1
   2228        vpaddl.u8       q2,  q2
   2229        vpaddl.u8       q3,  q3
   2230        vadd.i16        q0,  q0,  q1
   2231        vadd.i16        q2,  q2,  q3
   2232        vshl.i16        q0,  q0,  #1
   2233        vshl.i16        q1,  q2,  #1
   2234        subs            r8,  r8,  #2
   2235        vst1.16         {q0, q1}, [r0, :128]!
   2236        vadd.i16        q8,  q8,  q0
   2237        vadd.i16        q9,  q9,  q1
   2238        bgt             1b
   2239        cmp             r4,  #0
   2240        vmov            q0,  q1
   2241        b               L(ipred_cfl_ac_420_w8_hpad)
   2242 
   2243 L(ipred_cfl_ac_420_w8_wpad):
   2244 1:      // Copy and subsample input, padding 4
   2245        vld1.16         {d0}, [r1,  :64], r2
   2246        vld1.16         {d2}, [r12, :64], r2
   2247        vld1.16         {d1}, [r1,  :64], r2
   2248        vld1.16         {d3}, [r12, :64], r2
   2249        vpaddl.u8       q0,  q0
   2250        vpaddl.u8       q1,  q1
   2251        vadd.i16        q0,  q0,  q1
   2252        vshl.i16        q0,  q0,  #1
   2253        vdup.16         d3,  d1[3]
   2254        vmov            d2,  d1
   2255        vdup.16         d1,  d0[3]
   2256        subs            r8,  r8,  #2
   2257        vst1.16         {q0, q1}, [r0, :128]!
   2258        vadd.i16        q8,  q8,  q0
   2259        vadd.i16        q9,  q9,  q1
   2260        bgt             1b
   2261        cmp             r4,  #0
   2262        vmov            q0,  q1
   2263 
   2264 L(ipred_cfl_ac_420_w8_hpad):
   2265        beq             3f // This assumes that all callers already did "cmp r4, #0"
   2266 2:      // Vertical padding (h_pad > 0)
   2267        subs            r4,  r4,  #4
   2268        vst1.16         {q0, q1}, [r0, :128]!
   2269        vadd.i16        q8,  q8,  q0
   2270        vadd.i16        q9,  q9,  q1
   2271        vst1.16         {q0, q1}, [r0, :128]!
   2272        vadd.i16        q10, q10, q0
   2273        vadd.i16        q11, q11, q1
   2274        bgt             2b
   2275 3:
   2276 
   2277        // Double the height and reuse the w4 summing/subtracting
   2278        lsl             r6,  r6,  #1
   2279        b               L(ipred_cfl_ac_420_w4_calc_subtract_dc)
   2280 
   2281 L(ipred_cfl_ac_420_w16):
   2282        adr             r7,  L(ipred_cfl_ac_420_w16_tbl)
   2283        ldr             r3,  [r7, r3, lsl #2]
   2284        add             r7,  r7,  r3
   2285        bx              r7
   2286 
   2287        .align 2
   2288 L(ipred_cfl_ac_420_w16_tbl):
   2289        .word L(ipred_cfl_ac_420_w16_wpad0) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
   2290        .word L(ipred_cfl_ac_420_w16_wpad1) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
   2291        .word L(ipred_cfl_ac_420_w16_wpad2) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
   2292        .word L(ipred_cfl_ac_420_w16_wpad3) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
   2293 
   2294 L(ipred_cfl_ac_420_w16_wpad0):
   2295 1:      // Copy and subsample input, without padding
   2296        vld1.8          {q0, q1},   [r1,  :128], r2
   2297        vld1.8          {q2, q3},   [r12, :128], r2
   2298        vpaddl.u8       q0,  q0
   2299        vld1.8          {q12, q13}, [r1,  :128], r2
   2300        vpaddl.u8       q1,  q1
   2301        vpaddl.u8       q2,  q2
   2302        vpaddl.u8       q3,  q3
   2303        vadd.i16        q0,  q0,  q2
   2304        vadd.i16        q1,  q1,  q3
   2305        vld1.8          {q2, q3},   [r12, :128], r2
   2306        vpaddl.u8       q12, q12
   2307        vpaddl.u8       q13, q13
   2308        vpaddl.u8       q2,  q2
   2309        vpaddl.u8       q3,  q3
   2310        vadd.i16        q12, q12, q2
   2311        vadd.i16        q13, q13, q3
   2312        vshl.i16        q0,  q0,  #1
   2313        vshl.i16        q1,  q1,  #1
   2314        vshl.i16        q2,  q12, #1
   2315        vshl.i16        q3,  q13, #1
   2316        subs            r8,  r8,  #2
   2317        vst1.16         {q0, q1}, [r0, :128]!
   2318        vadd.i16        q8,  q8,  q0
   2319        vadd.i16        q9,  q9,  q1
   2320        vst1.16         {q2, q3}, [r0, :128]!
   2321        vadd.i16        q10, q10, q2
   2322        vadd.i16        q11, q11, q3
   2323        bgt             1b
   2324        cmp             r4,  #0
   2325        vmov            q0,  q2
   2326        vmov            q1,  q3
   2327        b               L(ipred_cfl_ac_420_w16_hpad)
   2328 
   2329 L(ipred_cfl_ac_420_w16_wpad1):
   2330 1:      // Copy and subsample input, padding 4
   2331        vldr            d2,    [r1,  #16]
   2332        vld1.8          {q0},  [r1,  :128], r2
   2333        vldr            d6,    [r12, #16]
   2334        vld1.8          {q2},  [r12, :128], r2
   2335        vpaddl.u8       d2,  d2
   2336        vldr            d26,   [r1,  #16]
   2337        vpaddl.u8       q0,  q0
   2338        vld1.8          {q12}, [r1,  :128], r2
   2339        vpaddl.u8       d6,  d6
   2340        vldr            d30,   [r12, #16]
   2341        vpaddl.u8       q2,  q2
   2342        vld1.8          {q14}, [r12, :128], r2
   2343        vpaddl.u8       d26, d26
   2344        vpaddl.u8       q12, q12
   2345        vpaddl.u8       d30, d30
   2346        vpaddl.u8       q14, q14
   2347        vadd.i16        d2,  d2,  d6
   2348        vadd.i16        q0,  q0,  q2
   2349        vadd.i16        d26, d26, d30
   2350        vadd.i16        q12, q12, q14
   2351        vshl.i16        d2,  d2,  #1
   2352        vshl.i16        q0,  q0,  #1
   2353        vshl.i16        d6,  d26, #1
   2354        vshl.i16        q2,  q12, #1
   2355        vdup.16         d3,  d2[3]
   2356        vdup.16         d7,  d6[3]
   2357        subs            r8,  r8,  #2
   2358        vst1.16         {q0, q1}, [r0, :128]!
   2359        vadd.i16        q8,  q8,  q0
   2360        vadd.i16        q9,  q9,  q1
   2361        vst1.16         {q2, q3}, [r0, :128]!
   2362        vadd.i16        q10, q10, q2
   2363        vadd.i16        q11, q11, q3
   2364        bgt             1b
   2365        cmp             r4,  #0
   2366        vmov            q0,  q2
   2367        vmov            q1,  q3
   2368        b               L(ipred_cfl_ac_420_w16_hpad)
   2369 
   2370 L(ipred_cfl_ac_420_w16_wpad2):
   2371 1:      // Copy and subsample input, padding 8
   2372        vld1.8          {q0}, [r1,  :128], r2
   2373        vld1.8          {q1}, [r12, :128], r2
   2374        vld1.8          {q2}, [r1,  :128], r2
   2375        vpaddl.u8       q0,  q0
   2376        vld1.8          {q3}, [r12, :128], r2
   2377        vpaddl.u8       q1,  q1
   2378        vpaddl.u8       q2,  q2
   2379        vpaddl.u8       q3,  q3
   2380        vadd.i16        q0,  q0,  q1
   2381        vadd.i16        q2,  q2,  q3
   2382        vshl.i16        q0,  q0,  #1
   2383        vshl.i16        q2,  q2,  #1
   2384        vdup.16         q1,  d1[3]
   2385        vdup.16         q3,  d5[3]
   2386        subs            r8,  r8,  #2
   2387        vst1.16         {q0, q1}, [r0, :128]!
   2388        vadd.i16        q8,  q8,  q0
   2389        vadd.i16        q9,  q9,  q1
   2390        vst1.16         {q2, q3}, [r0, :128]!
   2391        vadd.i16        q10, q10, q2
   2392        vadd.i16        q11, q11, q3
   2393        bgt             1b
   2394        cmp             r4,  #0
   2395        vmov            q0,  q2
   2396        vmov            q1,  q3
   2397        b               L(ipred_cfl_ac_420_w16_hpad)
   2398 
   2399 L(ipred_cfl_ac_420_w16_wpad3):
   2400 1:      // Copy and subsample input, padding 12
   2401        vld1.8          {d0}, [r1,  :64], r2
   2402        vld1.8          {d1}, [r12, :64], r2
   2403        vld1.8          {d4}, [r1,  :64], r2
   2404        vpaddl.u8       q0,  q0
   2405        vld1.8          {d5}, [r12, :64], r2
   2406        vpaddl.u8       q2,  q2
   2407        vadd.i16        d0,  d0,  d1
   2408        vadd.i16        d4,  d4,  d5
   2409        vshl.i16        d0,  d0,  #1
   2410        vshl.i16        d4,  d4,  #1
   2411        vdup.16         q1,  d0[3]
   2412        vdup.16         q3,  d4[3]
   2413        vdup.16         d1,  d0[3]
   2414        vdup.16         d5,  d4[3]
   2415        subs            r8,  r8,  #2
   2416        vst1.16         {q0, q1}, [r0, :128]!
   2417        vadd.i16        q8,  q8,  q0
   2418        vadd.i16        q9,  q9,  q1
   2419        vst1.16         {q2, q3}, [r0, :128]!
   2420        vadd.i16        q10, q10, q2
   2421        vadd.i16        q11, q11, q3
   2422        bgt             1b
   2423        cmp             r4,  #0
   2424        vmov            q0,  q2
   2425        vmov            q1,  q3
   2426        b               L(ipred_cfl_ac_420_w16_hpad)
   2427 
   2428 L(ipred_cfl_ac_420_w16_hpad):
   2429        beq             3f // This assumes that all callers already did "cmp r4, #0"
   2430 2:      // Vertical padding (h_pad > 0)
   2431        subs            r4,  r4,  #2
   2432        vst1.16         {q0, q1}, [r0, :128]!
   2433        vadd.i16        q8,  q8,  q0
   2434        vadd.i16        q9,  q9,  q1
   2435        vst1.16         {q2, q3}, [r0, :128]!
   2436        vadd.i16        q10, q10, q2
   2437        vadd.i16        q11, q11, q3
   2438        bgt             2b
   2439 3:
   2440 
   2441        // Quadruple the height and reuse the w4 summing/subtracting
   2442        lsl             r6,  r6,  #2
   2443        b               L(ipred_cfl_ac_420_w4_calc_subtract_dc)
   2444 endfunc
   2445 
   2446 // void cfl_ac_422_8bpc_neon(int16_t *const ac, const pixel *const ypx,
   2447 //                           const ptrdiff_t stride, const int w_pad,
   2448 //                           const int h_pad, const int cw, const int ch);
   2449 function ipred_cfl_ac_422_8bpc_neon, export=1
   2450        push            {r4-r8,lr}
   2451        ldrd            r4,  r5,  [sp, #24]
   2452        ldr             r6,  [sp, #32]
   2453        clz             r8,  r5
   2454        lsl             r4,  r4,  #2
   2455        adr             r7,  L(ipred_cfl_ac_422_tbl)
   2456        sub             r8,  r8,  #27
   2457        ldr             r8,  [r7, r8, lsl #2]
   2458        vmov.i16        q8,  #0
   2459        vmov.i16        q9,  #0
   2460        vmov.i16        q10, #0
   2461        vmov.i16        q11, #0
   2462        add             r7,  r7,  r8
   2463        sub             r8,  r6,  r4  // height - h_pad
   2464        rbit            lr,  r5       // rbit(width)
   2465        rbit            r12, r6       // rbit(height)
   2466        clz             lr,  lr       // ctz(width)
   2467        clz             r12, r12      // ctz(height)
   2468        add             lr,  lr,  r12 // log2sz
   2469        add             r12, r1,  r2
   2470        vdup.32         d31, lr
   2471        lsl             r2,  r2,  #1
   2472        vneg.s32        d31, d31      // -log2sz
   2473        bx              r7
   2474 
   2475        .align 2
   2476 L(ipred_cfl_ac_422_tbl):
   2477        .word L(ipred_cfl_ac_422_w16) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB
   2478        .word L(ipred_cfl_ac_422_w8) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB
   2479        .word L(ipred_cfl_ac_422_w4) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB
   2480 
   2481 L(ipred_cfl_ac_422_w4):
   2482 1:      // Copy and subsample input
   2483        vld1.8          {d0}, [r1,  :64], r2
   2484        vld1.8          {d1}, [r12, :64], r2
   2485        vld1.8          {d2}, [r1,  :64], r2
   2486        vld1.8          {d3}, [r12, :64], r2
   2487        vpaddl.u8       q0,  q0
   2488        vpaddl.u8       q1,  q1
   2489        vshl.i16        q0,  q0,  #2
   2490        vshl.i16        q1,  q1,  #2
   2491        subs            r8,  r8,  #4
   2492        vst1.16         {q0, q1}, [r0, :128]!
   2493        vadd.i16        q8,  q8,  q0
   2494        vadd.i16        q9,  q9,  q1
   2495        bgt             1b
   2496        cmp             r4,  #0
   2497        vmov            d0,  d3
   2498        vmov            d1,  d3
   2499        vmov            d2,  d3
   2500        b               L(ipred_cfl_ac_420_w4_hpad)
   2501 
   2502 L(ipred_cfl_ac_422_w8):
   2503        cmp             r3,  #0
   2504        bne             L(ipred_cfl_ac_422_w8_wpad)
   2505 1:      // Copy and subsample input, without padding
   2506        vld1.8          {q0}, [r1,  :128], r2
   2507        vld1.8          {q1}, [r12, :128], r2
   2508        vld1.8          {q2}, [r1,  :128], r2
   2509        vpaddl.u8       q0,  q0
   2510        vld1.8          {q3}, [r12, :128], r2
   2511        vpaddl.u8       q1,  q1
   2512        vpaddl.u8       q2,  q2
   2513        vpaddl.u8       q3,  q3
   2514        vshl.i16        q0,  q0,  #2
   2515        vshl.i16        q1,  q1,  #2
   2516        vshl.i16        q2,  q2,  #2
   2517        vshl.i16        q3,  q3,  #2
   2518        subs            r8,  r8,  #4
   2519        vst1.16         {q0, q1}, [r0, :128]!
   2520        vadd.i16        q8,  q8,  q0
   2521        vadd.i16        q9,  q9,  q1
   2522        vst1.16         {q2, q3}, [r0, :128]!
   2523        vadd.i16        q10, q10, q2
   2524        vadd.i16        q11, q11, q3
   2525        bgt             1b
   2526        cmp             r4,  #0
   2527        vmov            q0,  q3
   2528        vmov            q1,  q3
   2529        b               L(ipred_cfl_ac_420_w8_hpad)
   2530 
   2531 L(ipred_cfl_ac_422_w8_wpad):
   2532 1:      // Copy and subsample input, padding 4
   2533        vld1.8          {d0}, [r1,  :64], r2
   2534        vld1.8          {d1}, [r12, :64], r2
   2535        vld1.8          {d2}, [r1,  :64], r2
   2536        vld1.8          {d3}, [r12, :64], r2
   2537        vpaddl.u8       q0,  q0
   2538        vpaddl.u8       q1,  q1
   2539        vshl.i16        q0,  q0,  #2
   2540        vshl.i16        q1,  q1,  #2
   2541        vdup.16         d7,  d3[3]
   2542        vmov            d6,  d3
   2543        vdup.16         d5,  d2[3]
   2544        vmov            d4,  d2
   2545        vdup.16         d3,  d1[3]
   2546        vmov            d2,  d1
   2547        vdup.16         d1,  d0[3]
   2548        subs            r8,  r8,  #4
   2549        vst1.16         {q0, q1}, [r0, :128]!
   2550        vadd.i16        q8,  q8,  q0
   2551        vadd.i16        q9,  q9,  q1
   2552        vst1.16         {q2, q3}, [r0, :128]!
   2553        vadd.i16        q10, q10, q2
   2554        vadd.i16        q11, q11, q3
   2555        bgt             1b
   2556        cmp             r4,  #0
   2557        vmov            q0,  q3
   2558        vmov            q1,  q3
   2559        b               L(ipred_cfl_ac_420_w8_hpad)
   2560 
   2561 L(ipred_cfl_ac_422_w16):
   2562        adr             r7,  L(ipred_cfl_ac_422_w16_tbl)
   2563        ldr             r3,  [r7, r3, lsl #2]
   2564        add             r7,  r7,  r3
   2565        bx              r7
   2566 
   2567        .align 2
   2568 L(ipred_cfl_ac_422_w16_tbl):
   2569        .word L(ipred_cfl_ac_422_w16_wpad0) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
   2570        .word L(ipred_cfl_ac_422_w16_wpad1) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
   2571        .word L(ipred_cfl_ac_422_w16_wpad2) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
   2572        .word L(ipred_cfl_ac_422_w16_wpad3) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
   2573 
   2574 L(ipred_cfl_ac_422_w16_wpad0):
   2575 1:      // Copy and subsample input, without padding
   2576        vld1.8          {q0, q1}, [r1,  :128], r2
   2577        vld1.8          {q2, q3}, [r12, :128], r2
   2578        vpaddl.u8       q0,  q0
   2579        vpaddl.u8       q1,  q1
   2580        vpaddl.u8       q2,  q2
   2581        vpaddl.u8       q3,  q3
   2582        vshl.i16        q0,  q0,  #2
   2583        vshl.i16        q1,  q1,  #2
   2584        vshl.i16        q2,  q2,  #2
   2585        vshl.i16        q3,  q3,  #2
   2586        subs            r8,  r8,  #2
   2587        vst1.16         {q0, q1}, [r0, :128]!
   2588        vadd.i16        q8,  q8,  q0
   2589        vadd.i16        q9,  q9,  q1
   2590        vst1.16         {q2, q3}, [r0, :128]!
   2591        vadd.i16        q10, q10, q2
   2592        vadd.i16        q11, q11, q3
   2593        bgt             1b
   2594        cmp             r4,  #0
   2595        vmov            q0,  q2
   2596        vmov            q1,  q3
   2597        b               L(ipred_cfl_ac_420_w16_hpad)
   2598 
   2599 L(ipred_cfl_ac_422_w16_wpad1):
   2600 1:      // Copy and subsample input, padding 4
   2601        vldr            d2,   [r1,  #16]
   2602        vld1.8          {q0}, [r1,  :128], r2
   2603        vldr            d6,   [r12, #16]
   2604        vld1.8          {q2}, [r12, :128], r2
   2605        vpaddl.u8       d2,  d2
   2606        vpaddl.u8       q0,  q0
   2607        vpaddl.u8       d6,  d6
   2608        vpaddl.u8       q2,  q2
   2609        vshl.i16        d2,  d2,  #2
   2610        vshl.i16        q0,  q0,  #2
   2611        vshl.i16        d6,  d6,  #2
   2612        vshl.i16        q2,  q2,  #2
   2613        vdup.16         d3,  d2[3]
   2614        vdup.16         d7,  d6[3]
   2615        subs            r8,  r8,  #2
   2616        vst1.16         {q0, q1}, [r0, :128]!
   2617        vadd.i16        q8,  q8,  q0
   2618        vadd.i16        q9,  q9,  q1
   2619        vst1.16         {q2, q3}, [r0, :128]!
   2620        vadd.i16        q10, q10, q2
   2621        vadd.i16        q11, q11, q3
   2622        bgt             1b
   2623        cmp             r4,  #0
   2624        vmov            q0,  q2
   2625        vmov            q1,  q3
   2626        b               L(ipred_cfl_ac_420_w16_hpad)
   2627 
   2628 L(ipred_cfl_ac_422_w16_wpad2):
   2629 1:      // Copy and subsample input, padding 8
   2630        vld1.8          {q0}, [r1,  :128], r2
   2631        vld1.8          {q2}, [r12, :128], r2
   2632        vpaddl.u8       q0,  q0
   2633        vpaddl.u8       q2,  q2
   2634        vshl.i16        q0,  q0,  #2
   2635        vshl.i16        q2,  q2,  #2
   2636        vdup.16         q1,  d1[3]
   2637        vdup.16         q3,  d5[3]
   2638        subs            r8,  r8,  #2
   2639        vst1.16         {q0, q1}, [r0, :128]!
   2640        vadd.i16        q8,  q8,  q0
   2641        vadd.i16        q9,  q9,  q1
   2642        vst1.16         {q2, q3}, [r0, :128]!
   2643        vadd.i16        q10, q10, q2
   2644        vadd.i16        q11, q11, q3
   2645        bgt             1b
   2646        cmp             r4,  #0
   2647        vmov            q0,  q2
   2648        vmov            q1,  q3
   2649        b               L(ipred_cfl_ac_420_w16_hpad)
   2650 
   2651 L(ipred_cfl_ac_422_w16_wpad3):
   2652 1:      // Copy and subsample input, padding 12
   2653        vld1.8          {d0}, [r1,  :64], r2
   2654        vld1.8          {d1}, [r12, :64], r2
   2655        vpaddl.u8       q0,  q0
   2656        vshl.i16        q0,  q0,  #2
   2657        vdup.16         q3,  d1[3]
   2658        vdup.16         q1,  d0[3]
   2659        vdup.16         d5,  d1[3]
   2660        vmov            d4,  d1
   2661        vdup.16         d1,  d0[3]
   2662        subs            r8,  r8,  #2
   2663        vst1.16         {q0, q1}, [r0, :128]!
   2664        vadd.i16        q8,  q8,  q0
   2665        vadd.i16        q9,  q9,  q1
   2666        vst1.16         {q2, q3}, [r0, :128]!
   2667        vadd.i16        q10, q10, q2
   2668        vadd.i16        q11, q11, q3
   2669        bgt             1b
   2670        cmp             r4,  #0
   2671        vmov            q0,  q2
   2672        vmov            q1,  q3
   2673        b               L(ipred_cfl_ac_420_w16_hpad)
   2674 endfunc
   2675 
   2676 // void cfl_ac_444_8bpc_neon(int16_t *const ac, const pixel *const ypx,
   2677 //                           const ptrdiff_t stride, const int w_pad,
   2678 //                           const int h_pad, const int cw, const int ch);
   2679 function ipred_cfl_ac_444_8bpc_neon, export=1
   2680        push            {r4-r8,lr}
   2681        ldrd            r4,  r5,  [sp, #24]
   2682        ldr             r6,  [sp, #32]
   2683        clz             r8,  r5
   2684        lsl             r4,  r4,  #2
   2685        adr             r7,  L(ipred_cfl_ac_444_tbl)
   2686        sub             r8,  r8,  #26
   2687        ldr             r8,  [r7, r8, lsl #2]
   2688        vmov.i16        q8,  #0
   2689        vmov.i16        q9,  #0
   2690        vmov.i16        q10, #0
   2691        vmov.i16        q11, #0
   2692        add             r7,  r7,  r8
   2693        sub             r8,  r6,  r4  // height - h_pad
   2694        rbit            lr,  r5       // rbit(width)
   2695        rbit            r12, r6       // rbit(height)
   2696        clz             lr,  lr       // ctz(width)
   2697        clz             r12, r12      // ctz(height)
   2698        add             lr,  lr,  r12 // log2sz
   2699        add             r12, r1,  r2
   2700        vdup.32         d31, lr
   2701        lsl             r2,  r2,  #1
   2702        vneg.s32        d31, d31      // -log2sz
   2703        bx              r7
   2704 
   2705        .align 2
   2706 L(ipred_cfl_ac_444_tbl):
   2707        .word L(ipred_cfl_ac_444_w32) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
   2708        .word L(ipred_cfl_ac_444_w16) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
   2709        .word L(ipred_cfl_ac_444_w8)  - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
   2710        .word L(ipred_cfl_ac_444_w4)  - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
   2711 
   2712 L(ipred_cfl_ac_444_w4):
   2713 1:      // Copy and expand input
   2714        vld1.32         {d0[]},  [r1,  :32], r2
   2715        vld1.32         {d0[1]}, [r12, :32], r2
   2716        vld1.32         {d2[]},  [r1,  :32], r2
   2717        vld1.32         {d2[1]}, [r12, :32], r2
   2718        vshll.u8        q0,  d0,  #3
   2719        vshll.u8        q1,  d2,  #3
   2720        subs            r8,  r8,  #4
   2721        vst1.16         {q0, q1}, [r0, :128]!
   2722        vadd.i16        q8,  q8,  q0
   2723        vadd.i16        q9,  q9,  q1
   2724        bgt             1b
   2725        cmp             r4,  #0
   2726        vmov            d0,  d3
   2727        vmov            d1,  d3
   2728        vmov            d2,  d3
   2729        b               L(ipred_cfl_ac_420_w4_hpad)
   2730 
   2731 L(ipred_cfl_ac_444_w8):
   2732 1:      // Copy and expand input
   2733        vld1.16         {d0}, [r1,  :64], r2
   2734        vld1.16         {d2}, [r12, :64], r2
   2735        vld1.16         {d4}, [r1,  :64], r2
   2736        vshll.u8        q0,  d0,  #3
   2737        vld1.16         {d6}, [r12, :64], r2
   2738        vshll.u8        q1,  d2,  #3
   2739        vshll.u8        q2,  d4,  #3
   2740        vshll.u8        q3,  d6,  #3
   2741        subs            r8,  r8,  #4
   2742        vst1.16         {q0, q1}, [r0, :128]!
   2743        vadd.i16        q8,  q8,  q0
   2744        vadd.i16        q9,  q9,  q1
   2745        vst1.16         {q2, q3}, [r0, :128]!
   2746        vadd.i16        q10, q10, q2
   2747        vadd.i16        q11, q11, q3
   2748        bgt             1b
   2749        cmp             r4,  #0
   2750        vmov            q0,  q3
   2751        vmov            q1,  q3
   2752        b               L(ipred_cfl_ac_420_w8_hpad)
   2753 
   2754 L(ipred_cfl_ac_444_w16):
   2755        cmp             r3,  #0
   2756        bne             L(ipred_cfl_ac_444_w16_wpad)
   2757 1:      // Copy and expand input, without padding
   2758        vld1.8          {q1}, [r1,  :128], r2
   2759        vld1.8          {q3}, [r12, :128], r2
   2760        vshll.u8        q0,  d2,  #3
   2761        vshll.u8        q1,  d3,  #3
   2762        vshll.u8        q2,  d6,  #3
   2763        vshll.u8        q3,  d7,  #3
   2764        subs            r8,  r8,  #2
   2765        vst1.16         {q0, q1}, [r0, :128]!
   2766        vadd.i16        q8,  q8,  q0
   2767        vadd.i16        q9,  q9,  q1
   2768        vst1.16         {q2, q3}, [r0, :128]!
   2769        vadd.i16        q10, q10, q2
   2770        vadd.i16        q11, q11, q3
   2771        bgt             1b
   2772        cmp             r4,  #0
   2773        vmov            q0,  q2
   2774        vmov            q1,  q3
   2775        b               L(ipred_cfl_ac_420_w16_hpad)
   2776 
   2777 L(ipred_cfl_ac_444_w16_wpad):
   2778 1:      // Copy and expand input, padding 8
   2779        vld1.8          {d0}, [r1,  :64], r2
   2780        vld1.8          {d4}, [r12, :64], r2
   2781        vshll.u8        q0,  d0,  #3
   2782        vshll.u8        q2,  d4,  #3
   2783        vdup.16         q1,  d1[3]
   2784        vdup.16         q3,  d5[3]
   2785        subs            r8,  r8,  #2
   2786        vst1.16         {q0, q1}, [r0, :128]!
   2787        vadd.i16        q8,  q8,  q0
   2788        vadd.i16        q9,  q9,  q1
   2789        vst1.16         {q2, q3}, [r0, :128]!
   2790        vadd.i16        q10, q10, q2
   2791        vadd.i16        q11, q11, q3
   2792        bgt             1b
   2793        cmp             r4,  #0
   2794        vmov            q0,  q2
   2795        vmov            q1,  q3
   2796        b               L(ipred_cfl_ac_420_w16_hpad)
   2797 
   2798 L(ipred_cfl_ac_444_w32):
   2799        adr             r7,  L(ipred_cfl_ac_444_w32_tbl)
   2800        ldr             r3,  [r7, r3, lsl #1] // (w3>>1) << 2
   2801        add             r7,  r7,  r3
   2802        bx              r7
   2803 
   2804        .align 2
   2805 L(ipred_cfl_ac_444_w32_tbl):
   2806        .word L(ipred_cfl_ac_444_w32_wpad0) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
   2807        .word L(ipred_cfl_ac_444_w32_wpad2) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
   2808        .word L(ipred_cfl_ac_444_w32_wpad4) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
   2809        .word L(ipred_cfl_ac_444_w32_wpad6) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
   2810 
   2811 L(ipred_cfl_ac_444_w32_wpad0):
   2812 1:      // Copy and expand input, without padding
   2813        vld1.8          {q2, q3},   [r1,  :128], r2
   2814        vld1.8          {q13, q14}, [r12, :128], r2
   2815        vshll.u8        q0,  d4,  #3
   2816        vshll.u8        q1,  d5,  #3
   2817        vshll.u8        q2,  d6,  #3
   2818        vshll.u8        q3,  d7,  #3
   2819        vshll.u8        q12, d26, #3
   2820        vshll.u8        q13, d27, #3
   2821        subs            r8,  r8,  #2
   2822        vst1.16         {q0, q1},   [r0, :128]!
   2823        vadd.i16        q8,  q8,  q0
   2824        vadd.i16        q9,  q9,  q1
   2825        vshll.u8        q0,  d28, #3
   2826        vshll.u8        q1,  d29, #3
   2827        vst1.16         {q2, q3},   [r0, :128]!
   2828        vadd.i16        q10, q10, q2
   2829        vadd.i16        q11, q11, q3
   2830        vst1.16         {q12, q13}, [r0, :128]!
   2831        vadd.i16        q8,  q8,  q12
   2832        vadd.i16        q9,  q9,  q13
   2833        vst1.16         {q0, q1},   [r0, :128]!
   2834        vadd.i16        q10, q10, q0
   2835        vadd.i16        q11, q11, q1
   2836        bgt             1b
   2837        cmp             r4,  #0
   2838        b               L(ipred_cfl_ac_444_w32_hpad)
   2839 
   2840 L(ipred_cfl_ac_444_w32_wpad2):
   2841 1:      // Copy and expand input, padding 8
   2842        vldr            d4,    [r1,  #16]
   2843        vld1.8          {q1},  [r1,  :128], r2
   2844        vldr            d28,   [r12, #16]
   2845        vld1.8          {q13}, [r12, :128], r2
   2846        vshll.u8        q2,  d4,  #3
   2847        vshll.u8        q0,  d2,  #3
   2848        vshll.u8        q1,  d3,  #3
   2849        vshll.u8        q12, d26, #3
   2850        vshll.u8        q13, d27, #3
   2851        vdup.16         q3,  d5[3]
   2852        subs            r8,  r8,  #2
   2853        vst1.16         {q0, q1},   [r0, :128]!
   2854        vadd.i16        q8,  q8,  q0
   2855        vadd.i16        q9,  q9,  q1
   2856        vshll.u8        q0,  d28, #3
   2857        vst1.16         {q2, q3},   [r0, :128]!
   2858        vadd.i16        q10, q10, q2
   2859        vadd.i16        q11, q11, q3
   2860        vdup.16         q1,  d1[3]
   2861        vst1.16         {q12, q13}, [r0, :128]!
   2862        vadd.i16        q8,  q8,  q12
   2863        vadd.i16        q9,  q9,  q13
   2864        vst1.16         {q0, q1},   [r0, :128]!
   2865        vadd.i16        q10, q10, q0
   2866        vadd.i16        q11, q11, q1
   2867        bgt             1b
   2868        cmp             r4,  #0
   2869        b               L(ipred_cfl_ac_444_w32_hpad)
   2870 
   2871 L(ipred_cfl_ac_444_w32_wpad4):
   2872 1:      // Copy and expand input, padding 16
   2873        vld1.8          {q1},  [r1,  :128], r2
   2874        vld1.8          {q13}, [r12, :128], r2
   2875        vshll.u8        q0,  d2,  #3
   2876        vshll.u8        q1,  d3,  #3
   2877        vshll.u8        q12, d26, #3
   2878        vshll.u8        q13, d27, #3
   2879        vdup.16         q2,  d3[3]
   2880        vdup.16         q3,  d3[3]
   2881        subs            r8,  r8,  #2
   2882        vst1.16         {q0, q1},   [r0, :128]!
   2883        vadd.i16        q8,  q8,  q0
   2884        vadd.i16        q9,  q9,  q1
   2885        vdup.16         q0,  d27[3]
   2886        vdup.16         q1,  d27[3]
   2887        vst1.16         {q2, q3},   [r0, :128]!
   2888        vadd.i16        q10, q10, q2
   2889        vadd.i16        q11, q11, q3
   2890        vst1.16         {q12, q13}, [r0, :128]!
   2891        vadd.i16        q8,  q8,  q12
   2892        vadd.i16        q9,  q9,  q13
   2893        vst1.16         {q0, q1},   [r0, :128]!
   2894        vadd.i16        q10, q10, q0
   2895        vadd.i16        q11, q11, q1
   2896        bgt             1b
   2897        cmp             r4,  #0
   2898        b               L(ipred_cfl_ac_444_w32_hpad)
   2899 
   2900 L(ipred_cfl_ac_444_w32_wpad6):
   2901 1:      // Copy and expand input, padding 24
   2902        vld1.8          {d0},  [r1,  :64], r2
   2903        vld1.8          {d24}, [r12, :64], r2
   2904        vshll.u8        q0,  d0,  #3
   2905        vshll.u8        q12, d24, #3
   2906        subs            r8,  r8,  #2
   2907        vdup.16         q1,  d1[3]
   2908        vdup.16         q2,  d1[3]
   2909        vdup.16         q3,  d1[3]
   2910        vst1.16         {q0, q1},   [r0, :128]!
   2911        vadd.i16        q8,  q8,  q0
   2912        vadd.i16        q9,  q9,  q1
   2913        vdup.16         q13, d25[3]
   2914        vdup.16         q0,  d25[3]
   2915        vdup.16         q1,  d25[3]
   2916        vst1.16         {q2, q3},   [r0, :128]!
   2917        vadd.i16        q10, q10, q2
   2918        vadd.i16        q11, q11, q3
   2919        vst1.16         {q12, q13}, [r0, :128]!
   2920        vadd.i16        q8,  q8,  q12
   2921        vadd.i16        q9,  q9,  q13
   2922        vst1.16         {q0, q1},   [r0, :128]!
   2923        vadd.i16        q10, q10, q0
   2924        vadd.i16        q11, q11, q1
   2925        bgt             1b
   2926        cmp             r4,  #0
   2927 
   2928 L(ipred_cfl_ac_444_w32_hpad):
   2929        beq             3f // This assumes that all callers already did "cmp r4, #0"
   2930 2:      // Vertical padding (h_pad > 0)
   2931        subs            r4,  r4,  #1
   2932        vst1.16         {q12, q13}, [r0, :128]!
   2933        vadd.i16        q8,  q8,  q12
   2934        vadd.i16        q9,  q9,  q13
   2935        vst1.16         {q0, q1},   [r0, :128]!
   2936        vadd.i16        q10, q10, q0
   2937        vadd.i16        q11, q11, q1
   2938        bgt             2b
   2939 3:
   2940 
   2941        //  Multiply the height by eight and reuse the w4 subtracting
   2942        lsl             r6,  r6,  #3
   2943        // Aggregate the sums, with wider intermediates earlier than in
   2944        // ipred_cfl_ac_420_w8_calc_subtract_dc.
   2945        vpaddl.u16      q0,  q8
   2946        vpaddl.u16      q1,  q9
   2947        vpaddl.u16      q2,  q10
   2948        vpaddl.u16      q3,  q11
   2949        vadd.i32        q0,  q0,  q1
   2950        vadd.i32        q2,  q2,  q3
   2951        vadd.i32        q0,  q0,  q2
   2952        vadd.i32        d0,  d0,  d1
   2953        vpadd.i32       d0,  d0,  d0  // sum
   2954        sub             r0,  r0,  r6, lsl #3
   2955        vrshl.u32       d16, d0,  d31 // (sum + (1 << (log2sz - 1))) >>= log2sz
   2956        vdup.16         q8,  d16[0]
   2957        b               L(ipred_cfl_ac_420_w4_subtract_dc)
   2958 endfunc