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