dv: Convert to the new bitstream reader
[ffmpeg.git] / libavcodec / arm / vp9lpf_neon.S
1 /*
2  * Copyright (c) 2016 Google Inc.
3  *
4  * This file is part of Libav.
5  *
6  * Libav 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  * Libav 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 Libav; 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
24 @ Do an 8x8 transpose, using q registers for the subtransposes that don't
25 @ need to address the indiviudal d registers.
26 @ r0,r1 == rq0, r2,r3 == rq1, etc
27 .macro transpose_q_8x8 rq0, rq1, rq2, rq3, r0, r1, r2, r3, r4, r5, r6, r7
28         vtrn.32         \rq0, \rq2
29         vtrn.32         \rq1, \rq3
30         vtrn.16         \rq0, \rq1
31         vtrn.16         \rq2, \rq3
32         vtrn.8          \r0,  \r1
33         vtrn.8          \r2,  \r3
34         vtrn.8          \r4,  \r5
35         vtrn.8          \r6,  \r7
36 .endm
37
38 @ Do a 4x4 transpose, using q registers for the subtransposes that don't
39 @ need to address the indiviudal d registers.
40 @ r0,r1 == rq0, r2,r3 == rq1
41 .macro transpose_q_4x4 rq0, rq1, r0, r1, r2, r3
42         vtrn.16         \rq0, \rq1
43         vtrn.8          \r0,  \r1
44         vtrn.8          \r2,  \r3
45 .endm
46
47 @ The input to and output from this macro is in the registers d16-d31,
48 @ and d0-d7 are used as scratch registers.
49 @ p7 = d16 .. p3 = d20, p0 = d23, q0 = d24, q3 = d27, q7 = d31
50 @ Depending on the width of the loop filter, we either use d16-d19
51 @ and d28-d31 as temp registers, or d8-d15.
52 @ tmp1,tmp2 = tmpq1, tmp3,tmp4 = tmpq2, tmp5,tmp6 = tmpq3, tmp7,tmp8 = tmpq4
53 .macro loop_filter wd, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmpq1, tmpq2, tmpq3, tmpq4
54         vdup.u16        q0,  r2 @ E
55         vdup.u8         d2,  r3 @ I
56         ldr             r3,  [sp]
57
58         vabd.u8         d4,  d20, d21    @ abs(p3 - p2)
59         vabd.u8         d5,  d21, d22    @ abs(p2 - p1)
60         vabd.u8         d6,  d22, d23    @ abs(p1 - p0)
61         vabd.u8         d7,  d24, d25    @ abs(q0 - q1)
62         vabd.u8         \tmp1,  d25, d26 @ abs(q1 - q2)
63         vabd.u8         \tmp2,  d26, d27 @ abs(q2 - q3)
64         vmax.u8         d4,  d4,  d5
65         vmax.u8         d5,  d6,  d7
66         vmax.u8         \tmp1,  \tmp1,  \tmp2
67         vabdl.u8        q3,  d23, d24    @ abs(p0 - q0)
68         vmax.u8         d4,  d4,  d5
69         vadd.u16        q3,  q3,  q3     @ abs(p0 - q0) * 2
70         vabd.u8         d5,  d22, d25    @ abs(p1 - q1)
71         vmax.u8         d4,  d4,  \tmp1  @ max(abs(p3 - p2), ..., abs(q2 - q3))
72         vshr.u8         d5,  d5,  #1
73         vcle.u8         d4,  d4,  d2     @ max(abs()) <= I
74         vaddw.u8        q3,  q3,  d5     @ abs(p0 - q0) * 2 + abs(p1 - q1) >> 1
75         vcle.u16        q3,  q3,  q0
76         vmovn.u16       d5,  q3
77         vand            d4,  d4,  d5     @ fm
78
79         vdup.u8         d3,  r3          @ H
80         vmov            r2,  r3,  d4
81         orrs            r2,  r2,  r3
82         @ If no pixels need filtering, just exit as soon as possible
83         beq             9f
84
85 .if \wd >= 8
86         vmov.u8         d0,  #1
87
88         vabd.u8         d6,  d20, d23    @ abs(p3 - p0)
89         vabd.u8         d2,  d21, d23    @ abs(p2 - p0)
90         vabd.u8         d1,  d22, d23    @ abs(p1 - p0)
91         vabd.u8         \tmp1,  d25, d24 @ abs(q1 - q0)
92         vabd.u8         \tmp2,  d26, d24 @ abs(q2 - q0)
93         vabd.u8         \tmp3,  d27, d24 @ abs(q3 - q0)
94         vmax.u8         d6,  d6,  d2
95         vmax.u8         d1,  d1,  \tmp1
96         vmax.u8         \tmp2,  \tmp2,  \tmp3
97 .if \wd == 16
98         vabd.u8         d7,  d16, d23    @ abs(p7 - p0)
99         vmax.u8         d6,  d6,  d1
100         vabd.u8         d2,  d17, d23    @ abs(p6 - p0)
101         vmax.u8         d6,  d6,  \tmp2
102         vabd.u8         d1,  d18, d23    @ abs(p5 - p0)
103         vcle.u8         d6,  d6,  d0     @ flat8in
104         vabd.u8         d8,  d19, d23    @ abs(p4 - p0)
105         vand            d6,  d6,  d4     @ flat8in && fm
106         vabd.u8         d9,  d28, d24    @ abs(q4 - q0)
107         vbic            d4,  d4,  d6     @ fm && !flat8in
108         vabd.u8         d10, d29, d24    @ abs(q5 - q0)
109         vabd.u8         d11, d30, d24    @ abs(q6 - q0)
110         vabd.u8         d12, d31, d24    @ abs(q7 - q0)
111
112         vmax.u8         d7,  d7,  d2
113         vmax.u8         d1,  d1,  d8
114         vmax.u8         d9,  d9,  d10
115         vmax.u8         d11, d11, d12
116         @ The rest of the calculation of flat8out is interleaved below
117 .else
118         @ The rest of the calculation of flat8in is interleaved below
119 .endif
120 .endif
121
122         @ Calculate the normal inner loop filter for 2 or 4 pixels
123         vabd.u8         d5,  d22, d23           @ abs(p1 - p0)
124 .if \wd == 16
125         vmax.u8         d7,  d7,  d1
126         vmax.u8         d9,  d9,  d11
127 .elseif \wd == 8
128         vmax.u8         d6,  d6,  d1
129 .endif
130         vabd.u8         d1,  d25, d24           @ abs(q1 - q0)
131 .if \wd == 16
132         vmax.u8         d7,  d7,  d9
133 .elseif \wd == 8
134         vmax.u8         d6,  d6,  \tmp2
135 .endif
136         vsubl.u8        \tmpq1,  d22, d25       @ p1 - q1
137         vmax.u8         d5,  d5,  d1            @ max(abs(p1 - p0), abs(q1 - q0))
138         vsubl.u8        \tmpq2,  d24, d23       @ q0 - p0
139         vmov.s16        \tmpq3,  #3
140 .if \wd == 8
141         vcle.u8         d6,  d6,  d0            @ flat8in
142 .endif
143         vcle.u8         d5,  d5,  d3            @ !hev
144 .if \wd == 8
145         vand            d6,  d6,  d4            @ flat8in && fm
146 .endif
147         vqmovn.s16      \tmp1,   \tmpq1         @ av_clip_int8(p1 - q1)
148 .if \wd == 16
149         vcle.u8         d7,  d7,  d0            @ flat8out
150 .elseif \wd == 8
151         vbic            d4,  d4,  d6            @ fm && !flat8in
152 .endif
153         vand            d5,  d5,  d4            @ !hev && fm && !flat8in
154 .if \wd == 16
155         vand            d7,  d7,  d6            @ flat8out && flat8in && fm
156 .endif
157
158         vmul.s16        \tmpq2,  \tmpq2, \tmpq3 @ 3 * (q0 - p0)
159         vbic            \tmp1,   \tmp1,   d5    @ if (!hev) av_clip_int8 = 0
160         vmov.s8         d2,  #4
161         vaddw.s8        \tmpq2,  \tmpq2,  \tmp1 @ 3 * (q0 - p0) [+ av_clip_int8(p1 - q1)]
162         vmov.s8         d3,  #3
163         vqmovn.s16      \tmp1,   \tmpq2         @ f
164 .if \wd == 16
165         vbic            d6,  d6,  d7            @ fm && flat8in && !flat8out
166 .endif
167
168         vqadd.s8        \tmp3, \tmp1,  d2       @ FFMIN(f + 4, 127)
169         vqadd.s8        \tmp4, \tmp1,  d3       @ FFMIN(f + 3, 127)
170         vmovl.u8        q0,  d23                @ p0
171         vshr.s8         \tmp3, \tmp3,  #3       @ f1
172         vshr.s8         \tmp4, \tmp4,  #3       @ f2
173
174         vmovl.u8        q1,  d24                @ q0
175         vaddw.s8        q0,  q0,  \tmp4         @ p0 + f2
176         vsubw.s8        q1,  q1,  \tmp3         @ q0 - f1
177         vqmovun.s16     d0,  q0                 @ out p0
178         vqmovun.s16     d1,  q1                 @ out q0
179         vrshr.s8        \tmp3, \tmp3, #1        @ f = (f1 + 1) >> 1
180         vbit            d23, d0,  d4            @ if (fm && !flat8in)
181         vbit            d24, d1,  d4
182
183         vmovl.u8        q0,  d22                @ p1
184         vmovl.u8        q1,  d25                @ q1
185         vaddw.s8        q0,  q0,  \tmp3         @ p1 + f
186         vsubw.s8        q1,  q1,  \tmp3         @ q1 - f
187         vqmovun.s16     d0,  q0                 @ out p1
188         vqmovun.s16     d2,  q1                 @ out q1
189         vbit            d22, d0,  d5            @ if (!hev && fm && !flat8in)
190         vbit            d25, d2,  d5
191
192 .if \wd >= 8
193         vmov            r2,  r3,  d6
194         orrs            r2,  r2,  r3
195         @ If no pixels need flat8in, jump to flat8out
196         @ (or to a writeout of the inner 4 pixels, for wd=8)
197         beq             6f
198
199         @ flat8in
200         vaddl.u8        \tmpq1, d20, d21
201         vaddl.u8        \tmpq2, d22, d25
202         vaddl.u8        \tmpq3, d20, d22
203         vaddl.u8        \tmpq4, d23, d26
204         vadd.u16        q0,  \tmpq1, \tmpq1
205         vaddw.u8        q0,  q0,  d23
206         vaddw.u8        q0,  q0,  d24
207         vadd.u16        q0,  q0,  \tmpq3
208         vsub.s16        \tmpq2, \tmpq2, \tmpq1
209         vsub.s16        \tmpq4, \tmpq4, \tmpq3
210         vrshrn.u16      d2,  q0,  #3            @ out p2
211
212         vadd.u16        q0,  q0,  \tmpq2
213         vaddl.u8        \tmpq1, d20, d23
214         vaddl.u8        \tmpq2, d24, d27
215         vrshrn.u16      d3,  q0,  #3            @ out p1
216
217         vadd.u16        q0,  q0,  \tmpq4
218         vsub.s16        \tmpq2, \tmpq2, \tmpq1
219         vaddl.u8        \tmpq3, d21, d24
220         vaddl.u8        \tmpq4, d25, d27
221         vrshrn.u16      d4,  q0,  #3            @ out p0
222
223         vadd.u16        q0,  q0,  \tmpq2
224         vsub.s16        \tmpq4, \tmpq4, \tmpq3
225         vaddl.u8        \tmpq1, d22, d25
226         vaddl.u8        \tmpq2, d26, d27
227         vrshrn.u16      d5,  q0,  #3            @ out q0
228
229         vadd.u16        q0,  q0,  \tmpq4
230         vsub.s16        \tmpq2, \tmpq2, \tmpq1
231         vrshrn.u16      \tmp5,  q0,  #3         @ out q1
232
233         vadd.u16        q0,  q0,  \tmpq2
234         @ The output here is written back into the input registers. This doesn't
235         @ matter for the flat8out part below, since we only update those pixels
236         @ which won't be touched below.
237         vbit            d21, d2,  d6
238         vbit            d22, d3,  d6
239         vbit            d23, d4,  d6
240         vrshrn.u16      \tmp6,  q0,  #3         @ out q2
241         vbit            d24, d5,  d6
242         vbit            d25, \tmp5,  d6
243         vbit            d26, \tmp6,  d6
244 .endif
245 .if \wd == 16
246 6:
247         vorr            d2,  d6,  d7
248         vmov            r2,  r3,  d2
249         orrs            r2,  r2,  r3
250         @ If no pixels needed flat8in nor flat8out, jump to a
251         @ writeout of the inner 4 pixels
252         beq             7f
253         vmov            r2,  r3,  d7
254         orrs            r2,  r2,  r3
255         @ If no pixels need flat8out, jump to a writeout of the inner 6 pixels
256         beq             8f
257
258         @ flat8out
259         @ This writes all outputs into d2-d17 (skipping d6 and d16).
260         @ If this part is skipped, the output is read from d21-d26 (which is the input
261         @ to this section).
262         vshll.u8        q0,  d16, #3  @ 8 * d16
263         vsubw.u8        q0,  q0,  d16 @ 7 * d16
264         vaddw.u8        q0,  q0,  d17
265         vaddl.u8        q4,  d17, d18
266         vaddl.u8        q5,  d19, d20
267         vadd.s16        q0,  q0,  q4
268         vaddl.u8        q4,  d16, d17
269         vaddl.u8        q6,  d21, d22
270         vadd.s16        q0,  q0,  q5
271         vaddl.u8        q5,  d18, d25
272         vaddl.u8        q7,  d23, d24
273         vsub.s16        q5,  q5,  q4
274         vadd.s16        q0,  q0,  q6
275         vadd.s16        q0,  q0,  q7
276         vaddl.u8        q6,  d16, d18
277         vaddl.u8        q7,  d19, d26
278         vrshrn.u16      d2,  q0,  #4
279
280         vadd.s16        q0,  q0,  q5
281         vaddl.u8        q4,  d16, d19
282         vaddl.u8        q5,  d20, d27
283         vsub.s16        q7,  q7,  q6
284         vbif            d2,  d17, d7
285         vrshrn.u16      d3,  q0,  #4
286
287         vadd.s16        q0,  q0,  q7
288         vaddl.u8        q6,  d16, d20
289         vaddl.u8        q7,  d21, d28
290         vsub.s16        q5,  q5,  q4
291         vbif            d3,  d18, d7
292         vrshrn.u16      d4,  q0,  #4
293
294         vadd.s16        q0,  q0,  q5
295         vaddl.u8        q4,  d16, d21
296         vaddl.u8        q5,  d22, d29
297         vsub.s16        q7,  q7,  q6
298         vbif            d4,  d19, d7
299         vrshrn.u16      d5,  q0,  #4
300
301         vadd.s16        q0,  q0,  q7
302         vaddl.u8        q6,  d16, d22
303         vaddl.u8        q7,  d23, d30
304         vsub.s16        q5,  q5,  q4
305         vbif            d5,  d20, d7
306         vrshrn.u16      d6,  q0,  #4
307
308         vadd.s16        q0,  q0,  q5
309         vaddl.u8        q5,  d16, d23
310         vsub.s16        q7,  q7,  q6
311         vaddl.u8        q6,  d24, d31
312         vbif            d6,  d21, d7
313         vrshrn.u16      d8,  q0,  #4
314
315         vadd.s16        q0,  q0,  q7
316         vsub.s16        q5,  q6,  q5
317         vaddl.u8        q6,  d17, d24
318         vaddl.u8        q7,  d25, d31
319         vbif            d8,  d22, d7
320         vrshrn.u16      d9,  q0,  #4
321
322         vadd.s16        q0,  q0,  q5
323         vsub.s16        q7,  q7,  q6
324         vaddl.u8        q6,  d26, d31
325         vbif            d9,  d23, d7
326         vrshrn.u16      d10, q0,  #4
327
328         vadd.s16        q0,  q0,  q7
329         vaddl.u8        q7,  d18, d25
330         vaddl.u8        q9,  d19, d26
331         vsub.s16        q6,  q6,  q7
332         vaddl.u8        q7,  d27, d31
333         vbif            d10, d24, d7
334         vrshrn.u16      d11, q0,  #4
335
336         vadd.s16        q0,  q0,  q6
337         vaddl.u8        q6,  d20, d27
338         vsub.s16        q7,  q7,  q9
339         vaddl.u8        q9,  d28, d31
340         vbif            d11, d25, d7
341         vsub.s16        q9,  q9,  q6
342         vrshrn.u16      d12, q0,  #4
343
344         vadd.s16        q0,  q0,  q7
345         vaddl.u8        q7,  d21, d28
346         vaddl.u8        q10, d29, d31
347         vbif            d12, d26, d7
348         vrshrn.u16      d13, q0,  #4
349
350         vadd.s16        q0,  q0,  q9
351         vsub.s16        q10, q10, q7
352         vaddl.u8        q9,  d22, d29
353         vaddl.u8        q11, d30, d31
354         vbif            d13, d27, d7
355         vrshrn.u16      d14, q0,  #4
356
357         vadd.s16        q0,  q0,  q10
358         vsub.s16        q11, q11, q9
359         vbif            d14, d28, d7
360         vrshrn.u16      d15, q0,  #4
361
362         vadd.s16        q0,  q0,  q11
363         vbif            d15, d29, d7
364         vrshrn.u16      d17, q0,  #4
365         vbif            d17, d30, d7
366 .endif
367 .endm
368
369 @ For wd <= 8, we use d16-d19 and d28-d31 for temp registers,
370 @ while we need those for inputs/outputs in wd=16 and use d8-d15
371 @ for temp registers there instead.
372 .macro loop_filter_4
373         loop_filter     4,  d16, d17, d18, d19, d28, d29, d30, d31, q8,  q9,  q14, q15
374 .endm
375
376 .macro loop_filter_8
377         loop_filter     8,  d16, d17, d18, d19, d28, d29, d30, d31, q8,  q9,  q14, q15
378 .endm
379
380 .macro loop_filter_16
381         loop_filter     16, d8,  d9,  d10, d11, d12, d13, d14, d15, q4,  q5,  q6,  q7
382 .endm
383
384
385 @ The public functions in this file have got the following signature:
386 @ void loop_filter(uint8_t *dst, ptrdiff_t stride, int mb_lim, int lim, int hev_thr);
387
388 function ff_vp9_loop_filter_v_4_8_neon, export=1
389         sub             r12, r0,  r1, lsl #2
390         vld1.8          {d20}, [r12,:64], r1 @ p3
391         vld1.8          {d24}, [r0, :64], r1 @ q0
392         vld1.8          {d21}, [r12,:64], r1 @ p2
393         vld1.8          {d25}, [r0, :64], r1 @ q1
394         vld1.8          {d22}, [r12,:64], r1 @ p1
395         vld1.8          {d26}, [r0, :64], r1 @ q2
396         vld1.8          {d23}, [r12,:64], r1 @ p0
397         vld1.8          {d27}, [r0, :64], r1 @ q3
398         sub             r0,  r0,  r1, lsl #2
399         sub             r12, r12, r1, lsl #1
400
401         loop_filter_4
402
403         vst1.8          {d22}, [r12,:64], r1
404         vst1.8          {d24}, [r0, :64], r1
405         vst1.8          {d23}, [r12,:64], r1
406         vst1.8          {d25}, [r0, :64], r1
407 9:
408         bx              lr
409 endfunc
410
411 function ff_vp9_loop_filter_h_4_8_neon, export=1
412         sub             r12, r0,  #4
413         add             r0,  r12, r1, lsl #2
414         vld1.8          {d20}, [r12], r1
415         vld1.8          {d24}, [r0],  r1
416         vld1.8          {d21}, [r12], r1
417         vld1.8          {d25}, [r0],  r1
418         vld1.8          {d22}, [r12], r1
419         vld1.8          {d26}, [r0],  r1
420         vld1.8          {d23}, [r12], r1
421         vld1.8          {d27}, [r0],  r1
422
423         sub             r12, r12, r1, lsl #2
424         sub             r0,  r0,  r1, lsl #2
425         @ Move r0/r12 forward by 2 pixels; we don't need to rewrite the
426         @ outermost 2 pixels since they aren't changed.
427         add             r12, r12, #2
428         add             r0,  r0,  #2
429
430         @ Transpose the 8x8 pixels, taking advantage of q registers, to get
431         @ one register per column.
432         transpose_q_8x8 q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27
433
434         loop_filter_4
435
436         @ We only will write the mid 4 pixels back; after the loop filter,
437         @ these are in d22, d23, d24, d25 (q11, q12), ordered as rows
438         @ (8x4 pixels). We need to transpose them to columns, done with a
439         @ 4x4 transpose (which in practice is two 4x4 transposes of the two
440         @ 4x4 halves of the 8x4 pixels; into 4x8 pixels).
441         transpose_q_4x4 q11, q12, d22, d23, d24, d25
442
443         vst1.32         {d22[0]}, [r12], r1
444         vst1.32         {d22[1]}, [r0],  r1
445         vst1.32         {d23[0]}, [r12], r1
446         vst1.32         {d23[1]}, [r0],  r1
447         vst1.32         {d24[0]}, [r12], r1
448         vst1.32         {d24[1]}, [r0],  r1
449         vst1.32         {d25[0]}, [r12], r1
450         vst1.32         {d25[1]}, [r0],  r1
451 9:
452         bx              lr
453 endfunc
454
455 function ff_vp9_loop_filter_v_8_8_neon, export=1
456         sub             r12, r0,  r1, lsl #2
457         vld1.8          {d20}, [r12,:64], r1 @ p3
458         vld1.8          {d24}, [r0, :64], r1 @ q0
459         vld1.8          {d21}, [r12,:64], r1 @ p2
460         vld1.8          {d25}, [r0, :64], r1 @ q1
461         vld1.8          {d22}, [r12,:64], r1 @ p1
462         vld1.8          {d26}, [r0, :64], r1 @ q2
463         vld1.8          {d23}, [r12,:64], r1 @ p0
464         vld1.8          {d27}, [r0, :64], r1 @ q3
465         sub             r12, r12, r1, lsl #2
466         sub             r0,  r0,  r1, lsl #2
467         add             r12, r12, r1
468
469         loop_filter_8
470
471         vst1.8          {d21}, [r12,:64], r1
472         vst1.8          {d24}, [r0, :64], r1
473         vst1.8          {d22}, [r12,:64], r1
474         vst1.8          {d25}, [r0, :64], r1
475         vst1.8          {d23}, [r12,:64], r1
476         vst1.8          {d26}, [r0, :64], r1
477 9:
478         bx              lr
479 6:
480         sub             r12, r0,  r1, lsl #1
481         vst1.8          {d22}, [r12,:64], r1
482         vst1.8          {d24}, [r0, :64], r1
483         vst1.8          {d23}, [r12,:64], r1
484         vst1.8          {d25}, [r0, :64], r1
485         bx              lr
486 endfunc
487
488 function ff_vp9_loop_filter_h_8_8_neon, export=1
489         sub             r12, r0,  #4
490         add             r0,  r12, r1, lsl #2
491         vld1.8          {d20}, [r12], r1
492         vld1.8          {d24}, [r0],  r1
493         vld1.8          {d21}, [r12], r1
494         vld1.8          {d25}, [r0],  r1
495         vld1.8          {d22}, [r12], r1
496         vld1.8          {d26}, [r0],  r1
497         vld1.8          {d23}, [r12], r1
498         vld1.8          {d27}, [r0],  r1
499
500         sub             r12, r12, r1, lsl #2
501         sub             r0,  r0,  r1, lsl #2
502
503         transpose_q_8x8 q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27
504
505         loop_filter_8
506
507         @ Even though only 6 pixels per row have been changed, we write the
508         @ full 8 pixel registers.
509         transpose_q_8x8 q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27
510
511         vst1.8          {d20}, [r12], r1
512         vst1.8          {d24}, [r0],  r1
513         vst1.8          {d21}, [r12], r1
514         vst1.8          {d25}, [r0],  r1
515         vst1.8          {d22}, [r12], r1
516         vst1.8          {d26}, [r0],  r1
517         vst1.8          {d23}, [r12], r1
518         vst1.8          {d27}, [r0],  r1
519 9:
520         bx              lr
521 6:
522         @ If we didn't need to do the flat8in part, we use the same writeback
523         @ as in loop_filter_h_4_8.
524         add             r12, r12, #2
525         add             r0,  r0,  #2
526         transpose_q_4x4 q11, q12, d22, d23, d24, d25
527         vst1.32         {d22[0]}, [r12], r1
528         vst1.32         {d22[1]}, [r0],  r1
529         vst1.32         {d23[0]}, [r12], r1
530         vst1.32         {d23[1]}, [r0],  r1
531         vst1.32         {d24[0]}, [r12], r1
532         vst1.32         {d24[1]}, [r0],  r1
533         vst1.32         {d25[0]}, [r12], r1
534         vst1.32         {d25[1]}, [r0],  r1
535         bx              lr
536 endfunc
537
538 function vp9_loop_filter_v_16_neon
539         sub             r12, r0,  r1, lsl #3
540         @ Read p7-p0 using r12 and q0-q7 using r0
541         vld1.8          {d16}, [r12,:64], r1 @ p7
542         vld1.8          {d24}, [r0, :64], r1 @ q0
543         vld1.8          {d17}, [r12,:64], r1 @ p6
544         vld1.8          {d25}, [r0, :64], r1 @ q1
545         vld1.8          {d18}, [r12,:64], r1 @ p5
546         vld1.8          {d26}, [r0, :64], r1 @ q2
547         vld1.8          {d19}, [r12,:64], r1 @ p4
548         vld1.8          {d27}, [r0, :64], r1 @ q3
549         vld1.8          {d20}, [r12,:64], r1 @ p3
550         vld1.8          {d28}, [r0, :64], r1 @ q4
551         vld1.8          {d21}, [r12,:64], r1 @ p2
552         vld1.8          {d29}, [r0, :64], r1 @ q5
553         vld1.8          {d22}, [r12,:64], r1 @ p1
554         vld1.8          {d30}, [r0, :64], r1 @ q6
555         vld1.8          {d23}, [r12,:64], r1 @ p0
556         vld1.8          {d31}, [r0, :64], r1 @ q7
557         sub             r12, r12, r1, lsl #3
558         sub             r0,  r0,  r1, lsl #3
559         add             r12, r12, r1
560
561         loop_filter_16
562
563         @ If we did the flat8out part, we get the output in
564         @ d2-d17 (skipping d7 and d16). r12 points to r0 - 7 * stride,
565         @ store d2-d9 there, and d10-d17 into r0.
566         vst1.8          {d2},  [r12,:64], r1
567         vst1.8          {d10}, [r0, :64], r1
568         vst1.8          {d3},  [r12,:64], r1
569         vst1.8          {d11}, [r0, :64], r1
570         vst1.8          {d4},  [r12,:64], r1
571         vst1.8          {d12}, [r0, :64], r1
572         vst1.8          {d5},  [r12,:64], r1
573         vst1.8          {d13}, [r0, :64], r1
574         vst1.8          {d6},  [r12,:64], r1
575         vst1.8          {d14}, [r0, :64], r1
576         vst1.8          {d8},  [r12,:64], r1
577         vst1.8          {d15}, [r0, :64], r1
578         vst1.8          {d9},  [r12,:64], r1
579         vst1.8          {d17}, [r0, :64], r1
580         sub             r0,  r0,  r1, lsl #3
581         add             r0,  r0,  r1
582
583 9:
584         bx              lr
585
586 8:
587         add             r12, r12, r1, lsl #2
588         @ If we didn't do the flat8out part, the output is left in the
589         @ input registers.
590         vst1.8          {d21}, [r12,:64], r1
591         vst1.8          {d24}, [r0, :64], r1
592         vst1.8          {d22}, [r12,:64], r1
593         vst1.8          {d25}, [r0, :64], r1
594         vst1.8          {d23}, [r12,:64], r1
595         vst1.8          {d26}, [r0, :64], r1
596         sub             r0,  r0,  r1, lsl #1
597         sub             r0,  r0,  r1
598         bx              lr
599 7:
600         sub             r12, r0,  r1, lsl #1
601         vst1.8          {d22}, [r12,:64], r1
602         vst1.8          {d24}, [r0, :64], r1
603         vst1.8          {d23}, [r12,:64], r1
604         vst1.8          {d25}, [r0, :64], r1
605         sub             r0,  r0,  r1, lsl #1
606         bx              lr
607 endfunc
608
609 function ff_vp9_loop_filter_v_16_8_neon, export=1
610         ldr             r12, [sp]
611         push            {lr}
612         vpush           {q4-q7}
613         push            {r12}
614         bl              vp9_loop_filter_v_16_neon
615         add             sp,  sp,  #4
616         vpop            {q4-q7}
617         pop             {pc}
618 endfunc
619
620 function ff_vp9_loop_filter_v_16_16_neon, export=1
621         ldr             r12, [sp]
622         // The filter clobbers r2 and r3, but we need to keep them for the second round
623         push            {r2, r3, lr}
624         vpush           {q4-q7}
625         push            {r12}
626         bl              vp9_loop_filter_v_16_neon
627         add             r0,  #8
628         ldr             r2,  [sp, #68]
629         ldr             r3,  [sp, #72]
630         bl              vp9_loop_filter_v_16_neon
631         add             sp,  sp,  #4
632         vpop            {q4-q7}
633         pop             {r2, r3, pc}
634 endfunc
635
636 function vp9_loop_filter_h_16_neon
637         sub             r12,  r0,  #8
638         vld1.8          {d16}, [r12,:64], r1
639         vld1.8          {d24}, [r0, :64], r1
640         vld1.8          {d17}, [r12,:64], r1
641         vld1.8          {d25}, [r0, :64], r1
642         vld1.8          {d18}, [r12,:64], r1
643         vld1.8          {d26}, [r0, :64], r1
644         vld1.8          {d19}, [r12,:64], r1
645         vld1.8          {d27}, [r0, :64], r1
646         vld1.8          {d20}, [r12,:64], r1
647         vld1.8          {d28}, [r0, :64], r1
648         vld1.8          {d21}, [r12,:64], r1
649         vld1.8          {d29}, [r0, :64], r1
650         vld1.8          {d22}, [r12,:64], r1
651         vld1.8          {d30}, [r0, :64], r1
652         vld1.8          {d23}, [r12,:64], r1
653         vld1.8          {d31}, [r0, :64], r1
654         sub             r0,  r0,  r1, lsl #3
655         sub             r12, r12, r1, lsl #3
656
657         @ The 16x8 pixels read above is in two 8x8 blocks; the left
658         @ half in d16-d23, and the right half in d24-d31. Do two 8x8 transposes
659         @ of this, to get one column per register. This could be done with two
660         @ transpose_8x8 as below, but this takes advantage of the q registers.
661         transpose16_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15
662         vtrn.8          d16, d17
663         vtrn.8          d18, d19
664         vtrn.8          d20, d21
665         vtrn.8          d22, d23
666         vtrn.8          d24, d25
667         vtrn.8          d26, d27
668         vtrn.8          d28, d29
669         vtrn.8          d30, d31
670
671         loop_filter_16
672
673         @ Transpose back; this is the same transpose as above, but
674         @ we can't take advantage of q registers for the transpose, since
675         @ all d registers in the transpose aren't consecutive.
676         transpose_8x8   d16, d2,  d3,  d4,  d5,  d6,  d8,  d9
677         transpose_8x8   d10, d11, d12, d13, d14, d15, d17, d31
678
679         vst1.8          {d16}, [r12,:64], r1
680         vst1.8          {d10}, [r0, :64], r1
681
682         vst1.8          {d2},  [r12,:64], r1
683         vst1.8          {d11}, [r0, :64], r1
684
685         vst1.8          {d3},  [r12,:64], r1
686         vst1.8          {d12}, [r0, :64], r1
687
688         vst1.8          {d4},  [r12,:64], r1
689         vst1.8          {d13}, [r0, :64], r1
690
691         vst1.8          {d5},  [r12,:64], r1
692         vst1.8          {d14}, [r0, :64], r1
693
694         vst1.8          {d6},  [r12,:64], r1
695         vst1.8          {d15}, [r0, :64], r1
696
697         vst1.8          {d8},  [r12,:64], r1
698         vst1.8          {d17}, [r0, :64], r1
699
700         vst1.8          {d9},  [r12,:64], r1
701         vst1.8          {d31}, [r0, :64], r1
702         sub             r0,  r0,  r1, lsl #3
703 9:
704         bx              lr
705 8:
706         @ The same writeback as in loop_filter_h_8_8
707         sub             r12, r0,  #4
708         add             r0,  r12, r1, lsl #2
709         transpose_q_8x8 q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27
710
711         vst1.8          {d20}, [r12], r1
712         vst1.8          {d24}, [r0],  r1
713         vst1.8          {d21}, [r12], r1
714         vst1.8          {d25}, [r0],  r1
715         vst1.8          {d22}, [r12], r1
716         vst1.8          {d26}, [r0],  r1
717         vst1.8          {d23}, [r12], r1
718         vst1.8          {d27}, [r0],  r1
719         sub             r0,  r0,  r1, lsl #3
720         add             r0,  r0,  #4
721         bx              lr
722 7:
723         @ The same writeback as in loop_filter_h_4_8
724         sub             r12, r0,  #2
725         add             r0,  r12, r1, lsl #2
726         transpose_q_4x4 q11, q12, d22, d23, d24, d25
727         vst1.32         {d22[0]}, [r12], r1
728         vst1.32         {d22[1]}, [r0],  r1
729         vst1.32         {d23[0]}, [r12], r1
730         vst1.32         {d23[1]}, [r0],  r1
731         vst1.32         {d24[0]}, [r12], r1
732         vst1.32         {d24[1]}, [r0],  r1
733         vst1.32         {d25[0]}, [r12], r1
734         vst1.32         {d25[1]}, [r0],  r1
735         sub             r0,  r0,  r1, lsl #3
736         add             r0,  r0,  #2
737         bx              lr
738 endfunc
739
740 function ff_vp9_loop_filter_h_16_8_neon, export=1
741         ldr             r12, [sp]
742         push            {lr}
743         vpush           {q4-q7}
744         push            {r12}
745         bl              vp9_loop_filter_h_16_neon
746         add             sp,  sp,  #4
747         vpop            {q4-q7}
748         pop             {pc}
749 endfunc
750
751 function ff_vp9_loop_filter_h_16_16_neon, export=1
752         ldr             r12, [sp]
753         // The filter clobbers r2 and r3, but we need to keep them for the second round
754         push            {r2, r3, lr}
755         vpush           {q4-q7}
756         push            {r12}
757         bl              vp9_loop_filter_h_16_neon
758         add             r0,  r0,  r1, lsl #3
759         ldr             r2,  [sp, #68]
760         ldr             r3,  [sp, #72]
761         bl              vp9_loop_filter_h_16_neon
762         add             sp,  sp,  #4
763         vpop            {q4-q7}
764         pop             {r2, r3, pc}
765 endfunc