Home | History | Annotate | Download | only in arm
      1 @/*****************************************************************************
      2 @*
      3 @* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
      4 @*
      5 @* Licensed under the Apache License, Version 2.0 (the "License");
      6 @* you may not use this file except in compliance with the License.
      7 @* You may obtain a copy of the License at:
      8 @*
      9 @* http://www.apache.org/licenses/LICENSE-2.0
     10 @*
     11 @* Unless required by applicable law or agreed to in writing, software
     12 @* distributed under the License is distributed on an "AS IS" BASIS,
     13 @* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 @* See the License for the specific language governing permissions and
     15 @* limitations under the License.
     16 @*
     17 @*****************************************************************************/
     18 @/**
     19 @*******************************************************************************
     20 @* ,:file
     21 @*  ihevc_sao_edge_offset_class1_chroma.s
     22 @*
     23 @* ,:brief
     24 @*  Contains function definitions for inter prediction  interpolation.
     25 @* Functions are coded using NEON  intrinsics and can be compiled using@ ARM
     26 @* RVCT
     27 @*
     28 @* ,:author
     29 @*  Parthiban V
     30 @*
     31 @* ,:par List of Functions:
     32 @*
     33 @*
     34 @* ,:remarks
     35 @*  None
     36 @*
     37 @*******************************************************************************
     38 @*/
     39 @void ihevc_sao_edge_offset_class1_chroma(UWORD8 *pu1_src,
     40 @                              WORD32 src_strd,
     41 @                              UWORD8 *pu1_src_left,
     42 @                              UWORD8 *pu1_src_top,
     43 @                              UWORD8 *pu1_src_top_left,
     44 @                              UWORD8 *pu1_src_top_right,
     45 @                              UWORD8 *pu1_src_bot_left,
     46 @                              UWORD8 *pu1_avail,
     47 @                              WORD8 *pi1_sao_offset_u,
     48 @                              WORD8 *pi1_sao_offset_v,
     49 @                              WORD32 wd,
     50 @                              WORD32 ht)
     51 @**************Variables Vs Registers*****************************************
     52 @r0 =>  *pu1_src
     53 @r1 =>  src_strd
     54 @r2 =>  *pu1_src_left
     55 @r3 =>  *pu1_src_top
     56 @r4 =>  *pu1_src_top_left
     57 @r5 =>  *pu1_avail
     58 @r6 =>  *pi1_sao_offset_u
     59 @r7 =>  *pi1_sao_offset_v
     60 @r8 =>  wd
     61 @r9 =>  ht
     62 
     63 .text
     64 .p2align 2
     65 
     66 .extern gi1_table_edge_idx
     67 .globl ihevc_sao_edge_offset_class1_chroma_a9q
     68 
     69 gi1_table_edge_idx_addr:
     70 .long gi1_table_edge_idx - ulbl1 - 8
     71 
     72 ihevc_sao_edge_offset_class1_chroma_a9q:
     73 
     74 
     75     STMFD       sp!, {r4-r12, r14}          @stack stores the values of the arguments
     76     LDR         r7,[sp,#60]                 @Loads wd
     77     LDR         r4,[sp,#40]                 @Loads pu1_src_top_left
     78     LDR         r5,[sp,#52]                 @Loads pu1_avail
     79     LDR         r6,[sp,#56]                 @Loads pi1_sao_offset_u
     80     LDR         r7,[sp,#60]                 @Loads pi1_sao_offset_v
     81     LDR         r8,[sp,#64]                 @Loads wd
     82     LDR         r9,[sp,#68]                 @Loads ht
     83 
     84     SUB         r10,r8,#2                   @wd - 2
     85     LDRH        r11,[r3,r10]                @pu1_src_top[wd - 2]
     86     STRH        r11,[r4]                    @*pu1_src_top_left = pu1_src_top[wd - 2]
     87     ADD         r11,r0,r10                  @pu1_src[row * src_strd + wd - 2]
     88     MOV         r12,r2                      @Move pu1_src_left pointer to r11
     89     MOV         r14,r9                      @Move ht to r14 for loop count
     90 SRC_LEFT_LOOP:
     91     LDRH        r10,[r11],r1                @Load pu1_src[row * src_strd + wd - 2]
     92     STRH        r10,[r12],#2                @pu1_src_left[row]
     93     SUBS        r14,#1                      @Decrement the loop count
     94     BNE         SRC_LEFT_LOOP               @If not equal to 0 jump to the src_left_loop
     95 
     96     SUB         r12,r9,#1                   @ht - 1
     97     MUL         r12,r12,r1                  @(ht - 1) * src_strd
     98     ADD         r12,r12,r0                  @pu1_src[(ht - 1) * src_strd]
     99 
    100     LDRB        r4,[r5,#2]                  @pu1_avail[2]
    101     CMP         r4,#0                       @0 == pu1_avail[2]
    102     ADDEQ       r0,r0,r1                    @pu1_src += src_strd
    103     SUBEQ       r9,r9,#1                    @ht--
    104 
    105     LDRB        r4,[r5,#3]                  @pu1_avail[3]
    106     CMP         r4,#0                       @0 == pu1_avail[3]
    107     SUBEQ       r9,r9,#1                    @ht--
    108 
    109     VMOV.I8     Q0,#2                       @const_2 = vdupq_n_s8(2)
    110     VMOV.I16    Q1,#0                       @const_min_clip = vdupq_n_s16(0)
    111     VMOV.I16    Q2,#255                     @const_max_clip = vdupq_n_u16((1 << bit_depth) - 1)
    112     LDR         r14, gi1_table_edge_idx_addr @table pointer
    113 ulbl1:
    114     add         r14,r14,pc
    115     VLD1.8      D6,[r14]                    @edge_idx_tbl = vld1_s8(gi1_table_edge_idx)
    116     VLD1.8      D7,[r6]                     @offset_tbl_u = vld1_s8(pi1_sao_offset_u)
    117     VLD1.8      D8,[r7]                     @offset_tbl_v = vld1_s8(pi1_sao_offset_v)
    118 
    119     CMP         r8,#16                      @Compare wd with 16
    120     BLT         WIDTH_RESIDUE               @If not jump to WIDTH_RESIDUE where loop is unrolled for 8 case
    121 
    122 WIDTH_LOOP_16:
    123     LDRB        r4,[r5,#2]                  @pu1_avail[2]
    124     CMP         r4,#0                       @0 == pu1_avail[2]
    125     SUBEQ       r11,r0,r1                   @pu1_src -= src_strd
    126     MOVNE       r11,r3                      @*pu1_src_top
    127 
    128     MOV         r10,r0                      @*pu1_src
    129 
    130     VLD1.8      D28,[r11]!                  @pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
    131     VLD1.8      D29,[r11]!                  @pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
    132     VLD1.8      D10,[r0]!                   @pu1_cur_row = vld1q_u8(pu1_src)
    133     VLD1.8      D11,[r0]!                   @pu1_cur_row = vld1q_u8(pu1_src)
    134 
    135     VLD1.8      D30,[r12]!                  @vld1q_u8(pu1_src[(ht - 1) * src_strd])
    136     VLD1.8      D31,[r12]!                  @vld1q_u8(pu1_src[(ht - 1) * src_strd])
    137     VCGT.U8     Q6,Q5,Q14                   @vcgtq_u8(pu1_cur_row, pu1_top_row)
    138 
    139     VST1.8      {Q15},[r3]!                 @vst1q_u8(pu1_src_top[col])
    140     VCLT.U8     Q7,Q5,Q14                   @vcltq_u8(pu1_cur_row, pu1_top_row)
    141 
    142     VSUB.U8     Q8,Q7,Q6                    @sign_up = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    143     MOV         r11,r9                      @move ht to r11 for loop count
    144 
    145 PU1_SRC_LOOP:
    146     ADD         r10,r10,r1                  @*pu1_src + src_strd
    147     VLD1.8      D18,[r10]!                  @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    148     VLD1.8      D19,[r10]                   @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    149     SUB         r10,#8
    150     ADD         r6,r10,r1                   @II Iteration *pu1_src + src_strd
    151 
    152     VCGT.U8     Q6,Q5,Q9                    @vcgtq_u8(pu1_cur_row, pu1_top_row)
    153     VLD1.8      D30,[r6]!                   @II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    154     VLD1.8      D31,[r6]                    @II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    155     SUB         r6,#8
    156 
    157     VCLT.U8     Q7,Q5,Q9                    @vcltq_u8(pu1_cur_row, pu1_top_row)
    158     SUB         r10,r10,r1
    159 
    160     VSUB.U8     Q10,Q7,Q6                   @sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    161     VMOVL.U8    Q13,D18                     @II pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    162 
    163     VADD.I8     Q6,Q0,Q8                    @edge_idx = vaddq_s8(const_2, sign_up)
    164     VMOVL.U8    Q14,D19                     @II pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
    165 
    166     VADD.I8     Q6,Q6,Q10                   @edge_idx = vaddq_s8(edge_idx, sign_down)
    167     VCGT.U8     Q11,Q9,Q15                  @II vcgtq_u8(pu1_cur_row, pu1_top_row)
    168 
    169     VNEG.S8     Q8,Q10                      @sign_up = vnegq_s8(sign_down)
    170     VTBL.8      D12,{D6},D12                @vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    171     VCLT.U8     Q12,Q9,Q15                  @II vcltq_u8(pu1_cur_row, pu1_top_row)
    172 
    173     VSUB.U8     Q14,Q12,Q11                 @II sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    174     VTBL.8      D13,{D6},D13                @vtbl1_s8(edge_idx_tbl, vget_high_s8(edge_idx))
    175     VADD.I8     Q11,Q0,Q8                   @II edge_idx = vaddq_s8(const_2, sign_up)
    176 
    177 
    178     VUZP.8      D12,D13
    179     VNEG.S8     Q8,Q14                      @II sign_up = vnegq_s8(sign_down)
    180     VTBL.8      D12,{D7},D12                @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    181     VADD.I8     Q11,Q11,Q14                 @II edge_idx = vaddq_s8(edge_idx, sign_down)
    182 
    183     VMOVL.U8    Q10,D10                     @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    184     VTBL.8      D13,{D8},D13
    185     VZIP.8      D12,D13
    186 
    187     VADDW.S8    Q10,Q10,D12                 @pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    188     VTBL.8      D22,{D6},D22                @II vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    189     VMAX.S16    Q10,Q10,Q1                  @pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    190 
    191     VMIN.U16    Q10,Q10,Q2                  @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    192     VTBL.8      D23,{D6},D23                @II vtbl1_s8(edge_idx_tbl, vget_high_s8(edge_idx))
    193     VUZP.8      D22,D23
    194 
    195     VMOVL.U8    Q14,D11                     @pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
    196     @VTBL.8     D13,D7,D13                  @offset = vtbl1_s8(offset_tbl, vget_high_s8(edge_idx))
    197     VMOV        Q5,Q15                      @II pu1_cur_row = pu1_next_row
    198 
    199     VADDW.S8    Q14,Q14,D13                 @pi2_tmp_cur_row.val[1] = vaddw_s8(pi2_tmp_cur_row.val[1], offset)
    200     VTBL.8      D24,{D7},D22                @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    201     VMAX.S16    Q14,Q14,Q1                  @pi2_tmp_cur_row.val[1] = vmaxq_s16(pi2_tmp_cur_row.val[1], const_min_clip)
    202 
    203     VTBL.8      D25,{D8},D23
    204     VZIP.8      D24,D25
    205     @VTBL.8     D24,D7,D22                  @II offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    206     VMIN.U16    Q14,Q14,Q2                  @pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[1]), const_max_clip))
    207     @VTBL.8     D25,D7,D23                  @II offset = vtbl1_s8(offset_tbl, vget_high_s8(edge_idx))
    208 
    209     VMOVN.I16   D20,Q10                     @vmovn_s16(pi2_tmp_cur_row.val[0])
    210     VADDW.S8    Q13,Q13,D24                 @II pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    211 
    212     VMOVN.I16   D21,Q14                     @vmovn_s16(pi2_tmp_cur_row.val[1])
    213 
    214     VMOVL.U8    Q14,D19                     @II pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
    215     VADDW.S8    Q14,Q14,D25                 @II pi2_tmp_cur_row.val[1] = vaddw_s8(pi2_tmp_cur_row.val[1], offset)
    216 
    217 
    218     VMAX.S16    Q13,Q13,Q1                  @II pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    219     VMIN.U16    Q13,Q13,Q2                  @II pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    220 
    221     VMAX.S16    Q14,Q14,Q1                  @II pi2_tmp_cur_row.val[1] = vmaxq_s16(pi2_tmp_cur_row.val[1], const_min_clip)
    222     VMIN.U16    Q14,Q14,Q2                  @II pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[1]), const_max_clip))
    223     VST1.8      {Q10},[r10],r1              @vst1q_u8(pu1_src_cpy, pu1_cur_row)
    224 
    225     VMOVN.I16   D30,Q13                     @II vmovn_s16(pi2_tmp_cur_row.val[0])
    226     SUBS        r11,r11,#2                  @II Decrement the ht loop count by 1
    227     VMOVN.I16   D31,Q14                     @II vmovn_s16(pi2_tmp_cur_row.val[1])
    228 
    229     VST1.8      {Q15},[r10],r1              @II vst1q_u8(pu1_src_cpy, pu1_cur_row)
    230 
    231     BEQ         PU1_SRC_LOOP_END            @if 0 == pu1_avail[3] || 0 == pu1_avail[2] ht = ht--
    232     CMP         r11,#1                      @checking any residue remains
    233     BGT         PU1_SRC_LOOP                @If not equal jump to PU1_SRC_LOOP
    234 
    235     ADD         r10,r10,r1                  @*pu1_src + src_strd
    236     VLD1.8      D18,[r10]!                  @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    237     VLD1.8      D19,[r10]                   @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    238     SUB         r10,#8
    239     VCGT.U8     Q6,Q5,Q9                    @vcgtq_u8(pu1_cur_row, pu1_top_row)
    240     VCLT.U8     Q7,Q5,Q9                    @vcltq_u8(pu1_cur_row, pu1_top_row)
    241     VSUB.U8     Q10,Q7,Q6                   @sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    242     SUB         r10,r10,r1
    243 
    244     VADD.I8     Q11,Q0,Q8                   @edge_idx = vaddq_s8(const_2, sign_up)
    245     VADD.I8     Q11,Q11,Q10                 @edge_idx = vaddq_s8(edge_idx, sign_down)
    246     VTBL.8      D22,{D6},D22                @vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    247     VTBL.8      D23,{D6},D23                @vtbl1_s8(edge_idx_tbl, vget_high_s8(edge_idx))
    248 
    249     VUZP.8      D22,D23
    250     VTBL.8      D24,{D7},D22
    251     VTBL.8      D25,{D8},D23
    252     VZIP.8      D24,D25
    253 
    254     @VTBL.8     D24,D7,D22                  @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    255     VMOVL.U8    Q13,D10                     @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    256     VADDW.S8    Q13,Q13,D24                 @pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    257     VMAX.S16    Q13,Q13,Q1                  @pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    258     VMIN.U16    Q13,Q13,Q2                  @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    259 
    260     @VTBL.8     D25,D7,D23                  @offset = vtbl1_s8(offset_tbl, vget_high_s8(edge_idx))
    261     VMOVL.U8    Q14,D11                     @pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
    262     VADDW.S8    Q14,Q14,D25                 @pi2_tmp_cur_row.val[1] = vaddw_s8(pi2_tmp_cur_row.val[1], offset)
    263     VMAX.S16    Q14,Q14,Q1                  @pi2_tmp_cur_row.val[1] = vmaxq_s16(pi2_tmp_cur_row.val[1], const_min_clip)
    264     VMIN.U16    Q14,Q14,Q2                  @pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[1]), const_max_clip))
    265 
    266     VMOVN.I16   D30,Q13                     @vmovn_s16(pi2_tmp_cur_row.val[0])
    267     VMOVN.I16   D31,Q14                     @vmovn_s16(pi2_tmp_cur_row.val[1])
    268 
    269     VST1.8      {Q15},[r10],r1              @vst1q_u8(pu1_src_cpy, pu1_cur_row)
    270 
    271 PU1_SRC_LOOP_END:
    272     VMOV        Q5,Q9                       @pu1_cur_row = pu1_next_row
    273     SUBS        r8,r8,#16                   @Decrement the wd loop count by 16
    274     CMP         r8,#8                       @Check whether residue remains
    275     BEQ         WIDTH_RESIDUE               @If residue remains jump to residue loop
    276     BGT         WIDTH_LOOP_16               @If not equal jump to width_loop
    277     BLT         END_LOOPS                   @Jump to end function
    278 
    279 
    280 WIDTH_RESIDUE:
    281     LDRB        r4,[r5,#2]                  @pu1_avail[2]
    282     CMP         r4,#0                       @0 == pu1_avail[2]
    283     SUBEQ       r11,r0,r1                   @pu1_src -= src_strd
    284     MOVNE       r11,r3                      @*pu1_src_top
    285     MOV         r10,r0
    286 
    287     VLD1.8      D28,[r11]!                  @pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
    288     VLD1.8      D29,[r11]!                  @pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
    289     VLD1.8      D10,[r0]!                   @pu1_cur_row = vld1q_u8(pu1_src)
    290     VLD1.8      D11,[r0]!                   @pu1_cur_row = vld1q_u8(pu1_src)
    291 
    292     VLD1.8      D30,[r12]                   @vld1_u8(pu1_src[(ht - 1) * src_strd])
    293     VST1.8      {D30},[r3]                  @vst1_u8(pu1_src_top[col])
    294 
    295     VCGT.U8     Q6,Q5,Q14                   @vcgtq_u8(pu1_cur_row, pu1_top_row)
    296     VCLT.U8     Q7,Q5,Q14                   @vcltq_u8(pu1_cur_row, pu1_top_row)
    297     VSUB.U8     Q8,Q7,Q6                    @sign_up = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    298     MOV         r11,r9                      @move ht to r11 for loop count
    299 
    300 PU1_SRC_LOOP_RESIDUE:
    301     ADD         r10,r10,r1                  @*pu1_src + src_strd
    302     VLD1.8      D18,[r10]!                  @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    303     VLD1.8      D19,[r10]                   @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    304     SUB         r10,#8
    305     ADD         r6,r10,r1                   @II Iteration *pu1_src + src_strd
    306 
    307     VCGT.U8     Q6,Q5,Q9                    @vcgtq_u8(pu1_cur_row, pu1_next_row)
    308     VLD1.8      D30,[r6]!                   @II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    309     VLD1.8      D31,[r6]                    @II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    310     SUB         r6,#8
    311 
    312     VCLT.U8     Q7,Q5,Q9                    @vcltq_u8(pu1_cur_row, pu1_next_row)
    313     SUB         r10,r10,r1
    314 
    315     VSUB.U8     Q10,Q7,Q6                   @sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    316     VMOVL.U8    Q13,D18                     @II pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    317 
    318     VADD.I8     Q6,Q0,Q8                    @edge_idx = vaddq_s8(const_2, sign_up)
    319     VCGT.U8     Q11,Q9,Q15                  @II vcgtq_u8(pu1_cur_row, pu1_next_row)
    320 
    321     VADD.I8     Q6,Q6,Q10                   @edge_idx = vaddq_s8(edge_idx, sign_down)
    322     VCLT.U8     Q12,Q9,Q15                  @II vcltq_u8(pu1_cur_row, pu1_next_row)
    323 
    324     VNEG.S8     Q8,Q10                      @sign_up = vnegq_s8(sign_down)
    325     VTBL.8      D12,{D6},D12                @vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    326     VSUB.U8     Q10,Q12,Q11                 @II sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    327 
    328     VUZP.8      D12,D13
    329 
    330     VADD.I8     Q11,Q0,Q8                   @II edge_idx = vaddq_s8(const_2, sign_up)
    331     VTBL.8      D12,{D7},D12
    332     VNEG.S8     Q8,Q10                      @II sign_up = vnegq_s8(sign_down)
    333 
    334     VTBL.8      D13,{D8},D13
    335     VZIP.8      D12,D13
    336 
    337     @VTBL.8     D12,D7,D12                  @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    338 
    339     VADD.I8     Q11,Q11,Q10                 @II edge_idx = vaddq_s8(edge_idx, sign_down)
    340     VMOVL.U8    Q10,D10                     @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    341 
    342     VADDW.S8    Q10,Q10,D12                 @pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    343     VTBL.8      D22,{D6},D22                @II vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    344     VMAX.S16    Q10,Q10,Q1                  @pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    345 
    346     VUZP.8      D22,D23
    347 
    348     VMIN.U16    Q10,Q10,Q2                  @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    349     VTBL.8      D24,{D7},D22
    350     VMOVN.I16   D20,Q10                     @vmovn_s16(pi2_tmp_cur_row.val[0])
    351 
    352     VTBL.8      D25,{D8},D23
    353     VZIP.8      D24,D25
    354     @VTBL.8     D24,D7,D22                  @II offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    355 
    356     VADDW.S8    Q13,Q13,D24                 @II pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    357     VMAX.S16    Q13,Q13,Q1                  @II pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    358     VMIN.U16    Q13,Q13,Q2                  @II pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    359 
    360     VMOV        Q5,Q15                      @II pu1_cur_row = pu1_next_row
    361     VST1.8      {D20},[r10],r1              @vst1q_u8(pu1_src_cpy, pu1_cur_row)
    362     VMOVN.I16   D30,Q13                     @II vmovn_s16(pi2_tmp_cur_row.val[0])
    363 
    364     SUBS        r11,r11,#2                  @Decrement the ht loop count by 1
    365     VST1.8      {D30},[r10],r1              @II vst1q_u8(pu1_src_cpy, pu1_cur_row)
    366 
    367     BEQ         END_LOOPS
    368     CMP         r11,#1
    369     BGT         PU1_SRC_LOOP_RESIDUE        @If not equal jump to PU1_SRC_LOOP
    370 
    371 
    372     ADD         r10,r10,r1                  @*pu1_src + src_strd
    373     VLD1.8      D18,[r10]!                  @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    374     VLD1.8      D19,[r10]                   @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    375     SUB         r10,#8
    376     VCGT.U8     Q6,Q5,Q9                    @vcgtq_u8(pu1_cur_row, pu1_next_row)
    377     VCGT.U8     Q7,Q9,Q5                    @vcltq_u8(pu1_cur_row, pu1_next_row)
    378     VSUB.U8     Q10,Q7,Q6                   @sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    379     SUB         r10,r10,r1
    380 
    381     VADD.I8     Q11,Q0,Q8                   @edge_idx = vaddq_s8(const_2, sign_up)
    382     VADD.I8     Q11,Q11,Q10                 @edge_idx = vaddq_s8(edge_idx, sign_down)
    383     VTBL.8      D22,{D6},D22                @vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    384 
    385     VUZP.8      D22,D23
    386     VTBL.8      D24,{D7},D22
    387     VTBL.8      D25,{D8},D23
    388     VZIP.8      D24,D25
    389 
    390     @VTBL.8     D24,D7,D22                  @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    391     VMOVL.U8    Q13,D10                     @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    392     VADDW.S8    Q13,Q13,D24                 @pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    393     VMAX.S16    Q13,Q13,Q1                  @pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    394     VMIN.U16    Q13,Q13,Q2                  @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    395 
    396     VMOVN.I16   D30,Q13                     @vmovn_s16(pi2_tmp_cur_row.val[0])
    397 
    398     VST1.8      {D30},[r10],r1              @vst1q_u8(pu1_src_cpy, pu1_cur_row)
    399 
    400 END_LOOPS:
    401     LDMFD       sp!,{r4-r12,r15}            @Reload the registers from SP
    402 
    403 
    404 
    405 
    406 
    407 
    408