1;
2;  Copyright (c) 2013 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    EXPORT  |vpx_idct16x16_256_add_neon_pass1|
12    EXPORT  |vpx_idct16x16_256_add_neon_pass2|
13    EXPORT  |vpx_idct16x16_10_add_neon_pass1|
14    EXPORT  |vpx_idct16x16_10_add_neon_pass2|
15    ARM
16    REQUIRE8
17    PRESERVE8
18
19    AREA ||.text||, CODE, READONLY, ALIGN=2
20
21    ; Transpose a 8x8 16bit data matrix. Datas are loaded in q8-q15.
22    MACRO
23    TRANSPOSE8X8
24    vswp            d17, d24
25    vswp            d23, d30
26    vswp            d21, d28
27    vswp            d19, d26
28    vtrn.32         q8, q10
29    vtrn.32         q9, q11
30    vtrn.32         q12, q14
31    vtrn.32         q13, q15
32    vtrn.16         q8, q9
33    vtrn.16         q10, q11
34    vtrn.16         q12, q13
35    vtrn.16         q14, q15
36    MEND
37
38    AREA    Block, CODE, READONLY ; name this block of code
39;void |vpx_idct16x16_256_add_neon_pass1|(int16_t *input,
40;                                          int16_t *output, int output_stride)
41;
42; r0  int16_t input
43; r1  int16_t *output
44; r2  int  output_stride)
45
46; idct16 stage1 - stage6 on all the elements loaded in q8-q15. The output
47; will be stored back into q8-q15 registers. This function will touch q0-q7
48; registers and use them as buffer during calculation.
49|vpx_idct16x16_256_add_neon_pass1| PROC
50
51    ; TODO(hkuang): Find a better way to load the elements.
52    ; load elements of 0, 2, 4, 6, 8, 10, 12, 14 into q8 - q15
53    vld2.s16        {q8,q9}, [r0]!
54    vld2.s16        {q9,q10}, [r0]!
55    vld2.s16        {q10,q11}, [r0]!
56    vld2.s16        {q11,q12}, [r0]!
57    vld2.s16        {q12,q13}, [r0]!
58    vld2.s16        {q13,q14}, [r0]!
59    vld2.s16        {q14,q15}, [r0]!
60    vld2.s16        {q1,q2}, [r0]!
61    vmov.s16        q15, q1
62
63    ; generate  cospi_28_64 = 3196
64    mov             r3, #0xc00
65    add             r3, #0x7c
66
67    ; generate cospi_4_64  = 16069
68    mov             r12, #0x3e00
69    add             r12, #0xc5
70
71    ; transpose the input data
72    TRANSPOSE8X8
73
74    ; stage 3
75    vdup.16         d0, r3                    ; duplicate cospi_28_64
76    vdup.16         d1, r12                   ; duplicate cospi_4_64
77
78    ; preloading to avoid stall
79    ; generate cospi_12_64 = 13623
80    mov             r3, #0x3500
81    add             r3, #0x37
82
83    ; generate cospi_20_64 = 9102
84    mov             r12, #0x2300
85    add             r12, #0x8e
86
87    ; step2[4] * cospi_28_64
88    vmull.s16       q2, d18, d0
89    vmull.s16       q3, d19, d0
90
91    ; step2[4] * cospi_4_64
92    vmull.s16       q5, d18, d1
93    vmull.s16       q6, d19, d1
94
95    ; temp1 = step2[4] * cospi_28_64 - step2[7] * cospi_4_64
96    vmlsl.s16       q2, d30, d1
97    vmlsl.s16       q3, d31, d1
98
99    ; temp2 = step2[4] * cospi_4_64 + step2[7] * cospi_28_64
100    vmlal.s16       q5, d30, d0
101    vmlal.s16       q6, d31, d0
102
103    vdup.16         d2, r3                    ; duplicate cospi_12_64
104    vdup.16         d3, r12                   ; duplicate cospi_20_64
105
106    ; dct_const_round_shift(temp1)
107    vqrshrn.s32     d8, q2, #14               ; >> 14
108    vqrshrn.s32     d9, q3, #14               ; >> 14
109
110    ; dct_const_round_shift(temp2)
111    vqrshrn.s32     d14, q5, #14              ; >> 14
112    vqrshrn.s32     d15, q6, #14              ; >> 14
113
114    ; preloading to avoid stall
115    ; generate cospi_16_64 = 11585
116    mov             r3, #0x2d00
117    add             r3, #0x41
118
119    ; generate cospi_24_64 = 6270
120    mov             r12, #0x1800
121    add             r12, #0x7e
122
123    ; step2[5] * cospi_12_64
124    vmull.s16       q2, d26, d2
125    vmull.s16       q3, d27, d2
126
127    ; step2[5] * cospi_20_64
128    vmull.s16       q9, d26, d3
129    vmull.s16       q15, d27, d3
130
131    ; temp1 = input[5] * cospi_12_64 - input[3] * cospi_20_64
132    vmlsl.s16       q2, d22, d3
133    vmlsl.s16       q3, d23, d3
134
135    ; temp2 = step2[5] * cospi_20_64 + step2[6] * cospi_12_64
136    vmlal.s16       q9, d22, d2
137    vmlal.s16       q15, d23, d2
138
139    ; dct_const_round_shift(temp1)
140    vqrshrn.s32     d10, q2, #14              ; >> 14
141    vqrshrn.s32     d11, q3, #14              ; >> 14
142
143    ; dct_const_round_shift(temp2)
144    vqrshrn.s32     d12, q9, #14              ; >> 14
145    vqrshrn.s32     d13, q15, #14             ; >> 14
146
147    ; stage 4
148    vdup.16         d30, r3                   ; cospi_16_64
149
150    ; step1[0] * cospi_16_64
151    vmull.s16       q2, d16, d30
152    vmull.s16       q11, d17, d30
153
154    ; step1[1] * cospi_16_64
155    vmull.s16       q0, d24, d30
156    vmull.s16       q1, d25, d30
157
158    ; generate cospi_8_64 = 15137
159    mov             r3, #0x3b00
160    add             r3, #0x21
161
162    vdup.16         d30, r12                  ; duplicate cospi_24_64
163    vdup.16         d31, r3                   ; duplicate cospi_8_64
164
165    ; temp1 = (step1[0] + step1[1]) * cospi_16_64
166    vadd.s32        q3, q2, q0
167    vadd.s32        q12, q11, q1
168
169    ; temp2 = (step1[0] - step1[1]) * cospi_16_64
170    vsub.s32        q13, q2, q0
171    vsub.s32        q1, q11, q1
172
173    ; dct_const_round_shift(temp1)
174    vqrshrn.s32     d16, q3, #14              ; >> 14
175    vqrshrn.s32     d17, q12, #14             ; >> 14
176
177    ; dct_const_round_shift(temp2)
178    vqrshrn.s32     d18, q13, #14             ; >> 14
179    vqrshrn.s32     d19, q1, #14              ; >> 14
180
181    ; step1[2] * cospi_24_64 - step1[3] * cospi_8_64;
182    ; step1[2] * cospi_8_64
183    vmull.s16       q0, d20, d31
184    vmull.s16       q1, d21, d31
185
186    ; step1[2] * cospi_24_64
187    vmull.s16       q12, d20, d30
188    vmull.s16       q13, d21, d30
189
190    ; temp2 = input[1] * cospi_8_64 + input[3] * cospi_24_64
191    vmlal.s16       q0, d28, d30
192    vmlal.s16       q1, d29, d30
193
194    ; temp1 = input[1] * cospi_24_64 - input[3] * cospi_8_64
195    vmlsl.s16       q12, d28, d31
196    vmlsl.s16       q13, d29, d31
197
198    ; dct_const_round_shift(temp2)
199    vqrshrn.s32     d22, q0, #14              ; >> 14
200    vqrshrn.s32     d23, q1, #14              ; >> 14
201
202    ; dct_const_round_shift(temp1)
203    vqrshrn.s32     d20, q12, #14             ; >> 14
204    vqrshrn.s32     d21, q13, #14             ; >> 14
205
206    vsub.s16        q13, q4, q5               ; step2[5] = step1[4] - step1[5];
207    vadd.s16        q4, q4, q5                ; step2[4] = step1[4] + step1[5];
208    vsub.s16        q14, q7, q6               ; step2[6] = -step1[6] + step1[7];
209    vadd.s16        q15, q6, q7               ; step2[7] = step1[6] + step1[7];
210
211    ; generate cospi_16_64 = 11585
212    mov             r3, #0x2d00
213    add             r3, #0x41
214
215    ; stage 5
216    vadd.s16        q0, q8, q11               ; step1[0] = step2[0] + step2[3];
217    vadd.s16        q1, q9, q10               ; step1[1] = step2[1] + step2[2];
218    vsub.s16        q2, q9, q10               ; step1[2] = step2[1] - step2[2];
219    vsub.s16        q3, q8, q11               ; step1[3] = step2[0] - step2[3];
220
221    vdup.16         d16, r3;                  ; duplicate cospi_16_64
222
223    ; step2[5] * cospi_16_64
224    vmull.s16       q11, d26, d16
225    vmull.s16       q12, d27, d16
226
227    ; step2[6] * cospi_16_64
228    vmull.s16       q9, d28, d16
229    vmull.s16       q10, d29, d16
230
231    ; temp1 = (step2[6] - step2[5]) * cospi_16_64
232    vsub.s32        q6, q9, q11
233    vsub.s32        q13, q10, q12
234
235    ; temp2 = (step2[5] + step2[6]) * cospi_16_64
236    vadd.s32        q9, q9, q11
237    vadd.s32        q10, q10, q12
238
239    ; dct_const_round_shift(temp1)
240    vqrshrn.s32     d10, q6, #14              ; >> 14
241    vqrshrn.s32     d11, q13, #14             ; >> 14
242
243    ; dct_const_round_shift(temp2)
244    vqrshrn.s32     d12, q9, #14              ; >> 14
245    vqrshrn.s32     d13, q10, #14             ; >> 14
246
247    ; stage 6
248    vadd.s16        q8, q0, q15                ; step2[0] = step1[0] + step1[7];
249    vadd.s16        q9, q1, q6                ; step2[1] = step1[1] + step1[6];
250    vadd.s16        q10, q2, q5               ; step2[2] = step1[2] + step1[5];
251    vadd.s16        q11, q3, q4               ; step2[3] = step1[3] + step1[4];
252    vsub.s16        q12, q3, q4               ; step2[4] = step1[3] - step1[4];
253    vsub.s16        q13, q2, q5               ; step2[5] = step1[2] - step1[5];
254    vsub.s16        q14, q1, q6               ; step2[6] = step1[1] - step1[6];
255    vsub.s16        q15, q0, q15              ; step2[7] = step1[0] - step1[7];
256
257    ; store the data
258    vst1.64         {d16}, [r1], r2
259    vst1.64         {d17}, [r1], r2
260    vst1.64         {d18}, [r1], r2
261    vst1.64         {d19}, [r1], r2
262    vst1.64         {d20}, [r1], r2
263    vst1.64         {d21}, [r1], r2
264    vst1.64         {d22}, [r1], r2
265    vst1.64         {d23}, [r1], r2
266    vst1.64         {d24}, [r1], r2
267    vst1.64         {d25}, [r1], r2
268    vst1.64         {d26}, [r1], r2
269    vst1.64         {d27}, [r1], r2
270    vst1.64         {d28}, [r1], r2
271    vst1.64         {d29}, [r1], r2
272    vst1.64         {d30}, [r1], r2
273    vst1.64         {d31}, [r1], r2
274
275    bx              lr
276    ENDP  ; |vpx_idct16x16_256_add_neon_pass1|
277
278;void vpx_idct16x16_256_add_neon_pass2(int16_t *src,
279;                                        int16_t *output,
280;                                        int16_t *pass1Output,
281;                                        int16_t skip_adding,
282;                                        uint8_t *dest,
283;                                        int dest_stride)
284;
285; r0  int16_t *src
286; r1  int16_t *output,
287; r2  int16_t *pass1Output,
288; r3  int16_t skip_adding,
289; r4  uint8_t *dest,
290; r5  int dest_stride)
291
292; idct16 stage1 - stage7 on all the elements loaded in q8-q15. The output
293; will be stored back into q8-q15 registers. This function will touch q0-q7
294; registers and use them as buffer during calculation.
295|vpx_idct16x16_256_add_neon_pass2| PROC
296    push            {r3-r9}
297
298    ; TODO(hkuang): Find a better way to load the elements.
299    ; load elements of 1, 3, 5, 7, 9, 11, 13, 15 into q8 - q15
300    vld2.s16        {q8,q9}, [r0]!
301    vld2.s16        {q9,q10}, [r0]!
302    vld2.s16        {q10,q11}, [r0]!
303    vld2.s16        {q11,q12}, [r0]!
304    vld2.s16        {q12,q13}, [r0]!
305    vld2.s16        {q13,q14}, [r0]!
306    vld2.s16        {q14,q15}, [r0]!
307    vld2.s16        {q0,q1}, [r0]!
308    vmov.s16        q15, q0;
309
310    ; generate  cospi_30_64 = 1606
311    mov             r3, #0x0600
312    add             r3, #0x46
313
314    ; generate cospi_2_64  = 16305
315    mov             r12, #0x3f00
316    add             r12, #0xb1
317
318    ; transpose the input data
319    TRANSPOSE8X8
320
321    ; stage 3
322    vdup.16         d12, r3                   ; duplicate cospi_30_64
323    vdup.16         d13, r12                  ; duplicate cospi_2_64
324
325    ; preloading to avoid stall
326    ; generate cospi_14_64 = 12665
327    mov             r3, #0x3100
328    add             r3, #0x79
329
330    ; generate cospi_18_64 = 10394
331    mov             r12, #0x2800
332    add             r12, #0x9a
333
334    ; step1[8] * cospi_30_64
335    vmull.s16       q2, d16, d12
336    vmull.s16       q3, d17, d12
337
338    ; step1[8] * cospi_2_64
339    vmull.s16       q1, d16, d13
340    vmull.s16       q4, d17, d13
341
342    ; temp1 = step1[8] * cospi_30_64 - step1[15] * cospi_2_64
343    vmlsl.s16       q2, d30, d13
344    vmlsl.s16       q3, d31, d13
345
346    ; temp2 = step1[8] * cospi_2_64 + step1[15] * cospi_30_64
347    vmlal.s16       q1, d30, d12
348    vmlal.s16       q4, d31, d12
349
350    vdup.16         d30, r3                   ; duplicate cospi_14_64
351    vdup.16         d31, r12                  ; duplicate cospi_18_64
352
353    ; dct_const_round_shift(temp1)
354    vqrshrn.s32     d0, q2, #14               ; >> 14
355    vqrshrn.s32     d1, q3, #14               ; >> 14
356
357    ; dct_const_round_shift(temp2)
358    vqrshrn.s32     d14, q1, #14              ; >> 14
359    vqrshrn.s32     d15, q4, #14              ; >> 14
360
361    ; preloading to avoid stall
362    ; generate cospi_22_64 = 7723
363    mov             r3, #0x1e00
364    add             r3, #0x2b
365
366    ; generate cospi_10_64 = 14449
367    mov             r12, #0x3800
368    add             r12, #0x71
369
370    ; step1[9] * cospi_14_64
371    vmull.s16       q2, d24, d30
372    vmull.s16       q3, d25, d30
373
374    ; step1[9] * cospi_18_64
375    vmull.s16       q4, d24, d31
376    vmull.s16       q5, d25, d31
377
378    ; temp1 = step1[9] * cospi_14_64 - step1[14] * cospi_18_64
379    vmlsl.s16       q2, d22, d31
380    vmlsl.s16       q3, d23, d31
381
382    ; temp2 = step1[9] * cospi_18_64 + step1[14] * cospi_14_64
383    vmlal.s16       q4, d22, d30
384    vmlal.s16       q5, d23, d30
385
386    vdup.16         d30, r3                   ; duplicate cospi_22_64
387    vdup.16         d31, r12                  ; duplicate cospi_10_64
388
389    ; dct_const_round_shift(temp1)
390    vqrshrn.s32     d2, q2, #14               ; >> 14
391    vqrshrn.s32     d3, q3, #14               ; >> 14
392
393    ; dct_const_round_shift(temp2)
394    vqrshrn.s32     d12, q4, #14              ; >> 14
395    vqrshrn.s32     d13, q5, #14              ; >> 14
396
397    ; step1[10] * cospi_22_64
398    vmull.s16       q11, d20, d30
399    vmull.s16       q12, d21, d30
400
401    ; step1[10] * cospi_10_64
402    vmull.s16       q4, d20, d31
403    vmull.s16       q5, d21, d31
404
405    ; temp1 = step1[10] * cospi_22_64 - step1[13] * cospi_10_64
406    vmlsl.s16       q11, d26, d31
407    vmlsl.s16       q12, d27, d31
408
409    ; temp2 = step1[10] * cospi_10_64 + step1[13] * cospi_22_64
410    vmlal.s16       q4, d26, d30
411    vmlal.s16       q5, d27, d30
412
413    ; preloading to avoid stall
414    ; generate cospi_6_64 = 15679
415    mov             r3, #0x3d00
416    add             r3, #0x3f
417
418    ; generate cospi_26_64 = 4756
419    mov             r12, #0x1200
420    add             r12, #0x94
421
422    vdup.16         d30, r3                   ; duplicate cospi_6_64
423    vdup.16         d31, r12                  ; duplicate cospi_26_64
424
425    ; dct_const_round_shift(temp1)
426    vqrshrn.s32     d4, q11, #14              ; >> 14
427    vqrshrn.s32     d5, q12, #14              ; >> 14
428
429    ; dct_const_round_shift(temp2)
430    vqrshrn.s32     d11, q5, #14              ; >> 14
431    vqrshrn.s32     d10, q4, #14              ; >> 14
432
433    ; step1[11] * cospi_6_64
434    vmull.s16       q10, d28, d30
435    vmull.s16       q11, d29, d30
436
437    ; step1[11] * cospi_26_64
438    vmull.s16       q12, d28, d31
439    vmull.s16       q13, d29, d31
440
441    ; temp1 = step1[11] * cospi_6_64 - step1[12] * cospi_26_64
442    vmlsl.s16       q10, d18, d31
443    vmlsl.s16       q11, d19, d31
444
445    ; temp2 = step1[11] * cospi_26_64 + step1[12] * cospi_6_64
446    vmlal.s16       q12, d18, d30
447    vmlal.s16       q13, d19, d30
448
449    vsub.s16        q9, q0, q1                ; step1[9]=step2[8]-step2[9]
450    vadd.s16        q0, q0, q1                ; step1[8]=step2[8]+step2[9]
451
452    ; dct_const_round_shift(temp1)
453    vqrshrn.s32     d6, q10, #14              ; >> 14
454    vqrshrn.s32     d7, q11, #14              ; >> 14
455
456    ; dct_const_round_shift(temp2)
457    vqrshrn.s32     d8, q12, #14              ; >> 14
458    vqrshrn.s32     d9, q13, #14              ; >> 14
459
460    ; stage 3
461    vsub.s16        q10, q3, q2               ; step1[10]=-step2[10]+step2[11]
462    vadd.s16        q11, q2, q3               ; step1[11]=step2[10]+step2[11]
463    vadd.s16        q12, q4, q5               ; step1[12]=step2[12]+step2[13]
464    vsub.s16        q13, q4, q5               ; step1[13]=step2[12]-step2[13]
465    vsub.s16        q14, q7, q6               ; step1[14]=-step2[14]+tep2[15]
466    vadd.s16        q7, q6, q7                ; step1[15]=step2[14]+step2[15]
467
468    ; stage 4
469    ; generate cospi_24_64 = 6270
470    mov             r3, #0x1800
471    add             r3, #0x7e
472
473    ; generate cospi_8_64 = 15137
474    mov             r12, #0x3b00
475    add             r12, #0x21
476
477    ; -step1[9] * cospi_8_64 + step1[14] * cospi_24_64
478    vdup.16         d30, r12                  ; duplicate cospi_8_64
479    vdup.16         d31, r3                   ; duplicate cospi_24_64
480
481    ; step1[9] * cospi_24_64
482    vmull.s16       q2, d18, d31
483    vmull.s16       q3, d19, d31
484
485    ; step1[14] * cospi_24_64
486    vmull.s16       q4, d28, d31
487    vmull.s16       q5, d29, d31
488
489    ; temp2 = step1[9] * cospi_24_64 + step1[14] * cospi_8_64
490    vmlal.s16       q2, d28, d30
491    vmlal.s16       q3, d29, d30
492
493    ; temp1 = -step1[9] * cospi_8_64 + step1[14] * cospi_24_64
494    vmlsl.s16       q4, d18, d30
495    vmlsl.s16       q5, d19, d30
496
497    rsb             r12, #0
498    vdup.16         d30, r12                  ; duplicate -cospi_8_64
499
500    ; dct_const_round_shift(temp2)
501    vqrshrn.s32     d12, q2, #14              ; >> 14
502    vqrshrn.s32     d13, q3, #14              ; >> 14
503
504    ; dct_const_round_shift(temp1)
505    vqrshrn.s32     d2, q4, #14               ; >> 14
506    vqrshrn.s32     d3, q5, #14               ; >> 14
507
508    vmov.s16        q3, q11
509    vmov.s16        q4, q12
510
511    ; - step1[13] * cospi_8_64
512    vmull.s16       q11, d26, d30
513    vmull.s16       q12, d27, d30
514
515    ; -step1[10] * cospi_8_64
516    vmull.s16       q8, d20, d30
517    vmull.s16       q9, d21, d30
518
519    ; temp2 = -step1[10] * cospi_8_64 + step1[13] * cospi_24_64
520    vmlsl.s16       q11, d20, d31
521    vmlsl.s16       q12, d21, d31
522
523    ; temp1 = -step1[10] * cospi_8_64 + step1[13] * cospi_24_64
524    vmlal.s16       q8, d26, d31
525    vmlal.s16       q9, d27, d31
526
527    ; dct_const_round_shift(temp2)
528    vqrshrn.s32     d4, q11, #14              ; >> 14
529    vqrshrn.s32     d5, q12, #14              ; >> 14
530
531    ; dct_const_round_shift(temp1)
532    vqrshrn.s32     d10, q8, #14              ; >> 14
533    vqrshrn.s32     d11, q9, #14              ; >> 14
534
535    ; stage 5
536    vadd.s16        q8, q0, q3                ; step1[8] = step2[8]+step2[11];
537    vadd.s16        q9, q1, q2                ; step1[9] = step2[9]+step2[10];
538    vsub.s16        q10, q1, q2               ; step1[10] = step2[9]-step2[10];
539    vsub.s16        q11, q0, q3               ; step1[11] = step2[8]-step2[11];
540    vsub.s16        q12, q7, q4               ; step1[12] =-step2[12]+step2[15];
541    vsub.s16        q13, q6, q5               ; step1[13] =-step2[13]+step2[14];
542    vadd.s16        q14, q6, q5               ; step1[14] =step2[13]+step2[14];
543    vadd.s16        q15, q7, q4               ; step1[15] =step2[12]+step2[15];
544
545    ; stage 6.
546    ; generate cospi_16_64 = 11585
547    mov             r12, #0x2d00
548    add             r12, #0x41
549
550    vdup.16         d14, r12                  ; duplicate cospi_16_64
551
552    ; step1[13] * cospi_16_64
553    vmull.s16       q3, d26, d14
554    vmull.s16       q4, d27, d14
555
556    ; step1[10] * cospi_16_64
557    vmull.s16       q0, d20, d14
558    vmull.s16       q1, d21, d14
559
560    ; temp1 = (-step1[10] + step1[13]) * cospi_16_64
561    vsub.s32        q5, q3, q0
562    vsub.s32        q6, q4, q1
563
564    ; temp2 = (step1[10] + step1[13]) * cospi_16_64
565    vadd.s32        q10, q3, q0
566    vadd.s32        q4, q4, q1
567
568    ; dct_const_round_shift(temp1)
569    vqrshrn.s32     d4, q5, #14               ; >> 14
570    vqrshrn.s32     d5, q6, #14               ; >> 14
571
572    ; dct_const_round_shift(temp2)
573    vqrshrn.s32     d10, q10, #14             ; >> 14
574    vqrshrn.s32     d11, q4, #14              ; >> 14
575
576    ; step1[11] * cospi_16_64
577    vmull.s16       q0, d22, d14
578    vmull.s16       q1, d23, d14
579
580    ; step1[12] * cospi_16_64
581    vmull.s16       q13, d24, d14
582    vmull.s16       q6, d25, d14
583
584    ; temp1 = (-step1[11] + step1[12]) * cospi_16_64
585    vsub.s32        q10, q13, q0
586    vsub.s32        q4, q6, q1
587
588    ; temp2 = (step1[11] + step1[12]) * cospi_16_64
589    vadd.s32        q13, q13, q0
590    vadd.s32        q6, q6, q1
591
592    ; dct_const_round_shift(temp1)
593    vqrshrn.s32     d6, q10, #14              ; >> 14
594    vqrshrn.s32     d7, q4, #14               ; >> 14
595
596    ; dct_const_round_shift(temp2)
597    vqrshrn.s32     d8, q13, #14              ; >> 14
598    vqrshrn.s32     d9, q6, #14               ; >> 14
599
600    mov              r4, #16                  ; pass1Output stride
601    ldr              r3, [sp]                 ; load skip_adding
602    cmp              r3, #0                   ; check if need adding dest data
603    beq              skip_adding_dest
604
605    ldr              r7, [sp, #28]            ; dest used to save element 0-7
606    mov              r9, r7                   ; save dest pointer for later use
607    ldr              r8, [sp, #32]            ; load dest_stride
608
609    ; stage 7
610    ; load the data in pass1
611    vld1.s16        {q0}, [r2], r4            ; load data step2[0]
612    vld1.s16        {q1}, [r2], r4            ; load data step2[1]
613    vld1.s16        {q10}, [r2], r4           ; load data step2[2]
614    vld1.s16        {q11}, [r2], r4           ; load data step2[3]
615    vld1.64         {d12}, [r7], r8           ; load destinatoin data
616    vld1.64         {d13}, [r7], r8           ; load destinatoin data
617    vadd.s16        q12, q0, q15              ; step2[0] + step2[15]
618    vadd.s16        q13, q1, q14              ; step2[1] + step2[14]
619    vrshr.s16       q12, q12, #6              ; ROUND_POWER_OF_TWO
620    vrshr.s16       q13, q13, #6              ; ROUND_POWER_OF_TWO
621    vaddw.u8        q12, q12, d12             ; + dest[j * dest_stride + i]
622    vaddw.u8        q13, q13, d13             ; + dest[j * dest_stride + i]
623    vqmovun.s16     d12, q12                  ; clip pixel
624    vqmovun.s16     d13, q13                  ; clip pixel
625    vst1.64         {d12}, [r9], r8           ; store the data
626    vst1.64         {d13}, [r9], r8           ; store the data
627    vsub.s16        q14, q1, q14              ; step2[1] - step2[14]
628    vsub.s16        q15, q0, q15              ; step2[0] - step2[15]
629    vld1.64         {d12}, [r7], r8           ; load destinatoin data
630    vld1.64         {d13}, [r7], r8           ; load destinatoin data
631    vadd.s16        q12, q10, q5              ; step2[2] + step2[13]
632    vadd.s16        q13, q11, q4              ; step2[3] + step2[12]
633    vrshr.s16       q12, q12, #6              ; ROUND_POWER_OF_TWO
634    vrshr.s16       q13, q13, #6              ; ROUND_POWER_OF_TWO
635    vaddw.u8        q12, q12, d12             ; + dest[j * dest_stride + i]
636    vaddw.u8        q13, q13, d13             ; + dest[j * dest_stride + i]
637    vqmovun.s16     d12, q12                  ; clip pixel
638    vqmovun.s16     d13, q13                  ; clip pixel
639    vst1.64         {d12}, [r9], r8           ; store the data
640    vst1.64         {d13}, [r9], r8           ; store the data
641    vsub.s16        q4, q11, q4               ; step2[3] - step2[12]
642    vsub.s16        q5, q10, q5               ; step2[2] - step2[13]
643    vld1.s16        {q0}, [r2], r4            ; load data step2[4]
644    vld1.s16        {q1}, [r2], r4            ; load data step2[5]
645    vld1.s16        {q10}, [r2], r4           ; load data step2[6]
646    vld1.s16        {q11}, [r2], r4           ; load data step2[7]
647    vld1.64         {d12}, [r7], r8           ; load destinatoin data
648    vld1.64         {d13}, [r7], r8           ; load destinatoin data
649    vadd.s16        q12, q0, q3               ; step2[4] + step2[11]
650    vadd.s16        q13, q1, q2               ; step2[5] + step2[10]
651    vrshr.s16       q12, q12, #6              ; ROUND_POWER_OF_TWO
652    vrshr.s16       q13, q13, #6              ; ROUND_POWER_OF_TWO
653    vaddw.u8        q12, q12, d12             ; + dest[j * dest_stride + i]
654    vaddw.u8        q13, q13, d13             ; + dest[j * dest_stride + i]
655    vqmovun.s16     d12, q12                  ; clip pixel
656    vqmovun.s16     d13, q13                  ; clip pixel
657    vst1.64         {d12}, [r9], r8           ; store the data
658    vst1.64         {d13}, [r9], r8           ; store the data
659    vsub.s16        q2, q1, q2                ; step2[5] - step2[10]
660    vsub.s16        q3, q0, q3                ; step2[4] - step2[11]
661    vld1.64         {d12}, [r7], r8           ; load destinatoin data
662    vld1.64         {d13}, [r7], r8           ; load destinatoin data
663    vadd.s16        q12, q10, q9              ; step2[6] + step2[9]
664    vadd.s16        q13, q11, q8              ; step2[7] + step2[8]
665    vrshr.s16       q12, q12, #6              ; ROUND_POWER_OF_TWO
666    vrshr.s16       q13, q13, #6              ; ROUND_POWER_OF_TWO
667    vaddw.u8        q12, q12, d12             ; + dest[j * dest_stride + i]
668    vaddw.u8        q13, q13, d13             ; + dest[j * dest_stride + i]
669    vqmovun.s16     d12, q12                  ; clip pixel
670    vqmovun.s16     d13, q13                  ; clip pixel
671    vst1.64         {d12}, [r9], r8           ; store the data
672    vst1.64         {d13}, [r9], r8           ; store the data
673    vld1.64         {d12}, [r7], r8           ; load destinatoin data
674    vld1.64         {d13}, [r7], r8           ; load destinatoin data
675    vsub.s16        q8, q11, q8               ; step2[7] - step2[8]
676    vsub.s16        q9, q10, q9               ; step2[6] - step2[9]
677
678    ; store the data  output 8,9,10,11,12,13,14,15
679    vrshr.s16       q8, q8, #6                ; ROUND_POWER_OF_TWO
680    vaddw.u8        q8, q8, d12               ; + dest[j * dest_stride + i]
681    vqmovun.s16     d12, q8                   ; clip pixel
682    vst1.64         {d12}, [r9], r8           ; store the data
683    vld1.64         {d12}, [r7], r8           ; load destinatoin data
684    vrshr.s16       q9, q9, #6
685    vaddw.u8        q9, q9, d13               ; + dest[j * dest_stride + i]
686    vqmovun.s16     d13, q9                   ; clip pixel
687    vst1.64         {d13}, [r9], r8           ; store the data
688    vld1.64         {d13}, [r7], r8           ; load destinatoin data
689    vrshr.s16       q2, q2, #6
690    vaddw.u8        q2, q2, d12               ; + dest[j * dest_stride + i]
691    vqmovun.s16     d12, q2                   ; clip pixel
692    vst1.64         {d12}, [r9], r8           ; store the data
693    vld1.64         {d12}, [r7], r8           ; load destinatoin data
694    vrshr.s16       q3, q3, #6
695    vaddw.u8        q3, q3, d13               ; + dest[j * dest_stride + i]
696    vqmovun.s16     d13, q3                   ; clip pixel
697    vst1.64         {d13}, [r9], r8           ; store the data
698    vld1.64         {d13}, [r7], r8           ; load destinatoin data
699    vrshr.s16       q4, q4, #6
700    vaddw.u8        q4, q4, d12               ; + dest[j * dest_stride + i]
701    vqmovun.s16     d12, q4                   ; clip pixel
702    vst1.64         {d12}, [r9], r8           ; store the data
703    vld1.64         {d12}, [r7], r8           ; load destinatoin data
704    vrshr.s16       q5, q5, #6
705    vaddw.u8        q5, q5, d13               ; + dest[j * dest_stride + i]
706    vqmovun.s16     d13, q5                   ; clip pixel
707    vst1.64         {d13}, [r9], r8           ; store the data
708    vld1.64         {d13}, [r7], r8           ; load destinatoin data
709    vrshr.s16       q14, q14, #6
710    vaddw.u8        q14, q14, d12             ; + dest[j * dest_stride + i]
711    vqmovun.s16     d12, q14                  ; clip pixel
712    vst1.64         {d12}, [r9], r8           ; store the data
713    vld1.64         {d12}, [r7], r8           ; load destinatoin data
714    vrshr.s16       q15, q15, #6
715    vaddw.u8        q15, q15, d13             ; + dest[j * dest_stride + i]
716    vqmovun.s16     d13, q15                  ; clip pixel
717    vst1.64         {d13}, [r9], r8           ; store the data
718    b               end_idct16x16_pass2
719
720skip_adding_dest
721    ; stage 7
722    ; load the data in pass1
723    mov              r5, #24
724    mov              r3, #8
725
726    vld1.s16        {q0}, [r2], r4            ; load data step2[0]
727    vld1.s16        {q1}, [r2], r4            ; load data step2[1]
728    vadd.s16        q12, q0, q15              ; step2[0] + step2[15]
729    vadd.s16        q13, q1, q14              ; step2[1] + step2[14]
730    vld1.s16        {q10}, [r2], r4           ; load data step2[2]
731    vld1.s16        {q11}, [r2], r4           ; load data step2[3]
732    vst1.64         {d24}, [r1], r3           ; store output[0]
733    vst1.64         {d25}, [r1], r5
734    vst1.64         {d26}, [r1], r3           ; store output[1]
735    vst1.64         {d27}, [r1], r5
736    vadd.s16        q12, q10, q5              ; step2[2] + step2[13]
737    vadd.s16        q13, q11, q4              ; step2[3] + step2[12]
738    vsub.s16        q14, q1, q14              ; step2[1] - step2[14]
739    vsub.s16        q15, q0, q15              ; step2[0] - step2[15]
740    vst1.64         {d24}, [r1], r3           ; store output[2]
741    vst1.64         {d25}, [r1], r5
742    vst1.64         {d26}, [r1], r3           ; store output[3]
743    vst1.64         {d27}, [r1], r5
744    vsub.s16        q4, q11, q4               ; step2[3] - step2[12]
745    vsub.s16        q5, q10, q5               ; step2[2] - step2[13]
746    vld1.s16        {q0}, [r2], r4            ; load data step2[4]
747    vld1.s16        {q1}, [r2], r4            ; load data step2[5]
748    vadd.s16        q12, q0, q3               ; step2[4] + step2[11]
749    vadd.s16        q13, q1, q2               ; step2[5] + step2[10]
750    vld1.s16        {q10}, [r2], r4           ; load data step2[6]
751    vld1.s16        {q11}, [r2], r4           ; load data step2[7]
752    vst1.64         {d24}, [r1], r3           ; store output[4]
753    vst1.64         {d25}, [r1], r5
754    vst1.64         {d26}, [r1], r3           ; store output[5]
755    vst1.64         {d27}, [r1], r5
756    vadd.s16        q12, q10, q9              ; step2[6] + step2[9]
757    vadd.s16        q13, q11, q8              ; step2[7] + step2[8]
758    vsub.s16        q2, q1, q2                ; step2[5] - step2[10]
759    vsub.s16        q3, q0, q3                ; step2[4] - step2[11]
760    vsub.s16        q8, q11, q8               ; step2[7] - step2[8]
761    vsub.s16        q9, q10, q9               ; step2[6] - step2[9]
762    vst1.64         {d24}, [r1], r3           ; store output[6]
763    vst1.64         {d25}, [r1], r5
764    vst1.64         {d26}, [r1], r3           ; store output[7]
765    vst1.64         {d27}, [r1], r5
766
767    ; store the data  output 8,9,10,11,12,13,14,15
768    vst1.64         {d16}, [r1], r3
769    vst1.64         {d17}, [r1], r5
770    vst1.64         {d18}, [r1], r3
771    vst1.64         {d19}, [r1], r5
772    vst1.64         {d4}, [r1], r3
773    vst1.64         {d5}, [r1], r5
774    vst1.64         {d6}, [r1], r3
775    vst1.64         {d7}, [r1], r5
776    vst1.64         {d8}, [r1], r3
777    vst1.64         {d9}, [r1], r5
778    vst1.64         {d10}, [r1], r3
779    vst1.64         {d11}, [r1], r5
780    vst1.64         {d28}, [r1], r3
781    vst1.64         {d29}, [r1], r5
782    vst1.64         {d30}, [r1], r3
783    vst1.64         {d31}, [r1], r5
784end_idct16x16_pass2
785    pop             {r3-r9}
786    bx              lr
787    ENDP  ; |vpx_idct16x16_256_add_neon_pass2|
788
789;void |vpx_idct16x16_10_add_neon_pass1|(int16_t *input,
790;                                             int16_t *output, int output_stride)
791;
792; r0  int16_t input
793; r1  int16_t *output
794; r2  int  output_stride)
795
796; idct16 stage1 - stage6 on all the elements loaded in q8-q15. The output
797; will be stored back into q8-q15 registers. This function will touch q0-q7
798; registers and use them as buffer during calculation.
799|vpx_idct16x16_10_add_neon_pass1| PROC
800
801    ; TODO(hkuang): Find a better way to load the elements.
802    ; load elements of 0, 2, 4, 6, 8, 10, 12, 14 into q8 - q15
803    vld2.s16        {q8,q9}, [r0]!
804    vld2.s16        {q9,q10}, [r0]!
805    vld2.s16        {q10,q11}, [r0]!
806    vld2.s16        {q11,q12}, [r0]!
807    vld2.s16        {q12,q13}, [r0]!
808    vld2.s16        {q13,q14}, [r0]!
809    vld2.s16        {q14,q15}, [r0]!
810    vld2.s16        {q1,q2}, [r0]!
811    vmov.s16        q15, q1
812
813    ; generate  cospi_28_64*2 = 6392
814    mov             r3, #0x1800
815    add             r3, #0xf8
816
817    ; generate cospi_4_64*2  = 32138
818    mov             r12, #0x7d00
819    add             r12, #0x8a
820
821    ; transpose the input data
822    TRANSPOSE8X8
823
824    ; stage 3
825    vdup.16         q0, r3                    ; duplicate cospi_28_64*2
826    vdup.16         q1, r12                   ; duplicate cospi_4_64*2
827
828    ; The following instructions use vqrdmulh to do the
829    ; dct_const_round_shift(step2[4] * cospi_28_64). vvqrdmulh will multiply,
830    ; double, and return the high 16 bits, effectively giving >> 15. Doubling
831    ; the constant will change this to >> 14.
832    ; dct_const_round_shift(step2[4] * cospi_28_64);
833    vqrdmulh.s16    q4, q9, q0
834
835    ; preloading to avoid stall
836    ; generate cospi_16_64*2 = 23170
837    mov             r3, #0x5a00
838    add             r3, #0x82
839
840    ; dct_const_round_shift(step2[4] * cospi_4_64);
841    vqrdmulh.s16    q7, q9, q1
842
843    ; stage 4
844    vdup.16         q1, r3                    ; cospi_16_64*2
845
846    ; generate cospi_16_64 = 11585
847    mov             r3, #0x2d00
848    add             r3, #0x41
849
850    vdup.16         d4, r3;                   ; duplicate cospi_16_64
851
852    ; dct_const_round_shift(step1[0] * cospi_16_64)
853    vqrdmulh.s16    q8, q8, q1
854
855    ; step2[6] * cospi_16_64
856    vmull.s16       q9, d14, d4
857    vmull.s16       q10, d15, d4
858
859    ; step2[5] * cospi_16_64
860    vmull.s16       q12, d9, d4
861    vmull.s16       q11, d8, d4
862
863    ; temp1 = (step2[6] - step2[5]) * cospi_16_64
864    vsub.s32        q15, q10, q12
865    vsub.s32        q6, q9, q11
866
867    ; temp2 = (step2[5] + step2[6]) * cospi_16_64
868    vadd.s32        q9, q9, q11
869    vadd.s32        q10, q10, q12
870
871    ; dct_const_round_shift(temp1)
872    vqrshrn.s32     d11, q15, #14             ; >> 14
873    vqrshrn.s32     d10, q6, #14              ; >> 14
874
875    ; dct_const_round_shift(temp2)
876    vqrshrn.s32     d12, q9, #14              ; >> 14
877    vqrshrn.s32     d13, q10, #14             ; >> 14
878
879    ; stage 6
880    vadd.s16        q2, q8, q7                ; step2[0] = step1[0] + step1[7];
881    vadd.s16        q10, q8, q5               ; step2[2] = step1[2] + step1[5];
882    vadd.s16        q11, q8, q4               ; step2[3] = step1[3] + step1[4];
883    vadd.s16        q9, q8, q6                ; step2[1] = step1[1] + step1[6];
884    vsub.s16        q12, q8, q4               ; step2[4] = step1[3] - step1[4];
885    vsub.s16        q13, q8, q5               ; step2[5] = step1[2] - step1[5];
886    vsub.s16        q14, q8, q6               ; step2[6] = step1[1] - step1[6];
887    vsub.s16        q15, q8, q7               ; step2[7] = step1[0] - step1[7];
888
889    ; store the data
890    vst1.64         {d4}, [r1], r2
891    vst1.64         {d5}, [r1], r2
892    vst1.64         {d18}, [r1], r2
893    vst1.64         {d19}, [r1], r2
894    vst1.64         {d20}, [r1], r2
895    vst1.64         {d21}, [r1], r2
896    vst1.64         {d22}, [r1], r2
897    vst1.64         {d23}, [r1], r2
898    vst1.64         {d24}, [r1], r2
899    vst1.64         {d25}, [r1], r2
900    vst1.64         {d26}, [r1], r2
901    vst1.64         {d27}, [r1], r2
902    vst1.64         {d28}, [r1], r2
903    vst1.64         {d29}, [r1], r2
904    vst1.64         {d30}, [r1], r2
905    vst1.64         {d31}, [r1], r2
906
907    bx              lr
908    ENDP  ; |vpx_idct16x16_10_add_neon_pass1|
909
910;void vpx_idct16x16_10_add_neon_pass2(int16_t *src,
911;                                           int16_t *output,
912;                                           int16_t *pass1Output,
913;                                           int16_t skip_adding,
914;                                           uint8_t *dest,
915;                                           int dest_stride)
916;
917; r0  int16_t *src
918; r1  int16_t *output,
919; r2  int16_t *pass1Output,
920; r3  int16_t skip_adding,
921; r4  uint8_t *dest,
922; r5  int dest_stride)
923
924; idct16 stage1 - stage7 on all the elements loaded in q8-q15. The output
925; will be stored back into q8-q15 registers. This function will touch q0-q7
926; registers and use them as buffer during calculation.
927|vpx_idct16x16_10_add_neon_pass2| PROC
928    push            {r3-r9}
929
930    ; TODO(hkuang): Find a better way to load the elements.
931    ; load elements of 1, 3, 5, 7, 9, 11, 13, 15 into q8 - q15
932    vld2.s16        {q8,q9}, [r0]!
933    vld2.s16        {q9,q10}, [r0]!
934    vld2.s16        {q10,q11}, [r0]!
935    vld2.s16        {q11,q12}, [r0]!
936    vld2.s16        {q12,q13}, [r0]!
937    vld2.s16        {q13,q14}, [r0]!
938    vld2.s16        {q14,q15}, [r0]!
939    vld2.s16        {q0,q1}, [r0]!
940    vmov.s16        q15, q0;
941
942    ; generate 2*cospi_30_64 = 3212
943    mov             r3, #0xc00
944    add             r3, #0x8c
945
946    ; generate 2*cospi_2_64  = 32610
947    mov             r12, #0x7f00
948    add             r12, #0x62
949
950    ; transpose the input data
951    TRANSPOSE8X8
952
953    ; stage 3
954    vdup.16         q6, r3                    ; duplicate 2*cospi_30_64
955
956    ; dct_const_round_shift(step1[8] * cospi_30_64)
957    vqrdmulh.s16    q0, q8, q6
958
959    vdup.16         q6, r12                   ; duplicate 2*cospi_2_64
960
961    ; dct_const_round_shift(step1[8] * cospi_2_64)
962    vqrdmulh.s16    q7, q8, q6
963
964    ; preloading to avoid stall
965    ; generate 2*cospi_26_64 = 9512
966    mov             r12, #0x2500
967    add             r12, #0x28
968    rsb             r12, #0
969    vdup.16         q15, r12                  ; duplicate -2*cospi_26_64
970
971    ; generate 2*cospi_6_64 = 31358
972    mov             r3, #0x7a00
973    add             r3, #0x7e
974    vdup.16         q14, r3                   ; duplicate 2*cospi_6_64
975
976    ; dct_const_round_shift(- step1[12] * cospi_26_64)
977    vqrdmulh.s16    q3, q9, q15
978
979    ; dct_const_round_shift(step1[12] * cospi_6_64)
980    vqrdmulh.s16    q4, q9, q14
981
982    ; stage 4
983    ; generate cospi_24_64 = 6270
984    mov             r3, #0x1800
985    add             r3, #0x7e
986    vdup.16         d31, r3                   ; duplicate cospi_24_64
987
988    ; generate cospi_8_64 = 15137
989    mov             r12, #0x3b00
990    add             r12, #0x21
991    vdup.16         d30, r12                  ; duplicate cospi_8_64
992
993    ; step1[14] * cospi_24_64
994    vmull.s16       q12, d14, d31
995    vmull.s16       q5, d15, d31
996
997    ; step1[9] * cospi_24_64
998    vmull.s16       q2, d0, d31
999    vmull.s16       q11, d1, d31
1000
1001    ; temp1 = -step1[9] * cospi_8_64 + step1[14] * cospi_24_64
1002    vmlsl.s16       q12, d0, d30
1003    vmlsl.s16       q5, d1, d30
1004
1005    ; temp2 = step1[9] * cospi_24_64 + step1[14] * cospi_8_64
1006    vmlal.s16       q2, d14, d30
1007    vmlal.s16       q11, d15, d30
1008
1009    rsb              r12, #0
1010    vdup.16          d30, r12                 ; duplicate -cospi_8_64
1011
1012    ; dct_const_round_shift(temp1)
1013    vqrshrn.s32     d2, q12, #14              ; >> 14
1014    vqrshrn.s32     d3, q5, #14               ; >> 14
1015
1016    ; dct_const_round_shift(temp2)
1017    vqrshrn.s32     d12, q2, #14              ; >> 14
1018    vqrshrn.s32     d13, q11, #14             ; >> 14
1019
1020    ; - step1[13] * cospi_8_64
1021    vmull.s16       q10, d8, d30
1022    vmull.s16       q13, d9, d30
1023
1024    ; -step1[10] * cospi_8_64
1025    vmull.s16       q8, d6, d30
1026    vmull.s16       q9, d7, d30
1027
1028    ; temp1 = -step1[10] * cospi_24_64 - step1[13] * cospi_8_64
1029    vmlsl.s16       q10, d6, d31
1030    vmlsl.s16       q13, d7, d31
1031
1032    ; temp2 = -step1[10] * cospi_8_64 + step1[13] * cospi_24_64
1033    vmlal.s16       q8, d8, d31
1034    vmlal.s16       q9, d9, d31
1035
1036    ; dct_const_round_shift(temp1)
1037    vqrshrn.s32     d4, q10, #14              ; >> 14
1038    vqrshrn.s32     d5, q13, #14              ; >> 14
1039
1040    ; dct_const_round_shift(temp2)
1041    vqrshrn.s32     d10, q8, #14              ; >> 14
1042    vqrshrn.s32     d11, q9, #14              ; >> 14
1043
1044    ; stage 5
1045    vadd.s16        q8, q0, q3                ; step1[8] = step2[8]+step2[11];
1046    vadd.s16        q9, q1, q2                ; step1[9] = step2[9]+step2[10];
1047    vsub.s16        q10, q1, q2               ; step1[10] = step2[9]-step2[10];
1048    vsub.s16        q11, q0, q3               ; step1[11] = step2[8]-step2[11];
1049    vsub.s16        q12, q7, q4               ; step1[12] =-step2[12]+step2[15];
1050    vsub.s16        q13, q6, q5               ; step1[13] =-step2[13]+step2[14];
1051    vadd.s16        q14, q6, q5               ; step1[14] =step2[13]+step2[14];
1052    vadd.s16        q15, q7, q4               ; step1[15] =step2[12]+step2[15];
1053
1054    ; stage 6.
1055    ; generate cospi_16_64 = 11585
1056    mov             r12, #0x2d00
1057    add             r12, #0x41
1058
1059    vdup.16         d14, r12                  ; duplicate cospi_16_64
1060
1061    ; step1[13] * cospi_16_64
1062    vmull.s16       q3, d26, d14
1063    vmull.s16       q4, d27, d14
1064
1065    ; step1[10] * cospi_16_64
1066    vmull.s16       q0, d20, d14
1067    vmull.s16       q1, d21, d14
1068
1069    ; temp1 = (-step1[10] + step1[13]) * cospi_16_64
1070    vsub.s32        q5, q3, q0
1071    vsub.s32        q6, q4, q1
1072
1073    ; temp2 = (step1[10] + step1[13]) * cospi_16_64
1074    vadd.s32        q0, q3, q0
1075    vadd.s32        q1, q4, q1
1076
1077    ; dct_const_round_shift(temp1)
1078    vqrshrn.s32     d4, q5, #14               ; >> 14
1079    vqrshrn.s32     d5, q6, #14               ; >> 14
1080
1081    ; dct_const_round_shift(temp2)
1082    vqrshrn.s32     d10, q0, #14              ; >> 14
1083    vqrshrn.s32     d11, q1, #14              ; >> 14
1084
1085    ; step1[11] * cospi_16_64
1086    vmull.s16       q0, d22, d14
1087    vmull.s16       q1, d23, d14
1088
1089    ; step1[12] * cospi_16_64
1090    vmull.s16       q13, d24, d14
1091    vmull.s16       q6, d25, d14
1092
1093    ; temp1 = (-step1[11] + step1[12]) * cospi_16_64
1094    vsub.s32        q10, q13, q0
1095    vsub.s32        q4, q6, q1
1096
1097    ; temp2 = (step1[11] + step1[12]) * cospi_16_64
1098    vadd.s32        q13, q13, q0
1099    vadd.s32        q6, q6, q1
1100
1101    ; dct_const_round_shift(input_dc * cospi_16_64)
1102    vqrshrn.s32     d6, q10, #14              ; >> 14
1103    vqrshrn.s32     d7, q4, #14               ; >> 14
1104
1105    ; dct_const_round_shift((step1[11] + step1[12]) * cospi_16_64);
1106    vqrshrn.s32     d8, q13, #14              ; >> 14
1107    vqrshrn.s32     d9, q6, #14               ; >> 14
1108
1109    mov              r4, #16                  ; pass1Output stride
1110    ldr              r3, [sp]                 ; load skip_adding
1111
1112    ; stage 7
1113    ; load the data in pass1
1114    mov              r5, #24
1115    mov              r3, #8
1116
1117    vld1.s16        {q0}, [r2], r4            ; load data step2[0]
1118    vld1.s16        {q1}, [r2], r4            ; load data step2[1]
1119    vadd.s16        q12, q0, q15              ; step2[0] + step2[15]
1120    vadd.s16        q13, q1, q14              ; step2[1] + step2[14]
1121    vld1.s16        {q10}, [r2], r4           ; load data step2[2]
1122    vld1.s16        {q11}, [r2], r4           ; load data step2[3]
1123    vst1.64         {d24}, [r1], r3           ; store output[0]
1124    vst1.64         {d25}, [r1], r5
1125    vst1.64         {d26}, [r1], r3           ; store output[1]
1126    vst1.64         {d27}, [r1], r5
1127    vadd.s16        q12, q10, q5              ; step2[2] + step2[13]
1128    vadd.s16        q13, q11, q4              ; step2[3] + step2[12]
1129    vsub.s16        q14, q1, q14              ; step2[1] - step2[14]
1130    vsub.s16        q15, q0, q15              ; step2[0] - step2[15]
1131    vst1.64         {d24}, [r1], r3           ; store output[2]
1132    vst1.64         {d25}, [r1], r5
1133    vst1.64         {d26}, [r1], r3           ; store output[3]
1134    vst1.64         {d27}, [r1], r5
1135    vsub.s16        q4, q11, q4               ; step2[3] - step2[12]
1136    vsub.s16        q5, q10, q5               ; step2[2] - step2[13]
1137    vld1.s16        {q0}, [r2], r4            ; load data step2[4]
1138    vld1.s16        {q1}, [r2], r4            ; load data step2[5]
1139    vadd.s16        q12, q0, q3               ; step2[4] + step2[11]
1140    vadd.s16        q13, q1, q2               ; step2[5] + step2[10]
1141    vld1.s16        {q10}, [r2], r4           ; load data step2[6]
1142    vld1.s16        {q11}, [r2], r4           ; load data step2[7]
1143    vst1.64         {d24}, [r1], r3           ; store output[4]
1144    vst1.64         {d25}, [r1], r5
1145    vst1.64         {d26}, [r1], r3           ; store output[5]
1146    vst1.64         {d27}, [r1], r5
1147    vadd.s16        q12, q10, q9              ; step2[6] + step2[9]
1148    vadd.s16        q13, q11, q8              ; step2[7] + step2[8]
1149    vsub.s16        q2, q1, q2                ; step2[5] - step2[10]
1150    vsub.s16        q3, q0, q3                ; step2[4] - step2[11]
1151    vsub.s16        q8, q11, q8               ; step2[7] - step2[8]
1152    vsub.s16        q9, q10, q9               ; step2[6] - step2[9]
1153    vst1.64         {d24}, [r1], r3           ; store output[6]
1154    vst1.64         {d25}, [r1], r5
1155    vst1.64         {d26}, [r1], r3           ; store output[7]
1156    vst1.64         {d27}, [r1], r5
1157
1158    ; store the data  output 8,9,10,11,12,13,14,15
1159    vst1.64         {d16}, [r1], r3
1160    vst1.64         {d17}, [r1], r5
1161    vst1.64         {d18}, [r1], r3
1162    vst1.64         {d19}, [r1], r5
1163    vst1.64         {d4}, [r1], r3
1164    vst1.64         {d5}, [r1], r5
1165    vst1.64         {d6}, [r1], r3
1166    vst1.64         {d7}, [r1], r5
1167    vst1.64         {d8}, [r1], r3
1168    vst1.64         {d9}, [r1], r5
1169    vst1.64         {d10}, [r1], r3
1170    vst1.64         {d11}, [r1], r5
1171    vst1.64         {d28}, [r1], r3
1172    vst1.64         {d29}, [r1], r5
1173    vst1.64         {d30}, [r1], r3
1174    vst1.64         {d31}, [r1], r5
1175end_idct10_16x16_pass2
1176    pop             {r3-r9}
1177    bx              lr
1178    ENDP  ; |vpx_idct16x16_10_add_neon_pass2|
1179    END
1180