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_sub_pixel_variance16x16_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_pixels_per_line, 24 ; stack(r6) unsigned int *sse 25 ;note: most of the code is copied from bilinear_predict16x16_neon and vp8_variance16x16_neon. 26 27 |vp8_sub_pixel_variance16x16_neon| PROC 28 push {r4-r6, lr} 29 30 ldr r12, _BilinearTaps_coeff_ 31 ldr r4, [sp, #16] ;load *dst_ptr from stack 32 ldr r5, [sp, #20] ;load dst_pixels_per_line from stack 33 ldr r6, [sp, #24] ;load *sse from stack 34 35 cmp r2, #0 ;skip first_pass filter if xoffset=0 36 beq secondpass_bfilter16x16_only 37 38 add r2, r12, r2, lsl #3 ;calculate filter location 39 40 cmp r3, #0 ;skip second_pass filter if yoffset=0 41 42 vld1.s32 {d31}, [r2] ;load first_pass filter 43 44 beq firstpass_bfilter16x16_only 45 46 sub sp, sp, #272 ;reserve space on stack for temporary storage 47 vld1.u8 {d2, d3, d4}, [r0], r1 ;load src data 48 mov lr, sp 49 vld1.u8 {d5, d6, d7}, [r0], r1 50 51 mov r2, #3 ;loop counter 52 vld1.u8 {d8, d9, d10}, [r0], r1 53 54 vdup.8 d0, d31[0] ;first_pass filter (d0 d1) 55 vld1.u8 {d11, d12, d13}, [r0], r1 56 57 vdup.8 d1, d31[4] 58 59 ;First Pass: output_height lines x output_width columns (17x16) 60 vp8e_filt_blk2d_fp16x16_loop_neon 61 pld [r0] 62 pld [r0, r1] 63 pld [r0, r1, lsl #1] 64 65 vmull.u8 q7, d2, d0 ;(src_ptr[0] * Filter[0]) 66 vmull.u8 q8, d3, d0 67 vmull.u8 q9, d5, d0 68 vmull.u8 q10, d6, d0 69 vmull.u8 q11, d8, d0 70 vmull.u8 q12, d9, d0 71 vmull.u8 q13, d11, d0 72 vmull.u8 q14, d12, d0 73 74 vext.8 d2, d2, d3, #1 ;construct src_ptr[1] 75 vext.8 d5, d5, d6, #1 76 vext.8 d8, d8, d9, #1 77 vext.8 d11, d11, d12, #1 78 79 vmlal.u8 q7, d2, d1 ;(src_ptr[0] * Filter[1]) 80 vmlal.u8 q9, d5, d1 81 vmlal.u8 q11, d8, d1 82 vmlal.u8 q13, d11, d1 83 84 vext.8 d3, d3, d4, #1 85 vext.8 d6, d6, d7, #1 86 vext.8 d9, d9, d10, #1 87 vext.8 d12, d12, d13, #1 88 89 vmlal.u8 q8, d3, d1 ;(src_ptr[0] * Filter[1]) 90 vmlal.u8 q10, d6, d1 91 vmlal.u8 q12, d9, d1 92 vmlal.u8 q14, d12, d1 93 94 subs r2, r2, #1 95 96 vqrshrn.u16 d14, q7, #7 ;shift/round/saturate to u8 97 vqrshrn.u16 d15, q8, #7 98 vqrshrn.u16 d16, q9, #7 99 vqrshrn.u16 d17, q10, #7 100 vqrshrn.u16 d18, q11, #7 101 vqrshrn.u16 d19, q12, #7 102 vqrshrn.u16 d20, q13, #7 103 104 vld1.u8 {d2, d3, d4}, [r0], r1 ;load src data 105 vqrshrn.u16 d21, q14, #7 106 vld1.u8 {d5, d6, d7}, [r0], r1 107 108 vst1.u8 {d14, d15, d16, d17}, [lr]! ;store result 109 vld1.u8 {d8, d9, d10}, [r0], r1 110 vst1.u8 {d18, d19, d20, d21}, [lr]! 111 vld1.u8 {d11, d12, d13}, [r0], r1 112 113 bne vp8e_filt_blk2d_fp16x16_loop_neon 114 115 ;First-pass filtering for rest 5 lines 116 vld1.u8 {d14, d15, d16}, [r0], r1 117 118 vmull.u8 q9, d2, d0 ;(src_ptr[0] * Filter[0]) 119 vmull.u8 q10, d3, d0 120 vmull.u8 q11, d5, d0 121 vmull.u8 q12, d6, d0 122 vmull.u8 q13, d8, d0 123 vmull.u8 q14, d9, d0 124 125 vext.8 d2, d2, d3, #1 ;construct src_ptr[1] 126 vext.8 d5, d5, d6, #1 127 vext.8 d8, d8, d9, #1 128 129 vmlal.u8 q9, d2, d1 ;(src_ptr[0] * Filter[1]) 130 vmlal.u8 q11, d5, d1 131 vmlal.u8 q13, d8, d1 132 133 vext.8 d3, d3, d4, #1 134 vext.8 d6, d6, d7, #1 135 vext.8 d9, d9, d10, #1 136 137 vmlal.u8 q10, d3, d1 ;(src_ptr[0] * Filter[1]) 138 vmlal.u8 q12, d6, d1 139 vmlal.u8 q14, d9, d1 140 141 vmull.u8 q1, d11, d0 142 vmull.u8 q2, d12, d0 143 vmull.u8 q3, d14, d0 144 vmull.u8 q4, d15, d0 145 146 vext.8 d11, d11, d12, #1 ;construct src_ptr[1] 147 vext.8 d14, d14, d15, #1 148 149 vmlal.u8 q1, d11, d1 ;(src_ptr[0] * Filter[1]) 150 vmlal.u8 q3, d14, d1 151 152 vext.8 d12, d12, d13, #1 153 vext.8 d15, d15, d16, #1 154 155 vmlal.u8 q2, d12, d1 ;(src_ptr[0] * Filter[1]) 156 vmlal.u8 q4, d15, d1 157 158 vqrshrn.u16 d10, q9, #7 ;shift/round/saturate to u8 159 vqrshrn.u16 d11, q10, #7 160 vqrshrn.u16 d12, q11, #7 161 vqrshrn.u16 d13, q12, #7 162 vqrshrn.u16 d14, q13, #7 163 vqrshrn.u16 d15, q14, #7 164 vqrshrn.u16 d16, q1, #7 165 vqrshrn.u16 d17, q2, #7 166 vqrshrn.u16 d18, q3, #7 167 vqrshrn.u16 d19, q4, #7 168 169 vst1.u8 {d10, d11, d12, d13}, [lr]! ;store result 170 vst1.u8 {d14, d15, d16, d17}, [lr]! 171 vst1.u8 {d18, d19}, [lr]! 172 173 ;Second pass: 16x16 174 ;secondpass_filter 175 add r3, r12, r3, lsl #3 176 sub lr, lr, #272 177 178 vld1.u32 {d31}, [r3] ;load second_pass filter 179 180 sub sp, sp, #256 181 mov r3, sp 182 183 vld1.u8 {d22, d23}, [lr]! ;load src data 184 185 vdup.8 d0, d31[0] ;second_pass filter parameters (d0 d1) 186 vdup.8 d1, d31[4] 187 mov r12, #4 ;loop counter 188 189 vp8e_filt_blk2d_sp16x16_loop_neon 190 vld1.u8 {d24, d25}, [lr]! 191 vmull.u8 q1, d22, d0 ;(src_ptr[0] * Filter[0]) 192 vld1.u8 {d26, d27}, [lr]! 193 vmull.u8 q2, d23, d0 194 vld1.u8 {d28, d29}, [lr]! 195 vmull.u8 q3, d24, d0 196 vld1.u8 {d30, d31}, [lr]! 197 198 vmull.u8 q4, d25, d0 199 vmull.u8 q5, d26, d0 200 vmull.u8 q6, d27, d0 201 vmull.u8 q7, d28, d0 202 vmull.u8 q8, d29, d0 203 204 vmlal.u8 q1, d24, d1 ;(src_ptr[pixel_step] * Filter[1]) 205 vmlal.u8 q2, d25, d1 206 vmlal.u8 q3, d26, d1 207 vmlal.u8 q4, d27, d1 208 vmlal.u8 q5, d28, d1 209 vmlal.u8 q6, d29, d1 210 vmlal.u8 q7, d30, d1 211 vmlal.u8 q8, d31, d1 212 213 subs r12, r12, #1 214 215 vqrshrn.u16 d2, q1, #7 ;shift/round/saturate to u8 216 vqrshrn.u16 d3, q2, #7 217 vqrshrn.u16 d4, q3, #7 218 vqrshrn.u16 d5, q4, #7 219 vqrshrn.u16 d6, q5, #7 220 vqrshrn.u16 d7, q6, #7 221 vqrshrn.u16 d8, q7, #7 222 vqrshrn.u16 d9, q8, #7 223 224 vst1.u8 {d2, d3}, [r3]! ;store result 225 vst1.u8 {d4, d5}, [r3]! 226 vst1.u8 {d6, d7}, [r3]! 227 vmov q11, q15 228 vst1.u8 {d8, d9}, [r3]! 229 230 bne vp8e_filt_blk2d_sp16x16_loop_neon 231 232 b sub_pixel_variance16x16_neon 233 234 ;-------------------- 235 firstpass_bfilter16x16_only 236 mov r2, #4 ;loop counter 237 sub sp, sp, #528 ;reserve space on stack for temporary storage 238 vdup.8 d0, d31[0] ;first_pass filter (d0 d1) 239 vdup.8 d1, d31[4] 240 mov r3, sp 241 242 ;First Pass: output_height lines x output_width columns (16x16) 243 vp8e_filt_blk2d_fpo16x16_loop_neon 244 vld1.u8 {d2, d3, d4}, [r0], r1 ;load src data 245 vld1.u8 {d5, d6, d7}, [r0], r1 246 vld1.u8 {d8, d9, d10}, [r0], r1 247 vld1.u8 {d11, d12, d13}, [r0], r1 248 249 pld [r0] 250 pld [r0, r1] 251 pld [r0, r1, lsl #1] 252 253 vmull.u8 q7, d2, d0 ;(src_ptr[0] * Filter[0]) 254 vmull.u8 q8, d3, d0 255 vmull.u8 q9, d5, d0 256 vmull.u8 q10, d6, d0 257 vmull.u8 q11, d8, d0 258 vmull.u8 q12, d9, d0 259 vmull.u8 q13, d11, d0 260 vmull.u8 q14, d12, d0 261 262 vext.8 d2, d2, d3, #1 ;construct src_ptr[1] 263 vext.8 d5, d5, d6, #1 264 vext.8 d8, d8, d9, #1 265 vext.8 d11, d11, d12, #1 266 267 vmlal.u8 q7, d2, d1 ;(src_ptr[0] * Filter[1]) 268 vmlal.u8 q9, d5, d1 269 vmlal.u8 q11, d8, d1 270 vmlal.u8 q13, d11, d1 271 272 vext.8 d3, d3, d4, #1 273 vext.8 d6, d6, d7, #1 274 vext.8 d9, d9, d10, #1 275 vext.8 d12, d12, d13, #1 276 277 vmlal.u8 q8, d3, d1 ;(src_ptr[0] * Filter[1]) 278 vmlal.u8 q10, d6, d1 279 vmlal.u8 q12, d9, d1 280 vmlal.u8 q14, d12, d1 281 282 subs r2, r2, #1 283 284 vqrshrn.u16 d14, q7, #7 ;shift/round/saturate to u8 285 vqrshrn.u16 d15, q8, #7 286 vqrshrn.u16 d16, q9, #7 287 vqrshrn.u16 d17, q10, #7 288 vqrshrn.u16 d18, q11, #7 289 vqrshrn.u16 d19, q12, #7 290 vqrshrn.u16 d20, q13, #7 291 vst1.u8 {d14, d15}, [r3]! ;store result 292 vqrshrn.u16 d21, q14, #7 293 294 vst1.u8 {d16, d17}, [r3]! 295 vst1.u8 {d18, d19}, [r3]! 296 vst1.u8 {d20, d21}, [r3]! 297 298 bne vp8e_filt_blk2d_fpo16x16_loop_neon 299 300 b sub_pixel_variance16x16_neon 301 302 ;--------------------- 303 secondpass_bfilter16x16_only 304 ;Second pass: 16x16 305 ;secondpass_filter 306 sub sp, sp, #528 ;reserve space on stack for temporary storage 307 add r3, r12, r3, lsl #3 308 mov r12, #4 ;loop counter 309 vld1.u32 {d31}, [r3] ;load second_pass filter 310 vld1.u8 {d22, d23}, [r0], r1 ;load src data 311 mov r3, sp 312 313 vdup.8 d0, d31[0] ;second_pass filter parameters (d0 d1) 314 vdup.8 d1, d31[4] 315 316 vp8e_filt_blk2d_spo16x16_loop_neon 317 vld1.u8 {d24, d25}, [r0], r1 318 vmull.u8 q1, d22, d0 ;(src_ptr[0] * Filter[0]) 319 vld1.u8 {d26, d27}, [r0], r1 320 vmull.u8 q2, d23, d0 321 vld1.u8 {d28, d29}, [r0], r1 322 vmull.u8 q3, d24, d0 323 vld1.u8 {d30, d31}, [r0], r1 324 325 vmull.u8 q4, d25, d0 326 vmull.u8 q5, d26, d0 327 vmull.u8 q6, d27, d0 328 vmull.u8 q7, d28, d0 329 vmull.u8 q8, d29, d0 330 331 vmlal.u8 q1, d24, d1 ;(src_ptr[pixel_step] * Filter[1]) 332 vmlal.u8 q2, d25, d1 333 vmlal.u8 q3, d26, d1 334 vmlal.u8 q4, d27, d1 335 vmlal.u8 q5, d28, d1 336 vmlal.u8 q6, d29, d1 337 vmlal.u8 q7, d30, d1 338 vmlal.u8 q8, d31, d1 339 340 vqrshrn.u16 d2, q1, #7 ;shift/round/saturate to u8 341 vqrshrn.u16 d3, q2, #7 342 vqrshrn.u16 d4, q3, #7 343 vqrshrn.u16 d5, q4, #7 344 vqrshrn.u16 d6, q5, #7 345 vqrshrn.u16 d7, q6, #7 346 vqrshrn.u16 d8, q7, #7 347 vqrshrn.u16 d9, q8, #7 348 349 vst1.u8 {d2, d3}, [r3]! ;store result 350 subs r12, r12, #1 351 vst1.u8 {d4, d5}, [r3]! 352 vmov q11, q15 353 vst1.u8 {d6, d7}, [r3]! 354 vst1.u8 {d8, d9}, [r3]! 355 356 bne vp8e_filt_blk2d_spo16x16_loop_neon 357 358 b sub_pixel_variance16x16_neon 359 360 ;---------------------------- 361 ;variance16x16 362 sub_pixel_variance16x16_neon 363 vmov.i8 q8, #0 ;q8 - sum 364 vmov.i8 q9, #0 ;q9, q10 - sse 365 vmov.i8 q10, #0 366 367 sub r3, r3, #256 368 mov r12, #8 369 370 sub_pixel_variance16x16_neon_loop 371 vld1.8 {q0}, [r3]! ;Load up source and reference 372 vld1.8 {q2}, [r4], r5 373 vld1.8 {q1}, [r3]! 374 vld1.8 {q3}, [r4], r5 375 376 vsubl.u8 q11, d0, d4 ;diff 377 vsubl.u8 q12, d1, d5 378 vsubl.u8 q13, d2, d6 379 vsubl.u8 q14, d3, d7 380 381 vpadal.s16 q8, q11 ;sum 382 vmlal.s16 q9, d22, d22 ;sse 383 vmlal.s16 q10, d23, d23 384 385 subs r12, r12, #1 386 387 vpadal.s16 q8, q12 388 vmlal.s16 q9, d24, d24 389 vmlal.s16 q10, d25, d25 390 vpadal.s16 q8, q13 391 vmlal.s16 q9, d26, d26 392 vmlal.s16 q10, d27, d27 393 vpadal.s16 q8, q14 394 vmlal.s16 q9, d28, d28 395 vmlal.s16 q10, d29, d29 396 397 bne sub_pixel_variance16x16_neon_loop 398 399 vadd.u32 q10, q9, q10 ;accumulate sse 400 vpaddl.s32 q0, q8 ;accumulate sum 401 402 vpaddl.u32 q1, q10 403 vadd.s64 d0, d0, d1 404 vadd.u64 d1, d2, d3 405 406 vmull.s32 q5, d0, d0 407 vst1.32 {d1[0]}, [r6] ;store sse 408 vshr.s32 d10, d10, #8 409 vsub.s32 d0, d1, d10 410 411 add sp, sp, #528 412 vmov.32 r0, d0[0] ;return 413 414 pop {r4-r6,pc} 415 416 ENDP 417 418 ;----------------- 419 AREA vp8e_bilinear_taps_dat, DATA, READWRITE ;read/write by default 420 ;Data section with name data_area is specified. DCD reserves space in memory for 48 data. 421 ;One word each is reserved. Label filter_coeff can be used to access the data. 422 ;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ... 423 _BilinearTaps_coeff_ 424 DCD bilinear_taps_coeff 425 bilinear_taps_coeff 426 DCD 128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112 427 428 END 429