Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / libvpx / source / libvpx / vp9 / common / arm / neon / vp9_idct8x8_add_neon.asm
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  |vp9_idct8x8_64_add_neon|
12     EXPORT  |vp9_idct8x8_10_add_neon|
13     ARM
14     REQUIRE8
15     PRESERVE8
16
17     AREA ||.text||, CODE, READONLY, ALIGN=2
18
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
22     ; calculation.
23     MACRO
24     IDCT8x8_1D
25     ; stage 1
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
30
31     ; input[1] * cospi_28_64
32     vmull.s16       q2, d18, d0
33     vmull.s16       q3, d19, d0
34
35     ; input[5] * cospi_12_64
36     vmull.s16       q5, d26, d2
37     vmull.s16       q6, d27, d2
38
39     ; input[1]*cospi_28_64-input[7]*cospi_4_64
40     vmlsl.s16       q2, d30, d1
41     vmlsl.s16       q3, d31, d1
42
43     ; input[5] * cospi_12_64 - input[3] * cospi_20_64
44     vmlsl.s16       q5, d22, d3
45     vmlsl.s16       q6, d23, d3
46
47     ; dct_const_round_shift(input_dc * cospi_16_64)
48     vqrshrn.s32     d8, q2, #14               ; >> 14
49     vqrshrn.s32     d9, q3, #14               ; >> 14
50
51     ; dct_const_round_shift(input_dc * cospi_16_64)
52     vqrshrn.s32     d10, q5, #14              ; >> 14
53     vqrshrn.s32     d11, q6, #14              ; >> 14
54
55     ; input[1] * cospi_4_64
56     vmull.s16       q2, d18, d1
57     vmull.s16       q3, d19, d1
58
59     ; input[5] * cospi_20_64
60     vmull.s16       q9, d26, d3
61     vmull.s16       q13, d27, d3
62
63     ; input[1]*cospi_4_64+input[7]*cospi_28_64
64     vmlal.s16       q2, d30, d0
65     vmlal.s16       q3, d31, d0
66
67     ; input[5] * cospi_20_64 + input[3] * cospi_12_64
68     vmlal.s16       q9, d22, d2
69     vmlal.s16       q13, d23, d2
70
71     ; dct_const_round_shift(input_dc * cospi_16_64)
72     vqrshrn.s32     d14, q2, #14              ; >> 14
73     vqrshrn.s32     d15, q3, #14              ; >> 14
74
75     ; stage 2 & stage 3 - even half
76     vdup.16         d0, r7                    ; duplicate cospi_16_64
77
78     ; dct_const_round_shift(input_dc * cospi_16_64)
79     vqrshrn.s32     d12, q9, #14              ; >> 14
80     vqrshrn.s32     d13, q13, #14              ; >> 14
81
82     ; input[0] * cospi_16_64
83     vmull.s16       q2, d16, d0
84     vmull.s16       q3, d17, d0
85
86     ; input[0] * cospi_16_64
87     vmull.s16       q13, d16, d0
88     vmull.s16       q15, d17, d0
89
90     ; (input[0] + input[2]) * cospi_16_64
91     vmlal.s16       q2,  d24, d0
92     vmlal.s16       q3, d25, d0
93
94     ; (input[0] - input[2]) * cospi_16_64
95     vmlsl.s16       q13, d24, d0
96     vmlsl.s16       q15, d25, d0
97
98     vdup.16         d0, r8                    ; duplicate cospi_24_64
99     vdup.16         d1, r9                    ; duplicate cospi_8_64
100
101     ; dct_const_round_shift(input_dc * cospi_16_64)
102     vqrshrn.s32     d18, q2, #14              ; >> 14
103     vqrshrn.s32     d19, q3, #14              ; >> 14
104
105     ; dct_const_round_shift(input_dc * cospi_16_64)
106     vqrshrn.s32     d22, q13, #14              ; >> 14
107     vqrshrn.s32     d23, q15, #14              ; >> 14
108
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
113
114     ; input[1] * cospi_8_64
115     vmull.s16       q8, d20, d1
116     vmull.s16       q12, d21, d1
117
118     ; input[1] * cospi_24_64 - input[3] * cospi_8_64
119     vmlsl.s16       q2, d28, d1
120     vmlsl.s16       q3, d29, d1
121
122     ; input[1] * cospi_8_64 + input[3] * cospi_24_64
123     vmlal.s16       q8, d28, d0
124     vmlal.s16       q12, d29, d0
125
126     ; dct_const_round_shift(input_dc * cospi_16_64)
127     vqrshrn.s32     d26, q2, #14              ; >> 14
128     vqrshrn.s32     d27, q3, #14              ; >> 14
129
130     ; dct_const_round_shift(input_dc * cospi_16_64)
131     vqrshrn.s32     d30, q8, #14              ; >> 14
132     vqrshrn.s32     d31, q12, #14              ; >> 14
133
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]
138
139     ; stage 3 -odd half
140     vdup.16         d16, r7                   ; duplicate cospi_16_64
141
142     ; stage 2 - odd half
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]
147
148     ; step2[6] * cospi_16_64
149     vmull.s16       q9, d28, d16
150     vmull.s16       q10, d29, d16
151
152     ; step2[6] * cospi_16_64
153     vmull.s16       q11, d28, d16
154     vmull.s16       q12, d29, d16
155
156     ; (step2[6] - step2[5]) * cospi_16_64
157     vmlsl.s16       q9, d26, d16
158     vmlsl.s16       q10, d27, d16
159
160     ; (step2[5] + step2[6]) * cospi_16_64
161     vmlal.s16       q11, d26, d16
162     vmlal.s16       q12, d27, d16
163
164     ; dct_const_round_shift(input_dc * cospi_16_64)
165     vqrshrn.s32     d10, q9, #14              ; >> 14
166     vqrshrn.s32     d11, q10, #14             ; >> 14
167
168     ; dct_const_round_shift(input_dc * cospi_16_64)
169     vqrshrn.s32     d12, q11, #14              ; >> 14
170     vqrshrn.s32     d13, q12, #14             ; >> 14
171
172     ; stage 4
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];
181     MEND
182
183     ; Transpose a 8x8 16bit data matrix. Datas are loaded in q8-q15.
184     MACRO
185     TRANSPOSE8X8
186     vswp            d17, d24
187     vswp            d23, d30
188     vswp            d21, d28
189     vswp            d19, d26
190     vtrn.32         q8, q10
191     vtrn.32         q9, q11
192     vtrn.32         q12, q14
193     vtrn.32         q13, q15
194     vtrn.16         q8, q9
195     vtrn.16         q10, q11
196     vtrn.16         q12, q13
197     vtrn.16         q14, q15
198     MEND
199
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)
202 ;
203 ; r0  int16_t input
204 ; r1  uint8_t *dest
205 ; r2  int dest_stride)
206
207 |vp9_idct8x8_64_add_neon| PROC
208     push            {r4-r9}
209     vpush           {d8-d15}
210     vld1.s16        {q8,q9}, [r0]!
211     vld1.s16        {q10,q11}, [r0]!
212     vld1.s16        {q12,q13}, [r0]!
213     vld1.s16        {q14,q15}, [r0]!
214
215     ; transpose the input data
216     TRANSPOSE8X8
217
218     ; generate  cospi_28_64 = 3196
219     mov             r3, #0x0c00
220     add             r3, #0x7c
221
222     ; generate cospi_4_64  = 16069
223     mov             r4, #0x3e00
224     add             r4, #0xc5
225
226     ; generate cospi_12_64 = 13623
227     mov             r5, #0x3500
228     add             r5, #0x37
229
230     ; generate cospi_20_64 = 9102
231     mov             r6, #0x2300
232     add             r6, #0x8e
233
234     ; generate cospi_16_64 = 11585
235     mov             r7, #0x2d00
236     add             r7, #0x41
237
238     ; generate cospi_24_64 = 6270
239     mov             r8, #0x1800
240     add             r8, #0x7e
241
242     ; generate cospi_8_64 = 15137
243     mov             r9, #0x3b00
244     add             r9, #0x21
245
246     ; First transform rows
247     IDCT8x8_1D
248
249     ; Transpose the matrix
250     TRANSPOSE8X8
251
252     ; Then transform columns
253     IDCT8x8_1D
254
255     ; ROUND_POWER_OF_TWO(temp_out[j], 5)
256     vrshr.s16       q8, q8, #5
257     vrshr.s16       q9, q9, #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
264
265     ; save dest pointer
266     mov             r0, r1
267
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
276     vld1.64         {d7}, [r1]
277
278     ; ROUND_POWER_OF_TWO(temp_out[j], 5) + dest[j * dest_stride + i]
279     vaddw.u8        q8, q8, d0
280     vaddw.u8        q9, q9, d1
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
287
288     ; clip_pixel
289     vqmovun.s16     d0, q8
290     vqmovun.s16     d1, q9
291     vqmovun.s16     d2, q10
292     vqmovun.s16     d3, q11
293     vqmovun.s16     d4, q12
294     vqmovun.s16     d5, q13
295     vqmovun.s16     d6, q14
296     vqmovun.s16     d7, q15
297
298     ; store the data
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
307
308     vpop            {d8-d15}
309     pop             {r4-r9}
310     bx              lr
311     ENDP  ; |vp9_idct8x8_64_add_neon|
312
313 ;void vp9_idct8x8_10_add_neon(int16_t *input, uint8_t *dest, int dest_stride)
314 ;
315 ; r0  int16_t input
316 ; r1  uint8_t *dest
317 ; r2  int dest_stride)
318
319 |vp9_idct8x8_10_add_neon| PROC
320     push            {r4-r9}
321     vpush           {d8-d15}
322     vld1.s16        {q8,q9}, [r0]!
323     vld1.s16        {q10,q11}, [r0]!
324     vld1.s16        {q12,q13}, [r0]!
325     vld1.s16        {q14,q15}, [r0]!
326
327     ; transpose the input data
328     TRANSPOSE8X8
329
330     ; generate  cospi_28_64 = 3196
331     mov             r3, #0x0c00
332     add             r3, #0x7c
333
334     ; generate cospi_4_64  = 16069
335     mov             r4, #0x3e00
336     add             r4, #0xc5
337
338     ; generate cospi_12_64 = 13623
339     mov             r5, #0x3500
340     add             r5, #0x37
341
342     ; generate cospi_20_64 = 9102
343     mov             r6, #0x2300
344     add             r6, #0x8e
345
346     ; generate cospi_16_64 = 11585
347     mov             r7, #0x2d00
348     add             r7, #0x41
349
350     ; generate cospi_24_64 = 6270
351     mov             r8, #0x1800
352     add             r8, #0x7e
353
354     ; generate cospi_8_64 = 15137
355     mov             r9, #0x3b00
356     add             r9, #0x21
357
358     ; First transform rows
359     ; stage 1
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.
364     mov             r12, r3, lsl #1
365     vdup.16         q0, r12                   ; duplicate cospi_28_64*2
366     mov             r12, r4, lsl #1
367     vdup.16         q1, r12                   ; duplicate cospi_4_64*2
368
369     ; dct_const_round_shift(input[1] * cospi_28_64)
370     vqrdmulh.s16    q4, q9, q0
371
372     mov             r12, r6, lsl #1
373     rsb             r12, #0
374     vdup.16         q0, r12                   ; duplicate -cospi_20_64*2
375
376     ; dct_const_round_shift(input[1] * cospi_4_64)
377     vqrdmulh.s16    q7, q9, q1
378
379     mov             r12, r5, lsl #1
380     vdup.16         q1, r12                   ; duplicate cospi_12_64*2
381
382     ; dct_const_round_shift(- input[3] * cospi_20_64)
383     vqrdmulh.s16    q5, q11, q0
384
385     mov             r12, r7, lsl #1
386     vdup.16         q0, r12                   ; duplicate cospi_16_64*2
387
388     ; dct_const_round_shift(input[3] * cospi_12_64)
389     vqrdmulh.s16    q6, q11, q1
390
391     ; stage 2 & stage 3 - even half
392     mov             r12, r8, lsl #1
393     vdup.16         q1, r12                   ; duplicate cospi_24_64*2
394
395     ; dct_const_round_shift(input_dc * cospi_16_64)
396     vqrdmulh.s16    q9, q8, q0
397
398     mov             r12, r9, lsl #1
399     vdup.16         q0, r12                   ; duplicate cospi_8_64*2
400
401     ; dct_const_round_shift(input[1] * cospi_24_64)
402     vqrdmulh.s16    q13, q10, q1
403
404     ; dct_const_round_shift(input[1] * cospi_8_64)
405     vqrdmulh.s16    q15, q10, q0
406
407     ; stage 3 -odd half
408     vdup.16         d16, r7                   ; duplicate cospi_16_64
409
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]
414
415     ; stage 2 - odd half
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]
420
421     ; step2[6] * cospi_16_64
422     vmull.s16       q9, d28, d16
423     vmull.s16       q10, d29, d16
424
425     ; step2[6] * cospi_16_64
426     vmull.s16       q11, d28, d16
427     vmull.s16       q12, d29, d16
428
429     ; (step2[6] - step2[5]) * cospi_16_64
430     vmlsl.s16       q9, d26, d16
431     vmlsl.s16       q10, d27, d16
432
433     ; (step2[5] + step2[6]) * cospi_16_64
434     vmlal.s16       q11, d26, d16
435     vmlal.s16       q12, d27, d16
436
437     ; dct_const_round_shift(input_dc * cospi_16_64)
438     vqrshrn.s32     d10, q9, #14              ; >> 14
439     vqrshrn.s32     d11, q10, #14             ; >> 14
440
441     ; dct_const_round_shift(input_dc * cospi_16_64)
442     vqrshrn.s32     d12, q11, #14              ; >> 14
443     vqrshrn.s32     d13, q12, #14             ; >> 14
444
445     ; stage 4
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];
454
455     ; Transpose the matrix
456     TRANSPOSE8X8
457
458     ; Then transform columns
459     IDCT8x8_1D
460
461     ; ROUND_POWER_OF_TWO(temp_out[j], 5)
462     vrshr.s16       q8, q8, #5
463     vrshr.s16       q9, q9, #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
470
471     ; save dest pointer
472     mov             r0, r1
473
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
482     vld1.64         {d7}, [r1]
483
484     ; ROUND_POWER_OF_TWO(temp_out[j], 5) + dest[j * dest_stride + i]
485     vaddw.u8        q8, q8, d0
486     vaddw.u8        q9, q9, d1
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
493
494     ; clip_pixel
495     vqmovun.s16     d0, q8
496     vqmovun.s16     d1, q9
497     vqmovun.s16     d2, q10
498     vqmovun.s16     d3, q11
499     vqmovun.s16     d4, q12
500     vqmovun.s16     d5, q13
501     vqmovun.s16     d6, q14
502     vqmovun.s16     d7, q15
503
504     ; store the data
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
513
514     vpop            {d8-d15}
515     pop             {r4-r9}
516     bx              lr
517     ENDP  ; |vp9_idct8x8_10_add_neon|
518
519     END