1/* 2 * Copyright (c) 2009 David Conrad 3 * 4 * This file is part of Libav. 5 * 6 * Libav 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 * Libav 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 Libav; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#include "asm.S" 22 23const vp3_idct_constants, align=4 24.short 64277, 60547, 54491, 46341, 36410, 25080, 12785 25endconst 26 27#define xC1S7 d0[0] 28#define xC2S6 d0[1] 29#define xC3S5 d0[2] 30#define xC4S4 d0[3] 31#define xC5S3 d1[0] 32#define xC6S2 d1[1] 33#define xC7S1 d1[2] 34 35.macro vp3_loop_filter 36 vsubl.u8 q3, d18, d17 37 vsubl.u8 q2, d16, d19 38 vadd.i16 q1, q3, q3 39 vadd.i16 q2, q2, q3 40 vadd.i16 q0, q1, q2 41 vrshr.s16 q0, q0, #3 42 vmovl.u8 q9, d18 43 vdup.u16 q15, r2 44 45 vabs.s16 q1, q0 46 vshr.s16 q0, q0, #15 47 vqsub.u16 q2, q15, q1 48 vqsub.u16 q3, q2, q1 49 vsub.i16 q1, q2, q3 50 veor q1, q1, q0 51 vsub.i16 q0, q1, q0 52 53 vaddw.u8 q2, q0, d17 54 vsub.i16 q3, q9, q0 55 vqmovun.s16 d0, q2 56 vqmovun.s16 d1, q3 57.endm 58 59function ff_vp3_v_loop_filter_neon, export=1 60 sub ip, r0, r1 61 sub r0, r0, r1, lsl #1 62 vld1.64 {d16}, [r0,:64], r1 63 vld1.64 {d17}, [r0,:64], r1 64 vld1.64 {d18}, [r0,:64], r1 65 vld1.64 {d19}, [r0,:64], r1 66 ldrb r2, [r2, #129*4] 67 68 vp3_loop_filter 69 70 vst1.64 {d0}, [ip,:64], r1 71 vst1.64 {d1}, [ip,:64], r1 72 bx lr 73endfunc 74 75function ff_vp3_h_loop_filter_neon, export=1 76 sub ip, r0, #1 77 sub r0, r0, #2 78 vld1.32 {d16[]}, [r0], r1 79 vld1.32 {d17[]}, [r0], r1 80 vld1.32 {d18[]}, [r0], r1 81 vld1.32 {d19[]}, [r0], r1 82 vld1.32 {d16[1]}, [r0], r1 83 vld1.32 {d17[1]}, [r0], r1 84 vld1.32 {d18[1]}, [r0], r1 85 vld1.32 {d19[1]}, [r0], r1 86 ldrb r2, [r2, #129*4] 87 88 vtrn.8 d16, d17 89 vtrn.8 d18, d19 90 vtrn.16 d16, d18 91 vtrn.16 d17, d19 92 93 vp3_loop_filter 94 95 vtrn.8 d0, d1 96 97 vst1.16 {d0[0]}, [ip], r1 98 vst1.16 {d1[0]}, [ip], r1 99 vst1.16 {d0[1]}, [ip], r1 100 vst1.16 {d1[1]}, [ip], r1 101 vst1.16 {d0[2]}, [ip], r1 102 vst1.16 {d1[2]}, [ip], r1 103 vst1.16 {d0[3]}, [ip], r1 104 vst1.16 {d1[3]}, [ip], r1 105 bx lr 106endfunc 107 108 109function vp3_idct_start_neon 110 vpush {d8-d15} 111 movrel r3, vp3_idct_constants 112 vld1.64 {d0-d1}, [r3,:128] 113 vld1.64 {d16-d19}, [r2,:128]! 114 vld1.64 {d20-d23}, [r2,:128]! 115 vld1.64 {d24-d27}, [r2,:128]! 116 vadd.s16 q1, q8, q12 117 vsub.s16 q8, q8, q12 118 vld1.64 {d28-d31}, [r2,:128]! 119endfunc 120 121function vp3_idct_core_neon 122 vmull.s16 q2, d18, xC1S7 // (ip[1] * C1) << 16 123 vmull.s16 q3, d19, xC1S7 124 vmull.s16 q4, d2, xC4S4 // ((ip[0] + ip[4]) * C4) << 16 125 vmull.s16 q5, d3, xC4S4 126 vmull.s16 q6, d16, xC4S4 // ((ip[0] - ip[4]) * C4) << 16 127 vmull.s16 q7, d17, xC4S4 128 vshrn.s32 d4, q2, #16 129 vshrn.s32 d5, q3, #16 130 vshrn.s32 d6, q4, #16 131 vshrn.s32 d7, q5, #16 132 vshrn.s32 d8, q6, #16 133 vshrn.s32 d9, q7, #16 134 vadd.s16 q12, q1, q3 // E = (ip[0] + ip[4]) * C4 135 vadd.s16 q8, q8, q4 // F = (ip[0] - ip[4]) * C4 136 vadd.s16 q1, q2, q9 // ip[1] * C1 137 138 vmull.s16 q2, d30, xC1S7 // (ip[7] * C1) << 16 139 vmull.s16 q3, d31, xC1S7 140 vmull.s16 q4, d30, xC7S1 // (ip[7] * C7) << 16 141 vmull.s16 q5, d31, xC7S1 142 vmull.s16 q6, d18, xC7S1 // (ip[1] * C7) << 16 143 vmull.s16 q7, d19, xC7S1 144 vshrn.s32 d4, q2, #16 145 vshrn.s32 d5, q3, #16 146 vshrn.s32 d6, q4, #16 // ip[7] * C7 147 vshrn.s32 d7, q5, #16 148 vshrn.s32 d8, q6, #16 // ip[1] * C7 149 vshrn.s32 d9, q7, #16 150 vadd.s16 q2, q2, q15 // ip[7] * C1 151 vadd.s16 q9, q1, q3 // A = ip[1] * C1 + ip[7] * C7 152 vsub.s16 q15, q4, q2 // B = ip[1] * C7 - ip[7] * C1 153 154 vmull.s16 q2, d22, xC5S3 // (ip[3] * C5) << 16 155 vmull.s16 q3, d23, xC5S3 156 vmull.s16 q4, d22, xC3S5 // (ip[3] * C3) << 16 157 vmull.s16 q5, d23, xC3S5 158 vmull.s16 q6, d26, xC5S3 // (ip[5] * C5) << 16 159 vmull.s16 q7, d27, xC5S3 160 vshrn.s32 d4, q2, #16 161 vshrn.s32 d5, q3, #16 162 vshrn.s32 d6, q4, #16 163 vshrn.s32 d7, q5, #16 164 vshrn.s32 d8, q6, #16 165 vshrn.s32 d9, q7, #16 166 vadd.s16 q3, q3, q11 // ip[3] * C3 167 vadd.s16 q4, q4, q13 // ip[5] * C5 168 vadd.s16 q1, q2, q11 // ip[3] * C5 169 vadd.s16 q11, q3, q4 // C = ip[3] * C3 + ip[5] * C5 170 171 vmull.s16 q2, d26, xC3S5 // (ip[5] * C3) << 16 172 vmull.s16 q3, d27, xC3S5 173 vmull.s16 q4, d20, xC2S6 // (ip[2] * C2) << 16 174 vmull.s16 q5, d21, xC2S6 175 vmull.s16 q6, d28, xC6S2 // (ip[6] * C6) << 16 176 vmull.s16 q7, d29, xC6S2 177 vshrn.s32 d4, q2, #16 178 vshrn.s32 d5, q3, #16 179 vshrn.s32 d6, q4, #16 180 vshrn.s32 d7, q5, #16 181 vshrn.s32 d8, q6, #16 // ip[6] * C6 182 vshrn.s32 d9, q7, #16 183 vadd.s16 q2, q2, q13 // ip[5] * C3 184 vadd.s16 q3, q3, q10 // ip[2] * C2 185 vsub.s16 q13, q2, q1 // D = ip[5] * C3 - ip[3] * C5 186 vsub.s16 q1, q9, q11 // (A - C) 187 vadd.s16 q11, q9, q11 // Cd = A + C 188 vsub.s16 q9, q15, q13 // (B - D) 189 vadd.s16 q13, q15, q13 // Dd = B + D 190 vadd.s16 q15, q3, q4 // G = ip[2] * C2 + ip[6] * C6 191 192 vmull.s16 q2, d2, xC4S4 // ((A - C) * C4) << 16 193 vmull.s16 q3, d3, xC4S4 194 vmull.s16 q4, d28, xC2S6 // (ip[6] * C2) << 16 195 vmull.s16 q5, d29, xC2S6 196 vmull.s16 q6, d20, xC6S2 // (ip[2] * C6) << 16 197 vmull.s16 q7, d21, xC6S2 198 vshrn.s32 d4, q2, #16 199 vshrn.s32 d5, q3, #16 200 vshrn.s32 d6, q4, #16 201 vshrn.s32 d7, q5, #16 202 vshrn.s32 d8, q6, #16 // ip[2] * C6 203 vmull.s16 q5, d18, xC4S4 // ((B - D) * C4) << 16 204 vmull.s16 q6, d19, xC4S4 205 vshrn.s32 d9, q7, #16 206 vadd.s16 q3, q3, q14 // ip[6] * C2 207 vadd.s16 q10, q1, q2 // Ad = (A - C) * C4 208 vsub.s16 q14, q4, q3 // H = ip[2] * C6 - ip[6] * C2 209 bx lr 210endfunc 211 212.macro VP3_IDCT_END type 213function vp3_idct_end_\type\()_neon 214.ifc \type, col 215 vdup.16 q0, r3 216 vadd.s16 q12, q12, q0 217 vadd.s16 q8, q8, q0 218.endif 219 220 vshrn.s32 d2, q5, #16 221 vshrn.s32 d3, q6, #16 222 vadd.s16 q2, q12, q15 // Gd = E + G 223 vadd.s16 q9, q1, q9 // (B - D) * C4 224 vsub.s16 q12, q12, q15 // Ed = E - G 225 vsub.s16 q3, q8, q10 // Fd = F - Ad 226 vadd.s16 q10, q8, q10 // Add = F + Ad 227 vadd.s16 q4, q9, q14 // Hd = Bd + H 228 vsub.s16 q14, q9, q14 // Bdd = Bd - H 229 vadd.s16 q8, q2, q11 // [0] = Gd + Cd 230 vsub.s16 q15, q2, q11 // [7] = Gd - Cd 231 vadd.s16 q9, q10, q4 // [1] = Add + Hd 232 vsub.s16 q10, q10, q4 // [2] = Add - Hd 233 vadd.s16 q11, q12, q13 // [3] = Ed + Dd 234 vsub.s16 q12, q12, q13 // [4] = Ed - Dd 235.ifc \type, row 236 vtrn.16 q8, q9 237.endif 238 vadd.s16 q13, q3, q14 // [5] = Fd + Bdd 239 vsub.s16 q14, q3, q14 // [6] = Fd - Bdd 240 241.ifc \type, row 242 // 8x8 transpose 243 vtrn.16 q10, q11 244 vtrn.16 q12, q13 245 vtrn.16 q14, q15 246 vtrn.32 q8, q10 247 vtrn.32 q9, q11 248 vtrn.32 q12, q14 249 vtrn.32 q13, q15 250 vswp d17, d24 251 vswp d19, d26 252 vadd.s16 q1, q8, q12 253 vswp d21, d28 254 vsub.s16 q8, q8, q12 255 vswp d23, d30 256.endif 257 bx lr 258endfunc 259.endm 260 261VP3_IDCT_END row 262VP3_IDCT_END col 263 264function ff_vp3_idct_neon, export=1 265 mov ip, lr 266 mov r2, r0 267 bl vp3_idct_start_neon 268 bl vp3_idct_end_row_neon 269 mov r3, #8 270 bl vp3_idct_core_neon 271 bl vp3_idct_end_col_neon 272 mov lr, ip 273 vpop {d8-d15} 274 275 vshr.s16 q8, q8, #4 276 vshr.s16 q9, q9, #4 277 vshr.s16 q10, q10, #4 278 vshr.s16 q11, q11, #4 279 vshr.s16 q12, q12, #4 280 vst1.64 {d16-d19}, [r0,:128]! 281 vshr.s16 q13, q13, #4 282 vshr.s16 q14, q14, #4 283 vst1.64 {d20-d23}, [r0,:128]! 284 vshr.s16 q15, q15, #4 285 vst1.64 {d24-d27}, [r0,:128]! 286 vst1.64 {d28-d31}, [r0,:128]! 287 bx lr 288endfunc 289 290function ff_vp3_idct_put_neon, export=1 291 mov ip, lr 292 bl vp3_idct_start_neon 293 bl vp3_idct_end_row_neon 294 mov r3, #8 295 add r3, r3, #2048 // convert signed pixel to unsigned 296 bl vp3_idct_core_neon 297 bl vp3_idct_end_col_neon 298 mov lr, ip 299 vpop {d8-d15} 300 301 vqshrun.s16 d0, q8, #4 302 vqshrun.s16 d1, q9, #4 303 vqshrun.s16 d2, q10, #4 304 vqshrun.s16 d3, q11, #4 305 vst1.64 {d0}, [r0,:64], r1 306 vqshrun.s16 d4, q12, #4 307 vst1.64 {d1}, [r0,:64], r1 308 vqshrun.s16 d5, q13, #4 309 vst1.64 {d2}, [r0,:64], r1 310 vqshrun.s16 d6, q14, #4 311 vst1.64 {d3}, [r0,:64], r1 312 vqshrun.s16 d7, q15, #4 313 vst1.64 {d4}, [r0,:64], r1 314 vst1.64 {d5}, [r0,:64], r1 315 vst1.64 {d6}, [r0,:64], r1 316 vst1.64 {d7}, [r0,:64], r1 317 bx lr 318endfunc 319 320function ff_vp3_idct_add_neon, export=1 321 mov ip, lr 322 bl vp3_idct_start_neon 323 bl vp3_idct_end_row_neon 324 mov r3, #8 325 bl vp3_idct_core_neon 326 bl vp3_idct_end_col_neon 327 mov lr, ip 328 vpop {d8-d15} 329 mov r2, r0 330 331 vld1.64 {d0}, [r0,:64], r1 332 vshr.s16 q8, q8, #4 333 vld1.64 {d1}, [r0,:64], r1 334 vshr.s16 q9, q9, #4 335 vld1.64 {d2}, [r0,:64], r1 336 vaddw.u8 q8, q8, d0 337 vld1.64 {d3}, [r0,:64], r1 338 vaddw.u8 q9, q9, d1 339 vld1.64 {d4}, [r0,:64], r1 340 vshr.s16 q10, q10, #4 341 vld1.64 {d5}, [r0,:64], r1 342 vshr.s16 q11, q11, #4 343 vld1.64 {d6}, [r0,:64], r1 344 vqmovun.s16 d0, q8 345 vld1.64 {d7}, [r0,:64], r1 346 vqmovun.s16 d1, q9 347 vaddw.u8 q10, q10, d2 348 vaddw.u8 q11, q11, d3 349 vshr.s16 q12, q12, #4 350 vshr.s16 q13, q13, #4 351 vqmovun.s16 d2, q10 352 vqmovun.s16 d3, q11 353 vaddw.u8 q12, q12, d4 354 vaddw.u8 q13, q13, d5 355 vshr.s16 q14, q14, #4 356 vshr.s16 q15, q15, #4 357 vst1.64 {d0}, [r2,:64], r1 358 vqmovun.s16 d4, q12 359 vst1.64 {d1}, [r2,:64], r1 360 vqmovun.s16 d5, q13 361 vst1.64 {d2}, [r2,:64], r1 362 vaddw.u8 q14, q14, d6 363 vst1.64 {d3}, [r2,:64], r1 364 vaddw.u8 q15, q15, d7 365 vst1.64 {d4}, [r2,:64], r1 366 vqmovun.s16 d6, q14 367 vst1.64 {d5}, [r2,:64], r1 368 vqmovun.s16 d7, q15 369 vst1.64 {d6}, [r2,:64], r1 370 vst1.64 {d7}, [r2,:64], r1 371 bx lr 372endfunc 373 374function ff_vp3_idct_dc_add_neon, export=1 375 ldrsh r2, [r2] 376 mov r3, r0 377 add r2, r2, #15 378 vdup.16 q15, r2 379 vshr.s16 q15, q15, #5 380 381 vld1.8 {d0}, [r0,:64], r1 382 vld1.8 {d1}, [r0,:64], r1 383 vld1.8 {d2}, [r0,:64], r1 384 vaddw.u8 q8, q15, d0 385 vld1.8 {d3}, [r0,:64], r1 386 vaddw.u8 q9, q15, d1 387 vld1.8 {d4}, [r0,:64], r1 388 vaddw.u8 q10, q15, d2 389 vld1.8 {d5}, [r0,:64], r1 390 vaddw.u8 q11, q15, d3 391 vld1.8 {d6}, [r0,:64], r1 392 vaddw.u8 q12, q15, d4 393 vld1.8 {d7}, [r0,:64], r1 394 vaddw.u8 q13, q15, d5 395 vqmovun.s16 d0, q8 396 vaddw.u8 q14, q15, d6 397 vqmovun.s16 d1, q9 398 vaddw.u8 q15, q15, d7 399 vqmovun.s16 d2, q10 400 vst1.8 {d0}, [r3,:64], r1 401 vqmovun.s16 d3, q11 402 vst1.8 {d1}, [r3,:64], r1 403 vqmovun.s16 d4, q12 404 vst1.8 {d2}, [r3,:64], r1 405 vqmovun.s16 d5, q13 406 vst1.8 {d3}, [r3,:64], r1 407 vqmovun.s16 d6, q14 408 vst1.8 {d4}, [r3,:64], r1 409 vqmovun.s16 d7, q15 410 vst1.8 {d5}, [r3,:64], r1 411 vst1.8 {d6}, [r3,:64], r1 412 vst1.8 {d7}, [r3,:64], r1 413 bx lr 414endfunc 415