1/***************************************************************************** 2 * mc.S: arm motion compensation 3 ***************************************************************************** 4 * Copyright (C) 2009-2021 x264 project 5 * 6 * Authors: David Conrad <lessen42@gmail.com> 7 * Mans Rullgard <mans@mansr.com> 8 * Stefan Groenroos <stefan.gronroos@gmail.com> 9 * Janne Grunau <janne-x264@jannau.net> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. 24 * 25 * This program is also available under a commercial proprietary license. 26 * For more information, contact us at licensing@x264.com. 27 *****************************************************************************/ 28 29#include "asm.S" 30 31const pw_0to15, align=4 32.short 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 33endconst 34 35.text 36 37// note: prefetch stuff assumes 64-byte cacheline, true for the Cortex-A8 38// They also use nothing above armv5te, but we don't care about pre-armv6 39 40// void prefetch_ref( uint8_t *pix, intptr_t stride, int parity ) 41function prefetch_ref_arm 42 sub r2, r2, #1 43 add r0, r0, #64 44 and r2, r2, r1 45 add r0, r0, r2, lsl #3 46 add r2, r1, r1, lsl #1 47 pld [r0] 48 pld [r0, r1] 49 pld [r0, r1, lsl #1] 50 add r3, r0, r1, lsl #2 51 pld [r0, r2] 52 pld [r3] 53 pld [r3, r1] 54 pld [r3, r1, lsl #1] 55 pld [r3, r2] 56 bx lr 57endfunc 58 59// void prefetch_fenc( uint8_t *pix_y, intptr_t stride_y, 60// uint8_t *pix_uv, intptr_t stride_uv, int mb_x ) 61function prefetch_fenc_arm 62 ldr ip, [sp] 63 push {lr} 64 and lr, ip, #3 65 smulbb lr, lr, r1 // note: this assumes stride_y is <= 16 bits signed 66 and ip, ip, #6 67 smulbb ip, ip, r3 68 add r0, r0, #64 69 add r2, r2, #64 70 add r0, r0, lr, lsl #2 71 pld [r0] 72 add lr, r0, r1, lsl #1 73 pld [r0, r1] 74 pld [lr] 75 add r2, r2, ip, lsl #2 76 pld [lr, r1] 77 pld [r2] 78 add ip, r2, r3, lsl #1 79 pld [r2, r3] 80 pld [ip] 81 pld [ip, r3] 82 pop {pc} 83endfunc 84 85 86// void *memcpy_aligned( void *dst, const void *src, size_t n ) 87function memcpy_aligned_neon 88 orr r3, r0, r1, lsr #1 89 movrel ip, memcpy_table 90 and r3, r3, #0xc 91 ldr pc, [ip, r3] 92endfunc 93 94.macro MEMCPY_ALIGNED srcalign dstalign 95function memcpy_aligned_\dstalign\()_\srcalign\()_neon, export=0 96 mov r3, r0 97.if \srcalign == 8 && \dstalign == 8 98 sub r2, #16 99 vld1.64 {d0}, [r1,:64]! 100 vst1.64 {d0}, [r3,:64]! 101 .set r1align, 128 102 .set r3align, 128 103.else 104 .set r1align, \srcalign * 8 105 .set r3align, \dstalign * 8 106.endif 107 tst r2, #16 108 beq 32f 109 sub r2, #16 110 vld1.64 {d0-d1}, [r1,:r1align]! 111 vst1.64 {d0-d1}, [r3,:r3align]! 11232: // n is a multiple of 32 113 tst r2, #32 114 beq 640f 115 sub r2, #32 116 vld1.64 {d0-d3}, [r1,:r1align]! 117 vst1.64 {d0-d3}, [r3,:r3align]! 118640: // n is a multiple of 64 119 cmp r2, #0 120 beq 1f 12164: 122 subs r2, #64 123 vld1.64 {d0-d3}, [r1,:r1align]! 124 vld1.64 {d4-d7}, [r1,:r1align]! 125 vst1.64 {d0-d3}, [r3,:r3align]! 126 vst1.64 {d4-d7}, [r3,:r3align]! 127 bgt 64b 1281: // end 129.if \srcalign == 8 && \dstalign == 8 130 vld1.64 {d0}, [r1,:64]! 131 vst1.64 {d0}, [r3,:64]! 132.endif 133 bx lr 134endfunc 135.endm 136 137MEMCPY_ALIGNED 16, 16 138MEMCPY_ALIGNED 16, 8 139MEMCPY_ALIGNED 8, 16 140MEMCPY_ALIGNED 8, 8 141 142const memcpy_table, align=2, relocate=1 143.word memcpy_aligned_16_16_neon 144.word memcpy_aligned_16_8_neon 145.word memcpy_aligned_8_16_neon 146.word memcpy_aligned_8_8_neon 147endconst 148 149.text 150 151.ltorg 152 153// void memzero_aligned( void *dst, size_t n ) 154function memzero_aligned_neon 155 vmov.i8 q0, #0 156 vmov.i8 q1, #0 157memzero_loop: 158 subs r1, #128 159.rept 4 160 vst1.64 {d0-d3}, [r0,:128]! 161.endr 162 bgt memzero_loop 163 bx lr 164endfunc 165 166 167// void pixel_avg( uint8_t *dst, intptr_t dst_stride, 168// uint8_t *src1, intptr_t src1_stride, 169// uint8_t *src2, intptr_t src2_stride, int weight ); 170.macro AVGH w h 171function pixel_avg_\w\()x\h\()_neon 172 ldr ip, [sp, #8] 173 push {r4-r6,lr} 174 cmp ip, #32 175 ldrd r4, r5, [sp, #16] 176 mov lr, #\h 177 beq pixel_avg_w\w\()_neon 178 rsbs r6, ip, #64 179 blt pixel_avg_weight_w\w\()_add_sub_neon // weight > 64 180 cmp ip, #0 181 bge pixel_avg_weight_w\w\()_add_add_neon 182 b pixel_avg_weight_w\w\()_sub_add_neon // weight < 0 183endfunc 184.endm 185 186AVGH 4, 2 187AVGH 4, 4 188AVGH 4, 8 189AVGH 4, 16 190AVGH 8, 4 191AVGH 8, 8 192AVGH 8, 16 193AVGH 16, 8 194AVGH 16, 16 195 196// 0 < weight < 64 197.macro load_weights_add_add 198 vdup.8 d30, ip 199 vdup.8 d31, r6 200.endm 201 202.macro load_add_add d1 d2 203 vld1.32 {\d1}, [r2], r3 204 vld1.32 {\d2}, [r4], r5 205.endm 206 207.macro weight_add_add dst s1 s2 208 vmull.u8 \dst, \s1, d30 209 vmlal.u8 \dst, \s2, d31 210.endm 211 212// weight > 64 213.macro load_weights_add_sub 214 rsb r6, #0 215 vdup.8 d30, ip 216 vdup.8 d31, r6 217.endm 218 219.macro load_add_sub d1 d2 220 vld1.32 {\d1}, [r2], r3 221 vld1.32 {\d2}, [r4], r5 222.endm 223 224.macro weight_add_sub dst s1 s2 225 vmull.u8 \dst, \s1, d30 226 vmlsl.u8 \dst, \s2, d31 227.endm 228 229// weight < 0 230.macro load_weights_sub_add 231 rsb ip, #0 232 vdup.8 d31, r6 233 vdup.8 d30, ip 234.endm 235 236.macro load_sub_add d1 d2 237 vld1.32 {\d2}, [r4], r5 238 vld1.32 {\d1}, [r2], r3 239.endm 240 241.macro weight_sub_add dst s1 s2 242 vmull.u8 \dst, \s2, d31 243 vmlsl.u8 \dst, \s1, d30 244.endm 245 246.macro AVG_WEIGHT ext 247function pixel_avg_weight_w4_\ext\()_neon, export=0 248 load_weights_\ext 2491: // height loop 250 subs lr, lr, #2 251 load_\ext d0[], d1[] 252 weight_\ext q8, d0, d1 253 load_\ext d2[], d3[] 254 vqrshrun.s16 d0, q8, #6 255 weight_\ext q9, d2, d3 256 vst1.32 {d0[0]}, [r0,:32], r1 257 vqrshrun.s16 d1, q9, #6 258 vst1.32 {d1[0]}, [r0,:32], r1 259 bgt 1b 260 pop {r4-r6,pc} 261endfunc 262 263function pixel_avg_weight_w8_\ext\()_neon, export=0 264 load_weights_\ext 2651: // height loop 266 subs lr, lr, #4 267 load_\ext d0, d1 268 weight_\ext q8, d0, d1 269 load_\ext d2, d3 270 weight_\ext q9, d2, d3 271 load_\ext d4, d5 272 weight_\ext q10, d4, d5 273 load_\ext d6, d7 274 weight_\ext q11, d6, d7 275 vqrshrun.s16 d0, q8, #6 276 vqrshrun.s16 d1, q9, #6 277 vqrshrun.s16 d2, q10, #6 278 vqrshrun.s16 d3, q11, #6 279 vst1.64 {d0}, [r0,:64], r1 280 vst1.64 {d1}, [r0,:64], r1 281 vst1.64 {d2}, [r0,:64], r1 282 vst1.64 {d3}, [r0,:64], r1 283 bgt 1b 284 pop {r4-r6,pc} 285endfunc 286 287function pixel_avg_weight_w16_\ext\()_neon, export=0 288 load_weights_\ext 2891: // height loop 290 subs lr, lr, #2 291 load_\ext d0-d1, d2-d3 292 weight_\ext q8, d0, d2 293 weight_\ext q9, d1, d3 294 load_\ext d4-d5, d6-d7 295 weight_\ext q10, d4, d6 296 weight_\ext q11, d5, d7 297 vqrshrun.s16 d0, q8, #6 298 vqrshrun.s16 d1, q9, #6 299 vqrshrun.s16 d2, q10, #6 300 vqrshrun.s16 d3, q11, #6 301 vst1.64 {d0-d1}, [r0,:128], r1 302 vst1.64 {d2-d3}, [r0,:128], r1 303 bgt 1b 304 pop {r4-r6,pc} 305endfunc 306.endm 307 308AVG_WEIGHT add_add 309AVG_WEIGHT add_sub 310AVG_WEIGHT sub_add 311 312function pixel_avg_w4_neon, export=0 313 subs lr, lr, #2 314 vld1.32 {d0[]}, [r2], r3 315 vld1.32 {d2[]}, [r4], r5 316 vrhadd.u8 d0, d0, d2 317 vld1.32 {d1[]}, [r2], r3 318 vld1.32 {d3[]}, [r4], r5 319 vrhadd.u8 d1, d1, d3 320 vst1.32 {d0[0]}, [r0,:32], r1 321 vst1.32 {d1[0]}, [r0,:32], r1 322 bgt pixel_avg_w4_neon 323 pop {r4-r6,pc} 324endfunc 325 326function pixel_avg_w8_neon, export=0 327 subs lr, lr, #4 328 vld1.64 {d0}, [r2], r3 329 vld1.64 {d2}, [r4], r5 330 vrhadd.u8 d0, d0, d2 331 vld1.64 {d1}, [r2], r3 332 vld1.64 {d3}, [r4], r5 333 vrhadd.u8 d1, d1, d3 334 vst1.64 {d0}, [r0,:64], r1 335 vld1.64 {d2}, [r2], r3 336 vld1.64 {d4}, [r4], r5 337 vrhadd.u8 d2, d2, d4 338 vst1.64 {d1}, [r0,:64], r1 339 vld1.64 {d3}, [r2], r3 340 vld1.64 {d5}, [r4], r5 341 vrhadd.u8 d3, d3, d5 342 vst1.64 {d2}, [r0,:64], r1 343 vst1.64 {d3}, [r0,:64], r1 344 bgt pixel_avg_w8_neon 345 pop {r4-r6,pc} 346endfunc 347 348function pixel_avg_w16_neon, export=0 349 subs lr, lr, #4 350 vld1.64 {d0-d1}, [r2], r3 351 vld1.64 {d2-d3}, [r4], r5 352 vrhadd.u8 q0, q0, q1 353 vld1.64 {d2-d3}, [r2], r3 354 vld1.64 {d4-d5}, [r4], r5 355 vrhadd.u8 q1, q1, q2 356 vst1.64 {d0-d1}, [r0,:128], r1 357 vld1.64 {d4-d5}, [r2], r3 358 vld1.64 {d6-d7}, [r4], r5 359 vrhadd.u8 q2, q2, q3 360 vst1.64 {d2-d3}, [r0,:128], r1 361 vld1.64 {d6-d7}, [r2], r3 362 vld1.64 {d0-d1}, [r4], r5 363 vrhadd.u8 q3, q3, q0 364 vst1.64 {d4-d5}, [r0,:128], r1 365 vst1.64 {d6-d7}, [r0,:128], r1 366 bgt pixel_avg_w16_neon 367 pop {r4-r6,pc} 368endfunc 369 370 371function pixel_avg2_w4_neon 372 ldr ip, [sp, #4] 373 push {lr} 374 ldr lr, [sp, #4] 375avg2_w4_loop: 376 subs ip, ip, #2 377 vld1.32 {d0[]}, [r2], r3 378 vld1.32 {d2[]}, [lr], r3 379 vrhadd.u8 d0, d0, d2 380 vld1.32 {d1[]}, [r2], r3 381 vld1.32 {d3[]}, [lr], r3 382 vrhadd.u8 d1, d1, d3 383 vst1.32 {d0[0]}, [r0,:32], r1 384 vst1.32 {d1[0]}, [r0,:32], r1 385 bgt avg2_w4_loop 386 pop {pc} 387endfunc 388 389function pixel_avg2_w8_neon 390 ldr ip, [sp, #4] 391 push {lr} 392 ldr lr, [sp, #4] 393avg2_w8_loop: 394 subs ip, ip, #2 395 vld1.64 {d0}, [r2], r3 396 vld1.64 {d2}, [lr], r3 397 vrhadd.u8 d0, d0, d2 398 vld1.64 {d1}, [r2], r3 399 vld1.64 {d3}, [lr], r3 400 vrhadd.u8 d1, d1, d3 401 vst1.64 {d0}, [r0,:64], r1 402 vst1.64 {d1}, [r0,:64], r1 403 bgt avg2_w8_loop 404 pop {pc} 405endfunc 406 407function pixel_avg2_w16_neon 408 ldr ip, [sp, #4] 409 push {lr} 410 ldr lr, [sp, #4] 411avg2_w16_loop: 412 subs ip, ip, #2 413 vld1.64 {d0-d1}, [r2], r3 414 vld1.64 {d2-d3}, [lr], r3 415 vrhadd.u8 q0, q0, q1 416 vld1.64 {d4-d5}, [r2], r3 417 vld1.64 {d6-d7}, [lr], r3 418 vrhadd.u8 q2, q2, q3 419 vst1.64 {d0-d1}, [r0,:128], r1 420 vst1.64 {d4-d5}, [r0,:128], r1 421 bgt avg2_w16_loop 422 pop {pc} 423endfunc 424 425function pixel_avg2_w20_neon 426 ldr ip, [sp, #4] 427 push {lr} 428 sub r1, r1, #16 429 ldr lr, [sp, #4] 430avg2_w20_loop: 431 subs ip, ip, #2 432 vld1.64 {d0-d2}, [r2], r3 433 vld1.64 {d4-d6}, [lr], r3 434 vrhadd.u8 q0, q0, q2 435 vrhadd.u8 d2, d2, d6 436 vld1.64 {d4-d6}, [r2], r3 437 vld1.64 {d16-d18},[lr], r3 438 vrhadd.u8 q2, q2, q8 439 vst1.64 {d0-d1}, [r0,:128]! 440 vrhadd.u8 d6, d6, d18 441 vst1.32 {d2[0]}, [r0,:32], r1 442 vst1.64 {d4-d5}, [r0,:128]! 443 vst1.32 {d6[0]}, [r0,:32], r1 444 bgt avg2_w20_loop 445 pop {pc} 446endfunc 447 448 449.macro weight_prologue type 450 push {r4-r5,lr} 451 ldr r4, [sp, #4*3] // weight_t 452 ldr ip, [sp, #4*3+4] // h 453.ifc \type, full 454 ldr lr, [r4, #32] // denom 455.endif 456 ldrd r4, r5, [r4, #32+4] // scale, offset 457 vdup.8 d0, r4 458 vdup.16 q1, r5 459.ifc \type, full 460 rsb lr, lr, #0 461 vdup.16 q2, lr 462.endif 463.endm 464 465// void mc_weight( uint8_t *src, intptr_t src_stride, uint8_t *dst, intptr_t dst_stride, 466// const x264_weight_t *weight, int height ) 467function mc_weight_w20_neon 468 weight_prologue full 469 sub r1, #16 470weight20_loop: 471 subs ip, #2 472 vld1.8 {d17-d19}, [r2], r3 473 vmull.u8 q10, d17, d0 474 vmull.u8 q11, d18, d0 475 vld1.8 {d16-d18}, [r2], r3 476 vmull.u8 q12, d16, d0 477 vmull.u8 q13, d17, d0 478 vtrn.32 d19, d18 479 vmull.u8 q14, d19, d0 480 vrshl.s16 q10, q10, q2 481 vrshl.s16 q11, q11, q2 482 vrshl.s16 q12, q12, q2 483 vrshl.s16 q13, q13, q2 484 vrshl.s16 q14, q14, q2 485 vadd.s16 q10, q10, q1 486 vadd.s16 q11, q11, q1 487 vadd.s16 q12, q12, q1 488 vadd.s16 q13, q13, q1 489 vadd.s16 q14, q14, q1 490 vqmovun.s16 d16, q10 491 vqmovun.s16 d17, q11 492 vqmovun.s16 d18, q12 493 vqmovun.s16 d19, q13 494 vqmovun.s16 d20, q14 495 vst1.8 {d16-d17}, [r0,:128]! 496 vst1.32 {d20[0]}, [r0,:32], r1 497 vst1.8 {d18-d19}, [r0,:128]! 498 vst1.32 {d20[1]}, [r0,:32], r1 499 bgt weight20_loop 500 pop {r4-r5,pc} 501endfunc 502 503function mc_weight_w16_neon 504 weight_prologue full 505weight16_loop: 506 subs ip, #2 507 vld1.8 {d16-d17}, [r2], r3 508 vld1.8 {d18-d19}, [r2], r3 509 vmull.u8 q10, d16, d0 510 vmull.u8 q11, d17, d0 511 vmull.u8 q12, d18, d0 512 vmull.u8 q13, d19, d0 513 vrshl.s16 q10, q10, q2 514 vrshl.s16 q11, q11, q2 515 vrshl.s16 q12, q12, q2 516 vrshl.s16 q13, q13, q2 517 vadd.s16 q10, q10, q1 518 vadd.s16 q11, q11, q1 519 vadd.s16 q12, q12, q1 520 vadd.s16 q13, q13, q1 521 vqmovun.s16 d16, q10 522 vqmovun.s16 d17, q11 523 vqmovun.s16 d18, q12 524 vqmovun.s16 d19, q13 525 vst1.8 {d16-d17}, [r0,:128], r1 526 vst1.8 {d18-d19}, [r0,:128], r1 527 bgt weight16_loop 528 pop {r4-r5,pc} 529endfunc 530 531function mc_weight_w8_neon 532 weight_prologue full 533weight8_loop: 534 subs ip, #2 535 vld1.8 {d16}, [r2], r3 536 vld1.8 {d18}, [r2], r3 537 vmull.u8 q8, d16, d0 538 vmull.u8 q9, d18, d0 539 vrshl.s16 q8, q8, q2 540 vrshl.s16 q9, q9, q2 541 vadd.s16 q8, q8, q1 542 vadd.s16 q9, q9, q1 543 vqmovun.s16 d16, q8 544 vqmovun.s16 d18, q9 545 vst1.8 {d16}, [r0,:64], r1 546 vst1.8 {d18}, [r0,:64], r1 547 bgt weight8_loop 548 pop {r4-r5,pc} 549endfunc 550 551function mc_weight_w4_neon 552 weight_prologue full 553weight4_loop: 554 subs ip, #2 555 vld1.32 {d16[0]}, [r2], r3 556 vld1.32 {d16[1]}, [r2], r3 557 vmull.u8 q8, d16, d0 558 vrshl.s16 q8, q8, q2 559 vadd.s16 q8, q8, q1 560 vqmovun.s16 d16, q8 561 vst1.32 {d16[0]}, [r0], r1 562 vst1.32 {d16[1]}, [r0], r1 563 bgt weight4_loop 564 pop {r4-r5,pc} 565endfunc 566 567function mc_weight_w20_nodenom_neon 568 weight_prologue nodenom 569 sub r1, #16 570weight20_nodenom_loop: 571 subs ip, #2 572 vld1.8 {d26-d28}, [r2], r3 573 vmov q8, q1 574 vmov q9, q1 575 vld1.8 {d29-d31}, [r2], r3 576 vmov q10, q1 577 vmov q11, q1 578 vmov q12, q1 579 vtrn.32 d28, d31 580 vmlal.u8 q8, d26, d0 581 vmlal.u8 q9, d27, d0 582 vmlal.u8 q10, d29, d0 583 vmlal.u8 q11, d30, d0 584 vmlal.u8 q12, d28, d0 585 vqmovun.s16 d16, q8 586 vqmovun.s16 d17, q9 587 vqmovun.s16 d18, q10 588 vqmovun.s16 d19, q11 589 vqmovun.s16 d20, q12 590 vst1.8 {d16-d17}, [r0,:128]! 591 vst1.32 {d20[0]}, [r0,:32], r1 592 vst1.8 {d18-d19}, [r0,:128]! 593 vst1.32 {d20[1]}, [r0,:32], r1 594 bgt weight20_nodenom_loop 595 pop {r4-r5,pc} 596endfunc 597 598function mc_weight_w16_nodenom_neon 599 weight_prologue nodenom 600weight16_nodenom_loop: 601 subs ip, #2 602 vld1.8 {d16-d17}, [r2], r3 603 vld1.8 {d18-d19}, [r2], r3 604 vmov q12, q1 605 vmov q13, q1 606 vmov q14, q1 607 vmov q15, q1 608 vmlal.u8 q12, d16, d0 609 vmlal.u8 q13, d17, d0 610 vmlal.u8 q14, d18, d0 611 vmlal.u8 q15, d19, d0 612 vqmovun.s16 d16, q12 613 vqmovun.s16 d17, q13 614 vqmovun.s16 d18, q14 615 vqmovun.s16 d19, q15 616 vst1.8 {d16-d17}, [r0,:128], r1 617 vst1.8 {d18-d19}, [r0,:128], r1 618 bgt weight16_nodenom_loop 619 pop {r4-r5,pc} 620endfunc 621 622function mc_weight_w8_nodenom_neon 623 weight_prologue nodenom 624weight8_nodenom_loop: 625 subs ip, #2 626 vld1.8 {d16}, [r2], r3 627 vld1.8 {d18}, [r2], r3 628 vmov q10, q1 629 vmov q11, q1 630 vmlal.u8 q10, d16, d0 631 vmlal.u8 q11, d18, d0 632 vqmovun.s16 d16, q10 633 vqmovun.s16 d17, q11 634 vst1.8 {d16}, [r0,:64], r1 635 vst1.8 {d17}, [r0,:64], r1 636 bgt weight8_nodenom_loop 637 pop {r4-r5,pc} 638endfunc 639 640function mc_weight_w4_nodenom_neon 641 weight_prologue nodenom 642weight4_nodenom_loop: 643 subs ip, #2 644 vld1.32 {d16[0]}, [r2], r3 645 vld1.32 {d16[1]}, [r2], r3 646 vmov q10, q1 647 vmlal.u8 q10, d16, d0 648 vqmovun.s16 d16, q10 649 vst1.32 {d16[0]}, [r0], r1 650 vst1.32 {d16[1]}, [r0], r1 651 bgt weight4_nodenom_loop 652 pop {r4-r5,pc} 653endfunc 654 655.macro weight_simple_prologue 656 push {lr} 657 ldr lr, [sp, #4] // weight_t 658 ldr ip, [sp, #8] // h 659 ldr lr, [lr] // offset 660 vdup.8 q1, lr 661.endm 662 663.macro weight_simple name op 664function mc_weight_w20_\name\()_neon 665 weight_simple_prologue 666weight20_\name\()_loop: 667 subs ip, #2 668 vld1.8 {d16-d18}, [r2], r3 669 vld1.8 {d19-d21}, [r2], r3 670 \op q8, q8, q1 671 \op q9, q9, q1 672 \op q10, q10, q1 673 vst1.8 {d16-d18}, [r0,:64], r1 674 vst1.8 {d19-d21}, [r0,:64], r1 675 bgt weight20_\name\()_loop 676 pop {pc} 677endfunc 678 679function mc_weight_w16_\name\()_neon 680 weight_simple_prologue 681weight16_\name\()_loop: 682 subs ip, #2 683 vld1.8 {d16-d17}, [r2], r3 684 vld1.8 {d18-d19}, [r2], r3 685 \op q8, q8, q1 686 \op q9, q9, q1 687 vst1.8 {d16-d17}, [r0,:128], r1 688 vst1.8 {d18-d19}, [r0,:128], r1 689 bgt weight16_\name\()_loop 690 pop {pc} 691endfunc 692 693function mc_weight_w8_\name\()_neon 694 weight_simple_prologue 695weight8_\name\()_loop: 696 subs ip, #2 697 vld1.8 {d16}, [r2], r3 698 vld1.8 {d17}, [r2], r3 699 \op q8, q8, q1 700 vst1.8 {d16}, [r0,:64], r1 701 vst1.8 {d17}, [r0,:64], r1 702 bgt weight8_\name\()_loop 703 pop {pc} 704endfunc 705 706function mc_weight_w4_\name\()_neon 707 weight_simple_prologue 708weight4_\name\()_loop: 709 subs ip, #2 710 vld1.32 {d16[]}, [r2], r3 711 vld1.32 {d17[]}, [r2], r3 712 \op q8, q8, q1 713 vst1.32 {d16[0]}, [r0], r1 714 vst1.32 {d17[0]}, [r0], r1 715 bgt weight4_\name\()_loop 716 pop {pc} 717endfunc 718.endm 719 720weight_simple offsetadd, vqadd.u8 721weight_simple offsetsub, vqsub.u8 722 723 724// void mc_copy( uint8_t *dst, intptr_t dst_stride, uint8_t *src, intptr_t src_stride, int height ) 725function mc_copy_w4_neon 726 ldr ip, [sp] 727copy_w4_loop: 728 subs ip, ip, #4 729 vld1.32 {d0[]}, [r2], r3 730 vld1.32 {d1[]}, [r2], r3 731 vld1.32 {d2[]}, [r2], r3 732 vld1.32 {d3[]}, [r2], r3 733 vst1.32 {d0[0]}, [r0,:32], r1 734 vst1.32 {d1[0]}, [r0,:32], r1 735 vst1.32 {d2[0]}, [r0,:32], r1 736 vst1.32 {d3[0]}, [r0,:32], r1 737 bgt copy_w4_loop 738 bx lr 739endfunc 740 741function mc_copy_w8_neon 742 ldr ip, [sp] 743copy_w8_loop: 744 subs ip, ip, #4 745 vld1.32 {d0}, [r2], r3 746 vld1.32 {d1}, [r2], r3 747 vld1.32 {d2}, [r2], r3 748 vld1.32 {d3}, [r2], r3 749 vst1.32 {d0}, [r0,:64], r1 750 vst1.32 {d1}, [r0,:64], r1 751 vst1.32 {d2}, [r0,:64], r1 752 vst1.32 {d3}, [r0,:64], r1 753 bgt copy_w8_loop 754 bx lr 755endfunc 756 757function mc_copy_w16_neon 758 ldr ip, [sp] 759copy_w16_loop: 760 subs ip, ip, #4 761 vld1.32 {d0-d1}, [r2], r3 762 vld1.32 {d2-d3}, [r2], r3 763 vld1.32 {d4-d5}, [r2], r3 764 vld1.32 {d6-d7}, [r2], r3 765 vst1.32 {d0-d1}, [r0,:128], r1 766 vst1.32 {d2-d3}, [r0,:128], r1 767 vst1.32 {d4-d5}, [r0,:128], r1 768 vst1.32 {d6-d7}, [r0,:128], r1 769 bgt copy_w16_loop 770 bx lr 771endfunc 772 773function mc_copy_w16_aligned_neon 774 ldr ip, [sp] 775copy_w16_aligned_loop: 776 subs ip, ip, #4 777 vld1.32 {d0-d1}, [r2,:128], r3 778 vld1.32 {d2-d3}, [r2,:128], r3 779 vld1.32 {d4-d5}, [r2,:128], r3 780 vld1.32 {d6-d7}, [r2,:128], r3 781 vst1.32 {d0-d1}, [r0,:128], r1 782 vst1.32 {d2-d3}, [r0,:128], r1 783 vst1.32 {d4-d5}, [r0,:128], r1 784 vst1.32 {d6-d7}, [r0,:128], r1 785 bgt copy_w16_aligned_loop 786 bx lr 787endfunc 788 789 790// void mc_chroma( uint8_t *dst, intptr_t i_dst_stride, 791// uint8_t *src, intptr_t i_src_stride, 792// int dx, int dy, int i_width, int i_height ); 793function mc_chroma_neon 794 push {r4-r8, lr} 795 vpush {d8-d11} 796 ldrd r4, r5, [sp, #56] 797 ldrd r6, r7, [sp, #64] 798 799 asr lr, r6, #3 800 mul lr, r4, lr 801 add r3, r3, r5, asr #2 802 cmp r7, #4 803 804 and r5, r5, #7 805 and r6, r6, #7 806 807 add r3, r3, lr 808 bic r3, r3, #0x1 809 810 pld [r3] 811 pld [r3, r4] 812 813 bgt mc_chroma_w8 814 beq mc_chroma_w4 815 816.macro CHROMA_MC_START r00, r01, r10, r11 817 muls lr, r5, r6 818 rsb r7, lr, r6, lsl #3 819 rsb ip, lr, r5, lsl #3 820 sub r5, lr, r5, lsl #3 821 sub r5, r5, r6, lsl #3 822 add r5, r5, #64 823 824 beq 2f 825 vld2.8 {\r00-\r01}, [r3], r4 826 827 vdup.8 d0, r5 828 vdup.8 d1, ip 829 830 vdup.8 d2, r7 831 vld2.8 {\r10-\r11}, [r3], r4 832 vdup.8 d3, lr 833 ldr r5, [sp, #72] 834.endm 835 836.macro CHROMA_MC width, align 837mc_chroma_w\width: 838 CHROMA_MC_START d4, d5, d8, d9 839 vext.8 d6, d4, d6, #1 840 vext.8 d7, d5, d7, #1 841 vext.8 d10, d8, d10, #1 842 vext.8 d11, d9, d11, #1 843// since the element size varies, there's a different index for the 2nd store 844.if \width == 4 845 .set st2, 1 846.else 847 .set st2, 2 848.endif 849 850 vtrn.32 d4, d6 851 vtrn.32 d5, d7 852 vtrn.32 d8, d10 853 vtrn.32 d9, d11 854 855 vtrn.32 d0, d1 856 vtrn.32 d2, d3 857 8581: // height loop, interpolate xy 859 860 vmull.u8 q8, d4, d0 861 vmlal.u8 q8, d8, d2 862 vmull.u8 q9, d5, d0 863 vmlal.u8 q9, d9, d2 864 865 vld2.8 {d4-d5}, [r3], r4 866 867 vext.8 d6, d4, d6, #1 868 vext.8 d7, d5, d7, #1 869 870 vadd.i16 d16, d16, d17 871 vadd.i16 d17, d18, d19 872 873 vtrn.32 d4, d6 874 vtrn.32 d5, d7 875 876 vmull.u8 q10, d8, d0 877 vmlal.u8 q10, d4, d2 878 vmull.u8 q11, d9, d0 879 vmlal.u8 q11, d5, d2 880 881 vld2.8 {d8-d9}, [r3], r4 882 883 vrshrn.u16 d16, q8, #6 884 885 vext.8 d10, d8, d10, #1 886 vext.8 d11, d9, d11, #1 887 888 vadd.i16 d18, d20, d21 889 vadd.i16 d19, d22, d23 890 891 vtrn.32 d8, d10 892 vtrn.32 d9, d11 893 894 vrshrn.u16 d18, q9, #6 895 896 subs r5, r5, #2 897 898 pld [r3] 899 pld [r3, r4] 900 901 vst1.\align {d16[0]}, [r0,:\align], r2 902 vst1.\align {d16[st2]}, [r1,:\align], r2 903 vst1.\align {d18[0]}, [r0,:\align], r2 904 vst1.\align {d18[st2]}, [r1,:\align], r2 905 bgt 1b 906 907 vpop {d8-d11} 908 pop {r4-r8, pc} 909 9102: // dx or dy are 0 911 tst r7, r7 912 add ip, ip, r7 913 vdup.8 d0, r5 914 ldr r5, [sp, #72] 915 vdup.8 d1, ip 916 917 beq 4f 918 919 vld1.64 {d4}, [r3], r4 920 vld1.64 {d6}, [r3], r4 921 9223: // vertical interpolation loop 923 924 vmull.u8 q8, d4, d0 925 vmlal.u8 q8, d6, d1 926 vmull.u8 q9, d6, d0 927 vld1.64 {d4}, [r3], r4 928 vmlal.u8 q9, d4, d1 929 vld1.64 {d6}, [r3], r4 930 931 vrshrn.u16 d16, q8, #6 // uvuvuvuv 932 vrshrn.u16 d17, q9, #6 // uvuvuvuv 933 subs r5, r5, #2 934 vuzp.8 d16, d17 // d16=uuuu|uuuu, d17=vvvv|vvvv 935 936 pld [r3] 937 pld [r3, r4] 938 939 vst1.\align {d16[0]}, [r0,:\align], r2 940 vst1.\align {d16[st2]}, [r0,:\align], r2 941 vst1.\align {d17[0]}, [r1,:\align], r2 942 vst1.\align {d17[st2]}, [r1,:\align], r2 943 bgt 3b 944 945 vpop {d8-d11} 946 pop {r4-r8, pc} 947 9484: // dy is 0 949 950 vld1.64 {d4-d5}, [r3], r4 951 vld1.64 {d6-d7}, [r3], r4 952 953 vext.8 d5, d4, d5, #2 954 vext.8 d7, d6, d7, #2 955 9565: // horizontal interpolation loop 957 958 vmull.u8 q8, d4, d0 959 vmlal.u8 q8, d5, d1 960 vmull.u8 q9, d6, d0 961 vmlal.u8 q9, d7, d1 962 963 subs r5, r5, #2 964 vld1.64 {d4-d5}, [r3], r4 965 vld1.64 {d6-d7}, [r3], r4 966 vext.8 d5, d4, d5, #2 967 vrshrn.u16 d16, q8, #6 968 vrshrn.u16 d17, q9, #6 969 vext.8 d7, d6, d7, #2 970 vuzp.8 d16, d17 971 972 pld [r3] 973 pld [r3, r4] 974 975 vst1.\align {d16[0]}, [r0,:\align], r2 976 vst1.\align {d16[st2]}, [r0,:\align], r2 977 vst1.\align {d17[0]}, [r1,:\align], r2 978 vst1.\align {d17[st2]}, [r1,:\align], r2 979 bgt 5b 980 981 vpop {d8-d11} 982 pop {r4-r8, pc} 983.endm 984 985 CHROMA_MC 2, 16 986 CHROMA_MC 4, 32 987 988mc_chroma_w8: 989 CHROMA_MC_START d4, d7, d8, d11 990 vext.8 d5, d4, d5, #1 991 vext.8 d9, d8, d9, #1 992 vext.8 d7, d6, d7, #1 993 vext.8 d11, d10, d11, #1 994 9951: // height loop, interpolate xy 996 vmull.u8 q8, d4, d0 997 vmlal.u8 q8, d5, d1 998 vmlal.u8 q8, d8, d2 999 vmlal.u8 q8, d9, d3 1000 1001 vmull.u8 q9, d6, d0 1002 vmlal.u8 q9, d7, d1 1003 vmlal.u8 q9, d10, d2 1004 vmlal.u8 q9, d11, d3 1005 1006 vld2.8 {d4-d7}, [r3], r4 1007 1008 vext.8 d5, d4, d5, #1 1009 vext.8 d7, d6, d7, #1 1010 1011 vmull.u8 q10, d8, d0 1012 vmlal.u8 q10, d9, d1 1013 vmlal.u8 q10, d4, d2 1014 vmlal.u8 q10, d5, d3 1015 1016 vmull.u8 q11, d10, d0 1017 vmlal.u8 q11, d11, d1 1018 vmlal.u8 q11, d6, d2 1019 vmlal.u8 q11, d7, d3 1020 1021 subs r5, r5, #2 1022 vld2.8 {d8-d11}, [r3], r4 1023 1024 vrshrn.u16 d16, q8, #6 1025 vrshrn.u16 d17, q9, #6 1026 vrshrn.u16 d18, q10, #6 1027 vext.8 d9, d8, d9, #1 1028 vrshrn.u16 d19, q11, #6 1029 vext.8 d11, d10, d11, #1 1030 1031 pld [r3] 1032 pld [r3, r4] 1033 1034 vst1.64 {d16}, [r0,:64], r2 1035 vst1.64 {d17}, [r1,:64], r2 1036 vst1.64 {d18}, [r0,:64], r2 1037 vst1.64 {d19}, [r1,:64], r2 1038 1039 bgt 1b 1040 1041 vpop {d8-d11} 1042 pop {r4-r8, pc} 1043 10442: // dx or dy are 0 1045 tst r7, r7 1046 add ip, ip, r7 1047 vdup.8 d0, r5 1048 ldr r5, [sp, #72] 1049 vdup.8 d1, ip 1050 1051 beq 4f 1052 1053 vld2.8 {d4-d5}, [r3], r4 1054 vld2.8 {d6-d7}, [r3], r4 1055 10563: // vertical interpolation loop 1057 vmull.u8 q8, d4, d0 //U 1058 vmlal.u8 q8, d6, d1 1059 vmull.u8 q9, d5, d0 //V 1060 vmlal.u8 q9, d7, d1 1061 1062 vld2.8 {d4-d5}, [r3], r4 1063 1064 vmull.u8 q10, d6, d0 1065 vmlal.u8 q10, d4, d1 1066 vmull.u8 q11, d7, d0 1067 vmlal.u8 q11, d5, d1 1068 1069 vld2.8 {d6-d7}, [r3], r4 1070 1071 vrshrn.u16 d16, q8, #6 1072 vrshrn.u16 d17, q9, #6 1073 vrshrn.u16 d18, q10, #6 1074 vrshrn.u16 d19, q11, #6 1075 subs r5, r5, #2 1076 1077 pld [r3] 1078 pld [r3, r4] 1079 1080 vst1.64 {d16}, [r0,:64], r2 1081 vst1.64 {d17}, [r1,:64], r2 1082 vst1.64 {d18}, [r0,:64], r2 1083 vst1.64 {d19}, [r1,:64], r2 1084 1085 bgt 3b 1086 1087 vpop {d8-d11} 1088 pop {r4-r8, pc} 1089 10904: // dy is 0 1091 1092 vld2.8 {d4-d7}, [r3], r4 1093 vld2.8 {d8-d11}, [r3], r4 1094 vext.8 d5, d4, d5, #1 1095 vext.8 d7, d6, d7, #1 1096 vext.8 d9, d8, d9, #1 1097 vext.8 d11, d10, d11, #1 1098 10995: // horizontal interpolation loop 1100 subs r5, r5, #2 1101 vmull.u8 q8, d4, d0 //U 1102 vmlal.u8 q8, d5, d1 1103 vmull.u8 q9, d6, d0 //V 1104 vmlal.u8 q9, d7, d1 1105 1106 vld2.8 {d4-d7}, [r3], r4 1107 1108 vmull.u8 q10, d8, d0 1109 vmlal.u8 q10, d9, d1 1110 vmull.u8 q11, d10, d0 1111 vmlal.u8 q11, d11, d1 1112 1113 vld2.8 {d8-d11}, [r3], r4 1114 1115 vext.8 d5, d4, d5, #1 1116 vrshrn.u16 d16, q8, #6 1117 vext.8 d7, d6, d7, #1 1118 vrshrn.u16 d17, q9, #6 1119 vext.8 d9, d8, d9, #1 1120 vrshrn.u16 d18, q10, #6 1121 vext.8 d11, d10, d11, #1 1122 vrshrn.u16 d19, q11, #6 1123 1124 pld [r3] 1125 pld [r3, r4] 1126 1127 vst1.64 {d16}, [r0,:64], r2 1128 vst1.64 {d17}, [r1,:64], r2 1129 vst1.64 {d18}, [r0,:64], r2 1130 vst1.64 {d19}, [r1,:64], r2 1131 bgt 5b 1132 1133 vpop {d8-d11} 1134 pop {r4-r8, pc} 1135 1136endfunc 1137 1138 1139// hpel_filter_v( uint8_t *dst, uint8_t *src, int16_t *buf, intptr_t stride, int width ) 1140function hpel_filter_v_neon 1141 ldr ip, [sp] 1142 sub r1, r1, r3, lsl #1 1143 push {lr} 1144 add lr, r1, ip 1145 vmov.u8 d30, #5 1146 vmov.u8 d31, #20 1147 1148filter_v_loop: 1149 subs ip, ip, #16 1150 vld1.64 {d0-d1}, [r1,:128], r3 1151 vld1.64 {d2-d3}, [r1,:128], r3 1152 vld1.64 {d4-d5}, [r1,:128], r3 1153 vld1.64 {d6-d7}, [r1,:128], r3 1154 vld1.64 {d16-d17}, [r1,:128], r3 1155 vld1.64 {d18-d19}, [r1,:128], r3 1156 sub r1, lr, ip 1157 1158 vaddl.u8 q10, d0, d18 1159 vmlsl.u8 q10, d2, d30 1160 vmlal.u8 q10, d4, d31 1161 vmlal.u8 q10, d6, d31 1162 vmlsl.u8 q10, d16, d30 1163 1164 vaddl.u8 q11, d1, d19 1165 vmlsl.u8 q11, d3, d30 1166 vmlal.u8 q11, d5, d31 1167 vmlal.u8 q11, d7, d31 1168 vmlsl.u8 q11, d17, d30 1169 1170 vqrshrun.s16 d0, q10, #5 1171 vst1.64 {d20-d21}, [r2,:128]! 1172 vqrshrun.s16 d1, q11, #5 1173 vst1.64 {d22-d23}, [r2,:128]! 1174 vst1.64 {d0-d1}, [r0,:128]! 1175 bgt filter_v_loop 1176 pop {pc} 1177endfunc 1178 1179// hpel_filter_c( uint8_t *dst, int16_t *buf, int width ); 1180function hpel_filter_c_neon 1181 sub r1, #16 1182 vld1.64 {d0-d3}, [r1,:128]! 1183 1184 // unrolled 2x: 4% faster 1185filter_c_loop: 1186 subs r2, r2, #16 1187 vld1.64 {d4-d7}, [r1,:128]! 1188 vext.16 q8, q0, q1, #6 1189 vext.16 q12, q1, q2, #3 1190 vadd.s16 q8, q8, q12 1191 vext.16 q9, q0, q1, #7 1192 vext.16 q11, q1, q2, #2 1193 vadd.s16 q9, q9, q11 1194 vext.16 q10, q1, q2, #1 1195 vext.16 q11, q1, q2, #6 1196 vadd.s16 q10, q1, q10 1197 vsub.s16 q8, q8, q9 // a-b 1198 vext.16 q15, q2, q3, #3 1199 vsub.s16 q9, q9, q10 // b-c 1200 1201 vext.16 q12, q1, q2, #7 1202 vshr.s16 q8, q8, #2 // (a-b)/4 1203 vadd.s16 q11, q11, q15 1204 vext.16 q14, q2, q3, #2 1205 vsub.s16 q8, q8, q9 // (a-b)/4-b+c 1206 vadd.s16 q12, q12, q14 1207 vext.16 q13, q2, q3, #1 1208 1209 vshr.s16 q8, q8, #2 // ((a-b)/4-b+c)/4 1210 vadd.s16 q13, q2, q13 1211 vadd.s16 q8, q8, q10 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16 1212 vsub.s16 q11, q11, q12 // a-b 1213 vsub.s16 q12, q12, q13 // b-c 1214 vshr.s16 q11, q11, #2 // (a-b)/4 1215 vqrshrun.s16 d30, q8, #6 1216 vsub.s16 q11, q11, q12 // (a-b)/4-b+c 1217 vshr.s16 q11, q11, #2 // ((a-b)/4-b+c)/4 1218 vld1.64 {d0-d3}, [r1,:128]! 1219 vadd.s16 q11, q11, q13 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16 1220 1221 vext.16 q8, q2, q3, #6 1222 vqrshrun.s16 d31, q11, #6 1223 vext.16 q12, q3, q0, #3 1224 vadd.s16 q8, q8, q12 1225 vext.16 q9, q2, q3, #7 1226 vst1.64 {d30-d31}, [r0,:128]! 1227 bxle lr 1228 subs r2, r2, #16 1229 1230 vext.16 q11, q3, q0, #2 1231 vadd.s16 q9, q9, q11 1232 vext.16 q10, q3, q0, #1 1233 vext.16 q11, q3, q0, #6 1234 vadd.s16 q10, q3, q10 1235 vsub.s16 q8, q8, q9 // a-b 1236 vext.16 q15, q0, q1, #3 1237 vsub.s16 q9, q9, q10 // b-c 1238 1239 vext.16 q12, q3, q0, #7 1240 vshr.s16 q8, q8, #2 // (a-b)/4 1241 vadd.s16 q11, q11, q15 1242 vext.16 q14, q0, q1, #2 1243 vsub.s16 q8, q8, q9 // (a-b)/4-b+c 1244 vadd.s16 q12, q12, q14 1245 vext.16 q13, q0, q1, #1 1246 1247 vshr.s16 q8, q8, #2 // ((a-b)/4-b+c)/4 1248 vadd.s16 q13, q0, q13 1249 vadd.s16 q8, q8, q10 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16 1250 vsub.s16 q11, q11, q12 // a-b 1251 vsub.s16 q12, q12, q13 // b-c 1252 vshr.s16 q11, q11, #2 // (a-b)/4 1253 vqrshrun.s16 d30, q8, #6 1254 vsub.s16 q11, q11, q12 // (a-b)/4-b+c 1255 vshr.s16 q11, q11, #2 // ((a-b)/4-b+c)/4 1256 vadd.s16 q11, q11, q13 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16 1257 1258 vqrshrun.s16 d31, q11, #6 1259 vst1.64 {d30-d31}, [r0,:128]! 1260 bgt filter_c_loop 1261 bx lr 1262endfunc 1263 1264// hpel_filter_h( uint8_t *dst, uint8_t *src, int width ); 1265function hpel_filter_h_neon 1266 sub r1, #16 1267 vmov.u8 d30, #5 1268 vld1.64 {d0-d3}, [r1,:128]! 1269 vmov.u8 d31, #20 1270 1271 // unrolled 3x because it's 5% faster, due to mitigating 1272 // the high latency of multiplication and vqrshrun 1273filter_h_loop: 1274 subs r2, r2, #16 1275 vld1.64 {d4-d5}, [r1,:128]! 1276 vext.8 q8, q0, q1, #14 1277 vext.8 q12, q1, q2, #3 1278 vaddl.u8 q13, d16, d24 1279 vext.8 q9, q0, q1, #15 1280 vaddl.u8 q14, d17, d25 1281 1282 vext.8 q10, q1, q2, #1 1283 vmlal.u8 q13, d2, d31 1284 vmlsl.u8 q13, d18, d30 1285 vext.8 q11, q1, q2, #2 1286 vmlal.u8 q13, d20, d31 1287 vmlsl.u8 q13, d22, d30 1288 1289 vmlsl.u8 q14, d19, d30 1290 vmlal.u8 q14, d3, d31 1291 vmlal.u8 q14, d21, d31 1292 vmlsl.u8 q14, d23, d30 1293 vqrshrun.s16 d6, q13, #5 1294 1295 vld1.64 {d0-d1}, [r1,:128]! 1296 vext.8 q8, q1, q2, #14 1297 vext.8 q12, q2, q0, #3 1298 vaddl.u8 q13, d16, d24 1299 vqrshrun.s16 d7, q14, #5 1300 vext.8 q9, q1, q2, #15 1301 vaddl.u8 q14, d17, d25 1302 1303 vst1.64 {d6-d7}, [r0,:128]! 1304 bxle lr 1305 subs r2, r2, #16 1306 1307 vext.8 q10, q2, q0, #1 1308 vmlal.u8 q13, d4, d31 1309 vmlsl.u8 q13, d18, d30 1310 vext.8 q11, q2, q0, #2 1311 vmlal.u8 q13, d20, d31 1312 vmlsl.u8 q13, d22, d30 1313 1314 vmlsl.u8 q14, d19, d30 1315 vmlal.u8 q14, d5, d31 1316 vmlal.u8 q14, d21, d31 1317 vmlsl.u8 q14, d23, d30 1318 vqrshrun.s16 d6, q13, #5 1319 1320 vld1.64 {d2-d3}, [r1,:128]! 1321 vext.8 q8, q2, q0, #14 1322 vext.8 q12, q0, q1, #3 1323 vaddl.u8 q13, d16, d24 1324 vqrshrun.s16 d7, q14, #5 1325 vext.8 q9, q2, q0, #15 1326 vaddl.u8 q14, d17, d25 1327 1328 vst1.64 {d6-d7}, [r0,:128]! 1329 bxle lr 1330 subs r2, r2, #16 1331 1332 vext.8 q10, q0, q1, #1 1333 vmlal.u8 q13, d0, d31 1334 vmlsl.u8 q13, d18, d30 1335 vext.8 q11, q0, q1, #2 1336 vmlal.u8 q13, d20, d31 1337 vmlsl.u8 q13, d22, d30 1338 1339 vmlsl.u8 q14, d19, d30 1340 vmlal.u8 q14, d1, d31 1341 vmlal.u8 q14, d21, d31 1342 vmlsl.u8 q14, d23, d30 1343 1344 vqrshrun.s16 d6, q13, #5 1345 vqrshrun.s16 d7, q14, #5 1346 vst1.64 {d6-d7}, [r0,:128]! 1347 bgt filter_h_loop 1348 bx lr 1349endfunc 1350 1351 1352// frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv, 1353// uint8_t *dstc, intptr_t src_stride, intptr_t dst_stride, int width, 1354// int height ) 1355function frame_init_lowres_core_neon 1356 push {r4-r10,lr} 1357 vpush {d8-d15} 1358 ldrd r4, r5, [sp, #96] 1359 ldrd r6, r7, [sp, #104] 1360 ldr lr, [sp, #112] 1361 sub r10, r6, r7 // dst_stride - width 1362 and r10, r10, #~15 1363 1364lowres_yloop: 1365 mov ip, r7 // width 1366 mov r6, r0 // src0 1367 add r8, r0, r5 // src1 = src0 + src_stride 1368 add r9, r0, r5, lsl #1 // src2 = src1 + src_stride 1369 1370 vld2.8 {d8, d10}, [r6,:128]! 1371 vld2.8 {d12,d14}, [r8,:128]! 1372 vld2.8 {d16,d18}, [r9,:128]! 1373 1374lowres_xloop: 1375 subs ip, ip, #16 1376 1377 vld2.8 {d9, d11}, [r6,:128]! 1378 vld2.8 {d13,d15}, [r8,:128]! 1379 vrhadd.u8 q0, q4, q6 1380 vld2.8 {d17,d19}, [r9,:128]! 1381 vrhadd.u8 q5, q5, q7 1382 vld2.8 {d20,d22}, [r6,:128]! 1383 vrhadd.u8 q1, q6, q8 1384 vld2.8 {d24,d26}, [r8,:128]! 1385 vrhadd.u8 q7, q7, q9 1386 vext.8 q4, q4, q10, #1 1387 vrhadd.u8 q0, q0, q5 1388 vext.8 q6, q6, q12, #1 1389 vrhadd.u8 q1, q1, q7 1390 vld2.8 {d28,d30}, [r9,:128]! 1391 vrhadd.u8 q4, q4, q6 1392 vext.8 q8, q8, q14, #1 1393 vrhadd.u8 q6, q6, q8 1394 vst1.64 {d0-d1}, [r1,:128]! 1395 vrhadd.u8 q2, q4, q5 1396 vst1.64 {d2-d3}, [r3,:128]! 1397 vrhadd.u8 q3, q6, q7 1398 vst1.64 {d4-d5}, [r2,:128]! 1399 vst1.64 {d6-d7}, [r4,:128]! 1400 1401 ble lowres_xloop_end 1402 subs ip, ip, #16 1403 1404 vld2.8 {d21,d23}, [r6,:128]! 1405 vld2.8 {d25,d27}, [r8,:128]! 1406 vrhadd.u8 q0, q10, q12 1407 vld2.8 {d29,d31}, [r9,:128]! 1408 vrhadd.u8 q11, q11, q13 1409 vld2.8 {d8, d10}, [r6,:128]! 1410 vrhadd.u8 q1, q12, q14 1411 vld2.8 {d12,d14}, [r8,:128]! 1412 vrhadd.u8 q13, q13, q15 1413 vext.8 q10, q10, q4, #1 1414 vrhadd.u8 q0, q0, q11 1415 vext.8 q12, q12, q6, #1 1416 vrhadd.u8 q1, q1, q13 1417 vld2.8 {d16,d18}, [r9,:128]! 1418 vrhadd.u8 q10, q10, q12 1419 vext.8 q14, q14, q8, #1 1420 vrhadd.u8 q12, q12, q14 1421 vst1.64 {d0-d1}, [r1,:128]! 1422 vrhadd.u8 q2, q10, q11 1423 vst1.64 {d2-d3}, [r3,:128]! 1424 vrhadd.u8 q3, q12, q13 1425 vst1.64 {d4-d5}, [r2,:128]! 1426 vst1.64 {d6-d7}, [r4,:128]! 1427 1428 bgt lowres_xloop 1429 1430lowres_xloop_end: 1431 subs lr, lr, #1 1432 add r0, r0, r5, lsl #1 1433 add r1, r1, r10 1434 add r2, r2, r10 1435 add r3, r3, r10 1436 add r4, r4, r10 1437 bgt lowres_yloop 1438 1439 vpop {d8-d15} 1440 pop {r4-r10,pc} 1441endfunc 1442 1443function load_deinterleave_chroma_fdec_neon 1444 mov ip, #FDEC_STRIDE/2 14451: 1446 vld2.8 {d0-d1}, [r1,:128], r2 1447 subs r3, r3, #1 1448 pld [r1] 1449 vst1.8 {d0}, [r0,:64], ip 1450 vst1.8 {d1}, [r0,:64], ip 1451 bgt 1b 1452 1453 bx lr 1454endfunc 1455 1456function load_deinterleave_chroma_fenc_neon 1457 mov ip, #FENC_STRIDE/2 14581: 1459 vld2.8 {d0-d1}, [r1,:128], r2 1460 subs r3, r3, #1 1461 pld [r1] 1462 vst1.8 {d0}, [r0,:64], ip 1463 vst1.8 {d1}, [r0,:64], ip 1464 bgt 1b 1465 1466 bx lr 1467endfunc 1468 1469function plane_copy_core_neon 1470 push {r4,lr} 1471 ldr r4, [sp, #8] 1472 ldr lr, [sp, #12] 1473 add r12, r4, #15 1474 bic r4, r12, #15 1475 sub r1, r1, r4 1476 sub r3, r3, r4 14771: 1478 mov r12, r4 147916: 1480 tst r12, #16 1481 beq 32f 1482 subs r12, r12, #16 1483 vld1.8 {q0}, [r2]! 1484 vst1.8 {q0}, [r0]! 1485 beq 0f 148632: 1487 subs r12, r12, #32 1488 vld1.8 {q0, q1}, [r2]! 1489 vst1.8 {q0, q1}, [r0]! 1490 bgt 32b 14910: 1492 subs lr, lr, #1 1493 add r2, r2, r3 1494 add r0, r0, r1 1495 bgt 1b 1496 1497 pop {r4,pc} 1498endfunc 1499 1500function plane_copy_deinterleave_neon 1501 push {r4-r7, lr} 1502 ldrd r6, r7, [sp, #28] 1503 ldrd r4, r5, [sp, #20] 1504 add lr, r6, #15 1505 bic lr, lr, #15 1506 sub r1, r1, lr 1507 sub r3, r3, lr 1508 sub r5, r5, lr, lsl #1 1509block: 1510 vld2.8 {d0-d3}, [r4,:128]! 1511 subs lr, lr, #16 1512 vst1.8 {q0}, [r0]! 1513 vst1.8 {q1}, [r2]! 1514 bgt block 1515 1516 add r4, r4, r5 1517 subs r7, r7, #1 1518 add r0, r0, r1 1519 add r2, r2, r3 1520 mov lr, r6 1521 bgt block 1522 1523 pop {r4-r7, pc} 1524endfunc 1525 1526function plane_copy_deinterleave_rgb_neon 1527 push {r4-r8, r10, r11, lr} 1528 ldrd r4, r5, [sp, #32] 1529 ldrd r6, r7, [sp, #40] 1530 ldr r8, [sp, #48] 1531 ldrd r10, r11, [sp, #52] 1532 add lr, r10, #7 1533 subs r8, r8, #3 1534 bic lr, lr, #7 1535 sub r7, r7, lr, lsl #1 1536 sub r1, r1, lr 1537 sub r3, r3, lr 1538 sub r5, r5, lr 1539 subne r7, r7, lr, lsl #1 1540 subeq r7, r7, lr 1541 bne block4 1542block3: 1543 vld3.8 {d0,d1,d2}, [r6]! 1544 subs lr, lr, #8 1545 vst1.8 {d0}, [r0]! 1546 vst1.8 {d1}, [r2]! 1547 vst1.8 {d2}, [r4]! 1548 bgt block3 1549 1550 subs r11, r11, #1 1551 add r0, r0, r1 1552 add r2, r2, r3 1553 add r4, r4, r5 1554 add r6, r6, r7 1555 mov lr, r10 1556 bgt block3 1557 1558 pop {r4-r8, r10, r11, pc} 1559block4: 1560 vld4.8 {d0,d1,d2,d3}, [r6]! 1561 subs lr, lr, #8 1562 vst1.8 {d0}, [r0]! 1563 vst1.8 {d1}, [r2]! 1564 vst1.8 {d2}, [r4]! 1565 bgt block4 1566 1567 subs r11, r11, #1 1568 add r0, r0, r1 1569 add r2, r2, r3 1570 add r4, r4, r5 1571 add r6, r6, r7 1572 mov lr, r10 1573 bgt block4 1574 1575 pop {r4-r8, r10, r11, pc} 1576endfunc 1577 1578function plane_copy_interleave_core_neon 1579 push {r4-r7, lr} 1580 ldrd r6, r7, [sp, #28] 1581 ldrd r4, r5, [sp, #20] 1582 add lr, r6, #15 1583 bic lr, lr, #15 1584 sub r1, r1, lr, lsl #1 1585 sub r3, r3, lr 1586 sub r5, r5, lr 1587blocki: 1588 vld1.8 {q0}, [r2]! 1589 vld1.8 {q1}, [r4]! 1590 subs lr, lr, #16 1591 vst2.8 {d0,d2}, [r0]! 1592 vst2.8 {d1,d3}, [r0]! 1593 bgt blocki 1594 1595 subs r7, r7, #1 1596 add r0, r0, r1 1597 add r2, r2, r3 1598 add r4, r4, r5 1599 mov lr, r6 1600 bgt blocki 1601 1602 pop {r4-r7, pc} 1603endfunc 1604 1605function plane_copy_swap_core_neon 1606 push {r4-r5, lr} 1607 ldrd r4, r5, [sp, #12] 1608 add lr, r4, #15 1609 bic lr, lr, #15 1610 sub r1, r1, lr, lsl #1 1611 sub r3, r3, lr, lsl #1 16121: 1613 vld1.8 {q0, q1}, [r2]! 1614 subs lr, lr, #16 1615 vrev16.8 q0, q0 1616 vrev16.8 q1, q1 1617 vst1.8 {q0, q1}, [r0]! 1618 bgt 1b 1619 1620 subs r5, r5, #1 1621 add r0, r0, r1 1622 add r2, r2, r3 1623 mov lr, r4 1624 bgt 1b 1625 1626 pop {r4-r5, pc} 1627endfunc 1628 1629function store_interleave_chroma_neon 1630 push {lr} 1631 ldr lr, [sp, #4] 1632 mov ip, #FDEC_STRIDE 16331: 1634 vld1.8 {d0}, [r2], ip 1635 vld1.8 {d1}, [r3], ip 1636 subs lr, lr, #1 1637 vst2.8 {d0,d1}, [r0,:128], r1 1638 bgt 1b 1639 1640 pop {pc} 1641endfunc 1642 1643.macro integral4h p1, p2 1644 vext.8 d1, \p1, \p2, #1 1645 vext.8 d2, \p1, \p2, #2 1646 vext.8 d3, \p1, \p2, #3 1647 vaddl.u8 q0, \p1, d1 1648 vaddl.u8 q1, d2, d3 1649 vadd.u16 q0, q0, q1 1650 vadd.u16 q0, q0, q2 1651.endm 1652 1653function integral_init4h_neon 1654 sub r3, r0, r2, lsl #1 1655 vld1.8 {d6, d7}, [r1, :128]! 16561: 1657 subs r2, r2, #16 1658 vld1.16 {q2}, [r3, :128]! 1659 integral4h d6, d7 1660 vld1.8 {d6}, [r1, :64]! 1661 vld1.16 {q2}, [r3, :128]! 1662 vst1.16 {q0}, [r0, :128]! 1663 integral4h d7, d6 1664 vld1.8 {d7}, [r1, :64]! 1665 vst1.16 {q0}, [r0, :128]! 1666 bgt 1b 1667 bx lr 1668endfunc 1669 1670.macro integral8h p1, p2, s 1671 vext.8 d1, \p1, \p2, #1 1672 vext.8 d2, \p1, \p2, #2 1673 vext.8 d3, \p1, \p2, #3 1674 vext.8 d4, \p1, \p2, #4 1675 vext.8 d5, \p1, \p2, #5 1676 vext.8 d6, \p1, \p2, #6 1677 vext.8 d7, \p1, \p2, #7 1678 vaddl.u8 q0, \p1, d1 1679 vaddl.u8 q1, d2, d3 1680 vaddl.u8 q2, d4, d5 1681 vaddl.u8 q3, d6, d7 1682 vadd.u16 q0, q0, q1 1683 vadd.u16 q2, q2, q3 1684 vadd.u16 q0, q0, q2 1685 vadd.u16 q0, q0, \s 1686.endm 1687 1688function integral_init8h_neon 1689 sub r3, r0, r2, lsl #1 1690 vld1.8 {d16, d17}, [r1, :128]! 16911: 1692 subs r2, r2, #16 1693 vld1.16 {q9}, [r3, :128]! 1694 integral8h d16, d17, q9 1695 vld1.8 {d16}, [r1, :64]! 1696 vld1.16 {q9}, [r3, :128]! 1697 vst1.16 {q0}, [r0, :128]! 1698 integral8h d17, d16, q9 1699 vld1.8 {d17}, [r1, :64]! 1700 vst1.16 {q0}, [r0, :128]! 1701 bgt 1b 1702 bx lr 1703endfunc 1704 1705function integral_init4v_neon 1706 push {r4-r5} 1707 mov r3, r0 1708 add r4, r0, r2, lsl #3 1709 add r5, r0, r2, lsl #4 1710 sub r2, r2, #8 1711 vld1.16 {q11, q12}, [r3]! 1712 vld1.16 {q8, q9}, [r5]! 1713 vld1.16 {q13}, [r3]! 1714 vld1.16 {q10}, [r5]! 17151: 1716 subs r2, r2, #16 1717 vld1.16 {q14, q15}, [r4]! 1718 vext.8 q0, q11, q12, #8 1719 vext.8 q1, q12, q13, #8 1720 vext.8 q2, q8, q9, #8 1721 vext.8 q3, q9, q10, #8 1722 vsub.u16 q14, q14, q11 1723 vsub.u16 q15, q15, q12 1724 vadd.u16 q0, q0, q11 1725 vadd.u16 q1, q1, q12 1726 vadd.u16 q2, q2, q8 1727 vadd.u16 q3, q3, q9 1728 vst1.16 {q14}, [r1]! 1729 vst1.16 {q15}, [r1]! 1730 vmov q11, q13 1731 vmov q8, q10 1732 vsub.u16 q0, q2, q0 1733 vsub.u16 q1, q3, q1 1734 vld1.16 {q12, q13}, [r3]! 1735 vld1.16 {q9, q10}, [r5]! 1736 vst1.16 {q0}, [r0]! 1737 vst1.16 {q1}, [r0]! 1738 bgt 1b 17392: 1740 pop {r4-r5} 1741 bx lr 1742endfunc 1743 1744function integral_init8v_neon 1745 add r2, r0, r1, lsl #4 1746 sub r1, r1, #8 1747 ands r3, r1, #16 - 1 1748 beq 1f 1749 subs r1, r1, #8 1750 vld1.16 {q0}, [r0] 1751 vld1.16 {q2}, [r2]! 1752 vsub.u16 q8, q2, q0 1753 vst1.16 {q8}, [r0]! 1754 ble 2f 17551: 1756 subs r1, r1, #16 1757 vld1.16 {q0, q1}, [r0] 1758 vld1.16 {q2, q3}, [r2]! 1759 vsub.u16 q8, q2, q0 1760 vsub.u16 q9, q3, q1 1761 vst1.16 {q8}, [r0]! 1762 vst1.16 {q9}, [r0]! 1763 bgt 1b 17642: 1765 bx lr 1766endfunc 1767 1768function mbtree_propagate_cost_neon 1769 push {r4-r5,lr} 1770 ldrd r4, r5, [sp, #12] 1771 ldr lr, [sp, #20] 1772 vld1.32 {d6[], d7[]}, [r5] 17738: 1774 subs lr, lr, #8 1775 vld1.16 {q8}, [r1]! 1776 vld1.16 {q9}, [r2]! 1777 vld1.16 {q10}, [r3]! 1778 vld1.16 {q11}, [r4]! 1779 vbic.u16 q10, #0xc000 1780 vmin.u16 q10, q9, q10 1781 vmull.u16 q12, d18, d22 @ propagate_intra 1782 vmull.u16 q13, d19, d23 @ propagate_intra 1783 vsubl.u16 q14, d18, d20 @ propagate_num 1784 vsubl.u16 q15, d19, d21 @ propagate_num 1785 vmovl.u16 q10, d18 @ propagate_denom 1786 vmovl.u16 q11, d19 @ propagate_denom 1787 vmovl.u16 q9, d17 1788 vmovl.u16 q8, d16 1789 vcvt.f32.s32 q12, q12 1790 vcvt.f32.s32 q13, q13 1791 vcvt.f32.s32 q14, q14 1792 vcvt.f32.s32 q15, q15 1793 vcvt.f32.s32 q10, q10 1794 vcvt.f32.s32 q11, q11 1795 vrecpe.f32 q0, q10 1796 vrecpe.f32 q1, q11 1797 vcvt.f32.s32 q8, q8 1798 vcvt.f32.s32 q9, q9 1799 vrecps.f32 q10, q0, q10 1800 vrecps.f32 q11, q1, q11 1801 vmla.f32 q8, q12, q3 @ propagate_amount 1802 vmla.f32 q9, q13, q3 @ propagate_amount 1803 vmul.f32 q0, q0, q10 1804 vmul.f32 q1, q1, q11 1805 vmul.f32 q8, q8, q14 1806 vmul.f32 q9, q9, q15 1807 vmul.f32 q0, q8, q0 1808 vmul.f32 q1, q9, q1 1809 vcvt.s32.f32 q0, q0 1810 vcvt.s32.f32 q1, q1 1811 vqmovn.s32 d0, q0 1812 vqmovn.s32 d1, q1 1813 vst1.16 {q0}, [r0]! 1814 bgt 8b 1815 pop {r4-r5,pc} 1816endfunc 1817 1818function mbtree_propagate_list_internal_neon 1819 vld1.16 {d4[]}, [sp] @ bipred_weight 1820 movrel r12, pw_0to15 1821 vmov.u16 q10, #0xc000 1822 vld1.16 {q0}, [r12, :128] @h->mb.i_mb_x,h->mb.i_mb_y 1823 ldrh r12, [sp, #4] 1824 vmov.u32 q11, #4 1825 vmov.u8 q3, #32 1826 vdup.u16 q8, r12 @ mb_y 1827 vzip.u16 q0, q8 1828 ldr r12, [sp, #8] 18298: 1830 subs r12, r12, #8 1831 vld1.16 {q14}, [r1, :128]! @ propagate_amount 1832 vld1.16 {q15}, [r2]! @ lowres_cost 1833 vld1.16 {q8, q9}, [r0]! 1834 vand q15, q15, q10 1835 vceq.u16 q1, q15, q10 1836 vmull.u16 q12, d28, d4 1837 vmull.u16 q13, d29, d4 1838 vrshrn.u32 d30, q12, #6 1839 vrshrn.u32 d31, q13, #6 1840 vbsl q1, q15, q14 @ if( lists_used == 3 ) 1841 @ propagate_amount = (propagate_amount * bipred_weight + 32) >> 6 1842 vshr.s16 q12, q8, #5 1843 vshr.s16 q13, q9, #5 1844 vuzp.16 q8, q9 @ x & 31, y & 31 1845 vadd.s16 q12, q12, q0 1846 vadd.s16 q0, q0, q11 1847 vmovn.i16 d16, q8 1848 vmovn.i16 d17, q9 1849 vadd.s16 q13, q13, q0 1850 vbic.i16 q8, #128+64+32 1851 vadd.s16 q0, q0, q11 1852 vbic.i16 q8, #(128+64+32)<<8 1853 vst1.16 {q12, q13}, [r3, :128]! 1854 vsub.i8 q9, q3, q8 1855 vmull.u8 q12, d17, d16 @ idx3weight = y*x 1856 vmull.u8 q14, d19, d16 @ idx1weight = (32-y)*x 1857 vmull.u8 q15, d19, d18 @ idx0weight = (32-y)*(32-x) 1858 vmull.u8 q13, d17, d18 @ idx2weight = y*(32-x) 1859 vmull.u16 q9, d28, d2 @ idx1weight 1860 vmull.u16 q8, d29, d3 1861 vmull.u16 q14, d30, d2 @ idx0weight 1862 vmull.u16 q15, d31, d3 1863 vrshrn.u32 d18, q9, #10 @ idx1weight 1864 vrshrn.u32 d19, q8, #10 1865 vrshrn.u32 d16, q14, #10 @ idx0weight 1866 vrshrn.u32 d17, q15, #10 1867 vmull.u16 q14, d24, d2 @ idx3weight 1868 vmull.u16 q15, d25, d3 1869 vzip.16 q8, q9 1870 vmull.u16 q12, d26, d2 @ idx2weight 1871 vmull.u16 q13, d27, d3 1872 vst1.16 {q8, q9}, [r3, :128]! 1873 vrshrn.u32 d19, q15, #10 @ idx3weight 1874 vrshrn.u32 d18, q14, #10 1875 vrshrn.u32 d16, q12, #10 @ idx2weight 1876 vrshrn.u32 d17, q13, #10 1877 vzip.16 q8, q9 1878 vst1.16 {q8, q9}, [r3, :128]! 1879 bge 8b 1880 bx lr 1881endfunc 1882 1883@ void mbtree_fix8_pack( int16_t *dst, float *src, int count ) 1884function mbtree_fix8_pack_neon, export=1 1885 subs r3, r2, #8 1886 blt 2f 18871: 1888 subs r3, r3, #8 1889 vld1.32 {q0,q1}, [r1,:128]! 1890 vcvt.s32.f32 q0, q0, #8 1891 vcvt.s32.f32 q1, q1, #8 1892 vqmovn.s32 d4, q0 1893 vqmovn.s32 d5, q1 1894 vrev16.8 q3, q2 1895 vst1.16 {q3}, [r0,:128]! 1896 bge 1b 18972: 1898 adds r3, r3, #8 1899 bxeq lr 19003: 1901 subs r3, r3, #1 1902 vld1.32 {d0[0]}, [r1]! 1903 vcvt.s32.f32 s0, s0, #8 1904 vrev16.8 d0, d0 1905 vst1.16 {d0[0]}, [r0]! 1906 bgt 3b 1907 1908 bx lr 1909endfunc 1910 1911@ void mbtree_fix8_unpack( float *dst, int16_t *src, int count ) 1912function mbtree_fix8_unpack_neon, export=1 1913 subs r3, r2, #8 1914 blt 2f 19151: 1916 subs r3, r3, #8 1917 vld1.16 {q0}, [r1,:128]! 1918 vrev16.8 q1, q0 1919 vmovl.s16 q0, d2 1920 vmovl.s16 q1, d3 1921 vcvt.f32.s32 q0, q0, #8 1922 vcvt.f32.s32 q1, q1, #8 1923 vst1.32 {q0,q1}, [r0,:128]! 1924 bge 1b 19252: 1926 adds r3, r3, #8 1927 bxeq lr 19283: 1929 subs r3, r3, #1 1930 vld1.16 {d0[0]}, [r1]! 1931 vrev16.8 d0, d0 1932 vmovl.s16 q0, d0 1933 vcvt.f32.s32 d0, d0, #8 1934 vst1.32 {d0[0]}, [r0]! 1935 bgt 3b 1936 1937 bx lr 1938endfunc 1939