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 "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 .fpu neon 49 50 .macro idct_col4_top 51 vmull.s16 q7, d6, w2 /* q9 = W2 * col[2] */ 52 vmull.s16 q8, d6, w6 /* q10 = W6 * col[2] */ 53 vmull.s16 q9, d4, w1 /* q9 = W1 * col[1] */ 54 vadd.i32 q11, q15, q7 55 vmull.s16 q10, d4, w3 /* q10 = W3 * col[1] */ 56 vadd.i32 q12, q15, q8 57 vmull.s16 q5, d4, w5 /* q5 = W5 * col[1] */ 58 vsub.i32 q13, q15, q8 59 vmull.s16 q6, d4, w7 /* q6 = W7 * col[1] */ 60 vsub.i32 q14, q15, q7 61 62 vmlal.s16 q9, d8, w3 /* q9 += W3 * col[3] */ 63 vmlsl.s16 q10, d8, w7 /* q10 -= W7 * col[3] */ 64 vmlsl.s16 q5, d8, w1 /* q5 -= W1 * col[3] */ 65 vmlsl.s16 q6, d8, w5 /* q6 -= W5 * col[3] */ 66 .endm 67 68 .text 69 .align 6 70 71function idct_row4_neon 72 vmov.i32 q15, #(1<<(ROW_SHIFT-1)) 73 vld1.64 {d2-d5}, [r2,:128]! 74 vmlal.s16 q15, d2, w4 /* q15 += W4 * col[0] */ 75 vld1.64 {d6,d7}, [r2,:128]! 76 vorr d10, d3, d5 77 vld1.64 {d8,d9}, [r2,:128]! 78 add r2, r2, #-64 79 80 vorr d11, d7, d9 81 vorr d10, d10, d11 82 vmov r3, r4, d10 83 84 idct_col4_top 85 86 orrs r3, r3, r4 87 beq 1f 88 89 vmull.s16 q7, d3, w4 /* q7 = W4 * col[4] */ 90 vmlal.s16 q9, d5, w5 /* q9 += W5 * col[5] */ 91 vmlsl.s16 q10, d5, w1 /* q10 -= W1 * col[5] */ 92 vmull.s16 q8, d7, w2 /* q8 = W2 * col[6] */ 93 vmlal.s16 q5, d5, w7 /* q5 += W7 * col[5] */ 94 vadd.i32 q11, q11, q7 95 vsub.i32 q12, q12, q7 96 vsub.i32 q13, q13, q7 97 vadd.i32 q14, q14, q7 98 vmlal.s16 q6, d5, w3 /* q6 += W3 * col[5] */ 99 vmull.s16 q7, d7, w6 /* q7 = W6 * col[6] */ 100 vmlal.s16 q9, d9, w7 101 vmlsl.s16 q10, d9, w5 102 vmlal.s16 q5, d9, w3 103 vmlsl.s16 q6, d9, w1 104 vadd.i32 q11, q11, q7 105 vsub.i32 q12, q12, q8 106 vadd.i32 q13, q13, q8 107 vsub.i32 q14, q14, q7 108 1091: vadd.i32 q3, q11, q9 110 vadd.i32 q4, q12, q10 111 vshrn.i32 d2, q3, #ROW_SHIFT 112 vshrn.i32 d4, q4, #ROW_SHIFT 113 vadd.i32 q7, q13, q5 114 vadd.i32 q8, q14, q6 115 vtrn.16 d2, d4 116 vshrn.i32 d6, q7, #ROW_SHIFT 117 vshrn.i32 d8, q8, #ROW_SHIFT 118 vsub.i32 q14, q14, q6 119 vsub.i32 q11, q11, q9 120 vtrn.16 d6, d8 121 vsub.i32 q13, q13, q5 122 vshrn.i32 d3, q14, #ROW_SHIFT 123 vtrn.32 d2, d6 124 vsub.i32 q12, q12, q10 125 vtrn.32 d4, d8 126 vshrn.i32 d5, q13, #ROW_SHIFT 127 vshrn.i32 d7, q12, #ROW_SHIFT 128 vshrn.i32 d9, q11, #ROW_SHIFT 129 130 vtrn.16 d3, d5 131 vtrn.16 d7, d9 132 vtrn.32 d3, d7 133 vtrn.32 d5, d9 134 135 vst1.64 {d2-d5}, [r2,:128]! 136 vst1.64 {d6-d9}, [r2,:128]! 137 138 bx lr 139 .endfunc 140 141function idct_col4_neon 142 mov ip, #16 143 vld1.64 {d2}, [r2,:64], ip /* d2 = col[0] */ 144 vdup.16 d30, w4c 145 vld1.64 {d4}, [r2,:64], ip /* d3 = col[1] */ 146 vadd.i16 d30, d30, d2 147 vld1.64 {d6}, [r2,:64], ip /* d4 = col[2] */ 148 vmull.s16 q15, d30, w4 /* q15 = W4*(col[0]+(1<<COL_SHIFT-1)/W4)*/ 149 vld1.64 {d8}, [r2,:64], ip /* d5 = col[3] */ 150 151 ldrd r4, [r2] 152 ldrd r6, [r2, #16] 153 orrs r4, r4, r5 154 155 idct_col4_top 156 addeq r2, r2, #16 157 beq 1f 158 159 vld1.64 {d3}, [r2,:64], ip /* d6 = col[4] */ 160 vmull.s16 q7, d3, w4 /* q7 = W4 * col[4] */ 161 vadd.i32 q11, q11, q7 162 vsub.i32 q12, q12, q7 163 vsub.i32 q13, q13, q7 164 vadd.i32 q14, q14, q7 165 1661: orrs r6, r6, r7 167 ldrd r4, [r2, #16] 168 addeq r2, r2, #16 169 beq 2f 170 171 vld1.64 {d5}, [r2,:64], ip /* d7 = col[5] */ 172 vmlal.s16 q9, d5, w5 /* q9 += W5 * col[5] */ 173 vmlsl.s16 q10, d5, w1 /* q10 -= W1 * col[5] */ 174 vmlal.s16 q5, d5, w7 /* q5 += W7 * col[5] */ 175 vmlal.s16 q6, d5, w3 /* q6 += W3 * col[5] */ 176 1772: orrs r4, r4, r5 178 ldrd r4, [r2, #16] 179 addeq r2, r2, #16 180 beq 3f 181 182 vld1.64 {d7}, [r2,:64], ip /* d8 = col[6] */ 183 vmull.s16 q7, d7, w6 /* q7 = W6 * col[6] */ 184 vmull.s16 q8, d7, w2 /* q8 = W2 * col[6] */ 185 vadd.i32 q11, q11, q7 186 vsub.i32 q14, q14, q7 187 vsub.i32 q12, q12, q8 188 vadd.i32 q13, q13, q8 189 1903: orrs r4, r4, r5 191 addeq r2, r2, #16 192 beq 4f 193 194 vld1.64 {d9}, [r2,:64], ip /* d9 = col[7] */ 195 vmlal.s16 q9, d9, w7 196 vmlsl.s16 q10, d9, w5 197 vmlal.s16 q5, d9, w3 198 vmlsl.s16 q6, d9, w1 199 2004: vaddhn.i32 d2, q11, q9 201 vaddhn.i32 d3, q12, q10 202 vaddhn.i32 d4, q13, q5 203 vaddhn.i32 d5, q14, q6 204 vsubhn.i32 d9, q11, q9 205 vsubhn.i32 d8, q12, q10 206 vsubhn.i32 d7, q13, q5 207 vsubhn.i32 d6, q14, q6 208 209 bx lr 210 .endfunc 211 212 .align 6 213 214function idct_col4_st8_neon 215 vqshrun.s16 d2, q1, #COL_SHIFT-16 216 vqshrun.s16 d3, q2, #COL_SHIFT-16 217 vqshrun.s16 d4, q3, #COL_SHIFT-16 218 vqshrun.s16 d5, q4, #COL_SHIFT-16 219 vst1.32 {d2[0]}, [r0,:32], r1 220 vst1.32 {d2[1]}, [r0,:32], r1 221 vst1.32 {d3[0]}, [r0,:32], r1 222 vst1.32 {d3[1]}, [r0,:32], r1 223 vst1.32 {d4[0]}, [r0,:32], r1 224 vst1.32 {d4[1]}, [r0,:32], r1 225 vst1.32 {d5[0]}, [r0,:32], r1 226 vst1.32 {d5[1]}, [r0,:32], r1 227 228 bx lr 229 .endfunc 230 231 .section .rodata 232 .align 4 233idct_coeff_neon: 234 .short W1, W2, W3, W4, W5, W6, W7, W4c 235 .previous 236 237 .macro idct_start data 238 push {r4-r7, lr} 239 pld [\data] 240 pld [\data, #64] 241 vpush {d8-d15} 242 movrel r3, idct_coeff_neon 243 vld1.64 {d0,d1}, [r3,:128] 244 .endm 245 246 .macro idct_end 247 vpop {d8-d15} 248 pop {r4-r7, pc} 249 .endm 250 251/* void ff_simple_idct_put_neon(uint8_t *dst, int line_size, DCTELEM *data); */ 252function ff_simple_idct_put_neon, export=1 253 idct_start r2 254 255 bl idct_row4_neon 256 bl idct_row4_neon 257 add r2, r2, #-128 258 bl idct_col4_neon 259 bl idct_col4_st8_neon 260 sub r0, r0, r1, lsl #3 261 add r0, r0, #4 262 add r2, r2, #-120 263 bl idct_col4_neon 264 bl idct_col4_st8_neon 265 266 idct_end 267 .endfunc 268 269 .align 6 270 271function idct_col4_add8_neon 272 mov ip, r0 273 274 vld1.32 {d10[0]}, [r0,:32], r1 275 vshr.s16 q1, q1, #COL_SHIFT-16 276 vld1.32 {d10[1]}, [r0,:32], r1 277 vshr.s16 q2, q2, #COL_SHIFT-16 278 vld1.32 {d11[0]}, [r0,:32], r1 279 vshr.s16 q3, q3, #COL_SHIFT-16 280 vld1.32 {d11[1]}, [r0,:32], r1 281 vshr.s16 q4, q4, #COL_SHIFT-16 282 vld1.32 {d12[0]}, [r0,:32], r1 283 vaddw.u8 q1, q1, d10 284 vld1.32 {d12[1]}, [r0,:32], r1 285 vaddw.u8 q2, q2, d11 286 vld1.32 {d13[0]}, [r0,:32], r1 287 vqmovun.s16 d2, q1 288 vld1.32 {d13[1]}, [r0,:32], r1 289 vaddw.u8 q3, q3, d12 290 vst1.32 {d2[0]}, [ip,:32], r1 291 vqmovun.s16 d3, q2 292 vst1.32 {d2[1]}, [ip,:32], r1 293 vaddw.u8 q4, q4, d13 294 vst1.32 {d3[0]}, [ip,:32], r1 295 vqmovun.s16 d4, q3 296 vst1.32 {d3[1]}, [ip,:32], r1 297 vqmovun.s16 d5, q4 298 vst1.32 {d4[0]}, [ip,:32], r1 299 vst1.32 {d4[1]}, [ip,:32], r1 300 vst1.32 {d5[0]}, [ip,:32], r1 301 vst1.32 {d5[1]}, [ip,:32], r1 302 303 bx lr 304 .endfunc 305 306/* void ff_simple_idct_add_neon(uint8_t *dst, int line_size, DCTELEM *data); */ 307function ff_simple_idct_add_neon, export=1 308 idct_start r2 309 310 bl idct_row4_neon 311 bl idct_row4_neon 312 add r2, r2, #-128 313 bl idct_col4_neon 314 bl idct_col4_add8_neon 315 sub r0, r0, r1, lsl #3 316 add r0, r0, #4 317 add r2, r2, #-120 318 bl idct_col4_neon 319 bl idct_col4_add8_neon 320 321 idct_end 322 .endfunc 323 324 .align 6 325 326function idct_col4_st16_neon 327 mov ip, #16 328 329 vshr.s16 q1, q1, #COL_SHIFT-16 330 vshr.s16 q2, q2, #COL_SHIFT-16 331 vst1.64 {d2}, [r2,:64], ip 332 vshr.s16 q3, q3, #COL_SHIFT-16 333 vst1.64 {d3}, [r2,:64], ip 334 vshr.s16 q4, q4, #COL_SHIFT-16 335 vst1.64 {d4}, [r2,:64], ip 336 vst1.64 {d5}, [r2,:64], ip 337 vst1.64 {d6}, [r2,:64], ip 338 vst1.64 {d7}, [r2,:64], ip 339 vst1.64 {d8}, [r2,:64], ip 340 vst1.64 {d9}, [r2,:64], ip 341 342 bx lr 343 .endfunc 344 345/* void ff_simple_idct_neon(DCTELEM *data); */ 346function ff_simple_idct_neon, export=1 347 idct_start r0 348 349 mov r2, r0 350 bl idct_row4_neon 351 bl idct_row4_neon 352 add r2, r2, #-128 353 bl idct_col4_neon 354 add r2, r2, #-128 355 bl idct_col4_st16_neon 356 add r2, r2, #-120 357 bl idct_col4_neon 358 add r2, r2, #-128 359 bl idct_col4_st16_neon 360 361 idct_end 362 .endfunc 363