tor-browser

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

cdef_tmpl.S (19319B)


      1 /*
      2 * Copyright © 2018, VideoLAN and dav1d authors
      3 * Copyright © 2020, Martin Storsjo
      4 * All rights reserved.
      5 *
      6 * Redistribution and use in source and binary forms, with or without
      7 * modification, are permitted provided that the following conditions are met:
      8 *
      9 * 1. Redistributions of source code must retain the above copyright notice, this
     10 *    list of conditions and the following disclaimer.
     11 *
     12 * 2. Redistributions in binary form must reproduce the above copyright notice,
     13 *    this list of conditions and the following disclaimer in the documentation
     14 *    and/or other materials provided with the distribution.
     15 *
     16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 */
     27 
     28 #include "src/arm/asm.S"
     29 #include "util.S"
     30 
     31 .macro dir_table w, stride
     32 const directions\w
     33        .byte           -1 * \stride + 1, -2 * \stride + 2
     34        .byte            0 * \stride + 1, -1 * \stride + 2
     35        .byte            0 * \stride + 1,  0 * \stride + 2
     36        .byte            0 * \stride + 1,  1 * \stride + 2
     37        .byte            1 * \stride + 1,  2 * \stride + 2
     38        .byte            1 * \stride + 0,  2 * \stride + 1
     39        .byte            1 * \stride + 0,  2 * \stride + 0
     40        .byte            1 * \stride + 0,  2 * \stride - 1
     41 // Repeated, to avoid & 7
     42        .byte           -1 * \stride + 1, -2 * \stride + 2
     43        .byte            0 * \stride + 1, -1 * \stride + 2
     44        .byte            0 * \stride + 1,  0 * \stride + 2
     45        .byte            0 * \stride + 1,  1 * \stride + 2
     46        .byte            1 * \stride + 1,  2 * \stride + 2
     47        .byte            1 * \stride + 0,  2 * \stride + 1
     48 endconst
     49 .endm
     50 
     51 .macro tables
     52 dir_table 8, 16
     53 dir_table 4, 8
     54 
     55 const pri_taps
     56        .byte           4, 2, 3, 3
     57 endconst
     58 .endm
     59 
     60 .macro load_px d11, d12, d21, d22, w
     61 .if \w == 8
     62        add             r6,  r2,  r9, lsl #1 // x + off
     63        sub             r9,  r2,  r9, lsl #1 // x - off
     64        vld1.16         {\d11,\d12}, [r6]    // p0
     65        vld1.16         {\d21,\d22}, [r9]    // p1
     66 .else
     67        add             r6,  r2,  r9, lsl #1 // x + off
     68        sub             r9,  r2,  r9, lsl #1 // x - off
     69        vld1.16         {\d11}, [r6]         // p0
     70        add             r6,  r6,  #2*8       // += stride
     71        vld1.16         {\d21}, [r9]         // p1
     72        add             r9,  r9,  #2*8       // += stride
     73        vld1.16         {\d12}, [r6]         // p0
     74        vld1.16         {\d22}, [r9]         // p1
     75 .endif
     76 .endm
     77 .macro handle_pixel s1, s2, thresh_vec, shift, tap, min
     78 .if \min
     79        vmin.u16        q2,  q2,  \s1
     80        vmax.s16        q3,  q3,  \s1
     81        vmin.u16        q2,  q2,  \s2
     82        vmax.s16        q3,  q3,  \s2
     83 .endif
     84        vabd.u16        q8,  q0,  \s1        // abs(diff)
     85        vabd.u16        q11, q0,  \s2        // abs(diff)
     86        vshl.u16        q9,  q8,  \shift     // abs(diff) >> shift
     87        vshl.u16        q12, q11, \shift     // abs(diff) >> shift
     88        vqsub.u16       q9,  \thresh_vec, q9 // clip = imax(0, threshold - (abs(diff) >> shift))
     89        vqsub.u16       q12, \thresh_vec, q12// clip = imax(0, threshold - (abs(diff) >> shift))
     90        vsub.i16        q10, \s1, q0         // diff = p0 - px
     91        vsub.i16        q13, \s2, q0         // diff = p1 - px
     92        vneg.s16        q8,  q9              // -clip
     93        vneg.s16        q11, q12             // -clip
     94        vmin.s16        q10, q10, q9         // imin(diff, clip)
     95        vmin.s16        q13, q13, q12        // imin(diff, clip)
     96        vdup.16         q9,  \tap            // taps[k]
     97        vmax.s16        q10, q10, q8         // constrain() = imax(imin(diff, clip), -clip)
     98        vmax.s16        q13, q13, q11        // constrain() = imax(imin(diff, clip), -clip)
     99        vmla.i16        q1,  q10, q9         // sum += taps[k] * constrain()
    100        vmla.i16        q1,  q13, q9         // sum += taps[k] * constrain()
    101 .endm
    102 
    103 // void dav1d_cdef_filterX_Ybpc_neon(pixel *dst, ptrdiff_t dst_stride,
    104 //                                   const uint16_t *tmp, int pri_strength,
    105 //                                   int sec_strength, int dir, int damping,
    106 //                                   int h, size_t edges);
    107 .macro filter_func w, bpc, pri, sec, min, suffix
    108 function cdef_filter\w\suffix\()_\bpc\()bpc_neon
    109 .if \bpc == 8
    110        cmp             r8,  #0xf
    111        beq             cdef_filter\w\suffix\()_edged_neon
    112 .endif
    113 .if \pri
    114 .if \bpc == 16
    115        clz             r9,  r9
    116        sub             r9,  r9,  #24        // -bitdepth_min_8
    117        neg             r9,  r9              // bitdepth_min_8
    118 .endif
    119        movrel_local    r8,  pri_taps
    120 .if \bpc == 16
    121        lsr             r9,  r3,  r9         // pri_strength >> bitdepth_min_8
    122        and             r9,  r9,  #1         // (pri_strength >> bitdepth_min_8) & 1
    123 .else
    124        and             r9,  r3,  #1
    125 .endif
    126        add             r8,  r8,  r9, lsl #1
    127 .endif
    128        movrel_local    r9,  directions\w
    129        add             r5,  r9,  r5, lsl #1
    130        vmov.u16        d17, #15
    131        vdup.16         d16, r6              // damping
    132 
    133 .if \pri
    134        vdup.16         q5,  r3              // threshold
    135 .endif
    136 .if \sec
    137        vdup.16         q7,  r4              // threshold
    138 .endif
    139        vmov.16         d8[0], r3
    140        vmov.16         d8[1], r4
    141        vclz.i16        d8,  d8              // clz(threshold)
    142        vsub.i16        d8,  d17, d8         // ulog2(threshold)
    143        vqsub.u16       d8,  d16, d8         // shift = imax(0, damping - ulog2(threshold))
    144        vneg.s16        d8,  d8              // -shift
    145 .if \sec
    146        vdup.16         q6,  d8[1]
    147 .endif
    148 .if \pri
    149        vdup.16         q4,  d8[0]
    150 .endif
    151 
    152 1:
    153 .if \w == 8
    154        vld1.16         {q0},  [r2, :128]    // px
    155 .else
    156        add             r12, r2,  #2*8
    157        vld1.16         {d0},  [r2,  :64]    // px
    158        vld1.16         {d1},  [r12, :64]    // px
    159 .endif
    160 
    161        vmov.u16        q1,  #0              // sum
    162 .if \min
    163        vmov.u16        q2,  q0              // min
    164        vmov.u16        q3,  q0              // max
    165 .endif
    166 
    167        // Instead of loading sec_taps 2, 1 from memory, just set it
    168        // to 2 initially and decrease for the second round.
    169        // This is also used as loop counter.
    170        mov             lr,  #2              // sec_taps[0]
    171 
    172 2:
    173 .if \pri
    174        ldrsb           r9,  [r5]            // off1
    175 
    176        load_px         d28, d29, d30, d31, \w
    177 .endif
    178 
    179 .if \sec
    180        add             r5,  r5,  #4         // +2*2
    181        ldrsb           r9,  [r5]            // off2
    182 .endif
    183 
    184 .if \pri
    185        ldrb            r12, [r8]            // *pri_taps
    186 
    187        handle_pixel    q14, q15, q5,  q4,  r12, \min
    188 .endif
    189 
    190 .if \sec
    191        load_px         d28, d29, d30, d31, \w
    192 
    193        add             r5,  r5,  #8         // +2*4
    194        ldrsb           r9,  [r5]            // off3
    195 
    196        handle_pixel    q14, q15, q7,  q6,  lr, \min
    197 
    198        load_px         d28, d29, d30, d31, \w
    199 
    200        handle_pixel    q14, q15, q7,  q6,  lr, \min
    201 
    202        sub             r5,  r5,  #11        // r5 -= 2*(2+4); r5 += 1;
    203 .else
    204        add             r5,  r5,  #1         // r5 += 1
    205 .endif
    206        subs            lr,  lr,  #1         // sec_tap-- (value)
    207 .if \pri
    208        add             r8,  r8,  #1         // pri_taps++ (pointer)
    209 .endif
    210        bne             2b
    211 
    212        vshr.s16        q14, q1,  #15        // -(sum < 0)
    213        vadd.i16        q1,  q1,  q14        // sum - (sum < 0)
    214        vrshr.s16       q1,  q1,  #4         // (8 + sum - (sum < 0)) >> 4
    215        vadd.i16        q0,  q0,  q1         // px + (8 + sum ...) >> 4
    216 .if \min
    217        vmin.s16        q0,  q0,  q3
    218        vmax.s16        q0,  q0,  q2         // iclip(px + .., min, max)
    219 .endif
    220 .if \bpc == 8
    221        vmovn.u16       d0,  q0
    222 .endif
    223 .if \w == 8
    224        add             r2,  r2,  #2*16      // tmp += tmp_stride
    225        subs            r7,  r7,  #1         // h--
    226 .if \bpc == 8
    227        vst1.8          {d0}, [r0, :64], r1
    228 .else
    229        vst1.16         {q0}, [r0, :128], r1
    230 .endif
    231 .else
    232 .if \bpc == 8
    233        vst1.32         {d0[0]}, [r0, :32], r1
    234 .else
    235        vst1.16         {d0},    [r0, :64], r1
    236 .endif
    237        add             r2,  r2,  #2*16      // tmp += 2*tmp_stride
    238        subs            r7,  r7,  #2         // h -= 2
    239 .if \bpc == 8
    240        vst1.32         {d0[1]}, [r0, :32], r1
    241 .else
    242        vst1.16         {d1},    [r0, :64], r1
    243 .endif
    244 .endif
    245 
    246        // Reset pri_taps and directions back to the original point
    247        sub             r5,  r5,  #2
    248 .if \pri
    249        sub             r8,  r8,  #2
    250 .endif
    251 
    252        bgt             1b
    253        vpop            {q4-q7}
    254        pop             {r4-r9,pc}
    255 endfunc
    256 .endm
    257 
    258 .macro filter w, bpc
    259 filter_func \w, \bpc, pri=1, sec=0, min=0, suffix=_pri
    260 filter_func \w, \bpc, pri=0, sec=1, min=0, suffix=_sec
    261 filter_func \w, \bpc, pri=1, sec=1, min=1, suffix=_pri_sec
    262 
    263 function cdef_filter\w\()_\bpc\()bpc_neon, export=1
    264        push            {r4-r9,lr}
    265        vpush           {q4-q7}
    266        ldrd            r4,  r5,  [sp, #92]
    267        ldrd            r6,  r7,  [sp, #100]
    268 .if \bpc == 16
    269        ldrd            r8,  r9,  [sp, #108]
    270 .else
    271        ldr             r8,  [sp, #108]
    272 .endif
    273        cmp             r3,  #0 // pri_strength
    274        bne             1f
    275        b               cdef_filter\w\()_sec_\bpc\()bpc_neon // only sec
    276 1:
    277        cmp             r4,  #0 // sec_strength
    278        bne             1f
    279        b               cdef_filter\w\()_pri_\bpc\()bpc_neon // only pri
    280 1:
    281        b               cdef_filter\w\()_pri_sec_\bpc\()bpc_neon // both pri and sec
    282 endfunc
    283 .endm
    284 
    285 const div_table, align=4
    286        .short         840, 420, 280, 210, 168, 140, 120, 105
    287 endconst
    288 
    289 const alt_fact, align=4
    290        .short         420, 210, 140, 105, 105, 105, 105, 105, 140, 210, 420, 0
    291 endconst
    292 
    293 .macro cost_alt dest, s1, s2, s3, s4, s5, s6
    294        vmull.s16       q1,  \s1, \s1          // sum_alt[n]*sum_alt[n]
    295        vmull.s16       q2,  \s2, \s2
    296        vmull.s16       q3,  \s3, \s3
    297        vmull.s16       q5,  \s4, \s4          // sum_alt[n]*sum_alt[n]
    298        vmull.s16       q12, \s5, \s5
    299        vmull.s16       q6,  \s6, \s6          // q6 overlaps the first \s1-\s2 here
    300        vmul.i32        q1,  q1,  q13          // sum_alt[n]^2*fact
    301        vmla.i32        q1,  q2,  q14
    302        vmla.i32        q1,  q3,  q15
    303        vmul.i32        q5,  q5,  q13          // sum_alt[n]^2*fact
    304        vmla.i32        q5,  q12, q14
    305        vmla.i32        q5,  q6,  q15
    306        vadd.i32        d2,  d2,  d3
    307        vadd.i32        d3,  d10, d11
    308        vpadd.i32       \dest, d2, d3          // *cost_ptr
    309 .endm
    310 
    311 .macro find_best s1, s2, s3
    312 .ifnb \s2
    313        vmov.32         lr,  \s2
    314 .endif
    315        cmp             r12, r1                // cost[n] > best_cost
    316        itt             gt
    317        movgt           r0,  r3                // best_dir = n
    318        movgt           r1,  r12               // best_cost = cost[n]
    319 .ifnb \s2
    320        add             r3,  r3,  #1           // n++
    321        cmp             lr,  r1                // cost[n] > best_cost
    322        vmov.32         r12, \s3
    323        itt             gt
    324        movgt           r0,  r3                // best_dir = n
    325        movgt           r1,  lr                // best_cost = cost[n]
    326        add             r3,  r3,  #1           // n++
    327 .endif
    328 .endm
    329 
    330 // int dav1d_cdef_find_dir_Xbpc_neon(const pixel *img, const ptrdiff_t stride,
    331 //                                   unsigned *const var)
    332 .macro find_dir bpc
    333 function cdef_find_dir_\bpc\()bpc_neon, export=1
    334        push            {lr}
    335        vpush           {q4-q7}
    336 .if \bpc == 16
    337        clz             r3,  r3                // clz(bitdepth_max)
    338        sub             lr,  r3,  #24          // -bitdepth_min_8
    339 .endif
    340        sub             sp,  sp,  #32          // cost
    341        mov             r3,  #8
    342        vmov.u16        q1,  #0                // q0-q1   sum_diag[0]
    343        vmov.u16        q3,  #0                // q2-q3   sum_diag[1]
    344        vmov.u16        q5,  #0                // q4-q5   sum_hv[0-1]
    345        vmov.u16        q8,  #0                // q6,d16  sum_alt[0]
    346                                               // q7,d17  sum_alt[1]
    347        vmov.u16        q9,  #0                // q9,d22  sum_alt[2]
    348        vmov.u16        q11, #0
    349        vmov.u16        q10, #0                // q10,d23 sum_alt[3]
    350 
    351 
    352 .irpc i, 01234567
    353 .if \bpc == 8
    354        vld1.8          {d30}, [r0, :64], r1
    355        vmov.u8         d31, #128
    356        vsubl.u8        q15, d30, d31          // img[x] - 128
    357 .else
    358        vld1.16         {q15}, [r0, :128], r1
    359        vdup.16         q14, lr                // -bitdepth_min_8
    360        vshl.u16        q15, q15, q14
    361        vmov.u16        q14, #128
    362        vsub.i16        q15, q15, q14          // img[x] - 128
    363 .endif
    364        vmov.u16        q14, #0
    365 
    366 .if \i == 0
    367        vmov            q0,  q15               // sum_diag[0]
    368 .else
    369        vext.8          q12, q14, q15, #(16-2*\i)
    370        vext.8          q13, q15, q14, #(16-2*\i)
    371        vadd.i16        q0,  q0,  q12          // sum_diag[0]
    372        vadd.i16        q1,  q1,  q13          // sum_diag[0]
    373 .endif
    374        vrev64.16       q13, q15
    375        vswp            d26, d27               // [-x]
    376 .if \i == 0
    377        vmov            q2,  q13               // sum_diag[1]
    378 .else
    379        vext.8          q12, q14, q13, #(16-2*\i)
    380        vext.8          q13, q13, q14, #(16-2*\i)
    381        vadd.i16        q2,  q2,  q12          // sum_diag[1]
    382        vadd.i16        q3,  q3,  q13          // sum_diag[1]
    383 .endif
    384 
    385        vpadd.u16       d26, d30, d31          // [(x >> 1)]
    386        vmov.u16        d27, #0
    387        vpadd.u16       d24, d26, d28
    388        vpadd.u16       d24, d24, d28          // [y]
    389        vmov.u16        r12, d24[0]
    390        vadd.i16        q5,  q5,  q15          // sum_hv[1]
    391 .if \i < 4
    392        vmov.16         d8[\i],   r12          // sum_hv[0]
    393 .else
    394        vmov.16         d9[\i-4], r12          // sum_hv[0]
    395 .endif
    396 
    397 .if \i == 0
    398        vmov.u16        q6,  q13               // sum_alt[0]
    399 .else
    400        vext.8          q12, q14, q13, #(16-2*\i)
    401        vext.8          q14, q13, q14, #(16-2*\i)
    402        vadd.i16        q6,  q6,  q12          // sum_alt[0]
    403        vadd.i16        d16, d16, d28          // sum_alt[0]
    404 .endif
    405        vrev64.16       d26, d26               // [-(x >> 1)]
    406        vmov.u16        q14, #0
    407 .if \i == 0
    408        vmov            q7,  q13               // sum_alt[1]
    409 .else
    410        vext.8          q12, q14, q13, #(16-2*\i)
    411        vext.8          q13, q13, q14, #(16-2*\i)
    412        vadd.i16        q7,  q7,  q12          // sum_alt[1]
    413        vadd.i16        d17, d17, d26          // sum_alt[1]
    414 .endif
    415 
    416 .if \i < 6
    417        vext.8          q12, q14, q15, #(16-2*(3-(\i/2)))
    418        vext.8          q13, q15, q14, #(16-2*(3-(\i/2)))
    419        vadd.i16        q9,  q9,  q12          // sum_alt[2]
    420        vadd.i16        d22, d22, d26          // sum_alt[2]
    421 .else
    422        vadd.i16        q9,  q9,  q15          // sum_alt[2]
    423 .endif
    424 .if \i == 0
    425        vmov            q10, q15               // sum_alt[3]
    426 .elseif \i == 1
    427        vadd.i16        q10, q10, q15          // sum_alt[3]
    428 .else
    429        vext.8          q12, q14, q15, #(16-2*(\i/2))
    430        vext.8          q13, q15, q14, #(16-2*(\i/2))
    431        vadd.i16        q10, q10, q12          // sum_alt[3]
    432        vadd.i16        d23, d23, d26          // sum_alt[3]
    433 .endif
    434 .endr
    435 
    436        vmov.u32        q15, #105
    437 
    438        vmull.s16       q12, d8,  d8           // sum_hv[0]*sum_hv[0]
    439        vmlal.s16       q12, d9,  d9
    440        vmull.s16       q13, d10, d10          // sum_hv[1]*sum_hv[1]
    441        vmlal.s16       q13, d11, d11
    442        vadd.s32        d8,  d24, d25
    443        vadd.s32        d9,  d26, d27
    444        vpadd.s32       d8,  d8,  d9           // cost[2,6] (s16, s17)
    445        vmul.i32        d8,  d8,  d30          // cost[2,6] *= 105
    446 
    447        vrev64.16       q1,  q1
    448        vrev64.16       q3,  q3
    449        vext.8          q1,  q1,  q1,  #10     // sum_diag[0][14-n]
    450        vext.8          q3,  q3,  q3,  #10     // sum_diag[1][14-n]
    451 
    452        vstr            s16, [sp, #2*4]        // cost[2]
    453        vstr            s17, [sp, #6*4]        // cost[6]
    454 
    455        movrel_local    r12, div_table
    456        vld1.16         {q14}, [r12, :128]
    457 
    458        vmull.s16       q5,  d0,  d0           // sum_diag[0]*sum_diag[0]
    459        vmull.s16       q12, d1,  d1
    460        vmlal.s16       q5,  d2,  d2
    461        vmlal.s16       q12, d3,  d3
    462        vmull.s16       q0,  d4,  d4           // sum_diag[1]*sum_diag[1]
    463        vmull.s16       q1,  d5,  d5
    464        vmlal.s16       q0,  d6,  d6
    465        vmlal.s16       q1,  d7,  d7
    466        vmovl.u16       q13, d28               // div_table
    467        vmovl.u16       q14, d29
    468        vmul.i32        q5,  q5,  q13          // cost[0]
    469        vmla.i32        q5,  q12, q14
    470        vmul.i32        q0,  q0,  q13          // cost[4]
    471        vmla.i32        q0,  q1,  q14
    472        vadd.i32        d10, d10, d11
    473        vadd.i32        d0,  d0,  d1
    474        vpadd.i32       d0,  d10, d0           // cost[0,4] = s0,s1
    475 
    476        movrel_local    r12, alt_fact
    477        vld1.16         {d29, d30, d31}, [r12, :64] // div_table[2*m+1] + 105
    478 
    479        vstr            s0,  [sp, #0*4]        // cost[0]
    480        vstr            s1,  [sp, #4*4]        // cost[4]
    481 
    482        vmovl.u16       q13, d29               // div_table[2*m+1] + 105
    483        vmovl.u16       q14, d30
    484        vmovl.u16       q15, d31
    485 
    486        cost_alt        d14, d12, d13, d16, d14, d15, d17 // cost[1], cost[3]
    487        cost_alt        d15, d18, d19, d22, d20, d21, d23 // cost[5], cost[7]
    488        vstr            s28, [sp, #1*4]        // cost[1]
    489        vstr            s29, [sp, #3*4]        // cost[3]
    490 
    491        mov             r0,  #0                // best_dir
    492        vmov.32         r1,  d0[0]             // best_cost
    493        mov             r3,  #1                // n
    494 
    495        vstr            s30, [sp, #5*4]        // cost[5]
    496        vstr            s31, [sp, #7*4]        // cost[7]
    497 
    498        vmov.32         r12, d14[0]
    499 
    500        find_best       d14[0], d8[0], d14[1]
    501        find_best       d14[1], d0[1], d15[0]
    502        find_best       d15[0], d8[1], d15[1]
    503        find_best       d15[1]
    504 
    505        eor             r3,  r0,  #4           // best_dir ^4
    506        ldr             r12, [sp, r3, lsl #2]
    507        sub             r1,  r1,  r12          // best_cost - cost[best_dir ^ 4]
    508        lsr             r1,  r1,  #10
    509        str             r1,  [r2]              // *var
    510 
    511        add             sp,  sp,  #32
    512        vpop            {q4-q7}
    513        pop             {pc}
    514 endfunc
    515 .endm