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_mbloop_filter_horizontal_edge_y_neon| 13 EXPORT |vp8_mbloop_filter_horizontal_edge_uv_neon| 14 EXPORT |vp8_mbloop_filter_vertical_edge_y_neon| 15 EXPORT |vp8_mbloop_filter_vertical_edge_uv_neon| 16 ARM 17 18 AREA ||.text||, CODE, READONLY, ALIGN=2 19 20; void vp8_mbloop_filter_horizontal_edge_y_neon(unsigned char *src, int pitch, 21; const unsigned char *blimit, 22; const unsigned char *limit, 23; const unsigned char *thresh) 24; r0 unsigned char *src, 25; r1 int pitch, 26; r2 unsigned char blimit 27; r3 unsigned char limit 28; sp unsigned char thresh, 29|vp8_mbloop_filter_horizontal_edge_y_neon| PROC 30 push {lr} 31 add r1, r1, r1 ; double stride 32 ldr r12, [sp, #4] ; load thresh 33 sub r0, r0, r1, lsl #1 ; move src pointer down by 4 lines 34 vdup.u8 q2, r12 ; thresh 35 add r12, r0, r1, lsr #1 ; move src pointer up by 1 line 36 37 vld1.u8 {q3}, [r0@128], r1 ; p3 38 vld1.u8 {q4}, [r12@128], r1 ; p2 39 vld1.u8 {q5}, [r0@128], r1 ; p1 40 vld1.u8 {q6}, [r12@128], r1 ; p0 41 vld1.u8 {q7}, [r0@128], r1 ; q0 42 vld1.u8 {q8}, [r12@128], r1 ; q1 43 vld1.u8 {q9}, [r0@128], r1 ; q2 44 vld1.u8 {q10}, [r12@128], r1 ; q3 45 46 bl vp8_mbloop_filter_neon 47 48 sub r12, r12, r1, lsl #2 49 add r0, r12, r1, lsr #1 50 51 vst1.u8 {q4}, [r12@128],r1 ; store op2 52 vst1.u8 {q5}, [r0@128],r1 ; store op1 53 vst1.u8 {q6}, [r12@128], r1 ; store op0 54 vst1.u8 {q7}, [r0@128],r1 ; store oq0 55 vst1.u8 {q8}, [r12@128] ; store oq1 56 vst1.u8 {q9}, [r0@128] ; store oq2 57 58 pop {pc} 59 ENDP ; |vp8_mbloop_filter_horizontal_edge_y_neon| 60 61; void vp8_mbloop_filter_horizontal_edge_uv_neon(unsigned char *u, int pitch, 62; const unsigned char *blimit, 63; const unsigned char *limit, 64; const unsigned char *thresh, 65; unsigned char *v) 66; r0 unsigned char *u, 67; r1 int pitch, 68; r2 unsigned char blimit 69; r3 unsigned char limit 70; sp unsigned char thresh, 71; sp+4 unsigned char *v 72 73|vp8_mbloop_filter_horizontal_edge_uv_neon| PROC 74 push {lr} 75 ldr r12, [sp, #4] ; load thresh 76 sub r0, r0, r1, lsl #2 ; move u pointer down by 4 lines 77 vdup.u8 q2, r12 ; thresh 78 ldr r12, [sp, #8] ; load v ptr 79 sub r12, r12, r1, lsl #2 ; move v pointer down by 4 lines 80 81 vld1.u8 {d6}, [r0@64], r1 ; p3 82 vld1.u8 {d7}, [r12@64], r1 ; p3 83 vld1.u8 {d8}, [r0@64], r1 ; p2 84 vld1.u8 {d9}, [r12@64], r1 ; p2 85 vld1.u8 {d10}, [r0@64], r1 ; p1 86 vld1.u8 {d11}, [r12@64], r1 ; p1 87 vld1.u8 {d12}, [r0@64], r1 ; p0 88 vld1.u8 {d13}, [r12@64], r1 ; p0 89 vld1.u8 {d14}, [r0@64], r1 ; q0 90 vld1.u8 {d15}, [r12@64], r1 ; q0 91 vld1.u8 {d16}, [r0@64], r1 ; q1 92 vld1.u8 {d17}, [r12@64], r1 ; q1 93 vld1.u8 {d18}, [r0@64], r1 ; q2 94 vld1.u8 {d19}, [r12@64], r1 ; q2 95 vld1.u8 {d20}, [r0@64], r1 ; q3 96 vld1.u8 {d21}, [r12@64], r1 ; q3 97 98 bl vp8_mbloop_filter_neon 99 100 sub r0, r0, r1, lsl #3 101 sub r12, r12, r1, lsl #3 102 103 add r0, r0, r1 104 add r12, r12, r1 105 106 vst1.u8 {d8}, [r0@64], r1 ; store u op2 107 vst1.u8 {d9}, [r12@64], r1 ; store v op2 108 vst1.u8 {d10}, [r0@64], r1 ; store u op1 109 vst1.u8 {d11}, [r12@64], r1 ; store v op1 110 vst1.u8 {d12}, [r0@64], r1 ; store u op0 111 vst1.u8 {d13}, [r12@64], r1 ; store v op0 112 vst1.u8 {d14}, [r0@64], r1 ; store u oq0 113 vst1.u8 {d15}, [r12@64], r1 ; store v oq0 114 vst1.u8 {d16}, [r0@64], r1 ; store u oq1 115 vst1.u8 {d17}, [r12@64], r1 ; store v oq1 116 vst1.u8 {d18}, [r0@64], r1 ; store u oq2 117 vst1.u8 {d19}, [r12@64], r1 ; store v oq2 118 119 pop {pc} 120 ENDP ; |vp8_mbloop_filter_horizontal_edge_uv_neon| 121 122; void vp8_mbloop_filter_vertical_edge_y_neon(unsigned char *src, int pitch, 123; const unsigned char *blimit, 124; const unsigned char *limit, 125; const unsigned char *thresh) 126; r0 unsigned char *src, 127; r1 int pitch, 128; r2 unsigned char blimit 129; r3 unsigned char limit 130; sp unsigned char thresh, 131|vp8_mbloop_filter_vertical_edge_y_neon| PROC 132 push {lr} 133 ldr r12, [sp, #4] ; load thresh 134 sub r0, r0, #4 ; move src pointer down by 4 columns 135 vdup.s8 q2, r12 ; thresh 136 add r12, r0, r1, lsl #3 ; move src pointer down by 8 lines 137 138 vld1.u8 {d6}, [r0], r1 ; load first 8-line src data 139 vld1.u8 {d7}, [r12], r1 ; load second 8-line src data 140 vld1.u8 {d8}, [r0], r1 141 vld1.u8 {d9}, [r12], r1 142 vld1.u8 {d10}, [r0], r1 143 vld1.u8 {d11}, [r12], r1 144 vld1.u8 {d12}, [r0], r1 145 vld1.u8 {d13}, [r12], r1 146 vld1.u8 {d14}, [r0], r1 147 vld1.u8 {d15}, [r12], r1 148 vld1.u8 {d16}, [r0], r1 149 vld1.u8 {d17}, [r12], r1 150 vld1.u8 {d18}, [r0], r1 151 vld1.u8 {d19}, [r12], r1 152 vld1.u8 {d20}, [r0], r1 153 vld1.u8 {d21}, [r12], r1 154 155 ;transpose to 8x16 matrix 156 vtrn.32 q3, q7 157 vtrn.32 q4, q8 158 vtrn.32 q5, q9 159 vtrn.32 q6, q10 160 161 vtrn.16 q3, q5 162 vtrn.16 q4, q6 163 vtrn.16 q7, q9 164 vtrn.16 q8, q10 165 166 vtrn.8 q3, q4 167 vtrn.8 q5, q6 168 vtrn.8 q7, q8 169 vtrn.8 q9, q10 170 171 sub r0, r0, r1, lsl #3 172 173 bl vp8_mbloop_filter_neon 174 175 sub r12, r12, r1, lsl #3 176 177 ;transpose to 16x8 matrix 178 vtrn.32 q3, q7 179 vtrn.32 q4, q8 180 vtrn.32 q5, q9 181 vtrn.32 q6, q10 182 183 vtrn.16 q3, q5 184 vtrn.16 q4, q6 185 vtrn.16 q7, q9 186 vtrn.16 q8, q10 187 188 vtrn.8 q3, q4 189 vtrn.8 q5, q6 190 vtrn.8 q7, q8 191 vtrn.8 q9, q10 192 193 ;store op2, op1, op0, oq0, oq1, oq2 194 vst1.8 {d6}, [r0], r1 195 vst1.8 {d7}, [r12], r1 196 vst1.8 {d8}, [r0], r1 197 vst1.8 {d9}, [r12], r1 198 vst1.8 {d10}, [r0], r1 199 vst1.8 {d11}, [r12], r1 200 vst1.8 {d12}, [r0], r1 201 vst1.8 {d13}, [r12], r1 202 vst1.8 {d14}, [r0], r1 203 vst1.8 {d15}, [r12], r1 204 vst1.8 {d16}, [r0], r1 205 vst1.8 {d17}, [r12], r1 206 vst1.8 {d18}, [r0], r1 207 vst1.8 {d19}, [r12], r1 208 vst1.8 {d20}, [r0] 209 vst1.8 {d21}, [r12] 210 211 pop {pc} 212 ENDP ; |vp8_mbloop_filter_vertical_edge_y_neon| 213 214; void vp8_mbloop_filter_vertical_edge_uv_neon(unsigned char *u, int pitch, 215; const unsigned char *blimit, 216; const unsigned char *limit, 217; const unsigned char *thresh, 218; unsigned char *v) 219; r0 unsigned char *u, 220; r1 int pitch, 221; r2 const signed char *flimit, 222; r3 const signed char *limit, 223; sp const signed char *thresh, 224; sp+4 unsigned char *v 225|vp8_mbloop_filter_vertical_edge_uv_neon| PROC 226 push {lr} 227 ldr r12, [sp, #4] ; load thresh 228 sub r0, r0, #4 ; move u pointer down by 4 columns 229 vdup.u8 q2, r12 ; thresh 230 ldr r12, [sp, #8] ; load v ptr 231 sub r12, r12, #4 ; move v pointer down by 4 columns 232 233 vld1.u8 {d6}, [r0], r1 ;load u data 234 vld1.u8 {d7}, [r12], r1 ;load v data 235 vld1.u8 {d8}, [r0], r1 236 vld1.u8 {d9}, [r12], r1 237 vld1.u8 {d10}, [r0], r1 238 vld1.u8 {d11}, [r12], r1 239 vld1.u8 {d12}, [r0], r1 240 vld1.u8 {d13}, [r12], r1 241 vld1.u8 {d14}, [r0], r1 242 vld1.u8 {d15}, [r12], r1 243 vld1.u8 {d16}, [r0], r1 244 vld1.u8 {d17}, [r12], r1 245 vld1.u8 {d18}, [r0], r1 246 vld1.u8 {d19}, [r12], r1 247 vld1.u8 {d20}, [r0], r1 248 vld1.u8 {d21}, [r12], r1 249 250 ;transpose to 8x16 matrix 251 vtrn.32 q3, q7 252 vtrn.32 q4, q8 253 vtrn.32 q5, q9 254 vtrn.32 q6, q10 255 256 vtrn.16 q3, q5 257 vtrn.16 q4, q6 258 vtrn.16 q7, q9 259 vtrn.16 q8, q10 260 261 vtrn.8 q3, q4 262 vtrn.8 q5, q6 263 vtrn.8 q7, q8 264 vtrn.8 q9, q10 265 266 sub r0, r0, r1, lsl #3 267 268 bl vp8_mbloop_filter_neon 269 270 sub r12, r12, r1, lsl #3 271 272 ;transpose to 16x8 matrix 273 vtrn.32 q3, q7 274 vtrn.32 q4, q8 275 vtrn.32 q5, q9 276 vtrn.32 q6, q10 277 278 vtrn.16 q3, q5 279 vtrn.16 q4, q6 280 vtrn.16 q7, q9 281 vtrn.16 q8, q10 282 283 vtrn.8 q3, q4 284 vtrn.8 q5, q6 285 vtrn.8 q7, q8 286 vtrn.8 q9, q10 287 288 ;store op2, op1, op0, oq0, oq1, oq2 289 vst1.8 {d6}, [r0], r1 290 vst1.8 {d7}, [r12], r1 291 vst1.8 {d8}, [r0], r1 292 vst1.8 {d9}, [r12], r1 293 vst1.8 {d10}, [r0], r1 294 vst1.8 {d11}, [r12], r1 295 vst1.8 {d12}, [r0], r1 296 vst1.8 {d13}, [r12], r1 297 vst1.8 {d14}, [r0], r1 298 vst1.8 {d15}, [r12], r1 299 vst1.8 {d16}, [r0], r1 300 vst1.8 {d17}, [r12], r1 301 vst1.8 {d18}, [r0], r1 302 vst1.8 {d19}, [r12], r1 303 vst1.8 {d20}, [r0] 304 vst1.8 {d21}, [r12] 305 306 pop {pc} 307 ENDP ; |vp8_mbloop_filter_vertical_edge_uv_neon| 308 309; void vp8_mbloop_filter_neon() 310; This is a helper function for the macroblock loopfilters. The individual 311; functions do the necessary load, transpose (if necessary), preserve (if 312; necessary) and store. 313 314; r0,r1 PRESERVE 315; r2 mblimit 316; r3 limit 317 318; q2 thresh 319; q3 p3 PRESERVE 320; q4 p2 321; q5 p1 322; q6 p0 323; q7 q0 324; q8 q1 325; q9 q2 326; q10 q3 PRESERVE 327 328|vp8_mbloop_filter_neon| PROC 329 330 ; vp8_filter_mask 331 vabd.u8 q11, q3, q4 ; abs(p3 - p2) 332 vabd.u8 q12, q4, q5 ; abs(p2 - p1) 333 vabd.u8 q13, q5, q6 ; abs(p1 - p0) 334 vabd.u8 q14, q8, q7 ; abs(q1 - q0) 335 vabd.u8 q1, q9, q8 ; abs(q2 - q1) 336 vabd.u8 q0, q10, q9 ; abs(q3 - q2) 337 338 vmax.u8 q11, q11, q12 339 vmax.u8 q12, q13, q14 340 vmax.u8 q1, q1, q0 341 vmax.u8 q15, q11, q12 342 343 vabd.u8 q12, q6, q7 ; abs(p0 - q0) 344 345 ; vp8_hevmask 346 vcgt.u8 q13, q13, q2 ; (abs(p1 - p0) > thresh) * -1 347 vcgt.u8 q14, q14, q2 ; (abs(q1 - q0) > thresh) * -1 348 vmax.u8 q15, q15, q1 349 350 vdup.u8 q1, r3 ; limit 351 vdup.u8 q2, r2 ; mblimit 352 353 vmov.u8 q0, #0x80 ; 0x80 354 355 vcge.u8 q15, q1, q15 356 357 vabd.u8 q1, q5, q8 ; a = abs(p1 - q1) 358 vqadd.u8 q12, q12, q12 ; b = abs(p0 - q0) * 2 359 vmov.u16 q11, #3 ; #3 360 361 ; vp8_filter 362 ; convert to signed 363 veor q7, q7, q0 ; qs0 364 vshr.u8 q1, q1, #1 ; a = a / 2 365 veor q6, q6, q0 ; ps0 366 veor q5, q5, q0 ; ps1 367 368 vqadd.u8 q12, q12, q1 ; a = b + a 369 370 veor q8, q8, q0 ; qs1 371 veor q4, q4, q0 ; ps2 372 veor q9, q9, q0 ; qs2 373 374 vorr q14, q13, q14 ; vp8_hevmask 375 376 vcge.u8 q12, q2, q12 ; (a > flimit * 2 + limit) * -1 377 378 vsubl.s8 q2, d14, d12 ; qs0 - ps0 379 vsubl.s8 q13, d15, d13 380 381 vqsub.s8 q1, q5, q8 ; vp8_filter = clamp(ps1-qs1) 382 383 vmul.i16 q2, q2, q11 ; 3 * ( qs0 - ps0) 384 385 vand q15, q15, q12 ; vp8_filter_mask 386 387 vmul.i16 q13, q13, q11 388 389 vmov.u8 q12, #3 ; #3 390 391 vaddw.s8 q2, q2, d2 ; vp8_filter + 3 * ( qs0 - ps0) 392 vaddw.s8 q13, q13, d3 393 394 vmov.u8 q11, #4 ; #4 395 396 ; vp8_filter = clamp(vp8_filter + 3 * ( qs0 - ps0)) 397 vqmovn.s16 d2, q2 398 vqmovn.s16 d3, q13 399 400 vand q1, q1, q15 ; vp8_filter &= mask 401 402 vmov.u16 q15, #63 ; #63 403 404 vand q13, q1, q14 ; Filter2 &= hev 405 406 vqadd.s8 q2, q13, q11 ; Filter1 = clamp(Filter2+4) 407 vqadd.s8 q13, q13, q12 ; Filter2 = clamp(Filter2+3) 408 409 vmov q0, q15 410 411 vshr.s8 q2, q2, #3 ; Filter1 >>= 3 412 vshr.s8 q13, q13, #3 ; Filter2 >>= 3 413 414 vmov q11, q15 415 vmov q12, q15 416 417 vqsub.s8 q7, q7, q2 ; qs0 = clamp(qs0 - Filter1) 418 419 vqadd.s8 q6, q6, q13 ; ps0 = clamp(ps0 + Filter2) 420 421 vbic q1, q1, q14 ; vp8_filter &= ~hev 422 423 ; roughly 1/7th difference across boundary 424 ; roughly 2/7th difference across boundary 425 ; roughly 3/7th difference across boundary 426 427 vmov.u8 d5, #9 ; #9 428 vmov.u8 d4, #18 ; #18 429 430 vmov q13, q15 431 vmov q14, q15 432 433 vmlal.s8 q0, d2, d5 ; 63 + Filter2 * 9 434 vmlal.s8 q11, d3, d5 435 vmov.u8 d5, #27 ; #27 436 vmlal.s8 q12, d2, d4 ; 63 + Filter2 * 18 437 vmlal.s8 q13, d3, d4 438 vmlal.s8 q14, d2, d5 ; 63 + Filter2 * 27 439 vmlal.s8 q15, d3, d5 440 441 vqshrn.s16 d0, q0, #7 ; u = clamp((63 + Filter2 * 9)>>7) 442 vqshrn.s16 d1, q11, #7 443 vqshrn.s16 d24, q12, #7 ; u = clamp((63 + Filter2 * 18)>>7) 444 vqshrn.s16 d25, q13, #7 445 vqshrn.s16 d28, q14, #7 ; u = clamp((63 + Filter2 * 27)>>7) 446 vqshrn.s16 d29, q15, #7 447 448 vmov.u8 q1, #0x80 ; 0x80 449 450 vqsub.s8 q11, q9, q0 ; s = clamp(qs2 - u) 451 vqadd.s8 q0, q4, q0 ; s = clamp(ps2 + u) 452 vqsub.s8 q13, q8, q12 ; s = clamp(qs1 - u) 453 vqadd.s8 q12, q5, q12 ; s = clamp(ps1 + u) 454 vqsub.s8 q15, q7, q14 ; s = clamp(qs0 - u) 455 vqadd.s8 q14, q6, q14 ; s = clamp(ps0 + u) 456 457 veor q9, q11, q1 ; *oq2 = s^0x80 458 veor q4, q0, q1 ; *op2 = s^0x80 459 veor q8, q13, q1 ; *oq1 = s^0x80 460 veor q5, q12, q1 ; *op2 = s^0x80 461 veor q7, q15, q1 ; *oq0 = s^0x80 462 veor q6, q14, q1 ; *op0 = s^0x80 463 464 bx lr 465 ENDP ; |vp8_mbloop_filter_neon| 466 467;----------------- 468 469 END 470