• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.equ    pu1_src_top_left_offset,    104
64.equ    pu1_src_top_right_offset,   108
65.equ    pu1_src_bot_left_offset,    112
66.equ    pu1_avail_offset,           116
67.equ    pi1_sao_u_offset,           120
68.equ    pi1_sao_v_offset,           124
69.equ    wd_offset,                  128
70.equ    ht_offset,                  132
71
72.text
73.p2align 2
74
75.extern gi1_table_edge_idx
76.globl ihevc_sao_edge_offset_class1_chroma_a9q
77
78gi1_table_edge_idx_addr:
79.long gi1_table_edge_idx - ulbl1 - 8
80
81ihevc_sao_edge_offset_class1_chroma_a9q:
82
83
84    STMFD       sp!, {r4-r12, r14}          @stack stores the values of the arguments
85    vpush       {d8  -  d15}
86    LDR         r4,[sp,#pu1_src_top_left_offset]    @Loads pu1_src_top_left
87    LDR         r5,[sp,#pu1_avail_offset]   @Loads pu1_avail
88    LDR         r6,[sp,#pi1_sao_u_offset]   @Loads pi1_sao_offset_u
89    LDR         r7,[sp,#pi1_sao_v_offset]   @Loads pi1_sao_offset_v
90    LDR         r8,[sp,#wd_offset]          @Loads wd
91    LDR         r9,[sp,#ht_offset]          @Loads ht
92
93    SUB         r10,r8,#2                   @wd - 2
94    LDRH        r11,[r3,r10]                @pu1_src_top[wd - 2]
95    STRH        r11,[r4]                    @*pu1_src_top_left = pu1_src_top[wd - 2]
96    ADD         r11,r0,r10                  @pu1_src[row * src_strd + wd - 2]
97    MOV         r12,r2                      @Move pu1_src_left pointer to r11
98    MOV         r14,r9                      @Move ht to r14 for loop count
99SRC_LEFT_LOOP:
100    LDRH        r10,[r11],r1                @Load pu1_src[row * src_strd + wd - 2]
101    STRH        r10,[r12],#2                @pu1_src_left[row]
102    SUBS        r14,#1                      @Decrement the loop count
103    BNE         SRC_LEFT_LOOP               @If not equal to 0 jump to the src_left_loop
104
105    SUB         r12,r9,#1                   @ht - 1
106    MUL         r12,r12,r1                  @(ht - 1) * src_strd
107    ADD         r12,r12,r0                  @pu1_src[(ht - 1) * src_strd]
108
109    LDRB        r4,[r5,#2]                  @pu1_avail[2]
110    CMP         r4,#0                       @0 == pu1_avail[2]
111    ADDEQ       r0,r0,r1                    @pu1_src += src_strd
112    SUBEQ       r9,r9,#1                    @ht--
113
114    LDRB        r4,[r5,#3]                  @pu1_avail[3]
115    CMP         r4,#0                       @0 == pu1_avail[3]
116    SUBEQ       r9,r9,#1                    @ht--
117
118    VMOV.I8     Q0,#2                       @const_2 = vdupq_n_s8(2)
119    VMOV.I16    Q1,#0                       @const_min_clip = vdupq_n_s16(0)
120    VMOV.I16    Q2,#255                     @const_max_clip = vdupq_n_u16((1 << bit_depth) - 1)
121    LDR         r14, gi1_table_edge_idx_addr @table pointer
122ulbl1:
123    add         r14,r14,pc
124    VLD1.8      D6,[r14]                    @edge_idx_tbl = vld1_s8(gi1_table_edge_idx)
125    VLD1.8      D7,[r6]                     @offset_tbl_u = vld1_s8(pi1_sao_offset_u)
126    VLD1.8      D8,[r7]                     @offset_tbl_v = vld1_s8(pi1_sao_offset_v)
127
128    CMP         r8,#16                      @Compare wd with 16
129    BLT         WIDTH_RESIDUE               @If not jump to WIDTH_RESIDUE where loop is unrolled for 8 case
130
131WIDTH_LOOP_16:
132    LDRB        r4,[r5,#2]                  @pu1_avail[2]
133    CMP         r4,#0                       @0 == pu1_avail[2]
134    SUBEQ       r11,r0,r1                   @pu1_src -= src_strd
135    MOVNE       r11,r3                      @*pu1_src_top
136
137    MOV         r10,r0                      @*pu1_src
138
139    VLD1.8      D28,[r11]!                  @pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
140    VLD1.8      D29,[r11]!                  @pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
141    VLD1.8      D10,[r0]!                   @pu1_cur_row = vld1q_u8(pu1_src)
142    VLD1.8      D11,[r0]!                   @pu1_cur_row = vld1q_u8(pu1_src)
143
144    VLD1.8      D30,[r12]!                  @vld1q_u8(pu1_src[(ht - 1) * src_strd])
145    VLD1.8      D31,[r12]!                  @vld1q_u8(pu1_src[(ht - 1) * src_strd])
146    VCGT.U8     Q6,Q5,Q14                   @vcgtq_u8(pu1_cur_row, pu1_top_row)
147
148    VST1.8      {Q15},[r3]!                 @vst1q_u8(pu1_src_top[col])
149    VCLT.U8     Q7,Q5,Q14                   @vcltq_u8(pu1_cur_row, pu1_top_row)
150
151    VSUB.U8     Q8,Q7,Q6                    @sign_up = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
152    MOV         r11,r9                      @move ht to r11 for loop count
153
154PU1_SRC_LOOP:
155    ADD         r10,r10,r1                  @*pu1_src + src_strd
156    VLD1.8      D18,[r10]!                  @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
157    VLD1.8      D19,[r10]                   @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
158    SUB         r10,#8
159    ADD         r6,r10,r1                   @II Iteration *pu1_src + src_strd
160
161    VCGT.U8     Q6,Q5,Q9                    @vcgtq_u8(pu1_cur_row, pu1_top_row)
162    VLD1.8      D30,[r6]!                   @II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
163    VLD1.8      D31,[r6]                    @II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
164    SUB         r6,#8
165
166    VCLT.U8     Q7,Q5,Q9                    @vcltq_u8(pu1_cur_row, pu1_top_row)
167    SUB         r10,r10,r1
168
169    VSUB.U8     Q10,Q7,Q6                   @sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
170    VMOVL.U8    Q13,D18                     @II pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
171
172    VADD.I8     Q6,Q0,Q8                    @edge_idx = vaddq_s8(const_2, sign_up)
173    VMOVL.U8    Q14,D19                     @II pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
174
175    VADD.I8     Q6,Q6,Q10                   @edge_idx = vaddq_s8(edge_idx, sign_down)
176    VCGT.U8     Q11,Q9,Q15                  @II vcgtq_u8(pu1_cur_row, pu1_top_row)
177
178    VNEG.S8     Q8,Q10                      @sign_up = vnegq_s8(sign_down)
179    VTBL.8      D12,{D6},D12                @vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
180    VCLT.U8     Q12,Q9,Q15                  @II vcltq_u8(pu1_cur_row, pu1_top_row)
181
182    VSUB.U8     Q14,Q12,Q11                 @II sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
183    VTBL.8      D13,{D6},D13                @vtbl1_s8(edge_idx_tbl, vget_high_s8(edge_idx))
184    VADD.I8     Q11,Q0,Q8                   @II edge_idx = vaddq_s8(const_2, sign_up)
185
186
187    VUZP.8      D12,D13
188    VNEG.S8     Q8,Q14                      @II sign_up = vnegq_s8(sign_down)
189    VTBL.8      D12,{D7},D12                @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
190    VADD.I8     Q11,Q11,Q14                 @II edge_idx = vaddq_s8(edge_idx, sign_down)
191
192    VMOVL.U8    Q10,D10                     @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
193    VTBL.8      D13,{D8},D13
194    VZIP.8      D12,D13
195
196    VADDW.S8    Q10,Q10,D12                 @pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
197    VTBL.8      D22,{D6},D22                @II vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
198    VMAX.S16    Q10,Q10,Q1                  @pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
199
200    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))
201    VTBL.8      D23,{D6},D23                @II vtbl1_s8(edge_idx_tbl, vget_high_s8(edge_idx))
202    VUZP.8      D22,D23
203
204    VMOVL.U8    Q14,D11                     @pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
205    @VTBL.8     D13,D7,D13                  @offset = vtbl1_s8(offset_tbl, vget_high_s8(edge_idx))
206    VMOV        Q5,Q15                      @II pu1_cur_row = pu1_next_row
207
208    VADDW.S8    Q14,Q14,D13                 @pi2_tmp_cur_row.val[1] = vaddw_s8(pi2_tmp_cur_row.val[1], offset)
209    VTBL.8      D24,{D7},D22                @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
210    VMAX.S16    Q14,Q14,Q1                  @pi2_tmp_cur_row.val[1] = vmaxq_s16(pi2_tmp_cur_row.val[1], const_min_clip)
211
212    VTBL.8      D25,{D8},D23
213    VZIP.8      D24,D25
214    @VTBL.8     D24,D7,D22                  @II offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
215    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))
216    @VTBL.8     D25,D7,D23                  @II offset = vtbl1_s8(offset_tbl, vget_high_s8(edge_idx))
217
218    VMOVN.I16   D20,Q10                     @vmovn_s16(pi2_tmp_cur_row.val[0])
219    VADDW.S8    Q13,Q13,D24                 @II pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
220
221    VMOVN.I16   D21,Q14                     @vmovn_s16(pi2_tmp_cur_row.val[1])
222
223    VMOVL.U8    Q14,D19                     @II pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
224    VADDW.S8    Q14,Q14,D25                 @II pi2_tmp_cur_row.val[1] = vaddw_s8(pi2_tmp_cur_row.val[1], offset)
225
226
227    VMAX.S16    Q13,Q13,Q1                  @II pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
228    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))
229
230    VMAX.S16    Q14,Q14,Q1                  @II pi2_tmp_cur_row.val[1] = vmaxq_s16(pi2_tmp_cur_row.val[1], const_min_clip)
231    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))
232    VST1.8      {Q10},[r10],r1              @vst1q_u8(pu1_src_cpy, pu1_cur_row)
233
234    VMOVN.I16   D30,Q13                     @II vmovn_s16(pi2_tmp_cur_row.val[0])
235    SUBS        r11,r11,#2                  @II Decrement the ht loop count by 1
236    VMOVN.I16   D31,Q14                     @II vmovn_s16(pi2_tmp_cur_row.val[1])
237
238    VST1.8      {Q15},[r10],r1              @II vst1q_u8(pu1_src_cpy, pu1_cur_row)
239
240    BEQ         PU1_SRC_LOOP_END            @if 0 == pu1_avail[3] || 0 == pu1_avail[2] ht = ht--
241    CMP         r11,#1                      @checking any residue remains
242    BGT         PU1_SRC_LOOP                @If not equal jump to PU1_SRC_LOOP
243
244    ADD         r10,r10,r1                  @*pu1_src + src_strd
245    VLD1.8      D18,[r10]!                  @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
246    VLD1.8      D19,[r10]                   @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
247    SUB         r10,#8
248    VCGT.U8     Q6,Q5,Q9                    @vcgtq_u8(pu1_cur_row, pu1_top_row)
249    VCLT.U8     Q7,Q5,Q9                    @vcltq_u8(pu1_cur_row, pu1_top_row)
250    VSUB.U8     Q10,Q7,Q6                   @sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
251    SUB         r10,r10,r1
252
253    VADD.I8     Q11,Q0,Q8                   @edge_idx = vaddq_s8(const_2, sign_up)
254    VADD.I8     Q11,Q11,Q10                 @edge_idx = vaddq_s8(edge_idx, sign_down)
255    VTBL.8      D22,{D6},D22                @vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
256    VTBL.8      D23,{D6},D23                @vtbl1_s8(edge_idx_tbl, vget_high_s8(edge_idx))
257
258    VUZP.8      D22,D23
259    VTBL.8      D24,{D7},D22
260    VTBL.8      D25,{D8},D23
261    VZIP.8      D24,D25
262
263    @VTBL.8     D24,D7,D22                  @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
264    VMOVL.U8    Q13,D10                     @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
265    VADDW.S8    Q13,Q13,D24                 @pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
266    VMAX.S16    Q13,Q13,Q1                  @pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
267    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))
268
269    @VTBL.8     D25,D7,D23                  @offset = vtbl1_s8(offset_tbl, vget_high_s8(edge_idx))
270    VMOVL.U8    Q14,D11                     @pi2_tmp_cur_row.val[1] = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(pu1_cur_row)))
271    VADDW.S8    Q14,Q14,D25                 @pi2_tmp_cur_row.val[1] = vaddw_s8(pi2_tmp_cur_row.val[1], offset)
272    VMAX.S16    Q14,Q14,Q1                  @pi2_tmp_cur_row.val[1] = vmaxq_s16(pi2_tmp_cur_row.val[1], const_min_clip)
273    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))
274
275    VMOVN.I16   D30,Q13                     @vmovn_s16(pi2_tmp_cur_row.val[0])
276    VMOVN.I16   D31,Q14                     @vmovn_s16(pi2_tmp_cur_row.val[1])
277
278    VST1.8      {Q15},[r10],r1              @vst1q_u8(pu1_src_cpy, pu1_cur_row)
279
280PU1_SRC_LOOP_END:
281    VMOV        Q5,Q9                       @pu1_cur_row = pu1_next_row
282    SUBS        r8,r8,#16                   @Decrement the wd loop count by 16
283    CMP         r8,#8                       @Check whether residue remains
284    BEQ         WIDTH_RESIDUE               @If residue remains jump to residue loop
285    BGT         WIDTH_LOOP_16               @If not equal jump to width_loop
286    BLT         END_LOOPS                   @Jump to end function
287
288
289WIDTH_RESIDUE:
290    LDRB        r4,[r5,#2]                  @pu1_avail[2]
291    CMP         r4,#0                       @0 == pu1_avail[2]
292    SUBEQ       r11,r0,r1                   @pu1_src -= src_strd
293    MOVNE       r11,r3                      @*pu1_src_top
294    MOV         r10,r0
295
296    VLD1.8      D28,[r11]!                  @pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
297    VLD1.8      D29,[r11]!                  @pu1_top_row = vld1q_u8(pu1_src_top_cpy || pu1_src - src_strd)
298    VLD1.8      D10,[r0]!                   @pu1_cur_row = vld1q_u8(pu1_src)
299    VLD1.8      D11,[r0]!                   @pu1_cur_row = vld1q_u8(pu1_src)
300
301    VLD1.8      D30,[r12]                   @vld1_u8(pu1_src[(ht - 1) * src_strd])
302    VST1.8      {D30},[r3]                  @vst1_u8(pu1_src_top[col])
303
304    VCGT.U8     Q6,Q5,Q14                   @vcgtq_u8(pu1_cur_row, pu1_top_row)
305    VCLT.U8     Q7,Q5,Q14                   @vcltq_u8(pu1_cur_row, pu1_top_row)
306    VSUB.U8     Q8,Q7,Q6                    @sign_up = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
307    MOV         r11,r9                      @move ht to r11 for loop count
308
309PU1_SRC_LOOP_RESIDUE:
310    ADD         r10,r10,r1                  @*pu1_src + src_strd
311    VLD1.8      D18,[r10]!                  @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
312    VLD1.8      D19,[r10]                   @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
313    SUB         r10,#8
314    ADD         r6,r10,r1                   @II Iteration *pu1_src + src_strd
315
316    VCGT.U8     Q6,Q5,Q9                    @vcgtq_u8(pu1_cur_row, pu1_next_row)
317    VLD1.8      D30,[r6]!                   @II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
318    VLD1.8      D31,[r6]                    @II pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
319    SUB         r6,#8
320
321    VCLT.U8     Q7,Q5,Q9                    @vcltq_u8(pu1_cur_row, pu1_next_row)
322    SUB         r10,r10,r1
323
324    VSUB.U8     Q10,Q7,Q6                   @sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
325    VMOVL.U8    Q13,D18                     @II pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
326
327    VADD.I8     Q6,Q0,Q8                    @edge_idx = vaddq_s8(const_2, sign_up)
328    VCGT.U8     Q11,Q9,Q15                  @II vcgtq_u8(pu1_cur_row, pu1_next_row)
329
330    VADD.I8     Q6,Q6,Q10                   @edge_idx = vaddq_s8(edge_idx, sign_down)
331    VCLT.U8     Q12,Q9,Q15                  @II vcltq_u8(pu1_cur_row, pu1_next_row)
332
333    VNEG.S8     Q8,Q10                      @sign_up = vnegq_s8(sign_down)
334    VTBL.8      D12,{D6},D12                @vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
335    VSUB.U8     Q10,Q12,Q11                 @II sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
336
337    VUZP.8      D12,D13
338
339    VADD.I8     Q11,Q0,Q8                   @II edge_idx = vaddq_s8(const_2, sign_up)
340    VTBL.8      D12,{D7},D12
341    VNEG.S8     Q8,Q10                      @II sign_up = vnegq_s8(sign_down)
342
343    VTBL.8      D13,{D8},D13
344    VZIP.8      D12,D13
345
346    @VTBL.8     D12,D7,D12                  @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
347
348    VADD.I8     Q11,Q11,Q10                 @II edge_idx = vaddq_s8(edge_idx, sign_down)
349    VMOVL.U8    Q10,D10                     @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
350
351    VADDW.S8    Q10,Q10,D12                 @pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
352    VTBL.8      D22,{D6},D22                @II vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
353    VMAX.S16    Q10,Q10,Q1                  @pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
354
355    VUZP.8      D22,D23
356
357    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))
358    VTBL.8      D24,{D7},D22
359    VMOVN.I16   D20,Q10                     @vmovn_s16(pi2_tmp_cur_row.val[0])
360
361    VTBL.8      D25,{D8},D23
362    VZIP.8      D24,D25
363    @VTBL.8     D24,D7,D22                  @II offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
364
365    VADDW.S8    Q13,Q13,D24                 @II pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
366    VMAX.S16    Q13,Q13,Q1                  @II pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
367    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))
368
369    VMOV        Q5,Q15                      @II pu1_cur_row = pu1_next_row
370    VST1.8      {D20},[r10],r1              @vst1q_u8(pu1_src_cpy, pu1_cur_row)
371    VMOVN.I16   D30,Q13                     @II vmovn_s16(pi2_tmp_cur_row.val[0])
372
373    SUBS        r11,r11,#2                  @Decrement the ht loop count by 1
374    VST1.8      {D30},[r10],r1              @II vst1q_u8(pu1_src_cpy, pu1_cur_row)
375
376    BEQ         END_LOOPS
377    CMP         r11,#1
378    BGT         PU1_SRC_LOOP_RESIDUE        @If not equal jump to PU1_SRC_LOOP
379
380
381    ADD         r10,r10,r1                  @*pu1_src + src_strd
382    VLD1.8      D18,[r10]!                  @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
383    VLD1.8      D19,[r10]                   @pu1_next_row = vld1q_u8(pu1_src_cpy + src_strd)
384    SUB         r10,#8
385    VCGT.U8     Q6,Q5,Q9                    @vcgtq_u8(pu1_cur_row, pu1_next_row)
386    VCGT.U8     Q7,Q9,Q5                    @vcltq_u8(pu1_cur_row, pu1_next_row)
387    VSUB.U8     Q10,Q7,Q6                   @sign_down = vreinterpretq_s8_u8(vsubq_u8(cmp_lt, cmp_gt))
388    SUB         r10,r10,r1
389
390    VADD.I8     Q11,Q0,Q8                   @edge_idx = vaddq_s8(const_2, sign_up)
391    VADD.I8     Q11,Q11,Q10                 @edge_idx = vaddq_s8(edge_idx, sign_down)
392    VTBL.8      D22,{D6},D22                @vtbl1_s8(edge_idx_tbl, vget_low_s8(edge_idx))
393
394    VUZP.8      D22,D23
395    VTBL.8      D24,{D7},D22
396    VTBL.8      D25,{D8},D23
397    VZIP.8      D24,D25
398
399    @VTBL.8     D24,D7,D22                  @offset = vtbl1_s8(offset_tbl, vget_low_s8(edge_idx))
400    VMOVL.U8    Q13,D10                     @pi2_tmp_cur_row.val[0] = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(pu1_cur_row)))
401    VADDW.S8    Q13,Q13,D24                 @pi2_tmp_cur_row.val[0] = vaddw_s8(pi2_tmp_cur_row.val[0], offset)
402    VMAX.S16    Q13,Q13,Q1                  @pi2_tmp_cur_row.val[0] = vmaxq_s16(pi2_tmp_cur_row.val[0], const_min_clip)
403    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))
404
405    VMOVN.I16   D30,Q13                     @vmovn_s16(pi2_tmp_cur_row.val[0])
406
407    VST1.8      {D30},[r10],r1              @vst1q_u8(pu1_src_cpy, pu1_cur_row)
408
409END_LOOPS:
410    vpop        {d8  -  d15}
411    LDMFD       sp!,{r4-r12,r15}            @Reload the registers from SP
412
413
414
415
416
417
418