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