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_iht8x8_64_add_neon|
16 AREA ||.text||, CODE, READONLY, ALIGN=2
18 ; Generate IADST constants in r0 - r12 for the IADST.
20 GENERATE_IADST_CONSTANTS
21 ; generate cospi_2_64 = 16305
25 ; generate cospi_30_64 = 1606
29 ; generate cospi_10_64 = 14449
33 ; generate cospi_22_64 = 7723
37 ; generate cospi_18_64 = 10394
41 ; generate cospi_14_64 = 12665
45 ; generate cospi_26_64 = 4756
49 ; generate cospi_6_64 = 15679
53 ; generate cospi_8_64 = 15137
57 ; generate cospi_24_64 = 6270
64 ; generate cospi_16_64 = 11585
69 ; Generate IDCT constants in r3 - r9 for the IDCT.
71 GENERATE_IDCT_CONSTANTS
72 ; generate cospi_28_64 = 3196
76 ; generate cospi_4_64 = 16069
80 ; generate cospi_12_64 = 13623
84 ; generate cospi_20_64 = 9102
88 ; generate cospi_16_64 = 11585
92 ; generate cospi_24_64 = 6270
96 ; generate cospi_8_64 = 15137
101 ; Transpose a 8x8 16bits data matrix. Datas are loaded in q8-q15.
118 ; Parallel 1D IDCT on all the columns of a 8x8 16bits data matrix which are
119 ; loaded in q8-q15. The IDCT constants are loaded in r3 - r9. The output
120 ; will be stored back into q8-q15 registers. This macro will touch q0-q7
121 ; registers and use them as buffer during calculation.
125 vdup.16 d0, r3 ; duplicate cospi_28_64
126 vdup.16 d1, r4 ; duplicate cospi_4_64
127 vdup.16 d2, r5 ; duplicate cospi_12_64
128 vdup.16 d3, r6 ; duplicate cospi_20_64
130 ; input[1] * cospi_28_64
131 vmull.s16 q2, d18, d0
132 vmull.s16 q3, d19, d0
134 ; input[5] * cospi_12_64
135 vmull.s16 q5, d26, d2
136 vmull.s16 q6, d27, d2
138 ; input[1]*cospi_28_64-input[7]*cospi_4_64
139 vmlsl.s16 q2, d30, d1
140 vmlsl.s16 q3, d31, d1
142 ; input[5] * cospi_12_64 - input[3] * cospi_20_64
143 vmlsl.s16 q5, d22, d3
144 vmlsl.s16 q6, d23, d3
146 ; dct_const_round_shift(input_dc * cospi_16_64)
147 vqrshrn.s32 d8, q2, #14 ; >> 14
148 vqrshrn.s32 d9, q3, #14 ; >> 14
150 ; dct_const_round_shift(input_dc * cospi_16_64)
151 vqrshrn.s32 d10, q5, #14 ; >> 14
152 vqrshrn.s32 d11, q6, #14 ; >> 14
154 ; input[1] * cospi_4_64
155 vmull.s16 q2, d18, d1
156 vmull.s16 q3, d19, d1
158 ; input[5] * cospi_20_64
159 vmull.s16 q9, d26, d3
160 vmull.s16 q13, d27, d3
162 ; input[1]*cospi_4_64+input[7]*cospi_28_64
163 vmlal.s16 q2, d30, d0
164 vmlal.s16 q3, d31, d0
166 ; input[5] * cospi_20_64 + input[3] * cospi_12_64
167 vmlal.s16 q9, d22, d2
168 vmlal.s16 q13, d23, d2
170 ; dct_const_round_shift(input_dc * cospi_16_64)
171 vqrshrn.s32 d14, q2, #14 ; >> 14
172 vqrshrn.s32 d15, q3, #14 ; >> 14
174 ; stage 2 & stage 3 - even half
175 vdup.16 d0, r7 ; duplicate cospi_16_64
177 ; dct_const_round_shift(input_dc * cospi_16_64)
178 vqrshrn.s32 d12, q9, #14 ; >> 14
179 vqrshrn.s32 d13, q13, #14 ; >> 14
181 ; input[0] * cospi_16_64
182 vmull.s16 q2, d16, d0
183 vmull.s16 q3, d17, d0
185 ; input[0] * cospi_16_64
186 vmull.s16 q13, d16, d0
187 vmull.s16 q15, d17, d0
189 ; (input[0] + input[2]) * cospi_16_64
190 vmlal.s16 q2, d24, d0
191 vmlal.s16 q3, d25, d0
193 ; (input[0] - input[2]) * cospi_16_64
194 vmlsl.s16 q13, d24, d0
195 vmlsl.s16 q15, d25, d0
197 vdup.16 d0, r8 ; duplicate cospi_24_64
198 vdup.16 d1, r9 ; duplicate cospi_8_64
200 ; dct_const_round_shift(input_dc * cospi_16_64)
201 vqrshrn.s32 d18, q2, #14 ; >> 14
202 vqrshrn.s32 d19, q3, #14 ; >> 14
204 ; dct_const_round_shift(input_dc * cospi_16_64)
205 vqrshrn.s32 d22, q13, #14 ; >> 14
206 vqrshrn.s32 d23, q15, #14 ; >> 14
208 ; input[1] * cospi_24_64
209 vmull.s16 q2, d20, d0
210 vmull.s16 q3, d21, d0
212 ; input[1] * cospi_8_64
213 vmull.s16 q8, d20, d1
214 vmull.s16 q12, d21, d1
216 ; input[1] * cospi_24_64 - input[3] * cospi_8_64
217 vmlsl.s16 q2, d28, d1
218 vmlsl.s16 q3, d29, d1
220 ; input[1] * cospi_8_64 + input[3] * cospi_24_64
221 vmlal.s16 q8, d28, d0
222 vmlal.s16 q12, d29, d0
224 ; dct_const_round_shift(input_dc * cospi_16_64)
225 vqrshrn.s32 d26, q2, #14 ; >> 14
226 vqrshrn.s32 d27, q3, #14 ; >> 14
228 ; dct_const_round_shift(input_dc * cospi_16_64)
229 vqrshrn.s32 d30, q8, #14 ; >> 14
230 vqrshrn.s32 d31, q12, #14 ; >> 14
232 vadd.s16 q0, q9, q15 ; output[0] = step[0] + step[3]
233 vadd.s16 q1, q11, q13 ; output[1] = step[1] + step[2]
234 vsub.s16 q2, q11, q13 ; output[2] = step[1] - step[2]
235 vsub.s16 q3, q9, q15 ; output[3] = step[0] - step[3]
238 vdup.16 d16, r7 ; duplicate cospi_16_64
241 vsub.s16 q13, q4, q5 ; step2[5] = step1[4] - step1[5]
242 vadd.s16 q4, q4, q5 ; step2[4] = step1[4] + step1[5]
243 vsub.s16 q14, q7, q6 ; step2[6] = -step1[6] + step1[7]
244 vadd.s16 q7, q7, q6 ; step2[7] = step1[6] + step1[7]
246 ; step2[6] * cospi_16_64
247 vmull.s16 q9, d28, d16
248 vmull.s16 q10, d29, d16
250 ; step2[6] * cospi_16_64
251 vmull.s16 q11, d28, d16
252 vmull.s16 q12, d29, d16
254 ; (step2[6] - step2[5]) * cospi_16_64
255 vmlsl.s16 q9, d26, d16
256 vmlsl.s16 q10, d27, d16
258 ; (step2[5] + step2[6]) * cospi_16_64
259 vmlal.s16 q11, d26, d16
260 vmlal.s16 q12, d27, d16
262 ; dct_const_round_shift(input_dc * cospi_16_64)
263 vqrshrn.s32 d10, q9, #14 ; >> 14
264 vqrshrn.s32 d11, q10, #14 ; >> 14
266 ; dct_const_round_shift(input_dc * cospi_16_64)
267 vqrshrn.s32 d12, q11, #14 ; >> 14
268 vqrshrn.s32 d13, q12, #14 ; >> 14
271 vadd.s16 q8, q0, q7 ; output[0] = step1[0] + step1[7];
272 vadd.s16 q9, q1, q6 ; output[1] = step1[1] + step1[6];
273 vadd.s16 q10, q2, q5 ; output[2] = step1[2] + step1[5];
274 vadd.s16 q11, q3, q4 ; output[3] = step1[3] + step1[4];
275 vsub.s16 q12, q3, q4 ; output[4] = step1[3] - step1[4];
276 vsub.s16 q13, q2, q5 ; output[5] = step1[2] - step1[5];
277 vsub.s16 q14, q1, q6 ; output[6] = step1[1] - step1[6];
278 vsub.s16 q15, q0, q7 ; output[7] = step1[0] - step1[7];
281 ; Parallel 1D IADST on all the columns of a 8x8 16bits data matrix which
282 ; loaded in q8-q15. IADST constants are loaded in r0 - r12 registers. The
283 ; output will be stored back into q8-q15 registers. This macro will touch
284 ; q0 - q7 registers and use them as buffer during calculation.
287 vdup.16 d14, r0 ; duplicate cospi_2_64
288 vdup.16 d15, r1 ; duplicate cospi_30_64
291 vmull.s16 q1, d30, d14
292 vmull.s16 q2, d31, d14
295 vmull.s16 q3, d30, d15
296 vmull.s16 q4, d31, d15
298 vdup.16 d30, r4 ; duplicate cospi_18_64
299 vdup.16 d31, r5 ; duplicate cospi_14_64
301 ; s0 = cospi_2_64 * x0 + cospi_30_64 * x1;
302 vmlal.s16 q1, d16, d15
303 vmlal.s16 q2, d17, d15
305 ; s1 = cospi_30_64 * x0 - cospi_2_64 * x1
306 vmlsl.s16 q3, d16, d14
307 vmlsl.s16 q4, d17, d14
310 vmull.s16 q5, d22, d30
311 vmull.s16 q6, d23, d30
314 vmull.s16 q7, d22, d31
315 vmull.s16 q8, d23, d31
317 ; s4 = cospi_18_64 * x4 + cospi_14_64 * x5;
318 vmlal.s16 q5, d24, d31
319 vmlal.s16 q6, d25, d31
321 ; s5 = cospi_14_64 * x4 - cospi_18_64 * x5
322 vmlsl.s16 q7, d24, d30
323 vmlsl.s16 q8, d25, d30
329 vdup.16 d0, r2 ; duplicate cospi_10_64
330 vdup.16 d1, r3 ; duplicate cospi_22_64
336 ; x0 = dct_const_round_shift(s0 + s4);
337 vqrshrn.s32 d22, q11, #14 ; >> 14
338 vqrshrn.s32 d23, q12, #14 ; >> 14
348 ; x4 = dct_const_round_shift(s0 - s4);
349 vqrshrn.s32 d2, q1, #14 ; >> 14
350 vqrshrn.s32 d3, q2, #14 ; >> 14
352 ; x1 = dct_const_round_shift(s1 + s5);
353 vqrshrn.s32 d24, q12, #14 ; >> 14
354 vqrshrn.s32 d25, q15, #14 ; >> 14
356 ; x5 = dct_const_round_shift(s1 - s5);
357 vqrshrn.s32 d6, q3, #14 ; >> 14
358 vqrshrn.s32 d7, q4, #14 ; >> 14
361 vmull.s16 q4, d26, d0
362 vmull.s16 q5, d27, d0
365 vmull.s16 q2, d26, d1
366 vmull.s16 q6, d27, d1
368 vdup.16 d30, r6 ; duplicate cospi_26_64
369 vdup.16 d31, r7 ; duplicate cospi_6_64
371 ; s2 = cospi_10_64 * x2 + cospi_22_64 * x3;
372 vmlal.s16 q4, d20, d1
373 vmlal.s16 q5, d21, d1
375 ; s3 = cospi_22_64 * x2 - cospi_10_64 * x3;
376 vmlsl.s16 q2, d20, d0
377 vmlsl.s16 q6, d21, d0
380 vmull.s16 q0, d18, d30
381 vmull.s16 q13, d19, d30
383 ; s6 = cospi_26_64 * x6 + cospi_6_64 * x7;
384 vmlal.s16 q0, d28, d31
385 vmlal.s16 q13, d29, d31
388 vmull.s16 q10, d18, d31
389 vmull.s16 q9, d19, d31
391 ; s7 = cospi_6_64 * x6 - cospi_26_64 * x7;
392 vmlsl.s16 q10, d28, d30
393 vmlsl.s16 q9, d29, d30
396 vadd.s32 q14, q2, q10
403 ; x3 = dct_const_round_shift(s3 + s7);
404 vqrshrn.s32 d28, q14, #14 ; >> 14
405 vqrshrn.s32 d29, q15, #14 ; >> 14
407 ; x7 = dct_const_round_shift(s3 - s7);
408 vqrshrn.s32 d4, q2, #14 ; >> 14
409 vqrshrn.s32 d5, q6, #14 ; >> 14
413 vadd.s32 q10, q5, q13
419 vdup.16 d30, r8 ; duplicate cospi_8_64
420 vdup.16 d31, r9 ; duplicate cospi_24_64
422 ; x2 = dct_const_round_shift(s2 + s6);
423 vqrshrn.s32 d18, q9, #14 ; >> 14
424 vqrshrn.s32 d19, q10, #14 ; >> 14
426 ; x6 = dct_const_round_shift(s2 - s6);
427 vqrshrn.s32 d8, q4, #14 ; >> 14
428 vqrshrn.s32 d9, q5, #14 ; >> 14
431 vmull.s16 q5, d2, d30
432 vmull.s16 q6, d3, d30
435 vmull.s16 q7, d2, d31
436 vmull.s16 q0, d3, d31
438 ; s4 = cospi_8_64 * x4 + cospi_24_64 * x5;
439 vmlal.s16 q5, d6, d31
440 vmlal.s16 q6, d7, d31
442 ; s5 = cospi_24_64 * x4 - cospi_8_64 * x5;
443 vmlsl.s16 q7, d6, d30
444 vmlsl.s16 q0, d7, d30
447 vmull.s16 q1, d4, d30
448 vmull.s16 q3, d5, d30
451 vmull.s16 q10, d4, d31
452 vmull.s16 q2, d5, d31
454 ; s6 = -cospi_24_64 * x6 + cospi_8_64 * x7;
455 vmlsl.s16 q1, d8, d31
456 vmlsl.s16 q3, d9, d31
458 ; s7 = cospi_8_64 * x6 + cospi_24_64 * x7;
459 vmlal.s16 q10, d8, d30
460 vmlal.s16 q2, d9, d30
462 vadd.s16 q8, q11, q9 ; x0 = s0 + s2;
464 vsub.s16 q11, q11, q9 ; x2 = s0 - s2;
466 vadd.s16 q4, q12, q14 ; x1 = s1 + s3;
468 vsub.s16 q12, q12, q14 ; x3 = s1 - s3;
478 ; x4 = dct_const_round_shift(s4 + s6);
479 vqrshrn.s32 d18, q14, #14 ; >> 14
480 vqrshrn.s32 d19, q15, #14 ; >> 14
482 ; x6 = dct_const_round_shift(s4 - s6);
483 vqrshrn.s32 d10, q5, #14 ; >> 14
484 vqrshrn.s32 d11, q6, #14 ; >> 14
494 ; x5 = dct_const_round_shift(s5 + s7);
495 vqrshrn.s32 d28, q1, #14 ; >> 14
496 vqrshrn.s32 d29, q3, #14 ; >> 14
498 ; x7 = dct_const_round_shift(s5 - s7);
499 vqrshrn.s32 d14, q7, #14 ; >> 14
500 vqrshrn.s32 d15, q0, #14 ; >> 14
502 vdup.16 d30, r12 ; duplicate cospi_16_64
505 vmull.s16 q2, d22, d30
506 vmull.s16 q3, d23, d30
509 vmull.s16 q13, d22, d30
510 vmull.s16 q1, d23, d30
512 ; cospi_16_64 * x2 + cospi_16_64 * x3;
513 vmlal.s16 q2, d24, d30
514 vmlal.s16 q3, d25, d30
516 ; cospi_16_64 * x2 - cospi_16_64 * x3;
517 vmlsl.s16 q13, d24, d30
518 vmlsl.s16 q1, d25, d30
520 ; x2 = dct_const_round_shift(s2);
521 vqrshrn.s32 d4, q2, #14 ; >> 14
522 vqrshrn.s32 d5, q3, #14 ; >> 14
524 ;x3 = dct_const_round_shift(s3);
525 vqrshrn.s32 d24, q13, #14 ; >> 14
526 vqrshrn.s32 d25, q1, #14 ; >> 14
529 vmull.s16 q13, d10, d30
530 vmull.s16 q1, d11, d30
533 vmull.s16 q11, d10, d30
534 vmull.s16 q0, d11, d30
536 ; cospi_16_64 * x6 + cospi_16_64 * x7;
537 vmlal.s16 q13, d14, d30
538 vmlal.s16 q1, d15, d30
540 ; cospi_16_64 * x6 - cospi_16_64 * x7;
541 vmlsl.s16 q11, d14, d30
542 vmlsl.s16 q0, d15, d30
544 ; x6 = dct_const_round_shift(s6);
545 vqrshrn.s32 d20, q13, #14 ; >> 14
546 vqrshrn.s32 d21, q1, #14 ; >> 14
548 ;x7 = dct_const_round_shift(s7);
549 vqrshrn.s32 d12, q11, #14 ; >> 14
550 vqrshrn.s32 d13, q0, #14 ; >> 14
552 vdup.16 q5, r10 ; duplicate 0
554 vsub.s16 q9, q5, q9 ; output[1] = -x4;
555 vsub.s16 q11, q5, q2 ; output[3] = -x2;
556 vsub.s16 q13, q5, q6 ; output[5] = -x7;
557 vsub.s16 q15, q5, q4 ; output[7] = -x1;
561 AREA Block, CODE, READONLY ; name this block of code
562 ;void vp9_iht8x8_64_add_neon(int16_t *input, uint8_t *dest,
563 ; int dest_stride, int tx_type)
569 ; This function will only handle tx_type of 1,2,3.
570 |vp9_iht8x8_64_add_neon| PROC
572 ; load the inputs into d16-d19
573 vld1.s16 {q8,q9}, [r0]!
574 vld1.s16 {q10,q11}, [r0]!
575 vld1.s16 {q12,q13}, [r0]!
576 vld1.s16 {q14,q15}, [r0]!
580 ; transpose the input data
583 ; decide the type of transform
590 ; generate IDCT constants
591 GENERATE_IDCT_CONSTANTS
593 ; first transform rows
596 ; transpose the matrix
599 ; generate IADST constants
600 GENERATE_IADST_CONSTANTS
602 ; then transform columns
605 b end_vp9_iht8x8_64_add_neon
608 ; generate IADST constants
609 GENERATE_IADST_CONSTANTS
611 ; first transform rows
614 ; transpose the matrix
617 ; generate IDCT constants
618 GENERATE_IDCT_CONSTANTS
620 ; then transform columns
623 b end_vp9_iht8x8_64_add_neon
626 ; generate IADST constants
627 GENERATE_IADST_CONSTANTS
629 ; first transform rows
632 ; transpose the matrix
635 ; then transform columns
638 end_vp9_iht8x8_64_add_neon
641 ; ROUND_POWER_OF_TWO(temp_out[j], 5)
644 vrshr.s16 q10, q10, #5
645 vrshr.s16 q11, q11, #5
646 vrshr.s16 q12, q12, #5
647 vrshr.s16 q13, q13, #5
648 vrshr.s16 q14, q14, #5
649 vrshr.s16 q15, q15, #5
654 ; load destination data
655 vld1.64 {d0}, [r1], r2
656 vld1.64 {d1}, [r1], r2
657 vld1.64 {d2}, [r1], r2
658 vld1.64 {d3}, [r1], r2
659 vld1.64 {d4}, [r1], r2
660 vld1.64 {d5}, [r1], r2
661 vld1.64 {d6}, [r1], r2
664 ; ROUND_POWER_OF_TWO(temp_out[j], 5) + dest[j * dest_stride + i]
667 vaddw.u8 q10, q10, d2
668 vaddw.u8 q11, q11, d3
669 vaddw.u8 q12, q12, d4
670 vaddw.u8 q13, q13, d5
671 vaddw.u8 q14, q14, d6
672 vaddw.u8 q15, q15, d7
685 vst1.64 {d0}, [r0], r2
686 vst1.64 {d1}, [r0], r2
687 vst1.64 {d2}, [r0], r2
688 vst1.64 {d3}, [r0], r2
689 vst1.64 {d4}, [r0], r2
690 vst1.64 {d5}, [r0], r2
691 vst1.64 {d6}, [r0], r2
692 vst1.64 {d7}, [r0], r2
694 ENDP ; |vp9_iht8x8_64_add_neon|