1/* 2 * Copyright (c) 2016 Google Inc. 3 * 4 * This file is part of FFmpeg. 5 * 6 * FFmpeg is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * FFmpeg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with FFmpeg; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#include "libavutil/arm/asm.S" 22#include "neon.S" 23 24const itxfm4_coeffs, align=4 25 .short 11585, 0, 6270, 15137 26iadst4_coeffs: 27 .short 5283, 15212, 9929, 13377 28endconst 29 30const iadst8_coeffs, align=4 31 .short 16305, 1606, 14449, 7723, 10394, 12665, 4756, 15679 32idct_coeffs: 33 .short 11585, 0, 6270, 15137, 3196, 16069, 13623, 9102 34 .short 1606, 16305, 12665, 10394, 7723, 14449, 15679, 4756 35 .short 804, 16364, 12140, 11003, 7005, 14811, 15426, 5520 36 .short 3981, 15893, 14053, 8423, 9760, 13160, 16207, 2404 37endconst 38 39const iadst16_coeffs, align=4 40 .short 16364, 804, 15893, 3981, 11003, 12140, 8423, 14053 41 .short 14811, 7005, 13160, 9760, 5520, 15426, 2404, 16207 42endconst 43 44@ Do four 4x4 transposes, using q registers for the subtransposes that don't 45@ need to address the individual d registers. 46@ r0,r1 == rq1, r2,r3 == rq1, etc 47.macro transpose16_q_4x_4x4 rq0, rq1, rq2, rq3, rq4, rq5, rq6, rq7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15 48 vtrn.32 \rq0, \rq1 49 vtrn.32 \rq2, \rq3 50 vtrn.32 \rq4, \rq5 51 vtrn.32 \rq6, \rq7 52 vtrn.16 \r0, \r1 53 vtrn.16 \r2, \r3 54 vtrn.16 \r4, \r5 55 vtrn.16 \r6, \r7 56 vtrn.16 \r8, \r9 57 vtrn.16 \r10, \r11 58 vtrn.16 \r12, \r13 59 vtrn.16 \r14, \r15 60.endm 61 62@ out1 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14 63@ out2 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14 64@ in/out are d registers 65.macro mbutterfly0 out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4, neg=0 66 vadd.s16 \tmpd1, \in1, \in2 67 vsub.s16 \tmpd2, \in1, \in2 68 vmull.s16 \tmpq3, \tmpd1, d0[0] 69 vmull.s16 \tmpq4, \tmpd2, d0[0] 70.if \neg > 0 71 vneg.s32 \tmpq3, \tmpq3 72.endif 73 vrshrn.s32 \out1, \tmpq3, #14 74 vrshrn.s32 \out2, \tmpq4, #14 75.endm 76 77@ Same as mbutterfly0 above, but treating the input in in2 as zero, 78@ writing the same output into both out1 and out2. 79.macro mbutterfly0_h out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4 80 vmull.s16 \tmpq3, \in1, d0[0] 81 vrshrn.s32 \out1, \tmpq3, #14 82 vrshrn.s32 \out2, \tmpq3, #14 83.endm 84 85@ out1,out2 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14 86@ out3,out4 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14 87@ Same as mbutterfly0, but with input being 2 q registers, output 88@ being 4 d registers. 89@ This can do with either 4 or 6 temporary q registers. 90.macro dmbutterfly0 out1, out2, out3, out4, in1, in2, tmpq1, tmpq2, tmpd11, tmpd12, tmpd21, tmpd22, tmpq3, tmpq4, tmpq5, tmpq6 91 vadd.s16 \tmpq1, \in1, \in2 92 vsub.s16 \tmpq2, \in1, \in2 93 vmull.s16 \tmpq3, \tmpd11, d0[0] 94 vmull.s16 \tmpq4, \tmpd12, d0[0] 95.ifb \tmpq5 96 vrshrn.s32 \out1, \tmpq3, #14 97 vrshrn.s32 \out2, \tmpq4, #14 98 vmull.s16 \tmpq3, \tmpd21, d0[0] 99 vmull.s16 \tmpq4, \tmpd22, d0[0] 100 vrshrn.s32 \out3, \tmpq3, #14 101 vrshrn.s32 \out4, \tmpq4, #14 102.else 103 vmull.s16 \tmpq5, \tmpd21, d0[0] 104 vmull.s16 \tmpq6, \tmpd22, d0[0] 105 vrshrn.s32 \out1, \tmpq3, #14 106 vrshrn.s32 \out2, \tmpq4, #14 107 vrshrn.s32 \out3, \tmpq5, #14 108 vrshrn.s32 \out4, \tmpq6, #14 109.endif 110.endm 111 112@ out1 = in1 * coef1 - in2 * coef2 113@ out2 = in1 * coef2 + in2 * coef1 114@ out are 2 q registers, in are 2 d registers 115.macro mbutterfly_l out1, out2, in1, in2, coef1, coef2 116 vmull.s16 \out1, \in1, \coef1 117 vmlsl.s16 \out1, \in2, \coef2 118 vmull.s16 \out2, \in1, \coef2 119 vmlal.s16 \out2, \in2, \coef1 120.endm 121 122@ out1,out2 = in1,in2 * coef1 - in3,in4 * coef2 123@ out3,out4 = in1,in2 * coef2 + in3,in4 * coef1 124@ out are 4 q registers, in are 4 d registers 125.macro dmbutterfly_l out1, out2, out3, out4, in1, in2, in3, in4, coef1, coef2 126 vmull.s16 \out1, \in1, \coef1 127 vmull.s16 \out2, \in2, \coef1 128 vmull.s16 \out3, \in1, \coef2 129 vmull.s16 \out4, \in2, \coef2 130 vmlsl.s16 \out1, \in3, \coef2 131 vmlsl.s16 \out2, \in4, \coef2 132 vmlal.s16 \out3, \in3, \coef1 133 vmlal.s16 \out4, \in4, \coef1 134.endm 135 136@ inout1 = (inout1 * coef1 - inout2 * coef2 + (1 << 13)) >> 14 137@ inout2 = (inout1 * coef2 + inout2 * coef1 + (1 << 13)) >> 14 138@ inout are 2 d registers, tmp are 2 q registers 139.macro mbutterfly inout1, inout2, coef1, coef2, tmp1, tmp2, neg=0 140 mbutterfly_l \tmp1, \tmp2, \inout1, \inout2, \coef1, \coef2 141.if \neg > 0 142 vneg.s32 \tmp2, \tmp2 143.endif 144 vrshrn.s32 \inout1, \tmp1, #14 145 vrshrn.s32 \inout2, \tmp2, #14 146.endm 147 148@ Same as mbutterfly above, but treating the input in inout2 as zero 149.macro mbutterfly_h1 inout1, inout2, coef1, coef2, tmp1, tmp2 150 vmull.s16 \tmp1, \inout1, \coef1 151 vmull.s16 \tmp2, \inout1, \coef2 152 vrshrn.s32 \inout1, \tmp1, #14 153 vrshrn.s32 \inout2, \tmp2, #14 154.endm 155 156@ Same as mbutterfly above, but treating the input in inout1 as zero 157.macro mbutterfly_h2 inout1, inout2, coef1, coef2, tmp1, tmp2 158 vmull.s16 \tmp1, \inout2, \coef2 159 vmull.s16 \tmp2, \inout2, \coef1 160 vneg.s32 \tmp1, \tmp1 161 vrshrn.s32 \inout2, \tmp2, #14 162 vrshrn.s32 \inout1, \tmp1, #14 163.endm 164 165@ inout1,inout2 = (inout1,inout2 * coef1 - inout3,inout4 * coef2 + (1 << 13)) >> 14 166@ inout3,inout4 = (inout1,inout2 * coef2 + inout3,inout4 * coef1 + (1 << 13)) >> 14 167@ inout are 4 d registers, tmp are 4 q registers 168.macro dmbutterfly inout1, inout2, inout3, inout4, coef1, coef2, tmp1, tmp2, tmp3, tmp4 169 dmbutterfly_l \tmp1, \tmp2, \tmp3, \tmp4, \inout1, \inout2, \inout3, \inout4, \coef1, \coef2 170 vrshrn.s32 \inout1, \tmp1, #14 171 vrshrn.s32 \inout2, \tmp2, #14 172 vrshrn.s32 \inout3, \tmp3, #14 173 vrshrn.s32 \inout4, \tmp4, #14 174.endm 175 176@ out1 = in1 + in2 177@ out2 = in1 - in2 178.macro butterfly out1, out2, in1, in2 179 vadd.s16 \out1, \in1, \in2 180 vsub.s16 \out2, \in1, \in2 181.endm 182 183@ out1 = in1 - in2 184@ out2 = in1 + in2 185.macro butterfly_r out1, out2, in1, in2 186 vsub.s16 \out1, \in1, \in2 187 vadd.s16 \out2, \in1, \in2 188.endm 189 190@ out1 = (in1 + in2 + (1 << 13)) >> 14 191@ out2 = (in1 - in2 + (1 << 13)) >> 14 192@ out are 2 d registers, in are 2 q registers, tmp are 2 q registers 193.macro butterfly_n out1, out2, in1, in2, tmp1, tmp2 194 vadd.s32 \tmp1, \in1, \in2 195 vsub.s32 \tmp2, \in1, \in2 196 vrshrn.s32 \out1, \tmp1, #14 197 vrshrn.s32 \out2, \tmp2, #14 198.endm 199 200@ out1,out2 = (in1,in2 + in3,in4 + (1 << 13)) >> 14 201@ out3,out4 = (in1,in2 - in3,in4 + (1 << 13)) >> 14 202@ out are 4 d registers, in are 4 q registers, tmp are 4 q registers 203.macro dbutterfly_n out1, out2, out3, out4, in1, in2, in3, in4, tmp1, tmp2, tmp3, tmp4 204 vadd.s32 \tmp1, \in1, \in3 205 vadd.s32 \tmp2, \in2, \in4 206 vsub.s32 \tmp3, \in1, \in3 207 vsub.s32 \tmp4, \in2, \in4 208 vrshrn.s32 \out1, \tmp1, #14 209 vrshrn.s32 \out2, \tmp2, #14 210 vrshrn.s32 \out3, \tmp3, #14 211 vrshrn.s32 \out4, \tmp4, #14 212.endm 213 214 215.macro iwht4 c0, c1, c2, c3 216 vadd.i16 \c0, \c0, \c1 217 vsub.i16 d17, \c2, \c3 218 vsub.i16 d16, \c0, d17 219 vshr.s16 d16, d16, #1 220 vsub.i16 \c2, d16, \c1 221 vsub.i16 \c1, d16, \c3 222 vadd.i16 \c3, d17, \c2 223 vsub.i16 \c0, \c0, \c1 224.endm 225 226.macro idct4 c0, c1, c2, c3 227 vmull.s16 q13, \c1, d0[3] 228 vmull.s16 q11, \c1, d0[2] 229 vadd.i16 d16, \c0, \c2 230 vsub.i16 d17, \c0, \c2 231 vmlal.s16 q13, \c3, d0[2] 232 vmull.s16 q9, d16, d0[0] 233 vmull.s16 q10, d17, d0[0] 234 vmlsl.s16 q11, \c3, d0[3] 235 vrshrn.s32 d26, q13, #14 236 vrshrn.s32 d18, q9, #14 237 vrshrn.s32 d20, q10, #14 238 vrshrn.s32 d22, q11, #14 239 vadd.i16 \c0, d18, d26 240 vsub.i16 \c3, d18, d26 241 vadd.i16 \c1, d20, d22 242 vsub.i16 \c2, d20, d22 243.endm 244 245.macro iadst4 c0, c1, c2, c3 246 vmull.s16 q10, \c0, d1[0] 247 vmlal.s16 q10, \c2, d1[1] 248 vmlal.s16 q10, \c3, d1[2] 249 vmull.s16 q11, \c0, d1[2] 250 vmlsl.s16 q11, \c2, d1[0] 251 vsub.s16 \c0, \c0, \c2 252 vmlsl.s16 q11, \c3, d1[1] 253 vadd.s16 \c0, \c0, \c3 254 vmull.s16 q13, \c1, d1[3] 255 vmull.s16 q12, \c0, d1[3] 256 vadd.s32 q14, q10, q13 257 vadd.s32 q1, q11, q13 258 vrshrn.s32 \c0, q14, #14 259 vadd.s32 q10, q10, q11 260 vrshrn.s32 \c1, q1, #14 261 vsub.s32 q10, q10, q13 262 vrshrn.s32 \c2, q12, #14 263 vrshrn.s32 \c3, q10, #14 264.endm 265 266@ The public functions in this file have got the following signature: 267@ void itxfm_add(uint8_t *dst, ptrdiff_t stride, int16_t *block, int eob); 268 269.macro itxfm_func4x4 txfm1, txfm2 270function ff_vp9_\txfm1\()_\txfm2\()_4x4_add_neon, export=1 271.ifc \txfm1,\txfm2 272.ifc \txfm1,idct 273 movrel r12, itxfm4_coeffs 274 vld1.16 {d0}, [r12,:64] 275.endif 276.ifc \txfm1,iadst 277 movrel r12, iadst4_coeffs 278 vld1.16 {d1}, [r12,:64] 279.endif 280.else 281 movrel r12, itxfm4_coeffs 282 vld1.16 {q0}, [r12,:128] 283.endif 284 285 vmov.i16 q15, #0 286.ifc \txfm1\()_\txfm2,idct_idct 287 cmp r3, #1 288 bne 1f 289 @ DC-only for idct/idct 290 vld1.16 {d4[]}, [r2,:16] 291 vmull.s16 q2, d4, d0[0] 292 vrshrn.s32 d4, q2, #14 293 vmull.s16 q2, d4, d0[0] 294 vrshrn.s32 d4, q2, #14 295 vst1.16 {d30[0]}, [r2,:16] 296 vdup.16 q2, d4[0] 297 vmov q3, q2 298 b 2f 299.endif 300 3011: 302 vld1.16 {d4-d7}, [r2,:128] 303 vst1.16 {q15}, [r2,:128]! 304 305.ifc \txfm1,iwht 306 vshr.s16 q2, q2, #2 307 vshr.s16 q3, q3, #2 308.endif 309 310 \txfm1\()4 d4, d5, d6, d7 311 312 vst1.16 {q15}, [r2,:128]! 313 @ Transpose 4x4 with 16 bit elements 314 vtrn.16 d4, d5 315 vtrn.16 d6, d7 316 vtrn.32 q2, q3 317 318 \txfm2\()4 d4, d5, d6, d7 3192: 320 vld1.32 {d0[]}, [r0,:32], r1 321 vld1.32 {d0[1]}, [r0,:32], r1 322.ifnc \txfm1,iwht 323 vrshr.s16 q2, q2, #4 324 vrshr.s16 q3, q3, #4 325.endif 326 vaddw.u8 q2, q2, d0 327 vld1.32 {d1[]}, [r0,:32], r1 328 vld1.32 {d1[1]}, [r0,:32], r1 329 vqmovun.s16 d0, q2 330 sub r0, r0, r1, lsl #2 331 332 vaddw.u8 q3, q3, d1 333 vst1.32 {d0[0]}, [r0,:32], r1 334 vqmovun.s16 d1, q3 335 336 vst1.32 {d0[1]}, [r0,:32], r1 337 vst1.32 {d1[0]}, [r0,:32], r1 338 vst1.32 {d1[1]}, [r0,:32], r1 339 340 bx lr 341endfunc 342.endm 343 344itxfm_func4x4 idct, idct 345itxfm_func4x4 iadst, idct 346itxfm_func4x4 idct, iadst 347itxfm_func4x4 iadst, iadst 348itxfm_func4x4 iwht, iwht 349 350 351.macro idct8 352 dmbutterfly0 d16, d17, d24, d25, q8, q12, q2, q4, d4, d5, d8, d9, q3, q2, q5, q4 @ q8 = t0a, q12 = t1a 353 dmbutterfly d20, d21, d28, d29, d0[2], d0[3], q2, q3, q4, q5 @ q10 = t2a, q14 = t3a 354 dmbutterfly d18, d19, d30, d31, d1[0], d1[1], q2, q3, q4, q5 @ q9 = t4a, q15 = t7a 355 dmbutterfly d26, d27, d22, d23, d1[2], d1[3], q2, q3, q4, q5 @ q13 = t5a, q11 = t6a 356 357 butterfly q2, q14, q8, q14 @ q2 = t0, q14 = t3 358 butterfly q3, q10, q12, q10 @ q3 = t1, q10 = t2 359 butterfly q4, q13, q9, q13 @ q4 = t4, q13 = t5a 360 butterfly q5, q11, q15, q11 @ q5 = t7, q11 = t6a 361 362 butterfly q8, q15, q2, q5 @ q8 = out[0], q15 = out[7] 363 364 dmbutterfly0 d4, d5, d10, d11, q11, q13, q9, q13, d18, d19, d26, d27, q2, q5, q11, q12 @ q2 = t6, q5 = t5 365 366 butterfly q11, q12, q14, q4 @ q11 = out[3], q12 = out[4] 367 butterfly q9, q14, q3, q2 @ q9 = out[1], q14 = out[6] 368 butterfly_r q13, q10, q10, q5 @ q13 = out[5], q10 = out[2] 369.endm 370 371.macro iadst8 372 dmbutterfly_l q4, q5, q2, q3, d30, d31, d16, d17, d2[1], d2[0] @ q4,q5 = t1a, q2,q3 = t0a 373 dmbutterfly_l q8, q15, q6, q7, d22, d23, d24, d25, d3[1], d3[0] @ q8,q15 = t5a, q6,q7 = t4a 374 375 dbutterfly_n d22, d23, d4, d5, q2, q3, q6, q7, q11, q12, q2, q3 @ q11 = t0, q2 = t4 376 377 dbutterfly_n d24, d25, d6, d7, q4, q5, q8, q15, q12, q3, q6, q7 @ q12 = t1, q3 = t5 378 379 dmbutterfly_l q6, q7, q4, q5, d26, d27, d20, d21, d2[3], d2[2] @ q6,q7 = t3a, q4,q5 = t2a 380 dmbutterfly_l q10, q13, q8, q15, d18, d19, d28, d29, d3[3], d3[2] @ q10,q13 = t7a, q8,q15 = t6a 381 382 dbutterfly_n d18, d19, d8, d9, q4, q5, q8, q15, q9, q14, q4, q5 @ q9 = t2, q4 = t6 383 dbutterfly_n d16, d17, d12, d13, q6, q7, q10, q13, q8, q15, q6, q7 @ q8 = t3, q6 = t7 384 385 butterfly q15, q12, q12, q8 @ q15 = -out[7], q12 = t3 386 vneg.s16 q15, q15 @ q15 = out[7] 387 butterfly q8, q9, q11, q9 @ q8 = out[0], q9 = t2 388 389 dmbutterfly_l q10, q11, q5, q7, d4, d5, d6, d7, d0[2], d0[3] @ q10,q11 = t5a, q5,q7 = t4a 390 dmbutterfly_l q2, q3, q13, q14, d12, d13, d8, d9, d0[3], d0[2] @ q2,q3 = t6a, q13,q14 = t7a 391 392 dbutterfly_n d28, d29, d8, d9, q10, q11, q13, q14, q4, q6, q10, q11 @ q14 = out[6], q4 = t7 393 394 dmbutterfly0 d22, d23, d24, d25, q9, q12, q6, q13, d12, d13, d26, d27, q9, q10 @ q11 = -out[3], q12 = out[4] 395 vneg.s16 q11, q11 @ q11 = out[3] 396 397 dbutterfly_n d18, d19, d4, d5, q5, q7, q2, q3, q9, q10, q2, q3 @ q9 = -out[1], q2 = t6 398 vneg.s16 q9, q9 @ q9 = out[1] 399 400 dmbutterfly0 d20, d21, d26, d27, q2, q4, q3, q5, d6, d7, d10, d11, q6, q7 @ q10 = out[2], q13 = -out[5] 401 vneg.s16 q13, q13 @ q13 = out[5] 402.endm 403 404 405.macro itxfm_func8x8 txfm1, txfm2 406function ff_vp9_\txfm1\()_\txfm2\()_8x8_add_neon, export=1 407 @ Push q4-q7 if iadst is used, idct requires 408 @ a few scratch registers less, so only push q4-q5 409 @ if only idct is involved. 410 @ The iadst also uses a few coefficients from 411 @ idct, so those always need to be loaded. 412.ifc \txfm1\()_\txfm2,idct_idct 413 movrel r12, idct_coeffs 414 vpush {q4-q5} 415.else 416 movrel r12, iadst8_coeffs 417 vld1.16 {q1}, [r12,:128]! 418 vpush {q4-q7} 419.endif 420 vld1.16 {q0}, [r12,:128] 421 422 vmov.i16 q2, #0 423 vmov.i16 q3, #0 424 425.ifc \txfm1\()_\txfm2,idct_idct 426 cmp r3, #1 427 bne 1f 428 @ DC-only for idct/idct 429 vld1.16 {d16[]}, [r2,:16] 430 vmull.s16 q8, d16, d0[0] 431 vrshrn.s32 d16, q8, #14 432 vmull.s16 q8, d16, d0[0] 433 vrshrn.s32 d16, q8, #14 434 vdup.16 q8, d16[0] 435 vmov q9, q8 436 vmov q10, q8 437 vmov q11, q8 438 vmov q12, q8 439 vmov q13, q8 440 vmov q14, q8 441 vmov q15, q8 442 vst1.16 {d4[0]}, [r2,:16] 443 b 2f 444.endif 4451: 446 vld1.16 {q8-q9}, [r2,:128]! 447 vld1.16 {q10-q11}, [r2,:128]! 448 vld1.16 {q12-q13}, [r2,:128]! 449 vld1.16 {q14-q15}, [r2,:128]! 450 sub r2, r2, #128 451 vst1.16 {q2-q3}, [r2,:128]! 452 vst1.16 {q2-q3}, [r2,:128]! 453 vst1.16 {q2-q3}, [r2,:128]! 454 vst1.16 {q2-q3}, [r2,:128]! 455 456 \txfm1\()8 457 458 @ Transpose 8x8 with 16 bit elements 459 vswp d17, d24 460 vswp d19, d26 461 vswp d21, d28 462 vswp d23, d30 463 transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15 464 465 \txfm2\()8 4662: 467 mov r3, r0 468 @ Add into the destination 469 vld1.8 {d4}, [r0,:64], r1 470 vrshr.s16 q8, q8, #5 471 vld1.8 {d5}, [r0,:64], r1 472 vrshr.s16 q9, q9, #5 473 vld1.8 {d6}, [r0,:64], r1 474 vrshr.s16 q10, q10, #5 475 vaddw.u8 q8, q8, d4 476 vld1.8 {d7}, [r0,:64], r1 477 vrshr.s16 q11, q11, #5 478 vaddw.u8 q9, q9, d5 479 vld1.8 {d8}, [r0,:64], r1 480 vrshr.s16 q12, q12, #5 481 vaddw.u8 q10, q10, d6 482 vqmovun.s16 d4, q8 483 vld1.8 {d9}, [r0,:64], r1 484 vrshr.s16 q13, q13, #5 485 vaddw.u8 q11, q11, d7 486 vqmovun.s16 d5, q9 487 vld1.8 {d10}, [r0,:64], r1 488 vrshr.s16 q14, q14, #5 489 vaddw.u8 q12, q12, d8 490 vqmovun.s16 d6, q10 491 vld1.8 {d11}, [r0,:64], r1 492 vrshr.s16 q15, q15, #5 493 vaddw.u8 q13, q13, d9 494 vqmovun.s16 d7, q11 495 496 497 vst1.8 {d4}, [r3,:64], r1 498 vaddw.u8 q14, q14, d10 499 vst1.8 {d5}, [r3,:64], r1 500 vqmovun.s16 d8, q12 501 vst1.8 {d6}, [r3,:64], r1 502 vaddw.u8 q15, q15, d11 503 vst1.8 {d7}, [r3,:64], r1 504 vqmovun.s16 d9, q13 505 vst1.8 {d8}, [r3,:64], r1 506 vqmovun.s16 d10, q14 507 vst1.8 {d9}, [r3,:64], r1 508 vqmovun.s16 d11, q15 509 510 vst1.8 {d10}, [r3,:64], r1 511 vst1.8 {d11}, [r3,:64], r1 512 513.ifc \txfm1\()_\txfm2,idct_idct 514 vpop {q4-q5} 515.else 516 vpop {q4-q7} 517.endif 518 bx lr 519endfunc 520.endm 521 522itxfm_func8x8 idct, idct 523itxfm_func8x8 iadst, idct 524.ltorg 525itxfm_func8x8 idct, iadst 526itxfm_func8x8 iadst, iadst 527 528 529function idct16x16_dc_add_neon 530 movrel r12, idct_coeffs 531 vld1.16 {d0}, [r12,:64] 532 533 vmov.i16 q2, #0 534 535 vld1.16 {d16[]}, [r2,:16] 536 vmull.s16 q8, d16, d0[0] 537 vrshrn.s32 d16, q8, #14 538 vmull.s16 q8, d16, d0[0] 539 vrshrn.s32 d16, q8, #14 540 vdup.16 q8, d16[0] 541 vst1.16 {d4[0]}, [r2,:16] 542 543 vrshr.s16 q8, q8, #6 544 545 mov r3, r0 546 mov r12, #16 5471: 548 @ Loop to add the constant from q8 into all 16x16 outputs 549 subs r12, r12, #2 550 vld1.8 {q2}, [r0,:128], r1 551 vaddw.u8 q10, q8, d4 552 vld1.8 {q3}, [r0,:128], r1 553 vaddw.u8 q11, q8, d5 554 vaddw.u8 q12, q8, d6 555 vaddw.u8 q13, q8, d7 556 vqmovun.s16 d4, q10 557 vqmovun.s16 d5, q11 558 vqmovun.s16 d6, q12 559 vst1.8 {q2}, [r3,:128], r1 560 vqmovun.s16 d7, q13 561 vst1.8 {q3}, [r3,:128], r1 562 bne 1b 563 564 bx lr 565endfunc 566.ltorg 567 568.macro idct16_end 569 butterfly d18, d7, d4, d7 @ d18 = t0a, d7 = t7a 570 butterfly d19, d22, d5, d22 @ d19 = t1a, d22 = t6 571 butterfly d4, d26, d20, d26 @ d4 = t2a, d26 = t5 572 butterfly d5, d6, d28, d6 @ d5 = t3a, d6 = t4 573 butterfly d20, d28, d16, d24 @ d20 = t8a, d28 = t11a 574 butterfly d24, d21, d23, d21 @ d24 = t9, d21 = t10 575 butterfly d23, d27, d25, d27 @ d23 = t14, d27 = t13 576 butterfly d25, d29, d29, d17 @ d25 = t15a, d29 = t12a 577 578 mbutterfly0 d27, d21, d27, d21, d16, d30, q8, q15 @ d27 = t13a, d21 = t10a 579 mbutterfly0 d29, d28, d29, d28, d16, d30, q8, q15 @ d29 = t12, d28 = t11 580 581 vswp d27, d29 @ d27 = t12, d29 = t13a 582 vswp d28, d27 @ d28 = t12, d27 = t11 583 butterfly d16, d31, d18, d25 @ d16 = out[0], d31 = out[15] 584 butterfly d17, d30, d19, d23 @ d17 = out[1], d30 = out[14] 585 butterfly_r d25, d22, d22, d24 @ d25 = out[9], d22 = out[6] 586 butterfly d23, d24, d7, d20 @ d23 = out[7], d24 = out[8] 587 butterfly d18, d29, d4, d29 @ d18 = out[2], d29 = out[13] 588 butterfly d19, d28, d5, d28 @ d19 = out[3], d28 = out[12] 589 vmov d4, d21 @ d4 = t10a 590 butterfly d20, d27, d6, d27 @ d20 = out[4], d27 = out[11] 591 butterfly d21, d26, d26, d4 @ d21 = out[5], d26 = out[10] 592 bx lr 593.endm 594 595function idct16 596 mbutterfly0 d16, d24, d16, d24, d4, d6, q2, q3 @ d16 = t0a, d24 = t1a 597 mbutterfly d20, d28, d0[2], d0[3], q2, q3 @ d20 = t2a, d28 = t3a 598 mbutterfly d18, d30, d1[0], d1[1], q2, q3 @ d18 = t4a, d30 = t7a 599 mbutterfly d26, d22, d1[2], d1[3], q2, q3 @ d26 = t5a, d22 = t6a 600 mbutterfly d17, d31, d2[0], d2[1], q2, q3 @ d17 = t8a, d31 = t15a 601 mbutterfly d25, d23, d2[2], d2[3], q2, q3 @ d25 = t9a, d23 = t14a 602 mbutterfly d21, d27, d3[0], d3[1], q2, q3 @ d21 = t10a, d27 = t13a 603 mbutterfly d29, d19, d3[2], d3[3], q2, q3 @ d29 = t11a, d19 = t12a 604 605 butterfly d4, d28, d16, d28 @ d4 = t0, d28 = t3 606 butterfly d5, d20, d24, d20 @ d5 = t1, d20 = t2 607 butterfly d6, d26, d18, d26 @ d6 = t4, d26 = t5 608 butterfly d7, d22, d30, d22 @ d7 = t7, d22 = t6 609 butterfly d16, d25, d17, d25 @ d16 = t8, d25 = t9 610 butterfly d24, d21, d29, d21 @ d24 = t11, d21 = t10 611 butterfly d17, d27, d19, d27 @ d17 = t12, d27 = t13 612 butterfly d29, d23, d31, d23 @ d29 = t15, d23 = t14 613 614 mbutterfly0 d22, d26, d22, d26, d18, d30, q9, q15 @ d22 = t6a, d26 = t5a 615 mbutterfly d23, d25, d0[2], d0[3], q9, q15 @ d23 = t9a, d25 = t14a 616 mbutterfly d27, d21, d0[2], d0[3], q9, q15, neg=1 @ d27 = t13a, d21 = t10a 617 idct16_end 618endfunc 619 620function idct16_half 621 mbutterfly0_h d16, d24, d16, d24, d4, d6, q2, q3 @ d16 = t0a, d24 = t1a 622 mbutterfly_h1 d20, d28, d0[2], d0[3], q2, q3 @ d20 = t2a, d28 = t3a 623 mbutterfly_h1 d18, d30, d1[0], d1[1], q2, q3 @ d18 = t4a, d30 = t7a 624 mbutterfly_h2 d26, d22, d1[2], d1[3], q2, q3 @ d26 = t5a, d22 = t6a 625 mbutterfly_h1 d17, d31, d2[0], d2[1], q2, q3 @ d17 = t8a, d31 = t15a 626 mbutterfly_h2 d25, d23, d2[2], d2[3], q2, q3 @ d25 = t9a, d23 = t14a 627 mbutterfly_h1 d21, d27, d3[0], d3[1], q2, q3 @ d21 = t10a, d27 = t13a 628 mbutterfly_h2 d29, d19, d3[2], d3[3], q2, q3 @ d29 = t11a, d19 = t12a 629 630 butterfly d4, d28, d16, d28 @ d4 = t0, d28 = t3 631 butterfly d5, d20, d24, d20 @ d5 = t1, d20 = t2 632 butterfly d6, d26, d18, d26 @ d6 = t4, d26 = t5 633 butterfly d7, d22, d30, d22 @ d7 = t7, d22 = t6 634 butterfly d16, d25, d17, d25 @ d16 = t8, d25 = t9 635 butterfly d24, d21, d29, d21 @ d24 = t11, d21 = t10 636 butterfly d17, d27, d19, d27 @ d17 = t12, d27 = t13 637 butterfly d29, d23, d31, d23 @ d29 = t15, d23 = t14 638 639 mbutterfly0 d22, d26, d22, d26, d18, d30, q9, q15 @ d22 = t6a, d26 = t5a 640 mbutterfly d23, d25, d0[2], d0[3], q9, q15 @ d23 = t9a, d25 = t14a 641 mbutterfly d27, d21, d0[2], d0[3], q9, q15, neg=1 @ d27 = t13a, d21 = t10a 642 idct16_end 643endfunc 644 645function idct16_quarter 646 vmull.s16 q12, d19, d3[3] 647 vmull.s16 q2, d17, d2[0] 648 vmull.s16 q3, d18, d1[1] 649 vmull.s16 q15, d18, d1[0] 650 vneg.s32 q12, q12 651 vmull.s16 q14, d17, d2[1] 652 vmull.s16 q13, d19, d3[2] 653 vmull.s16 q11, d16, d0[0] 654 vrshrn.s32 d24, q12, #14 655 vrshrn.s32 d16, q2, #14 656 vrshrn.s32 d7, q3, #14 657 vrshrn.s32 d6, q15, #14 658 vrshrn.s32 d29, q14, #14 659 vrshrn.s32 d17, q13, #14 660 vrshrn.s32 d28, q11, #14 661 662 mbutterfly_l q10, q11, d17, d24, d0[2], d0[3] 663 mbutterfly_l q9, q15, d29, d16, d0[2], d0[3] 664 vneg.s32 q11, q11 665 vrshrn.s32 d27, q10, #14 666 vrshrn.s32 d21, q11, #14 667 vrshrn.s32 d23, q9, #14 668 vrshrn.s32 d25, q15, #14 669 vmov d4, d28 670 vmov d5, d28 671 mbutterfly0 d22, d26, d7, d6, d18, d30, q9, q15 672 vmov d20, d28 673 idct16_end 674endfunc 675 676function iadst16 677 movrel r12, iadst16_coeffs 678 vld1.16 {q0-q1}, [r12,:128] 679 680 mbutterfly_l q3, q2, d31, d16, d0[1], d0[0] @ q3 = t1, q2 = t0 681 mbutterfly_l q5, q4, d23, d24, d1[1], d1[0] @ q5 = t9, q4 = t8 682 butterfly_n d31, d24, q3, q5, q6, q5 @ d31 = t1a, d24 = t9a 683 mbutterfly_l q7, q6, d29, d18, d0[3], d0[2] @ q7 = t3, q6 = t2 684 butterfly_n d16, d23, q2, q4, q3, q4 @ d16 = t0a, d23 = t8a 685 686 mbutterfly_l q3, q2, d21, d26, d1[3], d1[2] @ q3 = t11, q2 = t10 687 butterfly_n d29, d26, q7, q3, q4, q3 @ d29 = t3a, d26 = t11a 688 mbutterfly_l q5, q4, d27, d20, d2[1], d2[0] @ q5 = t5, q4 = t4 689 butterfly_n d18, d21, q6, q2, q3, q2 @ d18 = t2a, d21 = t10a 690 691 mbutterfly_l q7, q6, d19, d28, d3[1], d3[0] @ q7 = t13, q6 = t12 692 butterfly_n d20, d28, q5, q7, q2, q7 @ d20 = t5a, d28 = t13a 693 mbutterfly_l q3, q2, d25, d22, d2[3], d2[2] @ q3 = t7, q2 = t6 694 butterfly_n d27, d19, q4, q6, q5, q6 @ d27 = t4a, d19 = t12a 695 696 mbutterfly_l q5, q4, d17, d30, d3[3], d3[2] @ q5 = t15, q4 = t14 697 movrel r12, idct_coeffs 698 vld1.16 {q0}, [r12,:128] 699 butterfly_n d22, d30, q3, q5, q6, q5 @ d22 = t7a, d30 = t15a 700 mbutterfly_l q7, q6, d23, d24, d1[0], d1[1] @ q7 = t9, q6 = t8 701 butterfly_n d25, d17, q2, q4, q3, q4 @ d25 = t6a, d17 = t14a 702 703 mbutterfly_l q2, q3, d28, d19, d1[1], d1[0] @ q2 = t12, q3 = t13 704 butterfly_n d23, d19, q6, q2, q4, q2 @ d23 = t8a, d19 = t12a 705 mbutterfly_l q5, q4, d21, d26, d1[2], d1[3] @ q5 = t11, q4 = t10 706 butterfly_r d4, d27, d16, d27 @ d4 = t4, d27 = t0 707 butterfly_n d24, d28, q7, q3, q6, q3 @ d24 = t9a, d28 = t13a 708 709 mbutterfly_l q6, q7, d30, d17, d1[3], d1[2] @ q6 = t14, q7 = t15 710 butterfly_r d5, d20, d31, d20 @ d5 = t5, d20 = t1 711 butterfly_n d21, d17, q4, q6, q3, q6 @ d21 = t10a, d17 = t14a 712 butterfly_n d26, d30, q5, q7, q4, q7 @ d26 = t11a, d30 = t15a 713 714 butterfly_r d6, d25, d18, d25 @ d6 = t6, d25 = t2 715 butterfly_r d7, d22, d29, d22 @ d7 = t7, d22 = t3 716 717 mbutterfly_l q5, q4, d19, d28, d0[2], d0[3] @ q5 = t13, q4 = t12 718 mbutterfly_l q6, q7, d30, d17, d0[3], d0[2] @ q6 = t14, q7 = t15 719 720 butterfly_n d18, d30, q4, q6, q8, q6 @ d18 = out[2], d30 = t14a 721 butterfly_n d29, d17, q5, q7, q6, q7 @ d29 = -out[13], d17 = t15a 722 vneg.s16 d29, d29 @ d29 = out[13] 723 724 mbutterfly_l q5, q4, d4, d5, d0[2], d0[3] @ q5 = t5a, q4 = t4a 725 mbutterfly_l q6, q7, d7, d6, d0[3], d0[2] @ q6 = t6a, q7 = t7a 726 727 butterfly d2, d6, d27, d25 @ d2 = out[0], d6 = t2a 728 butterfly d3, d7, d23, d21 @ d3 =-out[1], d7 = t10 729 730 butterfly_n d19, d31, q4, q6, q2, q4 @ d19 = -out[3], d31 = t6 731 vneg.s16 d19, d19 @ d19 = out[3] 732 butterfly_n d28, d16, q5, q7, q2, q5 @ d28 = out[12], d16 = t7 733 734 butterfly d5, d8, d20, d22 @ d5 =-out[15],d8 = t3a 735 butterfly d4, d9, d24, d26 @ d4 = out[14],d9 = t11 736 737 mbutterfly0 d23, d24, d6, d8, d10, d11, q6, q7, 1 @ d23 = out[7], d24 = out[8] 738 mbutterfly0 d20, d27, d16, d31, d10, d11, q6, q7 @ d20 = out[4], d27 = out[11] 739 mbutterfly0 d22, d25, d9, d7, d10, d11, q6, q7 @ d22 = out[6], d25 = out[9] 740 mbutterfly0 d21, d26, d30, d17, d10, d11, q6, q7, 1 @ d21 = out[5], d26 = out[10] 741 742 vneg.s16 d31, d5 @ d31 = out[15] 743 vneg.s16 d17, d3 @ d17 = out[1] 744 745 vmov d16, d2 746 vmov d30, d4 747 bx lr 748endfunc 749 750.macro load_add_store coef0, coef1, coef2, coef3 751 vrshr.s16 \coef0, \coef0, #6 752 vrshr.s16 \coef1, \coef1, #6 753 754 vld1.32 {d4[]}, [r0,:32], r1 755 vld1.32 {d4[1]}, [r3,:32], r1 756 vrshr.s16 \coef2, \coef2, #6 757 vrshr.s16 \coef3, \coef3, #6 758 vld1.32 {d5[]}, [r0,:32], r1 759 vld1.32 {d5[1]}, [r3,:32], r1 760 vaddw.u8 \coef0, \coef0, d4 761 vld1.32 {d6[]}, [r0,:32], r1 762 vld1.32 {d6[1]}, [r3,:32], r1 763 vaddw.u8 \coef1, \coef1, d5 764 vld1.32 {d7[]}, [r0,:32], r1 765 vld1.32 {d7[1]}, [r3,:32], r1 766 767 vqmovun.s16 d4, \coef0 768 vqmovun.s16 d5, \coef1 769 sub r0, r0, r1, lsl #2 770 sub r3, r3, r1, lsl #2 771 vaddw.u8 \coef2, \coef2, d6 772 vaddw.u8 \coef3, \coef3, d7 773 vst1.32 {d4[0]}, [r0,:32], r1 774 vst1.32 {d4[1]}, [r3,:32], r1 775 vqmovun.s16 d6, \coef2 776 vst1.32 {d5[0]}, [r0,:32], r1 777 vst1.32 {d5[1]}, [r3,:32], r1 778 vqmovun.s16 d7, \coef3 779 780 vst1.32 {d6[0]}, [r0,:32], r1 781 vst1.32 {d6[1]}, [r3,:32], r1 782 vst1.32 {d7[0]}, [r0,:32], r1 783 vst1.32 {d7[1]}, [r3,:32], r1 784.endm 785 786.macro itxfm16_1d_funcs txfm 787@ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it, 788@ transpose into a horizontal 16x4 slice and store. 789@ r0 = dst (temp buffer) 790@ r1 = slice offset 791@ r2 = src 792function \txfm\()16_1d_4x16_pass1_neon 793 push {lr} 794 795 mov r12, #32 796 vmov.s16 q2, #0 797.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 798 vld1.16 {d\i}, [r2,:64] 799 vst1.16 {d4}, [r2,:64], r12 800.endr 801 802 bl \txfm\()16 803 804 @ Do four 4x4 transposes. Originally, d16-d31 contain the 805 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31 806 @ contain the transposed 4x4 blocks. 807 transpose16_q_4x_4x4 q8, q9, q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 808 809 @ Store the transposed 4x4 blocks horizontally. 810 cmp r1, #12 811 beq 1f 812.irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31 813 vst1.16 {d\i}, [r0,:64]! 814.endr 815 pop {pc} 8161: 817 @ Special case: For the last input column (r1 == 12), 818 @ which would be stored as the last row in the temp buffer, 819 @ don't store the first 4x4 block, but keep it in registers 820 @ for the first slice of the second pass (where it is the 821 @ last 4x4 block). 822 add r0, r0, #8 823 vst1.16 {d20}, [r0,:64]! 824 vst1.16 {d24}, [r0,:64]! 825 vst1.16 {d28}, [r0,:64]! 826 add r0, r0, #8 827 vst1.16 {d21}, [r0,:64]! 828 vst1.16 {d25}, [r0,:64]! 829 vst1.16 {d29}, [r0,:64]! 830 add r0, r0, #8 831 vst1.16 {d22}, [r0,:64]! 832 vst1.16 {d26}, [r0,:64]! 833 vst1.16 {d30}, [r0,:64]! 834 add r0, r0, #8 835 vst1.16 {d23}, [r0,:64]! 836 vst1.16 {d27}, [r0,:64]! 837 vst1.16 {d31}, [r0,:64]! 838 vmov d28, d16 839 vmov d29, d17 840 vmov d30, d18 841 vmov d31, d19 842 pop {pc} 843endfunc 844 845@ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it, 846@ load the destination pixels (from a similar 4x16 slice), add and store back. 847@ r0 = dst 848@ r1 = dst stride 849@ r2 = src (temp buffer) 850@ r3 = slice offset 851function \txfm\()16_1d_4x16_pass2_neon 852 push {lr} 853 mov r12, #32 854.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 855 vld1.16 {d\i}, [r2,:64], r12 856.endr 857 cmp r3, #0 858 beq 1f 859.irp i, 28, 29, 30, 31 860 vld1.16 {d\i}, [r2,:64], r12 861.endr 8621: 863 864 add r3, r0, r1 865 lsl r1, r1, #1 866 bl \txfm\()16 867 868 load_add_store q8, q9, q10, q11 869 load_add_store q12, q13, q14, q15 870 871 pop {pc} 872endfunc 873.endm 874 875itxfm16_1d_funcs idct 876itxfm16_1d_funcs iadst 877 878@ This is the minimum eob value for each subpartition, in increments of 4 879const min_eob_idct_idct_16, align=4 880 .short 0, 10, 38, 89 881endconst 882 883.macro itxfm_func16x16 txfm1, txfm2 884function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1 885.ifc \txfm1\()_\txfm2,idct_idct 886 cmp r3, #1 887 beq idct16x16_dc_add_neon 888.endif 889 push {r4-r8,lr} 890.ifnc \txfm1\()_\txfm2,idct_idct 891 vpush {q4-q7} 892.endif 893 894 @ Align the stack, allocate a temp buffer 895T mov r7, sp 896T and r7, r7, #15 897A and r7, sp, #15 898 add r7, r7, #512 899 sub sp, sp, r7 900 901 mov r4, r0 902 mov r5, r1 903 mov r6, r2 904 905.ifc \txfm1,idct 906 movrel r12, idct_coeffs 907 vld1.16 {q0-q1}, [r12,:128] 908.endif 909 910.ifc \txfm1\()_\txfm2,idct_idct 911 cmp r3, #10 912 ble idct16x16_quarter_add_neon 913 cmp r3, #38 914 ble idct16x16_half_add_neon 915 916 movrel r8, min_eob_idct_idct_16 + 2 917.endif 918 919.irp i, 0, 4, 8, 12 920 add r0, sp, #(\i*32) 921.ifc \txfm1\()_\txfm2,idct_idct 922.if \i > 0 923 ldrh_post r1, r8, #2 924 cmp r3, r1 925 it le 926 movle r1, #(16 - \i)/4 927 ble 1f 928.endif 929.endif 930 mov r1, #\i 931 add r2, r6, #(\i*2) 932 bl \txfm1\()16_1d_4x16_pass1_neon 933.endr 934 935.ifc \txfm1\()_\txfm2,idct_idct 936 b 3f 9371: 938 @ For all-zero slices in pass 1, set d28-d31 to zero, for the in-register 939 @ passthrough of coefficients to pass 2 and clear the end of the temp buffer 940 vmov.i16 q14, #0 941 vmov.i16 q15, #0 9422: 943 subs r1, r1, #1 944.rept 4 945 vst1.16 {q14-q15}, [r0,:128]! 946.endr 947 bne 2b 9483: 949.endif 950 951.ifc \txfm1\()_\txfm2,iadst_idct 952 movrel r12, idct_coeffs 953 vld1.16 {q0-q1}, [r12,:128] 954.endif 955.irp i, 0, 4, 8, 12 956 add r0, r4, #(\i) 957 mov r1, r5 958 add r2, sp, #(\i*2) 959 mov r3, #\i 960 bl \txfm2\()16_1d_4x16_pass2_neon 961.endr 962 963 add sp, sp, r7 964.ifnc \txfm1\()_\txfm2,idct_idct 965 vpop {q4-q7} 966.endif 967 pop {r4-r8,pc} 968endfunc 969.endm 970 971itxfm_func16x16 idct, idct 972itxfm_func16x16 iadst, idct 973itxfm_func16x16 idct, iadst 974itxfm_func16x16 iadst, iadst 975.ltorg 976 977function idct16_1d_4x16_pass1_quarter_neon 978 push {lr} 979 mov r12, #32 980 vmov.s16 q2, #0 981.irp i, 16, 17, 18, 19 982 vld1.16 {d\i}, [r2,:64] 983 vst1.16 {d4}, [r2,:64], r12 984.endr 985 986 bl idct16_quarter 987 988 @ Do four 4x4 transposes. Originally, d16-d31 contain the 989 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31 990 @ contain the transposed 4x4 blocks. 991 transpose16_q_4x_4x4 q8, q9, q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 992 993 @ Store the transposed 4x4 blocks horizontally. 994 @ The first 4x4 block is kept in registers for the second pass, 995 @ store the rest in the temp buffer. 996 add r0, r0, #8 997 vst1.16 {d20}, [r0,:64]! 998 vst1.16 {d24}, [r0,:64]! 999 vst1.16 {d28}, [r0,:64]! 1000 add r0, r0, #8 1001 vst1.16 {d21}, [r0,:64]! 1002 vst1.16 {d25}, [r0,:64]! 1003 vst1.16 {d29}, [r0,:64]! 1004 add r0, r0, #8 1005 vst1.16 {d22}, [r0,:64]! 1006 vst1.16 {d26}, [r0,:64]! 1007 vst1.16 {d30}, [r0,:64]! 1008 add r0, r0, #8 1009 vst1.16 {d23}, [r0,:64]! 1010 vst1.16 {d27}, [r0,:64]! 1011 vst1.16 {d31}, [r0,:64]! 1012 pop {pc} 1013endfunc 1014 1015function idct16_1d_4x16_pass2_quarter_neon 1016 push {lr} 1017 @ Only load the top 4 lines, and only do it for the later slices. 1018 @ For the first slice, d16-d19 is kept in registers from the first pass. 1019 cmp r3, #0 1020 beq 1f 1021 mov r12, #32 1022.irp i, 16, 17, 18, 19 1023 vld1.16 {d\i}, [r2,:64], r12 1024.endr 10251: 1026 1027 add r3, r0, r1 1028 lsl r1, r1, #1 1029 bl idct16_quarter 1030 1031 load_add_store q8, q9, q10, q11 1032 load_add_store q12, q13, q14, q15 1033 1034 pop {pc} 1035endfunc 1036 1037function idct16_1d_4x16_pass1_half_neon 1038 push {lr} 1039 mov r12, #32 1040 vmov.s16 q2, #0 1041.irp i, 16, 17, 18, 19, 20, 21, 22, 23 1042 vld1.16 {d\i}, [r2,:64] 1043 vst1.16 {d4}, [r2,:64], r12 1044.endr 1045 1046 bl idct16_half 1047 1048 @ Do four 4x4 transposes. Originally, d16-d31 contain the 1049 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31 1050 @ contain the transposed 4x4 blocks. 1051 transpose16_q_4x_4x4 q8, q9, q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 1052 1053 @ Store the transposed 4x4 blocks horizontally. 1054 cmp r1, #4 1055 beq 1f 1056.irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31 1057 vst1.16 {d\i}, [r0,:64]! 1058.endr 1059 pop {pc} 10601: 1061 @ Special case: For the second input column (r1 == 4), 1062 @ which would be stored as the second row in the temp buffer, 1063 @ don't store the first 4x4 block, but keep it in registers 1064 @ for the first slice of the second pass (where it is the 1065 @ second 4x4 block). 1066 add r0, r0, #8 1067 vst1.16 {d20}, [r0,:64]! 1068 vst1.16 {d24}, [r0,:64]! 1069 vst1.16 {d28}, [r0,:64]! 1070 add r0, r0, #8 1071 vst1.16 {d21}, [r0,:64]! 1072 vst1.16 {d25}, [r0,:64]! 1073 vst1.16 {d29}, [r0,:64]! 1074 add r0, r0, #8 1075 vst1.16 {d22}, [r0,:64]! 1076 vst1.16 {d26}, [r0,:64]! 1077 vst1.16 {d30}, [r0,:64]! 1078 add r0, r0, #8 1079 vst1.16 {d23}, [r0,:64]! 1080 vst1.16 {d27}, [r0,:64]! 1081 vst1.16 {d31}, [r0,:64]! 1082 vmov d20, d16 1083 vmov d21, d17 1084 vmov d22, d18 1085 vmov d23, d19 1086 pop {pc} 1087endfunc 1088 1089function idct16_1d_4x16_pass2_half_neon 1090 push {lr} 1091 mov r12, #32 1092 cmp r3, #0 1093.irp i, 16, 17, 18, 19 1094 vld1.16 {d\i}, [r2,:64], r12 1095.endr 1096 beq 1f 1097.irp i, 20, 21, 22, 23 1098 vld1.16 {d\i}, [r2,:64], r12 1099.endr 11001: 1101 1102 add r3, r0, r1 1103 lsl r1, r1, #1 1104 bl idct16_half 1105 1106 load_add_store q8, q9, q10, q11 1107 load_add_store q12, q13, q14, q15 1108 1109 pop {pc} 1110endfunc 1111.purgem load_add_store 1112 1113.macro idct16_partial size 1114function idct16x16_\size\()_add_neon 1115 add r0, sp, #(0*32) 1116 mov r1, #0 1117 add r2, r6, #(0*2) 1118 bl idct16_1d_4x16_pass1_\size\()_neon 1119.ifc \size,half 1120 add r0, sp, #(4*32) 1121 mov r1, #4 1122 add r2, r6, #(4*2) 1123 bl idct16_1d_4x16_pass1_\size\()_neon 1124.endif 1125.irp i, 0, 4, 8, 12 1126 add r0, r4, #(\i) 1127 mov r1, r5 1128 add r2, sp, #(\i*2) 1129 mov r3, #\i 1130 bl idct16_1d_4x16_pass2_\size\()_neon 1131.endr 1132 1133 add sp, sp, r7 1134 pop {r4-r8,pc} 1135endfunc 1136.endm 1137 1138idct16_partial quarter 1139idct16_partial half 1140 1141function idct32x32_dc_add_neon 1142 movrel r12, idct_coeffs 1143 vld1.16 {d0}, [r12,:64] 1144 1145 vmov.i16 q2, #0 1146 1147 vld1.16 {d16[]}, [r2,:16] 1148 vmull.s16 q8, d16, d0[0] 1149 vrshrn.s32 d16, q8, #14 1150 vmull.s16 q8, d16, d0[0] 1151 vrshrn.s32 d16, q8, #14 1152 vdup.16 q8, d16[0] 1153 vst1.16 {d4[0]}, [r2,:16] 1154 1155 vrshr.s16 q8, q8, #6 1156 1157 mov r3, r0 1158 mov r12, #32 11591: 1160 @ Loop to add the constant from q8 into all 32x32 outputs 1161 subs r12, r12, #2 1162 vld1.8 {q0-q1}, [r0,:128], r1 1163 vaddw.u8 q9, q8, d0 1164 vaddw.u8 q10, q8, d1 1165 vld1.8 {q2-q3}, [r0,:128], r1 1166 vaddw.u8 q11, q8, d2 1167 vaddw.u8 q12, q8, d3 1168 vaddw.u8 q13, q8, d4 1169 vaddw.u8 q14, q8, d5 1170 vaddw.u8 q15, q8, d6 1171 vqmovun.s16 d0, q9 1172 vaddw.u8 q9, q8, d7 1173 vqmovun.s16 d1, q10 1174 vqmovun.s16 d2, q11 1175 vqmovun.s16 d3, q12 1176 vqmovun.s16 d4, q13 1177 vqmovun.s16 d5, q14 1178 vst1.8 {q0-q1}, [r3,:128], r1 1179 vqmovun.s16 d6, q15 1180 vqmovun.s16 d7, q9 1181 vst1.8 {q2-q3}, [r3,:128], r1 1182 bne 1b 1183 1184 bx lr 1185endfunc 1186 1187.macro idct32_end 1188 butterfly d16, d9, d8, d9 @ d16 = t16a, d9 = t19a 1189 butterfly d17, d20, d23, d20 @ d17 = t17, d20 = t18 1190 butterfly d18, d10, d11, d10 @ d18 = t23a, d10 = t20a 1191 butterfly d19, d21, d22, d21 @ d19 = t22, d21 = t21 1192 butterfly d8, d28, d28, d30 @ d8 = t24a, d28 = t27a 1193 butterfly d23, d26, d25, d26 @ d23 = t25, d26 = t26 1194 butterfly d11, d29, d29, d31 @ d11 = t31a, d29 = t28a 1195 butterfly d22, d27, d24, d27 @ d22 = t30, d27 = t29 1196 1197 mbutterfly d27, d20, d0[2], d0[3], q12, q15 @ d27 = t18a, d20 = t29a 1198 mbutterfly d29, d9, d0[2], d0[3], q12, q15 @ d29 = t19, d5 = t28 1199 mbutterfly d28, d10, d0[2], d0[3], q12, q15, neg=1 @ d28 = t27, d6 = t20 1200 mbutterfly d26, d21, d0[2], d0[3], q12, q15, neg=1 @ d26 = t26a, d21 = t21a 1201 1202 butterfly d31, d24, d11, d8 @ d31 = t31, d24 = t24 1203 butterfly d30, d25, d22, d23 @ d30 = t30a, d25 = t25a 1204 butterfly_r d23, d16, d16, d18 @ d23 = t23, d16 = t16 1205 butterfly_r d22, d17, d17, d19 @ d22 = t22a, d17 = t17a 1206 butterfly d18, d21, d27, d21 @ d18 = t18, d21 = t21 1207 butterfly_r d27, d28, d9, d28 @ d27 = t27a, d28 = t28a 1208 butterfly d8, d26, d20, d26 @ d8 = t29, d26 = t26 1209 butterfly d19, d20, d29, d10 @ d19 = t19a, d20 = t20 1210 vmov d29, d8 @ d29 = t29 1211 1212 mbutterfly0 d27, d20, d27, d20, d8, d10, q4, q5 @ d27 = t27, d20 = t20 1213 mbutterfly0 d26, d21, d26, d21, d8, d10, q4, q5 @ d26 = t26a, d21 = t21a 1214 mbutterfly0 d25, d22, d25, d22, d8, d10, q4, q5 @ d25 = t25, d22 = t22 1215 mbutterfly0 d24, d23, d24, d23, d8, d10, q4, q5 @ d24 = t24a, d23 = t23a 1216 bx lr 1217.endm 1218 1219function idct32_odd 1220 mbutterfly d16, d31, d4[0], d4[1], q4, q5 @ d16 = t16a, d31 = t31a 1221 mbutterfly d24, d23, d4[2], d4[3], q4, q5 @ d24 = t17a, d23 = t30a 1222 mbutterfly d20, d27, d5[0], d5[1], q4, q5 @ d20 = t18a, d27 = t29a 1223 mbutterfly d28, d19, d5[2], d5[3], q4, q5 @ d28 = t19a, d19 = t28a 1224 mbutterfly d18, d29, d6[0], d6[1], q4, q5 @ d18 = t20a, d29 = t27a 1225 mbutterfly d26, d21, d6[2], d6[3], q4, q5 @ d26 = t21a, d21 = t26a 1226 mbutterfly d22, d25, d7[0], d7[1], q4, q5 @ d22 = t22a, d25 = t25a 1227 mbutterfly d30, d17, d7[2], d7[3], q4, q5 @ d30 = t23a, d17 = t24a 1228 1229 butterfly d8, d24, d16, d24 @ d8 = t16, d24 = t17 1230 butterfly d9, d20, d28, d20 @ d9 = t19, d20 = t18 1231 butterfly d10, d26, d18, d26 @ d10 = t20, d26 = t21 1232 butterfly d11, d22, d30, d22 @ d11 = t23, d22 = t22 1233 butterfly d28, d25, d17, d25 @ d28 = t24, d25 = t25 1234 butterfly d30, d21, d29, d21 @ d30 = t27, d21 = t26 1235 butterfly d29, d23, d31, d23 @ d29 = t31, d23 = t30 1236 butterfly d31, d27, d19, d27 @ d31 = t28, d27 = t29 1237 1238 mbutterfly d23, d24, d1[0], d1[1], q8, q9 @ d23 = t17a, d24 = t30a 1239 mbutterfly d27, d20, d1[0], d1[1], q8, q9, neg=1 @ d27 = t29a, d20 = t18a 1240 mbutterfly d21, d26, d1[2], d1[3], q8, q9 @ d21 = t21a, d26 = t26a 1241 mbutterfly d25, d22, d1[2], d1[3], q8, q9, neg=1 @ d25 = t25a, d22 = t22a 1242 idct32_end 1243endfunc 1244 1245function idct32_odd_half 1246 mbutterfly_h1 d16, d31, d4[0], d4[1], q4, q5 @ d16 = t16a, d31 = t31a 1247 mbutterfly_h2 d24, d23, d4[2], d4[3], q4, q5 @ d24 = t17a, d23 = t30a 1248 mbutterfly_h1 d20, d27, d5[0], d5[1], q4, q5 @ d20 = t18a, d27 = t29a 1249 mbutterfly_h2 d28, d19, d5[2], d5[3], q4, q5 @ d28 = t19a, d19 = t28a 1250 mbutterfly_h1 d18, d29, d6[0], d6[1], q4, q5 @ d18 = t20a, d29 = t27a 1251 mbutterfly_h2 d26, d21, d6[2], d6[3], q4, q5 @ d26 = t21a, d21 = t26a 1252 mbutterfly_h1 d22, d25, d7[0], d7[1], q4, q5 @ d22 = t22a, d25 = t25a 1253 mbutterfly_h2 d30, d17, d7[2], d7[3], q4, q5 @ d30 = t23a, d17 = t24a 1254 1255 butterfly d8, d24, d16, d24 @ d8 = t16, d24 = t17 1256 butterfly d9, d20, d28, d20 @ d9 = t19, d20 = t18 1257 butterfly d10, d26, d18, d26 @ d10 = t20, d26 = t21 1258 butterfly d11, d22, d30, d22 @ d11 = t23, d22 = t22 1259 butterfly d28, d25, d17, d25 @ d28 = t24, d25 = t25 1260 butterfly d30, d21, d29, d21 @ d30 = t27, d21 = t26 1261 butterfly d29, d23, d31, d23 @ d29 = t31, d23 = t30 1262 butterfly d31, d27, d19, d27 @ d31 = t28, d27 = t29 1263 1264 mbutterfly d23, d24, d1[0], d1[1], q8, q9 @ d23 = t17a, d24 = t30a 1265 mbutterfly d27, d20, d1[0], d1[1], q8, q9, neg=1 @ d27 = t29a, d20 = t18a 1266 mbutterfly d21, d26, d1[2], d1[3], q8, q9 @ d21 = t21a, d26 = t26a 1267 mbutterfly d25, d22, d1[2], d1[3], q8, q9, neg=1 @ d25 = t25a, d22 = t22a 1268 1269 idct32_end 1270endfunc 1271 1272function idct32_odd_quarter 1273 vmull.s16 q4, d16, d4[0] 1274 vmull.s16 q14, d19, d5[3] 1275 vmull.s16 q15, d16, d4[1] 1276 vmull.s16 q11, d17, d7[2] 1277 vmull.s16 q5, d17, d7[3] 1278 vmull.s16 q13, d19, d5[2] 1279 vmull.s16 q10, d18, d6[0] 1280 vmull.s16 q12, d18, d6[1] 1281 1282 vneg.s32 q14, q14 1283 vneg.s32 q5, q5 1284 1285 vrshrn.s32 d8, q4, #14 1286 vrshrn.s32 d9, q14, #14 1287 vrshrn.s32 d29, q15, #14 1288 vrshrn.s32 d28, q11, #14 1289 vrshrn.s32 d11, q5, #14 1290 vrshrn.s32 d31, q13, #14 1291 vrshrn.s32 d10, q10, #14 1292 vrshrn.s32 d30, q12, #14 1293 1294 mbutterfly_l q8, q9, d29, d8, d1[0], d1[1] 1295 mbutterfly_l q13, q10, d31, d9, d1[0], d1[1] 1296 vrshrn.s32 d23, q8, #14 1297 vrshrn.s32 d24, q9, #14 1298 vneg.s32 q10, q10 1299 vrshrn.s32 d27, q13, #14 1300 vrshrn.s32 d20, q10, #14 1301 mbutterfly_l q8, q9, d30, d10, d1[2], d1[3] 1302 vrshrn.s32 d21, q8, #14 1303 vrshrn.s32 d26, q9, #14 1304 mbutterfly_l q8, q9, d28, d11, d1[2], d1[3] 1305 vrshrn.s32 d25, q8, #14 1306 vneg.s32 q9, q9 1307 vrshrn.s32 d22, q9, #14 1308 1309 idct32_end 1310endfunc 1311 1312.macro idct32_funcs suffix 1313@ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix. 1314@ We don't have register space to do a single pass IDCT of 4x32 though, 1315@ but the 32-point IDCT can be decomposed into two 16-point IDCTs; 1316@ a normal IDCT16 with every other input component (the even ones, with 1317@ each output written twice), followed by a separate 16-point IDCT 1318@ of the odd inputs, added/subtracted onto the outputs of the first idct16. 1319@ r0 = dst (temp buffer) 1320@ r1 = unused 1321@ r2 = src 1322function idct32_1d_4x32_pass1\suffix\()_neon 1323 push {lr} 1324 1325 @ idct16 clobbers q2-q3 (since it doesn't clobber q4-q7 at all 1326 @ when doing the normal 16x16 idct), so move the idct32_odd coeffs 1327 @ to q4-q5 1328 vmov q4, q2 1329 vmov q5, q3 1330 1331 @ Double stride of the input, since we only read every other line 1332 mov r12, #128 1333 vmov.s16 d4, #0 1334 1335 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30) 1336.ifb \suffix 1337.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 1338 vld1.16 {d\i}, [r2,:64] 1339 vst1.16 {d4}, [r2,:64], r12 1340.endr 1341.endif 1342.ifc \suffix,_quarter 1343.irp i, 16, 17, 18, 19 1344 vld1.16 {d\i}, [r2,:64] 1345 vst1.16 {d4}, [r2,:64], r12 1346.endr 1347.endif 1348.ifc \suffix,_half 1349.irp i, 16, 17, 18, 19, 20, 21, 22, 23 1350 vld1.16 {d\i}, [r2,:64] 1351 vst1.16 {d4}, [r2,:64], r12 1352.endr 1353.endif 1354 1355 bl idct16\suffix 1356 1357 @ Move the idct32_odd coeffs back into q2-q3 for idct32_odd; 1358 @ the constants for a vmul with a lane must be in q0-q3. 1359 vmov q2, q4 1360 vmov q3, q5 1361 1362 @ Do four 4x4 transposes. Originally, d16-d31 contain the 1363 @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31 1364 @ contain the transposed 4x4 blocks. 1365 transpose16_q_4x_4x4 q8, q9, q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31 1366 @ Store the registers a, b, c, d horizontally, followed 1367 @ by the same registers d, c, b, a mirrored. 1368.macro store_rev a, b, c, d 1369.irp i, \a, \b, \c, \d 1370 vst1.16 {d\i}, [r0,:64]! 1371 vrev64.16 d\i, d\i 1372.endr 1373.irp i, \d, \c, \b, \a 1374 vst1.16 {d\i}, [r0,:64]! 1375.endr 1376.endm 1377 store_rev 16, 20, 24, 28 1378 store_rev 17, 21, 25, 29 1379 store_rev 18, 22, 26, 30 1380 store_rev 19, 23, 27, 31 1381 sub r0, r0, #256 1382.purgem store_rev 1383 1384 @ Move r2 back to the start of the input, and move 1385 @ to the first odd row 1386.ifb \suffix 1387 sub r2, r2, r12, lsl #4 1388.endif 1389.ifc \suffix,_quarter 1390 sub r2, r2, r12, lsl #2 1391.endif 1392.ifc \suffix,_half 1393 sub r2, r2, r12, lsl #3 1394.endif 1395 add r2, r2, #64 1396 1397 vmov.s16 d8, #0 1398 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31) 1399.ifb \suffix 1400.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 1401 vld1.16 {d\i}, [r2,:64] 1402 vst1.16 {d8}, [r2,:64], r12 1403.endr 1404.endif 1405.ifc \suffix,_quarter 1406.irp i, 16, 17, 18, 19 1407 vld1.16 {d\i}, [r2,:64] 1408 vst1.16 {d8}, [r2,:64], r12 1409.endr 1410.endif 1411.ifc \suffix,_half 1412.irp i, 16, 17, 18, 19, 20, 21, 22, 23 1413 vld1.16 {d\i}, [r2,:64] 1414 vst1.16 {d8}, [r2,:64], r12 1415.endr 1416.endif 1417 1418 bl idct32_odd\suffix 1419 1420 transpose16_q_4x_4x4 q15, q14, q13, q12, q11, q10, q9, q8, d31, d30, d29, d28, d27, d26, d25, d24, d23, d22, d21, d20, d19, d18, d17, d16 1421 1422 @ Store the registers a, b, c, d horizontally, 1423 @ adding into the output first, and then mirrored, subtracted 1424 @ from the output. 1425.macro store_rev a, b, c, d 1426.irp i, \a, \b, \c, \d 1427 vld1.16 {d8}, [r0,:64] 1428 vadd.s16 d8, d8, d\i 1429 vst1.16 {d8}, [r0,:64]! 1430 vrev64.16 d\i, d\i 1431.endr 1432.irp i, \d, \c, \b, \a 1433 vld1.16 {d8}, [r0,:64] 1434 vsub.s16 d8, d8, d\i 1435 vst1.16 {d8}, [r0,:64]! 1436.endr 1437.endm 1438 1439 store_rev 31, 27, 23, 19 1440 store_rev 30, 26, 22, 18 1441 store_rev 29, 25, 21, 17 1442 store_rev 28, 24, 20, 16 1443.purgem store_rev 1444 pop {pc} 1445endfunc 1446.ltorg 1447 1448@ This is mostly the same as 4x32_pass1, but without the transpose, 1449@ and use the source as temp buffer between the two idct passes, and 1450@ add into the destination. 1451@ r0 = dst 1452@ r1 = dst stride 1453@ r2 = src (temp buffer) 1454function idct32_1d_4x32_pass2\suffix\()_neon 1455 push {lr} 1456 vmov q4, q2 1457 vmov q5, q3 1458 1459 mov r12, #128 1460 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30) 1461.ifb \suffix 1462.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 1463 vld1.16 {d\i}, [r2,:64], r12 1464.endr 1465 sub r2, r2, r12, lsl #4 1466.endif 1467.ifc \suffix,_quarter 1468.irp i, 16, 17, 18, 19 1469 vld1.16 {d\i}, [r2,:64], r12 1470.endr 1471 sub r2, r2, r12, lsl #2 1472.endif 1473.ifc \suffix,_half 1474.irp i, 16, 17, 18, 19, 20, 21, 22, 23 1475 vld1.16 {d\i}, [r2,:64], r12 1476.endr 1477 sub r2, r2, r12, lsl #3 1478.endif 1479 1480 bl idct16\suffix 1481 1482 vmov q2, q4 1483 vmov q3, q5 1484 1485.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 1486 vst1.16 {d\i}, [r2,:64], r12 1487.endr 1488 1489 sub r2, r2, r12, lsl #4 1490 add r2, r2, #64 1491 1492 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31) 1493.ifb \suffix 1494.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 1495 vld1.16 {d\i}, [r2,:64], r12 1496.endr 1497 sub r2, r2, r12, lsl #4 1498.endif 1499.ifc \suffix,_quarter 1500.irp i, 16, 17, 18, 19 1501 vld1.16 {d\i}, [r2,:64], r12 1502.endr 1503 sub r2, r2, r12, lsl #2 1504.endif 1505.ifc \suffix,_half 1506.irp i, 16, 17, 18, 19, 20, 21, 22, 23 1507 vld1.16 {d\i}, [r2,:64], r12 1508.endr 1509 sub r2, r2, r12, lsl #3 1510.endif 1511 sub r2, r2, #64 1512 1513 bl idct32_odd\suffix 1514 1515 mov r12, #128 1516.macro load_acc_store a, b, c, d, neg=0 1517 vld1.16 {d8}, [r2,:64], r12 1518 vld1.16 {d9}, [r2,:64], r12 1519.if \neg == 0 1520 vadd.s16 d8, d8, d\a 1521 vld1.16 {d10}, [r2,:64], r12 1522 vadd.s16 d9, d9, d\b 1523 vld1.16 {d11}, [r2,:64], r12 1524 vadd.s16 d10, d10, d\c 1525 vadd.s16 d11, d11, d\d 1526.else 1527 vsub.s16 d8, d8, d\a 1528 vld1.16 {d10}, [r2,:64], r12 1529 vsub.s16 d9, d9, d\b 1530 vld1.16 {d11}, [r2,:64], r12 1531 vsub.s16 d10, d10, d\c 1532 vsub.s16 d11, d11, d\d 1533.endif 1534 vld1.32 {d12[]}, [r0,:32], r1 1535 vld1.32 {d12[1]}, [r0,:32], r1 1536 vrshr.s16 q4, q4, #6 1537 vld1.32 {d13[]}, [r0,:32], r1 1538 vrshr.s16 q5, q5, #6 1539 vld1.32 {d13[1]}, [r0,:32], r1 1540 sub r0, r0, r1, lsl #2 1541 vaddw.u8 q4, q4, d12 1542 vaddw.u8 q5, q5, d13 1543 vqmovun.s16 d8, q4 1544 vqmovun.s16 d9, q5 1545 vst1.32 {d8[0]}, [r0,:32], r1 1546 vst1.32 {d8[1]}, [r0,:32], r1 1547 vst1.32 {d9[0]}, [r0,:32], r1 1548 vst1.32 {d9[1]}, [r0,:32], r1 1549.endm 1550 load_acc_store 31, 30, 29, 28 1551 load_acc_store 27, 26, 25, 24 1552 load_acc_store 23, 22, 21, 20 1553 load_acc_store 19, 18, 17, 16 1554 sub r2, r2, r12 1555 neg r12, r12 1556 load_acc_store 16, 17, 18, 19, 1 1557 load_acc_store 20, 21, 22, 23, 1 1558 load_acc_store 24, 25, 26, 27, 1 1559 load_acc_store 28, 29, 30, 31, 1 1560.purgem load_acc_store 1561 pop {pc} 1562endfunc 1563.endm 1564 1565idct32_funcs 1566idct32_funcs _quarter 1567idct32_funcs _half 1568 1569const min_eob_idct_idct_32, align=4 1570 .short 0, 9, 34, 70, 135, 240, 336, 448 1571endconst 1572 1573function ff_vp9_idct_idct_32x32_add_neon, export=1 1574 cmp r3, #1 1575 beq idct32x32_dc_add_neon 1576 push {r4-r8,lr} 1577 vpush {q4-q6} 1578 1579 @ Align the stack, allocate a temp buffer 1580T mov r7, sp 1581T and r7, r7, #15 1582A and r7, sp, #15 1583 add r7, r7, #2048 1584 sub sp, sp, r7 1585 1586 mov r4, r0 1587 mov r5, r1 1588 mov r6, r2 1589 1590 movrel r12, idct_coeffs 1591 vld1.16 {q0-q1}, [r12,:128]! 1592 vld1.16 {q2-q3}, [r12,:128] 1593 1594 cmp r3, #34 1595 ble idct32x32_quarter_add_neon 1596 cmp r3, #135 1597 ble idct32x32_half_add_neon 1598 1599 movrel r8, min_eob_idct_idct_32 + 2 1600 1601.irp i, 0, 4, 8, 12, 16, 20, 24, 28 1602 add r0, sp, #(\i*64) 1603.if \i > 0 1604 ldrh_post r1, r8, #2 1605 cmp r3, r1 1606 it le 1607 movle r1, #(32 - \i)/2 1608 ble 1f 1609.endif 1610 add r2, r6, #(\i*2) 1611 bl idct32_1d_4x32_pass1_neon 1612.endr 1613 b 3f 1614 16151: 1616 @ Write zeros to the temp buffer for pass 2 1617 vmov.i16 q14, #0 1618 vmov.i16 q15, #0 16192: 1620 subs r1, r1, #1 1621.rept 4 1622 vst1.16 {q14-q15}, [r0,:128]! 1623.endr 1624 bne 2b 16253: 1626.irp i, 0, 4, 8, 12, 16, 20, 24, 28 1627 add r0, r4, #(\i) 1628 mov r1, r5 1629 add r2, sp, #(\i*2) 1630 bl idct32_1d_4x32_pass2_neon 1631.endr 1632 1633 add sp, sp, r7 1634 vpop {q4-q6} 1635 pop {r4-r8,pc} 1636endfunc 1637 1638.macro idct32_partial size 1639function idct32x32_\size\()_add_neon 1640.irp i, 0, 4 1641 add r0, sp, #(\i*64) 1642.ifc \size,quarter 1643.if \i == 4 1644 cmp r3, #9 1645 ble 1f 1646.endif 1647.endif 1648 add r2, r6, #(\i*2) 1649 bl idct32_1d_4x32_pass1_\size\()_neon 1650.endr 1651 1652.ifc \size,half 1653.irp i, 8, 12 1654 add r0, sp, #(\i*64) 1655.if \i == 12 1656 cmp r3, #70 1657 ble 1f 1658.endif 1659 add r2, r6, #(\i*2) 1660 bl idct32_1d_4x32_pass1_\size\()_neon 1661.endr 1662.endif 1663 b 3f 1664 16651: 1666 @ Write zeros to the temp buffer for pass 2 1667 vmov.i16 q14, #0 1668 vmov.i16 q15, #0 1669.rept 8 1670 vst1.16 {q14-q15}, [r0,:128]! 1671.endr 1672 16733: 1674.irp i, 0, 4, 8, 12, 16, 20, 24, 28 1675 add r0, r4, #(\i) 1676 mov r1, r5 1677 add r2, sp, #(\i*2) 1678 bl idct32_1d_4x32_pass2_\size\()_neon 1679.endr 1680 1681 add sp, sp, r7 1682 vpop {q4-q6} 1683 pop {r4-r8,pc} 1684endfunc 1685.endm 1686 1687idct32_partial quarter 1688idct32_partial half 1689