cdef_tmpl.S (19319B)
1 /* 2 * Copyright © 2018, VideoLAN and dav1d authors 3 * Copyright © 2020, Martin Storsjo 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "src/arm/asm.S" 29 #include "util.S" 30 31 .macro dir_table w, stride 32 const directions\w 33 .byte -1 * \stride + 1, -2 * \stride + 2 34 .byte 0 * \stride + 1, -1 * \stride + 2 35 .byte 0 * \stride + 1, 0 * \stride + 2 36 .byte 0 * \stride + 1, 1 * \stride + 2 37 .byte 1 * \stride + 1, 2 * \stride + 2 38 .byte 1 * \stride + 0, 2 * \stride + 1 39 .byte 1 * \stride + 0, 2 * \stride + 0 40 .byte 1 * \stride + 0, 2 * \stride - 1 41 // Repeated, to avoid & 7 42 .byte -1 * \stride + 1, -2 * \stride + 2 43 .byte 0 * \stride + 1, -1 * \stride + 2 44 .byte 0 * \stride + 1, 0 * \stride + 2 45 .byte 0 * \stride + 1, 1 * \stride + 2 46 .byte 1 * \stride + 1, 2 * \stride + 2 47 .byte 1 * \stride + 0, 2 * \stride + 1 48 endconst 49 .endm 50 51 .macro tables 52 dir_table 8, 16 53 dir_table 4, 8 54 55 const pri_taps 56 .byte 4, 2, 3, 3 57 endconst 58 .endm 59 60 .macro load_px d11, d12, d21, d22, w 61 .if \w == 8 62 add r6, r2, r9, lsl #1 // x + off 63 sub r9, r2, r9, lsl #1 // x - off 64 vld1.16 {\d11,\d12}, [r6] // p0 65 vld1.16 {\d21,\d22}, [r9] // p1 66 .else 67 add r6, r2, r9, lsl #1 // x + off 68 sub r9, r2, r9, lsl #1 // x - off 69 vld1.16 {\d11}, [r6] // p0 70 add r6, r6, #2*8 // += stride 71 vld1.16 {\d21}, [r9] // p1 72 add r9, r9, #2*8 // += stride 73 vld1.16 {\d12}, [r6] // p0 74 vld1.16 {\d22}, [r9] // p1 75 .endif 76 .endm 77 .macro handle_pixel s1, s2, thresh_vec, shift, tap, min 78 .if \min 79 vmin.u16 q2, q2, \s1 80 vmax.s16 q3, q3, \s1 81 vmin.u16 q2, q2, \s2 82 vmax.s16 q3, q3, \s2 83 .endif 84 vabd.u16 q8, q0, \s1 // abs(diff) 85 vabd.u16 q11, q0, \s2 // abs(diff) 86 vshl.u16 q9, q8, \shift // abs(diff) >> shift 87 vshl.u16 q12, q11, \shift // abs(diff) >> shift 88 vqsub.u16 q9, \thresh_vec, q9 // clip = imax(0, threshold - (abs(diff) >> shift)) 89 vqsub.u16 q12, \thresh_vec, q12// clip = imax(0, threshold - (abs(diff) >> shift)) 90 vsub.i16 q10, \s1, q0 // diff = p0 - px 91 vsub.i16 q13, \s2, q0 // diff = p1 - px 92 vneg.s16 q8, q9 // -clip 93 vneg.s16 q11, q12 // -clip 94 vmin.s16 q10, q10, q9 // imin(diff, clip) 95 vmin.s16 q13, q13, q12 // imin(diff, clip) 96 vdup.16 q9, \tap // taps[k] 97 vmax.s16 q10, q10, q8 // constrain() = imax(imin(diff, clip), -clip) 98 vmax.s16 q13, q13, q11 // constrain() = imax(imin(diff, clip), -clip) 99 vmla.i16 q1, q10, q9 // sum += taps[k] * constrain() 100 vmla.i16 q1, q13, q9 // sum += taps[k] * constrain() 101 .endm 102 103 // void dav1d_cdef_filterX_Ybpc_neon(pixel *dst, ptrdiff_t dst_stride, 104 // const uint16_t *tmp, int pri_strength, 105 // int sec_strength, int dir, int damping, 106 // int h, size_t edges); 107 .macro filter_func w, bpc, pri, sec, min, suffix 108 function cdef_filter\w\suffix\()_\bpc\()bpc_neon 109 .if \bpc == 8 110 cmp r8, #0xf 111 beq cdef_filter\w\suffix\()_edged_neon 112 .endif 113 .if \pri 114 .if \bpc == 16 115 clz r9, r9 116 sub r9, r9, #24 // -bitdepth_min_8 117 neg r9, r9 // bitdepth_min_8 118 .endif 119 movrel_local r8, pri_taps 120 .if \bpc == 16 121 lsr r9, r3, r9 // pri_strength >> bitdepth_min_8 122 and r9, r9, #1 // (pri_strength >> bitdepth_min_8) & 1 123 .else 124 and r9, r3, #1 125 .endif 126 add r8, r8, r9, lsl #1 127 .endif 128 movrel_local r9, directions\w 129 add r5, r9, r5, lsl #1 130 vmov.u16 d17, #15 131 vdup.16 d16, r6 // damping 132 133 .if \pri 134 vdup.16 q5, r3 // threshold 135 .endif 136 .if \sec 137 vdup.16 q7, r4 // threshold 138 .endif 139 vmov.16 d8[0], r3 140 vmov.16 d8[1], r4 141 vclz.i16 d8, d8 // clz(threshold) 142 vsub.i16 d8, d17, d8 // ulog2(threshold) 143 vqsub.u16 d8, d16, d8 // shift = imax(0, damping - ulog2(threshold)) 144 vneg.s16 d8, d8 // -shift 145 .if \sec 146 vdup.16 q6, d8[1] 147 .endif 148 .if \pri 149 vdup.16 q4, d8[0] 150 .endif 151 152 1: 153 .if \w == 8 154 vld1.16 {q0}, [r2, :128] // px 155 .else 156 add r12, r2, #2*8 157 vld1.16 {d0}, [r2, :64] // px 158 vld1.16 {d1}, [r12, :64] // px 159 .endif 160 161 vmov.u16 q1, #0 // sum 162 .if \min 163 vmov.u16 q2, q0 // min 164 vmov.u16 q3, q0 // max 165 .endif 166 167 // Instead of loading sec_taps 2, 1 from memory, just set it 168 // to 2 initially and decrease for the second round. 169 // This is also used as loop counter. 170 mov lr, #2 // sec_taps[0] 171 172 2: 173 .if \pri 174 ldrsb r9, [r5] // off1 175 176 load_px d28, d29, d30, d31, \w 177 .endif 178 179 .if \sec 180 add r5, r5, #4 // +2*2 181 ldrsb r9, [r5] // off2 182 .endif 183 184 .if \pri 185 ldrb r12, [r8] // *pri_taps 186 187 handle_pixel q14, q15, q5, q4, r12, \min 188 .endif 189 190 .if \sec 191 load_px d28, d29, d30, d31, \w 192 193 add r5, r5, #8 // +2*4 194 ldrsb r9, [r5] // off3 195 196 handle_pixel q14, q15, q7, q6, lr, \min 197 198 load_px d28, d29, d30, d31, \w 199 200 handle_pixel q14, q15, q7, q6, lr, \min 201 202 sub r5, r5, #11 // r5 -= 2*(2+4); r5 += 1; 203 .else 204 add r5, r5, #1 // r5 += 1 205 .endif 206 subs lr, lr, #1 // sec_tap-- (value) 207 .if \pri 208 add r8, r8, #1 // pri_taps++ (pointer) 209 .endif 210 bne 2b 211 212 vshr.s16 q14, q1, #15 // -(sum < 0) 213 vadd.i16 q1, q1, q14 // sum - (sum < 0) 214 vrshr.s16 q1, q1, #4 // (8 + sum - (sum < 0)) >> 4 215 vadd.i16 q0, q0, q1 // px + (8 + sum ...) >> 4 216 .if \min 217 vmin.s16 q0, q0, q3 218 vmax.s16 q0, q0, q2 // iclip(px + .., min, max) 219 .endif 220 .if \bpc == 8 221 vmovn.u16 d0, q0 222 .endif 223 .if \w == 8 224 add r2, r2, #2*16 // tmp += tmp_stride 225 subs r7, r7, #1 // h-- 226 .if \bpc == 8 227 vst1.8 {d0}, [r0, :64], r1 228 .else 229 vst1.16 {q0}, [r0, :128], r1 230 .endif 231 .else 232 .if \bpc == 8 233 vst1.32 {d0[0]}, [r0, :32], r1 234 .else 235 vst1.16 {d0}, [r0, :64], r1 236 .endif 237 add r2, r2, #2*16 // tmp += 2*tmp_stride 238 subs r7, r7, #2 // h -= 2 239 .if \bpc == 8 240 vst1.32 {d0[1]}, [r0, :32], r1 241 .else 242 vst1.16 {d1}, [r0, :64], r1 243 .endif 244 .endif 245 246 // Reset pri_taps and directions back to the original point 247 sub r5, r5, #2 248 .if \pri 249 sub r8, r8, #2 250 .endif 251 252 bgt 1b 253 vpop {q4-q7} 254 pop {r4-r9,pc} 255 endfunc 256 .endm 257 258 .macro filter w, bpc 259 filter_func \w, \bpc, pri=1, sec=0, min=0, suffix=_pri 260 filter_func \w, \bpc, pri=0, sec=1, min=0, suffix=_sec 261 filter_func \w, \bpc, pri=1, sec=1, min=1, suffix=_pri_sec 262 263 function cdef_filter\w\()_\bpc\()bpc_neon, export=1 264 push {r4-r9,lr} 265 vpush {q4-q7} 266 ldrd r4, r5, [sp, #92] 267 ldrd r6, r7, [sp, #100] 268 .if \bpc == 16 269 ldrd r8, r9, [sp, #108] 270 .else 271 ldr r8, [sp, #108] 272 .endif 273 cmp r3, #0 // pri_strength 274 bne 1f 275 b cdef_filter\w\()_sec_\bpc\()bpc_neon // only sec 276 1: 277 cmp r4, #0 // sec_strength 278 bne 1f 279 b cdef_filter\w\()_pri_\bpc\()bpc_neon // only pri 280 1: 281 b cdef_filter\w\()_pri_sec_\bpc\()bpc_neon // both pri and sec 282 endfunc 283 .endm 284 285 const div_table, align=4 286 .short 840, 420, 280, 210, 168, 140, 120, 105 287 endconst 288 289 const alt_fact, align=4 290 .short 420, 210, 140, 105, 105, 105, 105, 105, 140, 210, 420, 0 291 endconst 292 293 .macro cost_alt dest, s1, s2, s3, s4, s5, s6 294 vmull.s16 q1, \s1, \s1 // sum_alt[n]*sum_alt[n] 295 vmull.s16 q2, \s2, \s2 296 vmull.s16 q3, \s3, \s3 297 vmull.s16 q5, \s4, \s4 // sum_alt[n]*sum_alt[n] 298 vmull.s16 q12, \s5, \s5 299 vmull.s16 q6, \s6, \s6 // q6 overlaps the first \s1-\s2 here 300 vmul.i32 q1, q1, q13 // sum_alt[n]^2*fact 301 vmla.i32 q1, q2, q14 302 vmla.i32 q1, q3, q15 303 vmul.i32 q5, q5, q13 // sum_alt[n]^2*fact 304 vmla.i32 q5, q12, q14 305 vmla.i32 q5, q6, q15 306 vadd.i32 d2, d2, d3 307 vadd.i32 d3, d10, d11 308 vpadd.i32 \dest, d2, d3 // *cost_ptr 309 .endm 310 311 .macro find_best s1, s2, s3 312 .ifnb \s2 313 vmov.32 lr, \s2 314 .endif 315 cmp r12, r1 // cost[n] > best_cost 316 itt gt 317 movgt r0, r3 // best_dir = n 318 movgt r1, r12 // best_cost = cost[n] 319 .ifnb \s2 320 add r3, r3, #1 // n++ 321 cmp lr, r1 // cost[n] > best_cost 322 vmov.32 r12, \s3 323 itt gt 324 movgt r0, r3 // best_dir = n 325 movgt r1, lr // best_cost = cost[n] 326 add r3, r3, #1 // n++ 327 .endif 328 .endm 329 330 // int dav1d_cdef_find_dir_Xbpc_neon(const pixel *img, const ptrdiff_t stride, 331 // unsigned *const var) 332 .macro find_dir bpc 333 function cdef_find_dir_\bpc\()bpc_neon, export=1 334 push {lr} 335 vpush {q4-q7} 336 .if \bpc == 16 337 clz r3, r3 // clz(bitdepth_max) 338 sub lr, r3, #24 // -bitdepth_min_8 339 .endif 340 sub sp, sp, #32 // cost 341 mov r3, #8 342 vmov.u16 q1, #0 // q0-q1 sum_diag[0] 343 vmov.u16 q3, #0 // q2-q3 sum_diag[1] 344 vmov.u16 q5, #0 // q4-q5 sum_hv[0-1] 345 vmov.u16 q8, #0 // q6,d16 sum_alt[0] 346 // q7,d17 sum_alt[1] 347 vmov.u16 q9, #0 // q9,d22 sum_alt[2] 348 vmov.u16 q11, #0 349 vmov.u16 q10, #0 // q10,d23 sum_alt[3] 350 351 352 .irpc i, 01234567 353 .if \bpc == 8 354 vld1.8 {d30}, [r0, :64], r1 355 vmov.u8 d31, #128 356 vsubl.u8 q15, d30, d31 // img[x] - 128 357 .else 358 vld1.16 {q15}, [r0, :128], r1 359 vdup.16 q14, lr // -bitdepth_min_8 360 vshl.u16 q15, q15, q14 361 vmov.u16 q14, #128 362 vsub.i16 q15, q15, q14 // img[x] - 128 363 .endif 364 vmov.u16 q14, #0 365 366 .if \i == 0 367 vmov q0, q15 // sum_diag[0] 368 .else 369 vext.8 q12, q14, q15, #(16-2*\i) 370 vext.8 q13, q15, q14, #(16-2*\i) 371 vadd.i16 q0, q0, q12 // sum_diag[0] 372 vadd.i16 q1, q1, q13 // sum_diag[0] 373 .endif 374 vrev64.16 q13, q15 375 vswp d26, d27 // [-x] 376 .if \i == 0 377 vmov q2, q13 // sum_diag[1] 378 .else 379 vext.8 q12, q14, q13, #(16-2*\i) 380 vext.8 q13, q13, q14, #(16-2*\i) 381 vadd.i16 q2, q2, q12 // sum_diag[1] 382 vadd.i16 q3, q3, q13 // sum_diag[1] 383 .endif 384 385 vpadd.u16 d26, d30, d31 // [(x >> 1)] 386 vmov.u16 d27, #0 387 vpadd.u16 d24, d26, d28 388 vpadd.u16 d24, d24, d28 // [y] 389 vmov.u16 r12, d24[0] 390 vadd.i16 q5, q5, q15 // sum_hv[1] 391 .if \i < 4 392 vmov.16 d8[\i], r12 // sum_hv[0] 393 .else 394 vmov.16 d9[\i-4], r12 // sum_hv[0] 395 .endif 396 397 .if \i == 0 398 vmov.u16 q6, q13 // sum_alt[0] 399 .else 400 vext.8 q12, q14, q13, #(16-2*\i) 401 vext.8 q14, q13, q14, #(16-2*\i) 402 vadd.i16 q6, q6, q12 // sum_alt[0] 403 vadd.i16 d16, d16, d28 // sum_alt[0] 404 .endif 405 vrev64.16 d26, d26 // [-(x >> 1)] 406 vmov.u16 q14, #0 407 .if \i == 0 408 vmov q7, q13 // sum_alt[1] 409 .else 410 vext.8 q12, q14, q13, #(16-2*\i) 411 vext.8 q13, q13, q14, #(16-2*\i) 412 vadd.i16 q7, q7, q12 // sum_alt[1] 413 vadd.i16 d17, d17, d26 // sum_alt[1] 414 .endif 415 416 .if \i < 6 417 vext.8 q12, q14, q15, #(16-2*(3-(\i/2))) 418 vext.8 q13, q15, q14, #(16-2*(3-(\i/2))) 419 vadd.i16 q9, q9, q12 // sum_alt[2] 420 vadd.i16 d22, d22, d26 // sum_alt[2] 421 .else 422 vadd.i16 q9, q9, q15 // sum_alt[2] 423 .endif 424 .if \i == 0 425 vmov q10, q15 // sum_alt[3] 426 .elseif \i == 1 427 vadd.i16 q10, q10, q15 // sum_alt[3] 428 .else 429 vext.8 q12, q14, q15, #(16-2*(\i/2)) 430 vext.8 q13, q15, q14, #(16-2*(\i/2)) 431 vadd.i16 q10, q10, q12 // sum_alt[3] 432 vadd.i16 d23, d23, d26 // sum_alt[3] 433 .endif 434 .endr 435 436 vmov.u32 q15, #105 437 438 vmull.s16 q12, d8, d8 // sum_hv[0]*sum_hv[0] 439 vmlal.s16 q12, d9, d9 440 vmull.s16 q13, d10, d10 // sum_hv[1]*sum_hv[1] 441 vmlal.s16 q13, d11, d11 442 vadd.s32 d8, d24, d25 443 vadd.s32 d9, d26, d27 444 vpadd.s32 d8, d8, d9 // cost[2,6] (s16, s17) 445 vmul.i32 d8, d8, d30 // cost[2,6] *= 105 446 447 vrev64.16 q1, q1 448 vrev64.16 q3, q3 449 vext.8 q1, q1, q1, #10 // sum_diag[0][14-n] 450 vext.8 q3, q3, q3, #10 // sum_diag[1][14-n] 451 452 vstr s16, [sp, #2*4] // cost[2] 453 vstr s17, [sp, #6*4] // cost[6] 454 455 movrel_local r12, div_table 456 vld1.16 {q14}, [r12, :128] 457 458 vmull.s16 q5, d0, d0 // sum_diag[0]*sum_diag[0] 459 vmull.s16 q12, d1, d1 460 vmlal.s16 q5, d2, d2 461 vmlal.s16 q12, d3, d3 462 vmull.s16 q0, d4, d4 // sum_diag[1]*sum_diag[1] 463 vmull.s16 q1, d5, d5 464 vmlal.s16 q0, d6, d6 465 vmlal.s16 q1, d7, d7 466 vmovl.u16 q13, d28 // div_table 467 vmovl.u16 q14, d29 468 vmul.i32 q5, q5, q13 // cost[0] 469 vmla.i32 q5, q12, q14 470 vmul.i32 q0, q0, q13 // cost[4] 471 vmla.i32 q0, q1, q14 472 vadd.i32 d10, d10, d11 473 vadd.i32 d0, d0, d1 474 vpadd.i32 d0, d10, d0 // cost[0,4] = s0,s1 475 476 movrel_local r12, alt_fact 477 vld1.16 {d29, d30, d31}, [r12, :64] // div_table[2*m+1] + 105 478 479 vstr s0, [sp, #0*4] // cost[0] 480 vstr s1, [sp, #4*4] // cost[4] 481 482 vmovl.u16 q13, d29 // div_table[2*m+1] + 105 483 vmovl.u16 q14, d30 484 vmovl.u16 q15, d31 485 486 cost_alt d14, d12, d13, d16, d14, d15, d17 // cost[1], cost[3] 487 cost_alt d15, d18, d19, d22, d20, d21, d23 // cost[5], cost[7] 488 vstr s28, [sp, #1*4] // cost[1] 489 vstr s29, [sp, #3*4] // cost[3] 490 491 mov r0, #0 // best_dir 492 vmov.32 r1, d0[0] // best_cost 493 mov r3, #1 // n 494 495 vstr s30, [sp, #5*4] // cost[5] 496 vstr s31, [sp, #7*4] // cost[7] 497 498 vmov.32 r12, d14[0] 499 500 find_best d14[0], d8[0], d14[1] 501 find_best d14[1], d0[1], d15[0] 502 find_best d15[0], d8[1], d15[1] 503 find_best d15[1] 504 505 eor r3, r0, #4 // best_dir ^4 506 ldr r12, [sp, r3, lsl #2] 507 sub r1, r1, r12 // best_cost - cost[best_dir ^ 4] 508 lsr r1, r1, #10 509 str r1, [r2] // *var 510 511 add sp, sp, #32 512 vpop {q4-q7} 513 pop {pc} 514 endfunc 515 .endm