1 ; 2 ; Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3 ; 4 ; Use of this source code is governed by a BSD-style license 5 ; that can be found in the LICENSE file in the root of the source 6 ; tree. An additional intellectual property rights grant can be found 7 ; in the file PATENTS. All contributing project authors may 8 ; be found in the AUTHORS file in the root of the source tree. 9 ; 10 11 12 EXPORT |vp8_sixtap_predict8x8_neon| 13 ARM 14 REQUIRE8 15 PRESERVE8 16 17 AREA ||.text||, CODE, READONLY, ALIGN=2 18 ; r0 unsigned char *src_ptr, 19 ; r1 int src_pixels_per_line, 20 ; r2 int xoffset, 21 ; r3 int yoffset, 22 ; stack(r4) unsigned char *dst_ptr, 23 ; stack(r5) int dst_pitch 24 25 |vp8_sixtap_predict8x8_neon| PROC 26 push {r4-r5, lr} 27 28 ldr r12, _filter8_coeff_ 29 30 ldr r4, [sp, #12] ;load parameters from stack 31 ldr r5, [sp, #16] ;load parameters from stack 32 33 cmp r2, #0 ;skip first_pass filter if xoffset=0 34 beq secondpass_filter8x8_only 35 36 add r2, r12, r2, lsl #5 ;calculate filter location 37 38 cmp r3, #0 ;skip second_pass filter if yoffset=0 39 40 vld1.s32 {q14, q15}, [r2] ;load first_pass filter 41 42 beq firstpass_filter8x8_only 43 44 sub sp, sp, #64 ;reserve space on stack for temporary storage 45 mov lr, sp 46 47 vabs.s32 q12, q14 48 vabs.s32 q13, q15 49 50 mov r2, #2 ;loop counter 51 sub r0, r0, #2 ;move srcptr back to (line-2) and (column-2) 52 sub r0, r0, r1, lsl #1 53 54 vdup.8 d0, d24[0] ;first_pass filter (d0-d5) 55 vdup.8 d1, d24[4] 56 vdup.8 d2, d25[0] 57 58 ;First pass: output_height lines x output_width columns (13x8) 59 vld1.u8 {q3}, [r0], r1 ;load src data 60 vdup.8 d3, d25[4] 61 vld1.u8 {q4}, [r0], r1 62 vdup.8 d4, d26[0] 63 vld1.u8 {q5}, [r0], r1 64 vdup.8 d5, d26[4] 65 vld1.u8 {q6}, [r0], r1 66 67 filt_blk2d_fp8x8_loop_neon 68 pld [r0] 69 pld [r0, r1] 70 pld [r0, r1, lsl #1] 71 72 vmull.u8 q7, d6, d0 ;(src_ptr[-2] * vp8_filter[0]) 73 vmull.u8 q8, d8, d0 74 vmull.u8 q9, d10, d0 75 vmull.u8 q10, d12, d0 76 77 vext.8 d28, d6, d7, #1 ;construct src_ptr[-1] 78 vext.8 d29, d8, d9, #1 79 vext.8 d30, d10, d11, #1 80 vext.8 d31, d12, d13, #1 81 82 vmlsl.u8 q7, d28, d1 ;-(src_ptr[-1] * vp8_filter[1]) 83 vmlsl.u8 q8, d29, d1 84 vmlsl.u8 q9, d30, d1 85 vmlsl.u8 q10, d31, d1 86 87 vext.8 d28, d6, d7, #4 ;construct src_ptr[2] 88 vext.8 d29, d8, d9, #4 89 vext.8 d30, d10, d11, #4 90 vext.8 d31, d12, d13, #4 91 92 vmlsl.u8 q7, d28, d4 ;-(src_ptr[2] * vp8_filter[4]) 93 vmlsl.u8 q8, d29, d4 94 vmlsl.u8 q9, d30, d4 95 vmlsl.u8 q10, d31, d4 96 97 vext.8 d28, d6, d7, #2 ;construct src_ptr[0] 98 vext.8 d29, d8, d9, #2 99 vext.8 d30, d10, d11, #2 100 vext.8 d31, d12, d13, #2 101 102 vmlal.u8 q7, d28, d2 ;(src_ptr[0] * vp8_filter[2]) 103 vmlal.u8 q8, d29, d2 104 vmlal.u8 q9, d30, d2 105 vmlal.u8 q10, d31, d2 106 107 vext.8 d28, d6, d7, #5 ;construct src_ptr[3] 108 vext.8 d29, d8, d9, #5 109 vext.8 d30, d10, d11, #5 110 vext.8 d31, d12, d13, #5 111 112 vmlal.u8 q7, d28, d5 ;(src_ptr[3] * vp8_filter[5]) 113 vmlal.u8 q8, d29, d5 114 vmlal.u8 q9, d30, d5 115 vmlal.u8 q10, d31, d5 116 117 vext.8 d28, d6, d7, #3 ;construct src_ptr[1] 118 vext.8 d29, d8, d9, #3 119 vext.8 d30, d10, d11, #3 120 vext.8 d31, d12, d13, #3 121 122 vmull.u8 q3, d28, d3 ;(src_ptr[1] * vp8_filter[3]) 123 vmull.u8 q4, d29, d3 124 vmull.u8 q5, d30, d3 125 vmull.u8 q6, d31, d3 126 127 subs r2, r2, #1 128 129 vqadd.s16 q7, q3 ;sum of all (src_data*filter_parameters) 130 vqadd.s16 q8, q4 131 vqadd.s16 q9, q5 132 vqadd.s16 q10, q6 133 134 vld1.u8 {q3}, [r0], r1 ;load src data 135 136 vqrshrun.s16 d22, q7, #7 ;shift/round/saturate to u8 137 vqrshrun.s16 d23, q8, #7 138 vqrshrun.s16 d24, q9, #7 139 vqrshrun.s16 d25, q10, #7 140 141 vst1.u8 {d22}, [lr]! ;store result 142 vld1.u8 {q4}, [r0], r1 143 vst1.u8 {d23}, [lr]! 144 vld1.u8 {q5}, [r0], r1 145 vst1.u8 {d24}, [lr]! 146 vld1.u8 {q6}, [r0], r1 147 vst1.u8 {d25}, [lr]! 148 149 bne filt_blk2d_fp8x8_loop_neon 150 151 ;first_pass filtering on the rest 5-line data 152 ;vld1.u8 {q3}, [r0], r1 ;load src data 153 ;vld1.u8 {q4}, [r0], r1 154 ;vld1.u8 {q5}, [r0], r1 155 ;vld1.u8 {q6}, [r0], r1 156 vld1.u8 {q7}, [r0], r1 157 158 vmull.u8 q8, d6, d0 ;(src_ptr[-2] * vp8_filter[0]) 159 vmull.u8 q9, d8, d0 160 vmull.u8 q10, d10, d0 161 vmull.u8 q11, d12, d0 162 vmull.u8 q12, d14, d0 163 164 vext.8 d27, d6, d7, #1 ;construct src_ptr[-1] 165 vext.8 d28, d8, d9, #1 166 vext.8 d29, d10, d11, #1 167 vext.8 d30, d12, d13, #1 168 vext.8 d31, d14, d15, #1 169 170 vmlsl.u8 q8, d27, d1 ;-(src_ptr[-1] * vp8_filter[1]) 171 vmlsl.u8 q9, d28, d1 172 vmlsl.u8 q10, d29, d1 173 vmlsl.u8 q11, d30, d1 174 vmlsl.u8 q12, d31, d1 175 176 vext.8 d27, d6, d7, #4 ;construct src_ptr[2] 177 vext.8 d28, d8, d9, #4 178 vext.8 d29, d10, d11, #4 179 vext.8 d30, d12, d13, #4 180 vext.8 d31, d14, d15, #4 181 182 vmlsl.u8 q8, d27, d4 ;-(src_ptr[2] * vp8_filter[4]) 183 vmlsl.u8 q9, d28, d4 184 vmlsl.u8 q10, d29, d4 185 vmlsl.u8 q11, d30, d4 186 vmlsl.u8 q12, d31, d4 187 188 vext.8 d27, d6, d7, #2 ;construct src_ptr[0] 189 vext.8 d28, d8, d9, #2 190 vext.8 d29, d10, d11, #2 191 vext.8 d30, d12, d13, #2 192 vext.8 d31, d14, d15, #2 193 194 vmlal.u8 q8, d27, d2 ;(src_ptr[0] * vp8_filter[2]) 195 vmlal.u8 q9, d28, d2 196 vmlal.u8 q10, d29, d2 197 vmlal.u8 q11, d30, d2 198 vmlal.u8 q12, d31, d2 199 200 vext.8 d27, d6, d7, #5 ;construct src_ptr[3] 201 vext.8 d28, d8, d9, #5 202 vext.8 d29, d10, d11, #5 203 vext.8 d30, d12, d13, #5 204 vext.8 d31, d14, d15, #5 205 206 vmlal.u8 q8, d27, d5 ;(src_ptr[3] * vp8_filter[5]) 207 vmlal.u8 q9, d28, d5 208 vmlal.u8 q10, d29, d5 209 vmlal.u8 q11, d30, d5 210 vmlal.u8 q12, d31, d5 211 212 vext.8 d27, d6, d7, #3 ;construct src_ptr[1] 213 vext.8 d28, d8, d9, #3 214 vext.8 d29, d10, d11, #3 215 vext.8 d30, d12, d13, #3 216 vext.8 d31, d14, d15, #3 217 218 vmull.u8 q3, d27, d3 ;(src_ptr[1] * vp8_filter[3]) 219 vmull.u8 q4, d28, d3 220 vmull.u8 q5, d29, d3 221 vmull.u8 q6, d30, d3 222 vmull.u8 q7, d31, d3 223 224 vqadd.s16 q8, q3 ;sum of all (src_data*filter_parameters) 225 vqadd.s16 q9, q4 226 vqadd.s16 q10, q5 227 vqadd.s16 q11, q6 228 vqadd.s16 q12, q7 229 230 add r3, r12, r3, lsl #5 231 232 vqrshrun.s16 d26, q8, #7 ;shift/round/saturate to u8 233 sub lr, lr, #64 234 vqrshrun.s16 d27, q9, #7 235 vld1.u8 {q9}, [lr]! ;load intermediate data from stack 236 vqrshrun.s16 d28, q10, #7 237 vld1.u8 {q10}, [lr]! 238 239 vld1.s32 {q5, q6}, [r3] ;load second_pass filter 240 241 vqrshrun.s16 d29, q11, #7 242 vld1.u8 {q11}, [lr]! 243 244 vabs.s32 q7, q5 245 vabs.s32 q8, q6 246 247 vqrshrun.s16 d30, q12, #7 248 vld1.u8 {q12}, [lr]! 249 250 ;Second pass: 8x8 251 mov r3, #2 ;loop counter 252 253 vdup.8 d0, d14[0] ;second_pass filter parameters (d0-d5) 254 vdup.8 d1, d14[4] 255 vdup.8 d2, d15[0] 256 vdup.8 d3, d15[4] 257 vdup.8 d4, d16[0] 258 vdup.8 d5, d16[4] 259 260 filt_blk2d_sp8x8_loop_neon 261 vmull.u8 q3, d18, d0 ;(src_ptr[-2] * vp8_filter[0]) 262 vmull.u8 q4, d19, d0 263 vmull.u8 q5, d20, d0 264 vmull.u8 q6, d21, d0 265 266 vmlsl.u8 q3, d19, d1 ;-(src_ptr[-1] * vp8_filter[1]) 267 vmlsl.u8 q4, d20, d1 268 vmlsl.u8 q5, d21, d1 269 vmlsl.u8 q6, d22, d1 270 271 vmlsl.u8 q3, d22, d4 ;-(src_ptr[2] * vp8_filter[4]) 272 vmlsl.u8 q4, d23, d4 273 vmlsl.u8 q5, d24, d4 274 vmlsl.u8 q6, d25, d4 275 276 vmlal.u8 q3, d20, d2 ;(src_ptr[0] * vp8_filter[2]) 277 vmlal.u8 q4, d21, d2 278 vmlal.u8 q5, d22, d2 279 vmlal.u8 q6, d23, d2 280 281 vmlal.u8 q3, d23, d5 ;(src_ptr[3] * vp8_filter[5]) 282 vmlal.u8 q4, d24, d5 283 vmlal.u8 q5, d25, d5 284 vmlal.u8 q6, d26, d5 285 286 vmull.u8 q7, d21, d3 ;(src_ptr[1] * vp8_filter[3]) 287 vmull.u8 q8, d22, d3 288 vmull.u8 q9, d23, d3 289 vmull.u8 q10, d24, d3 290 291 subs r3, r3, #1 292 293 vqadd.s16 q7, q3 ;sum of all (src_data*filter_parameters) 294 vqadd.s16 q8, q4 295 vqadd.s16 q9, q5 296 vqadd.s16 q10, q6 297 298 vqrshrun.s16 d6, q7, #7 ;shift/round/saturate to u8 299 vqrshrun.s16 d7, q8, #7 300 vqrshrun.s16 d8, q9, #7 301 vqrshrun.s16 d9, q10, #7 302 303 vmov q9, q11 304 vst1.u8 {d6}, [r4], r5 ;store result 305 vmov q10, q12 306 vst1.u8 {d7}, [r4], r5 307 vmov q11, q13 308 vst1.u8 {d8}, [r4], r5 309 vmov q12, q14 310 vst1.u8 {d9}, [r4], r5 311 vmov d26, d30 312 313 bne filt_blk2d_sp8x8_loop_neon 314 315 add sp, sp, #64 316 pop {r4-r5,pc} 317 318 ;--------------------- 319 firstpass_filter8x8_only 320 ;add r2, r12, r2, lsl #5 ;calculate filter location 321 ;vld1.s32 {q14, q15}, [r2] ;load first_pass filter 322 vabs.s32 q12, q14 323 vabs.s32 q13, q15 324 325 mov r2, #2 ;loop counter 326 sub r0, r0, #2 ;move srcptr back to (line-2) and (column-2) 327 328 vdup.8 d0, d24[0] ;first_pass filter (d0-d5) 329 vdup.8 d1, d24[4] 330 vdup.8 d2, d25[0] 331 vdup.8 d3, d25[4] 332 vdup.8 d4, d26[0] 333 vdup.8 d5, d26[4] 334 335 ;First pass: output_height lines x output_width columns (8x8) 336 filt_blk2d_fpo8x8_loop_neon 337 vld1.u8 {q3}, [r0], r1 ;load src data 338 vld1.u8 {q4}, [r0], r1 339 vld1.u8 {q5}, [r0], r1 340 vld1.u8 {q6}, [r0], r1 341 342 pld [r0] 343 pld [r0, r1] 344 pld [r0, r1, lsl #1] 345 346 vmull.u8 q7, d6, d0 ;(src_ptr[-2] * vp8_filter[0]) 347 vmull.u8 q8, d8, d0 348 vmull.u8 q9, d10, d0 349 vmull.u8 q10, d12, d0 350 351 vext.8 d28, d6, d7, #1 ;construct src_ptr[-1] 352 vext.8 d29, d8, d9, #1 353 vext.8 d30, d10, d11, #1 354 vext.8 d31, d12, d13, #1 355 356 vmlsl.u8 q7, d28, d1 ;-(src_ptr[-1] * vp8_filter[1]) 357 vmlsl.u8 q8, d29, d1 358 vmlsl.u8 q9, d30, d1 359 vmlsl.u8 q10, d31, d1 360 361 vext.8 d28, d6, d7, #4 ;construct src_ptr[2] 362 vext.8 d29, d8, d9, #4 363 vext.8 d30, d10, d11, #4 364 vext.8 d31, d12, d13, #4 365 366 vmlsl.u8 q7, d28, d4 ;-(src_ptr[2] * vp8_filter[4]) 367 vmlsl.u8 q8, d29, d4 368 vmlsl.u8 q9, d30, d4 369 vmlsl.u8 q10, d31, d4 370 371 vext.8 d28, d6, d7, #2 ;construct src_ptr[0] 372 vext.8 d29, d8, d9, #2 373 vext.8 d30, d10, d11, #2 374 vext.8 d31, d12, d13, #2 375 376 vmlal.u8 q7, d28, d2 ;(src_ptr[0] * vp8_filter[2]) 377 vmlal.u8 q8, d29, d2 378 vmlal.u8 q9, d30, d2 379 vmlal.u8 q10, d31, d2 380 381 vext.8 d28, d6, d7, #5 ;construct src_ptr[3] 382 vext.8 d29, d8, d9, #5 383 vext.8 d30, d10, d11, #5 384 vext.8 d31, d12, d13, #5 385 386 vmlal.u8 q7, d28, d5 ;(src_ptr[3] * vp8_filter[5]) 387 vmlal.u8 q8, d29, d5 388 vmlal.u8 q9, d30, d5 389 vmlal.u8 q10, d31, d5 390 391 vext.8 d28, d6, d7, #3 ;construct src_ptr[1] 392 vext.8 d29, d8, d9, #3 393 vext.8 d30, d10, d11, #3 394 vext.8 d31, d12, d13, #3 395 396 vmull.u8 q3, d28, d3 ;(src_ptr[1] * vp8_filter[3]) 397 vmull.u8 q4, d29, d3 398 vmull.u8 q5, d30, d3 399 vmull.u8 q6, d31, d3 400 ; 401 vqadd.s16 q7, q3 ;sum of all (src_data*filter_parameters) 402 vqadd.s16 q8, q4 403 vqadd.s16 q9, q5 404 vqadd.s16 q10, q6 405 406 subs r2, r2, #1 407 408 vqrshrun.s16 d22, q7, #7 ;shift/round/saturate to u8 409 vqrshrun.s16 d23, q8, #7 410 vqrshrun.s16 d24, q9, #7 411 vqrshrun.s16 d25, q10, #7 412 413 vst1.u8 {d22}, [r4], r5 ;store result 414 vst1.u8 {d23}, [r4], r5 415 vst1.u8 {d24}, [r4], r5 416 vst1.u8 {d25}, [r4], r5 417 418 bne filt_blk2d_fpo8x8_loop_neon 419 420 pop {r4-r5,pc} 421 422 ;--------------------- 423 secondpass_filter8x8_only 424 sub r0, r0, r1, lsl #1 425 add r3, r12, r3, lsl #5 426 427 vld1.u8 {d18}, [r0], r1 ;load src data 428 vld1.s32 {q5, q6}, [r3] ;load second_pass filter 429 vld1.u8 {d19}, [r0], r1 430 vabs.s32 q7, q5 431 vld1.u8 {d20}, [r0], r1 432 vabs.s32 q8, q6 433 vld1.u8 {d21}, [r0], r1 434 mov r3, #2 ;loop counter 435 vld1.u8 {d22}, [r0], r1 436 vdup.8 d0, d14[0] ;second_pass filter parameters (d0-d5) 437 vld1.u8 {d23}, [r0], r1 438 vdup.8 d1, d14[4] 439 vld1.u8 {d24}, [r0], r1 440 vdup.8 d2, d15[0] 441 vld1.u8 {d25}, [r0], r1 442 vdup.8 d3, d15[4] 443 vld1.u8 {d26}, [r0], r1 444 vdup.8 d4, d16[0] 445 vld1.u8 {d27}, [r0], r1 446 vdup.8 d5, d16[4] 447 vld1.u8 {d28}, [r0], r1 448 vld1.u8 {d29}, [r0], r1 449 vld1.u8 {d30}, [r0], r1 450 451 ;Second pass: 8x8 452 filt_blk2d_spo8x8_loop_neon 453 vmull.u8 q3, d18, d0 ;(src_ptr[-2] * vp8_filter[0]) 454 vmull.u8 q4, d19, d0 455 vmull.u8 q5, d20, d0 456 vmull.u8 q6, d21, d0 457 458 vmlsl.u8 q3, d19, d1 ;-(src_ptr[-1] * vp8_filter[1]) 459 vmlsl.u8 q4, d20, d1 460 vmlsl.u8 q5, d21, d1 461 vmlsl.u8 q6, d22, d1 462 463 vmlsl.u8 q3, d22, d4 ;-(src_ptr[2] * vp8_filter[4]) 464 vmlsl.u8 q4, d23, d4 465 vmlsl.u8 q5, d24, d4 466 vmlsl.u8 q6, d25, d4 467 468 vmlal.u8 q3, d20, d2 ;(src_ptr[0] * vp8_filter[2]) 469 vmlal.u8 q4, d21, d2 470 vmlal.u8 q5, d22, d2 471 vmlal.u8 q6, d23, d2 472 473 vmlal.u8 q3, d23, d5 ;(src_ptr[3] * vp8_filter[5]) 474 vmlal.u8 q4, d24, d5 475 vmlal.u8 q5, d25, d5 476 vmlal.u8 q6, d26, d5 477 478 vmull.u8 q7, d21, d3 ;(src_ptr[1] * vp8_filter[3]) 479 vmull.u8 q8, d22, d3 480 vmull.u8 q9, d23, d3 481 vmull.u8 q10, d24, d3 482 483 subs r3, r3, #1 484 485 vqadd.s16 q7, q3 ;sum of all (src_data*filter_parameters) 486 vqadd.s16 q8, q4 487 vqadd.s16 q9, q5 488 vqadd.s16 q10, q6 489 490 vqrshrun.s16 d6, q7, #7 ;shift/round/saturate to u8 491 vqrshrun.s16 d7, q8, #7 492 vqrshrun.s16 d8, q9, #7 493 vqrshrun.s16 d9, q10, #7 494 495 vmov q9, q11 496 vst1.u8 {d6}, [r4], r5 ;store result 497 vmov q10, q12 498 vst1.u8 {d7}, [r4], r5 499 vmov q11, q13 500 vst1.u8 {d8}, [r4], r5 501 vmov q12, q14 502 vst1.u8 {d9}, [r4], r5 503 vmov d26, d30 504 505 bne filt_blk2d_spo8x8_loop_neon 506 507 pop {r4-r5,pc} 508 509 ENDP 510 511 ;----------------- 512 AREA subpelfilters8_dat, DATA, READWRITE ;read/write by default 513 ;Data section with name data_area is specified. DCD reserves space in memory for 48 data. 514 ;One word each is reserved. Label filter_coeff can be used to access the data. 515 ;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ... 516 _filter8_coeff_ 517 DCD filter8_coeff 518 filter8_coeff 519 DCD 0, 0, 128, 0, 0, 0, 0, 0 520 DCD 0, -6, 123, 12, -1, 0, 0, 0 521 DCD 2, -11, 108, 36, -8, 1, 0, 0 522 DCD 0, -9, 93, 50, -6, 0, 0, 0 523 DCD 3, -16, 77, 77, -16, 3, 0, 0 524 DCD 0, -6, 50, 93, -9, 0, 0, 0 525 DCD 1, -8, 36, 108, -11, 2, 0, 0 526 DCD 0, -1, 12, 123, -6, 0, 0, 0 527 528 END 529