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