Home | History | Annotate | Download | only in neon
      1 ;
      2 ;  Copyright (c) 2010 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 
     12     EXPORT  |vp8_mbloop_filter_vertical_edge_uv_neon|
     13     ARM
     14     REQUIRE8
     15     PRESERVE8
     16 
     17     AREA ||.text||, CODE, READONLY, ALIGN=2
     18 ;Note: flimit, limit, and thresh shpuld be positive numbers. All 16 elements in flimit
     19 ;are equal. So, in the code, only one load is needed
     20 ;for flimit. Same way applies to limit and thresh.
     21 ; r0    unsigned char *u,
     22 ; r1    int p, //pitch
     23 ; r2    const signed char *flimit,
     24 ; r3    const signed char *limit,
     25 ; stack(r4) const signed char *thresh,
     26 ; stack(r5) unsigned char *v
     27 |vp8_mbloop_filter_vertical_edge_uv_neon| PROC
     28     sub         r0, r0, #4                  ; move src pointer down by 4 columns
     29     vld1.s8     {d2[], d3[]}, [r3]          ; limit
     30     ldr         r3, [sp, #4]                ; load v ptr
     31     ldr         r12, [sp, #0]               ; load thresh pointer
     32 
     33     sub         r3, r3, #4                  ; move v pointer down by 4 columns
     34 
     35     vld1.u8     {d6}, [r0], r1              ;load u data
     36     vld1.u8     {d7}, [r3], r1              ;load v data
     37     vld1.u8     {d8}, [r0], r1
     38     vld1.u8     {d9}, [r3], r1
     39     vld1.u8     {d10}, [r0], r1
     40     vld1.u8     {d11}, [r3], r1
     41     vld1.u8     {d12}, [r0], r1
     42     vld1.u8     {d13}, [r3], r1
     43     vld1.u8     {d14}, [r0], r1
     44     vld1.u8     {d15}, [r3], r1
     45     vld1.u8     {d16}, [r0], r1
     46     vld1.u8     {d17}, [r3], r1
     47     vld1.u8     {d18}, [r0], r1
     48     vld1.u8     {d19}, [r3], r1
     49     vld1.u8     {d20}, [r0], r1
     50     vld1.u8     {d21}, [r3], r1
     51 
     52     ;transpose to 8x16 matrix
     53     vtrn.32     q3, q7
     54     vtrn.32     q4, q8
     55     vtrn.32     q5, q9
     56     vtrn.32     q6, q10
     57 
     58     vtrn.16     q3, q5
     59     vtrn.16     q4, q6
     60     vtrn.16     q7, q9
     61     vtrn.16     q8, q10
     62 
     63     vtrn.8      q3, q4
     64     vtrn.8      q5, q6
     65     vtrn.8      q7, q8
     66     vtrn.8      q9, q10
     67 
     68     sub         sp, sp, #32
     69     vld1.s8     {d4[], d5[]}, [r12]         ; thresh
     70     vst1.u8     {q3}, [sp]!
     71     ldr         r12, _mbvlfuv_coeff_
     72     vst1.u8     {q10}, [sp]!
     73 
     74     ;vp8_filter_mask() function
     75     ;vp8_hevmask() function
     76     vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
     77     vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
     78     vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
     79     vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
     80     vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
     81     vabd.u8     q0, q10, q9                 ; abs(q3 - q2)
     82 
     83     vcge.u8     q15, q1, q11                ; (abs(p3 - p2) > limit)*-1
     84     vcge.u8     q12, q1, q12                ; (abs(p2 - p1) > limit)*-1
     85     vcge.u8     q10, q1, q13                ; (abs(p1 - p0) > limit)*-1
     86     vcge.u8     q11, q1, q14                ; (abs(q1 - q0) > limit)*-1
     87     vcge.u8     q3, q1, q3                  ; (abs(q2 - q1) > limit)*-1
     88     vcge.u8     q0, q1, q0                  ; (abs(q3 - q2) > limit)*-1
     89 
     90     vand        q15, q15, q12
     91 
     92     vabd.u8     q12, q6, q7                 ; abs(p0 - q0)
     93 
     94     vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
     95     vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
     96 
     97     vld1.s8     {d4[], d5[]}, [r2]          ; flimit
     98 
     99     vand        q10, q10, q11
    100     vand        q3, q3, q0
    101 
    102     vld1.u8     {q0}, [r12]!
    103 
    104     vadd.u8     q2, q2, q2                  ; flimit * 2
    105     vadd.u8     q2, q2, q1                  ; flimit * 2 + limit
    106 
    107     vabd.u8     q1, q5, q8                  ; abs(p1 - q1)
    108     vqadd.u8    q12, q12, q12               ; abs(p0 - q0) * 2
    109     vshr.u8     q1, q1, #1                  ; abs(p1 - q1) / 2
    110     vqadd.u8    q12, q12, q1                ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
    111     vcge.u8     q12, q2, q12                ; (abs(p0 - q0)*2 + abs(p1 - q1)/2 > flimit*2 + limit)*-1
    112 
    113     vand        q15, q15, q10
    114 
    115     ;vp8_filter() function
    116     veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
    117     veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
    118     veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
    119     veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
    120     veor        q4, q4, q0                  ; ps2: p2 offset to convert to a signed value
    121     veor        q9, q9, q0                  ; qs2: q2 offset to convert to a signed value
    122 ;;;;;;;;;;;;;
    123     vorr        q14, q13, q14               ; q14: vp8_hevmask
    124 
    125     ;vqsub.s8   q2, q7, q6                  ; ( qs0 - ps0)
    126     vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
    127     vsubl.s8    q13, d15, d13
    128 
    129     vqsub.s8    q1, q5, q8                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
    130 
    131     ;vadd.s8    q10, q2, q2                 ; 3 * ( qs0 - ps0)
    132     vadd.s16    q10, q2, q2                 ; 3 * ( qs0 - ps0)
    133     vadd.s16    q11, q13, q13
    134 
    135     vand        q3, q3, q12
    136 
    137     ;vadd.s8    q2, q2, q10
    138     vadd.s16    q2, q2, q10
    139     vadd.s16    q13, q13, q11
    140 
    141     vld1.u8     {q12}, [r12]!               ;#3
    142 
    143     ;vqadd.s8   q1, q1, q2                  ; vp8_filter + 3 * ( qs0 - ps0)
    144     vaddw.s8    q2, q2, d2                  ; vp8_filter + 3 * ( qs0 - ps0)
    145     vaddw.s8    q13, q13, d3
    146 
    147     vand        q15, q15, q3                ; q15: vp8_filter_mask
    148     vld1.u8     {q11}, [r12]!               ;#4
    149 
    150     vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
    151     vqmovn.s16  d3, q13
    152 
    153 ;;;;;;;;;;;;;;
    154     vand        q1, q1, q15                 ; vp8_filter &= mask
    155 
    156     vld1.u8     {q15}, [r12]!               ;#63
    157     ;
    158     vand        q13, q1, q14                ; Filter2: q13; Filter2 &= hev
    159 
    160     vld1.u8     {d7}, [r12]!                ;#9
    161     ;
    162 
    163 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Change for VP8 from VP7
    164 ;   vand        q2, q13, q12                ; s = Filter2 & 7
    165 
    166 ;   vqadd.s8    q13, q13, q11               ; Filter2 = vp8_signed_char_clamp(Filter2+4)
    167 ;   vld1.u8     {d6}, [r12]!                ;#18
    168 
    169 ;   sub         r0, r0, r1, lsl #3
    170 ;   sub         r3, r3, r1, lsl #3
    171 ;   sub         sp, sp, #32
    172 
    173 ;   vshr.s8     q13, q13, #3                ; Filter2 >>= 3
    174 ;   vceq.i8     q2, q2, q11                 ; s = (s==4)*-1
    175 
    176 ;   vqsub.s8    q7, q7, q13                 ; qs0 = vp8_signed_char_clamp(qs0 - Filter2)
    177 ;   vqadd.s8    q11, q2, q13                ; u = vp8_signed_char_clamp(s + Filter2)
    178 
    179 ;   vld1.u8     {d5}, [r12]!                ;#27
    180 ;   vmov        q10, q15
    181 ;   vmov        q12, q15
    182 
    183 ;   vqadd.s8    q6, q6, q11                 ; ps0 = vp8_signed_char_clamp(ps0 + u)
    184 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    185     vqadd.s8    q2, q13, q11                ; Filter1 = vp8_signed_char_clamp(Filter2+4)
    186     vqadd.s8    q13, q13, q12               ; Filter2 = vp8_signed_char_clamp(Filter2+3)
    187 
    188     vld1.u8     {d6}, [r12]!                ;#18
    189 
    190     sub         r0, r0, r1, lsl #3
    191     sub         r3, r3, r1, lsl #3
    192 
    193     vshr.s8     q2, q2, #3                  ; Filter1 >>= 3
    194     vshr.s8     q13, q13, #3                ; Filter2 >>= 3
    195 
    196     vmov        q10, q15
    197     vmov        q12, q15
    198 
    199     vqsub.s8    q7, q7, q2                  ; qs0 = vp8_signed_char_clamp(qs0 - Filter1)
    200 
    201     vld1.u8     {d5}, [r12]!                ;#27
    202 
    203     sub         sp, sp, #32
    204 
    205     vqadd.s8    q6, q6, q13                 ; ps0 = vp8_signed_char_clamp(ps0 + Filter2)
    206 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    207 
    208     vbic        q1, q1, q14                 ; Filter2: q1; vp8_filter &= ~hev; Filter2 = vp8_filter
    209 
    210     ; roughly 1/7th difference across boundary
    211     ; roughly 2/7th difference across boundary
    212     ; roughly 3/7th difference across boundary
    213     vmov        q11, q15
    214     vmov        q13, q15
    215     vmov        q14, q15
    216 
    217     vmlal.s8    q10, d2, d7                 ; Filter2 * 9
    218     vmlal.s8    q11, d3, d7
    219     vmlal.s8    q12, d2, d6                 ; Filter2 * 18
    220     vmlal.s8    q13, d3, d6
    221     vmlal.s8    q14, d2, d5                 ; Filter2 * 27
    222     vmlal.s8    q15, d3, d5
    223     vqshrn.s16  d20, q10, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
    224     vqshrn.s16  d21, q11, #7
    225     vqshrn.s16  d24, q12, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
    226     vqshrn.s16  d25, q13, #7
    227     vqshrn.s16  d28, q14, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
    228     vqshrn.s16  d29, q15, #7
    229 
    230     vqsub.s8    q11, q9, q10                ; s = vp8_signed_char_clamp(qs2 - u)
    231     vqadd.s8    q10, q4, q10                ; s = vp8_signed_char_clamp(ps2 + u)
    232     vqsub.s8    q13, q8, q12                ; s = vp8_signed_char_clamp(qs1 - u)
    233     vqadd.s8    q12, q5, q12                ; s = vp8_signed_char_clamp(ps1 + u)
    234     vqsub.s8    q15, q7, q14                ; s = vp8_signed_char_clamp(qs0 - u)
    235     vqadd.s8    q14, q6, q14                ; s = vp8_signed_char_clamp(ps0 + u)
    236     veor        q9, q11, q0                 ; *oq2 = s^0x80
    237     veor        q4, q10, q0                 ; *op2 = s^0x80
    238     veor        q8, q13, q0                 ; *oq1 = s^0x80
    239     veor        q5, q12, q0                 ; *op2 = s^0x80
    240     veor        q7, q15, q0                 ; *oq0 = s^0x80
    241     vld1.u8     {q3}, [sp]!
    242     veor        q6, q14, q0                 ; *op0 = s^0x80
    243     vld1.u8     {q10}, [sp]!
    244 
    245     ;transpose to 16x8 matrix
    246     vtrn.32     q3, q7
    247     vtrn.32     q4, q8
    248     vtrn.32     q5, q9
    249     vtrn.32     q6, q10
    250 
    251     vtrn.16     q3, q5
    252     vtrn.16     q4, q6
    253     vtrn.16     q7, q9
    254     vtrn.16     q8, q10
    255 
    256     vtrn.8      q3, q4
    257     vtrn.8      q5, q6
    258     vtrn.8      q7, q8
    259     vtrn.8      q9, q10
    260 
    261     ;store op2, op1, op0, oq0, oq1, oq2
    262     vst1.8      {d6}, [r0], r1
    263     vst1.8      {d7}, [r3], r1
    264     vst1.8      {d8}, [r0], r1
    265     vst1.8      {d9}, [r3], r1
    266     vst1.8      {d10}, [r0], r1
    267     vst1.8      {d11}, [r3], r1
    268     vst1.8      {d12}, [r0], r1
    269     vst1.8      {d13}, [r3], r1
    270     vst1.8      {d14}, [r0], r1
    271     vst1.8      {d15}, [r3], r1
    272     vst1.8      {d16}, [r0], r1
    273     vst1.8      {d17}, [r3], r1
    274     vst1.8      {d18}, [r0], r1
    275     vst1.8      {d19}, [r3], r1
    276     vst1.8      {d20}, [r0], r1
    277     vst1.8      {d21}, [r3], r1
    278 
    279     bx          lr
    280     ENDP        ; |vp8_mbloop_filter_vertical_edge_uv_neon|
    281 
    282 ;-----------------
    283     AREA    mbvloopfilteruv_dat, DATA, READWRITE            ;read/write by default
    284 ;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
    285 ;One word each is reserved. Label filter_coeff can be used to access the data.
    286 ;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
    287 _mbvlfuv_coeff_
    288     DCD     mbvlfuv_coeff
    289 mbvlfuv_coeff
    290     DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
    291     DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
    292     DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
    293     DCD     0x003f003f, 0x003f003f, 0x003f003f, 0x003f003f
    294     DCD     0x09090909, 0x09090909, 0x12121212, 0x12121212
    295     DCD     0x1b1b1b1b, 0x1b1b1b1b
    296 
    297     END
    298