1/* 2 * ARM NEON optimised IDCT functions for HEVC decoding 3 * Copyright (c) 2014 Seppo Tomperi <seppo.tomperi@vtt.fi> 4 * Copyright (c) 2017 Alexandra Hájková 5 * 6 * This file is part of FFmpeg. 7 * 8 * FFmpeg is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * FFmpeg is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with FFmpeg; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23#include "libavutil/arm/asm.S" 24 25const trans, align=4 26 .short 64, 83, 64, 36 27 .short 89, 75, 50, 18 28 .short 90, 87, 80, 70 29 .short 57, 43, 25, 9 30 .short 90, 90, 88, 85 31 .short 82, 78, 73, 67 32 .short 61, 54, 46, 38 33 .short 31, 22, 13, 4 34endconst 35 36.macro clip10 in1, in2, c1, c2 37 vmax.s16 \in1, \in1, \c1 38 vmax.s16 \in2, \in2, \c1 39 vmin.s16 \in1, \in1, \c2 40 vmin.s16 \in2, \in2, \c2 41.endm 42 43function ff_hevc_add_residual_4x4_8_neon, export=1 44 vld1.16 {q0-q1}, [r1, :128] 45 vld1.32 d4[0], [r0, :32], r2 46 vld1.32 d4[1], [r0, :32], r2 47 vld1.32 d5[0], [r0, :32], r2 48 vld1.32 d5[1], [r0, :32], r2 49 sub r0, r0, r2, lsl #2 50 vmovl.u8 q8, d4 51 vmovl.u8 q9, d5 52 vqadd.s16 q0, q0, q8 53 vqadd.s16 q1, q1, q9 54 vqmovun.s16 d0, q0 55 vqmovun.s16 d1, q1 56 vst1.32 d0[0], [r0, :32], r2 57 vst1.32 d0[1], [r0, :32], r2 58 vst1.32 d1[0], [r0, :32], r2 59 vst1.32 d1[1], [r0, :32], r2 60 bx lr 61endfunc 62 63function ff_hevc_add_residual_4x4_10_neon, export=1 64 mov r12, r0 65 vld1.16 {q0-q1}, [r1, :128] 66 vld1.16 d4, [r12, :64], r2 67 vld1.16 d5, [r12, :64], r2 68 vld1.16 d6, [r12, :64], r2 69 vqadd.s16 q0, q2 70 vld1.16 d7, [r12, :64], r2 71 vmov.s16 q12, #0 72 vqadd.s16 q1, q3 73 vmvn.s16 q13, #0xFC00 @ vmov.s16 #0x3FF 74 clip10 q0, q1, q12, q13 75 vst1.16 d0, [r0, :64], r2 76 vst1.16 d1, [r0, :64], r2 77 vst1.16 d2, [r0, :64], r2 78 vst1.16 d3, [r0, :64], r2 79 bx lr 80endfunc 81 82function ff_hevc_add_residual_8x8_8_neon, export=1 83 add r12, r0, r2 84 add r2, r2, r2 85 mov r3, #8 861: subs r3, #2 87 vld1.8 {d16}, [r0, :64] 88 vld1.8 {d17}, [r12, :64] 89 vmovl.u8 q9, d16 90 vld1.16 {q0-q1}, [r1, :128]! 91 vmovl.u8 q8, d17 92 vqadd.s16 q0, q9 93 vqadd.s16 q1, q8 94 vqmovun.s16 d0, q0 95 vqmovun.s16 d1, q1 96 vst1.8 d0, [r0, :64], r2 97 vst1.8 d1, [r12, :64], r2 98 bne 1b 99 bx lr 100endfunc 101 102function ff_hevc_add_residual_8x8_10_neon, export=1 103 add r12, r0, r2 104 add r2, r2, r2 105 mov r3, #8 106 vmov.s16 q12, #0 107 vmvn.s16 q13, #0xFC00 @ vmov.s16 #0x3FF 1081: subs r3, #2 109 vld1.16 {q0-q1}, [r1, :128]! 110 vld1.16 {q8}, [r0, :128] 111 vqadd.s16 q0, q8 112 vld1.16 {q9}, [r12, :128] 113 vqadd.s16 q1, q9 114 clip10 q0, q1, q12, q13 115 vst1.16 {q0}, [r0, :128], r2 116 vst1.16 {q1}, [r12, :128], r2 117 bne 1b 118 bx lr 119endfunc 120 121function ff_hevc_add_residual_16x16_8_neon, export=1 122 mov r3, #16 123 add r12, r0, r2 124 add r2, r2, r2 1251: subs r3, #2 126 vld1.8 {q8}, [r0, :128] 127 vld1.16 {q0, q1}, [r1, :128]! 128 vld1.8 {q11}, [r12, :128] 129 vld1.16 {q2, q3}, [r1, :128]! 130 vmovl.u8 q9, d16 131 vmovl.u8 q10, d17 132 vmovl.u8 q12, d22 133 vmovl.u8 q13, d23 134 vqadd.s16 q0, q9 135 vqadd.s16 q1, q10 136 vqadd.s16 q2, q12 137 vqadd.s16 q3, q13 138 vqmovun.s16 d0, q0 139 vqmovun.s16 d1, q1 140 vqmovun.s16 d2, q2 141 vqmovun.s16 d3, q3 142 vst1.8 {q0}, [r0, :128], r2 143 vst1.8 {q1}, [r12, :128], r2 144 bne 1b 145 bx lr 146endfunc 147 148function ff_hevc_add_residual_16x16_10_neon, export=1 149 mov r3, #16 150 vmov.s16 q12, #0 151 vmvn.s16 q13, #0xFC00 @ vmov.s16 #0x3FF 152 add r12, r0, r2 153 add r2, r2, r2 1541: subs r3, #2 155 vld1.16 {q8-q9}, [r0, :128] 156 vld1.16 {q0, q1}, [r1, :128]! 157 vqadd.s16 q0, q8 158 vld1.16 {q10-q11}, [r12, :128] 159 vqadd.s16 q1, q9 160 vld1.16 {q2, q3}, [r1, :128]! 161 vqadd.s16 q2, q10 162 vqadd.s16 q3, q11 163 clip10 q0, q1, q12, q13 164 clip10 q2, q3, q12, q13 165 vst1.16 {q0-q1}, [r0, :128], r2 166 vst1.16 {q2-q3}, [r12, :128], r2 167 bne 1b 168 bx lr 169endfunc 170 171function ff_hevc_add_residual_32x32_8_neon, export=1 172 vpush {q4-q7} 173 add r12, r0, r2 174 add r2, r2, r2 175 mov r3, #32 1761: subs r3, #2 177 vld1.8 {q12, q13}, [r0, :128] 178 vmovl.u8 q8, d24 179 vmovl.u8 q9, d25 180 vld1.8 {q14, q15}, [r12, :128] 181 vmovl.u8 q10, d26 182 vmovl.u8 q11, d27 183 vmovl.u8 q12, d28 184 vldm r1!, {q0-q7} 185 vmovl.u8 q13, d29 186 vmovl.u8 q14, d30 187 vmovl.u8 q15, d31 188 vqadd.s16 q0, q8 189 vqadd.s16 q1, q9 190 vqadd.s16 q2, q10 191 vqadd.s16 q3, q11 192 vqadd.s16 q4, q12 193 vqadd.s16 q5, q13 194 vqadd.s16 q6, q14 195 vqadd.s16 q7, q15 196 vqmovun.s16 d0, q0 197 vqmovun.s16 d1, q1 198 vqmovun.s16 d2, q2 199 vqmovun.s16 d3, q3 200 vqmovun.s16 d4, q4 201 vqmovun.s16 d5, q5 202 vst1.8 {q0, q1}, [r0, :128], r2 203 vqmovun.s16 d6, q6 204 vqmovun.s16 d7, q7 205 vst1.8 {q2, q3}, [r12, :128], r2 206 bne 1b 207 vpop {q4-q7} 208 bx lr 209endfunc 210 211function ff_hevc_add_residual_32x32_10_neon, export=1 212 mov r3, #32 213 add r12, r0, #32 214 vmov.s16 q12, #0 215 vmvn.s16 q13, #0xFC00 @ vmov.s16 #0x3FF 2161: subs r3, #1 217 vldm r1!, {q0-q3} 218 vld1.16 {q8, q9}, [r0, :128] 219 vld1.16 {q10, q11}, [r12, :128] 220 vqadd.s16 q0, q8 221 vqadd.s16 q1, q9 222 vqadd.s16 q2, q10 223 vqadd.s16 q3, q11 224 clip10 q0, q1, q12, q13 225 clip10 q2, q3, q12, q13 226 vst1.16 {q0-q1}, [r0, :128], r2 227 vst1.16 {q2-q3}, [r12, :128], r2 228 bne 1b 229 bx lr 230endfunc 231 232.macro idct_4x4_dc bitdepth 233function ff_hevc_idct_4x4_dc_\bitdepth\()_neon, export=1 234 ldrsh r1, [r0] 235 ldr r2, =(1 << (13 - \bitdepth)) 236 add r1, #1 237 asr r1, #1 238 add r1, r2 239 asr r1, #(14 - \bitdepth) 240 vdup.16 q0, r1 241 vdup.16 q1, r1 242 vst1.16 {q0, q1}, [r0, :128] 243 bx lr 244endfunc 245.endm 246 247.macro idct_8x8_dc bitdepth 248function ff_hevc_idct_8x8_dc_\bitdepth\()_neon, export=1 249 ldrsh r1, [r0] 250 ldr r2, =(1 << (13 - \bitdepth)) 251 add r1, #1 252 asr r1, #1 253 add r1, r2 254 asr r1, #(14 - \bitdepth) 255 vdup.16 q8, r1 256 vdup.16 q9, r1 257 vmov.16 q10, q8 258 vmov.16 q11, q8 259 vmov.16 q12, q8 260 vmov.16 q13, q8 261 vmov.16 q14, q8 262 vmov.16 q15, q8 263 vstm r0, {q8-q15} 264 bx lr 265endfunc 266.endm 267 268.macro idct_16x16_dc bitdepth 269function ff_hevc_idct_16x16_dc_\bitdepth\()_neon, export=1 270 ldrsh r1, [r0] 271 ldr r2, =(1 << (13 - \bitdepth)) 272 add r1, #1 273 asr r1, #1 274 add r1, r2 275 asr r1, #(14 - \bitdepth) 276 vdup.16 q8, r1 277 vdup.16 q9, r1 278 vmov.16 q10, q8 279 vmov.16 q11, q8 280 vmov.16 q12, q8 281 vmov.16 q13, q8 282 vmov.16 q14, q8 283 vmov.16 q15, q8 284 vstm r0!, {q8-q15} 285 vstm r0!, {q8-q15} 286 vstm r0!, {q8-q15} 287 vstm r0, {q8-q15} 288 bx lr 289endfunc 290.endm 291 292.macro idct_32x32_dc bitdepth 293function ff_hevc_idct_32x32_dc_\bitdepth\()_neon, export=1 294 ldrsh r1, [r0] 295 ldr r2, =(1 << (13 - \bitdepth)) 296 add r1, #1 297 asr r1, #1 298 add r1, r2 299 asr r1, #(14 - \bitdepth) 300 mov r3, #16 301 vdup.16 q8, r1 302 vdup.16 q9, r1 303 vmov.16 q10, q8 304 vmov.16 q11, q8 305 vmov.16 q12, q8 306 vmov.16 q13, q8 307 vmov.16 q14, q8 308 vmov.16 q15, q8 3091: subs r3, #1 310 vstm r0!, {q8-q15} 311 bne 1b 312 bx lr 313endfunc 314.endm 315 316.macro sum_sub out, in, c, op 317 .ifc \op, + 318 vmlal.s16 \out, \in, \c 319 .else 320 vmlsl.s16 \out, \in, \c 321 .endif 322.endm 323 324.macro tr_4x4 in0, in1, in2, in3, out0, out1, out2, out3, shift, tmp0, tmp1, tmp2, tmp3, tmp4 325 vshll.s16 \tmp0, \in0, #6 326 vmull.s16 \tmp2, \in1, d4[1] 327 vmov \tmp1, \tmp0 328 vmull.s16 \tmp3, \in1, d4[3] 329 vmlal.s16 \tmp0, \in2, d4[0] @e0 330 vmlsl.s16 \tmp1, \in2, d4[0] @e1 331 vmlal.s16 \tmp2, \in3, d4[3] @o0 332 vmlsl.s16 \tmp3, \in3, d4[1] @o1 333 334 vadd.s32 \tmp4, \tmp0, \tmp2 335 vsub.s32 \tmp0, \tmp0, \tmp2 336 vadd.s32 \tmp2, \tmp1, \tmp3 337 vsub.s32 \tmp1, \tmp1, \tmp3 338 vqrshrn.s32 \out0, \tmp4, #\shift 339 vqrshrn.s32 \out3, \tmp0, #\shift 340 vqrshrn.s32 \out1, \tmp2, #\shift 341 vqrshrn.s32 \out2, \tmp1, #\shift 342.endm 343 344.macro tr_4x4_8 in0, in1, in2, in3, out0, out1, out2, out3, tmp0, tmp1, tmp2, tmp3 345 vshll.s16 \tmp0, \in0, #6 346 vld1.s16 {\in0}, [r1, :64]! 347 vmov \tmp1, \tmp0 348 vmull.s16 \tmp2, \in1, \in0[1] 349 vmull.s16 \tmp3, \in1, \in0[3] 350 vmlal.s16 \tmp0, \in2, \in0[0] @e0 351 vmlsl.s16 \tmp1, \in2, \in0[0] @e1 352 vmlal.s16 \tmp2, \in3, \in0[3] @o0 353 vmlsl.s16 \tmp3, \in3, \in0[1] @o1 354 355 vld1.s16 {\in0}, [r1, :64] 356 357 vadd.s32 \out0, \tmp0, \tmp2 358 vadd.s32 \out1, \tmp1, \tmp3 359 vsub.s32 \out2, \tmp1, \tmp3 360 vsub.s32 \out3, \tmp0, \tmp2 361 362 sub r1, r1, #8 363.endm 364 365@ Do a 4x4 transpose, using q registers for the subtransposes that don't 366@ need to address the indiviudal d registers. 367@ r0,r1 == rq0, r2,r3 == rq1 368.macro transpose_4x4 rq0, rq1, r0, r1, r2, r3 369 vtrn.32 \rq0, \rq1 370 vtrn.16 \r0, \r1 371 vtrn.16 \r2, \r3 372.endm 373 374.macro idct_4x4 bitdepth 375function ff_hevc_idct_4x4_\bitdepth\()_neon, export=1 376@r0 - coeffs 377 vld1.s16 {q0-q1}, [r0, :128] 378 379 movrel r1, trans 380 vld1.s16 {d4}, [r1, :64] 381 382 tr_4x4 d0, d1, d2, d3, d16, d17, d18, d19, 7, q10, q11, q12, q13, q0 383 transpose_4x4 q8, q9, d16, d17, d18, d19 384 385 tr_4x4 d16, d17, d18, d19, d0, d1, d2, d3, 20 - \bitdepth, q10, q11, q12, q13, q0 386 transpose_4x4 q0, q1, d0, d1, d2, d3 387 vst1.s16 {d0-d3}, [r0, :128] 388 bx lr 389endfunc 390.endm 391 392.macro transpose8_4x4 r0, r1, r2, r3 393 vtrn.16 \r0, \r1 394 vtrn.16 \r2, \r3 395 vtrn.32 \r0, \r2 396 vtrn.32 \r1, \r3 397.endm 398 399.macro transpose_8x8 r0, r1, r2, r3, r4, r5, r6, r7, l0, l1, l2, l3, l4, l5, l6, l7 400 transpose8_4x4 \r0, \r1, \r2, \r3 401 transpose8_4x4 \r4, \r5, \r6, \r7 402 403 transpose8_4x4 \l0, \l1, \l2, \l3 404 transpose8_4x4 \l4, \l5, \l6, \l7 405.endm 406 407.macro tr_8x4 shift, in0, in1, in2, in3, in4, in5, in6, in7 408 tr_4x4_8 \in0, \in2, \in4, \in6, q8, q9, q10, q11, q12, q13, q14, q15 409 410 vmull.s16 q14, \in1, \in0[2] 411 vmull.s16 q12, \in1, \in0[0] 412 vmull.s16 q13, \in1, \in0[1] 413 sum_sub q14, \in3, \in0[0], - 414 sum_sub q12, \in3, \in0[1], + 415 sum_sub q13, \in3, \in0[3], - 416 417 sum_sub q14, \in5, \in0[3], + 418 sum_sub q12, \in5, \in0[2], + 419 sum_sub q13, \in5, \in0[0], - 420 421 sum_sub q14, \in7, \in0[1], + 422 sum_sub q12, \in7, \in0[3], + 423 sum_sub q13, \in7, \in0[2], - 424 425 vadd.s32 q15, q10, q14 426 vsub.s32 q10, q10, q14 427 vqrshrn.s32 \in2, q15, \shift 428 429 vmull.s16 q15, \in1, \in0[3] 430 sum_sub q15, \in3, \in0[2], - 431 sum_sub q15, \in5, \in0[1], + 432 sum_sub q15, \in7, \in0[0], - 433 434 vqrshrn.s32 \in5, q10, \shift 435 436 vadd.s32 q10, q8, q12 437 vsub.s32 q8, q8, q12 438 vadd.s32 q12, q9, q13 439 vsub.s32 q9, q9, q13 440 vadd.s32 q14, q11, q15 441 vsub.s32 q11, q11, q15 442 443 vqrshrn.s32 \in0, q10, \shift 444 vqrshrn.s32 \in7, q8, \shift 445 vqrshrn.s32 \in1, q12, \shift 446 vqrshrn.s32 \in6, q9, \shift 447 vqrshrn.s32 \in3, q14, \shift 448 vqrshrn.s32 \in4, q11, \shift 449.endm 450 451.macro idct_8x8 bitdepth 452function ff_hevc_idct_8x8_\bitdepth\()_neon, export=1 453@r0 - coeffs 454 vpush {q4-q7} 455 456 mov r1, r0 457 mov r2, #64 458 add r3, r0, #32 459 vld1.s16 {q0-q1}, [r1,:128], r2 460 vld1.s16 {q2-q3}, [r3,:128], r2 461 vld1.s16 {q4-q5}, [r1,:128], r2 462 vld1.s16 {q6-q7}, [r3,:128], r2 463 464 movrel r1, trans 465 466 tr_8x4 7, d0, d2, d4, d6, d8, d10, d12, d14 467 tr_8x4 7, d1, d3, d5, d7, d9, d11, d13, d15 468 469 @ Transpose each 4x4 block, and swap how d4-d7 and d8-d11 are used. 470 @ Layout before: 471 @ d0 d1 472 @ d2 d3 473 @ d4 d5 474 @ d6 d7 475 @ d8 d9 476 @ d10 d11 477 @ d12 d13 478 @ d14 d15 479 transpose_8x8 d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15 480 @ Now the layout is: 481 @ d0 d8 482 @ d2 d10 483 @ d4 d12 484 @ d6 d14 485 @ d1 d9 486 @ d3 d11 487 @ d5 d13 488 @ d7 d15 489 490 tr_8x4 20 - \bitdepth, d0, d2, d4, d6, d1, d3, d5, d7 491 vswp d0, d8 492 tr_8x4 20 - \bitdepth, d0, d10, d12, d14, d9, d11, d13, d15 493 vswp d0, d8 494 495 transpose_8x8 d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15 496 497 mov r1, r0 498 mov r2, #64 499 add r3, r0, #32 500 vst1.s16 {q0-q1}, [r1,:128], r2 501 vst1.s16 {q2-q3}, [r3,:128], r2 502 vst1.s16 {q4-q5}, [r1,:128], r2 503 vst1.s16 {q6-q7}, [r3,:128], r2 504 505 vpop {q4-q7} 506 bx lr 507endfunc 508.endm 509 510.macro butterfly e, o, tmp_p, tmp_m 511 vadd.s32 \tmp_p, \e, \o 512 vsub.s32 \tmp_m, \e, \o 513.endm 514 515.macro tr16_8x4 in0, in1, in2, in3, in4, in5, in6, in7, offset 516 tr_4x4_8 \in0, \in2, \in4, \in6, q8, q9, q10, q11, q12, q13, q14, q15 517 518 vmull.s16 q12, \in1, \in0[0] 519 vmull.s16 q13, \in1, \in0[1] 520 vmull.s16 q14, \in1, \in0[2] 521 vmull.s16 q15, \in1, \in0[3] 522 sum_sub q12, \in3, \in0[1], + 523 sum_sub q13, \in3, \in0[3], - 524 sum_sub q14, \in3, \in0[0], - 525 sum_sub q15, \in3, \in0[2], - 526 527 sum_sub q12, \in5, \in0[2], + 528 sum_sub q13, \in5, \in0[0], - 529 sum_sub q14, \in5, \in0[3], + 530 sum_sub q15, \in5, \in0[1], + 531 532 sum_sub q12, \in7, \in0[3], + 533 sum_sub q13, \in7, \in0[2], - 534 sum_sub q14, \in7, \in0[1], + 535 sum_sub q15, \in7, \in0[0], - 536 537 butterfly q8, q12, q0, q7 538 butterfly q9, q13, q1, q6 539 butterfly q10, q14, q2, q5 540 butterfly q11, q15, q3, q4 541 add r4, sp, #\offset 542 vst1.s32 {q0-q1}, [r4, :128]! 543 vst1.s32 {q2-q3}, [r4, :128]! 544 vst1.s32 {q4-q5}, [r4, :128]! 545 vst1.s32 {q6-q7}, [r4, :128] 546.endm 547 548.macro load16 in0, in1, in2, in3, in4, in5, in6, in7 549 vld1.s16 {\in0}, [r1, :64], r2 550 vld1.s16 {\in1}, [r3, :64], r2 551 vld1.s16 {\in2}, [r1, :64], r2 552 vld1.s16 {\in3}, [r3, :64], r2 553 vld1.s16 {\in4}, [r1, :64], r2 554 vld1.s16 {\in5}, [r3, :64], r2 555 vld1.s16 {\in6}, [r1, :64], r2 556 vld1.s16 {\in7}, [r3, :64], r2 557.endm 558 559.macro add_member in, t0, t1, t2, t3, t4, t5, t6, t7, op0, op1, op2, op3, op4, op5, op6, op7 560 sum_sub q5, \in, \t0, \op0 561 sum_sub q6, \in, \t1, \op1 562 sum_sub q7, \in, \t2, \op2 563 sum_sub q8, \in, \t3, \op3 564 sum_sub q9, \in, \t4, \op4 565 sum_sub q10, \in, \t5, \op5 566 sum_sub q11, \in, \t6, \op6 567 sum_sub q12, \in, \t7, \op7 568.endm 569 570.macro butterfly16 in0, in1, in2, in3, in4, in5, in6, in7 571 vadd.s32 q4, \in0, \in1 572 vsub.s32 \in0, \in0, \in1 573 vadd.s32 \in1, \in2, \in3 574 vsub.s32 \in2, \in2, \in3 575 vadd.s32 \in3, \in4, \in5 576 vsub.s32 \in4, \in4, \in5 577 vadd.s32 \in5, \in6, \in7 578 vsub.s32 \in6, \in6, \in7 579.endm 580 581.macro store16 in0, in1, in2, in3, in4, in5, in6, in7, rx 582 vst1.s16 \in0, [r1, :64], r2 583 vst1.s16 \in1, [r3, :64], \rx 584 vst1.s16 \in2, [r1, :64], r2 585 vst1.s16 \in3, [r3, :64], \rx 586 vst1.s16 \in4, [r1, :64], r2 587 vst1.s16 \in5, [r3, :64], \rx 588 vst1.s16 \in6, [r1, :64], r2 589 vst1.s16 \in7, [r3, :64], \rx 590.endm 591 592.macro scale out0, out1, out2, out3, out4, out5, out6, out7, in0, in1, in2, in3, in4, in5, in6, in7, shift 593 vqrshrn.s32 \out0, \in0, \shift 594 vqrshrn.s32 \out1, \in1, \shift 595 vqrshrn.s32 \out2, \in2, \shift 596 vqrshrn.s32 \out3, \in3, \shift 597 vqrshrn.s32 \out4, \in4, \shift 598 vqrshrn.s32 \out5, \in5, \shift 599 vqrshrn.s32 \out6, \in6, \shift 600 vqrshrn.s32 \out7, \in7, \shift 601.endm 602 603@stores in1, in2, in4, in6 ascending from off1 and 604@stores in1, in3, in5, in7 descending from off2 605.macro store_to_stack off1, off2, in0, in2, in4, in6, in7, in5, in3, in1 606 add r1, sp, #\off1 607 add r3, sp, #\off2 608 mov r2, #-16 609 vst1.s32 {\in0}, [r1, :128]! 610 vst1.s32 {\in1}, [r3, :128], r2 611 vst1.s32 {\in2}, [r1, :128]! 612 vst1.s32 {\in3}, [r3, :128], r2 613 vst1.s32 {\in4}, [r1, :128]! 614 vst1.s32 {\in5}, [r3, :128], r2 615 vst1.s32 {\in6}, [r1, :128] 616 vst1.s32 {\in7}, [r3, :128] 617.endm 618 619.macro tr_16x4 name, shift, offset, step 620function func_tr_16x4_\name 621 mov r1, r5 622 add r3, r5, #(\step * 64) 623 mov r2, #(\step * 128) 624 load16 d0, d1, d2, d3, d4, d5, d6, d7 625 movrel r1, trans 626 627 tr16_8x4 d0, d1, d2, d3, d4, d5, d6, d7, \offset 628 629 add r1, r5, #(\step * 32) 630 add r3, r5, #(\step * 3 *32) 631 mov r2, #(\step * 128) 632 load16 d8, d9, d2, d3, d4, d5, d6, d7 633 movrel r1, trans + 16 634 vld1.s16 {q0}, [r1, :128] 635 vmull.s16 q5, d8, d0[0] 636 vmull.s16 q6, d8, d0[1] 637 vmull.s16 q7, d8, d0[2] 638 vmull.s16 q8, d8, d0[3] 639 vmull.s16 q9, d8, d1[0] 640 vmull.s16 q10, d8, d1[1] 641 vmull.s16 q11, d8, d1[2] 642 vmull.s16 q12, d8, d1[3] 643 644 add_member d9, d0[1], d1[0], d1[3], d1[1], d0[2], d0[0], d0[3], d1[2], +, +, +, -, -, -, -, - 645 add_member d2, d0[2], d1[3], d0[3], d0[1], d1[2], d1[0], d0[0], d1[1], +, +, -, -, -, +, +, + 646 add_member d3, d0[3], d1[1], d0[1], d1[3], d0[0], d1[2], d0[2], d1[0], +, -, -, +, +, +, -, - 647 add_member d4, d1[0], d0[2], d1[2], d0[0], d1[3], d0[1], d1[1], d0[3], +, -, -, +, -, -, +, + 648 add_member d5, d1[1], d0[0], d1[0], d1[2], d0[1], d0[3], d1[3], d0[2], +, -, +, +, -, +, +, - 649 add_member d6, d1[2], d0[3], d0[0], d0[2], d1[1], d1[3], d1[0], d0[1], +, -, +, -, +, +, -, + 650 add_member d7, d1[3], d1[2], d1[1], d1[0], d0[3], d0[2], d0[1], d0[0], +, -, +, -, +, -, +, - 651 652 add r4, sp, #\offset 653 vld1.s32 {q0-q1}, [r4, :128]! 654 vld1.s32 {q2-q3}, [r4, :128]! 655 656 butterfly16 q0, q5, q1, q6, q2, q7, q3, q8 657 .if \shift > 0 658 scale d26, d27, d28, d29, d30, d31, d16, d17, q4, q0, q5, q1, q6, q2, q7, q3, \shift 659 transpose8_4x4 d26, d28, d30, d16 660 transpose8_4x4 d17, d31, d29, d27 661 mov r1, r6 662 add r3, r6, #(24 +3*32) 663 mov r2, #32 664 mov r4, #-32 665 store16 d26, d27, d28, d29, d30, d31, d16, d17, r4 666 .else 667 store_to_stack \offset, (\offset + 240), q4, q5, q6, q7, q3, q2, q1, q0 668 .endif 669 670 add r4, sp, #(\offset + 64) 671 vld1.s32 {q0-q1}, [r4, :128]! 672 vld1.s32 {q2-q3}, [r4, :128] 673 butterfly16 q0, q9, q1, q10, q2, q11, q3, q12 674 .if \shift > 0 675 scale d26, d27, d28, d29, d30, d31, d8, d9, q4, q0, q9, q1, q10, q2, q11, q3, \shift 676 transpose8_4x4 d26, d28, d30, d8 677 transpose8_4x4 d9, d31, d29, d27 678 679 add r1, r6, #8 680 add r3, r6, #(16 + 3 * 32) 681 mov r2, #32 682 mov r4, #-32 683 store16 d26, d27, d28, d29, d30, d31, d8, d9, r4 684 .else 685 store_to_stack (\offset + 64), (\offset + 176), q4, q9, q10, q11, q3, q2, q1, q0 686 .endif 687 688 bx lr 689endfunc 690.endm 691 692.macro idct_16x16 bitdepth 693function ff_hevc_idct_16x16_\bitdepth\()_neon, export=1 694@r0 - coeffs 695 push {r4-r7, lr} 696 vpush {q4-q7} 697 698 @ Align the stack, allocate a temp buffer 699T mov r7, sp 700T and r7, r7, #15 701A and r7, sp, #15 702 add r7, r7, #640 703 sub sp, sp, r7 704 705.irp i, 0, 1, 2, 3 706 add r5, r0, #(8 * \i) 707 add r6, sp, #(8 * \i * 16) 708 bl func_tr_16x4_firstpass 709.endr 710 711.irp i, 0, 1, 2, 3 712 add r5, sp, #(8 * \i) 713 add r6, r0, #(8 * \i * 16) 714 bl func_tr_16x4_secondpass_\bitdepth 715.endr 716 717 add sp, sp, r7 718 719 vpop {q4-q7} 720 pop {r4-r7, pc} 721endfunc 722.endm 723 724.macro load32 725 add r1, r5, #64 726 add r3, r1, #128 727 mov r2, #256 728 vld1.s16 {d4}, [r1, :64], r2 729 vld1.s16 {d5}, [r3, :64], r2 730 vld1.s16 {d6}, [r1, :64], r2 731 vld1.s16 {d7}, [r3, :64], r2 732 vld1.s16 {d8}, [r1, :64], r2 733 vld1.s16 {d9}, [r3, :64], r2 734 vld1.s16 {d10}, [r1, :64], r2 735 vld1.s16 {d11}, [r3, :64], r2 736 vld1.s16 {d12}, [r1, :64], r2 737 vld1.s16 {d13}, [r3, :64], r2 738 vld1.s16 {d14}, [r1, :64], r2 739 vld1.s16 {d15}, [r3, :64], r2 740 vld1.s16 {d16}, [r1, :64], r2 741 vld1.s16 {d17}, [r3, :64], r2 742 vld1.s16 {d18}, [r1, :64], r2 743 vld1.s16 {d19}, [r3, :64], r2 744.endm 745 746.macro add_member32 in, t0, t1, t2, t3, op0, op1, op2, op3 747 sum_sub q10, \in, \t0, \op0 748 sum_sub q11, \in, \t1, \op1 749 sum_sub q12, \in, \t2, \op2 750 sum_sub q13, \in, \t3, \op3 751.endm 752 753.macro butterfly32 in0, in1, in2, in3 754 vadd.s32 q1, \in0, \in1 755 vsub.s32 \in0, \in0, \in1 756 vadd.s32 \in1, \in2, \in3 757 vsub.s32 \in2, \in2, \in3 758.endm 759 760.macro scale32 out0, out1, out2, out3, in0, in1, in2, in3, shift 761 vqrshrn.s32 \out0, \in0, \shift 762 vqrshrn.s32 \out1, \in1, \shift 763 vqrshrn.s32 \out2, \in2, \shift 764 vqrshrn.s32 \out3, \in3, \shift 765.endm 766 767.macro multiply in 768 vmull.s16 q10, d4, \in[0] 769 vmull.s16 q11, d4, \in[1] 770 vmull.s16 q12, d4, \in[2] 771 vmull.s16 q13, d4, \in[3] 772.endm 773 774.macro scale_store shift 775 vld1.s16 {q14-q15}, [r4, :128]! 776 butterfly32 q14, q10, q15, q11 777 scale32 d22, d23, d20, d21, q1, q14, q10, q15, \shift 778 779 vld1.s16 {q14-q15}, [r4, :128]! 780 butterfly32 q14, q12, q15, q13 781 scale32 d2, d3, d28, d29, q1, q14, q12, q15, \shift 782 transpose8_4x4 d22, d20, d2, d28 783 transpose8_4x4 d29, d3, d21, d23 784 store16 d22, d23, d20, d21, d2, d3, d28, d29, r8 785 786 @ reload multiplication coefficiens to q1 787 vld1.s16 {q1}, [r9, :128] 788.endm 789 790function tr_block1 791 multiply d0 792 add_member32 d5, d0[1], d1[0], d1[3], d2[2], +, +, +, + 793 add_member32 d6, d0[2], d1[3], d3[0], d3[2], +, +, +, - 794 add_member32 d7, d0[3], d2[2], d3[2], d1[3], +, +, -, - 795 add_member32 d8, d1[0], d3[1], d2[1], d0[0], +, +, -, - 796 add_member32 d9, d1[1], d3[3], d1[0], d1[2], +, -, -, - 797 add_member32 d10, d1[2], d3[0], d0[0], d3[1], +, -, -, - 798 add_member32 d11, d1[3], d2[1], d1[1], d2[3], +, -, -, + 799 add_member32 d12, d2[0], d1[2], d2[2], d1[0], +, -, -, + 800 add_member32 d13, d2[1], d0[3], d3[3], d0[2], +, -, -, + 801 add_member32 d14, d2[2], d0[1], d2[3], d2[1], +, -, +, + 802 add_member32 d15, d2[3], d0[2], d1[2], d3[3], +, -, +, - 803 add_member32 d16, d3[0], d1[1], d0[1], d2[0], +, -, +, - 804 add_member32 d17, d3[1], d2[0], d0[3], d0[1], +, -, +, - 805 add_member32 d18, d3[2], d2[3], d2[0], d1[1], +, -, +, - 806 add_member32 d19, d3[3], d3[2], d3[1], d3[0], +, -, +, - 807 bx lr 808endfunc 809 810function tr_block2 811 multiply d1 812 add_member32 d5, d3[1], d3[3], d3[0], d2[1], +, -, -, - 813 add_member32 d6, d2[1], d1[0], d0[0], d1[1], -, -, -, - 814 add_member32 d7, d0[0], d1[2], d3[1], d2[3], -, -, -, + 815 add_member32 d8, d2[0], d3[2], d1[1], d0[3], -, +, +, + 816 add_member32 d9, d3[2], d0[3], d1[3], d3[1], +, +, +, - 817 add_member32 d10, d1[1], d1[3], d2[3], d0[0], +, +, -, - 818 add_member32 d11, d0[3], d3[1], d0[1], d3[3], +, -, -, + 819 add_member32 d12, d3[0], d0[2], d3[2], d0[1], +, -, -, + 820 add_member32 d13, d2[2], d2[0], d1[0], d3[2], -, -, +, + 821 add_member32 d14, d0[1], d3[0], d2[0], d0[2], -, +, +, - 822 add_member32 d15, d1[3], d0[1], d2[2], d3[0], -, +, -, - 823 add_member32 d16, d3[3], d2[1], d0[2], d1[0], +, +, -, + 824 add_member32 d17, d1[2], d2[3], d3[3], d2[2], +, -, -, + 825 add_member32 d18, d0[2], d0[1], d0[3], d1[2], +, -, +, - 826 add_member32 d19, d2[3], d2[2], d2[1], d2[0], +, -, +, - 827 bx lr 828endfunc 829 830function tr_block3 831 multiply d2 832 add_member32 d5, d1[2], d0[3], d0[0], d0[2], -, -, -, - 833 add_member32 d6, d2[2], d3[3], d2[3], d1[2], -, -, +, + 834 add_member32 d7, d1[0], d0[2], d2[1], d3[3], +, +, +, - 835 add_member32 d8, d3[0], d2[2], d0[1], d1[3], +, -, -, - 836 add_member32 d9, d0[2], d2[0], d3[0], d0[0], -, -, +, + 837 add_member32 d10, d3[2], d1[0], d2[0], d2[2], -, +, +, - 838 add_member32 d11, d0[0], d3[2], d0[2], d3[0], +, +, -, - 839 add_member32 d12, d3[3], d0[1], d3[1], d0[3], -, -, +, + 840 add_member32 d13, d0[1], d2[3], d1[3], d1[1], -, +, +, - 841 add_member32 d14, d3[1], d1[3], d0[3], d3[2], +, +, -, + 842 add_member32 d15, d0[3], d1[1], d3[2], d2[0], +, -, +, + 843 add_member32 d16, d2[3], d3[1], d1[2], d0[1], -, -, +, - 844 add_member32 d17, d1[1], d0[0], d1[0], d2[1], -, +, -, + 845 add_member32 d18, d2[1], d3[0], d3[3], d3[1], +, -, +, + 846 add_member32 d19, d1[3], d1[2], d1[1], d1[0], +, -, +, - 847 bx lr 848endfunc 849 850function tr_block4 851 multiply d3 852 add_member32 d5, d1[1], d2[0], d2[3], d3[2], -, -, -, - 853 add_member32 d6, d0[0], d0[3], d2[0], d3[1], +, +, +, + 854 add_member32 d7, d2[0], d0[0], d1[1], d3[0], -, -, -, - 855 add_member32 d8, d3[3], d1[2], d0[2], d2[3], +, +, +, + 856 add_member32 d9, d2[1], d2[3], d0[0], d2[2], +, -, -, - 857 add_member32 d10, d0[2], d3[3], d0[3], d2[1], -, -, +, + 858 add_member32 d11, d1[0], d2[2], d1[2], d2[0], +, +, -, - 859 add_member32 d12, d2[3], d1[1], d2[1], d1[3], -, -, +, + 860 add_member32 d13, d3[1], d0[1], d3[0], d1[2], -, +, -, - 861 add_member32 d14, d1[2], d1[0], d3[3], d1[1], +, -, +, + 862 add_member32 d15, d0[1], d2[1], d3[1], d1[0], -, +, +, - 863 add_member32 d16, d1[3], d3[2], d2[2], d0[3], +, -, -, + 864 add_member32 d17, d3[2], d3[0], d1[3], d0[2], -, -, +, - 865 add_member32 d18, d2[2], d1[3], d1[0], d0[1], -, +, -, + 866 add_member32 d19, d0[3], d0[2], d0[1], d0[0], +, -, +, - 867 bx lr 868endfunc 869 870.macro tr_32x4 name, shift 871function func_tr_32x4_\name 872 mov r10, lr 873 bl func_tr_16x4_noscale 874 875 load32 876 movrel r9, trans + 32 877 vld1.s16 {q0}, [r9, :128]! 878 vld1.s16 {q1}, [r9, :128] 879 880 bl tr_block1 881 882 add r4, sp, #2048 883 vld1.s16 {q14-q15}, [r4, :128]! 884 butterfly32 q14, q10, q15, q11 885 scale32 d22, d23, d20, d21, q1, q14, q10, q15, \shift 886 887 vld1.s16 {q14-q15}, [r4, :128]! 888 butterfly32 q14, q12, q15, q13 889 scale32 d2, d3, d28, d29, q1, q14, q12, q15, \shift 890 891 transpose8_4x4 d22, d20, d2, d28 892 transpose8_4x4 d29, d3, d21, d23 893 mov r1, r11 894 mov r2, #64 895 mov r8, #-64 896 add r3, r11, #(56 + 3 * 64) 897 store16 d22, d23, d20, d21, d2, d3, d28, d29, r8 898 899 @ reload multiplication coefficiens to q1 900 vld1.s16 {q1}, [r9, :128] 901 902 bl tr_block2 903 add r1, r11, #8 904 add r3, r11, #(48 + 3 * 64) 905 mov r2, #64 906 mov r8, #-64 907 scale_store \shift 908 909 bl tr_block3 910 add r1, r11, #16 911 add r3, r11, #(40 + 3 * 64) 912 mov r2, #64 913 mov r8, #-64 914 scale_store \shift 915 916 bl tr_block4 917 add r1, r11, #24 918 add r3, r11, #(32 + 3 * 64) 919 mov r2, #64 920 mov r8, #-64 921 scale_store \shift 922 923 bx r10 924endfunc 925.endm 926 927.macro idct_32x32 bitdepth 928function ff_hevc_idct_32x32_\bitdepth\()_neon, export=1 929@r0 - coeffs 930 push {r4-r11, lr} 931 vpush {q4-q7} 932 933 @ Align the stack, allocate a temp buffer 934T mov r7, sp 935T and r7, r7, #15 936A and r7, sp, #15 937 add r7, r7, #2432 938 sub sp, sp, r7 939 940.irp i, 0, 1, 2, 3, 4, 5, 6, 7 941 add r5, r0, #(8 * \i) 942 add r11, sp, #(8 * \i * 32) 943 bl func_tr_32x4_firstpass 944.endr 945 946.irp i, 0, 1, 2, 3, 4, 5, 6, 7 947 add r5, sp, #(8 * \i) 948 add r11, r0, #(8 * \i * 32) 949 bl func_tr_32x4_secondpass_\bitdepth 950.endr 951 952 add sp, sp, r7 953 vpop {q4-q7} 954 pop {r4-r11, pc} 955endfunc 956.endm 957 958tr_16x4 firstpass, 7, 512, 1 959tr_16x4 secondpass_8, 20 - 8, 512, 1 960tr_16x4 secondpass_10, 20 - 10, 512, 1 961tr_16x4 noscale, 0, 2048, 4 962.ltorg 963tr_32x4 firstpass, 7 964tr_32x4 secondpass_8, 20 - 8 965tr_32x4 secondpass_10, 20 - 10 966.ltorg 967 968idct_4x4 8 969idct_4x4_dc 8 970idct_4x4 10 971idct_4x4_dc 10 972idct_8x8 8 973idct_8x8_dc 8 974idct_8x8 10 975idct_8x8_dc 10 976idct_16x16 8 977idct_16x16_dc 8 978idct_16x16 10 979idct_16x16_dc 10 980idct_32x32 8 981idct_32x32_dc 8 982idct_32x32 10 983idct_32x32_dc 10 984 985/* uses registers q2 - q9 for temp values */ 986/* TODO: reorder */ 987.macro tr4_luma_shift r0, r1, r2, r3, shift 988 vaddl.s16 q5, \r0, \r2 // c0 = src0 + src2 989 vaddl.s16 q2, \r2, \r3 // c1 = src2 + src3 990 vsubl.s16 q4, \r0, \r3 // c2 = src0 - src3 991 vmull.s16 q6, \r1, d0[0] // c3 = 74 * src1 992 993 vaddl.s16 q7, \r0, \r3 // src0 + src3 994 vsubw.s16 q7, q7, \r2 // src0 - src2 + src3 995 vmul.s32 q7, q7, d0[0] // dst2 = 74 * (src0 - src2 + src3) 996 997 vmul.s32 q8, q5, d0[1] // 29 * c0 998 vmul.s32 q9, q2, d1[0] // 55 * c1 999 vadd.s32 q8, q9 // 29 * c0 + 55 * c1 1000 vadd.s32 q8, q6 // dst0 = 29 * c0 + 55 * c1 + c3 1001 1002 vmul.s32 q2, q2, d0[1] // 29 * c1 1003 vmul.s32 q9, q4, d1[0] // 55 * c2 1004 vsub.s32 q9, q2 // 55 * c2 - 29 * c1 1005 vadd.s32 q9, q6 // dst1 = 55 * c2 - 29 * c1 + c3 1006 1007 vmul.s32 q5, q5, d1[0] // 55 * c0 1008 vmul.s32 q4, q4, d0[1] // 29 * c2 1009 vadd.s32 q5, q4 // 55 * c0 + 29 * c2 1010 vsub.s32 q5, q6 // dst3 = 55 * c0 + 29 * c2 - c3 1011 1012 vqrshrn.s32 \r0, q8, \shift 1013 vqrshrn.s32 \r1, q9, \shift 1014 vqrshrn.s32 \r2, q7, \shift 1015 vqrshrn.s32 \r3, q5, \shift 1016.endm 1017 1018.ltorg 1019function ff_hevc_transform_luma_4x4_neon_8, export=1 1020 vpush {d8-d15} 1021 vld1.16 {q14, q15}, [r0] // coeffs 1022 ldr r3, =0x4a // 74 1023 vmov.32 d0[0], r3 1024 ldr r3, =0x1d // 29 1025 vmov.32 d0[1], r3 1026 ldr r3, =0x37 // 55 1027 vmov.32 d1[0], r3 1028 1029 tr4_luma_shift d28, d29, d30, d31, #7 1030 1031 vtrn.16 d28, d29 1032 vtrn.16 d30, d31 1033 vtrn.32 q14, q15 1034 1035 tr4_luma_shift d28, d29, d30, d31, #12 1036 1037 vtrn.16 d28, d29 1038 vtrn.16 d30, d31 1039 vtrn.32 q14, q15 1040 vst1.16 {q14, q15}, [r0] 1041 vpop {d8-d15} 1042 bx lr 1043endfunc 1044