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