Home | History | Annotate | Download | only in arm64
      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 //x0 =>    *pu1_src
     53 //x1 =>    src_strd
     54 //x2 =>    *pu1_src_left
     55 //x3 =>    *pu1_src_top
     56 //x4    =>    *pu1_src_top_left
     57 //x5    =>    *pu1_avail
     58 //x6    =>    *pi1_sao_offset_u
     59 //x7    =>    *pi1_sao_offset_v
     60 //x8    =>    wd
     61 //x9 =>    ht
     62 
     63 .text
     64 .p2align 2
     65 .include "ihevc_neon_macros.s"
     66 
     67 .globl gi1_table_edge_idx
     68 .globl ihevc_sao_edge_offset_class1_chroma_av8
     69 
     70 ihevc_sao_edge_offset_class1_chroma_av8:
     71 
     72 
     73     ldr         x8,[sp,#0]
     74     ldr         x9,[sp,#8]
     75     ldr         w10,[sp,#16]
     76     ldr         w11,[sp,#24]
     77 
     78 
     79 
     80     // STMFD sp!, {x4-x12, x14}            //stack stores the values of the arguments
     81     stp         x19, x20,[sp,#-16]!
     82     stp         x21, x22,[sp,#-16]!
     83     stp         x23, x24,[sp,#-16]!
     84     stp         x25, x26,[sp,#-16]!
     85 
     86     mov         x15,x4 // *pu1_src_top_left 40
     87     mov         x16,x5 // *pu1_src_top_right 44
     88     mov         x17,x6 // *pu1_src_bot_left 48
     89     mov         x21,x7 // *pu1_avail 52
     90     mov         x22,x8 // *pi1_sao_offset_u 56
     91     mov         x23,x9 // *pi1_sao_offset_v 60
     92     mov         x24,x10 // wd 64
     93     mov         x25,x11 // ht 68
     94 
     95     mov         x4,x15
     96     mov         x5,x21
     97     mov         x6,x22
     98     mov         x7,x23
     99     mov         x8,x24
    100     mov         x9,x25
    101 
    102     SUB         x10,x8,#2                   //wd - 2
    103     LDRH        w11,[x3,x10]                //pu1_src_top[wd - 2]
    104     STRH        w11,[x4]                    //*pu1_src_top_left = pu1_src_top[wd - 2]
    105     ADD         x11,x0,x10                  //pu1_src[row * src_strd + wd - 2]
    106     MOV         x12,x2                      //Move pu1_src_left pointer to x11
    107     MOV         x14,x9                      //Move ht to x14 for loop count
    108 SRC_LEFT_LOOP:
    109     LDRH        w10,[x11]                   //Load pu1_src[row * src_strd + wd - 2]
    110     ADD         x11,x11,x1
    111     STRH        w10,[x12],#2                //pu1_src_left[row]
    112     SUBS        x14, x14,#1                 //Decrement the loop count
    113     BNE         SRC_LEFT_LOOP               //If not equal to 0 jump to the src_left_loop
    114 
    115     SUB         x12,x9,#1                   //ht - 1
    116     mul         x12, x12, x1                //(ht - 1) * src_strd
    117     ADD         x12,x12,x0                  //pu1_src[(ht - 1) * src_strd]
    118 
    119     LDRB        w4,[x5,#2]                  //pu1_avail[2]
    120     CMP         x4,#0                       //0 == pu1_avail[2]
    121     ADD         x20,x0,x1                   //pu1_src += src_strd
    122     csel        x0, x20, x0,EQ
    123     SUB         x20,x9,#1                   //ht--
    124     csel        x9, x20, x9,EQ
    125 
    126     LDRB        w4,[x5,#3]                  //pu1_avail[3]
    127     CMP         x4,#0                       //0 == pu1_avail[3]
    128     SUB         x20,x9,#1                   //ht--
    129     csel        x9, x20, x9,EQ
    130 
    131     movi        v0.16b, #2                  //const_2 = vdupq_n_s8(2)
    132     movi        v2.8h, #0                   //const_min_clip = vdupq_n_s16(0)
    133     movi        v4.8h, #255                 //const_max_clip = vdupq_n_u16((1 << bit_depth) - 1)
    134     ADRP        x14, :got:gi1_table_edge_idx //table pointer
    135     LDR         x14, [x14, #:got_lo12:gi1_table_edge_idx]
    136     LD1         {v6.8b},[x14]               //edge_idx_tbl = vld1_s8(gi1_table_edge_idx)
    137     LD1         {v7.8b},[x6]                //offset_tbl_u = vld1_s8(pi1_sao_offset_u)
    138     LD1         {v1.8b},[x7]                //offset_tbl_v = vld1_s8(pi1_sao_offset_v)
    139 
    140     CMP         x8,#16                      //Compare wd with 16
    141     BLT         WIDTH_RESIDUE               //If not jump to WIDTH_RESIDUE where loop is unrolled for 8 case
    142 
    143 WIDTH_LOOP_16:
    144     LDRB        w4,[x5,#2]                  //pu1_avail[2]
    145     CMP         x4,#0                       //0 == pu1_avail[2]
    146     SUB         x20,x0,x1                   //pu1_src -= src_strd
    147     csel        x11, x20, x11,EQ
    148     csel        x11, x3, x11,NE             //*pu1_src_top
    149 
    150     MOV         x10,x0                      //*pu1_src
    151 
    152     LD1         {v28.16b},[x11],#16         //pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
    153     //LD1 {v29.8b},[x11],#8                    //pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
    154     LD1         {v3.16b},[x0],#16           //pu1_cur_row = vld1q_u8(pu1_src)
    155     //LD1 {v11.8b},[x0],#8                    //pu1_cur_row = vld1q_u8(pu1_src)
    156 
    157     LD1         {v30.16b},[x12],#16         //vld1q_u8(pu1_src[(ht - 1) * src_strd])
    158     //LD1 {v31.8b},[x12],#8                    //vld1q_u8(pu1_src[(ht - 1) * src_strd])
    159     cmhi        v5.16b,  v3.16b ,  v28.16b  //vcgtq_u8(pu1_cur_row, pu1_top_row)
    160 
    161     ST1         { v30.16b},[x3],#16         //vst1q_u8(pu1_src_top[col])
    162     cmhi        v19.16b,  v28.16b ,  v3.16b //vcltq_u8(pu1_cur_row, pu1_top_row)
    163 
    164     SUB         v16.16b,  v19.16b ,  v5.16b //sign_up = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    165     MOV         x11,x9                      //move ht to x11 for loop count
    166 
    167 PU1_SRC_LOOP:
    168     ADD         x10,x10,x1                  //*pu1_src + src_strd
    169     LD1         {v18.16b},[x10]             //pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    170     //LD1 {v19.8b},[x10]                    //pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    171     //SUB x10, x10,#8
    172     ADD         x6,x10,x1                   //II Iteration *pu1_src + src_strd
    173 
    174     //mov   v19.d[0],v18.d[1]
    175     cmhi        v5.16b,  v3.16b ,  v18.16b  //vcgtq_u8(pu1_cur_row, pu1_top_row)
    176     LD1         {v30.16b},[x6]              //II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    177     //LD1 {v31.8b},[x6]                    //II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    178     //SUB x6, x6,#8
    179 
    180     cmhi        v19.16b,  v18.16b ,  v3.16b //vcltq_u8(pu1_cur_row, pu1_top_row)
    181     SUB         x10,x10,x1
    182 
    183     SUB         v20.16b,  v19.16b ,  v5.16b //sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    184     Uxtl        v26.8h, v18.8b              //II pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    185 
    186     ADD         v5.16b,  v0.16b ,  v16.16b  //edge_idx = vaddq_s8(const_2, sign_up)
    187     Uxtl2       v28.8h, v18.16b             //II pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
    188 
    189     ADD         v5.16b,  v5.16b ,  v20.16b  //edge_idx = vaddq_s8(edge_idx, sign_down)
    190     cmhi        v22.16b,  v18.16b ,  v30.16b //II vcgtq_u8(pu1_cur_row, pu1_top_row)
    191 
    192     mov         v16.d[1],v16.d[0]
    193     NEG         v16.16b, v20.16b            //sign_up = vnegq_s8(sign_down)
    194     TBL         v5.16b, {v6.16b},v5.16b     //vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    195     cmhi        v24.16b,  v30.16b ,  v18.16b //II vcltq_u8(pu1_cur_row, pu1_top_row)
    196 
    197     SUB         v28.16b,  v24.16b ,  v22.16b //II sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    198     //TBL v13.8b, {v6.16b},v13.8b                //vtbl1_s8(edge_idx_tbl, vget_high_s8(edge_idx))
    199     ADD         v22.16b,  v0.16b ,  v16.16b //II edge_idx = vaddq_s8(const_2, sign_up)
    200 
    201     mov         v17.d[0], v5.d[1]
    202     UZP1        v27.8b, v5.8b, v17.8b
    203     UZP2        v17.8b, v5.8b, v17.8b
    204     mov         v5.8b,v27.8b
    205     NEG         v16.16b, v28.16b            //II sign_up = vnegq_s8(sign_down)
    206     TBL         v5.8b, {v7.16b},v5.8b       //offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    207     ADD         v22.16b,  v22.16b ,  v28.16b //II edge_idx = vaddq_s8(edge_idx, sign_down)
    208 
    209     Uxtl        v20.8h, v3.8b               //pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    210     TBL         v17.8b, {v1.16b},v17.8b
    211     ZIP1        v27.8b, v5.8b, v17.8b
    212     ZIP2        v17.8b, v5.8b, v17.8b
    213     mov         v5.8b,v27.8b
    214 
    215     SADDW       v20.8h,  v20.8h ,  v5.8b    //pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    216     TBL         v22.16b, {v6.16b},v22.16b   //II vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    217     SMAX        v20.8h,  v20.8h ,  v2.8h    //pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    218 
    219     UMIN        v20.8h,  v20.8h ,  v4.8h    //pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    220     //TBL v23.8b, {v6.16b},v23.8b                //II vtbl1_s8(edge_idx_tbl, vget_high_s8(edge_idx))
    221 
    222     mov         v23.d[0], v22.d[1]
    223     UZP1        v27.8b, v22.8b, v23.8b
    224     UZP2        v23.8b, v22.8b, v23.8b
    225     mov         v22.8b,v27.8b
    226 
    227     Uxtl2       v28.8h, v3.16b              //pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
    228     //VTBL.8        D13,D7,D13                    @offset = vtbl1_s8(offset_tbl, vget_high_s8(edge_idx))
    229     mov         v3.16b, v30.16b             //II pu1_cur_row = pu1_next_row
    230 
    231     SADDW       v28.8h,  v28.8h ,  v17.8b   //pi2_tmp_cur_row.val[1] = vaddw_s8(pi2_tmp_cur_row.val[1], offset)
    232     TBL         v24.8b, {v7.16b},v22.8b     //offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    233     SMAX        v28.8h,  v28.8h ,  v2.8h    //pi2_tmp_cur_row.val[1] = vmaxq_s16(pi2_tmp_cur_row.val[1], const_min_clip)
    234 
    235     TBL         v25.8b, {v1.16b},v23.8b
    236     ZIP1        v27.8b, v24.8b, v25.8b
    237     ZIP2        v25.8b, v24.8b, v25.8b
    238     mov         v24.8b,v27.8b
    239     //VTBL.8        D24,D7,D22                    @II offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    240     UMIN        v28.8h,  v28.8h ,  v4.8h    //pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[1]), const_max_clip))
    241     //VTBL.8        D25,D7,D23                    @II offset = vtbl1_s8(offset_tbl, vget_high_s8(edge_idx))
    242 
    243     xtn         v20.8b,  v20.8h             //vmovn_s16(pi2_tmp_cur_row.val[0])
    244     SADDW       v26.8h,  v26.8h ,  v24.8b   //II pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    245 
    246     xtn2        v20.16b,  v28.8h            //vmovn_s16(pi2_tmp_cur_row.val[1])
    247 
    248     Uxtl2       v28.8h, v18.16b             //II pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
    249     SADDW       v28.8h,  v28.8h ,  v25.8b   //II pi2_tmp_cur_row.val[1] = vaddw_s8(pi2_tmp_cur_row.val[1], offset)
    250 
    251 
    252     SMAX        v26.8h,  v26.8h ,  v2.8h    //II pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    253     UMIN        v26.8h,  v26.8h ,  v4.8h    //II pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    254 
    255     SMAX        v28.8h,  v28.8h ,  v2.8h    //II pi2_tmp_cur_row.val[1] = vmaxq_s16(pi2_tmp_cur_row.val[1], const_min_clip)
    256     UMIN        v28.8h,  v28.8h ,  v4.8h    //II pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[1]), const_max_clip))
    257     ST1         { v20.16b},[x10],x1         //vst1q_u8(pu1_src_cpy, pu1_cur_row)
    258 
    259     xtn         v30.8b,  v26.8h             //II vmovn_s16(pi2_tmp_cur_row.val[0])
    260     SUBS        x11,x11,#2                  //II Decrement the ht loop count by 1
    261     xtn2        v30.16b,  v28.8h            //II vmovn_s16(pi2_tmp_cur_row.val[1])
    262 
    263     ST1         { v30.16b},[x10],x1         //II vst1q_u8(pu1_src_cpy, pu1_cur_row)
    264 
    265     BEQ         PU1_SRC_LOOP_END            //if 0 == pu1_avail[3] || 0 == pu1_avail[2] ht = ht--
    266     CMP         x11,#1                      //checking any residue remains
    267     BGT         PU1_SRC_LOOP                //If not equal jump to PU1_SRC_LOOP
    268 
    269     ADD         x10,x10,x1                  //*pu1_src + src_strd
    270     LD1         {v18.16b},[x10]             //pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    271     //LD1 {v19.8b},[x10]                    //pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    272     //SUB x10, x10,#8
    273     cmhi        v5.16b,  v3.16b ,  v18.16b  //vcgtq_u8(pu1_cur_row, pu1_top_row)
    274     cmhi        v19.16b,  v18.16b ,  v3.16b //vcltq_u8(pu1_cur_row, pu1_top_row)
    275     SUB         v20.16b,  v19.16b ,  v5.16b //sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    276     SUB         x10,x10,x1
    277 
    278     ADD         v22.16b,  v0.16b ,  v16.16b //edge_idx = vaddq_s8(const_2, sign_up)
    279     ADD         v22.16b,  v22.16b ,  v20.16b //edge_idx = vaddq_s8(edge_idx, sign_down)
    280     TBL         v22.16b, {v6.16b},v22.16b   //vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    281     //TBL v23.8b, {v6.16b},v23.8b                //vtbl1_s8(edge_idx_tbl, vget_high_s8(edge_idx))
    282 
    283     mov         v23.d[0],v22.d[1]
    284     UZP1        v27.8b, v22.8b, v23.8b
    285     UZP2        v23.8b, v22.8b, v23.8b
    286     mov         v22.8b,v27.8b
    287     TBL         v24.8b, {v7.16b},v22.8b
    288     TBL         v25.8b, {v1.16b},v23.8b
    289     ZIP1        v27.8b, v24.8b, v25.8b
    290     ZIP2        v25.8b, v24.8b, v25.8b
    291     mov         v24.8b,v27.8b
    292 
    293     //VTBL.8        D24,D7,D22                    @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    294     Uxtl        v26.8h, v3.8b               //pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    295     SADDW       v26.8h,  v26.8h ,  v24.8b   //pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    296     SMAX        v26.8h,  v26.8h ,  v2.8h    //pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    297     UMIN        v26.8h,  v26.8h ,  v4.8h    //pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    298 
    299     //VTBL.8        D25,D7,D23                    @offset = vtbl1_s8(offset_tbl, vget_high_s8(edge_idx))
    300     Uxtl2       v28.8h, v3.16b              //pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
    301     SADDW       v28.8h,  v28.8h ,  v25.8b   //pi2_tmp_cur_row.val[1] = vaddw_s8(pi2_tmp_cur_row.val[1], offset)
    302     SMAX        v28.8h,  v28.8h ,  v2.8h    //pi2_tmp_cur_row.val[1] = vmaxq_s16(pi2_tmp_cur_row.val[1], const_min_clip)
    303     UMIN        v28.8h,  v28.8h ,  v4.8h    //pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[1]), const_max_clip))
    304 
    305     xtn         v30.8b,  v26.8h             //vmovn_s16(pi2_tmp_cur_row.val[0])
    306     xtn2        v30.16b,  v28.8h            //vmovn_s16(pi2_tmp_cur_row.val[1])
    307 
    308     ST1         { v30.16b},[x10],x1         //vst1q_u8(pu1_src_cpy, pu1_cur_row)
    309 
    310 PU1_SRC_LOOP_END:
    311     mov         v3.16b, v18.16b             //pu1_cur_row = pu1_next_row
    312     SUBS        x8,x8,#16                   //Decrement the wd loop count by 16
    313     CMP         x8,#8                       //Check whether residue remains
    314     BEQ         WIDTH_RESIDUE               //If residue remains jump to residue loop
    315     BGT         WIDTH_LOOP_16               //If not equal jump to width_loop
    316     BLT         END_LOOPS                   //Jump to end function
    317 
    318 
    319 WIDTH_RESIDUE:
    320     LDRB        w4,[x5,#2]                  //pu1_avail[2]
    321     CMP         x4,#0                       //0 == pu1_avail[2]
    322     SUB         x20,x0,x1                   //pu1_src -= src_strd
    323     csel        x11, x20, x11,EQ
    324     csel        x11, x3, x11,NE             //*pu1_src_top
    325     MOV         x10,x0
    326 
    327     LD1         {v28.16b},[x11]             //pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
    328     //LD1 {v29.8b},[x11],#8                    //pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
    329     LD1         {v3.16b},[x0]               //pu1_cur_row = vld1q_u8(pu1_src)
    330     //LD1 {v11.8b},[x0],#8                    //pu1_cur_row = vld1q_u8(pu1_src)
    331 
    332     LD1         {v30.8b},[x12]              //vld1_u8(pu1_src[(ht - 1) * src_strd])
    333     ST1         {v30.8b},[x3]               //vst1_u8(pu1_src_top[col])
    334 
    335     cmhi        v5.16b,  v3.16b ,  v28.16b  //vcgtq_u8(pu1_cur_row, pu1_top_row)
    336     cmhi        v19.16b,  v28.16b ,  v3.16b //vcltq_u8(pu1_cur_row, pu1_top_row)
    337     SUB         v16.16b,  v19.16b ,  v5.16b //sign_up = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    338     MOV         x11,x9                      //move ht to x11 for loop count
    339 
    340 PU1_SRC_LOOP_RESIDUE:
    341     ADD         x10,x10,x1                  //*pu1_src + src_strd
    342     LD1         {v18.16b},[x10]             //pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    343     //LD1 {v19.8b},[x10]                    //pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    344     //SUB x10, x10,#8
    345     ADD         x6,x10,x1                   //II Iteration *pu1_src + src_strd
    346 
    347     cmhi        v5.16b,  v3.16b ,  v18.16b  //vcgtq_u8(pu1_cur_row, pu1_next_row)
    348     LD1         {v30.16b},[x6]              //II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    349     //LD1 {v31.8b},[x6]                    //II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    350     //SUB x6, x6,#8
    351 
    352     cmhi        v19.16b,  v18.16b ,  v3.16b //vcltq_u8(pu1_cur_row, pu1_next_row)
    353     SUB         x10,x10,x1
    354 
    355     SUB         v20.16b,  v19.16b ,  v5.16b //sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    356     Uxtl        v26.8h, v18.8b              //II pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    357 
    358     ADD         v5.16b,  v0.16b ,  v16.16b  //edge_idx = vaddq_s8(const_2, sign_up)
    359     cmhi        v22.16b,  v18.16b ,  v30.16b //II vcgtq_u8(pu1_cur_row, pu1_next_row)
    360 
    361     ADD         v5.16b,  v5.16b ,  v20.16b  //edge_idx = vaddq_s8(edge_idx, sign_down)
    362     cmhi        v24.16b,  v30.16b ,  v18.16b //II vcltq_u8(pu1_cur_row, pu1_next_row)
    363 
    364     NEG         v16.16b, v20.16b            //sign_up = vnegq_s8(sign_down)
    365     TBL         v5.8b, {v6.16b},v5.8b       //vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    366     SUB         v20.16b,  v24.16b ,  v22.16b //II sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    367 
    368     UZP1        v27.8b, v5.8b, v17.8b
    369     UZP2        v17.8b, v5.8b, v17.8b
    370     mov         v5.8b,v27.8b
    371 
    372     ADD         v22.16b,  v0.16b ,  v16.16b //II edge_idx = vaddq_s8(const_2, sign_up)
    373     TBL         v5.8b, {v7.16b},v5.8b
    374     NEG         v16.16b, v20.16b            //II sign_up = vnegq_s8(sign_down)
    375 
    376     TBL         v17.8b, {v1.16b},v17.8b
    377     ZIP1        v27.8b, v5.8b, v17.8b
    378     ZIP2        v17.8b, v5.8b, v17.8b
    379     mov         v5.8b,v27.8b
    380 
    381     //VTBL.8        D12,D7,D12                    @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    382 
    383     ADD         v22.16b,  v22.16b ,  v20.16b //II edge_idx = vaddq_s8(edge_idx, sign_down)
    384     Uxtl        v20.8h, v3.8b               //pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    385 
    386     SADDW       v20.8h,  v20.8h ,  v5.8b    //pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    387     TBL         v22.8b, {v6.16b},v22.8b     //II vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    388     SMAX        v20.8h,  v20.8h ,  v2.8h    //pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    389 
    390     UZP1        v27.8b, v22.8b, v23.8b
    391     UZP2        v23.8b, v22.8b, v23.8b
    392     mov         v22.8b,v27.8b
    393 
    394     UMIN        v20.8h,  v20.8h ,  v4.8h    //pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    395     TBL         v24.8b, {v7.16b},v22.8b
    396     xtn         v20.8b,  v20.8h             //vmovn_s16(pi2_tmp_cur_row.val[0])
    397 
    398     TBL         v25.8b, {v1.16b},v23.8b
    399     ZIP1        v27.8b, v24.8b, v25.8b
    400     ZIP2        v25.8b, v24.8b, v25.8b
    401     mov         v24.8b,v27.8b
    402     //VTBL.8        D24,D7,D22                    @II offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    403 
    404     SADDW       v26.8h,  v26.8h ,  v24.8b   //II pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    405     SMAX        v26.8h,  v26.8h ,  v2.8h    //II pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    406     UMIN        v26.8h,  v26.8h ,  v4.8h    //II pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    407 
    408     mov         v3.16b, v30.16b             //II pu1_cur_row = pu1_next_row
    409     ST1         {v20.8b},[x10],x1           //vst1q_u8(pu1_src_cpy, pu1_cur_row)
    410     xtn         v30.8b,  v26.8h             //II vmovn_s16(pi2_tmp_cur_row.val[0])
    411 
    412     SUBS        x11,x11,#2                  //Decrement the ht loop count by 1
    413     ST1         {v30.8b},[x10],x1           //II vst1q_u8(pu1_src_cpy, pu1_cur_row)
    414 
    415     BEQ         END_LOOPS
    416     CMP         x11,#1
    417     BGT         PU1_SRC_LOOP_RESIDUE        //If not equal jump to PU1_SRC_LOOP
    418 
    419 
    420     ADD         x10,x10,x1                  //*pu1_src + src_strd
    421     LD1         {v18.16b},[x10]             //pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    422     //LD1 {v19.8b},[x10]                    //pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
    423     //SUB x10, x10,#8
    424     cmhi        v5.16b,  v3.16b ,  v18.16b  //vcgtq_u8(pu1_cur_row, pu1_next_row)
    425     cmhi        v19.16b,  v18.16b ,  v3.16b //vcltq_u8(pu1_cur_row, pu1_next_row)
    426     SUB         v20.16b,  v19.16b ,  v5.16b //sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
    427     SUB         x10,x10,x1
    428 
    429     ADD         v22.16b,  v0.16b ,  v16.16b //edge_idx = vaddq_s8(const_2, sign_up)
    430     ADD         v22.16b,  v22.16b ,  v20.16b //edge_idx = vaddq_s8(edge_idx, sign_down)
    431     TBL         v22.8b, {v6.16b},v22.8b     //vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
    432 
    433     UZP1        v27.8b, v22.8b, v23.8b
    434     UZP2        v23.8b, v22.8b, v23.8b
    435     mov         v22.8b,v27.8b
    436 
    437     TBL         v24.8b, {v7.16b},v22.8b
    438     TBL         v25.8b, {v1.16b},v23.8b
    439     ZIP1        v27.8b, v24.8b, v25.8b
    440     ZIP2        v25.8b, v24.8b, v25.8b
    441     mov         v24.8b,v27.8b
    442 
    443     //VTBL.8        D24,D7,D22                    @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
    444     Uxtl        v26.8h, v3.8b               //pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
    445     SADDW       v26.8h,  v26.8h ,  v24.8b   //pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
    446     SMAX        v26.8h,  v26.8h ,  v2.8h    //pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
    447     UMIN        v26.8h,  v26.8h ,  v4.8h    //pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vminq_u16(vreinterpretq_u16_s16(pi2_tmp_cur_row.val[0]), const_max_clip))
    448 
    449     xtn         v30.8b,  v26.8h             //vmovn_s16(pi2_tmp_cur_row.val[0])
    450 
    451     ST1         {v30.8b},[x10],x1           //vst1q_u8(pu1_src_cpy, pu1_cur_row)
    452 
    453 END_LOOPS:
    454     // LDMFD sp!,{x4-x12,x15}             //Reload the registers from SP
    455     ldp         x25, x26,[sp],#16
    456     ldp         x23, x24,[sp],#16
    457     ldp         x21, x22,[sp],#16
    458     ldp         x19, x20,[sp],#16
    459 
    460 
    461     ret
    462 
    463 
    464 
    465 
    466 
    467 
    468