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_inter_pred_chroma_vert_neon_w16inp_neon.s 22@* 23@* @brief 24@* contains function definitions for inter prediction interpolation. 25@* functions are coded using neon intrinsics and can be compiled using 26 27@* rvct 28@* 29@* @author 30@* yogeswaran rs / parthiban 31@* 32@* @par list of functions: 33@* 34@* 35@* @remarks 36@* none 37@* 38@******************************************************************************* 39@*/ 40@/** 41@/** 42@******************************************************************************* 43@* 44@* @brief 45@* chroma interprediction filter for 16bit vertical input. 46@* 47@* @par description: 48@* applies a vertical filter with coefficients pointed to by 'pi1_coeff' to 49@* the elements pointed by 'pu1_src' and writes to the location pointed by 50@* 'pu1_dst' input is 16 bits the filter output is downshifted by 12 and 51@* clipped to lie between 0 and 255 assumptions : the function is 52@* optimized considering the fact width and height are multiple of 2. 53@* 54@* @param[in] pi2_src 55@* word16 pointer to the source 56@* 57@* @param[out] pu1_dst 58@* uword8 pointer to the destination 59@* 60@* @param[in] src_strd 61@* integer source stride 62@* 63@* @param[in] dst_strd 64@* integer destination stride 65@* 66@* @param[in] pi1_coeff 67@* word8 pointer to the filter coefficients 68@* 69@* @param[in] ht 70@* integer height of the array 71@* 72@* @param[in] wd 73@* integer width of the array 74@* 75@* @returns 76@* 77@* @remarks 78@* none 79@* 80@******************************************************************************* 81@*/ 82@void ihevc_inter_pred_chroma_vert_w16inp(word16 *pi2_src, 83@ uword8 *pu1_dst, 84@ word32 src_strd, 85@ word32 dst_strd, 86@ word8 *pi1_coeff, 87@ word32 ht, 88@ word32 wd) 89@**************variables vs registers***************************************** 90@r0 => *pu1_src 91@r1 => *pi2_dst 92@r2 => src_strd 93@r3 => dst_strd 94 95.equ coeff_offset, 104 96.equ ht_offset, 108 97.equ wd_offset, 112 98 99 100.text 101.align 4 102 103 104 105 106.globl ihevc_inter_pred_chroma_vert_w16inp_a9q 107 108.type ihevc_inter_pred_chroma_vert_w16inp_a9q, %function 109 110ihevc_inter_pred_chroma_vert_w16inp_a9q: 111 112 stmfd sp!, {r4-r12, r14} @stack stores the values of the arguments 113 vpush {d8 - d15} 114 115 ldr r4, [sp,#coeff_offset] @loads pi1_coeff 116 ldr r6, [sp,#wd_offset] @wd 117 lsl r2,r2,#1 @src_strd = 2* src_strd 118 ldr r5,[sp,#ht_offset] @loads ht 119 vld1.8 {d0},[r4] @loads pi1_coeff 120 sub r4,r0,r2 @pu1_src - src_strd 121 vmovl.s8 q0,d0 @long the value 122 123 tst r6,#3 @checks wd == 2 124 vdup.16 d12,d0[0] @coeff_0 125 vdup.16 d13,d0[1] @coeff_1 126 vdup.16 d14,d0[2] @coeff_2 127 vdup.16 d15,d0[3] @coeff_3 128 129 bgt core_loop_ht_2 @jumps to loop handles wd 2 130 131 tst r5,#3 @checks ht == mul of 4 132 beq core_loop_ht_4 @jumps to loop handles ht mul of 4 133 134core_loop_ht_2: 135 lsl r7,r2,#1 @2*src_strd 136 lsl r12,r3,#1 @2*dst_strd 137 lsl r9,r6,#2 @4*wd 138 sub r6,r12,r6,lsl #1 @2*dst_strd - 2*wd 139 sub r8,r7,r9 @2*src_strd - 4*wd 140 mov r12,r9 @4wd 141 142inner_loop_ht_2: 143 add r0,r4,r2 @increments pi2_src 144 vld1.16 {d0},[r4]! @loads pu1_src 145 vmull.s16 q0,d0,d12 @vmull_s16(src_tmp1, coeff_0) 146 subs r12,r12,#8 @2wd + 8 147 vld1.16 {d2},[r0],r2 @loads pi2_src 148 vmull.s16 q4,d2,d12 @vmull_s16(src_tmp2, coeff_0) 149 vld1.16 {d3},[r0],r2 @loads pi2_src 150 vmlal.s16 q0,d2,d13 151 vld1.16 {d6},[r0],r2 152 vmlal.s16 q4,d3,d13 153 vld1.16 {d2},[r0] 154 add r7,r1,r3 @pu1_dst + dst_strd 155 vmlal.s16 q0,d3,d14 156 vmlal.s16 q4,d6,d14 157 vmlal.s16 q0,d6,d15 158 vmlal.s16 q4,d2,d15 159 vqshrn.s32 d0,q0,#6 @right shift 160 vqshrn.s32 d30,q4,#6 @right shift 161 vqrshrun.s16 d0,q0,#6 @rounding shift 162 vqrshrun.s16 d30,q15,#6 @rounding shift 163 vst1.32 {d0[0]},[r1]! @stores the loaded value 164 vst1.32 {d30[0]},[r7] @stores the loaded value 165 bgt inner_loop_ht_2 @inner loop -again 166 167 @inner loop ends 168 subs r5,r5,#2 @increments ht 169 add r1,r1,r6 @pu1_dst += 2*dst_strd - 2*wd 170 mov r12,r9 @4wd 171 add r4,r4,r8 @pi1_src_tmp1 += 2*src_strd - 4*wd 172 bgt inner_loop_ht_2 @loop again 173 174 b end_loops @jumps to end 175 176core_loop_ht_4: 177 lsl r7,r2,#2 @2*src_strd 178 lsl r12,r3,#2 @2*dst_strd 179 mov r11,r6,lsr #1 @divide by 2 180 sub lr,r12,r6,lsl #1 @2*dst_strd - 2*wd 181 sub r8,r7,r6,lsl #2 @2*src_strd - 4*wd 182 183 mul r12,r5,r11 @multiply height by width 184 sub r12,#4 @subtract by one for epilog 185 mov r11,r6,lsl #1 @2*wd 186 187prolog: 188 add r0,r4,r2 @increments pi2_src 189 vld1.16 {d0},[r4]! @loads pu1_src 190 vld1.16 {d1},[r0],r2 @loads pi2_src 191 subs r11,r11,#4 192 vld1.16 {d2},[r0],r2 @loads pi2_src 193 vmull.s16 q15,d0,d12 @vmull_s16(src_tmp1, coeff_0) 194 vld1.16 {d3},[r0],r2 195 vmlal.s16 q15,d1,d13 196 vmlal.s16 q15,d2,d14 197 add r9,r1,r3 @pu1_dst + dst_strd 198 vmlal.s16 q15,d3,d15 199 200 vld1.16 {d4},[r0],r2 201 vmull.s16 q14,d1,d12 @vmull_s16(src_tmp2, coeff_0) 202 addle r4,r4,r8 203 vmlal.s16 q14,d2,d13 204 vld1.s16 {d5},[r0],r2 205 vmlal.s16 q14,d3,d14 206 vld1.s16 {d6},[r0],r2 207 vmlal.s16 q14,d4,d15 208 movle r11,r6,lsl #1 209 210 vqshrn.s32 d30,q15,#6 @right shift 211 212 vmull.s16 q13,d2,d12 @vmull_s16(src_tmp2, coeff_0) 213 add r0,r4,r2 214 vmlal.s16 q13,d3,d13 215 vmlal.s16 q13,d4,d14 216 vld1.16 {d0},[r4]! @loads pu1_src 217 vmlal.s16 q13,d5,d15 218 219 vqrshrun.s16 d30,q15,#6 @rounding shift 220 vqshrn.s32 d28,q14,#6 @right shift 221 222 vld1.16 {d1},[r0],r2 @loads pi2_src 223 vmull.s16 q12,d3,d12 @vmull_s16(src_tmp2, coeff_0) 224 vst1.32 {d30[0]},[r1]! @stores the loaded value 225 vmlal.s16 q12,d4,d13 226 vld1.16 {d2},[r0],r2 @loads pi2_src 227 vmlal.s16 q12,d5,d14 228 vld1.16 {d3},[r0],r2 229 vmlal.s16 q12,d6,d15 230 addle r1,r1,lr 231 232 vqshrn.s32 d26,q13,#6 @right shift 233 subs r12,r12,#4 234 vqrshrun.s16 d28,q14,#6 @rounding shift 235 236 beq epilog @jumps to epilog 237 238kernel_4: 239 vmull.s16 q15,d0,d12 @vmull_s16(src_tmp1, coeff_0) 240 subs r11,r11,#4 241 vmlal.s16 q15,d1,d13 242 vst1.32 {d28[0]},[r9],r3 @stores the loaded value 243 vmlal.s16 q15,d2,d14 244 vmlal.s16 q15,d3,d15 245 246 vqshrn.s32 d24,q12,#6 @right shift 247 vqrshrun.s16 d26,q13,#6 @rounding shift 248 249 vld1.16 {d4},[r0],r2 250 vmull.s16 q14,d1,d12 @vmull_s16(src_tmp2, coeff_0) 251 vmlal.s16 q14,d2,d13 252 vmlal.s16 q14,d3,d14 253 vmlal.s16 q14,d4,d15 254 vst1.32 {d26[0]},[r9],r3 @stores the loaded value 255 addle r4,r4,r8 256 movle r11,r6,lsl #1 257 258 vqshrn.s32 d30,q15,#6 @right shift 259 vqrshrun.s16 d24,q12,#6 @rounding shift 260 261 vld1.s16 {d5},[r0],r2 262 vmull.s16 q13,d2,d12 @vmull_s16(src_tmp2, coeff_0) 263 vld1.s16 {d6},[r0],r2 264 vmlal.s16 q13,d3,d13 265 vst1.32 {d24[0]},[r9] @stores the loaded value 266 add r0,r4,r2 267 vmlal.s16 q13,d4,d14 268 vld1.16 {d0},[r4]! @loads pu1_src 269 vmlal.s16 q13,d5,d15 270 271 vqshrn.s32 d28,q14,#6 @right shift 272 vqrshrun.s16 d30,q15,#6 @rounding shift 273 274 vld1.16 {d1},[r0],r2 @loads pi2_src 275 vmull.s16 q12,d3,d12 @vmull_s16(src_tmp2, coeff_0) 276 add r9,r1,r3 @pu1_dst + dst_strd 277 vld1.16 {d2},[r0],r2 @loads pi2_src 278 vmlal.s16 q12,d4,d13 279 vld1.16 {d3},[r0],r2 280 vmlal.s16 q12,d5,d14 281 282 vst1.32 {d30[0]},[r1]! @stores the loaded value 283 vmlal.s16 q12,d6,d15 284 285 vqshrn.s32 d26,q13,#6 @right shift 286 vqrshrun.s16 d28,q14,#6 @rounding shift 287 addle r1,r1,lr 288 289 subs r12,r12,#4 290 291 bgt kernel_4 @jumps to kernel_4 292 293epilog: 294 vmull.s16 q15,d0,d12 @vmull_s16(src_tmp1, coeff_0) 295 vst1.32 {d28[0]},[r9],r3 @stores the loaded value 296 vmlal.s16 q15,d1,d13 297 vmlal.s16 q15,d2,d14 298 vmlal.s16 q15,d3,d15 299 300 vqshrn.s32 d24,q12,#6 @right shift 301 vqrshrun.s16 d26,q13,#6 @rounding shift 302 303 vmull.s16 q14,d1,d12 @vmull_s16(src_tmp2, coeff_0) 304 vld1.16 {d4},[r0],r2 305 vmlal.s16 q14,d2,d13 306 vst1.32 {d26[0]},[r9],r3 @stores the loaded value 307 vmlal.s16 q14,d3,d14 308 vmlal.s16 q14,d4,d15 309 310 vqshrn.s32 d30,q15,#6 @right shift 311 vqrshrun.s16 d24,q12,#6 @rounding shift 312 313 vmull.s16 q13,d2,d12 @vmull_s16(src_tmp2, coeff_0) 314 vld1.s16 {d5},[r0],r2 315 vmlal.s16 q13,d3,d13 316 vmlal.s16 q13,d4,d14 317 vmlal.s16 q13,d5,d15 318 319 vqshrn.s32 d28,q14,#6 @right shift 320 vqrshrun.s16 d30,q15,#6 @rounding shift 321 322 vst1.32 {d24[0]},[r9] @stores the loaded value 323 vmull.s16 q12,d3,d12 @vmull_s16(src_tmp2, coeff_0) 324 vmlal.s16 q12,d4,d13 325 add r9,r1,r3 @pu1_dst + dst_strd 326 vld1.s16 {d6},[r0],r2 327 vmlal.s16 q12,d5,d14 328 vmlal.s16 q12,d6,d15 329 vst1.32 {d30[0]},[r1]! @stores the loaded value 330 331 vqrshrun.s16 d28,q14,#6 @rounding shift 332 vqshrn.s32 d26,q13,#6 @right shift 333 334 vst1.32 {d28[0]},[r9],r3 @stores the loaded value 335 vqrshrun.s16 d26,q13,#6 @rounding shift 336 337 vqshrn.s32 d24,q12,#6 @right shift 338 vst1.32 {d26[0]},[r9],r3 @stores the loaded value 339 vqrshrun.s16 d24,q12,#6 @rounding shift 340 341 vst1.32 {d24[0]},[r9] @stores the loaded value 342 343end_loops: 344 vpop {d8 - d15} 345 ldmfd sp!,{r4-r12,r15} @reload the registers from sp 346 347 348 349 350