2 ; Copyright (c) 2010 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.
12 EXPORT |idct_dequant_full_2x_neon|
17 AREA ||.text||, CODE, READONLY, ALIGN=2
18 ;void idct_dequant_full_2x_neon(short *q, short *dq,
19 ; unsigned char *dst, int stride);
24 |idct_dequant_full_2x_neon| PROC
25 vld1.16 {q0, q1}, [r1] ; dq (same l/r)
26 vld1.16 {q2, q3}, [r0] ; l q
28 vld1.16 {q4, q5}, [r0] ; r q
31 ; interleave the predictors
32 vld1.32 {d28[0]}, [r2], r3 ; l pre
33 vld1.32 {d28[1]}, [r12], r3 ; r pre
34 vld1.32 {d29[0]}, [r2], r3
35 vld1.32 {d29[1]}, [r12], r3
36 vld1.32 {d30[0]}, [r2], r3
37 vld1.32 {d30[1]}, [r12], r3
38 vld1.32 {d31[0]}, [r2], r3
39 vld1.32 {d31[1]}, [r12]
41 adr r1, cospi8sqrt2minus1 ; pointer to the first constant
43 ; dequant: q[i] = q[i] * dq[i]
56 ; _CONSTANTS_ * 4,12 >> 16
57 ; q6: 4 * sinpi : c1/temp1
58 ; q7: 12 * sinpi : d1/temp2
61 vqdmulh.s16 q6, q4, d0[2] ; sinpi8sqrt2
62 vqdmulh.s16 q7, q5, d0[2]
63 vqdmulh.s16 q8, q4, d0[0] ; cospi8sqrt2minus1
64 vqdmulh.s16 q9, q5, d0[0]
66 vqadd.s16 q10, q2, q3 ; a1 = 0 + 8
67 vqsub.s16 q11, q2, q3 ; b1 = 0 - 8
69 ; vqdmulh only accepts signed values. this was a problem because
70 ; our constant had the high bit set, and was treated as a negative value.
71 ; vqdmulh also doubles the value before it shifts by 16. we need to
72 ; compensate for this. in the case of sinpi8sqrt2, the lowest bit is 0,
73 ; so we can shift the constant without losing precision. this avoids
74 ; shift again afterward, but also avoids the sign issue. win win!
75 ; for cospi8sqrt2minus1 the lowest bit is 1, so we lose precision if we
80 ; q4: 4 + 4 * cospi : d1/temp1
81 ; q5: 12 + 12 * cospi : c1/temp2
105 ; q4: l 0, 4, 8,12 r 0, 4, 8,12
106 ; q5: l 1, 5, 9,13 r 1, 5, 9,13
107 ; q6: l 2, 6,10,14 r 2, 6,10,14
108 ; q7: l 3, 7,11,15 r 3, 7,11,15
110 ; q8: 1 * sinpi : c1/temp1
111 ; q9: 3 * sinpi : d1/temp2
114 vqdmulh.s16 q8, q5, d0[2] ; sinpi8sqrt2
115 vqdmulh.s16 q9, q7, d0[2]
116 vqdmulh.s16 q10, q5, d0[0] ; cospi8sqrt2minus1
117 vqdmulh.s16 q11, q7, d0[0]
119 vqadd.s16 q2, q4, q6 ; a1 = 0 + 2
120 vqsub.s16 q3, q4, q6 ; b1 = 0 - 2
122 ; see note on shifting above
123 vshr.s16 q10, q10, #1
124 vshr.s16 q11, q11, #1
126 ; q10: 1 + 1 * cospi : d1/temp1
127 ; q11: 3 + 3 * cospi : c1/temp2
128 vqadd.s16 q10, q5, q10
129 vqadd.s16 q11, q7, q11
131 ; q8: c1 = temp1 - temp2
132 ; q9: d1 = temp1 + temp2
133 vqsub.s16 q8, q8, q11
134 vqadd.s16 q9, q10, q9
146 vrshr.s16 q4, q4, #3 ; lo
148 vrshr.s16 q6, q6, #3 ; hi
157 ; input is still packed. pre was read interleaved
165 vst1.16 {q14, q15}, [r0] ; write over high input
167 vst1.16 {q14, q15}, [r0] ; write over low input
169 sub r2, r2, r3, lsl #2 ; dst - 4*stride
173 vqmovun.s16 d0, q4 ; lo
175 vqmovun.s16 d2, q6 ; hi
178 vst1.32 {d0[0]}, [r2], r3 ; lo
179 vst1.32 {d0[1]}, [r1], r3 ; hi
180 vst1.32 {d1[0]}, [r2], r3
181 vst1.32 {d1[1]}, [r1], r3
182 vst1.32 {d2[0]}, [r2], r3
183 vst1.32 {d2[1]}, [r1], r3
184 vst1.32 {d3[0]}, [r2]
185 vst1.32 {d3[1]}, [r1]
189 ENDP ; |idct_dequant_full_2x_neon|
192 cospi8sqrt2minus1 DCD 0x4e7b
193 ; because the lowest bit in 0x8a8c is 0, we can pre-shift this
194 sinpi8sqrt2 DCD 0x4546