Home | History | Annotate | Download | only in arm
      1 ;
      2 ;  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
      3 ;
      4 ;  Use of this source code is governed by a BSD-style license
      5 ;  that can be found in the LICENSE file in the root of the source
      6 ;  tree. An additional intellectual property rights grant can be found
      7 ;  in the file PATENTS.  All contributing project authors may
      8 ;  be found in the AUTHORS file in the root of the source tree.
      9 ;
     10 
     11     EXPORT  |vpx_lpf_horizontal_16_neon|
     12     EXPORT  |vpx_lpf_horizontal_16_dual_neon|
     13     EXPORT  |vpx_lpf_vertical_16_neon|
     14     EXPORT  |vpx_lpf_vertical_16_dual_neon|
     15     ARM
     16 
     17     AREA ||.text||, CODE, READONLY, ALIGN=2
     18 
     19 ; void mb_lpf_horizontal_edge(uint8_t *s, int p,
     20 ;                             const uint8_t *blimit,
     21 ;                             const uint8_t *limit,
     22 ;                             const uint8_t *thresh,
     23 ;                             int count)
     24 ; r0    uint8_t *s,
     25 ; r1    int p, /* pitch */
     26 ; r2    const uint8_t *blimit,
     27 ; r3    const uint8_t *limit,
     28 ; sp    const uint8_t *thresh,
     29 ; r12   int count
     30 |mb_lpf_horizontal_edge| PROC
     31     push        {r4-r8, lr}
     32     vpush       {d8-d15}
     33     ldr         r4, [sp, #88]              ; load thresh
     34 
     35 h_count
     36     vld1.8      {d16[]}, [r2]              ; load *blimit
     37     vld1.8      {d17[]}, [r3]              ; load *limit
     38     vld1.8      {d18[]}, [r4]              ; load *thresh
     39 
     40     sub         r8, r0, r1, lsl #3         ; move src pointer down by 8 lines
     41 
     42     vld1.u8     {d0}, [r8@64], r1          ; p7
     43     vld1.u8     {d1}, [r8@64], r1          ; p6
     44     vld1.u8     {d2}, [r8@64], r1          ; p5
     45     vld1.u8     {d3}, [r8@64], r1          ; p4
     46     vld1.u8     {d4}, [r8@64], r1          ; p3
     47     vld1.u8     {d5}, [r8@64], r1          ; p2
     48     vld1.u8     {d6}, [r8@64], r1          ; p1
     49     vld1.u8     {d7}, [r8@64], r1          ; p0
     50     vld1.u8     {d8}, [r8@64], r1          ; q0
     51     vld1.u8     {d9}, [r8@64], r1          ; q1
     52     vld1.u8     {d10}, [r8@64], r1         ; q2
     53     vld1.u8     {d11}, [r8@64], r1         ; q3
     54     vld1.u8     {d12}, [r8@64], r1         ; q4
     55     vld1.u8     {d13}, [r8@64], r1         ; q5
     56     vld1.u8     {d14}, [r8@64], r1         ; q6
     57     vld1.u8     {d15}, [r8@64], r1         ; q7
     58 
     59     bl          vpx_wide_mbfilter_neon
     60 
     61     tst         r7, #1
     62     beq         h_mbfilter
     63 
     64     ; flat && mask were not set for any of the channels. Just store the values
     65     ; from filter.
     66     sub         r8, r0, r1, lsl #1
     67 
     68     vst1.u8     {d25}, [r8@64], r1         ; store op1
     69     vst1.u8     {d24}, [r8@64], r1         ; store op0
     70     vst1.u8     {d23}, [r8@64], r1         ; store oq0
     71     vst1.u8     {d26}, [r8@64], r1         ; store oq1
     72 
     73     b           h_next
     74 
     75 h_mbfilter
     76     tst         r7, #2
     77     beq         h_wide_mbfilter
     78 
     79     ; flat2 was not set for any of the channels. Just store the values from
     80     ; mbfilter.
     81     sub         r8, r0, r1, lsl #1
     82     sub         r8, r8, r1
     83 
     84     vst1.u8     {d18}, [r8@64], r1         ; store op2
     85     vst1.u8     {d19}, [r8@64], r1         ; store op1
     86     vst1.u8     {d20}, [r8@64], r1         ; store op0
     87     vst1.u8     {d21}, [r8@64], r1         ; store oq0
     88     vst1.u8     {d22}, [r8@64], r1         ; store oq1
     89     vst1.u8     {d23}, [r8@64], r1         ; store oq2
     90 
     91     b           h_next
     92 
     93 h_wide_mbfilter
     94     sub         r8, r0, r1, lsl #3
     95     add         r8, r8, r1
     96 
     97     vst1.u8     {d16}, [r8@64], r1         ; store op6
     98     vst1.u8     {d24}, [r8@64], r1         ; store op5
     99     vst1.u8     {d25}, [r8@64], r1         ; store op4
    100     vst1.u8     {d26}, [r8@64], r1         ; store op3
    101     vst1.u8     {d27}, [r8@64], r1         ; store op2
    102     vst1.u8     {d18}, [r8@64], r1         ; store op1
    103     vst1.u8     {d19}, [r8@64], r1         ; store op0
    104     vst1.u8     {d20}, [r8@64], r1         ; store oq0
    105     vst1.u8     {d21}, [r8@64], r1         ; store oq1
    106     vst1.u8     {d22}, [r8@64], r1         ; store oq2
    107     vst1.u8     {d23}, [r8@64], r1         ; store oq3
    108     vst1.u8     {d1}, [r8@64], r1          ; store oq4
    109     vst1.u8     {d2}, [r8@64], r1          ; store oq5
    110     vst1.u8     {d3}, [r8@64], r1          ; store oq6
    111 
    112 h_next
    113     add         r0, r0, #8
    114     subs        r12, r12, #1
    115     bne         h_count
    116 
    117     vpop        {d8-d15}
    118     pop         {r4-r8, pc}
    119 
    120     ENDP        ; |mb_lpf_horizontal_edge|
    121 
    122 ; void vpx_lpf_horizontal_16_neon(uint8_t *s, int pitch,
    123 ;                                     const uint8_t *blimit,
    124 ;                                     const uint8_t *limit,
    125 ;                                     const uint8_t *thresh)
    126 ; r0    uint8_t *s,
    127 ; r1    int pitch,
    128 ; r2    const uint8_t *blimit,
    129 ; r3    const uint8_t *limit,
    130 ; sp    const uint8_t *thresh
    131 |vpx_lpf_horizontal_16_neon| PROC
    132     mov r12, #1
    133     b mb_lpf_horizontal_edge
    134     ENDP        ; |vpx_lpf_horizontal_16_neon|
    135 
    136 ; void vpx_lpf_horizontal_16_dual_neon(uint8_t *s, int pitch,
    137 ;                                      const uint8_t *blimit,
    138 ;                                      const uint8_t *limit,
    139 ;                                      const uint8_t *thresh)
    140 ; r0    uint8_t *s,
    141 ; r1    int pitch,
    142 ; r2    const uint8_t *blimit,
    143 ; r3    const uint8_t *limit,
    144 ; sp    const uint8_t *thresh
    145 |vpx_lpf_horizontal_16_dual_neon| PROC
    146     mov r12, #2
    147     b mb_lpf_horizontal_edge
    148     ENDP        ; |vpx_lpf_horizontal_16_dual_neon|
    149 
    150 ; void mb_lpf_vertical_edge_w(uint8_t *s, int p, const uint8_t *blimit,
    151 ;                             const uint8_t *limit, const uint8_t *thresh,
    152 ;                             int count) {
    153 ; r0    uint8_t *s,
    154 ; r1    int p, /* pitch */
    155 ; r2    const uint8_t *blimit,
    156 ; r3    const uint8_t *limit,
    157 ; sp    const uint8_t *thresh,
    158 ; r12   int count
    159 |mb_lpf_vertical_edge_w| PROC
    160     push        {r4-r8, lr}
    161     vpush       {d8-d15}
    162     ldr         r4, [sp, #88]              ; load thresh
    163 
    164 v_count
    165     vld1.8      {d16[]}, [r2]              ; load *blimit
    166     vld1.8      {d17[]}, [r3]              ; load *limit
    167     vld1.8      {d18[]}, [r4]              ; load *thresh
    168 
    169     sub         r8, r0, #8
    170 
    171     vld1.8      {d0}, [r8@64], r1
    172     vld1.8      {d8}, [r0@64], r1
    173     vld1.8      {d1}, [r8@64], r1
    174     vld1.8      {d9}, [r0@64], r1
    175     vld1.8      {d2}, [r8@64], r1
    176     vld1.8      {d10}, [r0@64], r1
    177     vld1.8      {d3}, [r8@64], r1
    178     vld1.8      {d11}, [r0@64], r1
    179     vld1.8      {d4}, [r8@64], r1
    180     vld1.8      {d12}, [r0@64], r1
    181     vld1.8      {d5}, [r8@64], r1
    182     vld1.8      {d13}, [r0@64], r1
    183     vld1.8      {d6}, [r8@64], r1
    184     vld1.8      {d14}, [r0@64], r1
    185     vld1.8      {d7}, [r8@64], r1
    186     vld1.8      {d15}, [r0@64], r1
    187 
    188     sub         r0, r0, r1, lsl #3
    189 
    190     vtrn.32     q0, q2
    191     vtrn.32     q1, q3
    192     vtrn.32     q4, q6
    193     vtrn.32     q5, q7
    194 
    195     vtrn.16     q0, q1
    196     vtrn.16     q2, q3
    197     vtrn.16     q4, q5
    198     vtrn.16     q6, q7
    199 
    200     vtrn.8      d0, d1
    201     vtrn.8      d2, d3
    202     vtrn.8      d4, d5
    203     vtrn.8      d6, d7
    204 
    205     vtrn.8      d8, d9
    206     vtrn.8      d10, d11
    207     vtrn.8      d12, d13
    208     vtrn.8      d14, d15
    209 
    210     bl          vpx_wide_mbfilter_neon
    211 
    212     tst         r7, #1
    213     beq         v_mbfilter
    214 
    215     ; flat && mask were not set for any of the channels. Just store the values
    216     ; from filter.
    217     sub         r0, #2
    218 
    219     vswp        d23, d25
    220 
    221     vst4.8      {d23[0], d24[0], d25[0], d26[0]}, [r0], r1
    222     vst4.8      {d23[1], d24[1], d25[1], d26[1]}, [r0], r1
    223     vst4.8      {d23[2], d24[2], d25[2], d26[2]}, [r0], r1
    224     vst4.8      {d23[3], d24[3], d25[3], d26[3]}, [r0], r1
    225     vst4.8      {d23[4], d24[4], d25[4], d26[4]}, [r0], r1
    226     vst4.8      {d23[5], d24[5], d25[5], d26[5]}, [r0], r1
    227     vst4.8      {d23[6], d24[6], d25[6], d26[6]}, [r0], r1
    228     vst4.8      {d23[7], d24[7], d25[7], d26[7]}, [r0], r1
    229     add         r0, #2
    230 
    231     b           v_next
    232 
    233 v_mbfilter
    234     tst         r7, #2
    235     beq         v_wide_mbfilter
    236 
    237     ; flat2 was not set for any of the channels. Just store the values from
    238     ; mbfilter.
    239     sub         r8, r0, #3
    240 
    241     vst3.8      {d18[0], d19[0], d20[0]}, [r8], r1
    242     vst3.8      {d21[0], d22[0], d23[0]}, [r0], r1
    243     vst3.8      {d18[1], d19[1], d20[1]}, [r8], r1
    244     vst3.8      {d21[1], d22[1], d23[1]}, [r0], r1
    245     vst3.8      {d18[2], d19[2], d20[2]}, [r8], r1
    246     vst3.8      {d21[2], d22[2], d23[2]}, [r0], r1
    247     vst3.8      {d18[3], d19[3], d20[3]}, [r8], r1
    248     vst3.8      {d21[3], d22[3], d23[3]}, [r0], r1
    249     vst3.8      {d18[4], d19[4], d20[4]}, [r8], r1
    250     vst3.8      {d21[4], d22[4], d23[4]}, [r0], r1
    251     vst3.8      {d18[5], d19[5], d20[5]}, [r8], r1
    252     vst3.8      {d21[5], d22[5], d23[5]}, [r0], r1
    253     vst3.8      {d18[6], d19[6], d20[6]}, [r8], r1
    254     vst3.8      {d21[6], d22[6], d23[6]}, [r0], r1
    255     vst3.8      {d18[7], d19[7], d20[7]}, [r8], r1
    256     vst3.8      {d21[7], d22[7], d23[7]}, [r0], r1
    257 
    258     b           v_next
    259 
    260 v_wide_mbfilter
    261     sub         r8, r0, #8
    262 
    263     vtrn.32     d0,  d26
    264     vtrn.32     d16, d27
    265     vtrn.32     d24, d18
    266     vtrn.32     d25, d19
    267 
    268     vtrn.16     d0,  d24
    269     vtrn.16     d16, d25
    270     vtrn.16     d26, d18
    271     vtrn.16     d27, d19
    272 
    273     vtrn.8      d0,  d16
    274     vtrn.8      d24, d25
    275     vtrn.8      d26, d27
    276     vtrn.8      d18, d19
    277 
    278     vtrn.32     d20, d1
    279     vtrn.32     d21, d2
    280     vtrn.32     d22, d3
    281     vtrn.32     d23, d15
    282 
    283     vtrn.16     d20, d22
    284     vtrn.16     d21, d23
    285     vtrn.16     d1,  d3
    286     vtrn.16     d2,  d15
    287 
    288     vtrn.8      d20, d21
    289     vtrn.8      d22, d23
    290     vtrn.8      d1,  d2
    291     vtrn.8      d3,  d15
    292 
    293     vst1.8      {d0}, [r8@64], r1
    294     vst1.8      {d20}, [r0@64], r1
    295     vst1.8      {d16}, [r8@64], r1
    296     vst1.8      {d21}, [r0@64], r1
    297     vst1.8      {d24}, [r8@64], r1
    298     vst1.8      {d22}, [r0@64], r1
    299     vst1.8      {d25}, [r8@64], r1
    300     vst1.8      {d23}, [r0@64], r1
    301     vst1.8      {d26}, [r8@64], r1
    302     vst1.8      {d1}, [r0@64], r1
    303     vst1.8      {d27}, [r8@64], r1
    304     vst1.8      {d2}, [r0@64], r1
    305     vst1.8      {d18}, [r8@64], r1
    306     vst1.8      {d3}, [r0@64], r1
    307     vst1.8      {d19}, [r8@64], r1
    308     vst1.8      {d15}, [r0@64], r1
    309 
    310 v_next
    311     subs        r12, #1
    312     bne         v_count
    313 
    314     vpop        {d8-d15}
    315     pop         {r4-r8, pc}
    316 
    317     ENDP        ; |mb_lpf_vertical_edge_w|
    318 
    319 ; void vpx_lpf_vertical_16_neon(uint8_t *s, int p, const uint8_t *blimit,
    320 ;                               const uint8_t *limit, const uint8_t *thresh)
    321 ; r0    uint8_t *s,
    322 ; r1    int p, /* pitch */
    323 ; r2    const uint8_t *blimit,
    324 ; r3    const uint8_t *limit,
    325 ; sp    const uint8_t *thresh
    326 |vpx_lpf_vertical_16_neon| PROC
    327     mov r12, #1
    328     b mb_lpf_vertical_edge_w
    329     ENDP        ; |vpx_lpf_vertical_16_neon|
    330 
    331 ; void vpx_lpf_vertical_16_dual_neon(uint8_t *s, int p, const uint8_t *blimit,
    332 ;                                    const uint8_t *limit,
    333 ;                                    const uint8_t *thresh)
    334 ; r0    uint8_t *s,
    335 ; r1    int p, /* pitch */
    336 ; r2    const uint8_t *blimit,
    337 ; r3    const uint8_t *limit,
    338 ; sp    const uint8_t *thresh
    339 |vpx_lpf_vertical_16_dual_neon| PROC
    340     mov r12, #2
    341     b mb_lpf_vertical_edge_w
    342     ENDP        ; |vpx_lpf_vertical_16_dual_neon|
    343 
    344 ; void vpx_wide_mbfilter_neon();
    345 ; This is a helper function for the loopfilters. The invidual functions do the
    346 ; necessary load, transpose (if necessary) and store.
    347 ;
    348 ; r0-r3 PRESERVE
    349 ; d16    blimit
    350 ; d17    limit
    351 ; d18    thresh
    352 ; d0    p7
    353 ; d1    p6
    354 ; d2    p5
    355 ; d3    p4
    356 ; d4    p3
    357 ; d5    p2
    358 ; d6    p1
    359 ; d7    p0
    360 ; d8    q0
    361 ; d9    q1
    362 ; d10   q2
    363 ; d11   q3
    364 ; d12   q4
    365 ; d13   q5
    366 ; d14   q6
    367 ; d15   q7
    368 |vpx_wide_mbfilter_neon| PROC
    369     mov         r7, #0
    370 
    371     ; filter_mask
    372     vabd.u8     d19, d4, d5                ; abs(p3 - p2)
    373     vabd.u8     d20, d5, d6                ; abs(p2 - p1)
    374     vabd.u8     d21, d6, d7                ; abs(p1 - p0)
    375     vabd.u8     d22, d9, d8                ; abs(q1 - q0)
    376     vabd.u8     d23, d10, d9               ; abs(q2 - q1)
    377     vabd.u8     d24, d11, d10              ; abs(q3 - q2)
    378 
    379     ; only compare the largest value to limit
    380     vmax.u8     d19, d19, d20              ; max(abs(p3 - p2), abs(p2 - p1))
    381     vmax.u8     d20, d21, d22              ; max(abs(p1 - p0), abs(q1 - q0))
    382     vmax.u8     d23, d23, d24              ; max(abs(q2 - q1), abs(q3 - q2))
    383     vmax.u8     d19, d19, d20
    384 
    385     vabd.u8     d24, d7, d8                ; abs(p0 - q0)
    386 
    387     vmax.u8     d19, d19, d23
    388 
    389     vabd.u8     d23, d6, d9                ; a = abs(p1 - q1)
    390     vqadd.u8    d24, d24, d24              ; b = abs(p0 - q0) * 2
    391 
    392     ; abs () > limit
    393     vcge.u8     d19, d17, d19
    394 
    395     ; flatmask4
    396     vabd.u8     d25, d7, d5                ; abs(p0 - p2)
    397     vabd.u8     d26, d8, d10               ; abs(q0 - q2)
    398     vabd.u8     d27, d4, d7                ; abs(p3 - p0)
    399     vabd.u8     d28, d11, d8               ; abs(q3 - q0)
    400 
    401     ; only compare the largest value to thresh
    402     vmax.u8     d25, d25, d26              ; max(abs(p0 - p2), abs(q0 - q2))
    403     vmax.u8     d26, d27, d28              ; max(abs(p3 - p0), abs(q3 - q0))
    404     vmax.u8     d25, d25, d26
    405     vmax.u8     d20, d20, d25
    406 
    407     vshr.u8     d23, d23, #1               ; a = a / 2
    408     vqadd.u8    d24, d24, d23              ; a = b + a
    409 
    410     vmov.u8     d30, #1
    411     vcge.u8     d24, d16, d24              ; (a > blimit * 2 + limit) * -1
    412 
    413     vcge.u8     d20, d30, d20              ; flat
    414 
    415     vand        d19, d19, d24              ; mask
    416 
    417     ; hevmask
    418     vcgt.u8     d21, d21, d18              ; (abs(p1 - p0) > thresh)*-1
    419     vcgt.u8     d22, d22, d18              ; (abs(q1 - q0) > thresh)*-1
    420     vorr        d21, d21, d22              ; hev
    421 
    422     vand        d16, d20, d19              ; flat && mask
    423     vmov        r5, r6, d16
    424 
    425     ; flatmask5(1, p7, p6, p5, p4, p0, q0, q4, q5, q6, q7)
    426     vabd.u8     d22, d3, d7                ; abs(p4 - p0)
    427     vabd.u8     d23, d12, d8               ; abs(q4 - q0)
    428     vabd.u8     d24, d7, d2                ; abs(p0 - p5)
    429     vabd.u8     d25, d8, d13               ; abs(q0 - q5)
    430     vabd.u8     d26, d1, d7                ; abs(p6 - p0)
    431     vabd.u8     d27, d14, d8               ; abs(q6 - q0)
    432     vabd.u8     d28, d0, d7                ; abs(p7 - p0)
    433     vabd.u8     d29, d15, d8               ; abs(q7 - q0)
    434 
    435     ; only compare the largest value to thresh
    436     vmax.u8     d22, d22, d23              ; max(abs(p4 - p0), abs(q4 - q0))
    437     vmax.u8     d23, d24, d25              ; max(abs(p0 - p5), abs(q0 - q5))
    438     vmax.u8     d24, d26, d27              ; max(abs(p6 - p0), abs(q6 - q0))
    439     vmax.u8     d25, d28, d29              ; max(abs(p7 - p0), abs(q7 - q0))
    440 
    441     vmax.u8     d26, d22, d23
    442     vmax.u8     d27, d24, d25
    443     vmax.u8     d23, d26, d27
    444 
    445     vcge.u8     d18, d30, d23              ; flat2
    446 
    447     vmov.u8     d22, #0x80
    448 
    449     orrs        r5, r5, r6                 ; Check for 0
    450     orreq       r7, r7, #1                 ; Only do filter branch
    451 
    452     vand        d17, d18, d16              ; flat2 && flat && mask
    453     vmov        r5, r6, d17
    454 
    455     ; mbfilter() function
    456 
    457     ; filter() function
    458     ; convert to signed
    459     veor        d23, d8, d22               ; qs0
    460     veor        d24, d7, d22               ; ps0
    461     veor        d25, d6, d22               ; ps1
    462     veor        d26, d9, d22               ; qs1
    463 
    464     vmov.u8     d27, #3
    465 
    466     vsub.s8     d28, d23, d24              ; ( qs0 - ps0)
    467     vqsub.s8    d29, d25, d26              ; filter = clamp(ps1-qs1)
    468     vmull.s8    q15, d28, d27              ; 3 * ( qs0 - ps0)
    469     vand        d29, d29, d21              ; filter &= hev
    470     vaddw.s8    q15, q15, d29              ; filter + 3 * (qs0 - ps0)
    471     vmov.u8     d29, #4
    472 
    473     ; filter = clamp(filter + 3 * ( qs0 - ps0))
    474     vqmovn.s16  d28, q15
    475 
    476     vand        d28, d28, d19              ; filter &= mask
    477 
    478     vqadd.s8    d30, d28, d27              ; filter2 = clamp(filter+3)
    479     vqadd.s8    d29, d28, d29              ; filter1 = clamp(filter+4)
    480     vshr.s8     d30, d30, #3               ; filter2 >>= 3
    481     vshr.s8     d29, d29, #3               ; filter1 >>= 3
    482 
    483 
    484     vqadd.s8    d24, d24, d30              ; op0 = clamp(ps0 + filter2)
    485     vqsub.s8    d23, d23, d29              ; oq0 = clamp(qs0 - filter1)
    486 
    487     ; outer tap adjustments: ++filter1 >> 1
    488     vrshr.s8    d29, d29, #1
    489     vbic        d29, d29, d21              ; filter &= ~hev
    490 
    491     vqadd.s8    d25, d25, d29              ; op1 = clamp(ps1 + filter)
    492     vqsub.s8    d26, d26, d29              ; oq1 = clamp(qs1 - filter)
    493 
    494     veor        d24, d24, d22              ; *f_op0 = u^0x80
    495     veor        d23, d23, d22              ; *f_oq0 = u^0x80
    496     veor        d25, d25, d22              ; *f_op1 = u^0x80
    497     veor        d26, d26, d22              ; *f_oq1 = u^0x80
    498 
    499     tst         r7, #1
    500     bxne        lr
    501 
    502     orrs        r5, r5, r6                 ; Check for 0
    503     orreq       r7, r7, #2                 ; Only do mbfilter branch
    504 
    505     ; mbfilter flat && mask branch
    506     ; TODO(fgalligan): Can I decrease the cycles shifting to consective d's
    507     ; and using vibt on the q's?
    508     vmov.u8     d29, #2
    509     vaddl.u8    q15, d7, d8                ; op2 = p0 + q0
    510     vmlal.u8    q15, d4, d27               ; op2 = p0 + q0 + p3 * 3
    511     vmlal.u8    q15, d5, d29               ; op2 = p0 + q0 + p3 * 3 + p2 * 2
    512     vaddl.u8    q10, d4, d5
    513     vaddw.u8    q15, d6                    ; op2=p1 + p0 + q0 + p3 * 3 + p2 *2
    514     vaddl.u8    q14, d6, d9
    515     vqrshrn.u16 d18, q15, #3               ; r_op2
    516 
    517     vsub.i16    q15, q10
    518     vaddl.u8    q10, d4, d6
    519     vadd.i16    q15, q14
    520     vaddl.u8    q14, d7, d10
    521     vqrshrn.u16 d19, q15, #3               ; r_op1
    522 
    523     vsub.i16    q15, q10
    524     vadd.i16    q15, q14
    525     vaddl.u8    q14, d8, d11
    526     vqrshrn.u16 d20, q15, #3               ; r_op0
    527 
    528     vsubw.u8    q15, d4                    ; oq0 = op0 - p3
    529     vsubw.u8    q15, d7                    ; oq0 -= p0
    530     vadd.i16    q15, q14
    531     vaddl.u8    q14, d9, d11
    532     vqrshrn.u16 d21, q15, #3               ; r_oq0
    533 
    534     vsubw.u8    q15, d5                    ; oq1 = oq0 - p2
    535     vsubw.u8    q15, d8                    ; oq1 -= q0
    536     vadd.i16    q15, q14
    537     vaddl.u8    q14, d10, d11
    538     vqrshrn.u16 d22, q15, #3               ; r_oq1
    539 
    540     vsubw.u8    q15, d6                    ; oq2 = oq0 - p1
    541     vsubw.u8    q15, d9                    ; oq2 -= q1
    542     vadd.i16    q15, q14
    543     vqrshrn.u16 d27, q15, #3               ; r_oq2
    544 
    545     ; Filter does not set op2 or oq2, so use p2 and q2.
    546     vbif        d18, d5, d16               ; t_op2 |= p2 & ~(flat & mask)
    547     vbif        d19, d25, d16              ; t_op1 |= f_op1 & ~(flat & mask)
    548     vbif        d20, d24, d16              ; t_op0 |= f_op0 & ~(flat & mask)
    549     vbif        d21, d23, d16              ; t_oq0 |= f_oq0 & ~(flat & mask)
    550     vbif        d22, d26, d16              ; t_oq1 |= f_oq1 & ~(flat & mask)
    551 
    552     vbit        d23, d27, d16              ; t_oq2 |= r_oq2 & (flat & mask)
    553     vbif        d23, d10, d16              ; t_oq2 |= q2 & ~(flat & mask)
    554 
    555     tst         r7, #2
    556     bxne        lr
    557 
    558     ; wide_mbfilter flat2 && flat && mask branch
    559     vmov.u8     d16, #7
    560     vaddl.u8    q15, d7, d8                ; op6 = p0 + q0
    561     vaddl.u8    q12, d2, d3
    562     vaddl.u8    q13, d4, d5
    563     vaddl.u8    q14, d1, d6
    564     vmlal.u8    q15, d0, d16               ; op6 += p7 * 3
    565     vadd.i16    q12, q13
    566     vadd.i16    q15, q14
    567     vaddl.u8    q14, d2, d9
    568     vadd.i16    q15, q12
    569     vaddl.u8    q12, d0, d1
    570     vaddw.u8    q15, d1
    571     vaddl.u8    q13, d0, d2
    572     vadd.i16    q14, q15, q14
    573     vqrshrn.u16 d16, q15, #4               ; w_op6
    574 
    575     vsub.i16    q15, q14, q12
    576     vaddl.u8    q14, d3, d10
    577     vqrshrn.u16 d24, q15, #4               ; w_op5
    578 
    579     vsub.i16    q15, q13
    580     vaddl.u8    q13, d0, d3
    581     vadd.i16    q15, q14
    582     vaddl.u8    q14, d4, d11
    583     vqrshrn.u16 d25, q15, #4               ; w_op4
    584 
    585     vadd.i16    q15, q14
    586     vaddl.u8    q14, d0, d4
    587     vsub.i16    q15, q13
    588     vsub.i16    q14, q15, q14
    589     vqrshrn.u16 d26, q15, #4               ; w_op3
    590 
    591     vaddw.u8    q15, q14, d5               ; op2 += p2
    592     vaddl.u8    q14, d0, d5
    593     vaddw.u8    q15, d12                   ; op2 += q4
    594     vbif        d26, d4, d17               ; op3 |= p3 & ~(f2 & f & m)
    595     vqrshrn.u16 d27, q15, #4               ; w_op2
    596 
    597     vsub.i16    q15, q14
    598     vaddl.u8    q14, d0, d6
    599     vaddw.u8    q15, d6                    ; op1 += p1
    600     vaddw.u8    q15, d13                   ; op1 += q5
    601     vbif        d27, d18, d17              ; op2 |= t_op2 & ~(f2 & f & m)
    602     vqrshrn.u16 d18, q15, #4               ; w_op1
    603 
    604     vsub.i16    q15, q14
    605     vaddl.u8    q14, d0, d7
    606     vaddw.u8    q15, d7                    ; op0 += p0
    607     vaddw.u8    q15, d14                   ; op0 += q6
    608     vbif        d18, d19, d17              ; op1 |= t_op1 & ~(f2 & f & m)
    609     vqrshrn.u16 d19, q15, #4               ; w_op0
    610 
    611     vsub.i16    q15, q14
    612     vaddl.u8    q14, d1, d8
    613     vaddw.u8    q15, d8                    ; oq0 += q0
    614     vaddw.u8    q15, d15                   ; oq0 += q7
    615     vbif        d19, d20, d17              ; op0 |= t_op0 & ~(f2 & f & m)
    616     vqrshrn.u16 d20, q15, #4               ; w_oq0
    617 
    618     vsub.i16    q15, q14
    619     vaddl.u8    q14, d2, d9
    620     vaddw.u8    q15, d9                    ; oq1 += q1
    621     vaddl.u8    q4, d10, d15
    622     vaddw.u8    q15, d15                   ; oq1 += q7
    623     vbif        d20, d21, d17              ; oq0 |= t_oq0 & ~(f2 & f & m)
    624     vqrshrn.u16 d21, q15, #4               ; w_oq1
    625 
    626     vsub.i16    q15, q14
    627     vaddl.u8    q14, d3, d10
    628     vadd.i16    q15, q4
    629     vaddl.u8    q4, d11, d15
    630     vbif        d21, d22, d17              ; oq1 |= t_oq1 & ~(f2 & f & m)
    631     vqrshrn.u16 d22, q15, #4               ; w_oq2
    632 
    633     vsub.i16    q15, q14
    634     vaddl.u8    q14, d4, d11
    635     vadd.i16    q15, q4
    636     vaddl.u8    q4, d12, d15
    637     vbif        d22, d23, d17              ; oq2 |= t_oq2 & ~(f2 & f & m)
    638     vqrshrn.u16 d23, q15, #4               ; w_oq3
    639 
    640     vsub.i16    q15, q14
    641     vaddl.u8    q14, d5, d12
    642     vadd.i16    q15, q4
    643     vaddl.u8    q4, d13, d15
    644     vbif        d16, d1, d17               ; op6 |= p6 & ~(f2 & f & m)
    645     vqrshrn.u16 d1, q15, #4                ; w_oq4
    646 
    647     vsub.i16    q15, q14
    648     vaddl.u8    q14, d6, d13
    649     vadd.i16    q15, q4
    650     vaddl.u8    q4, d14, d15
    651     vbif        d24, d2, d17               ; op5 |= p5 & ~(f2 & f & m)
    652     vqrshrn.u16 d2, q15, #4                ; w_oq5
    653 
    654     vsub.i16    q15, q14
    655     vbif        d25, d3, d17               ; op4 |= p4 & ~(f2 & f & m)
    656     vadd.i16    q15, q4
    657     vbif        d23, d11, d17              ; oq3 |= q3 & ~(f2 & f & m)
    658     vqrshrn.u16 d3, q15, #4                ; w_oq6
    659     vbif        d1, d12, d17               ; oq4 |= q4 & ~(f2 & f & m)
    660     vbif        d2, d13, d17               ; oq5 |= q5 & ~(f2 & f & m)
    661     vbif        d3, d14, d17               ; oq6 |= q6 & ~(f2 & f & m)
    662 
    663     bx          lr
    664     ENDP        ; |vpx_wide_mbfilter_neon|
    665 
    666     END
    667