1 @/****************************************************************************** 2 @ * 3 @ * Copyright (C) 2015 The Android Open Source Project 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 @ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore 19 @*/ 20 @** 21 @****************************************************************************** 22 @* @file 23 @* ih264_inter_pred_luma_horz_qpel_vert_hpel_a9q.s 24 @* 25 @* @brief 26 @* Contains function definitions for inter prediction interpolation. 27 @* 28 @* @author 29 @* Mohit 30 @* 31 @* @par List of Functions: 32 @* 33 @* - ih264_inter_pred_luma_horz_qpel_vert_hpel_a9q() 34 @* 35 @* @remarks 36 @* None 37 @* 38 @******************************************************************************* 39 @* 40 41 @* All the functions here are replicated from ih264_inter_pred_filters.c 42 @ 43 44 @** 45 @** 46 @** 47 @******************************************************************************* 48 @* 49 @* @brief 50 @* This function implements a two stage cascaded six tap filter. It 51 @* applies the six tap filter in the vertical direction on the 52 @* predictor values, followed by applying the same filter in the 53 @* horizontal direction on the output of the first stage. It then averages 54 @* the output of the 1st stage and the final stage to obtain the quarter 55 @* pel values.The six tap filtering operation is described in sec 8.4.2.2.1 56 @* titled "Luma sample interpolation process". 57 @* 58 @* @par Description: 59 @* This function is called to obtain pixels lying at the following 60 @* location (1/4,1/2) or (3/4,1/2). The function interpolates 61 @* the predictors first in the verical direction and then in the 62 @* horizontal direction to output the (1/2,1/2). It then averages 63 @* the output of the 2nd stage and (1/2,1/2) value to obtain (1/4,1/2) 64 @* or (3/4,1/2) depending on the offset. 65 @* 66 @* @param[in] pu1_src 67 @* UWORD8 pointer to the source 68 @* 69 @* @param[out] pu1_dst 70 @* UWORD8 pointer to the destination 71 @* 72 @* @param[in] src_strd 73 @* integer source stride 74 @* 75 @* @param[in] dst_strd 76 @* integer destination stride 77 @* 78 @* @param[in] ht 79 @* integer height of the array 80 @* 81 @* @param[in] wd 82 @* integer width of the array 83 @* 84 @* @param[in] pu1_tmp: temporary buffer 85 @* 86 @* @param[in] dydx: x and y reference offset for qpel calculations 87 @* 88 @* @returns 89 @* 90 @* @remarks 91 @* None 92 @* 93 @******************************************************************************* 94 @*; 95 96 @void ih264_inter_pred_luma_horz_qpel_vert_hpel(UWORD8 *pu1_src, 97 @ UWORD8 *pu1_dst, 98 @ WORD32 src_strd,, 99 @ WORD32 dst_strd, 100 @ WORD32 ht, 101 @ WORD32 wd, 102 @ UWORD8* pu1_tmp, 103 @ UWORD32 dydx) 104 105 @**************Variables Vs Registers***************************************** 106 @ r0 => *pu1_src 107 @ r1 => *pu1_dst 108 @ r2 => src_strd 109 @ r3 => dst_strd 110 @ r4 => ht 111 @ r5 => wd 112 @ r6 => dydx 113 @ r9 => *pu1_tmp 114 115 .text 116 .p2align 2 117 118 .global ih264_inter_pred_luma_horz_qpel_vert_hpel_a9q 119 120 ih264_inter_pred_luma_horz_qpel_vert_hpel_a9q: 121 122 stmfd sp!, {r4-r12, r14} @store register values to stack 123 vstmdb sp!, {d8-d15} @push neon registers to stack 124 ldr r4, [sp, #104] @ loads ht 125 sub r0, r0, r2, lsl #1 @pu1_src-2*src_strd 126 sub r0, r0, #2 @pu1_src-2 127 ldr r5, [sp, #108] @ loads wd 128 ldr r6, [sp, #116] @ loads dydx 129 and r6, r6, #2 @ dydx & 0x3 followed by dydx>>1 and dydx<<1 130 ldr r9, [sp, #112] @pu1_tmp 131 add r7, r9, #4 132 add r6, r7, r6 @ pi16_pred1_temp += (x_offset>>1) 133 134 vmov.u16 q13, #0x14 @ Filter coeff 20 into Q13 135 vmov.u16 q12, #0x5 @ Filter coeff 5 into Q12 136 mov r7, #0x20 137 mov r8, #0x30 138 subs r12, r5, #4 @if wd=4 branch to loop_4 139 beq loop_4 140 141 subs r12, r5, #8 @if wd=8 branch to loop_8 142 beq loop_8 143 144 @when wd=16 145 vmov.u16 q14, #0x14 @ Filter coeff 20 into Q13 146 vmov.u16 q15, #0x5 @ Filter coeff 5 into Q12 147 add r14, r2, #0 148 sub r2, r2, #16 149 150 151 loop_16: 152 153 vld1.u32 {q0}, [r0]! @ Vector load from src[0_0] 154 vld1.u32 d12, [r0], r2 @ Vector load from src[0_0] 155 vld1.u32 {q1}, [r0]! @ Vector load from src[1_0] 156 vld1.u32 d13, [r0], r2 @ Vector load from src[1_0] 157 vld1.u32 {q2}, [r0]! @ Vector load from src[2_0] 158 vld1.u32 d14, [r0], r2 @ Vector load from src[2_0] 159 vld1.u32 {q3}, [r0]! @ Vector load from src[3_0] 160 vld1.u32 d15, [r0], r2 @ Vector load from src[3_0] 161 vld1.u32 {q4}, [r0]! @ Vector load from src[4_0] 162 vld1.u32 d16, [r0], r2 @ Vector load from src[4_0] 163 164 vld1.u32 {q5}, [r0]! @ Vector load from src[5_0] 165 vld1.u32 d17, [r0], r2 @ Vector load from src[5_0] 166 167 vaddl.u8 q10, d4, d6 168 vaddl.u8 q9, d0, d10 169 vaddl.u8 q11, d2, d8 170 vmla.u16 q9, q10, q14 171 vaddl.u8 q12, d5, d7 172 vaddl.u8 q10, d1, d11 173 vaddl.u8 q13, d3, d9 174 vmla.u16 q10, q12, q14 175 vaddl.u8 q12, d14, d15 176 vmls.u16 q9, q11, q15 177 vaddl.u8 q11, d12, d17 178 vmls.u16 q10, q13, q15 179 vaddl.u8 q13, d13, d16 180 vmla.u16 q11, q12, q14 181 vmls.u16 q11, q13, q15 182 vst1.32 {q9}, [r9]! 183 vst1.32 {q10}, [r9]! 184 vext.16 q12, q9, q10, #2 185 vext.16 q13, q9, q10, #3 186 vst1.32 {q11}, [r9] 187 vext.16 q11, q9, q10, #5 188 vadd.s16 q0, q12, q13 189 vext.16 q12, q9, q10, #1 190 vext.16 q13, q9, q10, #4 191 vadd.s16 q12, q12, q13 192 193 vaddl.s16 q13, d18, d22 194 vmlal.s16 q13, d0, d28 195 vmlsl.s16 q13, d24, d30 196 197 vaddl.s16 q11, d19, d23 198 vmlal.s16 q11, d1, d28 199 vmlsl.s16 q11, d25, d30 200 201 vqrshrun.s32 d18, q13, #10 202 vqrshrun.s32 d19, q11, #10 203 vld1.32 {q11}, [r9]! 204 vqmovn.u16 d18, q9 205 206 vext.16 q12, q10, q11, #2 207 vext.16 q13, q10, q11, #3 208 vext.16 q0, q10, q11, #5 209 vst1.32 d18, [r1] 210 vadd.s16 q9, q12, q13 211 vext.16 q12, q10, q11, #1 212 vext.16 q13, q10, q11, #4 213 vadd.s16 q12, q12, q13 214 215 vaddl.s16 q13, d0, d20 216 vmlal.s16 q13, d18, d28 217 vmlsl.s16 q13, d24, d30 218 219 vaddl.s16 q11, d1, d21 220 vmlal.s16 q11, d19, d28 221 vmlsl.s16 q11, d25, d30 222 223 vqrshrun.s32 d18, q13, #10 224 vqrshrun.s32 d19, q11, #10 225 226 vaddl.u8 q12, d7, d9 227 vld1.32 {q10}, [r6]! 228 vld1.32 {q11}, [r6], r7 229 230 vqmovn.u16 d19, q9 231 232 vld1.32 d18, [r1] 233 vqrshrun.s16 d20, q10, #5 234 vqrshrun.s16 d21, q11, #5 235 vaddl.u8 q11, d4, d10 236 vld1.u32 {q0}, [r0]! @ Vector load from src[6_0] 237 vrhadd.u8 q9, q9, q10 238 vld1.u32 d12, [r0], r2 @ Vector load from src[6_0] 239 vaddl.u8 q10, d6, d8 240 vaddl.u8 q13, d5, d11 241 vst1.32 {q9}, [r1], r3 @ store row 0 242 243 @ROW_2 244 245 vaddl.u8 q9, d2, d0 246 247 vmla.u16 q9, q10, q14 248 249 vaddl.u8 q10, d3, d1 250 251 vmla.u16 q10, q12, q14 252 vaddl.u8 q12, d15, d16 253 vmls.u16 q9, q11, q15 254 vaddl.u8 q11, d13, d12 255 vmls.u16 q10, q13, q15 256 vaddl.u8 q13, d14, d17 257 vmla.u16 q11, q12, q14 258 vmls.u16 q11, q13, q15 259 vst1.32 {q9}, [r9]! 260 vst1.32 {q10}, [r9]! 261 vext.16 q12, q9, q10, #2 262 vext.16 q13, q9, q10, #3 263 vst1.32 {q11}, [r9] 264 vext.16 q11, q9, q10, #5 265 vadd.s16 q1, q12, q13 266 vext.16 q12, q9, q10, #1 267 vext.16 q13, q9, q10, #4 268 vadd.s16 q12, q12, q13 269 270 vaddl.s16 q13, d18, d22 271 vmlal.s16 q13, d2, d28 272 vmlsl.s16 q13, d24, d30 273 274 vaddl.s16 q11, d19, d23 275 vmlal.s16 q11, d3, d28 276 vmlsl.s16 q11, d25, d30 277 278 vqrshrun.s32 d18, q13, #10 279 vqrshrun.s32 d19, q11, #10 280 vld1.32 {q11}, [r9]! 281 vqmovn.u16 d18, q9 282 283 vext.16 q12, q10, q11, #2 284 vext.16 q13, q10, q11, #3 285 vext.16 q1, q10, q11, #5 286 vst1.32 d18, [r1] 287 vadd.s16 q9, q12, q13 288 vext.16 q12, q10, q11, #1 289 vext.16 q13, q10, q11, #4 290 vadd.s16 q12, q12, q13 291 292 vaddl.s16 q13, d2, d20 293 vmlal.s16 q13, d18, d28 294 vmlsl.s16 q13, d24, d30 295 296 vaddl.s16 q11, d3, d21 297 vmlal.s16 q11, d19, d28 298 vmlsl.s16 q11, d25, d30 299 300 vqrshrun.s32 d18, q13, #10 301 vqrshrun.s32 d19, q11, #10 302 vaddl.u8 q12, d9, d11 303 vld1.32 {q10}, [r6]! 304 vld1.32 {q11}, [r6], r7 305 vqmovn.u16 d19, q9 306 vld1.32 d18, [r1] 307 vqrshrun.s16 d20, q10, #5 308 vqrshrun.s16 d21, q11, #5 309 310 vrhadd.u8 q9, q9, q10 311 312 vst1.32 {q9}, [r1], r3 @ store row 1 313 314 subs r4, r4, #2 315 subne r0, r0 , r14, lsl #2 316 subne r0, r0, r14 317 318 beq end_func @ Branch if height==4 319 b loop_16 @ Loop if height==8 320 321 loop_8: 322 vld1.u32 {q0}, [r0], r2 @ Vector load from src[0_0] 323 vld1.u32 {q1}, [r0], r2 @ Vector load from src[1_0] 324 vld1.u32 {q2}, [r0], r2 @ Vector load from src[2_0] 325 vld1.u32 {q3}, [r0], r2 @ Vector load from src[3_0] 326 vld1.u32 {q4}, [r0], r2 @ Vector load from src[4_0] 327 328 vld1.u32 {q5}, [r0], r2 @ Vector load from src[5_0] 329 vaddl.u8 q7, d4, d6 330 vaddl.u8 q6, d0, d10 331 vaddl.u8 q8, d2, d8 332 vmla.u16 q6, q7, q13 333 vaddl.u8 q9, d5, d7 334 vaddl.u8 q7, d1, d11 335 vaddl.u8 q11, d3, d9 336 vmla.u16 q7, q9, q13 337 vmls.u16 q6, q8, q12 338 vld1.32 {q0}, [r0], r2 @ Vector load from src[6_0] 339 vaddl.u8 q8, d6, d8 340 vmls.u16 q7, q11, q12 341 vaddl.u8 q14, d2, d0 342 vst1.32 {q6}, [r9]! @ store row 0 to temp buffer: col 0 343 vext.16 q11, q6, q7, #5 344 vaddl.u8 q9, d4, d10 345 vmla.u16 q14, q8, q13 346 vaddl.s16 q15, d12, d22 347 vst1.32 {q7}, [r9], r7 @ store row 0 to temp buffer: col 1 348 vaddl.s16 q11, d13, d23 349 vext.16 q8, q6, q7, #2 350 vmls.u16 q14, q9, q12 351 vext.16 q9, q6, q7, #3 352 vext.16 q10, q6, q7, #4 353 vext.16 q7, q6, q7, #1 354 vadd.s16 q8, q8, q9 355 vadd.s16 q9, q7, q10 356 vaddl.u8 q10, d7, d9 357 vmlal.s16 q15, d16, d26 358 vmlsl.s16 q15, d18, d24 359 vmlal.s16 q11, d17, d26 360 vmlsl.s16 q11, d19, d24 361 vaddl.u8 q7, d3, d1 362 vst1.32 {q14}, [r9]! @ store row 1 to temp buffer: col 0 363 vmla.u16 q7, q10, q13 364 vqrshrun.s32 d12, q15, #10 365 vaddl.u8 q8, d5, d11 366 vqrshrun.s32 d13, q11, #10 367 vmls.u16 q7, q8, q12 368 @ vld1.32 {q1},[r0],r2 ; Vector load from src[7_0] 369 vqmovn.u16 d25, q6 370 vaddl.u8 q8, d8, d10 371 372 373 vext.16 q11, q14, q7, #5 374 vaddl.u8 q10, d4, d2 375 vaddl.s16 q15, d28, d22 376 vmla.u16 q10, q8, q13 377 vst1.32 {q7}, [r9], r7 @ store row 1 to temp buffer: col 1 378 vaddl.s16 q11, d29, d23 379 vext.16 q8, q14, q7, #2 380 vext.16 q9, q14, q7, #3 381 vext.16 q6, q14, q7, #4 382 vext.16 q7, q14, q7, #1 383 vadd.s16 q8, q8, q9 384 vadd.s16 q9, q6, q7 385 vld1.32 {q7}, [r6], r8 @ load row 0 from temp buffer 386 vmlal.s16 q15, d16, d26 387 vmlsl.s16 q15, d18, d24 388 vmlal.s16 q11, d17, d26 389 vmlsl.s16 q11, d19, d24 390 vqrshrun.s16 d14, q7, #0x5 391 vld1.32 {q14}, [r6], r8 @ load row 1 from temp buffer 392 vaddl.u8 q9, d6, d0 393 vqrshrun.s32 d16, q15, #10 394 vqrshrun.s16 d15, q14, #0x5 395 vqrshrun.s32 d17, q11, #10 396 vmov d12, d25 397 vmov d25, d24 398 399 vqmovn.u16 d13, q8 400 vrhadd.u8 q6, q6, q7 401 402 vst1.32 d12, [r1], r3 @ store row 0 403 vst1.32 d13, [r1], r3 @ store row 1 404 405 subs r4, r4, #2 406 subne r0, r0 , r2, lsl #2 407 subne r0, r0, r2 408 409 beq end_func @ Branch if height==4 410 b loop_8 @ Loop if height==8 411 412 loop_4: 413 vld1.u32 {q0}, [r0], r2 @ Vector load from src[0_0] 414 vld1.u32 {q1}, [r0], r2 @ Vector load from src[1_0] 415 vld1.u32 {q2}, [r0], r2 @ Vector load from src[2_0] 416 vld1.u32 {q3}, [r0], r2 @ Vector load from src[3_0] 417 vld1.u32 {q4}, [r0], r2 @ Vector load from src[4_0] 418 vld1.u32 {q5}, [r0], r2 @ Vector load from src[5_0] 419 420 vaddl.u8 q7, d4, d6 @ temp1 = src[2_0] + src[3_0] 421 vaddl.u8 q6, d0, d10 @ temp = src[0_0] + src[5_0] 422 vaddl.u8 q8, d2, d8 @ temp2 = src[1_0] + src[4_0] 423 vmla.u16 q6, q7, q13 @ temp += temp1 * 20 424 vaddl.u8 q9, d5, d7 @ temp1 = src[2_0] + src[3_0] 425 vaddl.u8 q7, d1, d11 @ temp = src[0_0] + src[5_0] 426 vaddl.u8 q11, d3, d9 @ temp2 = src[1_0] + src[4_0] 427 vmla.u16 q7, q9, q13 @ temp += temp1 * 20 428 vmls.u16 q6, q8, q12 @ temp -= temp2 * 5 429 vld1.32 {q0}, [r0], r2 @ Vector load from src[6_0] 430 vaddl.u8 q8, d6, d8 431 vmls.u16 q7, q11, q12 @ temp -= temp2 * 5 432 @Q6 and Q7 have filtered values 433 vaddl.u8 q14, d2, d0 434 vst1.32 {q6}, [r9]! @ store row 0 to temp buffer: col 0 435 vext.16 q11, q6, q7, #5 436 vaddl.u8 q9, d4, d10 437 vmla.u16 q14, q8, q13 438 vaddl.s16 q15, d12, d22 439 vst1.32 {q7}, [r9], r7 @ store row 0 to temp buffer: col 1 440 vaddl.s16 q11, d13, d23 441 vext.16 q8, q6, q7, #2 442 vmls.u16 q14, q9, q12 443 vext.16 q9, q6, q7, #3 444 vext.16 q10, q6, q7, #4 445 vext.16 q7, q6, q7, #1 446 vadd.s16 q8, q8, q9 447 vadd.s16 q9, q7, q10 448 vaddl.u8 q10, d7, d9 449 vmlal.s16 q15, d16, d26 450 vmlsl.s16 q15, d18, d24 451 vmlal.s16 q11, d17, d26 452 vmlsl.s16 q11, d19, d24 453 vaddl.u8 q7, d3, d1 454 vst1.32 {q14}, [r9]! @ store row 1 to temp buffer: col 0 455 vmla.u16 q7, q10, q13 456 vqrshrun.s32 d12, q15, #10 457 vaddl.u8 q8, d5, d11 458 vqrshrun.s32 d13, q11, #10 459 vmls.u16 q7, q8, q12 460 vqmovn.u16 d25, q6 461 vaddl.u8 q8, d8, d10 462 463 vext.16 q11, q14, q7, #5 464 vaddl.u8 q10, d4, d2 465 vaddl.s16 q15, d28, d22 466 vmla.u16 q10, q8, q13 467 vst1.32 {q7}, [r9], r7 @ store row 1 to temp buffer: col 1 468 vaddl.s16 q11, d29, d23 469 vext.16 q8, q14, q7, #2 470 vext.16 q9, q14, q7, #3 471 vext.16 q6, q14, q7, #4 472 vext.16 q7, q14, q7, #1 473 vadd.s16 q8, q8, q9 474 vadd.s16 q9, q6, q7 475 vld1.32 d14, [r6], r8 @load row 0 from temp buffer 476 vmlal.s16 q15, d16, d26 477 vmlsl.s16 q15, d18, d24 478 vmlal.s16 q11, d17, d26 479 vmlsl.s16 q11, d19, d24 480 vqrshrun.s16 d14, q7, #0x5 481 vld1.32 d28, [r6], r8 @load row 1 from temp buffer 482 vaddl.u8 q9, d6, d0 483 vqrshrun.s32 d16, q15, #10 484 vqrshrun.s16 d15, q14, #0x5 485 vqrshrun.s32 d17, q11, #10 486 vmov d12, d25 487 vmov d25, d24 488 489 vqmovn.u16 d13, q8 490 vrhadd.u8 q6, q6, q7 491 vst1.32 d12[0], [r1], r3 @ store row 0 492 vst1.32 d13[0], [r1], r3 @store row 1 493 494 subs r4, r4, #2 495 subne r0, r0 , r2, lsl #2 496 subne r0, r0, r2 497 498 beq end_func @ Branch if height==4 499 b loop_4 @ Loop if height==8 500 501 end_func: 502 vldmia sp!, {d8-d15} @ Restore neon registers that were saved 503 ldmfd sp!, {r4-r12, pc} @Restoring registers from stack 504 505 506