2 ; Copyright (c) 2013 The WebM project authors. All Rights Reserved.
4 ; Use of this source code is governed by a BSD-style license
5 ; that can be found in the LICENSE file in the root of the source
6 ; tree. An additional intellectual property rights grant can be found
7 ; in the file PATENTS. All contributing project authors may
8 ; be found in the AUTHORS file in the root of the source tree.
11 EXPORT |vp9_idct8x8_64_add_neon|
12 EXPORT |vp9_idct8x8_10_add_neon|
17 AREA ||.text||, CODE, READONLY, ALIGN=2
19 ; Parallel 1D IDCT on all the columns of a 8x8 16bit data matrix which are
20 ; loaded in q8-q15. The output will be stored back into q8-q15 registers.
21 ; This macro will touch q0-q7 registers and use them as buffer during
26 vdup.16 d0, r3 ; duplicate cospi_28_64
27 vdup.16 d1, r4 ; duplicate cospi_4_64
28 vdup.16 d2, r5 ; duplicate cospi_12_64
29 vdup.16 d3, r6 ; duplicate cospi_20_64
31 ; input[1] * cospi_28_64
35 ; input[5] * cospi_12_64
39 ; input[1]*cospi_28_64-input[7]*cospi_4_64
43 ; input[5] * cospi_12_64 - input[3] * cospi_20_64
47 ; dct_const_round_shift(input_dc * cospi_16_64)
48 vqrshrn.s32 d8, q2, #14 ; >> 14
49 vqrshrn.s32 d9, q3, #14 ; >> 14
51 ; dct_const_round_shift(input_dc * cospi_16_64)
52 vqrshrn.s32 d10, q5, #14 ; >> 14
53 vqrshrn.s32 d11, q6, #14 ; >> 14
55 ; input[1] * cospi_4_64
59 ; input[5] * cospi_20_64
61 vmull.s16 q13, d27, d3
63 ; input[1]*cospi_4_64+input[7]*cospi_28_64
67 ; input[5] * cospi_20_64 + input[3] * cospi_12_64
69 vmlal.s16 q13, d23, d2
71 ; dct_const_round_shift(input_dc * cospi_16_64)
72 vqrshrn.s32 d14, q2, #14 ; >> 14
73 vqrshrn.s32 d15, q3, #14 ; >> 14
75 ; stage 2 & stage 3 - even half
76 vdup.16 d0, r7 ; duplicate cospi_16_64
78 ; dct_const_round_shift(input_dc * cospi_16_64)
79 vqrshrn.s32 d12, q9, #14 ; >> 14
80 vqrshrn.s32 d13, q13, #14 ; >> 14
82 ; input[0] * cospi_16_64
86 ; input[0] * cospi_16_64
87 vmull.s16 q13, d16, d0
88 vmull.s16 q15, d17, d0
90 ; (input[0] + input[2]) * cospi_16_64
94 ; (input[0] - input[2]) * cospi_16_64
95 vmlsl.s16 q13, d24, d0
96 vmlsl.s16 q15, d25, d0
98 vdup.16 d0, r8 ; duplicate cospi_24_64
99 vdup.16 d1, r9 ; duplicate cospi_8_64
101 ; dct_const_round_shift(input_dc * cospi_16_64)
102 vqrshrn.s32 d18, q2, #14 ; >> 14
103 vqrshrn.s32 d19, q3, #14 ; >> 14
105 ; dct_const_round_shift(input_dc * cospi_16_64)
106 vqrshrn.s32 d22, q13, #14 ; >> 14
107 vqrshrn.s32 d23, q15, #14 ; >> 14
109 ; input[1] * cospi_24_64 - input[3] * cospi_8_64
110 ; input[1] * cospi_24_64
111 vmull.s16 q2, d20, d0
112 vmull.s16 q3, d21, d0
114 ; input[1] * cospi_8_64
115 vmull.s16 q8, d20, d1
116 vmull.s16 q12, d21, d1
118 ; input[1] * cospi_24_64 - input[3] * cospi_8_64
119 vmlsl.s16 q2, d28, d1
120 vmlsl.s16 q3, d29, d1
122 ; input[1] * cospi_8_64 + input[3] * cospi_24_64
123 vmlal.s16 q8, d28, d0
124 vmlal.s16 q12, d29, d0
126 ; dct_const_round_shift(input_dc * cospi_16_64)
127 vqrshrn.s32 d26, q2, #14 ; >> 14
128 vqrshrn.s32 d27, q3, #14 ; >> 14
130 ; dct_const_round_shift(input_dc * cospi_16_64)
131 vqrshrn.s32 d30, q8, #14 ; >> 14
132 vqrshrn.s32 d31, q12, #14 ; >> 14
134 vadd.s16 q0, q9, q15 ; output[0] = step[0] + step[3]
135 vadd.s16 q1, q11, q13 ; output[1] = step[1] + step[2]
136 vsub.s16 q2, q11, q13 ; output[2] = step[1] - step[2]
137 vsub.s16 q3, q9, q15 ; output[3] = step[0] - step[3]
140 vdup.16 d16, r7 ; duplicate cospi_16_64
143 vsub.s16 q13, q4, q5 ; step2[5] = step1[4] - step1[5]
144 vadd.s16 q4, q4, q5 ; step2[4] = step1[4] + step1[5]
145 vsub.s16 q14, q7, q6 ; step2[6] = -step1[6] + step1[7]
146 vadd.s16 q7, q7, q6 ; step2[7] = step1[6] + step1[7]
148 ; step2[6] * cospi_16_64
149 vmull.s16 q9, d28, d16
150 vmull.s16 q10, d29, d16
152 ; step2[6] * cospi_16_64
153 vmull.s16 q11, d28, d16
154 vmull.s16 q12, d29, d16
156 ; (step2[6] - step2[5]) * cospi_16_64
157 vmlsl.s16 q9, d26, d16
158 vmlsl.s16 q10, d27, d16
160 ; (step2[5] + step2[6]) * cospi_16_64
161 vmlal.s16 q11, d26, d16
162 vmlal.s16 q12, d27, d16
164 ; dct_const_round_shift(input_dc * cospi_16_64)
165 vqrshrn.s32 d10, q9, #14 ; >> 14
166 vqrshrn.s32 d11, q10, #14 ; >> 14
168 ; dct_const_round_shift(input_dc * cospi_16_64)
169 vqrshrn.s32 d12, q11, #14 ; >> 14
170 vqrshrn.s32 d13, q12, #14 ; >> 14
173 vadd.s16 q8, q0, q7 ; output[0] = step1[0] + step1[7];
174 vadd.s16 q9, q1, q6 ; output[1] = step1[1] + step1[6];
175 vadd.s16 q10, q2, q5 ; output[2] = step1[2] + step1[5];
176 vadd.s16 q11, q3, q4 ; output[3] = step1[3] + step1[4];
177 vsub.s16 q12, q3, q4 ; output[4] = step1[3] - step1[4];
178 vsub.s16 q13, q2, q5 ; output[5] = step1[2] - step1[5];
179 vsub.s16 q14, q1, q6 ; output[6] = step1[1] - step1[6];
180 vsub.s16 q15, q0, q7 ; output[7] = step1[0] - step1[7];
183 ; Transpose a 8x8 16bit data matrix. Datas are loaded in q8-q15.
200 AREA Block, CODE, READONLY ; name this block of code
201 ;void vp9_idct8x8_64_add_neon(int16_t *input, uint8_t *dest, int dest_stride)
205 ; r2 int dest_stride)
207 |vp9_idct8x8_64_add_neon| PROC
210 vld1.s16 {q8,q9}, [r0]!
211 vld1.s16 {q10,q11}, [r0]!
212 vld1.s16 {q12,q13}, [r0]!
213 vld1.s16 {q14,q15}, [r0]!
215 ; transpose the input data
218 ; generate cospi_28_64 = 3196
222 ; generate cospi_4_64 = 16069
226 ; generate cospi_12_64 = 13623
230 ; generate cospi_20_64 = 9102
234 ; generate cospi_16_64 = 11585
238 ; generate cospi_24_64 = 6270
242 ; generate cospi_8_64 = 15137
246 ; First transform rows
249 ; Transpose the matrix
252 ; Then transform columns
255 ; ROUND_POWER_OF_TWO(temp_out[j], 5)
258 vrshr.s16 q10, q10, #5
259 vrshr.s16 q11, q11, #5
260 vrshr.s16 q12, q12, #5
261 vrshr.s16 q13, q13, #5
262 vrshr.s16 q14, q14, #5
263 vrshr.s16 q15, q15, #5
268 ; load destination data
269 vld1.64 {d0}, [r1], r2
270 vld1.64 {d1}, [r1], r2
271 vld1.64 {d2}, [r1], r2
272 vld1.64 {d3}, [r1], r2
273 vld1.64 {d4}, [r1], r2
274 vld1.64 {d5}, [r1], r2
275 vld1.64 {d6}, [r1], r2
278 ; ROUND_POWER_OF_TWO(temp_out[j], 5) + dest[j * dest_stride + i]
281 vaddw.u8 q10, q10, d2
282 vaddw.u8 q11, q11, d3
283 vaddw.u8 q12, q12, d4
284 vaddw.u8 q13, q13, d5
285 vaddw.u8 q14, q14, d6
286 vaddw.u8 q15, q15, d7
299 vst1.64 {d0}, [r0], r2
300 vst1.64 {d1}, [r0], r2
301 vst1.64 {d2}, [r0], r2
302 vst1.64 {d3}, [r0], r2
303 vst1.64 {d4}, [r0], r2
304 vst1.64 {d5}, [r0], r2
305 vst1.64 {d6}, [r0], r2
306 vst1.64 {d7}, [r0], r2
311 ENDP ; |vp9_idct8x8_64_add_neon|
313 ;void vp9_idct8x8_10_add_neon(int16_t *input, uint8_t *dest, int dest_stride)
317 ; r2 int dest_stride)
319 |vp9_idct8x8_10_add_neon| PROC
322 vld1.s16 {q8,q9}, [r0]!
323 vld1.s16 {q10,q11}, [r0]!
324 vld1.s16 {q12,q13}, [r0]!
325 vld1.s16 {q14,q15}, [r0]!
327 ; transpose the input data
330 ; generate cospi_28_64 = 3196
334 ; generate cospi_4_64 = 16069
338 ; generate cospi_12_64 = 13623
342 ; generate cospi_20_64 = 9102
346 ; generate cospi_16_64 = 11585
350 ; generate cospi_24_64 = 6270
354 ; generate cospi_8_64 = 15137
358 ; First transform rows
360 ; The following instructions use vqrdmulh to do the
361 ; dct_const_round_shift(input[1] * cospi_28_64). vqrdmulh will do doubling
362 ; multiply and shift the result by 16 bits instead of 14 bits. So we need
363 ; to double the constants before multiplying to compensate this.
365 vdup.16 q0, r12 ; duplicate cospi_28_64*2
367 vdup.16 q1, r12 ; duplicate cospi_4_64*2
369 ; dct_const_round_shift(input[1] * cospi_28_64)
370 vqrdmulh.s16 q4, q9, q0
374 vdup.16 q0, r12 ; duplicate -cospi_20_64*2
376 ; dct_const_round_shift(input[1] * cospi_4_64)
377 vqrdmulh.s16 q7, q9, q1
380 vdup.16 q1, r12 ; duplicate cospi_12_64*2
382 ; dct_const_round_shift(- input[3] * cospi_20_64)
383 vqrdmulh.s16 q5, q11, q0
386 vdup.16 q0, r12 ; duplicate cospi_16_64*2
388 ; dct_const_round_shift(input[3] * cospi_12_64)
389 vqrdmulh.s16 q6, q11, q1
391 ; stage 2 & stage 3 - even half
393 vdup.16 q1, r12 ; duplicate cospi_24_64*2
395 ; dct_const_round_shift(input_dc * cospi_16_64)
396 vqrdmulh.s16 q9, q8, q0
399 vdup.16 q0, r12 ; duplicate cospi_8_64*2
401 ; dct_const_round_shift(input[1] * cospi_24_64)
402 vqrdmulh.s16 q13, q10, q1
404 ; dct_const_round_shift(input[1] * cospi_8_64)
405 vqrdmulh.s16 q15, q10, q0
408 vdup.16 d16, r7 ; duplicate cospi_16_64
410 vadd.s16 q0, q9, q15 ; output[0] = step[0] + step[3]
411 vadd.s16 q1, q9, q13 ; output[1] = step[1] + step[2]
412 vsub.s16 q2, q9, q13 ; output[2] = step[1] - step[2]
413 vsub.s16 q3, q9, q15 ; output[3] = step[0] - step[3]
416 vsub.s16 q13, q4, q5 ; step2[5] = step1[4] - step1[5]
417 vadd.s16 q4, q4, q5 ; step2[4] = step1[4] + step1[5]
418 vsub.s16 q14, q7, q6 ; step2[6] = -step1[6] + step1[7]
419 vadd.s16 q7, q7, q6 ; step2[7] = step1[6] + step1[7]
421 ; step2[6] * cospi_16_64
422 vmull.s16 q9, d28, d16
423 vmull.s16 q10, d29, d16
425 ; step2[6] * cospi_16_64
426 vmull.s16 q11, d28, d16
427 vmull.s16 q12, d29, d16
429 ; (step2[6] - step2[5]) * cospi_16_64
430 vmlsl.s16 q9, d26, d16
431 vmlsl.s16 q10, d27, d16
433 ; (step2[5] + step2[6]) * cospi_16_64
434 vmlal.s16 q11, d26, d16
435 vmlal.s16 q12, d27, d16
437 ; dct_const_round_shift(input_dc * cospi_16_64)
438 vqrshrn.s32 d10, q9, #14 ; >> 14
439 vqrshrn.s32 d11, q10, #14 ; >> 14
441 ; dct_const_round_shift(input_dc * cospi_16_64)
442 vqrshrn.s32 d12, q11, #14 ; >> 14
443 vqrshrn.s32 d13, q12, #14 ; >> 14
446 vadd.s16 q8, q0, q7 ; output[0] = step1[0] + step1[7];
447 vadd.s16 q9, q1, q6 ; output[1] = step1[1] + step1[6];
448 vadd.s16 q10, q2, q5 ; output[2] = step1[2] + step1[5];
449 vadd.s16 q11, q3, q4 ; output[3] = step1[3] + step1[4];
450 vsub.s16 q12, q3, q4 ; output[4] = step1[3] - step1[4];
451 vsub.s16 q13, q2, q5 ; output[5] = step1[2] - step1[5];
452 vsub.s16 q14, q1, q6 ; output[6] = step1[1] - step1[6];
453 vsub.s16 q15, q0, q7 ; output[7] = step1[0] - step1[7];
455 ; Transpose the matrix
458 ; Then transform columns
461 ; ROUND_POWER_OF_TWO(temp_out[j], 5)
464 vrshr.s16 q10, q10, #5
465 vrshr.s16 q11, q11, #5
466 vrshr.s16 q12, q12, #5
467 vrshr.s16 q13, q13, #5
468 vrshr.s16 q14, q14, #5
469 vrshr.s16 q15, q15, #5
474 ; load destination data
475 vld1.64 {d0}, [r1], r2
476 vld1.64 {d1}, [r1], r2
477 vld1.64 {d2}, [r1], r2
478 vld1.64 {d3}, [r1], r2
479 vld1.64 {d4}, [r1], r2
480 vld1.64 {d5}, [r1], r2
481 vld1.64 {d6}, [r1], r2
484 ; ROUND_POWER_OF_TWO(temp_out[j], 5) + dest[j * dest_stride + i]
487 vaddw.u8 q10, q10, d2
488 vaddw.u8 q11, q11, d3
489 vaddw.u8 q12, q12, d4
490 vaddw.u8 q13, q13, d5
491 vaddw.u8 q14, q14, d6
492 vaddw.u8 q15, q15, d7
505 vst1.64 {d0}, [r0], r2
506 vst1.64 {d1}, [r0], r2
507 vst1.64 {d2}, [r0], r2
508 vst1.64 {d3}, [r0], r2
509 vst1.64 {d4}, [r0], r2
510 vst1.64 {d5}, [r0], r2
511 vst1.64 {d6}, [r0], r2
512 vst1.64 {d7}, [r0], r2
517 ENDP ; |vp9_idct8x8_10_add_neon|