1;
2;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
3;
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.
9;
10
11
12    EXPORT  |vp8_fast_quantize_b_neon|
13    EXPORT  |vp8_fast_quantize_b_pair_neon|
14
15    INCLUDE vp8_asm_enc_offsets.asm
16
17    ARM
18    REQUIRE8
19    PRESERVE8
20
21    AREA ||.text||, CODE, READONLY, ALIGN=4
22
23;vp8_fast_quantize_b_pair_neon(BLOCK *b1, BLOCK *b2, BLOCKD *d1, BLOCKD *d2);
24|vp8_fast_quantize_b_pair_neon| PROC
25
26    stmfd           sp!, {r4-r9}
27    vstmdb          sp!, {q4-q7}
28
29    ldr             r4, [r0, #vp8_block_coeff]
30    ldr             r5, [r0, #vp8_block_quant_fast]
31    ldr             r6, [r0, #vp8_block_round]
32
33    vld1.16         {q0, q1}, [r4@128]  ; load z
34
35    ldr             r7, [r2, #vp8_blockd_qcoeff]
36
37    vabs.s16        q4, q0              ; calculate x = abs(z)
38    vabs.s16        q5, q1
39
40    ;right shift 15 to get sign, all 0 if it is positive, all 1 if it is negative
41    vshr.s16        q2, q0, #15         ; sz
42    vshr.s16        q3, q1, #15
43
44    vld1.s16        {q6, q7}, [r6@128]  ; load round_ptr [0-15]
45    vld1.s16        {q8, q9}, [r5@128]  ; load quant_ptr [0-15]
46
47    ldr             r4, [r1, #vp8_block_coeff]
48
49    vadd.s16        q4, q6              ; x + Round
50    vadd.s16        q5, q7
51
52    vld1.16         {q0, q1}, [r4@128]  ; load z2
53
54    vqdmulh.s16     q4, q8              ; y = ((Round+abs(z)) * Quant) >> 16
55    vqdmulh.s16     q5, q9
56
57    vabs.s16        q10, q0             ; calculate x2 = abs(z_2)
58    vabs.s16        q11, q1
59    vshr.s16        q12, q0, #15        ; sz2
60    vshr.s16        q13, q1, #15
61
62    ;modify data to have its original sign
63    veor.s16        q4, q2              ; y^sz
64    veor.s16        q5, q3
65
66    vadd.s16        q10, q6             ; x2 + Round
67    vadd.s16        q11, q7
68
69    ldr             r8, [r2, #vp8_blockd_dequant]
70
71    vqdmulh.s16     q10, q8             ; y2 = ((Round+abs(z)) * Quant) >> 16
72    vqdmulh.s16     q11, q9
73
74    vshr.s16        q4, #1              ; right shift 1 after vqdmulh
75    vshr.s16        q5, #1
76
77    vld1.s16        {q6, q7}, [r8@128]  ;load dequant_ptr[i]
78
79    vsub.s16        q4, q2              ; x1=(y^sz)-sz = (y^sz)-(-1) (2's complement)
80    vsub.s16        q5, q3
81
82    vshr.s16        q10, #1             ; right shift 1 after vqdmulh
83    vshr.s16        q11, #1
84
85    ldr             r9, [r2, #vp8_blockd_dqcoeff]
86
87    veor.s16        q10, q12            ; y2^sz2
88    veor.s16        q11, q13
89
90    vst1.s16        {q4, q5}, [r7]      ; store: qcoeff = x1
91
92
93    vsub.s16        q10, q12            ; x2=(y^sz)-sz = (y^sz)-(-1) (2's complement)
94    vsub.s16        q11, q13
95
96    ldr             r6, [r3, #vp8_blockd_qcoeff]
97
98    vmul.s16        q2, q6, q4          ; x * Dequant
99    vmul.s16        q3, q7, q5
100
101    adr             r0, inv_zig_zag     ; load ptr of inverse zigzag table
102
103    vceq.s16        q8, q8              ; set q8 to all 1
104
105    vst1.s16        {q10, q11}, [r6]    ; store: qcoeff = x2
106
107    vmul.s16        q12, q6, q10        ; x2 * Dequant
108    vmul.s16        q13, q7, q11
109
110    vld1.16         {q6, q7}, [r0@128]  ; load inverse scan order
111
112    vtst.16         q14, q4, q8         ; now find eob
113    vtst.16         q15, q5, q8         ; non-zero element is set to all 1
114
115    vst1.s16        {q2, q3}, [r9]      ; store dqcoeff = x * Dequant
116
117    ldr             r7, [r3, #vp8_blockd_dqcoeff]
118
119    vand            q0, q6, q14         ; get all valid numbers from scan array
120    vand            q1, q7, q15
121
122    vst1.s16        {q12, q13}, [r7]    ; store dqcoeff = x * Dequant
123
124    vtst.16         q2, q10, q8         ; now find eob
125    vtst.16         q3, q11, q8         ; non-zero element is set to all 1
126
127    vmax.u16        q0, q0, q1          ; find maximum value in q0, q1
128
129    vand            q10, q6, q2         ; get all valid numbers from scan array
130    vand            q11, q7, q3
131    vmax.u16        q10, q10, q11       ; find maximum value in q10, q11
132
133    vmax.u16        d0, d0, d1
134    vmax.u16        d20, d20, d21
135    vmovl.u16       q0, d0
136    vmovl.u16       q10, d20
137
138    vmax.u32        d0, d0, d1
139    vmax.u32        d20, d20, d21
140    vpmax.u32       d0, d0, d0
141    vpmax.u32       d20, d20, d20
142
143    ldr             r4, [r2, #vp8_blockd_eob]
144    ldr             r5, [r3, #vp8_blockd_eob]
145
146    vst1.8          {d0[0]}, [r4]       ; store eob
147    vst1.8          {d20[0]}, [r5]      ; store eob
148
149    vldmia          sp!, {q4-q7}
150    ldmfd           sp!, {r4-r9}
151    bx              lr
152
153    ENDP
154
155;void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d)
156|vp8_fast_quantize_b_neon| PROC
157
158    stmfd           sp!, {r4-r7}
159
160    ldr             r3, [r0, #vp8_block_coeff]
161    ldr             r4, [r0, #vp8_block_quant_fast]
162    ldr             r5, [r0, #vp8_block_round]
163
164    vld1.16         {q0, q1}, [r3@128]  ; load z
165    vorr.s16        q14, q0, q1         ; check if all zero (step 1)
166    ldr             r6, [r1, #vp8_blockd_qcoeff]
167    ldr             r7, [r1, #vp8_blockd_dqcoeff]
168    vorr.s16        d28, d28, d29       ; check if all zero (step 2)
169
170    vabs.s16        q12, q0             ; calculate x = abs(z)
171    vabs.s16        q13, q1
172
173    ;right shift 15 to get sign, all 0 if it is positive, all 1 if it is negative
174    vshr.s16        q2, q0, #15         ; sz
175    vmov            r2, r3, d28         ; check if all zero (step 3)
176    vshr.s16        q3, q1, #15
177
178    vld1.s16        {q14, q15}, [r5@128]; load round_ptr [0-15]
179    vld1.s16        {q8, q9}, [r4@128]  ; load quant_ptr [0-15]
180
181    vadd.s16        q12, q14            ; x + Round
182    vadd.s16        q13, q15
183
184    adr             r0, inv_zig_zag     ; load ptr of inverse zigzag table
185
186    vqdmulh.s16     q12, q8             ; y = ((Round+abs(z)) * Quant) >> 16
187    vqdmulh.s16     q13, q9
188
189    vld1.16         {q10, q11}, [r0@128]; load inverse scan order
190
191    vceq.s16        q8, q8              ; set q8 to all 1
192
193    ldr             r4, [r1, #vp8_blockd_dequant]
194
195    vshr.s16        q12, #1             ; right shift 1 after vqdmulh
196    vshr.s16        q13, #1
197
198    ldr             r5, [r1, #vp8_blockd_eob]
199
200    orr             r2, r2, r3          ; check if all zero (step 4)
201    cmp             r2, #0              ; check if all zero (step 5)
202    beq             zero_output         ; check if all zero (step 6)
203
204    ;modify data to have its original sign
205    veor.s16        q12, q2             ; y^sz
206    veor.s16        q13, q3
207
208    vsub.s16        q12, q2             ; x1=(y^sz)-sz = (y^sz)-(-1) (2's complement)
209    vsub.s16        q13, q3
210
211    vld1.s16        {q2, q3}, [r4@128]  ; load dequant_ptr[i]
212
213    vtst.16         q14, q12, q8        ; now find eob
214    vtst.16         q15, q13, q8        ; non-zero element is set to all 1
215
216    vst1.s16        {q12, q13}, [r6@128]; store: qcoeff = x1
217
218    vand            q10, q10, q14       ; get all valid numbers from scan array
219    vand            q11, q11, q15
220
221
222    vmax.u16        q0, q10, q11        ; find maximum value in q0, q1
223    vmax.u16        d0, d0, d1
224    vmovl.u16       q0, d0
225
226    vmul.s16        q2, q12             ; x * Dequant
227    vmul.s16        q3, q13
228
229    vmax.u32        d0, d0, d1
230    vpmax.u32       d0, d0, d0
231
232    vst1.s16        {q2, q3}, [r7@128]  ; store dqcoeff = x * Dequant
233
234    vst1.8          {d0[0]}, [r5]       ; store eob
235
236    ldmfd           sp!, {r4-r7}
237    bx              lr
238
239zero_output
240    strb            r2, [r5]            ; store eob
241    vst1.s16        {q0, q1}, [r6@128]  ; qcoeff = 0
242    vst1.s16        {q0, q1}, [r7@128]  ; dqcoeff = 0
243
244    ldmfd           sp!, {r4-r7}
245    bx              lr
246
247    ENDP
248
249; default inverse zigzag table is defined in vp8/common/entropy.c
250    ALIGN 16    ; enable use of @128 bit aligned loads
251inv_zig_zag
252    DCW 0x0001, 0x0002, 0x0006, 0x0007
253    DCW 0x0003, 0x0005, 0x0008, 0x000d
254    DCW 0x0004, 0x0009, 0x000c, 0x000e
255    DCW 0x000a, 0x000b, 0x000f, 0x0010
256
257    END
258
259