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_sub_pixel_variance16x16_neon|
     13     ARM
     14     REQUIRE8
     15     PRESERVE8
     16 
     17     AREA ||.text||, CODE, READONLY, ALIGN=2
     18 ; r0    unsigned char  *src_ptr,
     19 ; r1    int  src_pixels_per_line,
     20 ; r2    int  xoffset,
     21 ; r3    int  yoffset,
     22 ; stack(r4) unsigned char *dst_ptr,
     23 ; stack(r5) int dst_pixels_per_line,
     24 ; stack(r6) unsigned int *sse
     25 ;note: most of the code is copied from bilinear_predict16x16_neon and vp8_variance16x16_neon.
     26 
     27 |vp8_sub_pixel_variance16x16_neon| PROC
     28     push            {r4-r6, lr}
     29 
     30     ldr             r12, _BilinearTaps_coeff_
     31     ldr             r4, [sp, #16]           ;load *dst_ptr from stack
     32     ldr             r5, [sp, #20]           ;load dst_pixels_per_line from stack
     33     ldr             r6, [sp, #24]           ;load *sse from stack
     34 
     35     cmp             r2, #0                  ;skip first_pass filter if xoffset=0
     36     beq             secondpass_bfilter16x16_only
     37 
     38     add             r2, r12, r2, lsl #3     ;calculate filter location
     39 
     40     cmp             r3, #0                  ;skip second_pass filter if yoffset=0
     41 
     42     vld1.s32        {d31}, [r2]             ;load first_pass filter
     43 
     44     beq             firstpass_bfilter16x16_only
     45 
     46     sub             sp, sp, #272            ;reserve space on stack for temporary storage
     47     vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
     48     mov             lr, sp
     49     vld1.u8         {d5, d6, d7}, [r0], r1
     50 
     51     mov             r2, #3                  ;loop counter
     52     vld1.u8         {d8, d9, d10}, [r0], r1
     53 
     54     vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
     55     vld1.u8         {d11, d12, d13}, [r0], r1
     56 
     57     vdup.8          d1, d31[4]
     58 
     59 ;First Pass: output_height lines x output_width columns (17x16)
     60 vp8e_filt_blk2d_fp16x16_loop_neon
     61     pld             [r0]
     62     pld             [r0, r1]
     63     pld             [r0, r1, lsl #1]
     64 
     65     vmull.u8        q7, d2, d0              ;(src_ptr[0] * Filter[0])
     66     vmull.u8        q8, d3, d0
     67     vmull.u8        q9, d5, d0
     68     vmull.u8        q10, d6, d0
     69     vmull.u8        q11, d8, d0
     70     vmull.u8        q12, d9, d0
     71     vmull.u8        q13, d11, d0
     72     vmull.u8        q14, d12, d0
     73 
     74     vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
     75     vext.8          d5, d5, d6, #1
     76     vext.8          d8, d8, d9, #1
     77     vext.8          d11, d11, d12, #1
     78 
     79     vmlal.u8        q7, d2, d1              ;(src_ptr[0] * Filter[1])
     80     vmlal.u8        q9, d5, d1
     81     vmlal.u8        q11, d8, d1
     82     vmlal.u8        q13, d11, d1
     83 
     84     vext.8          d3, d3, d4, #1
     85     vext.8          d6, d6, d7, #1
     86     vext.8          d9, d9, d10, #1
     87     vext.8          d12, d12, d13, #1
     88 
     89     vmlal.u8        q8, d3, d1              ;(src_ptr[0] * Filter[1])
     90     vmlal.u8        q10, d6, d1
     91     vmlal.u8        q12, d9, d1
     92     vmlal.u8        q14, d12, d1
     93 
     94     subs            r2, r2, #1
     95 
     96     vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
     97     vqrshrn.u16    d15, q8, #7
     98     vqrshrn.u16    d16, q9, #7
     99     vqrshrn.u16    d17, q10, #7
    100     vqrshrn.u16    d18, q11, #7
    101     vqrshrn.u16    d19, q12, #7
    102     vqrshrn.u16    d20, q13, #7
    103 
    104     vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
    105     vqrshrn.u16    d21, q14, #7
    106     vld1.u8         {d5, d6, d7}, [r0], r1
    107 
    108     vst1.u8         {d14, d15, d16, d17}, [lr]!     ;store result
    109     vld1.u8         {d8, d9, d10}, [r0], r1
    110     vst1.u8         {d18, d19, d20, d21}, [lr]!
    111     vld1.u8         {d11, d12, d13}, [r0], r1
    112 
    113     bne             vp8e_filt_blk2d_fp16x16_loop_neon
    114 
    115 ;First-pass filtering for rest 5 lines
    116     vld1.u8         {d14, d15, d16}, [r0], r1
    117 
    118     vmull.u8        q9, d2, d0              ;(src_ptr[0] * Filter[0])
    119     vmull.u8        q10, d3, d0
    120     vmull.u8        q11, d5, d0
    121     vmull.u8        q12, d6, d0
    122     vmull.u8        q13, d8, d0
    123     vmull.u8        q14, d9, d0
    124 
    125     vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
    126     vext.8          d5, d5, d6, #1
    127     vext.8          d8, d8, d9, #1
    128 
    129     vmlal.u8        q9, d2, d1              ;(src_ptr[0] * Filter[1])
    130     vmlal.u8        q11, d5, d1
    131     vmlal.u8        q13, d8, d1
    132 
    133     vext.8          d3, d3, d4, #1
    134     vext.8          d6, d6, d7, #1
    135     vext.8          d9, d9, d10, #1
    136 
    137     vmlal.u8        q10, d3, d1             ;(src_ptr[0] * Filter[1])
    138     vmlal.u8        q12, d6, d1
    139     vmlal.u8        q14, d9, d1
    140 
    141     vmull.u8        q1, d11, d0
    142     vmull.u8        q2, d12, d0
    143     vmull.u8        q3, d14, d0
    144     vmull.u8        q4, d15, d0
    145 
    146     vext.8          d11, d11, d12, #1       ;construct src_ptr[1]
    147     vext.8          d14, d14, d15, #1
    148 
    149     vmlal.u8        q1, d11, d1             ;(src_ptr[0] * Filter[1])
    150     vmlal.u8        q3, d14, d1
    151 
    152     vext.8          d12, d12, d13, #1
    153     vext.8          d15, d15, d16, #1
    154 
    155     vmlal.u8        q2, d12, d1             ;(src_ptr[0] * Filter[1])
    156     vmlal.u8        q4, d15, d1
    157 
    158     vqrshrn.u16    d10, q9, #7              ;shift/round/saturate to u8
    159     vqrshrn.u16    d11, q10, #7
    160     vqrshrn.u16    d12, q11, #7
    161     vqrshrn.u16    d13, q12, #7
    162     vqrshrn.u16    d14, q13, #7
    163     vqrshrn.u16    d15, q14, #7
    164     vqrshrn.u16    d16, q1, #7
    165     vqrshrn.u16    d17, q2, #7
    166     vqrshrn.u16    d18, q3, #7
    167     vqrshrn.u16    d19, q4, #7
    168 
    169     vst1.u8         {d10, d11, d12, d13}, [lr]!         ;store result
    170     vst1.u8         {d14, d15, d16, d17}, [lr]!
    171     vst1.u8         {d18, d19}, [lr]!
    172 
    173 ;Second pass: 16x16
    174 ;secondpass_filter
    175     add             r3, r12, r3, lsl #3
    176     sub             lr, lr, #272
    177 
    178     vld1.u32        {d31}, [r3]             ;load second_pass filter
    179 
    180     sub             sp, sp, #256
    181     mov             r3, sp
    182 
    183     vld1.u8         {d22, d23}, [lr]!       ;load src data
    184 
    185     vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
    186     vdup.8          d1, d31[4]
    187     mov             r12, #4                 ;loop counter
    188 
    189 vp8e_filt_blk2d_sp16x16_loop_neon
    190     vld1.u8         {d24, d25}, [lr]!
    191     vmull.u8        q1, d22, d0             ;(src_ptr[0] * Filter[0])
    192     vld1.u8         {d26, d27}, [lr]!
    193     vmull.u8        q2, d23, d0
    194     vld1.u8         {d28, d29}, [lr]!
    195     vmull.u8        q3, d24, d0
    196     vld1.u8         {d30, d31}, [lr]!
    197 
    198     vmull.u8        q4, d25, d0
    199     vmull.u8        q5, d26, d0
    200     vmull.u8        q6, d27, d0
    201     vmull.u8        q7, d28, d0
    202     vmull.u8        q8, d29, d0
    203 
    204     vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * Filter[1])
    205     vmlal.u8        q2, d25, d1
    206     vmlal.u8        q3, d26, d1
    207     vmlal.u8        q4, d27, d1
    208     vmlal.u8        q5, d28, d1
    209     vmlal.u8        q6, d29, d1
    210     vmlal.u8        q7, d30, d1
    211     vmlal.u8        q8, d31, d1
    212 
    213     subs            r12, r12, #1
    214 
    215     vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
    216     vqrshrn.u16    d3, q2, #7
    217     vqrshrn.u16    d4, q3, #7
    218     vqrshrn.u16    d5, q4, #7
    219     vqrshrn.u16    d6, q5, #7
    220     vqrshrn.u16    d7, q6, #7
    221     vqrshrn.u16    d8, q7, #7
    222     vqrshrn.u16    d9, q8, #7
    223 
    224     vst1.u8         {d2, d3}, [r3]!         ;store result
    225     vst1.u8         {d4, d5}, [r3]!
    226     vst1.u8         {d6, d7}, [r3]!
    227     vmov            q11, q15
    228     vst1.u8         {d8, d9}, [r3]!
    229 
    230     bne             vp8e_filt_blk2d_sp16x16_loop_neon
    231 
    232     b               sub_pixel_variance16x16_neon
    233 
    234 ;--------------------
    235 firstpass_bfilter16x16_only
    236     mov             r2, #4                      ;loop counter
    237     sub             sp, sp, #528            ;reserve space on stack for temporary storage
    238     vdup.8          d0, d31[0]                  ;first_pass filter (d0 d1)
    239     vdup.8          d1, d31[4]
    240     mov             r3, sp
    241 
    242 ;First Pass: output_height lines x output_width columns (16x16)
    243 vp8e_filt_blk2d_fpo16x16_loop_neon
    244     vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
    245     vld1.u8         {d5, d6, d7}, [r0], r1
    246     vld1.u8         {d8, d9, d10}, [r0], r1
    247     vld1.u8         {d11, d12, d13}, [r0], r1
    248 
    249     pld             [r0]
    250     pld             [r0, r1]
    251     pld             [r0, r1, lsl #1]
    252 
    253     vmull.u8        q7, d2, d0              ;(src_ptr[0] * Filter[0])
    254     vmull.u8        q8, d3, d0
    255     vmull.u8        q9, d5, d0
    256     vmull.u8        q10, d6, d0
    257     vmull.u8        q11, d8, d0
    258     vmull.u8        q12, d9, d0
    259     vmull.u8        q13, d11, d0
    260     vmull.u8        q14, d12, d0
    261 
    262     vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
    263     vext.8          d5, d5, d6, #1
    264     vext.8          d8, d8, d9, #1
    265     vext.8          d11, d11, d12, #1
    266 
    267     vmlal.u8        q7, d2, d1              ;(src_ptr[0] * Filter[1])
    268     vmlal.u8        q9, d5, d1
    269     vmlal.u8        q11, d8, d1
    270     vmlal.u8        q13, d11, d1
    271 
    272     vext.8          d3, d3, d4, #1
    273     vext.8          d6, d6, d7, #1
    274     vext.8          d9, d9, d10, #1
    275     vext.8          d12, d12, d13, #1
    276 
    277     vmlal.u8        q8, d3, d1              ;(src_ptr[0] * Filter[1])
    278     vmlal.u8        q10, d6, d1
    279     vmlal.u8        q12, d9, d1
    280     vmlal.u8        q14, d12, d1
    281 
    282     subs            r2, r2, #1
    283 
    284     vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
    285     vqrshrn.u16    d15, q8, #7
    286     vqrshrn.u16    d16, q9, #7
    287     vqrshrn.u16    d17, q10, #7
    288     vqrshrn.u16    d18, q11, #7
    289     vqrshrn.u16    d19, q12, #7
    290     vqrshrn.u16    d20, q13, #7
    291     vst1.u8         {d14, d15}, [r3]!       ;store result
    292     vqrshrn.u16    d21, q14, #7
    293 
    294     vst1.u8         {d16, d17}, [r3]!
    295     vst1.u8         {d18, d19}, [r3]!
    296     vst1.u8         {d20, d21}, [r3]!
    297 
    298     bne             vp8e_filt_blk2d_fpo16x16_loop_neon
    299 
    300     b               sub_pixel_variance16x16_neon
    301 
    302 ;---------------------
    303 secondpass_bfilter16x16_only
    304 ;Second pass: 16x16
    305 ;secondpass_filter
    306     sub             sp, sp, #528            ;reserve space on stack for temporary storage
    307     add             r3, r12, r3, lsl #3
    308     mov             r12, #4                     ;loop counter
    309     vld1.u32        {d31}, [r3]                 ;load second_pass filter
    310     vld1.u8         {d22, d23}, [r0], r1        ;load src data
    311     mov             r3, sp
    312 
    313     vdup.8          d0, d31[0]                  ;second_pass filter parameters (d0 d1)
    314     vdup.8          d1, d31[4]
    315 
    316 vp8e_filt_blk2d_spo16x16_loop_neon
    317     vld1.u8         {d24, d25}, [r0], r1
    318     vmull.u8        q1, d22, d0             ;(src_ptr[0] * Filter[0])
    319     vld1.u8         {d26, d27}, [r0], r1
    320     vmull.u8        q2, d23, d0
    321     vld1.u8         {d28, d29}, [r0], r1
    322     vmull.u8        q3, d24, d0
    323     vld1.u8         {d30, d31}, [r0], r1
    324 
    325     vmull.u8        q4, d25, d0
    326     vmull.u8        q5, d26, d0
    327     vmull.u8        q6, d27, d0
    328     vmull.u8        q7, d28, d0
    329     vmull.u8        q8, d29, d0
    330 
    331     vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * Filter[1])
    332     vmlal.u8        q2, d25, d1
    333     vmlal.u8        q3, d26, d1
    334     vmlal.u8        q4, d27, d1
    335     vmlal.u8        q5, d28, d1
    336     vmlal.u8        q6, d29, d1
    337     vmlal.u8        q7, d30, d1
    338     vmlal.u8        q8, d31, d1
    339 
    340     vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
    341     vqrshrn.u16    d3, q2, #7
    342     vqrshrn.u16    d4, q3, #7
    343     vqrshrn.u16    d5, q4, #7
    344     vqrshrn.u16    d6, q5, #7
    345     vqrshrn.u16    d7, q6, #7
    346     vqrshrn.u16    d8, q7, #7
    347     vqrshrn.u16    d9, q8, #7
    348 
    349     vst1.u8         {d2, d3}, [r3]!         ;store result
    350     subs            r12, r12, #1
    351     vst1.u8         {d4, d5}, [r3]!
    352     vmov            q11, q15
    353     vst1.u8         {d6, d7}, [r3]!
    354     vst1.u8         {d8, d9}, [r3]!
    355 
    356     bne             vp8e_filt_blk2d_spo16x16_loop_neon
    357 
    358     b               sub_pixel_variance16x16_neon
    359 
    360 ;----------------------------
    361 ;variance16x16
    362 sub_pixel_variance16x16_neon
    363     vmov.i8         q8, #0                      ;q8 - sum
    364     vmov.i8         q9, #0                      ;q9, q10 - sse
    365     vmov.i8         q10, #0
    366 
    367     sub             r3, r3, #256
    368     mov             r12, #8
    369 
    370 sub_pixel_variance16x16_neon_loop
    371     vld1.8          {q0}, [r3]!                 ;Load up source and reference
    372     vld1.8          {q2}, [r4], r5
    373     vld1.8          {q1}, [r3]!
    374     vld1.8          {q3}, [r4], r5
    375 
    376     vsubl.u8        q11, d0, d4                 ;diff
    377     vsubl.u8        q12, d1, d5
    378     vsubl.u8        q13, d2, d6
    379     vsubl.u8        q14, d3, d7
    380 
    381     vpadal.s16      q8, q11                     ;sum
    382     vmlal.s16       q9, d22, d22                ;sse
    383     vmlal.s16       q10, d23, d23
    384 
    385     subs            r12, r12, #1
    386 
    387     vpadal.s16      q8, q12
    388     vmlal.s16       q9, d24, d24
    389     vmlal.s16       q10, d25, d25
    390     vpadal.s16      q8, q13
    391     vmlal.s16       q9, d26, d26
    392     vmlal.s16       q10, d27, d27
    393     vpadal.s16      q8, q14
    394     vmlal.s16       q9, d28, d28
    395     vmlal.s16       q10, d29, d29
    396 
    397     bne             sub_pixel_variance16x16_neon_loop
    398 
    399     vadd.u32        q10, q9, q10                ;accumulate sse
    400     vpaddl.s32      q0, q8                      ;accumulate sum
    401 
    402     vpaddl.u32      q1, q10
    403     vadd.s64        d0, d0, d1
    404     vadd.u64        d1, d2, d3
    405 
    406     vmull.s32       q5, d0, d0
    407     vst1.32         {d1[0]}, [r6]               ;store sse
    408     vshr.s32        d10, d10, #8
    409     vsub.s32        d0, d1, d10
    410 
    411     add             sp, sp, #528
    412     vmov.32         r0, d0[0]                   ;return
    413 
    414     pop             {r4-r6,pc}
    415 
    416     ENDP
    417 
    418 ;-----------------
    419     AREA    vp8e_bilinear_taps_dat, DATA, READWRITE          ;read/write by default
    420 ;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
    421 ;One word each is reserved. Label filter_coeff can be used to access the data.
    422 ;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
    423 _BilinearTaps_coeff_
    424     DCD     bilinear_taps_coeff
    425 bilinear_taps_coeff
    426     DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
    427 
    428     END
    429