1/* 2 * ARM NEON IDCT 3 * 4 * Copyright (c) 2008 Mans Rullgard <mans@mansr.com> 5 * 6 * Based on Simple IDCT 7 * Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at> 8 * 9 * This file is part of FFmpeg. 10 * 11 * FFmpeg is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * FFmpeg is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with FFmpeg; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 */ 25 26#include "libavutil/arm/asm.S" 27 28#define W1 22725 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 29#define W2 21407 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 30#define W3 19266 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 31#define W4 16383 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 32#define W5 12873 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 33#define W6 8867 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 34#define W7 4520 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 35#define W4c ((1<<(COL_SHIFT-1))/W4) 36#define ROW_SHIFT 11 37#define COL_SHIFT 20 38 39#define w1 d0[0] 40#define w2 d0[1] 41#define w3 d0[2] 42#define w4 d0[3] 43#define w5 d1[0] 44#define w6 d1[1] 45#define w7 d1[2] 46#define w4c d1[3] 47 48 .macro idct_col4_top 49 vmull.s16 q7, d6, w2 /* q9 = W2 * col[2] */ 50 vmull.s16 q8, d6, w6 /* q10 = W6 * col[2] */ 51 vmull.s16 q9, d4, w1 /* q9 = W1 * col[1] */ 52 vadd.i32 q11, q15, q7 53 vmull.s16 q10, d4, w3 /* q10 = W3 * col[1] */ 54 vadd.i32 q12, q15, q8 55 vmull.s16 q5, d4, w5 /* q5 = W5 * col[1] */ 56 vsub.i32 q13, q15, q8 57 vmull.s16 q6, d4, w7 /* q6 = W7 * col[1] */ 58 vsub.i32 q14, q15, q7 59 60 vmlal.s16 q9, d8, w3 /* q9 += W3 * col[3] */ 61 vmlsl.s16 q10, d8, w7 /* q10 -= W7 * col[3] */ 62 vmlsl.s16 q5, d8, w1 /* q5 -= W1 * col[3] */ 63 vmlsl.s16 q6, d8, w5 /* q6 -= W5 * col[3] */ 64 .endm 65 66 .text 67 .align 6 68 69function idct_row4_pld_neon 70 pld [r0] 71 add r3, r0, r1, lsl #2 72 pld [r0, r1] 73 pld [r0, r1, lsl #1] 74A pld [r3, -r1] 75 pld [r3] 76 pld [r3, r1] 77 add r3, r3, r1, lsl #1 78 pld [r3] 79 pld [r3, r1] 80endfunc 81 82function idct_row4_neon 83 vmov.i32 q15, #(1<<(ROW_SHIFT-1)) 84 vld1.64 {d2-d5}, [r2,:128]! 85 vmlal.s16 q15, d2, w4 /* q15 += W4 * col[0] */ 86 vld1.64 {d6,d7}, [r2,:128]! 87 vorr d10, d3, d5 88 vld1.64 {d8,d9}, [r2,:128]! 89 add r2, r2, #-64 90 91 vorr d11, d7, d9 92 vorr d10, d10, d11 93 vmov r3, r4, d10 94 95 idct_col4_top 96 97 orrs r3, r3, r4 98 beq 1f 99 100 vmull.s16 q7, d3, w4 /* q7 = W4 * col[4] */ 101 vmlal.s16 q9, d5, w5 /* q9 += W5 * col[5] */ 102 vmlsl.s16 q10, d5, w1 /* q10 -= W1 * col[5] */ 103 vmull.s16 q8, d7, w2 /* q8 = W2 * col[6] */ 104 vmlal.s16 q5, d5, w7 /* q5 += W7 * col[5] */ 105 vadd.i32 q11, q11, q7 106 vsub.i32 q12, q12, q7 107 vsub.i32 q13, q13, q7 108 vadd.i32 q14, q14, q7 109 vmlal.s16 q6, d5, w3 /* q6 += W3 * col[5] */ 110 vmull.s16 q7, d7, w6 /* q7 = W6 * col[6] */ 111 vmlal.s16 q9, d9, w7 112 vmlsl.s16 q10, d9, w5 113 vmlal.s16 q5, d9, w3 114 vmlsl.s16 q6, d9, w1 115 vadd.i32 q11, q11, q7 116 vsub.i32 q12, q12, q8 117 vadd.i32 q13, q13, q8 118 vsub.i32 q14, q14, q7 119 1201: vadd.i32 q3, q11, q9 121 vadd.i32 q4, q12, q10 122 vshrn.i32 d2, q3, #ROW_SHIFT 123 vshrn.i32 d4, q4, #ROW_SHIFT 124 vadd.i32 q7, q13, q5 125 vadd.i32 q8, q14, q6 126 vtrn.16 d2, d4 127 vshrn.i32 d6, q7, #ROW_SHIFT 128 vshrn.i32 d8, q8, #ROW_SHIFT 129 vsub.i32 q14, q14, q6 130 vsub.i32 q11, q11, q9 131 vtrn.16 d6, d8 132 vsub.i32 q13, q13, q5 133 vshrn.i32 d3, q14, #ROW_SHIFT 134 vtrn.32 d2, d6 135 vsub.i32 q12, q12, q10 136 vtrn.32 d4, d8 137 vshrn.i32 d5, q13, #ROW_SHIFT 138 vshrn.i32 d7, q12, #ROW_SHIFT 139 vshrn.i32 d9, q11, #ROW_SHIFT 140 141 vtrn.16 d3, d5 142 vtrn.16 d7, d9 143 vtrn.32 d3, d7 144 vtrn.32 d5, d9 145 146 vst1.64 {d2-d5}, [r2,:128]! 147 vst1.64 {d6-d9}, [r2,:128]! 148 149 bx lr 150endfunc 151 152function idct_col4_neon 153 mov ip, #16 154 vld1.64 {d2}, [r2,:64], ip /* d2 = col[0] */ 155 vdup.16 d30, w4c 156 vld1.64 {d4}, [r2,:64], ip /* d3 = col[1] */ 157 vadd.i16 d30, d30, d2 158 vld1.64 {d6}, [r2,:64], ip /* d4 = col[2] */ 159 vmull.s16 q15, d30, w4 /* q15 = W4*(col[0]+(1<<COL_SHIFT-1)/W4)*/ 160 vld1.64 {d8}, [r2,:64], ip /* d5 = col[3] */ 161 162 ldrd r4, r5, [r2] 163 ldrd r6, r7, [r2, #16] 164 orrs r4, r4, r5 165 166 idct_col4_top 167 it eq 168 addeq r2, r2, #16 169 beq 1f 170 171 vld1.64 {d3}, [r2,:64], ip /* d6 = col[4] */ 172 vmull.s16 q7, d3, w4 /* q7 = W4 * col[4] */ 173 vadd.i32 q11, q11, q7 174 vsub.i32 q12, q12, q7 175 vsub.i32 q13, q13, q7 176 vadd.i32 q14, q14, q7 177 1781: orrs r6, r6, r7 179 ldrd r4, r5, [r2, #16] 180 it eq 181 addeq r2, r2, #16 182 beq 2f 183 184 vld1.64 {d5}, [r2,:64], ip /* d7 = col[5] */ 185 vmlal.s16 q9, d5, w5 /* q9 += W5 * col[5] */ 186 vmlsl.s16 q10, d5, w1 /* q10 -= W1 * col[5] */ 187 vmlal.s16 q5, d5, w7 /* q5 += W7 * col[5] */ 188 vmlal.s16 q6, d5, w3 /* q6 += W3 * col[5] */ 189 1902: orrs r4, r4, r5 191 ldrd r4, r5, [r2, #16] 192 it eq 193 addeq r2, r2, #16 194 beq 3f 195 196 vld1.64 {d7}, [r2,:64], ip /* d8 = col[6] */ 197 vmull.s16 q7, d7, w6 /* q7 = W6 * col[6] */ 198 vmull.s16 q8, d7, w2 /* q8 = W2 * col[6] */ 199 vadd.i32 q11, q11, q7 200 vsub.i32 q14, q14, q7 201 vsub.i32 q12, q12, q8 202 vadd.i32 q13, q13, q8 203 2043: orrs r4, r4, r5 205 it eq 206 addeq r2, r2, #16 207 beq 4f 208 209 vld1.64 {d9}, [r2,:64], ip /* d9 = col[7] */ 210 vmlal.s16 q9, d9, w7 211 vmlsl.s16 q10, d9, w5 212 vmlal.s16 q5, d9, w3 213 vmlsl.s16 q6, d9, w1 214 2154: vaddhn.i32 d2, q11, q9 216 vaddhn.i32 d3, q12, q10 217 vaddhn.i32 d4, q13, q5 218 vaddhn.i32 d5, q14, q6 219 vsubhn.i32 d9, q11, q9 220 vsubhn.i32 d8, q12, q10 221 vsubhn.i32 d7, q13, q5 222 vsubhn.i32 d6, q14, q6 223 224 bx lr 225endfunc 226 227 .align 6 228 229function idct_col4_st8_neon 230 vqshrun.s16 d2, q1, #COL_SHIFT-16 231 vqshrun.s16 d3, q2, #COL_SHIFT-16 232 vqshrun.s16 d4, q3, #COL_SHIFT-16 233 vqshrun.s16 d5, q4, #COL_SHIFT-16 234 vst1.32 {d2[0]}, [r0,:32], r1 235 vst1.32 {d2[1]}, [r0,:32], r1 236 vst1.32 {d3[0]}, [r0,:32], r1 237 vst1.32 {d3[1]}, [r0,:32], r1 238 vst1.32 {d4[0]}, [r0,:32], r1 239 vst1.32 {d4[1]}, [r0,:32], r1 240 vst1.32 {d5[0]}, [r0,:32], r1 241 vst1.32 {d5[1]}, [r0,:32], r1 242 243 bx lr 244endfunc 245 246const idct_coeff_neon, align=4 247 .short W1, W2, W3, W4, W5, W6, W7, W4c 248endconst 249 250 .macro idct_start data 251 push {r4-r7, lr} 252 pld [\data] 253 pld [\data, #64] 254 vpush {d8-d15} 255 movrel r3, idct_coeff_neon 256 vld1.64 {d0,d1}, [r3,:128] 257 .endm 258 259 .macro idct_end 260 vpop {d8-d15} 261 pop {r4-r7, pc} 262 .endm 263 264/* void ff_simple_idct_put_neon(uint8_t *dst, ptrdiff_t line_size, int16_t *data); */ 265function ff_simple_idct_put_neon, export=1 266 idct_start r2 267 268 bl idct_row4_pld_neon 269 bl idct_row4_neon 270 add r2, r2, #-128 271 bl idct_col4_neon 272 bl idct_col4_st8_neon 273 sub r0, r0, r1, lsl #3 274 add r0, r0, #4 275 add r2, r2, #-120 276 bl idct_col4_neon 277 bl idct_col4_st8_neon 278 279 idct_end 280endfunc 281 282 .align 6 283 284function idct_col4_add8_neon 285 mov ip, r0 286 287 vld1.32 {d10[0]}, [r0,:32], r1 288 vshr.s16 q1, q1, #COL_SHIFT-16 289 vld1.32 {d10[1]}, [r0,:32], r1 290 vshr.s16 q2, q2, #COL_SHIFT-16 291 vld1.32 {d11[0]}, [r0,:32], r1 292 vshr.s16 q3, q3, #COL_SHIFT-16 293 vld1.32 {d11[1]}, [r0,:32], r1 294 vshr.s16 q4, q4, #COL_SHIFT-16 295 vld1.32 {d12[0]}, [r0,:32], r1 296 vaddw.u8 q1, q1, d10 297 vld1.32 {d12[1]}, [r0,:32], r1 298 vaddw.u8 q2, q2, d11 299 vld1.32 {d13[0]}, [r0,:32], r1 300 vqmovun.s16 d2, q1 301 vld1.32 {d13[1]}, [r0,:32], r1 302 vaddw.u8 q3, q3, d12 303 vst1.32 {d2[0]}, [ip,:32], r1 304 vqmovun.s16 d3, q2 305 vst1.32 {d2[1]}, [ip,:32], r1 306 vaddw.u8 q4, q4, d13 307 vst1.32 {d3[0]}, [ip,:32], r1 308 vqmovun.s16 d4, q3 309 vst1.32 {d3[1]}, [ip,:32], r1 310 vqmovun.s16 d5, q4 311 vst1.32 {d4[0]}, [ip,:32], r1 312 vst1.32 {d4[1]}, [ip,:32], r1 313 vst1.32 {d5[0]}, [ip,:32], r1 314 vst1.32 {d5[1]}, [ip,:32], r1 315 316 bx lr 317endfunc 318 319/* void ff_simple_idct_add_neon(uint8_t *dst, ptrdiff_t line_size, int16_t *data); */ 320function ff_simple_idct_add_neon, export=1 321 idct_start r2 322 323 bl idct_row4_pld_neon 324 bl idct_row4_neon 325 add r2, r2, #-128 326 bl idct_col4_neon 327 bl idct_col4_add8_neon 328 sub r0, r0, r1, lsl #3 329 add r0, r0, #4 330 add r2, r2, #-120 331 bl idct_col4_neon 332 bl idct_col4_add8_neon 333 334 idct_end 335endfunc 336 337 .align 6 338 339function idct_col4_st16_neon 340 mov ip, #16 341 342 vshr.s16 q1, q1, #COL_SHIFT-16 343 vshr.s16 q2, q2, #COL_SHIFT-16 344 vst1.64 {d2}, [r2,:64], ip 345 vshr.s16 q3, q3, #COL_SHIFT-16 346 vst1.64 {d3}, [r2,:64], ip 347 vshr.s16 q4, q4, #COL_SHIFT-16 348 vst1.64 {d4}, [r2,:64], ip 349 vst1.64 {d5}, [r2,:64], ip 350 vst1.64 {d6}, [r2,:64], ip 351 vst1.64 {d7}, [r2,:64], ip 352 vst1.64 {d8}, [r2,:64], ip 353 vst1.64 {d9}, [r2,:64], ip 354 355 bx lr 356endfunc 357 358/* void ff_simple_idct_neon(int16_t *data); */ 359function ff_simple_idct_neon, export=1 360 idct_start r0 361 362 mov r2, r0 363 bl idct_row4_neon 364 bl idct_row4_neon 365 add r2, r2, #-128 366 bl idct_col4_neon 367 add r2, r2, #-128 368 bl idct_col4_st16_neon 369 add r2, r2, #-120 370 bl idct_col4_neon 371 add r2, r2, #-128 372 bl idct_col4_st16_neon 373 374 idct_end 375endfunc 376