• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2016 Google Inc.
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "libavutil/arm/asm.S"
22#include "neon.S"
23
24const itxfm4_coeffs, align=4
25        .short  11585, 0, 6270, 15137
26iadst4_coeffs:
27        .short  5283, 15212, 9929, 13377
28endconst
29
30const iadst8_coeffs, align=4
31        .short  16305, 1606, 14449, 7723, 10394, 12665, 4756, 15679
32idct_coeffs:
33        .short  11585, 0, 6270, 15137, 3196, 16069, 13623, 9102
34        .short  1606, 16305, 12665, 10394, 7723, 14449, 15679, 4756
35        .short  804, 16364, 12140, 11003, 7005, 14811, 15426, 5520
36        .short  3981, 15893, 14053, 8423, 9760, 13160, 16207, 2404
37endconst
38
39const iadst16_coeffs, align=4
40        .short  16364, 804, 15893, 3981, 11003, 12140, 8423, 14053
41        .short  14811, 7005, 13160, 9760, 5520, 15426, 2404, 16207
42endconst
43
44@ Do four 4x4 transposes, using q registers for the subtransposes that don't
45@ need to address the individual d registers.
46@ r0,r1 == rq1, r2,r3 == rq1, etc
47.macro transpose16_q_4x_4x4 rq0, rq1, rq2, rq3, rq4, rq5, rq6, rq7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15
48        vtrn.32          \rq0, \rq1
49        vtrn.32          \rq2, \rq3
50        vtrn.32          \rq4, \rq5
51        vtrn.32          \rq6, \rq7
52        vtrn.16          \r0,  \r1
53        vtrn.16          \r2,  \r3
54        vtrn.16          \r4,  \r5
55        vtrn.16          \r6,  \r7
56        vtrn.16          \r8,  \r9
57        vtrn.16          \r10, \r11
58        vtrn.16          \r12, \r13
59        vtrn.16          \r14, \r15
60.endm
61
62@ out1 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
63@ out2 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
64@ in/out are d registers
65.macro mbutterfly0 out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4, neg=0
66        vadd.s16        \tmpd1, \in1,  \in2
67        vsub.s16        \tmpd2, \in1,  \in2
68        vmull.s16       \tmpq3, \tmpd1, d0[0]
69        vmull.s16       \tmpq4, \tmpd2, d0[0]
70.if \neg > 0
71        vneg.s32        \tmpq3, \tmpq3
72.endif
73        vrshrn.s32      \out1, \tmpq3, #14
74        vrshrn.s32      \out2, \tmpq4, #14
75.endm
76
77@ Same as mbutterfly0 above, but treating the input in in2 as zero,
78@ writing the same output into both out1 and out2.
79.macro mbutterfly0_h out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4
80        vmull.s16       \tmpq3, \in1, d0[0]
81        vrshrn.s32      \out1,  \tmpq3, #14
82        vrshrn.s32      \out2,  \tmpq3, #14
83.endm
84
85@ out1,out2 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
86@ out3,out4 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
87@ Same as mbutterfly0, but with input being 2 q registers, output
88@ being 4 d registers.
89@ This can do with either 4 or 6 temporary q registers.
90.macro dmbutterfly0 out1, out2, out3, out4, in1, in2, tmpq1, tmpq2, tmpd11, tmpd12, tmpd21, tmpd22, tmpq3, tmpq4, tmpq5, tmpq6
91        vadd.s16        \tmpq1, \in1,  \in2
92        vsub.s16        \tmpq2, \in1,  \in2
93        vmull.s16       \tmpq3, \tmpd11, d0[0]
94        vmull.s16       \tmpq4, \tmpd12, d0[0]
95.ifb \tmpq5
96        vrshrn.s32      \out1, \tmpq3, #14
97        vrshrn.s32      \out2, \tmpq4, #14
98        vmull.s16       \tmpq3, \tmpd21, d0[0]
99        vmull.s16       \tmpq4, \tmpd22, d0[0]
100        vrshrn.s32      \out3, \tmpq3, #14
101        vrshrn.s32      \out4, \tmpq4, #14
102.else
103        vmull.s16       \tmpq5, \tmpd21, d0[0]
104        vmull.s16       \tmpq6, \tmpd22, d0[0]
105        vrshrn.s32      \out1, \tmpq3, #14
106        vrshrn.s32      \out2, \tmpq4, #14
107        vrshrn.s32      \out3, \tmpq5, #14
108        vrshrn.s32      \out4, \tmpq6, #14
109.endif
110.endm
111
112@ out1 = in1 * coef1 - in2 * coef2
113@ out2 = in1 * coef2 + in2 * coef1
114@ out are 2 q registers, in are 2 d registers
115.macro mbutterfly_l out1, out2, in1, in2, coef1, coef2
116        vmull.s16       \out1, \in1, \coef1
117        vmlsl.s16       \out1, \in2, \coef2
118        vmull.s16       \out2, \in1, \coef2
119        vmlal.s16       \out2, \in2, \coef1
120.endm
121
122@ out1,out2 = in1,in2 * coef1 - in3,in4 * coef2
123@ out3,out4 = in1,in2 * coef2 + in3,in4 * coef1
124@ out are 4 q registers, in are 4 d registers
125.macro dmbutterfly_l out1, out2, out3, out4, in1, in2, in3, in4, coef1, coef2
126        vmull.s16       \out1, \in1, \coef1
127        vmull.s16       \out2, \in2, \coef1
128        vmull.s16       \out3, \in1, \coef2
129        vmull.s16       \out4, \in2, \coef2
130        vmlsl.s16       \out1, \in3, \coef2
131        vmlsl.s16       \out2, \in4, \coef2
132        vmlal.s16       \out3, \in3, \coef1
133        vmlal.s16       \out4, \in4, \coef1
134.endm
135
136@ inout1 = (inout1 * coef1 - inout2 * coef2 + (1 << 13)) >> 14
137@ inout2 = (inout1 * coef2 + inout2 * coef1 + (1 << 13)) >> 14
138@ inout are 2 d registers, tmp are 2 q registers
139.macro mbutterfly inout1, inout2, coef1, coef2, tmp1, tmp2, neg=0
140        mbutterfly_l    \tmp1, \tmp2, \inout1, \inout2, \coef1, \coef2
141.if \neg > 0
142        vneg.s32        \tmp2, \tmp2
143.endif
144        vrshrn.s32      \inout1, \tmp1,  #14
145        vrshrn.s32      \inout2, \tmp2,  #14
146.endm
147
148@ Same as mbutterfly above, but treating the input in inout2 as zero
149.macro mbutterfly_h1 inout1, inout2, coef1, coef2, tmp1, tmp2
150        vmull.s16       \tmp1,   \inout1, \coef1
151        vmull.s16       \tmp2,   \inout1, \coef2
152        vrshrn.s32      \inout1, \tmp1,   #14
153        vrshrn.s32      \inout2, \tmp2,   #14
154.endm
155
156@ Same as mbutterfly above, but treating the input in inout1 as zero
157.macro mbutterfly_h2 inout1, inout2, coef1, coef2, tmp1, tmp2
158        vmull.s16       \tmp1,   \inout2, \coef2
159        vmull.s16       \tmp2,   \inout2, \coef1
160        vneg.s32        \tmp1,   \tmp1
161        vrshrn.s32      \inout2, \tmp2,   #14
162        vrshrn.s32      \inout1, \tmp1,   #14
163.endm
164
165@ inout1,inout2 = (inout1,inout2 * coef1 - inout3,inout4 * coef2 + (1 << 13)) >> 14
166@ inout3,inout4 = (inout1,inout2 * coef2 + inout3,inout4 * coef1 + (1 << 13)) >> 14
167@ inout are 4 d registers, tmp are 4 q registers
168.macro dmbutterfly inout1, inout2, inout3, inout4, coef1, coef2, tmp1, tmp2, tmp3, tmp4
169        dmbutterfly_l   \tmp1, \tmp2, \tmp3, \tmp4, \inout1, \inout2, \inout3, \inout4, \coef1, \coef2
170        vrshrn.s32      \inout1, \tmp1,  #14
171        vrshrn.s32      \inout2, \tmp2,  #14
172        vrshrn.s32      \inout3, \tmp3,  #14
173        vrshrn.s32      \inout4, \tmp4,  #14
174.endm
175
176@ out1 = in1 + in2
177@ out2 = in1 - in2
178.macro butterfly out1, out2, in1, in2
179        vadd.s16        \out1, \in1, \in2
180        vsub.s16        \out2, \in1, \in2
181.endm
182
183@ out1 = in1 - in2
184@ out2 = in1 + in2
185.macro butterfly_r out1, out2, in1, in2
186        vsub.s16        \out1, \in1, \in2
187        vadd.s16        \out2, \in1, \in2
188.endm
189
190@ out1 = (in1 + in2 + (1 << 13)) >> 14
191@ out2 = (in1 - in2 + (1 << 13)) >> 14
192@ out are 2 d registers, in are 2 q registers, tmp are 2 q registers
193.macro butterfly_n out1, out2, in1, in2, tmp1, tmp2
194        vadd.s32        \tmp1, \in1, \in2
195        vsub.s32        \tmp2, \in1, \in2
196        vrshrn.s32      \out1, \tmp1,  #14
197        vrshrn.s32      \out2, \tmp2,  #14
198.endm
199
200@ out1,out2 = (in1,in2 + in3,in4 + (1 << 13)) >> 14
201@ out3,out4 = (in1,in2 - in3,in4 + (1 << 13)) >> 14
202@ out are 4 d registers, in are 4 q registers, tmp are 4 q registers
203.macro dbutterfly_n out1, out2, out3, out4, in1, in2, in3, in4, tmp1, tmp2, tmp3, tmp4
204        vadd.s32        \tmp1, \in1, \in3
205        vadd.s32        \tmp2, \in2, \in4
206        vsub.s32        \tmp3, \in1, \in3
207        vsub.s32        \tmp4, \in2, \in4
208        vrshrn.s32      \out1, \tmp1,  #14
209        vrshrn.s32      \out2, \tmp2,  #14
210        vrshrn.s32      \out3, \tmp3,  #14
211        vrshrn.s32      \out4, \tmp4,  #14
212.endm
213
214
215.macro iwht4 c0, c1, c2, c3
216        vadd.i16        \c0,  \c0,  \c1
217        vsub.i16        d17,  \c2,  \c3
218        vsub.i16        d16,  \c0,  d17
219        vshr.s16        d16,  d16,  #1
220        vsub.i16        \c2,  d16,  \c1
221        vsub.i16        \c1,  d16,  \c3
222        vadd.i16        \c3,  d17,  \c2
223        vsub.i16        \c0,  \c0,  \c1
224.endm
225
226.macro idct4 c0, c1, c2, c3
227        vmull.s16       q13,  \c1,  d0[3]
228        vmull.s16       q11,  \c1,  d0[2]
229        vadd.i16        d16,  \c0,  \c2
230        vsub.i16        d17,  \c0,  \c2
231        vmlal.s16       q13,  \c3,  d0[2]
232        vmull.s16       q9,   d16,  d0[0]
233        vmull.s16       q10,  d17,  d0[0]
234        vmlsl.s16       q11,  \c3,  d0[3]
235        vrshrn.s32      d26,  q13,  #14
236        vrshrn.s32      d18,  q9,   #14
237        vrshrn.s32      d20,  q10,  #14
238        vrshrn.s32      d22,  q11,  #14
239        vadd.i16        \c0,  d18,  d26
240        vsub.i16        \c3,  d18,  d26
241        vadd.i16        \c1,  d20,  d22
242        vsub.i16        \c2,  d20,  d22
243.endm
244
245.macro iadst4 c0, c1, c2, c3
246        vmull.s16       q10,  \c0,  d1[0]
247        vmlal.s16       q10,  \c2,  d1[1]
248        vmlal.s16       q10,  \c3,  d1[2]
249        vmull.s16       q11,  \c0,  d1[2]
250        vmlsl.s16       q11,  \c2,  d1[0]
251        vsub.s16        \c0,  \c0,  \c2
252        vmlsl.s16       q11,  \c3,  d1[1]
253        vadd.s16        \c0,  \c0,  \c3
254        vmull.s16       q13,  \c1,  d1[3]
255        vmull.s16       q12,  \c0,  d1[3]
256        vadd.s32        q14,  q10,  q13
257        vadd.s32        q1,   q11,  q13
258        vrshrn.s32      \c0,  q14,  #14
259        vadd.s32        q10,  q10,  q11
260        vrshrn.s32      \c1,  q1,   #14
261        vsub.s32        q10,  q10,  q13
262        vrshrn.s32      \c2,  q12,  #14
263        vrshrn.s32      \c3,  q10,  #14
264.endm
265
266@ The public functions in this file have got the following signature:
267@ void itxfm_add(uint8_t *dst, ptrdiff_t stride, int16_t *block, int eob);
268
269.macro itxfm_func4x4 txfm1, txfm2
270function ff_vp9_\txfm1\()_\txfm2\()_4x4_add_neon, export=1
271.ifc \txfm1,\txfm2
272.ifc \txfm1,idct
273        movrel          r12, itxfm4_coeffs
274        vld1.16         {d0}, [r12,:64]
275.endif
276.ifc \txfm1,iadst
277        movrel          r12, iadst4_coeffs
278        vld1.16         {d1}, [r12,:64]
279.endif
280.else
281        movrel          r12, itxfm4_coeffs
282        vld1.16         {q0}, [r12,:128]
283.endif
284
285        vmov.i16        q15, #0
286.ifc \txfm1\()_\txfm2,idct_idct
287        cmp             r3,  #1
288        bne             1f
289        @ DC-only for idct/idct
290        vld1.16         {d4[]},   [r2,:16]
291        vmull.s16       q2,  d4,  d0[0]
292        vrshrn.s32      d4,  q2,  #14
293        vmull.s16       q2,  d4,  d0[0]
294        vrshrn.s32      d4,  q2,  #14
295        vst1.16         {d30[0]}, [r2,:16]
296        vdup.16         q2,  d4[0]
297        vmov            q3,  q2
298        b               2f
299.endif
300
3011:
302        vld1.16         {d4-d7},  [r2,:128]
303        vst1.16         {q15}, [r2,:128]!
304
305.ifc \txfm1,iwht
306        vshr.s16        q2,  q2,  #2
307        vshr.s16        q3,  q3,  #2
308.endif
309
310        \txfm1\()4      d4,  d5,  d6,  d7
311
312        vst1.16         {q15}, [r2,:128]!
313        @ Transpose 4x4 with 16 bit elements
314        vtrn.16         d4,  d5
315        vtrn.16         d6,  d7
316        vtrn.32         q2,  q3
317
318        \txfm2\()4      d4,  d5,  d6,  d7
3192:
320        vld1.32         {d0[]},   [r0,:32], r1
321        vld1.32         {d0[1]},  [r0,:32], r1
322.ifnc \txfm1,iwht
323        vrshr.s16       q2,  q2,  #4
324        vrshr.s16       q3,  q3,  #4
325.endif
326        vaddw.u8        q2,  q2,  d0
327        vld1.32         {d1[]},   [r0,:32], r1
328        vld1.32         {d1[1]},  [r0,:32], r1
329        vqmovun.s16     d0,  q2
330        sub             r0,  r0,  r1, lsl #2
331
332        vaddw.u8        q3,  q3,  d1
333        vst1.32         {d0[0]},  [r0,:32], r1
334        vqmovun.s16     d1,  q3
335
336        vst1.32         {d0[1]},  [r0,:32], r1
337        vst1.32         {d1[0]},  [r0,:32], r1
338        vst1.32         {d1[1]},  [r0,:32], r1
339
340        bx              lr
341endfunc
342.endm
343
344itxfm_func4x4 idct,  idct
345itxfm_func4x4 iadst, idct
346itxfm_func4x4 idct,  iadst
347itxfm_func4x4 iadst, iadst
348itxfm_func4x4 iwht,  iwht
349
350
351.macro idct8
352        dmbutterfly0    d16, d17, d24, d25, q8,  q12, q2, q4, d4, d5, d8, d9, q3, q2, q5, q4 @ q8 = t0a, q12 = t1a
353        dmbutterfly     d20, d21, d28, d29, d0[2], d0[3], q2,  q3,  q4,  q5 @ q10 = t2a, q14 = t3a
354        dmbutterfly     d18, d19, d30, d31, d1[0], d1[1], q2,  q3,  q4,  q5 @ q9  = t4a, q15 = t7a
355        dmbutterfly     d26, d27, d22, d23, d1[2], d1[3], q2,  q3,  q4,  q5 @ q13 = t5a, q11 = t6a
356
357        butterfly       q2,  q14, q8,  q14 @ q2 = t0, q14 = t3
358        butterfly       q3,  q10, q12, q10 @ q3 = t1, q10 = t2
359        butterfly       q4,  q13, q9,  q13 @ q4 = t4, q13 = t5a
360        butterfly       q5,  q11, q15, q11 @ q5 = t7, q11 = t6a
361
362        butterfly       q8,  q15, q2,  q5  @ q8 = out[0], q15 = out[7]
363
364        dmbutterfly0    d4,  d5,  d10, d11, q11, q13, q9,  q13, d18, d19, d26, d27, q2,  q5, q11, q12 @ q2 = t6, q5 = t5
365
366        butterfly       q11, q12, q14, q4  @ q11 = out[3], q12 = out[4]
367        butterfly       q9,  q14, q3,  q2  @ q9 = out[1],  q14 = out[6]
368        butterfly_r     q13, q10, q10, q5  @ q13 = out[5], q10 = out[2]
369.endm
370
371.macro iadst8
372        dmbutterfly_l   q4,  q5,  q2,  q3,  d30, d31, d16, d17, d2[1], d2[0] @ q4,q5  = t1a, q2,q3 = t0a
373        dmbutterfly_l   q8,  q15, q6,  q7,  d22, d23, d24, d25, d3[1], d3[0] @ q8,q15 = t5a, q6,q7 = t4a
374
375        dbutterfly_n    d22, d23, d4,  d5,  q2,  q3,  q6,  q7,  q11, q12, q2,  q3 @ q11 = t0, q2 = t4
376
377        dbutterfly_n    d24, d25, d6,  d7,  q4,  q5,  q8,  q15, q12, q3,  q6,  q7 @ q12 = t1, q3 = t5
378
379        dmbutterfly_l   q6,  q7,  q4,  q5,  d26, d27, d20, d21, d2[3], d2[2] @ q6,q7 = t3a, q4,q5 = t2a
380        dmbutterfly_l   q10, q13, q8,  q15, d18, d19, d28, d29, d3[3], d3[2] @ q10,q13 = t7a, q8,q15 = t6a
381
382        dbutterfly_n    d18, d19, d8,  d9,  q4,  q5,  q8,  q15, q9,  q14, q4, q5 @ q9 = t2, q4 = t6
383        dbutterfly_n    d16, d17, d12, d13, q6,  q7,  q10, q13, q8,  q15, q6, q7 @ q8 = t3, q6 = t7
384
385        butterfly       q15, q12, q12, q8 @ q15 = -out[7], q12 = t3
386        vneg.s16        q15, q15          @ q15 = out[7]
387        butterfly       q8,  q9,  q11, q9 @ q8 = out[0], q9 = t2
388
389        dmbutterfly_l   q10, q11, q5,  q7,  d4,  d5,  d6,  d7,  d0[2], d0[3] @ q10,q11 = t5a, q5,q7 = t4a
390        dmbutterfly_l   q2,  q3,  q13, q14, d12, d13, d8,  d9,  d0[3], d0[2] @ q2,q3 = t6a, q13,q14 = t7a
391
392        dbutterfly_n    d28, d29, d8,  d9,  q10, q11, q13, q14, q4,  q6,  q10, q11 @ q14 = out[6], q4 = t7
393
394        dmbutterfly0    d22, d23, d24, d25, q9,  q12, q6, q13, d12, d13, d26, d27, q9, q10 @ q11 = -out[3], q12 = out[4]
395        vneg.s16        q11, q11      @ q11 = out[3]
396
397        dbutterfly_n    d18, d19, d4,  d5,  q5,  q7,  q2,  q3,  q9, q10, q2,  q3 @ q9 = -out[1], q2 = t6
398        vneg.s16        q9,  q9       @ q9 = out[1]
399
400        dmbutterfly0    d20, d21, d26, d27, q2,  q4,  q3, q5,  d6,  d7,  d10, d11, q6,  q7 @ q10 = out[2], q13 = -out[5]
401        vneg.s16        q13, q13      @ q13 = out[5]
402.endm
403
404
405.macro itxfm_func8x8 txfm1, txfm2
406function ff_vp9_\txfm1\()_\txfm2\()_8x8_add_neon, export=1
407        @ Push q4-q7 if iadst is used, idct requires
408        @ a few scratch registers less, so only push q4-q5
409        @ if only idct is involved.
410        @ The iadst also uses a few coefficients from
411        @ idct, so those always need to be loaded.
412.ifc \txfm1\()_\txfm2,idct_idct
413        movrel          r12, idct_coeffs
414        vpush           {q4-q5}
415.else
416        movrel          r12, iadst8_coeffs
417        vld1.16         {q1}, [r12,:128]!
418        vpush           {q4-q7}
419.endif
420        vld1.16         {q0}, [r12,:128]
421
422        vmov.i16        q2, #0
423        vmov.i16        q3, #0
424
425.ifc \txfm1\()_\txfm2,idct_idct
426        cmp             r3,  #1
427        bne             1f
428        @ DC-only for idct/idct
429        vld1.16         {d16[]}, [r2,:16]
430        vmull.s16       q8,  d16, d0[0]
431        vrshrn.s32      d16, q8,  #14
432        vmull.s16       q8,  d16, d0[0]
433        vrshrn.s32      d16, q8,  #14
434        vdup.16         q8,  d16[0]
435        vmov            q9,  q8
436        vmov            q10, q8
437        vmov            q11, q8
438        vmov            q12, q8
439        vmov            q13, q8
440        vmov            q14, q8
441        vmov            q15, q8
442        vst1.16         {d4[0]}, [r2,:16]
443        b               2f
444.endif
4451:
446        vld1.16         {q8-q9},    [r2,:128]!
447        vld1.16         {q10-q11},  [r2,:128]!
448        vld1.16         {q12-q13},  [r2,:128]!
449        vld1.16         {q14-q15},  [r2,:128]!
450        sub             r2,  r2,  #128
451        vst1.16         {q2-q3}, [r2,:128]!
452        vst1.16         {q2-q3}, [r2,:128]!
453        vst1.16         {q2-q3}, [r2,:128]!
454        vst1.16         {q2-q3}, [r2,:128]!
455
456        \txfm1\()8
457
458        @ Transpose 8x8 with 16 bit elements
459        vswp            d17, d24
460        vswp            d19, d26
461        vswp            d21, d28
462        vswp            d23, d30
463        transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15
464
465        \txfm2\()8
4662:
467        mov             r3,  r0
468        @ Add into the destination
469        vld1.8          {d4},  [r0,:64], r1
470        vrshr.s16       q8,  q8,  #5
471        vld1.8          {d5},  [r0,:64], r1
472        vrshr.s16       q9,  q9,  #5
473        vld1.8          {d6},  [r0,:64], r1
474        vrshr.s16       q10, q10, #5
475        vaddw.u8        q8,  q8,  d4
476        vld1.8          {d7},  [r0,:64], r1
477        vrshr.s16       q11, q11, #5
478        vaddw.u8        q9,  q9,  d5
479        vld1.8          {d8},  [r0,:64], r1
480        vrshr.s16       q12, q12, #5
481        vaddw.u8        q10, q10, d6
482        vqmovun.s16     d4,  q8
483        vld1.8          {d9},  [r0,:64], r1
484        vrshr.s16       q13, q13, #5
485        vaddw.u8        q11, q11, d7
486        vqmovun.s16     d5,  q9
487        vld1.8          {d10}, [r0,:64], r1
488        vrshr.s16       q14, q14, #5
489        vaddw.u8        q12, q12, d8
490        vqmovun.s16     d6,  q10
491        vld1.8          {d11}, [r0,:64], r1
492        vrshr.s16       q15, q15, #5
493        vaddw.u8        q13, q13, d9
494        vqmovun.s16     d7,  q11
495
496
497        vst1.8          {d4},  [r3,:64], r1
498        vaddw.u8        q14, q14, d10
499        vst1.8          {d5},  [r3,:64], r1
500        vqmovun.s16     d8,  q12
501        vst1.8          {d6},  [r3,:64], r1
502        vaddw.u8        q15, q15, d11
503        vst1.8          {d7},  [r3,:64], r1
504        vqmovun.s16     d9,  q13
505        vst1.8          {d8},  [r3,:64], r1
506        vqmovun.s16     d10, q14
507        vst1.8          {d9},  [r3,:64], r1
508        vqmovun.s16     d11, q15
509
510        vst1.8          {d10}, [r3,:64], r1
511        vst1.8          {d11}, [r3,:64], r1
512
513.ifc \txfm1\()_\txfm2,idct_idct
514        vpop            {q4-q5}
515.else
516        vpop            {q4-q7}
517.endif
518        bx              lr
519endfunc
520.endm
521
522itxfm_func8x8 idct,  idct
523itxfm_func8x8 iadst, idct
524.ltorg
525itxfm_func8x8 idct,  iadst
526itxfm_func8x8 iadst, iadst
527
528
529function idct16x16_dc_add_neon
530        movrel          r12, idct_coeffs
531        vld1.16         {d0}, [r12,:64]
532
533        vmov.i16        q2,  #0
534
535        vld1.16         {d16[]}, [r2,:16]
536        vmull.s16       q8,  d16, d0[0]
537        vrshrn.s32      d16, q8,  #14
538        vmull.s16       q8,  d16, d0[0]
539        vrshrn.s32      d16, q8,  #14
540        vdup.16         q8,  d16[0]
541        vst1.16         {d4[0]}, [r2,:16]
542
543        vrshr.s16       q8,  q8,  #6
544
545        mov             r3,  r0
546        mov             r12, #16
5471:
548        @ Loop to add the constant from q8 into all 16x16 outputs
549        subs            r12, r12, #2
550        vld1.8          {q2},  [r0,:128], r1
551        vaddw.u8        q10, q8,  d4
552        vld1.8          {q3},  [r0,:128], r1
553        vaddw.u8        q11, q8,  d5
554        vaddw.u8        q12, q8,  d6
555        vaddw.u8        q13, q8,  d7
556        vqmovun.s16     d4,  q10
557        vqmovun.s16     d5,  q11
558        vqmovun.s16     d6,  q12
559        vst1.8          {q2},  [r3,:128], r1
560        vqmovun.s16     d7,  q13
561        vst1.8          {q3},  [r3,:128], r1
562        bne             1b
563
564        bx              lr
565endfunc
566.ltorg
567
568.macro idct16_end
569        butterfly       d18, d7,  d4,  d7                @ d18 = t0a,  d7  = t7a
570        butterfly       d19, d22, d5,  d22               @ d19 = t1a,  d22 = t6
571        butterfly       d4,  d26, d20, d26               @ d4  = t2a,  d26 = t5
572        butterfly       d5,  d6,  d28, d6                @ d5  = t3a,  d6  = t4
573        butterfly       d20, d28, d16, d24               @ d20 = t8a,  d28 = t11a
574        butterfly       d24, d21, d23, d21               @ d24 = t9,   d21 = t10
575        butterfly       d23, d27, d25, d27               @ d23 = t14,  d27 = t13
576        butterfly       d25, d29, d29, d17               @ d25 = t15a, d29 = t12a
577
578        mbutterfly0     d27, d21, d27, d21, d16, d30, q8, q15 @ d27 = t13a, d21 = t10a
579        mbutterfly0     d29, d28, d29, d28, d16, d30, q8, q15 @ d29 = t12,  d28 = t11
580
581        vswp            d27, d29                         @ d27 = t12, d29 = t13a
582        vswp            d28, d27                         @ d28 = t12, d27 = t11
583        butterfly       d16, d31, d18, d25               @ d16 = out[0], d31 = out[15]
584        butterfly       d17, d30, d19, d23               @ d17 = out[1], d30 = out[14]
585        butterfly_r     d25, d22, d22, d24               @ d25 = out[9], d22 = out[6]
586        butterfly       d23, d24, d7,  d20               @ d23 = out[7], d24 = out[8]
587        butterfly       d18, d29, d4,  d29               @ d18 = out[2], d29 = out[13]
588        butterfly       d19, d28, d5,  d28               @ d19 = out[3], d28 = out[12]
589        vmov            d4,  d21                         @ d4  = t10a
590        butterfly       d20, d27, d6,  d27               @ d20 = out[4], d27 = out[11]
591        butterfly       d21, d26, d26, d4                @ d21 = out[5], d26 = out[10]
592        bx              lr
593.endm
594
595function idct16
596        mbutterfly0     d16, d24, d16, d24, d4, d6,  q2,  q3 @ d16 = t0a,  d24 = t1a
597        mbutterfly      d20, d28, d0[2], d0[3], q2,  q3  @ d20 = t2a,  d28 = t3a
598        mbutterfly      d18, d30, d1[0], d1[1], q2,  q3  @ d18 = t4a,  d30 = t7a
599        mbutterfly      d26, d22, d1[2], d1[3], q2,  q3  @ d26 = t5a,  d22 = t6a
600        mbutterfly      d17, d31, d2[0], d2[1], q2,  q3  @ d17 = t8a,  d31 = t15a
601        mbutterfly      d25, d23, d2[2], d2[3], q2,  q3  @ d25 = t9a,  d23 = t14a
602        mbutterfly      d21, d27, d3[0], d3[1], q2,  q3  @ d21 = t10a, d27 = t13a
603        mbutterfly      d29, d19, d3[2], d3[3], q2,  q3  @ d29 = t11a, d19 = t12a
604
605        butterfly       d4,  d28, d16, d28               @ d4  = t0,   d28 = t3
606        butterfly       d5,  d20, d24, d20               @ d5  = t1,   d20 = t2
607        butterfly       d6,  d26, d18, d26               @ d6  = t4,   d26 = t5
608        butterfly       d7,  d22, d30, d22               @ d7  = t7,   d22 = t6
609        butterfly       d16, d25, d17, d25               @ d16 = t8,   d25 = t9
610        butterfly       d24, d21, d29, d21               @ d24 = t11,  d21 = t10
611        butterfly       d17, d27, d19, d27               @ d17 = t12,  d27 = t13
612        butterfly       d29, d23, d31, d23               @ d29 = t15,  d23 = t14
613
614        mbutterfly0     d22, d26, d22, d26, d18, d30, q9,  q15  @ d22 = t6a, d26 = t5a
615        mbutterfly      d23, d25, d0[2], d0[3], q9,  q15        @ d23 = t9a,  d25 = t14a
616        mbutterfly      d27, d21, d0[2], d0[3], q9,  q15, neg=1 @ d27 = t13a, d21 = t10a
617        idct16_end
618endfunc
619
620function idct16_half
621        mbutterfly0_h   d16, d24, d16, d24, d4, d6,  q2,  q3 @ d16 = t0a,  d24 = t1a
622        mbutterfly_h1   d20, d28, d0[2], d0[3], q2,  q3  @ d20 = t2a,  d28 = t3a
623        mbutterfly_h1   d18, d30, d1[0], d1[1], q2,  q3  @ d18 = t4a,  d30 = t7a
624        mbutterfly_h2   d26, d22, d1[2], d1[3], q2,  q3  @ d26 = t5a,  d22 = t6a
625        mbutterfly_h1   d17, d31, d2[0], d2[1], q2,  q3  @ d17 = t8a,  d31 = t15a
626        mbutterfly_h2   d25, d23, d2[2], d2[3], q2,  q3  @ d25 = t9a,  d23 = t14a
627        mbutterfly_h1   d21, d27, d3[0], d3[1], q2,  q3  @ d21 = t10a, d27 = t13a
628        mbutterfly_h2   d29, d19, d3[2], d3[3], q2,  q3  @ d29 = t11a, d19 = t12a
629
630        butterfly       d4,  d28, d16, d28               @ d4  = t0,   d28 = t3
631        butterfly       d5,  d20, d24, d20               @ d5  = t1,   d20 = t2
632        butterfly       d6,  d26, d18, d26               @ d6  = t4,   d26 = t5
633        butterfly       d7,  d22, d30, d22               @ d7  = t7,   d22 = t6
634        butterfly       d16, d25, d17, d25               @ d16 = t8,   d25 = t9
635        butterfly       d24, d21, d29, d21               @ d24 = t11,  d21 = t10
636        butterfly       d17, d27, d19, d27               @ d17 = t12,  d27 = t13
637        butterfly       d29, d23, d31, d23               @ d29 = t15,  d23 = t14
638
639        mbutterfly0     d22, d26, d22, d26, d18, d30, q9,  q15  @ d22 = t6a, d26 = t5a
640        mbutterfly      d23, d25, d0[2], d0[3], q9,  q15        @ d23 = t9a,  d25 = t14a
641        mbutterfly      d27, d21, d0[2], d0[3], q9,  q15, neg=1 @ d27 = t13a, d21 = t10a
642        idct16_end
643endfunc
644
645function idct16_quarter
646        vmull.s16       q12, d19, d3[3]
647        vmull.s16       q2,  d17, d2[0]
648        vmull.s16       q3,  d18, d1[1]
649        vmull.s16       q15, d18, d1[0]
650        vneg.s32        q12, q12
651        vmull.s16       q14, d17, d2[1]
652        vmull.s16       q13, d19, d3[2]
653        vmull.s16       q11, d16, d0[0]
654        vrshrn.s32      d24, q12, #14
655        vrshrn.s32      d16, q2,  #14
656        vrshrn.s32      d7,  q3,  #14
657        vrshrn.s32      d6,  q15, #14
658        vrshrn.s32      d29, q14, #14
659        vrshrn.s32      d17, q13, #14
660        vrshrn.s32      d28, q11, #14
661
662        mbutterfly_l    q10, q11, d17, d24, d0[2], d0[3]
663        mbutterfly_l    q9,  q15, d29, d16, d0[2], d0[3]
664        vneg.s32        q11, q11
665        vrshrn.s32      d27, q10, #14
666        vrshrn.s32      d21, q11, #14
667        vrshrn.s32      d23, q9,  #14
668        vrshrn.s32      d25, q15, #14
669        vmov            d4,  d28
670        vmov            d5,  d28
671        mbutterfly0     d22, d26, d7,  d6,  d18, d30, q9,  q15
672        vmov            d20, d28
673        idct16_end
674endfunc
675
676function iadst16
677        movrel          r12, iadst16_coeffs
678        vld1.16         {q0-q1}, [r12,:128]
679
680        mbutterfly_l    q3,  q2,  d31, d16, d0[1], d0[0] @ q3  = t1,   q2  = t0
681        mbutterfly_l    q5,  q4,  d23, d24, d1[1], d1[0] @ q5  = t9,   q4  = t8
682        butterfly_n     d31, d24, q3,  q5,  q6,  q5      @ d31 = t1a,  d24 = t9a
683        mbutterfly_l    q7,  q6,  d29, d18, d0[3], d0[2] @ q7  = t3,   q6  = t2
684        butterfly_n     d16, d23, q2,  q4,  q3,  q4      @ d16 = t0a,  d23 = t8a
685
686        mbutterfly_l    q3,  q2,  d21, d26, d1[3], d1[2] @ q3  = t11,  q2  = t10
687        butterfly_n     d29, d26, q7,  q3,  q4,  q3      @ d29 = t3a,  d26 = t11a
688        mbutterfly_l    q5,  q4,  d27, d20, d2[1], d2[0] @ q5  = t5,   q4  = t4
689        butterfly_n     d18, d21, q6,  q2,  q3,  q2      @ d18 = t2a,  d21 = t10a
690
691        mbutterfly_l    q7,  q6,  d19, d28, d3[1], d3[0] @ q7  = t13,  q6  = t12
692        butterfly_n     d20, d28, q5,  q7,  q2,  q7      @ d20 = t5a,  d28 = t13a
693        mbutterfly_l    q3,  q2,  d25, d22, d2[3], d2[2] @ q3  = t7,   q2  = t6
694        butterfly_n     d27, d19, q4,  q6,  q5,  q6      @ d27 = t4a,  d19 = t12a
695
696        mbutterfly_l    q5,  q4,  d17, d30, d3[3], d3[2] @ q5  = t15,  q4  = t14
697        movrel          r12, idct_coeffs
698        vld1.16         {q0}, [r12,:128]
699        butterfly_n     d22, d30, q3,  q5,  q6,  q5      @ d22 = t7a,  d30 = t15a
700        mbutterfly_l    q7,  q6,  d23, d24, d1[0], d1[1] @ q7  = t9,   q6  = t8
701        butterfly_n     d25, d17, q2,  q4,  q3,  q4      @ d25 = t6a,  d17 = t14a
702
703        mbutterfly_l    q2,  q3,  d28, d19, d1[1], d1[0] @ q2  = t12,  q3  = t13
704        butterfly_n     d23, d19, q6,  q2,  q4,  q2      @ d23 = t8a,  d19 = t12a
705        mbutterfly_l    q5,  q4,  d21, d26, d1[2], d1[3] @ q5  = t11,  q4  = t10
706        butterfly_r     d4,  d27, d16, d27               @ d4  = t4,   d27 = t0
707        butterfly_n     d24, d28, q7,  q3,  q6,  q3      @ d24 = t9a,  d28 = t13a
708
709        mbutterfly_l    q6,  q7,  d30, d17, d1[3], d1[2] @ q6  = t14,  q7  = t15
710        butterfly_r     d5,  d20, d31, d20               @ d5  = t5,   d20 = t1
711        butterfly_n     d21, d17, q4,  q6,  q3,  q6      @ d21 = t10a, d17 = t14a
712        butterfly_n     d26, d30, q5,  q7,  q4,  q7      @ d26 = t11a, d30 = t15a
713
714        butterfly_r     d6,  d25, d18, d25               @ d6  = t6,   d25 = t2
715        butterfly_r     d7,  d22, d29, d22               @ d7  = t7,   d22 = t3
716
717        mbutterfly_l    q5,  q4,  d19, d28, d0[2], d0[3] @ q5  = t13,  q4  = t12
718        mbutterfly_l    q6,  q7,  d30, d17, d0[3], d0[2] @ q6  = t14,  q7  = t15
719
720        butterfly_n     d18, d30, q4,  q6,  q8,  q6      @ d18 = out[2],   d30 = t14a
721        butterfly_n     d29, d17, q5,  q7,  q6,  q7      @ d29 = -out[13], d17 = t15a
722        vneg.s16        d29, d29                         @ d29 = out[13]
723
724        mbutterfly_l    q5,  q4,  d4,  d5,  d0[2], d0[3] @ q5  = t5a,  q4  = t4a
725        mbutterfly_l    q6,  q7,  d7,  d6,  d0[3], d0[2] @ q6  = t6a,  q7  = t7a
726
727        butterfly       d2,  d6,  d27, d25               @ d2 = out[0], d6 = t2a
728        butterfly       d3,  d7,  d23, d21               @ d3 =-out[1], d7 = t10
729
730        butterfly_n     d19, d31, q4,  q6,  q2,  q4      @ d19 = -out[3],  d31 = t6
731        vneg.s16        d19, d19                         @ d19 = out[3]
732        butterfly_n     d28, d16, q5,  q7,  q2,  q5      @ d28 = out[12],  d16 = t7
733
734        butterfly       d5,  d8,  d20, d22               @ d5 =-out[15],d8 = t3a
735        butterfly       d4,  d9,  d24, d26               @ d4 = out[14],d9 = t11
736
737        mbutterfly0     d23, d24, d6,  d8,  d10, d11, q6,  q7, 1 @ d23 = out[7], d24 = out[8]
738        mbutterfly0     d20, d27, d16, d31, d10, d11, q6,  q7    @ d20 = out[4], d27 = out[11]
739        mbutterfly0     d22, d25, d9,  d7,  d10, d11, q6,  q7    @ d22 = out[6], d25 = out[9]
740        mbutterfly0     d21, d26, d30, d17, d10, d11, q6,  q7, 1 @ d21 = out[5], d26 = out[10]
741
742        vneg.s16        d31, d5                          @ d31 = out[15]
743        vneg.s16        d17, d3                          @ d17 = out[1]
744
745        vmov            d16, d2
746        vmov            d30, d4
747        bx              lr
748endfunc
749
750.macro load_add_store coef0, coef1, coef2, coef3
751        vrshr.s16       \coef0, \coef0, #6
752        vrshr.s16       \coef1, \coef1, #6
753
754        vld1.32         {d4[]},   [r0,:32], r1
755        vld1.32         {d4[1]},  [r3,:32], r1
756        vrshr.s16       \coef2, \coef2, #6
757        vrshr.s16       \coef3, \coef3, #6
758        vld1.32         {d5[]},   [r0,:32], r1
759        vld1.32         {d5[1]},  [r3,:32], r1
760        vaddw.u8        \coef0, \coef0, d4
761        vld1.32         {d6[]},   [r0,:32], r1
762        vld1.32         {d6[1]},  [r3,:32], r1
763        vaddw.u8        \coef1, \coef1, d5
764        vld1.32         {d7[]},   [r0,:32], r1
765        vld1.32         {d7[1]},  [r3,:32], r1
766
767        vqmovun.s16     d4,  \coef0
768        vqmovun.s16     d5,  \coef1
769        sub             r0,  r0,  r1, lsl #2
770        sub             r3,  r3,  r1, lsl #2
771        vaddw.u8        \coef2, \coef2, d6
772        vaddw.u8        \coef3, \coef3, d7
773        vst1.32         {d4[0]},  [r0,:32], r1
774        vst1.32         {d4[1]},  [r3,:32], r1
775        vqmovun.s16     d6,  \coef2
776        vst1.32         {d5[0]},  [r0,:32], r1
777        vst1.32         {d5[1]},  [r3,:32], r1
778        vqmovun.s16     d7,  \coef3
779
780        vst1.32         {d6[0]},  [r0,:32], r1
781        vst1.32         {d6[1]},  [r3,:32], r1
782        vst1.32         {d7[0]},  [r0,:32], r1
783        vst1.32         {d7[1]},  [r3,:32], r1
784.endm
785
786.macro itxfm16_1d_funcs txfm
787@ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
788@ transpose into a horizontal 16x4 slice and store.
789@ r0 = dst (temp buffer)
790@ r1 = slice offset
791@ r2 = src
792function \txfm\()16_1d_4x16_pass1_neon
793        push            {lr}
794
795        mov             r12, #32
796        vmov.s16        q2,  #0
797.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
798        vld1.16         {d\i}, [r2,:64]
799        vst1.16         {d4},  [r2,:64], r12
800.endr
801
802        bl              \txfm\()16
803
804        @ Do four 4x4 transposes. Originally, d16-d31 contain the
805        @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
806        @ contain the transposed 4x4 blocks.
807        transpose16_q_4x_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
808
809        @ Store the transposed 4x4 blocks horizontally.
810        cmp             r1,  #12
811        beq             1f
812.irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
813        vst1.16         {d\i}, [r0,:64]!
814.endr
815        pop             {pc}
8161:
817        @ Special case: For the last input column (r1 == 12),
818        @ which would be stored as the last row in the temp buffer,
819        @ don't store the first 4x4 block, but keep it in registers
820        @ for the first slice of the second pass (where it is the
821        @ last 4x4 block).
822        add             r0,  r0,  #8
823        vst1.16         {d20}, [r0,:64]!
824        vst1.16         {d24}, [r0,:64]!
825        vst1.16         {d28}, [r0,:64]!
826        add             r0,  r0,  #8
827        vst1.16         {d21}, [r0,:64]!
828        vst1.16         {d25}, [r0,:64]!
829        vst1.16         {d29}, [r0,:64]!
830        add             r0,  r0,  #8
831        vst1.16         {d22}, [r0,:64]!
832        vst1.16         {d26}, [r0,:64]!
833        vst1.16         {d30}, [r0,:64]!
834        add             r0,  r0,  #8
835        vst1.16         {d23}, [r0,:64]!
836        vst1.16         {d27}, [r0,:64]!
837        vst1.16         {d31}, [r0,:64]!
838        vmov            d28, d16
839        vmov            d29, d17
840        vmov            d30, d18
841        vmov            d31, d19
842        pop             {pc}
843endfunc
844
845@ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
846@ load the destination pixels (from a similar 4x16 slice), add and store back.
847@ r0 = dst
848@ r1 = dst stride
849@ r2 = src (temp buffer)
850@ r3 = slice offset
851function \txfm\()16_1d_4x16_pass2_neon
852        push            {lr}
853        mov             r12, #32
854.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
855        vld1.16         {d\i}, [r2,:64], r12
856.endr
857        cmp             r3,  #0
858        beq             1f
859.irp i, 28, 29, 30, 31
860        vld1.16         {d\i}, [r2,:64], r12
861.endr
8621:
863
864        add             r3,  r0,  r1
865        lsl             r1,  r1,  #1
866        bl              \txfm\()16
867
868        load_add_store  q8,  q9,  q10, q11
869        load_add_store  q12, q13, q14, q15
870
871        pop             {pc}
872endfunc
873.endm
874
875itxfm16_1d_funcs idct
876itxfm16_1d_funcs iadst
877
878@ This is the minimum eob value for each subpartition, in increments of 4
879const min_eob_idct_idct_16, align=4
880        .short  0, 10, 38, 89
881endconst
882
883.macro itxfm_func16x16 txfm1, txfm2
884function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
885.ifc \txfm1\()_\txfm2,idct_idct
886        cmp             r3,  #1
887        beq             idct16x16_dc_add_neon
888.endif
889        push            {r4-r8,lr}
890.ifnc \txfm1\()_\txfm2,idct_idct
891        vpush           {q4-q7}
892.endif
893
894        @ Align the stack, allocate a temp buffer
895T       mov             r7,  sp
896T       and             r7,  r7,  #15
897A       and             r7,  sp,  #15
898        add             r7,  r7,  #512
899        sub             sp,  sp,  r7
900
901        mov             r4,  r0
902        mov             r5,  r1
903        mov             r6,  r2
904
905.ifc \txfm1,idct
906        movrel          r12, idct_coeffs
907        vld1.16         {q0-q1}, [r12,:128]
908.endif
909
910.ifc \txfm1\()_\txfm2,idct_idct
911        cmp             r3,  #10
912        ble             idct16x16_quarter_add_neon
913        cmp             r3,  #38
914        ble             idct16x16_half_add_neon
915
916        movrel          r8,  min_eob_idct_idct_16 + 2
917.endif
918
919.irp i, 0, 4, 8, 12
920        add             r0,  sp,  #(\i*32)
921.ifc \txfm1\()_\txfm2,idct_idct
922.if \i > 0
923        ldrh_post       r1,  r8,  #2
924        cmp             r3,  r1
925        it              le
926        movle           r1,  #(16 - \i)/4
927        ble             1f
928.endif
929.endif
930        mov             r1,  #\i
931        add             r2,  r6,  #(\i*2)
932        bl              \txfm1\()16_1d_4x16_pass1_neon
933.endr
934
935.ifc \txfm1\()_\txfm2,idct_idct
936        b               3f
9371:
938        @ For all-zero slices in pass 1, set d28-d31 to zero, for the in-register
939        @ passthrough of coefficients to pass 2 and clear the end of the temp buffer
940        vmov.i16        q14, #0
941        vmov.i16        q15, #0
9422:
943        subs            r1,  r1,  #1
944.rept 4
945        vst1.16         {q14-q15}, [r0,:128]!
946.endr
947        bne             2b
9483:
949.endif
950
951.ifc \txfm1\()_\txfm2,iadst_idct
952        movrel          r12, idct_coeffs
953        vld1.16         {q0-q1}, [r12,:128]
954.endif
955.irp i, 0, 4, 8, 12
956        add             r0,  r4,  #(\i)
957        mov             r1,  r5
958        add             r2,  sp,  #(\i*2)
959        mov             r3,  #\i
960        bl              \txfm2\()16_1d_4x16_pass2_neon
961.endr
962
963        add             sp,  sp,  r7
964.ifnc \txfm1\()_\txfm2,idct_idct
965        vpop            {q4-q7}
966.endif
967        pop             {r4-r8,pc}
968endfunc
969.endm
970
971itxfm_func16x16 idct,  idct
972itxfm_func16x16 iadst, idct
973itxfm_func16x16 idct,  iadst
974itxfm_func16x16 iadst, iadst
975.ltorg
976
977function idct16_1d_4x16_pass1_quarter_neon
978        push            {lr}
979        mov             r12, #32
980        vmov.s16        q2, #0
981.irp i, 16, 17, 18, 19
982        vld1.16         {d\i}, [r2,:64]
983        vst1.16         {d4},  [r2,:64], r12
984.endr
985
986        bl              idct16_quarter
987
988        @ Do four 4x4 transposes. Originally, d16-d31 contain the
989        @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
990        @ contain the transposed 4x4 blocks.
991        transpose16_q_4x_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
992
993        @ Store the transposed 4x4 blocks horizontally.
994        @ The first 4x4 block is kept in registers for the second pass,
995        @ store the rest in the temp buffer.
996        add             r0,  r0,  #8
997        vst1.16         {d20}, [r0,:64]!
998        vst1.16         {d24}, [r0,:64]!
999        vst1.16         {d28}, [r0,:64]!
1000        add             r0,  r0,  #8
1001        vst1.16         {d21}, [r0,:64]!
1002        vst1.16         {d25}, [r0,:64]!
1003        vst1.16         {d29}, [r0,:64]!
1004        add             r0,  r0,  #8
1005        vst1.16         {d22}, [r0,:64]!
1006        vst1.16         {d26}, [r0,:64]!
1007        vst1.16         {d30}, [r0,:64]!
1008        add             r0,  r0,  #8
1009        vst1.16         {d23}, [r0,:64]!
1010        vst1.16         {d27}, [r0,:64]!
1011        vst1.16         {d31}, [r0,:64]!
1012        pop             {pc}
1013endfunc
1014
1015function idct16_1d_4x16_pass2_quarter_neon
1016        push            {lr}
1017        @ Only load the top 4 lines, and only do it for the later slices.
1018        @ For the first slice, d16-d19 is kept in registers from the first pass.
1019        cmp             r3,  #0
1020        beq             1f
1021        mov             r12, #32
1022.irp i, 16, 17, 18, 19
1023        vld1.16         {d\i}, [r2,:64], r12
1024.endr
10251:
1026
1027        add             r3,  r0,  r1
1028        lsl             r1,  r1,  #1
1029        bl              idct16_quarter
1030
1031        load_add_store  q8,  q9,  q10, q11
1032        load_add_store  q12, q13, q14, q15
1033
1034        pop             {pc}
1035endfunc
1036
1037function idct16_1d_4x16_pass1_half_neon
1038        push            {lr}
1039        mov             r12, #32
1040        vmov.s16        q2, #0
1041.irp i, 16, 17, 18, 19, 20, 21, 22, 23
1042        vld1.16         {d\i}, [r2,:64]
1043        vst1.16         {d4},  [r2,:64], r12
1044.endr
1045
1046        bl              idct16_half
1047
1048        @ Do four 4x4 transposes. Originally, d16-d31 contain the
1049        @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
1050        @ contain the transposed 4x4 blocks.
1051        transpose16_q_4x_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
1052
1053        @ Store the transposed 4x4 blocks horizontally.
1054        cmp             r1,  #4
1055        beq             1f
1056.irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
1057        vst1.16         {d\i}, [r0,:64]!
1058.endr
1059        pop             {pc}
10601:
1061        @ Special case: For the second input column (r1 == 4),
1062        @ which would be stored as the second row in the temp buffer,
1063        @ don't store the first 4x4 block, but keep it in registers
1064        @ for the first slice of the second pass (where it is the
1065        @ second 4x4 block).
1066        add             r0,  r0,  #8
1067        vst1.16         {d20}, [r0,:64]!
1068        vst1.16         {d24}, [r0,:64]!
1069        vst1.16         {d28}, [r0,:64]!
1070        add             r0,  r0,  #8
1071        vst1.16         {d21}, [r0,:64]!
1072        vst1.16         {d25}, [r0,:64]!
1073        vst1.16         {d29}, [r0,:64]!
1074        add             r0,  r0,  #8
1075        vst1.16         {d22}, [r0,:64]!
1076        vst1.16         {d26}, [r0,:64]!
1077        vst1.16         {d30}, [r0,:64]!
1078        add             r0,  r0,  #8
1079        vst1.16         {d23}, [r0,:64]!
1080        vst1.16         {d27}, [r0,:64]!
1081        vst1.16         {d31}, [r0,:64]!
1082        vmov            d20, d16
1083        vmov            d21, d17
1084        vmov            d22, d18
1085        vmov            d23, d19
1086        pop             {pc}
1087endfunc
1088
1089function idct16_1d_4x16_pass2_half_neon
1090        push            {lr}
1091        mov             r12, #32
1092        cmp             r3,  #0
1093.irp i, 16, 17, 18, 19
1094        vld1.16         {d\i}, [r2,:64], r12
1095.endr
1096        beq             1f
1097.irp i, 20, 21, 22, 23
1098        vld1.16         {d\i}, [r2,:64], r12
1099.endr
11001:
1101
1102        add             r3,  r0,  r1
1103        lsl             r1,  r1,  #1
1104        bl              idct16_half
1105
1106        load_add_store  q8,  q9,  q10, q11
1107        load_add_store  q12, q13, q14, q15
1108
1109        pop             {pc}
1110endfunc
1111.purgem load_add_store
1112
1113.macro idct16_partial size
1114function idct16x16_\size\()_add_neon
1115        add             r0,  sp,  #(0*32)
1116        mov             r1,  #0
1117        add             r2,  r6,  #(0*2)
1118        bl              idct16_1d_4x16_pass1_\size\()_neon
1119.ifc \size,half
1120        add             r0,  sp,  #(4*32)
1121        mov             r1,  #4
1122        add             r2,  r6,  #(4*2)
1123        bl              idct16_1d_4x16_pass1_\size\()_neon
1124.endif
1125.irp i, 0, 4, 8, 12
1126        add             r0,  r4,  #(\i)
1127        mov             r1,  r5
1128        add             r2,  sp,  #(\i*2)
1129        mov             r3,  #\i
1130        bl              idct16_1d_4x16_pass2_\size\()_neon
1131.endr
1132
1133        add             sp,  sp,  r7
1134        pop             {r4-r8,pc}
1135endfunc
1136.endm
1137
1138idct16_partial quarter
1139idct16_partial half
1140
1141function idct32x32_dc_add_neon
1142        movrel          r12, idct_coeffs
1143        vld1.16         {d0}, [r12,:64]
1144
1145        vmov.i16        q2,  #0
1146
1147        vld1.16         {d16[]}, [r2,:16]
1148        vmull.s16       q8,  d16, d0[0]
1149        vrshrn.s32      d16, q8,  #14
1150        vmull.s16       q8,  d16, d0[0]
1151        vrshrn.s32      d16, q8,  #14
1152        vdup.16         q8,  d16[0]
1153        vst1.16         {d4[0]}, [r2,:16]
1154
1155        vrshr.s16       q8,  q8,  #6
1156
1157        mov             r3,  r0
1158        mov             r12, #32
11591:
1160        @ Loop to add the constant from q8 into all 32x32 outputs
1161        subs            r12, r12, #2
1162        vld1.8          {q0-q1},  [r0,:128], r1
1163        vaddw.u8        q9,  q8,  d0
1164        vaddw.u8        q10, q8,  d1
1165        vld1.8          {q2-q3},  [r0,:128], r1
1166        vaddw.u8        q11, q8,  d2
1167        vaddw.u8        q12, q8,  d3
1168        vaddw.u8        q13, q8,  d4
1169        vaddw.u8        q14, q8,  d5
1170        vaddw.u8        q15, q8,  d6
1171        vqmovun.s16     d0,  q9
1172        vaddw.u8        q9,  q8,  d7
1173        vqmovun.s16     d1,  q10
1174        vqmovun.s16     d2,  q11
1175        vqmovun.s16     d3,  q12
1176        vqmovun.s16     d4,  q13
1177        vqmovun.s16     d5,  q14
1178        vst1.8          {q0-q1},  [r3,:128], r1
1179        vqmovun.s16     d6,  q15
1180        vqmovun.s16     d7,  q9
1181        vst1.8          {q2-q3},  [r3,:128], r1
1182        bne             1b
1183
1184        bx              lr
1185endfunc
1186
1187.macro idct32_end
1188        butterfly       d16, d9,  d8,  d9  @ d16 = t16a, d9  = t19a
1189        butterfly       d17, d20, d23, d20 @ d17 = t17,  d20 = t18
1190        butterfly       d18, d10, d11, d10 @ d18 = t23a, d10 = t20a
1191        butterfly       d19, d21, d22, d21 @ d19 = t22,  d21 = t21
1192        butterfly       d8,  d28, d28, d30 @ d8  = t24a, d28 = t27a
1193        butterfly       d23, d26, d25, d26 @ d23 = t25,  d26 = t26
1194        butterfly       d11, d29, d29, d31 @ d11 = t31a, d29 = t28a
1195        butterfly       d22, d27, d24, d27 @ d22 = t30,  d27 = t29
1196
1197        mbutterfly      d27, d20, d0[2], d0[3], q12, q15        @ d27 = t18a, d20 = t29a
1198        mbutterfly      d29, d9,  d0[2], d0[3], q12, q15        @ d29 = t19,  d5  = t28
1199        mbutterfly      d28, d10, d0[2], d0[3], q12, q15, neg=1 @ d28 = t27,  d6  = t20
1200        mbutterfly      d26, d21, d0[2], d0[3], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
1201
1202        butterfly       d31, d24, d11, d8  @ d31 = t31,  d24 = t24
1203        butterfly       d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
1204        butterfly_r     d23, d16, d16, d18 @ d23 = t23,  d16 = t16
1205        butterfly_r     d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
1206        butterfly       d18, d21, d27, d21 @ d18 = t18,  d21 = t21
1207        butterfly_r     d27, d28, d9,  d28 @ d27 = t27a, d28 = t28a
1208        butterfly       d8,  d26, d20, d26 @ d8  = t29,  d26 = t26
1209        butterfly       d19, d20, d29, d10 @ d19 = t19a, d20 = t20
1210        vmov            d29, d8            @ d29 = t29
1211
1212        mbutterfly0     d27, d20, d27, d20, d8, d10, q4, q5 @ d27 = t27,  d20 = t20
1213        mbutterfly0     d26, d21, d26, d21, d8, d10, q4, q5 @ d26 = t26a, d21 = t21a
1214        mbutterfly0     d25, d22, d25, d22, d8, d10, q4, q5 @ d25 = t25,  d22 = t22
1215        mbutterfly0     d24, d23, d24, d23, d8, d10, q4, q5 @ d24 = t24a, d23 = t23a
1216        bx              lr
1217.endm
1218
1219function idct32_odd
1220        mbutterfly      d16, d31, d4[0], d4[1], q4, q5 @ d16 = t16a, d31 = t31a
1221        mbutterfly      d24, d23, d4[2], d4[3], q4, q5 @ d24 = t17a, d23 = t30a
1222        mbutterfly      d20, d27, d5[0], d5[1], q4, q5 @ d20 = t18a, d27 = t29a
1223        mbutterfly      d28, d19, d5[2], d5[3], q4, q5 @ d28 = t19a, d19 = t28a
1224        mbutterfly      d18, d29, d6[0], d6[1], q4, q5 @ d18 = t20a, d29 = t27a
1225        mbutterfly      d26, d21, d6[2], d6[3], q4, q5 @ d26 = t21a, d21 = t26a
1226        mbutterfly      d22, d25, d7[0], d7[1], q4, q5 @ d22 = t22a, d25 = t25a
1227        mbutterfly      d30, d17, d7[2], d7[3], q4, q5 @ d30 = t23a, d17 = t24a
1228
1229        butterfly       d8,  d24, d16, d24 @ d8  = t16, d24 = t17
1230        butterfly       d9,  d20, d28, d20 @ d9  = t19, d20 = t18
1231        butterfly       d10, d26, d18, d26 @ d10 = t20, d26 = t21
1232        butterfly       d11, d22, d30, d22 @ d11 = t23, d22 = t22
1233        butterfly       d28, d25, d17, d25 @ d28 = t24, d25 = t25
1234        butterfly       d30, d21, d29, d21 @ d30 = t27, d21 = t26
1235        butterfly       d29, d23, d31, d23 @ d29 = t31, d23 = t30
1236        butterfly       d31, d27, d19, d27 @ d31 = t28, d27 = t29
1237
1238        mbutterfly      d23, d24, d1[0], d1[1], q8, q9        @ d23 = t17a, d24 = t30a
1239        mbutterfly      d27, d20, d1[0], d1[1], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
1240        mbutterfly      d21, d26, d1[2], d1[3], q8, q9        @ d21 = t21a, d26 = t26a
1241        mbutterfly      d25, d22, d1[2], d1[3], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
1242        idct32_end
1243endfunc
1244
1245function idct32_odd_half
1246        mbutterfly_h1   d16, d31, d4[0], d4[1], q4, q5 @ d16 = t16a, d31 = t31a
1247        mbutterfly_h2   d24, d23, d4[2], d4[3], q4, q5 @ d24 = t17a, d23 = t30a
1248        mbutterfly_h1   d20, d27, d5[0], d5[1], q4, q5 @ d20 = t18a, d27 = t29a
1249        mbutterfly_h2   d28, d19, d5[2], d5[3], q4, q5 @ d28 = t19a, d19 = t28a
1250        mbutterfly_h1   d18, d29, d6[0], d6[1], q4, q5 @ d18 = t20a, d29 = t27a
1251        mbutterfly_h2   d26, d21, d6[2], d6[3], q4, q5 @ d26 = t21a, d21 = t26a
1252        mbutterfly_h1   d22, d25, d7[0], d7[1], q4, q5 @ d22 = t22a, d25 = t25a
1253        mbutterfly_h2   d30, d17, d7[2], d7[3], q4, q5 @ d30 = t23a, d17 = t24a
1254
1255        butterfly       d8,  d24, d16, d24 @ d8  = t16, d24 = t17
1256        butterfly       d9,  d20, d28, d20 @ d9  = t19, d20 = t18
1257        butterfly       d10, d26, d18, d26 @ d10 = t20, d26 = t21
1258        butterfly       d11, d22, d30, d22 @ d11 = t23, d22 = t22
1259        butterfly       d28, d25, d17, d25 @ d28 = t24, d25 = t25
1260        butterfly       d30, d21, d29, d21 @ d30 = t27, d21 = t26
1261        butterfly       d29, d23, d31, d23 @ d29 = t31, d23 = t30
1262        butterfly       d31, d27, d19, d27 @ d31 = t28, d27 = t29
1263
1264        mbutterfly      d23, d24, d1[0], d1[1], q8, q9        @ d23 = t17a, d24 = t30a
1265        mbutterfly      d27, d20, d1[0], d1[1], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
1266        mbutterfly      d21, d26, d1[2], d1[3], q8, q9        @ d21 = t21a, d26 = t26a
1267        mbutterfly      d25, d22, d1[2], d1[3], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
1268
1269        idct32_end
1270endfunc
1271
1272function idct32_odd_quarter
1273        vmull.s16       q4,  d16, d4[0]
1274        vmull.s16       q14, d19, d5[3]
1275        vmull.s16       q15, d16, d4[1]
1276        vmull.s16       q11, d17, d7[2]
1277        vmull.s16       q5,  d17, d7[3]
1278        vmull.s16       q13, d19, d5[2]
1279        vmull.s16       q10, d18, d6[0]
1280        vmull.s16       q12, d18, d6[1]
1281
1282        vneg.s32        q14, q14
1283        vneg.s32        q5,  q5
1284
1285        vrshrn.s32      d8,  q4,  #14
1286        vrshrn.s32      d9,  q14, #14
1287        vrshrn.s32      d29, q15, #14
1288        vrshrn.s32      d28, q11, #14
1289        vrshrn.s32      d11, q5,  #14
1290        vrshrn.s32      d31, q13, #14
1291        vrshrn.s32      d10, q10, #14
1292        vrshrn.s32      d30, q12, #14
1293
1294        mbutterfly_l    q8,  q9,  d29, d8,  d1[0], d1[1]
1295        mbutterfly_l    q13, q10, d31, d9,  d1[0], d1[1]
1296        vrshrn.s32      d23, q8,  #14
1297        vrshrn.s32      d24, q9,  #14
1298        vneg.s32        q10, q10
1299        vrshrn.s32      d27, q13, #14
1300        vrshrn.s32      d20, q10, #14
1301        mbutterfly_l    q8,  q9,  d30, d10, d1[2], d1[3]
1302        vrshrn.s32      d21, q8,  #14
1303        vrshrn.s32      d26, q9,  #14
1304        mbutterfly_l    q8,  q9,  d28, d11, d1[2], d1[3]
1305        vrshrn.s32      d25, q8,  #14
1306        vneg.s32        q9,  q9
1307        vrshrn.s32      d22, q9,  #14
1308
1309        idct32_end
1310endfunc
1311
1312.macro idct32_funcs suffix
1313@ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
1314@ We don't have register space to do a single pass IDCT of 4x32 though,
1315@ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
1316@ a normal IDCT16 with every other input component (the even ones, with
1317@ each output written twice), followed by a separate 16-point IDCT
1318@ of the odd inputs, added/subtracted onto the outputs of the first idct16.
1319@ r0 = dst (temp buffer)
1320@ r1 = unused
1321@ r2 = src
1322function idct32_1d_4x32_pass1\suffix\()_neon
1323        push            {lr}
1324
1325        @ idct16 clobbers q2-q3 (since it doesn't clobber q4-q7 at all
1326        @ when doing the normal 16x16 idct), so move the idct32_odd coeffs
1327        @ to q4-q5
1328        vmov            q4,  q2
1329        vmov            q5,  q3
1330
1331        @ Double stride of the input, since we only read every other line
1332        mov             r12, #128
1333        vmov.s16        d4,  #0
1334
1335        @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1336.ifb \suffix
1337.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1338        vld1.16         {d\i}, [r2,:64]
1339        vst1.16         {d4},  [r2,:64], r12
1340.endr
1341.endif
1342.ifc \suffix,_quarter
1343.irp i, 16, 17, 18, 19
1344        vld1.16         {d\i}, [r2,:64]
1345        vst1.16         {d4},  [r2,:64], r12
1346.endr
1347.endif
1348.ifc \suffix,_half
1349.irp i, 16, 17, 18, 19, 20, 21, 22, 23
1350        vld1.16         {d\i}, [r2,:64]
1351        vst1.16         {d4},  [r2,:64], r12
1352.endr
1353.endif
1354
1355        bl              idct16\suffix
1356
1357        @ Move the idct32_odd coeffs back into q2-q3 for idct32_odd;
1358        @ the constants for a vmul with a lane must be in q0-q3.
1359        vmov            q2,  q4
1360        vmov            q3,  q5
1361
1362        @ Do four 4x4 transposes. Originally, d16-d31 contain the
1363        @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
1364        @ contain the transposed 4x4 blocks.
1365        transpose16_q_4x_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
1366        @ Store the registers a, b, c, d horizontally, followed
1367        @ by the same registers d, c, b, a mirrored.
1368.macro store_rev a, b, c, d
1369.irp i, \a, \b, \c, \d
1370        vst1.16         {d\i}, [r0,:64]!
1371        vrev64.16       d\i, d\i
1372.endr
1373.irp i, \d, \c, \b, \a
1374        vst1.16         {d\i}, [r0,:64]!
1375.endr
1376.endm
1377        store_rev       16, 20, 24, 28
1378        store_rev       17, 21, 25, 29
1379        store_rev       18, 22, 26, 30
1380        store_rev       19, 23, 27, 31
1381        sub             r0,  r0,  #256
1382.purgem store_rev
1383
1384        @ Move r2 back to the start of the input, and move
1385        @ to the first odd row
1386.ifb \suffix
1387        sub             r2,  r2,  r12, lsl #4
1388.endif
1389.ifc \suffix,_quarter
1390        sub             r2,  r2,  r12, lsl #2
1391.endif
1392.ifc \suffix,_half
1393        sub             r2,  r2,  r12, lsl #3
1394.endif
1395        add             r2,  r2,  #64
1396
1397        vmov.s16        d8,  #0
1398        @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1399.ifb \suffix
1400.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1401        vld1.16         {d\i}, [r2,:64]
1402        vst1.16         {d8},  [r2,:64], r12
1403.endr
1404.endif
1405.ifc \suffix,_quarter
1406.irp i, 16, 17, 18, 19
1407        vld1.16         {d\i}, [r2,:64]
1408        vst1.16         {d8},  [r2,:64], r12
1409.endr
1410.endif
1411.ifc \suffix,_half
1412.irp i, 16, 17, 18, 19, 20, 21, 22, 23
1413        vld1.16         {d\i}, [r2,:64]
1414        vst1.16         {d8},  [r2,:64], r12
1415.endr
1416.endif
1417
1418        bl              idct32_odd\suffix
1419
1420        transpose16_q_4x_4x4 q15, q14, q13, q12, q11, q10, q9,  q8,  d31, d30, d29, d28, d27, d26, d25, d24, d23, d22, d21, d20, d19, d18, d17, d16
1421
1422        @ Store the registers a, b, c, d horizontally,
1423        @ adding into the output first, and then mirrored, subtracted
1424        @ from the output.
1425.macro store_rev a, b, c, d
1426.irp i, \a, \b, \c, \d
1427        vld1.16         {d8},  [r0,:64]
1428        vadd.s16        d8,  d8,  d\i
1429        vst1.16         {d8},  [r0,:64]!
1430        vrev64.16       d\i, d\i
1431.endr
1432.irp i, \d, \c, \b, \a
1433        vld1.16         {d8},  [r0,:64]
1434        vsub.s16        d8,  d8,  d\i
1435        vst1.16         {d8},  [r0,:64]!
1436.endr
1437.endm
1438
1439        store_rev       31, 27, 23, 19
1440        store_rev       30, 26, 22, 18
1441        store_rev       29, 25, 21, 17
1442        store_rev       28, 24, 20, 16
1443.purgem store_rev
1444        pop             {pc}
1445endfunc
1446.ltorg
1447
1448@ This is mostly the same as 4x32_pass1, but without the transpose,
1449@ and use the source as temp buffer between the two idct passes, and
1450@ add into the destination.
1451@ r0 = dst
1452@ r1 = dst stride
1453@ r2 = src (temp buffer)
1454function idct32_1d_4x32_pass2\suffix\()_neon
1455        push            {lr}
1456        vmov            q4,  q2
1457        vmov            q5,  q3
1458
1459        mov             r12, #128
1460        @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
1461.ifb \suffix
1462.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1463        vld1.16         {d\i}, [r2,:64], r12
1464.endr
1465        sub             r2,  r2,  r12, lsl #4
1466.endif
1467.ifc \suffix,_quarter
1468.irp i, 16, 17, 18, 19
1469        vld1.16         {d\i}, [r2,:64], r12
1470.endr
1471        sub             r2,  r2,  r12, lsl #2
1472.endif
1473.ifc \suffix,_half
1474.irp i, 16, 17, 18, 19, 20, 21, 22, 23
1475        vld1.16         {d\i}, [r2,:64], r12
1476.endr
1477        sub             r2,  r2,  r12, lsl #3
1478.endif
1479
1480        bl              idct16\suffix
1481
1482        vmov            q2,  q4
1483        vmov            q3,  q5
1484
1485.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1486        vst1.16         {d\i}, [r2,:64], r12
1487.endr
1488
1489        sub             r2,  r2,  r12, lsl #4
1490        add             r2,  r2,  #64
1491
1492        @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
1493.ifb \suffix
1494.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
1495        vld1.16         {d\i}, [r2,:64], r12
1496.endr
1497        sub             r2,  r2,  r12, lsl #4
1498.endif
1499.ifc \suffix,_quarter
1500.irp i, 16, 17, 18, 19
1501        vld1.16         {d\i}, [r2,:64], r12
1502.endr
1503        sub             r2,  r2,  r12, lsl #2
1504.endif
1505.ifc \suffix,_half
1506.irp i, 16, 17, 18, 19, 20, 21, 22, 23
1507        vld1.16         {d\i}, [r2,:64], r12
1508.endr
1509        sub             r2,  r2,  r12, lsl #3
1510.endif
1511        sub             r2,  r2,  #64
1512
1513        bl              idct32_odd\suffix
1514
1515        mov             r12, #128
1516.macro load_acc_store a, b, c, d, neg=0
1517        vld1.16         {d8},  [r2,:64], r12
1518        vld1.16         {d9},  [r2,:64], r12
1519.if \neg == 0
1520        vadd.s16        d8,  d8,  d\a
1521        vld1.16         {d10}, [r2,:64], r12
1522        vadd.s16        d9,  d9,  d\b
1523        vld1.16         {d11}, [r2,:64], r12
1524        vadd.s16        d10, d10, d\c
1525        vadd.s16        d11, d11, d\d
1526.else
1527        vsub.s16        d8,  d8,  d\a
1528        vld1.16         {d10}, [r2,:64], r12
1529        vsub.s16        d9,  d9,  d\b
1530        vld1.16         {d11}, [r2,:64], r12
1531        vsub.s16        d10, d10, d\c
1532        vsub.s16        d11, d11, d\d
1533.endif
1534        vld1.32         {d12[]},  [r0,:32], r1
1535        vld1.32         {d12[1]}, [r0,:32], r1
1536        vrshr.s16       q4,  q4,  #6
1537        vld1.32         {d13[]},  [r0,:32], r1
1538        vrshr.s16       q5,  q5,  #6
1539        vld1.32         {d13[1]}, [r0,:32], r1
1540        sub             r0,  r0,  r1, lsl #2
1541        vaddw.u8        q4,  q4,  d12
1542        vaddw.u8        q5,  q5,  d13
1543        vqmovun.s16     d8,  q4
1544        vqmovun.s16     d9,  q5
1545        vst1.32         {d8[0]},  [r0,:32], r1
1546        vst1.32         {d8[1]},  [r0,:32], r1
1547        vst1.32         {d9[0]},  [r0,:32], r1
1548        vst1.32         {d9[1]},  [r0,:32], r1
1549.endm
1550        load_acc_store  31, 30, 29, 28
1551        load_acc_store  27, 26, 25, 24
1552        load_acc_store  23, 22, 21, 20
1553        load_acc_store  19, 18, 17, 16
1554        sub             r2,  r2,  r12
1555        neg             r12, r12
1556        load_acc_store  16, 17, 18, 19, 1
1557        load_acc_store  20, 21, 22, 23, 1
1558        load_acc_store  24, 25, 26, 27, 1
1559        load_acc_store  28, 29, 30, 31, 1
1560.purgem load_acc_store
1561        pop             {pc}
1562endfunc
1563.endm
1564
1565idct32_funcs
1566idct32_funcs _quarter
1567idct32_funcs _half
1568
1569const min_eob_idct_idct_32, align=4
1570        .short  0, 9, 34, 70, 135, 240, 336, 448
1571endconst
1572
1573function ff_vp9_idct_idct_32x32_add_neon, export=1
1574        cmp             r3,  #1
1575        beq             idct32x32_dc_add_neon
1576        push            {r4-r8,lr}
1577        vpush           {q4-q6}
1578
1579        @ Align the stack, allocate a temp buffer
1580T       mov             r7,  sp
1581T       and             r7,  r7,  #15
1582A       and             r7,  sp,  #15
1583        add             r7,  r7,  #2048
1584        sub             sp,  sp,  r7
1585
1586        mov             r4,  r0
1587        mov             r5,  r1
1588        mov             r6,  r2
1589
1590        movrel          r12, idct_coeffs
1591        vld1.16         {q0-q1}, [r12,:128]!
1592        vld1.16         {q2-q3}, [r12,:128]
1593
1594        cmp             r3,  #34
1595        ble             idct32x32_quarter_add_neon
1596        cmp             r3,  #135
1597        ble             idct32x32_half_add_neon
1598
1599        movrel          r8,  min_eob_idct_idct_32 + 2
1600
1601.irp i, 0, 4, 8, 12, 16, 20, 24, 28
1602        add             r0,  sp,  #(\i*64)
1603.if \i > 0
1604        ldrh_post       r1,  r8,  #2
1605        cmp             r3,  r1
1606        it              le
1607        movle           r1,  #(32 - \i)/2
1608        ble             1f
1609.endif
1610        add             r2,  r6,  #(\i*2)
1611        bl              idct32_1d_4x32_pass1_neon
1612.endr
1613        b               3f
1614
16151:
1616        @ Write zeros to the temp buffer for pass 2
1617        vmov.i16        q14, #0
1618        vmov.i16        q15, #0
16192:
1620        subs            r1,  r1,  #1
1621.rept 4
1622        vst1.16         {q14-q15}, [r0,:128]!
1623.endr
1624        bne             2b
16253:
1626.irp i, 0, 4, 8, 12, 16, 20, 24, 28
1627        add             r0,  r4,  #(\i)
1628        mov             r1,  r5
1629        add             r2,  sp,  #(\i*2)
1630        bl              idct32_1d_4x32_pass2_neon
1631.endr
1632
1633        add             sp,  sp,  r7
1634        vpop            {q4-q6}
1635        pop             {r4-r8,pc}
1636endfunc
1637
1638.macro idct32_partial size
1639function idct32x32_\size\()_add_neon
1640.irp i, 0, 4
1641        add             r0,  sp,  #(\i*64)
1642.ifc \size,quarter
1643.if \i == 4
1644        cmp             r3,  #9
1645        ble             1f
1646.endif
1647.endif
1648        add             r2,  r6,  #(\i*2)
1649        bl              idct32_1d_4x32_pass1_\size\()_neon
1650.endr
1651
1652.ifc \size,half
1653.irp i, 8, 12
1654        add             r0,  sp,  #(\i*64)
1655.if \i == 12
1656        cmp             r3,  #70
1657        ble             1f
1658.endif
1659        add             r2,  r6,  #(\i*2)
1660        bl              idct32_1d_4x32_pass1_\size\()_neon
1661.endr
1662.endif
1663        b               3f
1664
16651:
1666        @ Write zeros to the temp buffer for pass 2
1667        vmov.i16        q14, #0
1668        vmov.i16        q15, #0
1669.rept 8
1670        vst1.16         {q14-q15}, [r0,:128]!
1671.endr
1672
16733:
1674.irp i, 0, 4, 8, 12, 16, 20, 24, 28
1675        add             r0,  r4,  #(\i)
1676        mov             r1,  r5
1677        add             r2,  sp,  #(\i*2)
1678        bl              idct32_1d_4x32_pass2_\size\()_neon
1679.endr
1680
1681        add             sp,  sp,  r7
1682        vpop            {q4-q6}
1683        pop             {r4-r8,pc}
1684endfunc
1685.endm
1686
1687idct32_partial quarter
1688idct32_partial half
1689