1/***************************************************************************** 2 * pixel.S: arm pixel metrics 3 ***************************************************************************** 4 * Copyright (C) 2009-2021 x264 project 5 * 6 * Authors: David Conrad <lessen42@gmail.com> 7 * Janne Grunau <janne-x264@jannau.net> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. 22 * 23 * This program is also available under a commercial proprietary license. 24 * For more information, contact us at licensing@x264.com. 25 *****************************************************************************/ 26 27#include "asm.S" 28 29const mask_array, align=4 30.rept 16 31 .byte 0xff 32.endr 33mask_ff: 34.rept 16 35 .byte 0 36.endr 37endconst 38 39const mask_ac4, align=4 40.short 0, -1, -1, -1, 0, -1, -1, -1 41endconst 42const mask_ac8, align=4 43.short 0, -1, -1, -1, -1, -1, -1, -1 44endconst 45 46.text 47 48.macro SAD4_ARMV6 h 49function pixel_sad_4x\h\()_armv6 50 push {r4-r6,lr} 51 ldr r4, [r2], r3 52 ldr r5, [r0], r1 53 ldr r6, [r2], r3 54 ldr lr, [r0], r1 55 usad8 ip, r4, r5 56.rept (\h - 2)/2 57 ldr r4, [r2], r3 58 ldr r5, [r0], r1 59 usada8 ip, r6, lr, ip 60 ldr r6, [r2], r3 61 ldr lr, [r0], r1 62 usada8 ip, r4, r5, ip 63.endr 64 usada8 r0, r6, lr, ip 65 pop {r4-r6,pc} 66endfunc 67.endm 68 69SAD4_ARMV6 4 70SAD4_ARMV6 8 71 72 73.macro SAD_START_4 align:vararg 74 vld1.32 {d1[]}, [r2\align], r3 75 vld1.32 {d0[]}, [r0,:32], r1 76 vabdl.u8 q8, d0, d1 77.endm 78 79.macro SAD_4 align:vararg 80 vld1.32 {d1[]}, [r2\align], r3 81 vld1.32 {d0[]}, [r0,:32], r1 82 vabal.u8 q8, d0, d1 83.endm 84 85.macro SAD_START_8 align:vararg 86 vld1.64 {d1}, [r2\align], r3 87 vld1.64 {d0}, [r0,:64], r1 88 vabdl.u8 q8, d0, d1 89.endm 90 91.macro SAD_8 align:vararg 92 vld1.64 {d1}, [r2\align], r3 93 vld1.64 {d0}, [r0,:64], r1 94 vabal.u8 q8, d0, d1 95.endm 96 97.macro SAD_START_16 align:vararg 98 vld1.64 {d2-d3}, [r2\align], r3 99 vld1.64 {d0-d1}, [r0,:128], r1 100 vabdl.u8 q8, d0, d2 101 vld1.64 {d6-d7}, [r2\align], r3 102 vabdl.u8 q9, d1, d3 103 vld1.64 {d4-d5}, [r0,:128], r1 104.endm 105 106.macro SAD_16 align:vararg 107 vabal.u8 q8, d4, d6 108 vld1.64 {d2-d3}, [r2\align], r3 109 vabal.u8 q9, d5, d7 110 vld1.64 {d0-d1}, [r0,:128], r1 111 vabal.u8 q8, d0, d2 112 vld1.64 {d6-d7}, [r2\align], r3 113 vabal.u8 q9, d1, d3 114 vld1.64 {d4-d5}, [r0,:128], r1 115.endm 116 117.macro SAD_FUNC w, h, name, align:vararg 118function pixel_sad\name\()_\w\()x\h\()_neon 119 SAD_START_\w \align 120 121.if \w == 16 122.rept \h / 2 - 1 123 SAD_\w \align 124.endr 125.else 126.rept \h - 1 127 SAD_\w \align 128.endr 129.endif 130 131.if \w > 8 132 vabal.u8 q8, d4, d6 133 vabal.u8 q9, d5, d7 134 vadd.u16 q8, q8, q9 135.endif 136.if \w > 4 137 vadd.u16 d16, d16, d17 138.endif 139 vpadd.u16 d0, d16, d16 140 vpaddl.u16 d0, d0 141 vmov.u32 r0, d0[0] 142 bx lr 143endfunc 144.endm 145 146SAD_FUNC 4, 4 147SAD_FUNC 4, 8 148SAD_FUNC 8, 4 149SAD_FUNC 8, 8 150SAD_FUNC 8, 16 151SAD_FUNC 16, 8 152SAD_FUNC 16, 16 153 154SAD_FUNC 4, 4, _aligned, ,:32 155SAD_FUNC 4, 8, _aligned, ,:32 156SAD_FUNC 8, 4, _aligned, ,:64 157SAD_FUNC 8, 8, _aligned, ,:64 158SAD_FUNC 8, 16, _aligned, ,:64 159SAD_FUNC 16, 8, _aligned, ,:128 160SAD_FUNC 16, 16, _aligned, ,:128 161 162// If dual issue is possible, use additional accumulators to avoid 163// stalls from vadal's latency. This only matters for aligned. 164.macro SAD_DUAL_START_8 165 SAD_START_8 ,:64 166 vld1.64 {d3}, [r2,:64], r3 167 vld1.64 {d2}, [r0,:64], r1 168 vabdl.u8 q9, d2, d3 169.endm 170 171.macro SAD_DUAL_8 align:vararg 172 vld1.64 {d1}, [r2,:64], r3 173 vld1.64 {d0}, [r0,:64], r1 174 vabal.u8 q8, d0, d1 175 vld1.64 {d3}, [r2,:64], r3 176 vld1.64 {d2}, [r0,:64], r1 177 vabal.u8 q9, d2, d3 178.endm 179 180.macro SAD_DUAL_START_16 181 SAD_START_16 ,:128 182 vabdl.u8 q10, d4, d6 183 vld1.64 {d2-d3}, [r2,:128], r3 184 vabdl.u8 q11, d5, d7 185 vld1.64 {d0-d1}, [r0,:128], r1 186.endm 187 188.macro SAD_DUAL_16 189 vabal.u8 q8, d0, d2 190 vld1.64 {d6-d7}, [r2,:128], r3 191 vabal.u8 q9, d1, d3 192 vld1.64 {d4-d5}, [r0,:128], r1 193 vabal.u8 q10, d4, d6 194 vld1.64 {d2-d3}, [r2,:128], r3 195 vabal.u8 q11, d5, d7 196 vld1.64 {d0-d1}, [r0,:128], r1 197.endm 198 199.macro SAD_DUAL_END_16 200 vabal.u8 q8, d0, d2 201 vld1.64 {d6-d7}, [r2,:128], r3 202 vabal.u8 q9, d1, d3 203 vld1.64 {d4-d5}, [r0,:128], r1 204 vabal.u8 q10, d4, d6 205 vabal.u8 q11, d5, d7 206.endm 207 208.macro SAD_FUNC_DUAL w, h 209function pixel_sad_aligned_\w\()x\h\()_neon_dual 210 SAD_DUAL_START_\w 211.rept \h / 2 - \w / 8 212 SAD_DUAL_\w 213.endr 214 215.if \w > 8 216 SAD_DUAL_END_16 217 vadd.u16 q8, q8, q9 218 vadd.u16 q9, q10, q11 219.endif 220.if \w > 4 221 vadd.u16 q8, q8, q9 222 vadd.u16 d16, d16, d17 223.endif 224 vpadd.u16 d0, d16, d16 225 vpaddl.u16 d0, d0 226 vmov.u32 r0, d0[0] 227 bx lr 228endfunc 229.endm 230 231SAD_FUNC_DUAL 8, 4 232SAD_FUNC_DUAL 8, 8 233SAD_FUNC_DUAL 8, 16 234SAD_FUNC_DUAL 16, 8 235SAD_FUNC_DUAL 16, 16 236 237 238.macro SAD_X_START_4 x 239 vld1.32 {d0[]}, [r0,:32], lr 240 vld1.32 {d1[]}, [r1], r6 241 vabdl.u8 q8, d1, d0 242 vld1.32 {d2[]}, [r2], r6 243 vabdl.u8 q9, d2, d0 244 vld1.32 {d3[]}, [r3], r6 245 vabdl.u8 q10, d3, d0 246.if \x == 4 247 vld1.32 {d4[]}, [r12], r6 248 vabdl.u8 q11, d4, d0 249.endif 250.endm 251 252.macro SAD_X_4 x 253 vld1.32 {d0[]}, [r0,:32], lr 254 vld1.32 {d1[]}, [r1], r6 255 vabal.u8 q8, d1, d0 256 vld1.32 {d2[]}, [r2], r6 257 vabal.u8 q9, d2, d0 258 vld1.32 {d3[]}, [r3], r6 259 vabal.u8 q10, d3, d0 260.if \x == 4 261 vld1.32 {d4[]}, [r12], r6 262 vabal.u8 q11, d4, d0 263.endif 264.endm 265 266.macro SAD_X_START_8 x 267 vld1.64 {d0}, [r0,:64], lr 268 vld1.64 {d1}, [r1], r6 269 vabdl.u8 q8, d1, d0 270 vld1.64 {d2}, [r2], r6 271 vabdl.u8 q9, d2, d0 272 vld1.64 {d3}, [r3], r6 273 vabdl.u8 q10, d3, d0 274.if \x == 4 275 vld1.64 {d4}, [r12], r6 276 vabdl.u8 q11, d4, d0 277.endif 278.endm 279 280.macro SAD_X_8 x 281 vld1.64 {d0}, [r0,:64], lr 282 vld1.64 {d1}, [r1], r6 283 vabal.u8 q8, d1, d0 284 vld1.64 {d2}, [r2], r6 285 vabal.u8 q9, d2, d0 286 vld1.64 {d3}, [r3], r6 287 vabal.u8 q10, d3, d0 288.if \x == 4 289 vld1.64 {d4}, [r12], r6 290 vabal.u8 q11, d4, d0 291.endif 292.endm 293 294.macro SAD_X_START_16 x 295 vld1.64 {d0-d1}, [r0,:128], lr 296 vld1.64 {d2-d3}, [r1], r6 297 vabdl.u8 q8, d2, d0 298 vabdl.u8 q12, d3, d1 299 vld1.64 {d4-d5}, [r2], r6 300 vabdl.u8 q9, d4, d0 301 vabdl.u8 q13, d5, d1 302 vld1.64 {d6-d7}, [r3], r6 303 vabdl.u8 q10, d6, d0 304 vabdl.u8 q14, d7, d1 305.if \x == 4 306 vld1.64 {d2-d3}, [r12], r6 307 vabdl.u8 q11, d2, d0 308 vabdl.u8 q15, d3, d1 309.endif 310.endm 311 312.macro SAD_X_16 x 313 vld1.64 {d0-d1}, [r0,:128], lr 314 vld1.64 {d2-d3}, [r1], r6 315 vabal.u8 q8, d2, d0 316 vabal.u8 q12, d3, d1 317 vld1.64 {d4-d5}, [r2], r6 318 vabal.u8 q9, d4, d0 319 vabal.u8 q13, d5, d1 320 vld1.64 {d6-d7}, [r3], r6 321 vabal.u8 q10, d6, d0 322 vabal.u8 q14, d7, d1 323.if \x == 4 324 vld1.64 {d2-d3}, [r12], r6 325 vabal.u8 q11, d2, d0 326 vabal.u8 q15, d3, d1 327.endif 328.endm 329 330.macro SAD_X_FUNC x, w, h 331function pixel_sad_x\x\()_\w\()x\h\()_neon 332 push {r6-r7,lr} 333.if \x == 3 334 ldrd r6, r7, [sp, #12] 335.else 336 ldrd r6, r7, [sp, #16] 337 ldr r12, [sp, #12] 338.endif 339 mov lr, #FENC_STRIDE 340 341 SAD_X_START_\w \x 342.rept \h - 1 343 SAD_X_\w \x 344.endr 345 346// add up the sads 347.if \w > 8 348 vadd.u16 q8, q8, q12 349 vadd.u16 q9, q9, q13 350 vadd.u16 q10, q10, q14 351.if \x == 4 352 vadd.u16 q11, q11, q15 353.endif 354.endif 355.if \w > 4 356 vadd.u16 d16, d16, d17 357 vadd.u16 d18, d18, d19 358 vadd.u16 d20, d20, d21 359.if \x == 4 360 vadd.u16 d22, d22, d23 361.endif 362.endif 363 vpadd.u16 d0, d16, d18 364 vpadd.u16 d1, d20, d22 365 vpaddl.u16 q0, q0 366 367.if \x == 3 368 vst1.32 {d0}, [r7]! 369 vst1.32 {d1[0]}, [r7,:32] 370.else 371 vst1.32 {d0-d1}, [r7] 372.endif 373 pop {r6-r7,pc} 374endfunc 375.endm 376 377SAD_X_FUNC 3, 4, 4 378SAD_X_FUNC 3, 4, 8 379SAD_X_FUNC 3, 8, 4 380SAD_X_FUNC 3, 8, 8 381SAD_X_FUNC 3, 8, 16 382SAD_X_FUNC 3, 16, 8 383SAD_X_FUNC 3, 16, 16 384 385SAD_X_FUNC 4, 4, 4 386SAD_X_FUNC 4, 4, 8 387SAD_X_FUNC 4, 8, 4 388SAD_X_FUNC 4, 8, 8 389SAD_X_FUNC 4, 8, 16 390SAD_X_FUNC 4, 16, 8 391SAD_X_FUNC 4, 16, 16 392 393function pixel_vsad_neon 394 subs r2, r2, #2 395 vld1.8 {q0}, [r0], r1 396 vld1.8 {q1}, [r0], r1 397 vabdl.u8 q2, d0, d2 398 vabdl.u8 q3, d1, d3 399 ble 2f 4001: 401 subs r2, r2, #2 402 vld1.8 {q0}, [r0], r1 403 vabal.u8 q2, d2, d0 404 vabal.u8 q3, d3, d1 405 vld1.8 {q1}, [r0], r1 406 blt 2f 407 vabal.u8 q2, d0, d2 408 vabal.u8 q3, d1, d3 409 bgt 1b 4102: 411 vadd.u16 q0, q2, q3 412 HORIZ_ADD d0, d0, d1 413 vmov.32 r0, d0[0] 414 bx lr 415endfunc 416 417function pixel_asd8_neon 418 ldr r12, [sp, #0] 419 sub r12, r12, #2 420 vld1.8 {d0}, [r0], r1 421 vld1.8 {d1}, [r2], r3 422 vld1.8 {d2}, [r0], r1 423 vld1.8 {d3}, [r2], r3 424 vsubl.u8 q8, d0, d1 4251: 426 subs r12, r12, #2 427 vld1.8 {d4}, [r0], r1 428 vld1.8 {d5}, [r2], r3 429 vsubl.u8 q9, d2, d3 430 vsubl.u8 q10, d4, d5 431 vadd.s16 q8, q9 432 vld1.8 {d2}, [r0], r1 433 vld1.8 {d3}, [r2], r3 434 vadd.s16 q8, q10 435 bgt 1b 436 vsubl.u8 q9, d2, d3 437 vadd.s16 q8, q9 438 vpaddl.s16 q8, q8 439 vpadd.s32 d16, d16, d17 440 vpadd.s32 d16, d16, d17 441 vabs.s32 d16, d16 442 vmov.32 r0, d16[0] 443 bx lr 444endfunc 445 446 447.macro SSD_START_4 448 vld1.32 {d16[]}, [r0,:32], r1 449 vld1.32 {d17[]}, [r2,:32], r3 450 vsubl.u8 q2, d16, d17 451 vld1.32 {d16[]}, [r0,:32], r1 452 vmull.s16 q0, d4, d4 453 vld1.32 {d17[]}, [r2,:32], r3 454.endm 455 456.macro SSD_4 457 vsubl.u8 q2, d16, d17 458 vld1.32 {d16[]}, [r0,:32], r1 459 vmlal.s16 q0, d4, d4 460 vld1.32 {d17[]}, [r2,:32], r3 461.endm 462 463.macro SSD_END_4 464 vsubl.u8 q2, d16, d17 465 vmlal.s16 q0, d4, d4 466.endm 467 468.macro SSD_START_8 469 vld1.64 {d16}, [r0,:64], r1 470 vld1.64 {d17}, [r2,:64], r3 471 vsubl.u8 q2, d16, d17 472 vld1.64 {d16}, [r0,:64], r1 473 vmull.s16 q0, d4, d4 474 vmlal.s16 q0, d5, d5 475 vld1.64 {d17}, [r2,:64], r3 476.endm 477 478.macro SSD_8 479 vsubl.u8 q2, d16, d17 480 vld1.64 {d16}, [r0,:64], r1 481 vmlal.s16 q0, d4, d4 482 vmlal.s16 q0, d5, d5 483 vld1.64 {d17}, [r2,:64], r3 484.endm 485 486.macro SSD_END_8 487 vsubl.u8 q2, d16, d17 488 vmlal.s16 q0, d4, d4 489 vmlal.s16 q0, d5, d5 490.endm 491 492.macro SSD_START_16 493 vld1.64 {d16-d17}, [r0,:128], r1 494 vld1.64 {d18-d19}, [r2,:128], r3 495 vsubl.u8 q2, d16, d18 496 vsubl.u8 q3, d17, d19 497 vld1.64 {d16-d17}, [r0,:128], r1 498 vmull.s16 q0, d4, d4 499 vmlal.s16 q0, d5, d5 500 vld1.64 {d18-d19}, [r2,:128], r3 501 vmlal.s16 q0, d6, d6 502 vmlal.s16 q0, d7, d7 503.endm 504 505.macro SSD_16 506 vsubl.u8 q2, d16, d18 507 vsubl.u8 q3, d17, d19 508 vld1.64 {d16-d17}, [r0,:128], r1 509 vmlal.s16 q0, d4, d4 510 vmlal.s16 q0, d5, d5 511 vld1.64 {d18-d19}, [r2,:128], r3 512 vmlal.s16 q0, d6, d6 513 vmlal.s16 q0, d7, d7 514.endm 515 516.macro SSD_END_16 517 vsubl.u8 q2, d16, d18 518 vsubl.u8 q3, d17, d19 519 vmlal.s16 q0, d4, d4 520 vmlal.s16 q0, d5, d5 521 vmlal.s16 q0, d6, d6 522 vmlal.s16 q0, d7, d7 523.endm 524 525.macro SSD_FUNC w h 526function pixel_ssd_\w\()x\h\()_neon 527 SSD_START_\w 528.rept \h-2 529 SSD_\w 530.endr 531 SSD_END_\w 532 vadd.s32 d0, d0, d1 533 vpadd.s32 d0, d0, d0 534 vmov.32 r0, d0[0] 535 bx lr 536endfunc 537.endm 538 539SSD_FUNC 4, 4 540SSD_FUNC 4, 8 541SSD_FUNC 8, 4 542SSD_FUNC 8, 8 543SSD_FUNC 8, 16 544SSD_FUNC 16, 8 545SSD_FUNC 16, 16 546 547function pixel_ssd_nv12_core_neon 548 push {r4-r5} 549 ldrd r4, r5, [sp, #8] 550 add r12, r4, #8 551 bic r12, r12, #15 552 vmov.u64 q8, #0 553 vmov.u64 q9, #0 554 sub r1, r1, r12, lsl #1 555 sub r3, r3, r12, lsl #1 5561: 557 subs r12, r4, #16 558 vld2.8 {d0,d1}, [r0]! 559 vld2.8 {d2,d3}, [r2]! 560 vld2.8 {d4,d5}, [r0]! 561 vld2.8 {d6,d7}, [r2]! 562 563 vsubl.u8 q10, d0, d2 564 vsubl.u8 q11, d1, d3 565 vmull.s16 q14, d20, d20 566 vmull.s16 q15, d22, d22 567 vsubl.u8 q12, d4, d6 568 vsubl.u8 q13, d5, d7 569 vmlal.s16 q14, d21, d21 570 vmlal.s16 q15, d23, d23 571 572 blt 4f 573 beq 3f 5742: 575 vmlal.s16 q14, d24, d24 576 vmlal.s16 q15, d26, d26 577 vld2.8 {d0,d1}, [r0]! 578 vld2.8 {d2,d3}, [r2]! 579 vmlal.s16 q14, d25, d25 580 vmlal.s16 q15, d27, d27 581 582 subs r12, r12, #16 583 vsubl.u8 q10, d0, d2 584 vsubl.u8 q11, d1, d3 585 vmlal.s16 q14, d20, d20 586 vmlal.s16 q15, d22, d22 587 vld2.8 {d4,d5}, [r0]! 588 vld2.8 {d6,d7}, [r2]! 589 vmlal.s16 q14, d21, d21 590 vmlal.s16 q15, d23, d23 591 blt 4f 592 593 vsubl.u8 q12, d4, d6 594 vsubl.u8 q13, d5, d7 595 bgt 2b 5963: 597 vmlal.s16 q14, d24, d24 598 vmlal.s16 q15, d26, d26 599 vmlal.s16 q14, d25, d25 600 vmlal.s16 q15, d27, d27 6014: 602 subs r5, r5, #1 603 vaddw.s32 q8, q8, d28 604 vaddw.s32 q9, q9, d30 605 add r0, r0, r1 606 add r2, r2, r3 607 vaddw.s32 q8, q8, d29 608 vaddw.s32 q9, q9, d31 609 bgt 1b 610 611 vadd.u64 d16, d16, d17 612 vadd.u64 d18, d18, d19 613 ldrd r4, r5, [sp, #16] 614 vst1.64 {d16}, [r4] 615 vst1.64 {d18}, [r5] 616 617 pop {r4-r5} 618 bx lr 619endfunc 620 621.macro VAR_SQR_SUM qsqr_sum qsqr_last qsqr dsrc vpadal=vpadal.u16 622 vmull.u8 \qsqr, \dsrc, \dsrc 623 vaddw.u8 q0, q0, \dsrc 624 \vpadal \qsqr_sum, \qsqr_last 625.endm 626 627function pixel_var_8x8_neon 628 vld1.64 {d16}, [r0,:64], r1 629 vmull.u8 q1, d16, d16 630 vmovl.u8 q0, d16 631 vld1.64 {d18}, [r0,:64], r1 632 vmull.u8 q2, d18, d18 633 vaddw.u8 q0, q0, d18 634 635 vld1.64 {d20}, [r0,:64], r1 636 VAR_SQR_SUM q1, q1, q3, d20, vpaddl.u16 637 vld1.64 {d22}, [r0,:64], r1 638 VAR_SQR_SUM q2, q2, q8, d22, vpaddl.u16 639 640 vld1.64 {d24}, [r0,:64], r1 641 VAR_SQR_SUM q1, q3, q9, d24 642 vld1.64 {d26}, [r0,:64], r1 643 VAR_SQR_SUM q2, q8, q10, d26 644 vld1.64 {d24}, [r0,:64], r1 645 VAR_SQR_SUM q1, q9, q14, d24 646 vld1.64 {d26}, [r0,:64], r1 647 VAR_SQR_SUM q2, q10, q15, d26 648 b var_end 649endfunc 650 651function pixel_var_8x16_neon 652 vld1.64 {d16}, [r0,:64], r1 653 vld1.64 {d18}, [r0,:64], r1 654 vmull.u8 q1, d16, d16 655 vmovl.u8 q0, d16 656 vld1.64 {d20}, [r0,:64], r1 657 vmull.u8 q2, d18, d18 658 vaddw.u8 q0, q0, d18 659 660 mov ip, #12 661 662 vld1.64 {d22}, [r0,:64], r1 663 VAR_SQR_SUM q1, q1, q14, d20, vpaddl.u16 664 vld1.64 {d16}, [r0,:64], r1 665 VAR_SQR_SUM q2, q2, q15, d22, vpaddl.u16 666 6671: subs ip, ip, #4 668 vld1.64 {d18}, [r0,:64], r1 669 VAR_SQR_SUM q1, q14, q12, d16 670 vld1.64 {d20}, [r0,:64], r1 671 VAR_SQR_SUM q2, q15, q13, d18 672 vld1.64 {d22}, [r0,:64], r1 673 VAR_SQR_SUM q1, q12, q14, d20 674 beq 2f 675 vld1.64 {d16}, [r0,:64], r1 676 VAR_SQR_SUM q2, q13, q15, d22 677 b 1b 6782: 679 VAR_SQR_SUM q2, q13, q15, d22 680 b var_end 681endfunc 682 683function pixel_var_16x16_neon 684 vld1.64 {d16-d17}, [r0,:128], r1 685 vmull.u8 q12, d16, d16 686 vmovl.u8 q0, d16 687 vmull.u8 q13, d17, d17 688 vaddw.u8 q0, q0, d17 689 690 vld1.64 {d18-d19}, [r0,:128], r1 691 VAR_SQR_SUM q1, q12, q14, d18, vpaddl.u16 692 VAR_SQR_SUM q2, q13, q15, d19, vpaddl.u16 693 694 mov ip, #7 695var16_loop: 696 subs ip, ip, #1 697 vld1.64 {d16-d17}, [r0,:128], r1 698 VAR_SQR_SUM q1, q14, q12, d16 699 VAR_SQR_SUM q2, q15, q13, d17 700 701 vld1.64 {d18-d19}, [r0,:128], r1 702 VAR_SQR_SUM q1, q12, q14, d18 703 VAR_SQR_SUM q2, q13, q15, d19 704 bgt var16_loop 705endfunc 706 707function var_end, export=0 708 vpaddl.u16 q8, q14 709 vpaddl.u16 q9, q15 710 vadd.u32 q1, q1, q8 711 vadd.u16 d0, d0, d1 712 vadd.u32 q1, q1, q9 713 vadd.u32 q1, q1, q2 714 vpaddl.u16 d0, d0 715 vadd.u32 d2, d2, d3 716 vpadd.u32 d0, d0, d2 717 718 vmov r0, r1, d0 719 bx lr 720endfunc 721 722.macro DIFF_SUM diff1 diff2 da1 db1 da2 db2 lastdiff1 lastdiff2 acc1 acc2 723 vld1.64 {\da1}, [r0,:64]! 724 vld1.64 {\db1}, [r1,:64], r3 725.ifnb \lastdiff1 726 vadd.s16 \acc1, \acc1, \lastdiff1 727 vadd.s16 \acc2, \acc2, \lastdiff2 728.endif 729 vld1.64 {\da2}, [r0,:64]! 730 vld1.64 {\db2}, [r1,:64], r3 731 vsubl.u8 \diff1, \da1, \db1 732 vsubl.u8 \diff2, \da2, \db2 733.endm 734 735.macro SQR_ACC_DOUBLE acc1 acc2 d0 d1 d2 d3 vmlal=vmlal.s16 736 \vmlal \acc1, \d0, \d0 737 vmlal.s16 \acc1, \d1, \d1 738 \vmlal \acc2, \d2, \d2 739 vmlal.s16 \acc2, \d3, \d3 740.endm 741 742.macro SQR_ACC acc d0 d1 vmlal=vmlal.s16 743 \vmlal \acc, \d0, \d0 744 vmlal.s16 \acc, \d1, \d1 745.endm 746 747function pixel_var2_8x8_neon 748 mov r3, #16 749 DIFF_SUM q0, q10, d0, d1, d20, d21 750 DIFF_SUM q8, q11, d16, d17, d22, d23 751 SQR_ACC_DOUBLE q1, q13, d0, d1, d20, d21, vmull.s16 752 DIFF_SUM q9, q12, d18, d19, d24, d25, q8, q11, q0, q10 753 SQR_ACC_DOUBLE q2, q14, d16, d17, d22, d23, vmull.s16 754.rept 2 755 DIFF_SUM q8, q11, d16, d17, d22, d23, q9, q12, q0, q10 756 SQR_ACC_DOUBLE q1, q13, d18, d19, d24, d25 757 DIFF_SUM q9, q12, d18, d19, d24, d25, q8, q11, q0, q10 758 SQR_ACC_DOUBLE q2, q14, d16, d17, d22, d23 759.endr 760 DIFF_SUM q8, q11, d16, d17, d22, d23, q9, q12, q0, q10 761 SQR_ACC_DOUBLE q1, q13, d18, d19, d24, d25 762 vadd.s16 q0, q0, q8 763 vadd.s16 q10, q10, q11 764 SQR_ACC_DOUBLE q2, q14, d16, d17, d22, d23 765 766 vadd.s16 d0, d0, d1 767 vadd.s16 d20, d20, d21 768 vadd.s32 q1, q1, q2 769 vadd.s32 q13, q13, q14 770 vpaddl.s16 d0, d0 771 vpaddl.s16 d20, d20 772 vadd.s32 d1, d2, d3 773 vadd.s32 d26, d26, d27 774 vpadd.s32 d0, d0, d20 @ sum 775 vpadd.s32 d1, d1, d26 @ sqr 776 vmul.s32 d0, d0, d0 @ sum*sum 777 vshr.s32 d0, d0, #6 778 vsub.s32 d0, d1, d0 779 vpadd.s32 d0, d0, d0 780 781 vmov r0, r1, d0 782 vst1.32 {d1}, [r2,:64] 783 bx lr 784endfunc 785 786function pixel_var2_8x16_neon 787 mov r3, #16 788 vld1.64 {d16}, [r0,:64]! 789 vld1.64 {d17}, [r1,:64], r3 790 vld1.64 {d18}, [r0,:64]! 791 vld1.64 {d19}, [r1,:64], r3 792 vsubl.u8 q0, d16, d17 793 vsubl.u8 q3, d18, d19 794 SQR_ACC q1, d0, d1, vmull.s16 795 vld1.64 {d16}, [r0,:64]! 796 mov ip, #15 797 vld1.64 {d17}, [r1,:64], r3 798 SQR_ACC q2, d6, d7, vmull.s16 7991: subs ip, ip, #1 800 vld1.64 {d18}, [r0,:64]! 801 vsubl.u8 q10, d16, d17 802 vld1.64 {d19}, [r1,:64], r3 803 vadd.s16 q0, q0, q10 804 SQR_ACC q1, d20, d21 805 vsubl.u8 q11, d18, d19 806 beq 2f 807 vld1.64 {d16}, [r0,:64]! 808 vadd.s16 q3, q3, q11 809 vld1.64 {d17}, [r1,:64], r3 810 SQR_ACC q2, d22, d23 811 b 1b 8122: 813 vadd.s16 q3, q3, q11 814 SQR_ACC q2, d22, d23 815 816 vadd.s16 d0, d0, d1 817 vadd.s16 d6, d6, d7 818 vpaddl.s16 d0, d0 819 vpaddl.s16 d6, d6 820 vadd.s32 d2, d2, d3 821 vadd.s32 d4, d4, d5 822 vpadd.s32 d0, d0, d6 @ sum 823 vpadd.s32 d2, d2, d4 @ sqr 824 vmul.s32 d0, d0, d0 @ sum*sum 825 vshr.s32 d0, d0, #7 826 vsub.s32 d0, d2, d0 827 vpadd.s32 d0, d0, d0 828 829 vmov r0, r1, d0 830 vst1.32 {d2}, [r2,:64] 831 bx lr 832endfunc 833 834.macro LOAD_DIFF_8x4 q0 q1 q2 q3 835 vld1.32 {d1}, [r2], r3 836 vld1.32 {d0}, [r0,:64], r1 837 vsubl.u8 \q0, d0, d1 838 vld1.32 {d3}, [r2], r3 839 vld1.32 {d2}, [r0,:64], r1 840 vsubl.u8 \q1, d2, d3 841 vld1.32 {d5}, [r2], r3 842 vld1.32 {d4}, [r0,:64], r1 843 vsubl.u8 \q2, d4, d5 844 vld1.32 {d7}, [r2], r3 845 vld1.32 {d6}, [r0,:64], r1 846 vsubl.u8 \q3, d6, d7 847.endm 848 849function pixel_satd_4x4_neon 850 vld1.32 {d1[]}, [r2], r3 851 vld1.32 {d0[]}, [r0,:32], r1 852 vld1.32 {d3[]}, [r2], r3 853 vld1.32 {d2[]}, [r0,:32], r1 854 vld1.32 {d1[1]}, [r2], r3 855 vld1.32 {d0[1]}, [r0,:32], r1 856 vld1.32 {d3[1]}, [r2], r3 857 vld1.32 {d2[1]}, [r0,:32], r1 858 vsubl.u8 q0, d0, d1 859 vsubl.u8 q1, d2, d3 860 861 SUMSUB_AB q2, q3, q0, q1 862 SUMSUB_ABCD d0, d2, d1, d3, d4, d5, d6, d7 863 HADAMARD 1, sumsub, q2, q3, q0, q1 864 HADAMARD 2, amax, q0,, q2, q3 865 866 HORIZ_ADD d0, d0, d1 867 vmov.32 r0, d0[0] 868 bx lr 869endfunc 870 871function pixel_satd_4x8_neon 872 vld1.32 {d1[]}, [r2], r3 873 vld1.32 {d0[]}, [r0,:32], r1 874 vld1.32 {d3[]}, [r2], r3 875 vld1.32 {d2[]}, [r0,:32], r1 876 vld1.32 {d5[]}, [r2], r3 877 vld1.32 {d4[]}, [r0,:32], r1 878 vld1.32 {d7[]}, [r2], r3 879 vld1.32 {d6[]}, [r0,:32], r1 880 881 vld1.32 {d1[1]}, [r2], r3 882 vld1.32 {d0[1]}, [r0,:32], r1 883 vsubl.u8 q0, d0, d1 884 vld1.32 {d3[1]}, [r2], r3 885 vld1.32 {d2[1]}, [r0,:32], r1 886 vsubl.u8 q1, d2, d3 887 vld1.32 {d5[1]}, [r2], r3 888 vld1.32 {d4[1]}, [r0,:32], r1 889 vsubl.u8 q2, d4, d5 890 vld1.32 {d7[1]}, [r2], r3 891 SUMSUB_AB q8, q9, q0, q1 892 vld1.32 {d6[1]}, [r0,:32], r1 893 vsubl.u8 q3, d6, d7 894 SUMSUB_AB q10, q11, q2, q3 895 b satd_4x8_8x4_end_neon 896endfunc 897 898function pixel_satd_8x4_neon 899 vld1.64 {d1}, [r2], r3 900 vld1.64 {d0}, [r0,:64], r1 901 vsubl.u8 q0, d0, d1 902 vld1.64 {d3}, [r2], r3 903 vld1.64 {d2}, [r0,:64], r1 904 vsubl.u8 q1, d2, d3 905 vld1.64 {d5}, [r2], r3 906 vld1.64 {d4}, [r0,:64], r1 907 vsubl.u8 q2, d4, d5 908 vld1.64 {d7}, [r2], r3 909 SUMSUB_AB q8, q9, q0, q1 910 vld1.64 {d6}, [r0,:64], r1 911 vsubl.u8 q3, d6, d7 912 SUMSUB_AB q10, q11, q2, q3 913endfunc 914 915function satd_4x8_8x4_end_neon, export=0 916 vadd.s16 q0, q8, q10 917 vadd.s16 q1, q9, q11 918 vsub.s16 q2, q8, q10 919 vsub.s16 q3, q9, q11 920 921 vtrn.16 q0, q1 922 vadd.s16 q8, q0, q1 923 vtrn.16 q2, q3 924 vsub.s16 q9, q0, q1 925 vadd.s16 q10, q2, q3 926 vsub.s16 q11, q2, q3 927 vtrn.32 q8, q10 928 vabs.s16 q8, q8 929 vtrn.32 q9, q11 930 vabs.s16 q10, q10 931 vabs.s16 q9, q9 932 vabs.s16 q11, q11 933 vmax.u16 q0, q8, q10 934 vmax.u16 q1, q9, q11 935 936 vadd.u16 q0, q0, q1 937 HORIZ_ADD d0, d0, d1 938 vmov.32 r0, d0[0] 939 bx lr 940endfunc 941 942function pixel_satd_8x8_neon 943 mov ip, lr 944 945 bl satd_8x8_neon 946 vadd.u16 q0, q12, q13 947 vadd.u16 q1, q14, q15 948 949 vadd.u16 q0, q0, q1 950 HORIZ_ADD d0, d0, d1 951 mov lr, ip 952 vmov.32 r0, d0[0] 953 bx lr 954endfunc 955 956function pixel_satd_8x16_neon 957 vpush {d8-d11} 958 mov ip, lr 959 960 bl satd_8x8_neon 961 vadd.u16 q4, q12, q13 962 vadd.u16 q5, q14, q15 963 964 bl satd_8x8_neon 965 vadd.u16 q4, q4, q12 966 vadd.u16 q5, q5, q13 967 vadd.u16 q4, q4, q14 968 vadd.u16 q5, q5, q15 969 970 vadd.u16 q0, q4, q5 971 HORIZ_ADD d0, d0, d1 972 vpop {d8-d11} 973 mov lr, ip 974 vmov.32 r0, d0[0] 975 bx lr 976endfunc 977 978function satd_8x8_neon, export=0 979 LOAD_DIFF_8x4 q8, q9, q10, q11 980 vld1.64 {d7}, [r2], r3 981 SUMSUB_AB q0, q1, q8, q9 982 vld1.64 {d6}, [r0,:64], r1 983 vsubl.u8 q12, d6, d7 984 vld1.64 {d17}, [r2], r3 985 SUMSUB_AB q2, q3, q10, q11 986 vld1.64 {d16}, [r0,:64], r1 987 vsubl.u8 q13, d16, d17 988 vld1.64 {d19}, [r2], r3 989 SUMSUB_AB q8, q10, q0, q2 990 vld1.64 {d18}, [r0,:64], r1 991 vsubl.u8 q14, d18, d19 992 vld1.64 {d1}, [r2], r3 993 SUMSUB_AB q9, q11, q1, q3 994 vld1.64 {d0}, [r0,:64], r1 995 vsubl.u8 q15, d0, d1 996endfunc 997 998// one vertical hadamard pass and two horizontal 999function satd_8x4v_8x8h_neon, export=0 1000 SUMSUB_ABCD q0, q1, q2, q3, q12, q13, q14, q15 1001 vtrn.16 q8, q9 1002 SUMSUB_AB q12, q14, q0, q2 1003 vtrn.16 q10, q11 1004 SUMSUB_AB q13, q15, q1, q3 1005 SUMSUB_AB q0, q1, q8, q9 1006 vtrn.16 q12, q13 1007 SUMSUB_AB q2, q3, q10, q11 1008 vtrn.16 q14, q15 1009 SUMSUB_AB q8, q9, q12, q13 1010 vtrn.32 q0, q2 1011 SUMSUB_AB q10, q11, q14, q15 1012 1013 vtrn.32 q1, q3 1014 ABS2 q0, q2 1015 vtrn.32 q8, q10 1016 ABS2 q1, q3 1017 vtrn.32 q9, q11 1018 ABS2 q8, q10 1019 ABS2 q9, q11 1020 vmax.s16 q12, q0, q2 1021 vmax.s16 q13, q1, q3 1022 vmax.s16 q14, q8, q10 1023 vmax.s16 q15, q9, q11 1024 bx lr 1025endfunc 1026 1027function pixel_satd_16x8_neon 1028 vpush {d8-d11} 1029 mov ip, lr 1030 1031 bl satd_16x4_neon 1032 vadd.u16 q4, q12, q13 1033 vadd.u16 q5, q14, q15 1034 1035 bl satd_16x4_neon 1036 vadd.u16 q4, q4, q12 1037 vadd.u16 q5, q5, q13 1038 vadd.u16 q4, q4, q14 1039 vadd.u16 q5, q5, q15 1040 1041 vadd.u16 q0, q4, q5 1042 HORIZ_ADD d0, d0, d1 1043 vpop {d8-d11} 1044 mov lr, ip 1045 vmov.32 r0, d0[0] 1046 bx lr 1047endfunc 1048 1049function pixel_satd_16x16_neon 1050 vpush {d8-d11} 1051 mov ip, lr 1052 1053 bl satd_16x4_neon 1054 vadd.u16 q4, q12, q13 1055 vadd.u16 q5, q14, q15 1056 1057 bl satd_16x4_neon 1058 vadd.u16 q4, q4, q12 1059 vadd.u16 q5, q5, q13 1060 vadd.u16 q4, q4, q14 1061 vadd.u16 q5, q5, q15 1062 1063 bl satd_16x4_neon 1064 vadd.u16 q4, q4, q12 1065 vadd.u16 q5, q5, q13 1066 vadd.u16 q4, q4, q14 1067 vadd.u16 q5, q5, q15 1068 1069 bl satd_16x4_neon 1070 vadd.u16 q4, q4, q12 1071 vadd.u16 q5, q5, q13 1072 vadd.u16 q4, q4, q14 1073 vadd.u16 q5, q5, q15 1074 1075 vadd.u16 q0, q4, q5 1076 HORIZ_ADD d0, d0, d1 1077 vpop {d8-d11} 1078 mov lr, ip 1079 vmov.32 r0, d0[0] 1080 bx lr 1081endfunc 1082 1083function satd_16x4_neon, export=0 1084 vld1.64 {d2-d3}, [r2], r3 1085 vld1.64 {d0-d1}, [r0,:128], r1 1086 vsubl.u8 q8, d0, d2 1087 vld1.64 {d6-d7}, [r2], r3 1088 vsubl.u8 q12, d1, d3 1089 vld1.64 {d4-d5}, [r0,:128], r1 1090 vsubl.u8 q9, d4, d6 1091 vld1.64 {d2-d3}, [r2], r3 1092 vsubl.u8 q13, d5, d7 1093 vld1.64 {d0-d1}, [r0,:128], r1 1094 vsubl.u8 q10, d0, d2 1095 vld1.64 {d6-d7}, [r2], r3 1096 vsubl.u8 q14, d1, d3 1097 vadd.s16 q0, q8, q9 1098 vld1.64 {d4-d5}, [r0,:128], r1 1099 vsub.s16 q1, q8, q9 1100 vsubl.u8 q11, d4, d6 1101 vsubl.u8 q15, d5, d7 1102 SUMSUB_AB q2, q3, q10, q11 1103 SUMSUB_ABCD q8, q10, q9, q11, q0, q2, q1, q3 1104 b satd_8x4v_8x8h_neon 1105endfunc 1106 1107 1108function pixel_sa8d_8x8_neon 1109 mov ip, lr 1110 bl sa8d_8x8_neon 1111 vadd.u16 q0, q8, q9 1112 HORIZ_ADD d0, d0, d1 1113 mov lr, ip 1114 vmov.32 r0, d0[0] 1115 add r0, r0, #1 1116 lsr r0, r0, #1 1117 bx lr 1118endfunc 1119 1120function pixel_sa8d_16x16_neon 1121 vpush {d8-d11} 1122 mov ip, lr 1123 bl sa8d_8x8_neon 1124 vpaddl.u16 q4, q8 1125 vpaddl.u16 q5, q9 1126 bl sa8d_8x8_neon 1127 vpadal.u16 q4, q8 1128 vpadal.u16 q5, q9 1129 sub r0, r0, r1, lsl #4 1130 sub r2, r2, r3, lsl #4 1131 add r0, r0, #8 1132 add r2, r2, #8 1133 bl sa8d_8x8_neon 1134 vpadal.u16 q4, q8 1135 vpadal.u16 q5, q9 1136 bl sa8d_8x8_neon 1137 vpaddl.u16 q8, q8 1138 vpaddl.u16 q9, q9 1139 vadd.u32 q0, q4, q8 1140 vadd.u32 q1, q5, q9 1141 vadd.u32 q0, q0, q1 1142 vadd.u32 d0, d0, d1 1143 vpadd.u32 d0, d0, d0 1144 vpop {d8-d11} 1145 mov lr, ip 1146 vmov.32 r0, d0[0] 1147 add r0, r0, #1 1148 lsr r0, r0, #1 1149 bx lr 1150endfunc 1151 1152.macro HADAMARD4_V r1, r2, r3, r4, t1, t2, t3, t4 1153 SUMSUB_ABCD \t1, \t2, \t3, \t4, \r1, \r2, \r3, \r4 1154 SUMSUB_ABCD \r1, \r3, \r2, \r4, \t1, \t3, \t2, \t4 1155.endm 1156 1157.macro integrated_satd dst, s0, s1, s2, s3 1158 vmov q0, \s0 1159 vmov q1, \s1 1160 vmov q2, \s2 1161 vmov q3, \s3 1162 1163 vtrn.16 q0, q1 1164 vtrn.16 q2, q3 1165 1166 SUMSUB_AB q6, q7, q0, q1 1167 SUMSUB_AB q0, q1, q2, q3 1168 1169 vtrn.32 q6, q0 1170 vtrn.32 q7, q1 1171 1172 vabs.s16 q6, q6 1173 vabs.s16 q0, q0 1174 vabs.s16 q7, q7 1175 vabs.s16 q1, q1 1176 1177 vmax.u16 q6, q6, q0 1178 vmax.u16 q7, q7, q1 1179 1180 vadd.i16 q6, q6, q7 1181 vpadal.u16 \dst, q6 1182.endm 1183 1184.macro sa8d_satd_8x8 satd= 1185function sa8d_\satd\()8x8_neon, export=0 1186 LOAD_DIFF_8x4 q8, q9, q10, q11 1187 vld1.64 {d7}, [r2], r3 1188 SUMSUB_AB q0, q1, q8, q9 1189 vld1.64 {d6}, [r0,:64], r1 1190 vsubl.u8 q12, d6, d7 1191 vld1.64 {d17}, [r2], r3 1192 SUMSUB_AB q2, q3, q10, q11 1193 vld1.64 {d16}, [r0,:64], r1 1194 vsubl.u8 q13, d16, d17 1195 vld1.64 {d19}, [r2], r3 1196 SUMSUB_AB q8, q10, q0, q2 1197 vld1.64 {d18}, [r0,:64], r1 1198 vsubl.u8 q14, d18, d19 1199 vld1.64 {d1}, [r2], r3 1200 SUMSUB_AB q9, q11, q1, q3 1201 vld1.64 {d0}, [r0,:64], r1 1202 vsubl.u8 q15, d0, d1 1203 1204 HADAMARD4_V q12, q13, q14, q15, q0, q1, q2, q3 1205 1206.ifc \satd, satd_ 1207 integrated_satd q4, q8, q9, q10, q11 1208 integrated_satd q4, q12, q13, q14, q15 1209.endif 1210 1211 SUMSUB_ABCD q0, q8, q1, q9, q8, q12, q9, q13 1212 SUMSUB_AB q2, q10, q10, q14 1213 vtrn.16 q8, q9 1214 SUMSUB_AB q3, q11, q11, q15 1215 vtrn.16 q0, q1 1216 SUMSUB_AB q12, q13, q8, q9 1217 vtrn.16 q10, q11 1218 SUMSUB_AB q8, q9, q0, q1 1219 vtrn.16 q2, q3 1220 SUMSUB_AB q14, q15, q10, q11 1221 vadd.i16 q10, q2, q3 1222 vtrn.32 q12, q14 1223 vsub.i16 q11, q2, q3 1224 vtrn.32 q13, q15 1225 SUMSUB_AB q0, q2, q12, q14 1226 vtrn.32 q8, q10 1227 SUMSUB_AB q1, q3, q13, q15 1228 vtrn.32 q9, q11 1229 SUMSUB_AB q12, q14, q8, q10 1230 SUMSUB_AB q13, q15, q9, q11 1231 1232 vswp d1, d24 1233 ABS2 q0, q12 1234 vswp d3, d26 1235 ABS2 q1, q13 1236 vswp d5, d28 1237 ABS2 q2, q14 1238 vswp d7, d30 1239 ABS2 q3, q15 1240 vmax.s16 q8, q0, q12 1241 vmax.s16 q9, q1, q13 1242 vmax.s16 q10, q2, q14 1243 vmax.s16 q11, q3, q15 1244 vadd.i16 q8, q8, q9 1245 vadd.i16 q9, q10, q11 1246.ifc \satd, satd_ 1247 vpadal.u16 q5, q8 1248 vpadal.u16 q5, q9 1249.endif 1250 bx lr 1251endfunc 1252.endm 1253 1254sa8d_satd_8x8 1255sa8d_satd_8x8 satd_ 1256 1257function pixel_sa8d_satd_16x16_neon 1258 push {lr} 1259 vpush {q4-q7} 1260 vmov.u32 q4, #0 1261 vmov.u32 q5, #0 1262 bl sa8d_satd_8x8_neon 1263 bl sa8d_satd_8x8_neon 1264 sub r0, r0, r1, lsl #4 1265 sub r2, r2, r3, lsl #4 1266 add r0, r0, #8 1267 add r2, r2, #8 1268 bl sa8d_satd_8x8_neon 1269 bl sa8d_satd_8x8_neon 1270 vadd.u32 d1, d10, d11 1271 vadd.u32 d0, d8, d9 1272 vpadd.u32 d1, d1, d1 1273 vpadd.u32 d0, d0, d0 1274 vrshr.u32 d1, d1, #1 1275 vmov.32 r1, d0[0] 1276 vmov.32 r0, d1[0] 1277 vpop {q4-q7} 1278 pop {pc} 1279endfunc 1280 1281 1282.macro HADAMARD_AC w h 1283function pixel_hadamard_ac_\w\()x\h\()_neon 1284 vpush {d8-d15} 1285 movrel ip, mask_ac4 1286 vmov.i8 q4, #0 1287 // note: this assumes mask_ac8 is after mask_ac4 (so don't move it) 1288 vld1.64 {d12-d15}, [ip,:128] 1289 vmov.i8 q5, #0 1290 1291 mov ip, lr 1292 bl hadamard_ac_8x8_neon 1293.if \h > 8 1294 bl hadamard_ac_8x8_neon 1295.endif 1296.if \w > 8 1297 sub r0, r0, r1, lsl #3 1298 add r0, r0, #8 1299 bl hadamard_ac_8x8_neon 1300.endif 1301.if \w * \h == 256 1302 sub r0, r0, r1, lsl #4 1303 bl hadamard_ac_8x8_neon 1304.endif 1305 1306 vadd.s32 d8, d8, d9 1307 vadd.s32 d10, d10, d11 1308 vpadd.s32 d0, d8, d10 1309 vpop {d8-d15} 1310 mov lr, ip 1311 vmov r0, r1, d0 1312 lsr r0, r0, #1 1313 lsr r1, r1, #2 1314 bx lr 1315endfunc 1316.endm 1317 1318HADAMARD_AC 8, 8 1319HADAMARD_AC 8, 16 1320HADAMARD_AC 16, 8 1321HADAMARD_AC 16, 16 1322 1323// q4: satd q5: sa8d q6: mask_ac4 q7: mask_ac8 1324function hadamard_ac_8x8_neon, export=0 1325 vld1.64 {d2}, [r0,:64], r1 1326 vld1.64 {d3}, [r0,:64], r1 1327 vaddl.u8 q0, d2, d3 1328 vld1.64 {d6}, [r0,:64], r1 1329 vsubl.u8 q1, d2, d3 1330 vld1.64 {d7}, [r0,:64], r1 1331 vaddl.u8 q2, d6, d7 1332 vld1.64 {d18}, [r0,:64], r1 1333 vsubl.u8 q3, d6, d7 1334 vld1.64 {d19}, [r0,:64], r1 1335 vaddl.u8 q8, d18, d19 1336 vld1.64 {d22}, [r0,:64], r1 1337 vsubl.u8 q9, d18, d19 1338 vld1.64 {d23}, [r0,:64], r1 1339 1340 SUMSUB_ABCD q12, q14, q13, q15, q0, q2, q1, q3 1341 vaddl.u8 q10, d22, d23 1342 vsubl.u8 q11, d22, d23 1343 vtrn.16 q12, q13 1344 SUMSUB_ABCD q0, q2, q1, q3, q8, q10, q9, q11 1345 1346 vtrn.16 q14, q15 1347 SUMSUB_AB q8, q9, q12, q13 1348 vtrn.16 q0, q1 1349 SUMSUB_AB q10, q11, q14, q15 1350 vtrn.16 q2, q3 1351 SUMSUB_AB q12, q13, q0, q1 1352 vtrn.32 q8, q10 1353 SUMSUB_AB q14, q15, q2, q3 1354 vtrn.32 q9, q11 1355 SUMSUB_AB q0, q2, q8, q10 1356 vtrn.32 q12, q14 1357 SUMSUB_AB q1, q3, q9, q11 1358 vtrn.32 q13, q15 1359 SUMSUB_ABCD q8, q10, q9, q11, q12, q14, q13, q15 1360 1361 vabs.s16 q12, q0 1362 vabs.s16 q13, q8 1363 vabs.s16 q15, q1 1364 vadd.s16 q12, q12, q13 1365 vabs.s16 q14, q2 1366 vand.s16 q12, q12, q6 1367 vabs.s16 q13, q3 1368 vadd.s16 q12, q12, q15 1369 vabs.s16 q15, q9 1370 vadd.s16 q12, q12, q14 1371 vabs.s16 q14, q10 1372 vadd.s16 q12, q12, q13 1373 vabs.s16 q13, q11 1374 vadd.s16 q12, q12, q15 1375 vsub.s16 q15, q11, q3 1376 vadd.s16 q12, q12, q14 1377 vadd.s16 q14, q11, q3 1378 vadd.s16 q12, q12, q13 1379 vsub.s16 q13, q10, q2 1380 vadd.s16 q2, q10, q2 1381 vpadal.u16 q4, q12 1382 1383 SUMSUB_AB q10, q11, q9, q1 1384 SUMSUB_AB q9, q8, q0, q8 1385 vswp d29, d30 1386 vabs.s16 q14, q14 1387 vabs.s16 q15, q15 1388 vswp d5, d26 1389 vabs.s16 q2, q2 1390 vabs.s16 q13, q13 1391 vswp d21, d22 1392 vabs.s16 q10, q10 1393 vabs.s16 q11, q11 1394 vmax.s16 q3, q14, q15 1395 vmax.s16 q2, q2, q13 1396 vmax.s16 q1, q10, q11 1397 vswp d19, d16 1398 SUMSUB_AB q14, q15, q9, q8 1399 1400 vadd.s16 q2, q2, q3 1401 vadd.s16 q2, q2, q1 1402 vand q14, q14, q7 1403 vadd.s16 q2, q2, q2 1404 vabs.s16 q15, q15 1405 vabs.s16 q14, q14 1406 vadd.s16 q2, q2, q15 1407 vadd.s16 q2, q2, q14 1408 vpadal.u16 q5, q2 1409 bx lr 1410endfunc 1411 1412 1413.macro SSIM_ITER n ssa s12 ssb lastssa lasts12 lastssb da db dnext 1414 vld1.64 {\db}, [r2], r3 1415 vmull.u8 \ssa, \da, \da 1416 vmull.u8 \s12, \da, \db 1417.if \n == 1 1418 vpaddl.u16 q2, \lastssa 1419 vpaddl.u16 q3, \lasts12 1420 vaddl.u8 q0, d0, \da 1421.else 1422 vpadal.u16 q2, \lastssa 1423 vpadal.u16 q3, \lasts12 1424 vaddw.u8 q0, q0, \da 1425.endif 1426 vpadal.u16 q2, \lastssb 1427.if \n < 3 1428 vld1.64 {\dnext}, [r0], r1 1429.endif 1430.if \n == 1 1431 vaddl.u8 q1, d2, \db 1432.else 1433 vaddw.u8 q1, q1, \db 1434.endif 1435 vmull.u8 \ssb, \db, \db 1436.endm 1437 1438function pixel_ssim_4x4x2_core_neon 1439 ldr ip, [sp] 1440 vld1.64 {d0}, [r0], r1 1441 vld1.64 {d2}, [r2], r3 1442 vmull.u8 q2, d0, d0 1443 vmull.u8 q3, d0, d2 1444 vld1.64 {d28}, [r0], r1 1445 vmull.u8 q15, d2, d2 1446 1447 SSIM_ITER 1, q8, q9, q14, q2, q3, q15, d28, d29, d26 1448 SSIM_ITER 2, q10,q11,q13, q8, q9, q14, d26, d27, d28 1449 SSIM_ITER 3, q8, q9, q15, q10,q11,q13, d28, d29 1450 1451 vpadal.u16 q2, q8 1452 vpaddl.u16 q0, q0 1453 vpaddl.u16 q1, q1 1454 vpadal.u16 q2, q15 1455 vpadal.u16 q3, q9 1456 1457 vpadd.u32 d0, d0, d1 1458 vpadd.u32 d1, d2, d3 1459 vpadd.u32 d2, d4, d5 1460 vpadd.u32 d3, d6, d7 1461 1462 vst4.32 {d0-d3}, [ip] 1463 bx lr 1464endfunc 1465 1466// FIXME: see about doing 16x16 -> 32 bit multiplies for s1/s2 1467function pixel_ssim_end4_neon 1468 vld1.32 {d16-d19}, [r0,:128]! 1469 vld1.32 {d20-d23}, [r1,:128]! 1470 vadd.s32 q0, q8, q10 1471 vadd.s32 q1, q9, q11 1472 vld1.32 {d24-d27}, [r0,:128]! 1473 vadd.s32 q0, q0, q1 1474 vld1.32 {d28-d31}, [r1,:128]! 1475 vadd.s32 q2, q12, q14 1476 vadd.s32 q3, q13, q15 1477 vld1.32 {d16-d17}, [r0,:128] 1478 vadd.s32 q1, q1, q2 1479 vld1.32 {d18-d19}, [r1,:128] 1480 vadd.s32 q8, q8, q9 1481 vadd.s32 q2, q2, q3 1482 vadd.s32 q3, q3, q8 1483 1484 vtrn.32 q0, q1 1485 vtrn.32 q2, q3 1486 vswp d1, d4 1487 vswp d3, d6 1488 1489// s1=q0, s2=q1, ss=q2, s12=q3 1490 vmul.s32 q8, q0, q1 // s1*s2 1491 vmul.s32 q0, q0, q0 1492 vmla.s32 q0, q1, q1 // s1*s1 + s2*s2 1493 1494 vshl.s32 q3, q3, #7 1495 vshl.s32 q2, q2, #6 1496 vadd.s32 q1, q8, q8 1497 1498 mov r3, #416 // ssim_c1 = .01*.01*255*255*64 1499 movconst ip, 235963 // ssim_c2 = .03*.03*255*255*64*63 1500 vdup.32 q14, r3 1501 vdup.32 q15, ip 1502 1503 vsub.s32 q2, q2, q0 // vars 1504 vsub.s32 q3, q3, q1 // covar*2 1505 vadd.s32 q0, q0, q14 1506 vadd.s32 q2, q2, q15 1507 vadd.s32 q1, q1, q14 1508 vadd.s32 q3, q3, q15 1509 1510 vcvt.f32.s32 q0, q0 1511 vcvt.f32.s32 q2, q2 1512 vcvt.f32.s32 q1, q1 1513 vcvt.f32.s32 q3, q3 1514 1515 vmul.f32 q0, q0, q2 1516 vmul.f32 q1, q1, q3 1517 1518 cmp r2, #4 1519 1520 vdiv.f32 s0, s4, s0 1521 vdiv.f32 s1, s5, s1 1522 vdiv.f32 s2, s6, s2 1523 vdiv.f32 s3, s7, s3 1524 1525 beq ssim_skip 1526 movrel r3, mask_ff 1527 sub r3, r3, r2, lsl #2 1528 vld1.64 {d6-d7}, [r3] 1529 vand q0, q0, q3 1530ssim_skip: 1531 vadd.f32 d0, d0, d1 1532 vpadd.f32 d0, d0, d0 1533 vmov.32 r0, d0[0] 1534 bx lr 1535endfunc 1536