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
69gi1_table_edge_idx_addr:
70.long gi1_table_edge_idx - ulbl1 - 8
71
72ihevc_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
90SRC_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
113ulbl1:
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
122WIDTH_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
145PU1_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
271PU1_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
280WIDTH_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
300PU1_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
400END_LOOPS:
401    LDMFD       sp!,{r4-r12,r15}            @Reload the registers from SP
402
403
404
405
406
407
408