| OLD | NEW |
| (Empty) |
| 1 ; | |
| 2 ; Copyright (c) 2013 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 EXPORT |vp9_lpf_horizontal_4_neon| | |
| 12 EXPORT |vp9_lpf_vertical_4_neon| | |
| 13 EXPORT |vp9_lpf_horizontal_8_neon| | |
| 14 EXPORT |vp9_lpf_vertical_8_neon| | |
| 15 ARM | |
| 16 | |
| 17 AREA ||.text||, CODE, READONLY, ALIGN=2 | |
| 18 | |
| 19 ; Currently vp9 only works on iterations 8 at a time. The vp8 loop filter | |
| 20 ; works on 16 iterations at a time. | |
| 21 ; TODO(fgalligan): See about removing the count code as this function is only | |
| 22 ; called with a count of 1. | |
| 23 ; | |
| 24 ; void vp9_lpf_horizontal_4_neon(uint8_t *s, | |
| 25 ; int p /* pitch */, | |
| 26 ; const uint8_t *blimit, | |
| 27 ; const uint8_t *limit, | |
| 28 ; const uint8_t *thresh, | |
| 29 ; int count) | |
| 30 ; | |
| 31 ; r0 uint8_t *s, | |
| 32 ; r1 int p, /* pitch */ | |
| 33 ; r2 const uint8_t *blimit, | |
| 34 ; r3 const uint8_t *limit, | |
| 35 ; sp const uint8_t *thresh, | |
| 36 ; sp+4 int count | |
| 37 |vp9_lpf_horizontal_4_neon| PROC | |
| 38 push {lr} | |
| 39 | |
| 40 vld1.8 {d0[]}, [r2] ; duplicate *blimit | |
| 41 ldr r12, [sp, #8] ; load count | |
| 42 ldr r2, [sp, #4] ; load thresh | |
| 43 add r1, r1, r1 ; double pitch | |
| 44 | |
| 45 cmp r12, #0 | |
| 46 beq end_vp9_lf_h_edge | |
| 47 | |
| 48 vld1.8 {d1[]}, [r3] ; duplicate *limit | |
| 49 vld1.8 {d2[]}, [r2] ; duplicate *thresh | |
| 50 | |
| 51 count_lf_h_loop | |
| 52 sub r2, r0, r1, lsl #1 ; move src pointer down by 4 lines | |
| 53 add r3, r2, r1, lsr #1 ; set to 3 lines down | |
| 54 | |
| 55 vld1.u8 {d3}, [r2@64], r1 ; p3 | |
| 56 vld1.u8 {d4}, [r3@64], r1 ; p2 | |
| 57 vld1.u8 {d5}, [r2@64], r1 ; p1 | |
| 58 vld1.u8 {d6}, [r3@64], r1 ; p0 | |
| 59 vld1.u8 {d7}, [r2@64], r1 ; q0 | |
| 60 vld1.u8 {d16}, [r3@64], r1 ; q1 | |
| 61 vld1.u8 {d17}, [r2@64] ; q2 | |
| 62 vld1.u8 {d18}, [r3@64] ; q3 | |
| 63 | |
| 64 sub r2, r2, r1, lsl #1 | |
| 65 sub r3, r3, r1, lsl #1 | |
| 66 | |
| 67 bl vp9_loop_filter_neon | |
| 68 | |
| 69 vst1.u8 {d4}, [r2@64], r1 ; store op1 | |
| 70 vst1.u8 {d5}, [r3@64], r1 ; store op0 | |
| 71 vst1.u8 {d6}, [r2@64], r1 ; store oq0 | |
| 72 vst1.u8 {d7}, [r3@64], r1 ; store oq1 | |
| 73 | |
| 74 add r0, r0, #8 | |
| 75 subs r12, r12, #1 | |
| 76 bne count_lf_h_loop | |
| 77 | |
| 78 end_vp9_lf_h_edge | |
| 79 pop {pc} | |
| 80 ENDP ; |vp9_lpf_horizontal_4_neon| | |
| 81 | |
| 82 ; Currently vp9 only works on iterations 8 at a time. The vp8 loop filter | |
| 83 ; works on 16 iterations at a time. | |
| 84 ; TODO(fgalligan): See about removing the count code as this function is only | |
| 85 ; called with a count of 1. | |
| 86 ; | |
| 87 ; void vp9_lpf_vertical_4_neon(uint8_t *s, | |
| 88 ; int p /* pitch */, | |
| 89 ; const uint8_t *blimit, | |
| 90 ; const uint8_t *limit, | |
| 91 ; const uint8_t *thresh, | |
| 92 ; int count) | |
| 93 ; | |
| 94 ; r0 uint8_t *s, | |
| 95 ; r1 int p, /* pitch */ | |
| 96 ; r2 const uint8_t *blimit, | |
| 97 ; r3 const uint8_t *limit, | |
| 98 ; sp const uint8_t *thresh, | |
| 99 ; sp+4 int count | |
| 100 |vp9_lpf_vertical_4_neon| PROC | |
| 101 push {lr} | |
| 102 | |
| 103 vld1.8 {d0[]}, [r2] ; duplicate *blimit | |
| 104 ldr r12, [sp, #8] ; load count | |
| 105 vld1.8 {d1[]}, [r3] ; duplicate *limit | |
| 106 | |
| 107 ldr r3, [sp, #4] ; load thresh | |
| 108 sub r2, r0, #4 ; move s pointer down by 4 columns | |
| 109 cmp r12, #0 | |
| 110 beq end_vp9_lf_v_edge | |
| 111 | |
| 112 vld1.8 {d2[]}, [r3] ; duplicate *thresh | |
| 113 | |
| 114 count_lf_v_loop | |
| 115 vld1.u8 {d3}, [r2], r1 ; load s data | |
| 116 vld1.u8 {d4}, [r2], r1 | |
| 117 vld1.u8 {d5}, [r2], r1 | |
| 118 vld1.u8 {d6}, [r2], r1 | |
| 119 vld1.u8 {d7}, [r2], r1 | |
| 120 vld1.u8 {d16}, [r2], r1 | |
| 121 vld1.u8 {d17}, [r2], r1 | |
| 122 vld1.u8 {d18}, [r2] | |
| 123 | |
| 124 ;transpose to 8x16 matrix | |
| 125 vtrn.32 d3, d7 | |
| 126 vtrn.32 d4, d16 | |
| 127 vtrn.32 d5, d17 | |
| 128 vtrn.32 d6, d18 | |
| 129 | |
| 130 vtrn.16 d3, d5 | |
| 131 vtrn.16 d4, d6 | |
| 132 vtrn.16 d7, d17 | |
| 133 vtrn.16 d16, d18 | |
| 134 | |
| 135 vtrn.8 d3, d4 | |
| 136 vtrn.8 d5, d6 | |
| 137 vtrn.8 d7, d16 | |
| 138 vtrn.8 d17, d18 | |
| 139 | |
| 140 bl vp9_loop_filter_neon | |
| 141 | |
| 142 sub r0, r0, #2 | |
| 143 | |
| 144 ;store op1, op0, oq0, oq1 | |
| 145 vst4.8 {d4[0], d5[0], d6[0], d7[0]}, [r0], r1 | |
| 146 vst4.8 {d4[1], d5[1], d6[1], d7[1]}, [r0], r1 | |
| 147 vst4.8 {d4[2], d5[2], d6[2], d7[2]}, [r0], r1 | |
| 148 vst4.8 {d4[3], d5[3], d6[3], d7[3]}, [r0], r1 | |
| 149 vst4.8 {d4[4], d5[4], d6[4], d7[4]}, [r0], r1 | |
| 150 vst4.8 {d4[5], d5[5], d6[5], d7[5]}, [r0], r1 | |
| 151 vst4.8 {d4[6], d5[6], d6[6], d7[6]}, [r0], r1 | |
| 152 vst4.8 {d4[7], d5[7], d6[7], d7[7]}, [r0] | |
| 153 | |
| 154 add r0, r0, r1, lsl #3 ; s += pitch * 8 | |
| 155 subs r12, r12, #1 | |
| 156 subne r2, r0, #4 ; move s pointer down by 4 columns | |
| 157 bne count_lf_v_loop | |
| 158 | |
| 159 end_vp9_lf_v_edge | |
| 160 pop {pc} | |
| 161 ENDP ; |vp9_lpf_vertical_4_neon| | |
| 162 | |
| 163 ; void vp9_loop_filter_neon(); | |
| 164 ; This is a helper function for the loopfilters. The invidual functions do the | |
| 165 ; necessary load, transpose (if necessary) and store. The function does not use | |
| 166 ; registers d8-d15. | |
| 167 ; | |
| 168 ; Inputs: | |
| 169 ; r0-r3, r12 PRESERVE | |
| 170 ; d0 blimit | |
| 171 ; d1 limit | |
| 172 ; d2 thresh | |
| 173 ; d3 p3 | |
| 174 ; d4 p2 | |
| 175 ; d5 p1 | |
| 176 ; d6 p0 | |
| 177 ; d7 q0 | |
| 178 ; d16 q1 | |
| 179 ; d17 q2 | |
| 180 ; d18 q3 | |
| 181 ; | |
| 182 ; Outputs: | |
| 183 ; d4 op1 | |
| 184 ; d5 op0 | |
| 185 ; d6 oq0 | |
| 186 ; d7 oq1 | |
| 187 |vp9_loop_filter_neon| PROC | |
| 188 ; filter_mask | |
| 189 vabd.u8 d19, d3, d4 ; m1 = abs(p3 - p2) | |
| 190 vabd.u8 d20, d4, d5 ; m2 = abs(p2 - p1) | |
| 191 vabd.u8 d21, d5, d6 ; m3 = abs(p1 - p0) | |
| 192 vabd.u8 d22, d16, d7 ; m4 = abs(q1 - q0) | |
| 193 vabd.u8 d3, d17, d16 ; m5 = abs(q2 - q1) | |
| 194 vabd.u8 d4, d18, d17 ; m6 = abs(q3 - q2) | |
| 195 | |
| 196 ; only compare the largest value to limit | |
| 197 vmax.u8 d19, d19, d20 ; m1 = max(m1, m2) | |
| 198 vmax.u8 d20, d21, d22 ; m2 = max(m3, m4) | |
| 199 | |
| 200 vabd.u8 d17, d6, d7 ; abs(p0 - q0) | |
| 201 | |
| 202 vmax.u8 d3, d3, d4 ; m3 = max(m5, m6) | |
| 203 | |
| 204 vmov.u8 d18, #0x80 | |
| 205 | |
| 206 vmax.u8 d23, d19, d20 ; m1 = max(m1, m2) | |
| 207 | |
| 208 ; hevmask | |
| 209 vcgt.u8 d21, d21, d2 ; (abs(p1 - p0) > thresh)*-1 | |
| 210 vcgt.u8 d22, d22, d2 ; (abs(q1 - q0) > thresh)*-1 | |
| 211 vmax.u8 d23, d23, d3 ; m1 = max(m1, m3) | |
| 212 | |
| 213 vabd.u8 d28, d5, d16 ; a = abs(p1 - q1) | |
| 214 vqadd.u8 d17, d17, d17 ; b = abs(p0 - q0) * 2 | |
| 215 | |
| 216 veor d7, d7, d18 ; qs0 | |
| 217 | |
| 218 vcge.u8 d23, d1, d23 ; abs(m1) > limit | |
| 219 | |
| 220 ; filter() function | |
| 221 ; convert to signed | |
| 222 | |
| 223 vshr.u8 d28, d28, #1 ; a = a / 2 | |
| 224 veor d6, d6, d18 ; ps0 | |
| 225 | |
| 226 veor d5, d5, d18 ; ps1 | |
| 227 vqadd.u8 d17, d17, d28 ; a = b + a | |
| 228 | |
| 229 veor d16, d16, d18 ; qs1 | |
| 230 | |
| 231 vmov.u8 d19, #3 | |
| 232 | |
| 233 vsub.s8 d28, d7, d6 ; ( qs0 - ps0) | |
| 234 | |
| 235 vcge.u8 d17, d0, d17 ; a > blimit | |
| 236 | |
| 237 vqsub.s8 d27, d5, d16 ; filter = clamp(ps1-qs1) | |
| 238 vorr d22, d21, d22 ; hevmask | |
| 239 | |
| 240 vmull.s8 q12, d28, d19 ; 3 * ( qs0 - ps0) | |
| 241 | |
| 242 vand d27, d27, d22 ; filter &= hev | |
| 243 vand d23, d23, d17 ; filter_mask | |
| 244 | |
| 245 vaddw.s8 q12, q12, d27 ; filter + 3 * (qs0 - ps0) | |
| 246 | |
| 247 vmov.u8 d17, #4 | |
| 248 | |
| 249 ; filter = clamp(filter + 3 * ( qs0 - ps0)) | |
| 250 vqmovn.s16 d27, q12 | |
| 251 | |
| 252 vand d27, d27, d23 ; filter &= mask | |
| 253 | |
| 254 vqadd.s8 d28, d27, d19 ; filter2 = clamp(filter+3) | |
| 255 vqadd.s8 d27, d27, d17 ; filter1 = clamp(filter+4) | |
| 256 vshr.s8 d28, d28, #3 ; filter2 >>= 3 | |
| 257 vshr.s8 d27, d27, #3 ; filter1 >>= 3 | |
| 258 | |
| 259 vqadd.s8 d19, d6, d28 ; u = clamp(ps0 + filter2) | |
| 260 vqsub.s8 d26, d7, d27 ; u = clamp(qs0 - filter1) | |
| 261 | |
| 262 ; outer tap adjustments | |
| 263 vrshr.s8 d27, d27, #1 ; filter = ++filter1 >> 1 | |
| 264 | |
| 265 veor d6, d26, d18 ; *oq0 = u^0x80 | |
| 266 | |
| 267 vbic d27, d27, d22 ; filter &= ~hev | |
| 268 | |
| 269 vqadd.s8 d21, d5, d27 ; u = clamp(ps1 + filter) | |
| 270 vqsub.s8 d20, d16, d27 ; u = clamp(qs1 - filter) | |
| 271 | |
| 272 veor d5, d19, d18 ; *op0 = u^0x80 | |
| 273 veor d4, d21, d18 ; *op1 = u^0x80 | |
| 274 veor d7, d20, d18 ; *oq1 = u^0x80 | |
| 275 | |
| 276 bx lr | |
| 277 ENDP ; |vp9_loop_filter_neon| | |
| 278 | |
| 279 ; void vp9_lpf_horizontal_8_neon(uint8_t *s, int p, | |
| 280 ; const uint8_t *blimit, | |
| 281 ; const uint8_t *limit, | |
| 282 ; const uint8_t *thresh, | |
| 283 ; int count) | |
| 284 ; r0 uint8_t *s, | |
| 285 ; r1 int p, /* pitch */ | |
| 286 ; r2 const uint8_t *blimit, | |
| 287 ; r3 const uint8_t *limit, | |
| 288 ; sp const uint8_t *thresh, | |
| 289 ; sp+4 int count | |
| 290 |vp9_lpf_horizontal_8_neon| PROC | |
| 291 push {r4-r5, lr} | |
| 292 | |
| 293 vld1.8 {d0[]}, [r2] ; duplicate *blimit | |
| 294 ldr r12, [sp, #16] ; load count | |
| 295 ldr r2, [sp, #12] ; load thresh | |
| 296 add r1, r1, r1 ; double pitch | |
| 297 | |
| 298 cmp r12, #0 | |
| 299 beq end_vp9_mblf_h_edge | |
| 300 | |
| 301 vld1.8 {d1[]}, [r3] ; duplicate *limit | |
| 302 vld1.8 {d2[]}, [r2] ; duplicate *thresh | |
| 303 | |
| 304 count_mblf_h_loop | |
| 305 sub r3, r0, r1, lsl #1 ; move src pointer down by 4 lines | |
| 306 add r2, r3, r1, lsr #1 ; set to 3 lines down | |
| 307 | |
| 308 vld1.u8 {d3}, [r3@64], r1 ; p3 | |
| 309 vld1.u8 {d4}, [r2@64], r1 ; p2 | |
| 310 vld1.u8 {d5}, [r3@64], r1 ; p1 | |
| 311 vld1.u8 {d6}, [r2@64], r1 ; p0 | |
| 312 vld1.u8 {d7}, [r3@64], r1 ; q0 | |
| 313 vld1.u8 {d16}, [r2@64], r1 ; q1 | |
| 314 vld1.u8 {d17}, [r3@64] ; q2 | |
| 315 vld1.u8 {d18}, [r2@64], r1 ; q3 | |
| 316 | |
| 317 sub r3, r3, r1, lsl #1 | |
| 318 sub r2, r2, r1, lsl #2 | |
| 319 | |
| 320 bl vp9_mbloop_filter_neon | |
| 321 | |
| 322 vst1.u8 {d0}, [r2@64], r1 ; store op2 | |
| 323 vst1.u8 {d1}, [r3@64], r1 ; store op1 | |
| 324 vst1.u8 {d2}, [r2@64], r1 ; store op0 | |
| 325 vst1.u8 {d3}, [r3@64], r1 ; store oq0 | |
| 326 vst1.u8 {d4}, [r2@64], r1 ; store oq1 | |
| 327 vst1.u8 {d5}, [r3@64], r1 ; store oq2 | |
| 328 | |
| 329 add r0, r0, #8 | |
| 330 subs r12, r12, #1 | |
| 331 bne count_mblf_h_loop | |
| 332 | |
| 333 end_vp9_mblf_h_edge | |
| 334 pop {r4-r5, pc} | |
| 335 | |
| 336 ENDP ; |vp9_lpf_horizontal_8_neon| | |
| 337 | |
| 338 ; void vp9_lpf_vertical_8_neon(uint8_t *s, | |
| 339 ; int pitch, | |
| 340 ; const uint8_t *blimit, | |
| 341 ; const uint8_t *limit, | |
| 342 ; const uint8_t *thresh, | |
| 343 ; int count) | |
| 344 ; | |
| 345 ; r0 uint8_t *s, | |
| 346 ; r1 int pitch, | |
| 347 ; r2 const uint8_t *blimit, | |
| 348 ; r3 const uint8_t *limit, | |
| 349 ; sp const uint8_t *thresh, | |
| 350 ; sp+4 int count | |
| 351 |vp9_lpf_vertical_8_neon| PROC | |
| 352 push {r4-r5, lr} | |
| 353 | |
| 354 vld1.8 {d0[]}, [r2] ; duplicate *blimit | |
| 355 ldr r12, [sp, #16] ; load count | |
| 356 vld1.8 {d1[]}, [r3] ; duplicate *limit | |
| 357 | |
| 358 ldr r3, [sp, #12] ; load thresh | |
| 359 sub r2, r0, #4 ; move s pointer down by 4 columns | |
| 360 cmp r12, #0 | |
| 361 beq end_vp9_mblf_v_edge | |
| 362 | |
| 363 vld1.8 {d2[]}, [r3] ; duplicate *thresh | |
| 364 | |
| 365 count_mblf_v_loop | |
| 366 vld1.u8 {d3}, [r2], r1 ; load s data | |
| 367 vld1.u8 {d4}, [r2], r1 | |
| 368 vld1.u8 {d5}, [r2], r1 | |
| 369 vld1.u8 {d6}, [r2], r1 | |
| 370 vld1.u8 {d7}, [r2], r1 | |
| 371 vld1.u8 {d16}, [r2], r1 | |
| 372 vld1.u8 {d17}, [r2], r1 | |
| 373 vld1.u8 {d18}, [r2] | |
| 374 | |
| 375 ;transpose to 8x16 matrix | |
| 376 vtrn.32 d3, d7 | |
| 377 vtrn.32 d4, d16 | |
| 378 vtrn.32 d5, d17 | |
| 379 vtrn.32 d6, d18 | |
| 380 | |
| 381 vtrn.16 d3, d5 | |
| 382 vtrn.16 d4, d6 | |
| 383 vtrn.16 d7, d17 | |
| 384 vtrn.16 d16, d18 | |
| 385 | |
| 386 vtrn.8 d3, d4 | |
| 387 vtrn.8 d5, d6 | |
| 388 vtrn.8 d7, d16 | |
| 389 vtrn.8 d17, d18 | |
| 390 | |
| 391 sub r2, r0, #3 | |
| 392 add r3, r0, #1 | |
| 393 | |
| 394 bl vp9_mbloop_filter_neon | |
| 395 | |
| 396 ;store op2, op1, op0, oq0 | |
| 397 vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r2], r1 | |
| 398 vst4.8 {d0[1], d1[1], d2[1], d3[1]}, [r2], r1 | |
| 399 vst4.8 {d0[2], d1[2], d2[2], d3[2]}, [r2], r1 | |
| 400 vst4.8 {d0[3], d1[3], d2[3], d3[3]}, [r2], r1 | |
| 401 vst4.8 {d0[4], d1[4], d2[4], d3[4]}, [r2], r1 | |
| 402 vst4.8 {d0[5], d1[5], d2[5], d3[5]}, [r2], r1 | |
| 403 vst4.8 {d0[6], d1[6], d2[6], d3[6]}, [r2], r1 | |
| 404 vst4.8 {d0[7], d1[7], d2[7], d3[7]}, [r2] | |
| 405 | |
| 406 ;store oq1, oq2 | |
| 407 vst2.8 {d4[0], d5[0]}, [r3], r1 | |
| 408 vst2.8 {d4[1], d5[1]}, [r3], r1 | |
| 409 vst2.8 {d4[2], d5[2]}, [r3], r1 | |
| 410 vst2.8 {d4[3], d5[3]}, [r3], r1 | |
| 411 vst2.8 {d4[4], d5[4]}, [r3], r1 | |
| 412 vst2.8 {d4[5], d5[5]}, [r3], r1 | |
| 413 vst2.8 {d4[6], d5[6]}, [r3], r1 | |
| 414 vst2.8 {d4[7], d5[7]}, [r3] | |
| 415 | |
| 416 add r0, r0, r1, lsl #3 ; s += pitch * 8 | |
| 417 subs r12, r12, #1 | |
| 418 subne r2, r0, #4 ; move s pointer down by 4 columns | |
| 419 bne count_mblf_v_loop | |
| 420 | |
| 421 end_vp9_mblf_v_edge | |
| 422 pop {r4-r5, pc} | |
| 423 ENDP ; |vp9_lpf_vertical_8_neon| | |
| 424 | |
| 425 ; void vp9_mbloop_filter_neon(); | |
| 426 ; This is a helper function for the loopfilters. The invidual functions do the | |
| 427 ; necessary load, transpose (if necessary) and store. The function does not use | |
| 428 ; registers d8-d15. | |
| 429 ; | |
| 430 ; Inputs: | |
| 431 ; r0-r3, r12 PRESERVE | |
| 432 ; d0 blimit | |
| 433 ; d1 limit | |
| 434 ; d2 thresh | |
| 435 ; d3 p3 | |
| 436 ; d4 p2 | |
| 437 ; d5 p1 | |
| 438 ; d6 p0 | |
| 439 ; d7 q0 | |
| 440 ; d16 q1 | |
| 441 ; d17 q2 | |
| 442 ; d18 q3 | |
| 443 ; | |
| 444 ; Outputs: | |
| 445 ; d0 op2 | |
| 446 ; d1 op1 | |
| 447 ; d2 op0 | |
| 448 ; d3 oq0 | |
| 449 ; d4 oq1 | |
| 450 ; d5 oq2 | |
| 451 |vp9_mbloop_filter_neon| PROC | |
| 452 ; filter_mask | |
| 453 vabd.u8 d19, d3, d4 ; m1 = abs(p3 - p2) | |
| 454 vabd.u8 d20, d4, d5 ; m2 = abs(p2 - p1) | |
| 455 vabd.u8 d21, d5, d6 ; m3 = abs(p1 - p0) | |
| 456 vabd.u8 d22, d16, d7 ; m4 = abs(q1 - q0) | |
| 457 vabd.u8 d23, d17, d16 ; m5 = abs(q2 - q1) | |
| 458 vabd.u8 d24, d18, d17 ; m6 = abs(q3 - q2) | |
| 459 | |
| 460 ; only compare the largest value to limit | |
| 461 vmax.u8 d19, d19, d20 ; m1 = max(m1, m2) | |
| 462 vmax.u8 d20, d21, d22 ; m2 = max(m3, m4) | |
| 463 | |
| 464 vabd.u8 d25, d6, d4 ; m7 = abs(p0 - p2) | |
| 465 | |
| 466 vmax.u8 d23, d23, d24 ; m3 = max(m5, m6) | |
| 467 | |
| 468 vabd.u8 d26, d7, d17 ; m8 = abs(q0 - q2) | |
| 469 | |
| 470 vmax.u8 d19, d19, d20 | |
| 471 | |
| 472 vabd.u8 d24, d6, d7 ; m9 = abs(p0 - q0) | |
| 473 vabd.u8 d27, d3, d6 ; m10 = abs(p3 - p0) | |
| 474 vabd.u8 d28, d18, d7 ; m11 = abs(q3 - q0) | |
| 475 | |
| 476 vmax.u8 d19, d19, d23 | |
| 477 | |
| 478 vabd.u8 d23, d5, d16 ; a = abs(p1 - q1) | |
| 479 vqadd.u8 d24, d24, d24 ; b = abs(p0 - q0) * 2 | |
| 480 | |
| 481 ; abs () > limit | |
| 482 vcge.u8 d19, d1, d19 | |
| 483 | |
| 484 ; only compare the largest value to thresh | |
| 485 vmax.u8 d25, d25, d26 ; m4 = max(m7, m8) | |
| 486 vmax.u8 d26, d27, d28 ; m5 = max(m10, m11) | |
| 487 | |
| 488 vshr.u8 d23, d23, #1 ; a = a / 2 | |
| 489 | |
| 490 vmax.u8 d25, d25, d26 ; m4 = max(m4, m5) | |
| 491 | |
| 492 vqadd.u8 d24, d24, d23 ; a = b + a | |
| 493 | |
| 494 vmax.u8 d20, d20, d25 ; m2 = max(m2, m4) | |
| 495 | |
| 496 vmov.u8 d23, #1 | |
| 497 vcge.u8 d24, d0, d24 ; a > blimit | |
| 498 | |
| 499 vcgt.u8 d21, d21, d2 ; (abs(p1 - p0) > thresh)*-1 | |
| 500 | |
| 501 vcge.u8 d20, d23, d20 ; flat | |
| 502 | |
| 503 vand d19, d19, d24 ; mask | |
| 504 | |
| 505 vcgt.u8 d23, d22, d2 ; (abs(q1 - q0) > thresh)*-1 | |
| 506 | |
| 507 vand d20, d20, d19 ; flat & mask | |
| 508 | |
| 509 vmov.u8 d22, #0x80 | |
| 510 | |
| 511 vorr d23, d21, d23 ; hev | |
| 512 | |
| 513 ; This instruction will truncate the "flat & mask" masks down to 4 bits | |
| 514 ; each to fit into one 32 bit arm register. The values are stored in | |
| 515 ; q10.64[0]. | |
| 516 vshrn.u16 d30, q10, #4 | |
| 517 vmov.u32 r4, d30[0] ; flat & mask 4bits | |
| 518 | |
| 519 adds r5, r4, #1 ; Check for all 1's | |
| 520 | |
| 521 ; If mask and flat are 1's for all vectors, then we only need to execute | |
| 522 ; the power branch for all vectors. | |
| 523 beq power_branch_only | |
| 524 | |
| 525 cmp r4, #0 ; Check for 0, set flag for later | |
| 526 | |
| 527 ; mbfilter() function | |
| 528 ; filter() function | |
| 529 ; convert to signed | |
| 530 veor d21, d7, d22 ; qs0 | |
| 531 veor d24, d6, d22 ; ps0 | |
| 532 veor d25, d5, d22 ; ps1 | |
| 533 veor d26, d16, d22 ; qs1 | |
| 534 | |
| 535 vmov.u8 d27, #3 | |
| 536 | |
| 537 vsub.s8 d28, d21, d24 ; ( qs0 - ps0) | |
| 538 | |
| 539 vqsub.s8 d29, d25, d26 ; filter = clamp(ps1-qs1) | |
| 540 | |
| 541 vmull.s8 q15, d28, d27 ; 3 * ( qs0 - ps0) | |
| 542 | |
| 543 vand d29, d29, d23 ; filter &= hev | |
| 544 | |
| 545 vaddw.s8 q15, q15, d29 ; filter + 3 * (qs0 - ps0) | |
| 546 | |
| 547 vmov.u8 d29, #4 | |
| 548 | |
| 549 ; filter = clamp(filter + 3 * ( qs0 - ps0)) | |
| 550 vqmovn.s16 d28, q15 | |
| 551 | |
| 552 vand d28, d28, d19 ; filter &= mask | |
| 553 | |
| 554 vqadd.s8 d30, d28, d27 ; filter2 = clamp(filter+3) | |
| 555 vqadd.s8 d29, d28, d29 ; filter1 = clamp(filter+4) | |
| 556 vshr.s8 d30, d30, #3 ; filter2 >>= 3 | |
| 557 vshr.s8 d29, d29, #3 ; filter1 >>= 3 | |
| 558 | |
| 559 vqadd.s8 d24, d24, d30 ; op0 = clamp(ps0 + filter2) | |
| 560 vqsub.s8 d21, d21, d29 ; oq0 = clamp(qs0 - filter1) | |
| 561 | |
| 562 ; outer tap adjustments: ++filter1 >> 1 | |
| 563 vrshr.s8 d29, d29, #1 | |
| 564 vbic d29, d29, d23 ; filter &= ~hev | |
| 565 | |
| 566 vqadd.s8 d25, d25, d29 ; op1 = clamp(ps1 + filter) | |
| 567 vqsub.s8 d26, d26, d29 ; oq1 = clamp(qs1 - filter) | |
| 568 | |
| 569 ; If mask and flat are 0's for all vectors, then we only need to execute | |
| 570 ; the filter branch for all vectors. | |
| 571 beq filter_branch_only | |
| 572 | |
| 573 ; If mask and flat are mixed then we must perform both branches and | |
| 574 ; combine the data. | |
| 575 veor d24, d24, d22 ; *f_op0 = u^0x80 | |
| 576 veor d21, d21, d22 ; *f_oq0 = u^0x80 | |
| 577 veor d25, d25, d22 ; *f_op1 = u^0x80 | |
| 578 veor d26, d26, d22 ; *f_oq1 = u^0x80 | |
| 579 | |
| 580 ; At this point we have already executed the filter branch. The filter | |
| 581 ; branch does not set op2 or oq2, so use p2 and q2. Execute the power | |
| 582 ; branch and combine the data. | |
| 583 vmov.u8 d23, #2 | |
| 584 vaddl.u8 q14, d6, d7 ; r_op2 = p0 + q0 | |
| 585 vmlal.u8 q14, d3, d27 ; r_op2 += p3 * 3 | |
| 586 vmlal.u8 q14, d4, d23 ; r_op2 += p2 * 2 | |
| 587 | |
| 588 vbif d0, d4, d20 ; op2 |= p2 & ~(flat & mask) | |
| 589 | |
| 590 vaddw.u8 q14, d5 ; r_op2 += p1 | |
| 591 | |
| 592 vbif d1, d25, d20 ; op1 |= f_op1 & ~(flat & mask) | |
| 593 | |
| 594 vqrshrn.u16 d30, q14, #3 ; r_op2 | |
| 595 | |
| 596 vsubw.u8 q14, d3 ; r_op1 = r_op2 - p3 | |
| 597 vsubw.u8 q14, d4 ; r_op1 -= p2 | |
| 598 vaddw.u8 q14, d5 ; r_op1 += p1 | |
| 599 vaddw.u8 q14, d16 ; r_op1 += q1 | |
| 600 | |
| 601 vbif d2, d24, d20 ; op0 |= f_op0 & ~(flat & mask) | |
| 602 | |
| 603 vqrshrn.u16 d31, q14, #3 ; r_op1 | |
| 604 | |
| 605 vsubw.u8 q14, d3 ; r_op0 = r_op1 - p3 | |
| 606 vsubw.u8 q14, d5 ; r_op0 -= p1 | |
| 607 vaddw.u8 q14, d6 ; r_op0 += p0 | |
| 608 vaddw.u8 q14, d17 ; r_op0 += q2 | |
| 609 | |
| 610 vbit d0, d30, d20 ; op2 |= r_op2 & (flat & mask) | |
| 611 | |
| 612 vqrshrn.u16 d23, q14, #3 ; r_op0 | |
| 613 | |
| 614 vsubw.u8 q14, d3 ; r_oq0 = r_op0 - p3 | |
| 615 vsubw.u8 q14, d6 ; r_oq0 -= p0 | |
| 616 vaddw.u8 q14, d7 ; r_oq0 += q0 | |
| 617 | |
| 618 vbit d1, d31, d20 ; op1 |= r_op1 & (flat & mask) | |
| 619 | |
| 620 vaddw.u8 q14, d18 ; oq0 += q3 | |
| 621 | |
| 622 vbit d2, d23, d20 ; op0 |= r_op0 & (flat & mask) | |
| 623 | |
| 624 vqrshrn.u16 d22, q14, #3 ; r_oq0 | |
| 625 | |
| 626 vsubw.u8 q14, d4 ; r_oq1 = r_oq0 - p2 | |
| 627 vsubw.u8 q14, d7 ; r_oq1 -= q0 | |
| 628 vaddw.u8 q14, d16 ; r_oq1 += q1 | |
| 629 | |
| 630 vbif d3, d21, d20 ; oq0 |= f_oq0 & ~(flat & mask) | |
| 631 | |
| 632 vaddw.u8 q14, d18 ; r_oq1 += q3 | |
| 633 | |
| 634 vbif d4, d26, d20 ; oq1 |= f_oq1 & ~(flat & mask) | |
| 635 | |
| 636 vqrshrn.u16 d6, q14, #3 ; r_oq1 | |
| 637 | |
| 638 vsubw.u8 q14, d5 ; r_oq2 = r_oq1 - p1 | |
| 639 vsubw.u8 q14, d16 ; r_oq2 -= q1 | |
| 640 vaddw.u8 q14, d17 ; r_oq2 += q2 | |
| 641 vaddw.u8 q14, d18 ; r_oq2 += q3 | |
| 642 | |
| 643 vbif d5, d17, d20 ; oq2 |= q2 & ~(flat & mask) | |
| 644 | |
| 645 vqrshrn.u16 d7, q14, #3 ; r_oq2 | |
| 646 | |
| 647 vbit d3, d22, d20 ; oq0 |= r_oq0 & (flat & mask) | |
| 648 vbit d4, d6, d20 ; oq1 |= r_oq1 & (flat & mask) | |
| 649 vbit d5, d7, d20 ; oq2 |= r_oq2 & (flat & mask) | |
| 650 | |
| 651 bx lr | |
| 652 | |
| 653 power_branch_only | |
| 654 vmov.u8 d27, #3 | |
| 655 vmov.u8 d21, #2 | |
| 656 vaddl.u8 q14, d6, d7 ; op2 = p0 + q0 | |
| 657 vmlal.u8 q14, d3, d27 ; op2 += p3 * 3 | |
| 658 vmlal.u8 q14, d4, d21 ; op2 += p2 * 2 | |
| 659 vaddw.u8 q14, d5 ; op2 += p1 | |
| 660 vqrshrn.u16 d0, q14, #3 ; op2 | |
| 661 | |
| 662 vsubw.u8 q14, d3 ; op1 = op2 - p3 | |
| 663 vsubw.u8 q14, d4 ; op1 -= p2 | |
| 664 vaddw.u8 q14, d5 ; op1 += p1 | |
| 665 vaddw.u8 q14, d16 ; op1 += q1 | |
| 666 vqrshrn.u16 d1, q14, #3 ; op1 | |
| 667 | |
| 668 vsubw.u8 q14, d3 ; op0 = op1 - p3 | |
| 669 vsubw.u8 q14, d5 ; op0 -= p1 | |
| 670 vaddw.u8 q14, d6 ; op0 += p0 | |
| 671 vaddw.u8 q14, d17 ; op0 += q2 | |
| 672 vqrshrn.u16 d2, q14, #3 ; op0 | |
| 673 | |
| 674 vsubw.u8 q14, d3 ; oq0 = op0 - p3 | |
| 675 vsubw.u8 q14, d6 ; oq0 -= p0 | |
| 676 vaddw.u8 q14, d7 ; oq0 += q0 | |
| 677 vaddw.u8 q14, d18 ; oq0 += q3 | |
| 678 vqrshrn.u16 d3, q14, #3 ; oq0 | |
| 679 | |
| 680 vsubw.u8 q14, d4 ; oq1 = oq0 - p2 | |
| 681 vsubw.u8 q14, d7 ; oq1 -= q0 | |
| 682 vaddw.u8 q14, d16 ; oq1 += q1 | |
| 683 vaddw.u8 q14, d18 ; oq1 += q3 | |
| 684 vqrshrn.u16 d4, q14, #3 ; oq1 | |
| 685 | |
| 686 vsubw.u8 q14, d5 ; oq2 = oq1 - p1 | |
| 687 vsubw.u8 q14, d16 ; oq2 -= q1 | |
| 688 vaddw.u8 q14, d17 ; oq2 += q2 | |
| 689 vaddw.u8 q14, d18 ; oq2 += q3 | |
| 690 vqrshrn.u16 d5, q14, #3 ; oq2 | |
| 691 | |
| 692 bx lr | |
| 693 | |
| 694 filter_branch_only | |
| 695 ; TODO(fgalligan): See if we can rearange registers so we do not need to | |
| 696 ; do the 2 vswp. | |
| 697 vswp d0, d4 ; op2 | |
| 698 vswp d5, d17 ; oq2 | |
| 699 veor d2, d24, d22 ; *op0 = u^0x80 | |
| 700 veor d3, d21, d22 ; *oq0 = u^0x80 | |
| 701 veor d1, d25, d22 ; *op1 = u^0x80 | |
| 702 veor d4, d26, d22 ; *oq1 = u^0x80 | |
| 703 | |
| 704 bx lr | |
| 705 | |
| 706 ENDP ; |vp9_mbloop_filter_neon| | |
| 707 | |
| 708 END | |
| OLD | NEW |