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 .text 96 .align 4 97 98 99 100 101 .globl ihevc_inter_pred_chroma_vert_w16inp_a9q 102 103 .type ihevc_inter_pred_chroma_vert_w16inp_a9q, %function 104 105 ihevc_inter_pred_chroma_vert_w16inp_a9q: 106 107 stmfd sp!, {r4-r12, r14} @stack stores the values of the arguments 108 109 ldr r4, [sp,#40] @loads pi1_coeff 110 ldr r6, [sp,#48] @wd 111 lsl r2,r2,#1 @src_strd = 2* src_strd 112 ldr r5,[sp,#44] @loads ht 113 vld1.8 {d0},[r4] @loads pi1_coeff 114 sub r4,r0,r2 @pu1_src - src_strd 115 vmovl.s8 q0,d0 @long the value 116 117 tst r6,#3 @checks wd == 2 118 vdup.16 d12,d0[0] @coeff_0 119 vdup.16 d13,d0[1] @coeff_1 120 vdup.16 d14,d0[2] @coeff_2 121 vdup.16 d15,d0[3] @coeff_3 122 123 bgt core_loop_ht_2 @jumps to loop handles wd 2 124 125 tst r5,#3 @checks ht == mul of 4 126 beq core_loop_ht_4 @jumps to loop handles ht mul of 4 127 128 core_loop_ht_2: 129 lsl r7,r2,#1 @2*src_strd 130 lsl r12,r3,#1 @2*dst_strd 131 lsl r9,r6,#2 @4*wd 132 sub r6,r12,r6,lsl #1 @2*dst_strd - 2*wd 133 sub r8,r7,r9 @2*src_strd - 4*wd 134 mov r12,r9 @4wd 135 136 inner_loop_ht_2: 137 add r0,r4,r2 @increments pi2_src 138 vld1.16 {d0},[r4]! @loads pu1_src 139 vmull.s16 q0,d0,d12 @vmull_s16(src_tmp1, coeff_0) 140 subs r12,r12,#8 @2wd + 8 141 vld1.16 {d2},[r0],r2 @loads pi2_src 142 vmull.s16 q4,d2,d12 @vmull_s16(src_tmp2, coeff_0) 143 vld1.16 {d3},[r0],r2 @loads pi2_src 144 vmlal.s16 q0,d2,d13 145 vld1.16 {d6},[r0],r2 146 vmlal.s16 q4,d3,d13 147 vld1.16 {d2},[r0] 148 add r7,r1,r3 @pu1_dst + dst_strd 149 vmlal.s16 q0,d3,d14 150 vmlal.s16 q4,d6,d14 151 vmlal.s16 q0,d6,d15 152 vmlal.s16 q4,d2,d15 153 vqshrn.s32 d0,q0,#6 @right shift 154 vqshrn.s32 d30,q4,#6 @right shift 155 vqrshrun.s16 d0,q0,#6 @rounding shift 156 vqrshrun.s16 d30,q15,#6 @rounding shift 157 vst1.32 {d0[0]},[r1]! @stores the loaded value 158 vst1.32 {d30[0]},[r7] @stores the loaded value 159 bgt inner_loop_ht_2 @inner loop -again 160 161 @inner loop ends 162 subs r5,r5,#2 @increments ht 163 add r1,r1,r6 @pu1_dst += 2*dst_strd - 2*wd 164 mov r12,r9 @4wd 165 add r4,r4,r8 @pi1_src_tmp1 += 2*src_strd - 4*wd 166 bgt inner_loop_ht_2 @loop again 167 168 b end_loops @jumps to end 169 170 core_loop_ht_4: 171 lsl r7,r2,#2 @2*src_strd 172 lsl r12,r3,#2 @2*dst_strd 173 mov r11,r6,lsr #1 @divide by 2 174 sub lr,r12,r6,lsl #1 @2*dst_strd - 2*wd 175 sub r8,r7,r6,lsl #2 @2*src_strd - 4*wd 176 177 mul r12,r5,r11 @multiply height by width 178 sub r12,#4 @subtract by one for epilog 179 mov r11,r6,lsl #1 @2*wd 180 181 prolog: 182 add r0,r4,r2 @increments pi2_src 183 vld1.16 {d0},[r4]! @loads pu1_src 184 vld1.16 {d1},[r0],r2 @loads pi2_src 185 subs r11,r11,#4 186 vld1.16 {d2},[r0],r2 @loads pi2_src 187 vmull.s16 q15,d0,d12 @vmull_s16(src_tmp1, coeff_0) 188 vld1.16 {d3},[r0],r2 189 vmlal.s16 q15,d1,d13 190 vmlal.s16 q15,d2,d14 191 add r9,r1,r3 @pu1_dst + dst_strd 192 vmlal.s16 q15,d3,d15 193 194 vld1.16 {d4},[r0],r2 195 vmull.s16 q14,d1,d12 @vmull_s16(src_tmp2, coeff_0) 196 addle r4,r4,r8 197 vmlal.s16 q14,d2,d13 198 vld1.s16 {d5},[r0],r2 199 vmlal.s16 q14,d3,d14 200 vld1.s16 {d6},[r0],r2 201 vmlal.s16 q14,d4,d15 202 movle r11,r6,lsl #1 203 204 vqshrn.s32 d30,q15,#6 @right shift 205 206 vmull.s16 q13,d2,d12 @vmull_s16(src_tmp2, coeff_0) 207 add r0,r4,r2 208 vmlal.s16 q13,d3,d13 209 vmlal.s16 q13,d4,d14 210 vld1.16 {d0},[r4]! @loads pu1_src 211 vmlal.s16 q13,d5,d15 212 213 vqrshrun.s16 d30,q15,#6 @rounding shift 214 vqshrn.s32 d28,q14,#6 @right shift 215 216 vld1.16 {d1},[r0],r2 @loads pi2_src 217 vmull.s16 q12,d3,d12 @vmull_s16(src_tmp2, coeff_0) 218 vst1.32 {d30[0]},[r1]! @stores the loaded value 219 vmlal.s16 q12,d4,d13 220 vld1.16 {d2},[r0],r2 @loads pi2_src 221 vmlal.s16 q12,d5,d14 222 vld1.16 {d3},[r0],r2 223 vmlal.s16 q12,d6,d15 224 addle r1,r1,lr 225 226 vqshrn.s32 d26,q13,#6 @right shift 227 subs r12,r12,#4 228 vqrshrun.s16 d28,q14,#6 @rounding shift 229 230 beq epilog @jumps to epilog 231 232 kernel_4: 233 vmull.s16 q15,d0,d12 @vmull_s16(src_tmp1, coeff_0) 234 subs r11,r11,#4 235 vmlal.s16 q15,d1,d13 236 vst1.32 {d28[0]},[r9],r3 @stores the loaded value 237 vmlal.s16 q15,d2,d14 238 vmlal.s16 q15,d3,d15 239 240 vqshrn.s32 d24,q12,#6 @right shift 241 vqrshrun.s16 d26,q13,#6 @rounding shift 242 243 vld1.16 {d4},[r0],r2 244 vmull.s16 q14,d1,d12 @vmull_s16(src_tmp2, coeff_0) 245 vmlal.s16 q14,d2,d13 246 vmlal.s16 q14,d3,d14 247 vmlal.s16 q14,d4,d15 248 vst1.32 {d26[0]},[r9],r3 @stores the loaded value 249 addle r4,r4,r8 250 movle r11,r6,lsl #1 251 252 vqshrn.s32 d30,q15,#6 @right shift 253 vqrshrun.s16 d24,q12,#6 @rounding shift 254 255 vld1.s16 {d5},[r0],r2 256 vmull.s16 q13,d2,d12 @vmull_s16(src_tmp2, coeff_0) 257 vld1.s16 {d6},[r0],r2 258 vmlal.s16 q13,d3,d13 259 vst1.32 {d24[0]},[r9] @stores the loaded value 260 add r0,r4,r2 261 vmlal.s16 q13,d4,d14 262 vld1.16 {d0},[r4]! @loads pu1_src 263 vmlal.s16 q13,d5,d15 264 265 vqshrn.s32 d28,q14,#6 @right shift 266 vqrshrun.s16 d30,q15,#6 @rounding shift 267 268 vld1.16 {d1},[r0],r2 @loads pi2_src 269 vmull.s16 q12,d3,d12 @vmull_s16(src_tmp2, coeff_0) 270 add r9,r1,r3 @pu1_dst + dst_strd 271 vld1.16 {d2},[r0],r2 @loads pi2_src 272 vmlal.s16 q12,d4,d13 273 vld1.16 {d3},[r0],r2 274 vmlal.s16 q12,d5,d14 275 276 vst1.32 {d30[0]},[r1]! @stores the loaded value 277 vmlal.s16 q12,d6,d15 278 279 vqshrn.s32 d26,q13,#6 @right shift 280 vqrshrun.s16 d28,q14,#6 @rounding shift 281 addle r1,r1,lr 282 283 subs r12,r12,#4 284 285 bgt kernel_4 @jumps to kernel_4 286 287 epilog: 288 vmull.s16 q15,d0,d12 @vmull_s16(src_tmp1, coeff_0) 289 vst1.32 {d28[0]},[r9],r3 @stores the loaded value 290 vmlal.s16 q15,d1,d13 291 vmlal.s16 q15,d2,d14 292 vmlal.s16 q15,d3,d15 293 294 vqshrn.s32 d24,q12,#6 @right shift 295 vqrshrun.s16 d26,q13,#6 @rounding shift 296 297 vmull.s16 q14,d1,d12 @vmull_s16(src_tmp2, coeff_0) 298 vld1.16 {d4},[r0],r2 299 vmlal.s16 q14,d2,d13 300 vst1.32 {d26[0]},[r9],r3 @stores the loaded value 301 vmlal.s16 q14,d3,d14 302 vmlal.s16 q14,d4,d15 303 304 vqshrn.s32 d30,q15,#6 @right shift 305 vqrshrun.s16 d24,q12,#6 @rounding shift 306 307 vmull.s16 q13,d2,d12 @vmull_s16(src_tmp2, coeff_0) 308 vld1.s16 {d5},[r0],r2 309 vmlal.s16 q13,d3,d13 310 vmlal.s16 q13,d4,d14 311 vmlal.s16 q13,d5,d15 312 313 vqshrn.s32 d28,q14,#6 @right shift 314 vqrshrun.s16 d30,q15,#6 @rounding shift 315 316 vst1.32 {d24[0]},[r9] @stores the loaded value 317 vmull.s16 q12,d3,d12 @vmull_s16(src_tmp2, coeff_0) 318 vmlal.s16 q12,d4,d13 319 add r9,r1,r3 @pu1_dst + dst_strd 320 vld1.s16 {d6},[r0],r2 321 vmlal.s16 q12,d5,d14 322 vmlal.s16 q12,d6,d15 323 vst1.32 {d30[0]},[r1]! @stores the loaded value 324 325 vqrshrun.s16 d28,q14,#6 @rounding shift 326 vqshrn.s32 d26,q13,#6 @right shift 327 328 vst1.32 {d28[0]},[r9],r3 @stores the loaded value 329 vqrshrun.s16 d26,q13,#6 @rounding shift 330 331 vqshrn.s32 d24,q12,#6 @right shift 332 vst1.32 {d26[0]},[r9],r3 @stores the loaded value 333 vqrshrun.s16 d24,q12,#6 @rounding shift 334 335 vst1.32 {d24[0]},[r9] @stores the loaded value 336 337 end_loops: 338 ldmfd sp!,{r4-r12,r15} @reload the registers from sp 339 340 341 342 343