e9c7d9edc8029d5be171bfaf81aa3a25814649fc
[libav.git] / libavcodec / aarch64 / 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/aarch64/asm.S"
22 #include "neon.S"
23
24
25 // The main loop filter macro is templated and can produce filters for
26 // vectors of 8 or 16 bytes. The register mapping throughout the filter
27 // is close to identical to the arm version (please try to maintain this,
28 // if either is changed!). When the arm version uses e.g. d20 for the
29 // input variable p3, the aarch64 version uses v20.8b or v20.16b, depending
30 // on vector length.
31 //
32 // The number of elements in the vector is passed in via the macro parameter
33 // \sz, which is either .8b or .16b. For simple instructions that doesn't
34 // lengthen or narrow things, this can easily be templated like this:
35 //      uabd            v4\sz,  v20\sz, v21\sz
36 //
37 // For instructions that lengthen or narrow content, the arm version would
38 // have used q registers. For these instructions, we have macros that expand
39 // into either a single e.g. uaddl instruction, or into a uaddl + uaddl2
40 // pair, depending on the \sz parameter. Wherever the arm version would have
41 // used a q register, these macros instead take two v registers, i.e. q3
42 // is mapped to v6+v7. For the case with 8 byte input vectors, such a
43 // lengthening operation is only stored in v6.8h (what was in q3 in the arm
44 // case), while the 16 byte input vectors will use v6.8h + v7.8h.
45 // Such a macro invocation would look like this:
46 //      uaddl_sz        v8.8h,  v9.8h,  v17, v18, \sz
47 //
48 // That is, in the 8 byte input vector case, the second register in these
49 // register pairs will be unused.
50 // Unfortunately, this makes the code quite hard to read. For readability,
51 // see the arm version instead.
52
53
54 .macro uabdl_sz dst1, dst2, in1, in2, sz
55         uabdl           \dst1,  \in1\().8b,  \in2\().8b
56 .ifc \sz, .16b
57         uabdl2          \dst2,  \in1\().16b, \in2\().16b
58 .endif
59 .endm
60
61 .macro add_sz dst1, dst2, in1, in2, in3, in4, sz
62         add             \dst1,  \in1,  \in3
63 .ifc \sz, .16b
64         add             \dst2,  \in2,  \in4
65 .endif
66 .endm
67
68 .macro sub_sz dst1, dst2, in1, in2, in3, in4, sz
69         sub             \dst1,  \in1,  \in3
70 .ifc \sz, .16b
71         sub             \dst2,  \in2,  \in4
72 .endif
73 .endm
74
75 .macro uaddw_sz dst1, dst2, in1, in2, in3, sz
76         uaddw           \dst1,  \in1, \in3\().8b
77 .ifc \sz, .16b
78         uaddw2          \dst2,  \in2, \in3\().16b
79 .endif
80 .endm
81
82 .macro usubw_sz dst1, dst2, in1, in2, in3, sz
83         usubw           \dst1,  \in1, \in3\().8b
84 .ifc \sz, .16b
85         usubw2          \dst2,  \in2, \in3\().16b
86 .endif
87 .endm
88
89 .macro cmhs_sz dst1, dst2, in1, in2, in3, in4, sz
90         cmhs            \dst1,  \in1,  \in3
91 .ifc \sz, .16b
92         cmhs            \dst2,  \in2,  \in4
93 .endif
94 .endm
95
96 .macro xtn_sz dst, in1, in2, sz
97         xtn             \dst\().8b,  \in1
98 .ifc \sz, .16b
99         xtn2            \dst\().16b, \in2
100 .endif
101 .endm
102
103 .macro usubl_sz dst1, dst2, in1, in2, sz
104         usubl           \dst1,  \in1\().8b,  \in2\().8b
105 .ifc \sz, .16b
106         usubl2          \dst2,  \in1\().16b, \in2\().16b
107 .endif
108 .endm
109
110 .macro sqxtn_sz dst, in1, in2, sz
111         sqxtn           \dst\().8b,  \in1
112 .ifc \sz, .16b
113         sqxtn2          \dst\().16b, \in2
114 .endif
115 .endm
116
117 .macro sqxtun_sz dst, in1, in2, sz
118         sqxtun          \dst\().8b,  \in1
119 .ifc \sz, .16b
120         sqxtun2         \dst\().16b, \in2
121 .endif
122 .endm
123
124 .macro mul_sz dst1, dst2, in1, in2, in3, in4, sz
125         mul             \dst1,  \in1,  \in3
126 .ifc \sz, .16b
127         mul             \dst2,  \in2,  \in4
128 .endif
129 .endm
130
131 .macro saddw_sz dst1, dst2, in1, in2, in3, sz
132         saddw           \dst1,  \in1, \in3\().8b
133 .ifc \sz, .16b
134         saddw2          \dst2,  \in2, \in3\().16b
135 .endif
136 .endm
137
138 .macro ssubw_sz dst1, dst2, in1, in2, in3, sz
139         ssubw           \dst1,  \in1, \in3\().8b
140 .ifc \sz, .16b
141         ssubw2          \dst2,  \in2, \in3\().16b
142 .endif
143 .endm
144
145 .macro uxtl_sz dst1, dst2, in, sz
146         uxtl            \dst1,  \in\().8b
147 .ifc \sz, .16b
148         uxtl2           \dst2,  \in\().16b
149 .endif
150 .endm
151
152 .macro uaddl_sz dst1, dst2, in1, in2, sz
153         uaddl           \dst1,  \in1\().8b,  \in2\().8b
154 .ifc \sz, .16b
155         uaddl2          \dst2,  \in1\().16b, \in2\().16b
156 .endif
157 .endm
158
159 .macro rshrn_sz dst, in1, in2, shift, sz
160         rshrn           \dst\().8b,  \in1, \shift
161 .ifc \sz, .16b
162         rshrn2          \dst\().16b, \in2, \shift
163 .endif
164 .endm
165
166 .macro ushll_sz dst1, dst2, in, shift, sz
167         ushll           \dst1,  \in\().8b,  \shift
168 .ifc \sz, .16b
169         ushll2          \dst2,  \in\().16b, \shift
170 .endif
171 .endm
172
173 // The input to and output from this macro is in the registers v16-v31,
174 // and v0-v7 are used as scratch registers.
175 // p7 = v16 .. p3 = v20, p0 = v23, q0 = v24, q3 = v27, q7 = v31
176 // Depending on the width of the loop filter, we either use v16-v19
177 // and v28-v31 as temp registers, or v8-v15.
178 // When comparing to the arm version, tmpq1 == tmp1 + tmp2,
179 // tmpq2 == tmp3 + tmp4, etc.
180 .macro loop_filter wd, sz, mix, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8
181 .if \mix == 0
182         dup             v0.8h,  w2        // E
183         dup             v1.8h,  w2        // E
184         dup             v2\sz,  w3        // I
185         dup             v3\sz,  w4        // H
186 .else
187         dup             v0.8h,  w2        // E
188         dup             v2.8b,  w3        // I
189         dup             v3.8b,  w4        // H
190         lsr             w6,     w3,  #8
191         lsr             w7,     w4,  #8
192         ushr            v1.8h,  v0.8h, #8 // E
193         dup             v4.8b,  w6        // I
194         bic             v0.8h,  #255, lsl 8 // E
195         dup             v5.8b,  w7        // H
196         trn1            v2.2d,  v2.2d,  v4.2d
197         trn1            v3.2d,  v3.2d,  v5.2d
198 .endif
199
200         uabd            v4\sz,  v20\sz, v21\sz        // abs(p3 - p2)
201         uabd            v5\sz,  v21\sz, v22\sz        // abs(p2 - p1)
202         uabd            v6\sz,  v22\sz, v23\sz        // abs(p1 - p0)
203         uabd            v7\sz,  v24\sz, v25\sz        // abs(q0 - q1)
204         uabd            \tmp1\sz,  v25\sz, v26\sz     // abs(q1 - q2)
205         uabd            \tmp2\sz,  v26\sz, v27\sz     // abs(q2 - q3)
206         umax            v4\sz,  v4\sz,  v5\sz
207         umax            v5\sz,  v6\sz,  v7\sz
208         umax            \tmp1\sz, \tmp1\sz, \tmp2\sz
209         uabdl_sz        v6.8h,  v7.8h,  v23, v24, \sz // abs(p0 - q0)
210         umax            v4\sz,  v4\sz,  v5\sz
211         add_sz          v6.8h,  v7.8h,  v6.8h,  v7.8h,  v6.8h,  v7.8h, \sz // abs(p0 - q0) * 2
212         uabd            v5\sz,  v22\sz, v25\sz        // abs(p1 - q1)
213         umax            v4\sz,  v4\sz,  \tmp1\sz      // max(abs(p3 - p2), ..., abs(q2 - q3))
214         ushr            v5\sz,  v5\sz,  #1
215         cmhs            v4\sz,  v2\sz,  v4\sz         // max(abs()) <= I
216         uaddw_sz        v6.8h,  v7.8h,  v6.8h,  v7.8h,  v5, \sz // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1
217         cmhs_sz         v6.8h,  v7.8h,  v0.8h,  v1.8h,  v6.8h,  v7.8h, \sz
218         xtn_sz          v5,     v6.8h,  v7.8h,  \sz
219         and             v4\sz,  v4\sz,  v5\sz         // fm
220
221         // If no pixels need filtering, just exit as soon as possible
222         mov             x5,  v4.d[0]
223 .ifc \sz, .16b
224         mov             x6,  v4.d[1]
225         adds            x5,  x5,  x6
226         b.eq            9f
227 .else
228         cbz             x5,  9f
229 .endif
230
231 .if \wd >= 8
232         movi            v0\sz,  #1
233
234         uabd            v6\sz,  v20\sz, v23\sz    // abs(p3 - p0)
235         uabd            v2\sz,  v21\sz, v23\sz    // abs(p2 - p0)
236         uabd            v1\sz,  v22\sz, v23\sz    // abs(p1 - p0)
237         uabd            \tmp1\sz,  v25\sz, v24\sz // abs(q1 - q0)
238         uabd            \tmp2\sz,  v26\sz, v24\sz // abs(q2 - q0)
239         uabd            \tmp3\sz,  v27\sz, v24\sz // abs(q3 - q0)
240         umax            v6\sz,  v6\sz,  v2\sz
241         umax            v1\sz,  v1\sz,  \tmp1\sz
242         umax            \tmp2\sz,  \tmp2\sz,  \tmp3\sz
243 .if \wd == 16
244         uabd            v7\sz,  v16\sz, v23\sz    // abs(p7 - p0)
245         umax            v6\sz,  v6\sz,  v1\sz
246         uabd            v2\sz,  v17\sz, v23\sz    // abs(p6 - p0)
247         umax            v6\sz,  v6\sz,  \tmp2\sz
248         uabd            v1\sz,  v18\sz, v23\sz    // abs(p5 - p0)
249         cmhs            v6\sz,  v0\sz,  v6\sz     // flat8in
250         uabd            v8\sz,  v19\sz, v23\sz    // abs(p4 - p0)
251         and             v6\sz,  v6\sz,  v4\sz     // flat8in && fm
252         uabd            v9\sz,  v28\sz, v24\sz    // abs(q4 - q0)
253         bic             v4\sz,  v4\sz,  v6\sz     // fm && !flat8in
254         uabd            v10\sz, v29\sz, v24\sz    // abs(q5 - q0)
255         uabd            v11\sz, v30\sz, v24\sz    // abs(q6 - q0)
256         uabd            v12\sz, v31\sz, v24\sz    // abs(q7 - q0)
257
258         umax            v7\sz,  v7\sz,  v2\sz
259         umax            v1\sz,  v1\sz,  v8\sz
260         umax            v9\sz,  v9\sz,  v10\sz
261         umax            v11\sz, v11\sz, v12\sz
262         // The rest of the calculation of flat8out is interleaved below
263 .else
264         // The rest of the calculation of flat8in is interleaved below
265 .endif
266 .endif
267
268         // Calculate the normal inner loop filter for 2 or 4 pixels
269         uabd            v5\sz,  v22\sz, v23\sz // abs(p1 - p0)
270 .if \wd == 16
271         umax            v7\sz,  v7\sz,  v1\sz
272         umax            v9\sz,  v9\sz,  v11\sz
273 .elseif \wd == 8
274         umax            v6\sz,  v6\sz,  v1\sz
275 .endif
276         uabd            v1\sz,  v25\sz, v24\sz // abs(q1 - q0)
277 .if \wd == 16
278         umax            v7\sz,  v7\sz,  v9\sz
279 .elseif \wd == 8
280         umax            v6\sz,  v6\sz,  \tmp2\sz
281 .endif
282         usubl_sz        \tmp1\().8h,  \tmp2\().8h,  v22,  v25, \sz // p1 - q1
283         umax            v5\sz,  v5\sz,  v1\sz  // max(abs(p1 - p0), abs(q1 - q0))
284 .if \mix != 0
285         mov             v1.d[0], x11
286 .endif
287         usubl_sz        \tmp3\().8h,  \tmp4\().8h,  v24,  v23, \sz // q0 - p0
288         movi            \tmp5\().8h,  #3
289 .if \wd == 8
290         cmhs            v6\sz,  v0\sz,  v6\sz  // flat8in
291 .endif
292 .if \mix != 0
293         sxtl            v1.8h,  v1.8b
294 .endif
295         cmhi            v5\sz,  v5\sz,  v3\sz  // hev
296 .if \wd == 8
297         // If a 4/8 or 8/4 mix is used, clear the relevant half of v6
298 .if \mix != 0
299         and             v6\sz,  v6\sz,  v1.16b
300 .endif
301         and             v6\sz,  v6\sz,  v4\sz  // flat8in && fm
302 .endif
303         sqxtn_sz        \tmp1,        \tmp1\().8h,  \tmp2\().8h, \sz // av_clip_int8(p1 - q1)
304 .if \wd == 16
305         cmhs            v7\sz,  v0\sz,  v7\sz  // flat8out
306 .elseif \wd == 8
307         bic             v4\sz,  v4\sz,  v6\sz  // fm && !flat8in
308 .endif
309         mvn             v5\sz,  v5\sz          // !hev
310 .if \wd == 16
311         and             v7\sz,  v7\sz,  v6\sz  // flat8out && flat8in && fm
312 .endif
313         and             v5\sz,  v5\sz,  v4\sz  // !hev && fm && !flat8in
314
315         mul_sz          \tmp3\().8h,  \tmp4\().8h,  \tmp3\().8h, \tmp4\().8h,  \tmp5\().8h,  \tmp5\().8h, \sz // 3 * (q0 - p0)
316         bic             \tmp1\sz,  \tmp1\sz,  v5\sz    // if (!hev) av_clip_int8 = 0
317         movi            v2\sz,  #4
318         saddw_sz        \tmp3\().8h,  \tmp4\().8h,  \tmp3\().8h, \tmp4\().8h,  \tmp1, \sz // 3 * (q0 - p0) [+ av_clip_int8(p1 - q1)]
319         movi            v3\sz,  #3
320         sqxtn_sz        \tmp1,        \tmp3\().8h,  \tmp4\().8h, \sz       // f
321 .if \wd == 16
322         bic             v6\sz,  v6\sz,  v7\sz  // fm && flat8in && !flat8out
323 .endif
324
325         sqadd           \tmp3\sz,  \tmp1\sz,  v2\sz // FFMIN(f + 4, 127)
326         sqadd           \tmp4\sz,  \tmp1\sz,  v3\sz // FFMIN(f + 3, 127)
327         uxtl_sz         v0.8h,  v1.8h,  v23, \sz    // p0
328         sshr            \tmp3\sz,  \tmp3\sz,  #3    // f1
329         sshr            \tmp4\sz,  \tmp4\sz,  #3    // f2
330
331         uxtl_sz         v2.8h,  v3.8h,  v24, \sz    // q0
332         saddw_sz        v0.8h,  v1.8h,  v0.8h,  v1.8h,  \tmp4, \sz // p0 + f2
333         ssubw_sz        v2.8h,  v3.8h,  v2.8h,  v3.8h,  \tmp3, \sz // q0 - f1
334         sqxtun_sz       v0,  v0.8h,  v1.8h,  \sz    // out p0
335         sqxtun_sz       v1,  v2.8h,  v3.8h,  \sz    // out q0
336         srshr           \tmp3\sz, \tmp3\sz, #1      // f = (f1 + 1) >> 1
337         bit             v23\sz, v0\sz,  v4\sz       // if (fm && !flat8in)
338         bit             v24\sz, v1\sz,  v4\sz
339
340         uxtl_sz         v0.8h,  v1.8h,  v22, \sz    // p1
341         uxtl_sz         v2.8h,  v3.8h,  v25, \sz    // q1
342         saddw_sz        v0.8h,  v1.8h,  v0.8h,  v1.8h,  \tmp3, \sz // p1 + f
343         ssubw_sz        v2.8h,  v3.8h,  v2.8h,  v3.8h,  \tmp3, \sz // q1 - f
344         sqxtun_sz       v0,  v0.8h,  v1.8h, \sz     // out p1
345         sqxtun_sz       v2,  v2.8h,  v3.8h, \sz     // out q1
346         bit             v22\sz, v0\sz,  v5\sz       // if (!hev && fm && !flat8in)
347         bit             v25\sz, v2\sz,  v5\sz
348
349         // If no pixels need flat8in, jump to flat8out
350         // (or to a writeout of the inner 4 pixels, for wd=8)
351 .if \wd >= 8
352         mov             x5,  v6.d[0]
353 .ifc \sz, .16b
354         mov             x6,  v6.d[1]
355         adds            x5,  x5,  x6
356         b.eq            6f
357 .else
358         cbz             x5,  6f
359 .endif
360
361         // flat8in
362         uaddl_sz        \tmp1\().8h, \tmp2\().8h,  v20, v21, \sz
363         uaddl_sz        \tmp3\().8h, \tmp4\().8h,  v22, v25, \sz
364         uaddl_sz        \tmp5\().8h, \tmp6\().8h,  v20, v22, \sz
365         uaddl_sz        \tmp7\().8h, \tmp8\().8h,  v23, v26, \sz
366         add_sz          v0.8h,  v1.8h,  \tmp1\().8h, \tmp2\().8h, \tmp1\().8h, \tmp2\().8h, \sz
367         uaddw_sz        v0.8h,  v1.8h,  v0.8h,  v1.8h,  v23, \sz
368         uaddw_sz        v0.8h,  v1.8h,  v0.8h,  v1.8h,  v24, \sz
369         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  \tmp5\().8h, \tmp6\().8h, \sz
370         sub_sz          \tmp3\().8h, \tmp4\().8h,  \tmp3\().8h, \tmp4\().8h,  \tmp1\().8h, \tmp2\().8h, \sz
371         sub_sz          \tmp7\().8h, \tmp8\().8h,  \tmp7\().8h, \tmp8\().8h,  \tmp5\().8h, \tmp6\().8h, \sz
372         rshrn_sz        v2,  v0.8h,  v1.8h,  #3,  \sz // out p2
373
374         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  \tmp3\().8h, \tmp4\().8h, \sz
375         uaddl_sz        \tmp1\().8h, \tmp2\().8h,  v20,  v23, \sz
376         uaddl_sz        \tmp3\().8h, \tmp4\().8h,  v24,  v27, \sz
377         rshrn_sz        v3,  v0.8h,  v1.8h,  #3,  \sz // out p1
378
379         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  \tmp7\().8h, \tmp8\().8h, \sz
380         sub_sz          \tmp3\().8h, \tmp4\().8h,  \tmp3\().8h, \tmp4\().8h,  \tmp1\().8h, \tmp2\().8h, \sz
381         uaddl_sz        \tmp5\().8h, \tmp6\().8h,  v21,  v24, \sz
382         uaddl_sz        \tmp7\().8h, \tmp8\().8h,  v25,  v27, \sz
383         rshrn_sz        v4,  v0.8h,  v1.8h,  #3,  \sz // out p0
384
385         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  \tmp3\().8h, \tmp4\().8h, \sz
386         sub_sz          \tmp7\().8h, \tmp8\().8h,  \tmp7\().8h, \tmp8\().8h,  \tmp5\().8h, \tmp6\().8h, \sz
387         uaddl_sz        \tmp1\().8h, \tmp2\().8h,  v22,  v25, \sz
388         uaddl_sz        \tmp3\().8h, \tmp4\().8h,  v26,  v27, \sz
389         rshrn_sz        v5,  v0.8h,  v1.8h,  #3,  \sz // out q0
390
391         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  \tmp7\().8h, \tmp8\().8h, \sz
392         sub_sz          \tmp3\().8h, \tmp4\().8h,  \tmp3\().8h, \tmp4\().8h,  \tmp1\().8h, \tmp2\().8h, \sz
393         rshrn_sz        \tmp5,  v0.8h,  v1.8h,  #3,  \sz // out q1
394
395         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  \tmp3\().8h, \tmp4\().8h, \sz
396         // The output here is written back into the input registers. This doesn't
397         // matter for the flat8part below, since we only update those pixels
398         // which won't be touched below.
399         bit             v21\sz, v2\sz,  v6\sz
400         bit             v22\sz, v3\sz,  v6\sz
401         bit             v23\sz, v4\sz,  v6\sz
402         rshrn_sz        \tmp6,  v0.8h,  v1.8h,  #3,  \sz // out q2
403         bit             v24\sz, v5\sz,  v6\sz
404         bit             v25\sz, \tmp5\sz,  v6\sz
405         bit             v26\sz, \tmp6\sz,  v6\sz
406 .endif
407 .if \wd == 16
408 6:
409         orr             v2\sz,  v6\sz,  v7\sz
410         mov             x5,  v2.d[0]
411 .ifc \sz, .16b
412         mov             x6,  v2.d[1]
413         adds             x5,  x5,  x6
414         b.ne            1f
415 .else
416         cbnz            x5,  1f
417 .endif
418         // If no pixels needed flat8in nor flat8out, jump to a
419         // writeout of the inner 4 pixels
420         br              x14
421 1:
422
423         mov             x5,  v7.d[0]
424 .ifc \sz, .16b
425         mov             x6,  v7.d[1]
426         adds             x5,  x5,  x6
427         b.ne            1f
428 .else
429         cbnz            x5,  1f
430 .endif
431         // If no pixels need flat8out, jump to a writeout of the inner 6 pixels
432         br              x15
433
434 1:
435         // flat8out
436         // This writes all outputs into v2-v17 (skipping v6 and v16).
437         // If this part is skipped, the output is read from v21-v26 (which is the input
438         // to this section).
439         ushll_sz        v0.8h,  v1.8h,  v16,  #3,  \sz           // 8 * v16
440         usubw_sz        v0.8h,  v1.8h,  v0.8h,  v1.8h,  v16, \sz // 7 * v16
441         uaddw_sz        v0.8h,  v1.8h,  v0.8h,  v1.8h,  v17, \sz
442         uaddl_sz        v8.8h,  v9.8h,  v17, v18, \sz
443         uaddl_sz        v10.8h, v11.8h, v19, v20, \sz
444         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v8.8h,  v9.8h,  \sz
445         uaddl_sz        v8.8h,  v9.8h,  v16, v17, \sz
446         uaddl_sz        v12.8h, v13.8h, v21, v22, \sz
447         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v10.8h, v11.8h, \sz
448         uaddl_sz        v10.8h, v11.8h, v18, v25, \sz
449         uaddl_sz        v14.8h, v15.8h, v23, v24, \sz
450         sub_sz          v10.8h, v11.8h, v10.8h, v11.8h, v8.8h,  v9.8h,  \sz
451         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v12.8h, v13.8h, \sz
452         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v14.8h, v15.8h, \sz
453         uaddl_sz        v12.8h, v13.8h, v16, v18, \sz
454         uaddl_sz        v14.8h, v15.8h, v19, v26, \sz
455         rshrn_sz        v2,  v0.8h,  v1.8h,  #4,  \sz
456
457         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v10.8h, v11.8h, \sz
458         uaddl_sz        v8.8h,  v9.8h,  v16, v19, \sz
459         uaddl_sz        v10.8h, v11.8h, v20, v27, \sz
460         sub_sz          v14.8h, v15.8h, v14.8h, v15.8h, v12.8h, v13.8h, \sz
461         bif             v2\sz,  v17\sz, v7\sz
462         rshrn_sz        v3,  v0.8h,  v1.8h,  #4,  \sz
463
464         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v14.8h, v15.8h, \sz
465         uaddl_sz        v12.8h, v13.8h, v16, v20, \sz
466         uaddl_sz        v14.8h, v15.8h, v21, v28, \sz
467         sub_sz          v10.8h, v11.8h, v10.8h, v11.8h, v8.8h,  v9.8h,  \sz
468         bif             v3\sz,  v18\sz, v7\sz
469         rshrn_sz        v4,  v0.8h,  v1.8h,  #4,  \sz
470
471         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v10.8h, v11.8h, \sz
472         uaddl_sz        v8.8h,  v9.8h,  v16, v21, \sz
473         uaddl_sz        v10.8h, v11.8h, v22, v29, \sz
474         sub_sz          v14.8h, v15.8h, v14.8h, v15.8h, v12.8h, v13.8h, \sz
475         bif             v4\sz,  v19\sz, v7\sz
476         rshrn_sz        v5,  v0.8h,  v1.8h,  #4,  \sz
477
478         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v14.8h, v15.8h, \sz
479         uaddl_sz        v12.8h, v13.8h, v16, v22, \sz
480         uaddl_sz        v14.8h, v15.8h, v23, v30, \sz
481         sub_sz          v10.8h, v11.8h, v10.8h, v11.8h, v8.8h,  v9.8h,  \sz
482         bif             v5\sz,  v20\sz, v7\sz
483         rshrn_sz        v6,  v0.8h,  v1.8h,  #4,  \sz
484
485         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v10.8h, v11.8h, \sz
486         uaddl_sz        v10.8h, v11.8h, v16, v23, \sz
487         sub_sz          v14.8h, v15.8h, v14.8h, v15.8h, v12.8h, v13.8h, \sz
488         uaddl_sz        v12.8h, v13.8h, v24, v31, \sz
489         bif             v6\sz,  v21\sz, v7\sz
490         rshrn_sz        v8,  v0.8h,  v1.8h,  #4,  \sz
491
492         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v14.8h, v15.8h, \sz
493         sub_sz          v10.8h, v11.8h, v12.8h, v13.8h, v10.8h, v11.8h, \sz
494         uaddl_sz        v12.8h, v13.8h, v17, v24, \sz
495         uaddl_sz        v14.8h, v15.8h, v25, v31, \sz
496         bif             v8\sz,  v22\sz, v7\sz
497         rshrn_sz        v9,  v0.8h,  v1.8h,  #4,  \sz
498
499         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v10.8h, v11.8h, \sz
500         sub_sz          v14.8h, v15.8h, v14.8h, v15.8h, v12.8h, v13.8h, \sz
501         uaddl_sz        v12.8h, v13.8h, v26, v31, \sz
502         bif             v9\sz,  v23\sz, v7\sz
503         rshrn_sz        v10, v0.8h,  v1.8h,  #4,  \sz
504
505         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v14.8h, v15.8h, \sz
506         uaddl_sz        v14.8h, v15.8h, v18, v25, \sz
507         uaddl_sz        v18.8h, v19.8h, v19, v26, \sz
508         sub_sz          v12.8h, v13.8h, v12.8h, v13.8h, v14.8h, v15.8h, \sz
509         uaddl_sz        v14.8h, v15.8h, v27, v31, \sz
510         bif             v10\sz, v24\sz, v7\sz
511         rshrn_sz        v11, v0.8h,  v1.8h,  #4,  \sz
512
513         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v12.8h, v13.8h, \sz
514         uaddl_sz        v12.8h, v13.8h, v20, v27, \sz
515         sub_sz          v14.8h, v15.8h, v14.8h, v15.8h, v18.8h, v19.8h, \sz
516         uaddl_sz        v18.8h, v19.8h, v28, v31, \sz
517         bif             v11\sz, v25\sz, v7\sz
518         sub_sz          v18.8h, v19.8h, v18.8h, v19.8h, v12.8h, v13.8h, \sz
519         rshrn_sz        v12, v0.8h,  v1.8h,  #4,  \sz
520
521         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v14.8h, v15.8h, \sz
522         uaddl_sz        v14.8h, v15.8h, v21, v28, \sz
523         uaddl_sz        v20.8h, v21.8h, v29, v31, \sz
524         bif             v12\sz, v26\sz, v7\sz
525         rshrn_sz        v13, v0.8h,  v1.8h,  #4,  \sz
526
527         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v18.8h, v19.8h, \sz
528         sub_sz          v20.8h, v21.8h, v20.8h, v21.8h, v14.8h, v15.8h, \sz
529         uaddl_sz        v18.8h, v19.8h, v22, v29, \sz
530         uaddl_sz        v22.8h, v23.8h, v30, v31, \sz
531         bif             v13\sz, v27\sz, v7\sz
532         rshrn_sz        v14, v0.8h,  v1.8h,  #4,  \sz
533
534         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v20.8h, v21.8h, \sz
535         sub_sz          v22.8h, v23.8h, v22.8h, v23.8h, v18.8h, v19.8h, \sz
536         bif             v14\sz, v28\sz, v7\sz
537         rshrn_sz        v15, v0.8h,  v1.8h,  #4,  \sz
538
539         add_sz          v0.8h,  v1.8h,  v0.8h,  v1.8h,  v22.8h, v23.8h, \sz
540         bif             v15\sz, v29\sz, v7\sz
541         rshrn_sz        v17, v0.8h,  v1.8h,  #4,  \sz
542         bif             v17\sz, v30\sz, v7\sz
543 .endif
544 .endm
545
546 // For wd <= 8, we use v16-v19 and v28-v31 for temp registers,
547 // while we need those for inputs/outputs in wd=16 and use v8-v15
548 // for temp registers there instead.
549 function vp9_loop_filter_4
550         loop_filter     4,  .8b,  0,    v16, v17, v18, v19, v28, v29, v30, v31
551         ret
552 9:
553         br              x10
554 endfunc
555
556 function vp9_loop_filter_4_16b_mix_44
557         loop_filter     4,  .16b, 44,   v16, v17, v18, v19, v28, v29, v30, v31
558         ret
559 9:
560         br              x10
561 endfunc
562
563 function vp9_loop_filter_8
564         loop_filter     8,  .8b,  0,    v16, v17, v18, v19, v28, v29, v30, v31
565         ret
566 6:
567         br              x13
568 9:
569         br              x10
570 endfunc
571
572 function vp9_loop_filter_8_16b_mix
573         loop_filter     8,  .16b, 88,   v16, v17, v18, v19, v28, v29, v30, v31
574         ret
575 6:
576         br              x13
577 9:
578         br              x10
579 endfunc
580
581 function vp9_loop_filter_16
582         loop_filter     16, .8b,  0,    v8,  v9,  v10, v11, v12, v13, v14, v15
583         ret
584 9:
585         ldp             d8,  d9,  [sp], 0x10
586         ldp             d10, d11, [sp], 0x10
587         ldp             d12, d13, [sp], 0x10
588         ldp             d14, d15, [sp], 0x10
589         br              x10
590 endfunc
591
592 function vp9_loop_filter_16_16b
593         loop_filter     16, .16b, 0,    v8,  v9,  v10, v11, v12, v13, v14, v15
594         ret
595 9:
596         ldp             d8,  d9,  [sp], 0x10
597         ldp             d10, d11, [sp], 0x10
598         ldp             d12, d13, [sp], 0x10
599         ldp             d14, d15, [sp], 0x10
600         br              x10
601 endfunc
602
603 .macro loop_filter_4
604         bl              vp9_loop_filter_4
605 .endm
606
607 .macro loop_filter_4_16b_mix mix
608         bl              vp9_loop_filter_4_16b_mix_\mix
609 .endm
610
611 .macro loop_filter_8
612         // calculate alternative 'return' targets
613         adr             x13, 6f
614         bl              vp9_loop_filter_8
615 .endm
616
617 .macro loop_filter_8_16b_mix mix
618         // calculate alternative 'return' targets
619         adr             x13, 6f
620 .if \mix == 48
621         mov             x11, #0xffffffff00000000
622 .elseif \mix == 84
623         mov             x11, #0x00000000ffffffff
624 .else
625         mov             x11, #0xffffffffffffffff
626 .endif
627         bl              vp9_loop_filter_8_16b_mix
628 .endm
629
630 .macro loop_filter_16
631         // calculate alternative 'return' targets
632         adr             x14, 7f
633         adr             x15, 8f
634         bl              vp9_loop_filter_16
635 .endm
636
637 .macro loop_filter_16_16b
638         // calculate alternative 'return' targets
639         adr             x14, 7f
640         adr             x15, 8f
641         bl              vp9_loop_filter_16_16b
642 .endm
643
644
645 // The public functions in this file have got the following signature:
646 // void loop_filter(uint8_t *dst, ptrdiff_t stride, int mb_lim, int lim, int hev_thr);
647
648 function ff_vp9_loop_filter_v_4_8_neon, export=1
649         mov             x10, x30
650         sub             x9,  x0,  x1, lsl #2
651         ld1             {v20.8b}, [x9], x1 // p3
652         ld1             {v24.8b}, [x0], x1 // q0
653         ld1             {v21.8b}, [x9], x1 // p2
654         ld1             {v25.8b}, [x0], x1 // q1
655         ld1             {v22.8b}, [x9], x1 // p1
656         ld1             {v26.8b}, [x0], x1 // q2
657         ld1             {v23.8b}, [x9], x1 // p0
658         ld1             {v27.8b}, [x0], x1 // q3
659         sub             x0,  x0,  x1, lsl #2
660         sub             x9,  x9,  x1, lsl #1
661
662         loop_filter_4
663
664         st1             {v22.8b}, [x9], x1
665         st1             {v24.8b}, [x0], x1
666         st1             {v23.8b}, [x9], x1
667         st1             {v25.8b}, [x0], x1
668
669         br              x10
670 endfunc
671
672 function ff_vp9_loop_filter_v_44_16_neon, export=1
673         mov             x10, x30
674         sub             x9,  x0,  x1, lsl #2
675         ld1             {v20.16b}, [x9], x1 // p3
676         ld1             {v24.16b}, [x0], x1 // q0
677         ld1             {v21.16b}, [x9], x1 // p2
678         ld1             {v25.16b}, [x0], x1 // q1
679         ld1             {v22.16b}, [x9], x1 // p1
680         ld1             {v26.16b}, [x0], x1 // q2
681         ld1             {v23.16b}, [x9], x1 // p0
682         ld1             {v27.16b}, [x0], x1 // q3
683         sub             x0,  x0,  x1, lsl #2
684         sub             x9,  x9,  x1, lsl #1
685
686         loop_filter_4_16b_mix 44
687
688         st1             {v22.16b}, [x9], x1
689         st1             {v24.16b}, [x0], x1
690         st1             {v23.16b}, [x9], x1
691         st1             {v25.16b}, [x0], x1
692
693         br              x10
694 endfunc
695
696 function ff_vp9_loop_filter_h_4_8_neon, export=1
697         mov             x10, x30
698         sub             x9,  x0,  #4
699         add             x0,  x9,  x1, lsl #2
700         ld1             {v20.8b}, [x9], x1
701         ld1             {v24.8b}, [x0], x1
702         ld1             {v21.8b}, [x9], x1
703         ld1             {v25.8b}, [x0], x1
704         ld1             {v22.8b}, [x9], x1
705         ld1             {v26.8b}, [x0], x1
706         ld1             {v23.8b}, [x9], x1
707         ld1             {v27.8b}, [x0], x1
708
709         sub             x9,  x9,  x1, lsl #2
710         sub             x0,  x0,  x1, lsl #2
711         // Move x0/x9 forward by 2 pixels; we don't need to rewrite the
712         // outermost 2 pixels since they aren't changed.
713         add             x9,  x9,  #2
714         add             x0,  x0,  #2
715
716         transpose_8x8B  v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
717
718         loop_filter_4
719
720         // We only will write the mid 4 pixels back; after the loop filter,
721         // these are in v22, v23, v24, v25, ordered as rows (8x4 pixels).
722         // We need to transpose them to columns, done with a 4x8 transpose
723         // (which in practice is two 4x4 transposes of the two 4x4 halves
724         // of the 8x4 pixels; into 4x8 pixels).
725         transpose_4x8B  v22, v23, v24, v25, v26, v27, v28, v29
726         st1             {v22.s}[0], [x9], x1
727         st1             {v22.s}[1], [x0], x1
728         st1             {v23.s}[0], [x9], x1
729         st1             {v23.s}[1], [x0], x1
730         st1             {v24.s}[0], [x9], x1
731         st1             {v24.s}[1], [x0], x1
732         st1             {v25.s}[0], [x9], x1
733         st1             {v25.s}[1], [x0], x1
734
735         br              x10
736 endfunc
737
738 function ff_vp9_loop_filter_h_44_16_neon, export=1
739         mov             x10, x30
740         sub             x9,  x0,  #4
741         add             x0,  x9,  x1, lsl #3
742         ld1             {v20.8b},   [x9], x1
743         ld1             {v20.d}[1], [x0], x1
744         ld1             {v21.8b},   [x9], x1
745         ld1             {v21.d}[1], [x0], x1
746         ld1             {v22.8b},   [x9], x1
747         ld1             {v22.d}[1], [x0], x1
748         ld1             {v23.8b},   [x9], x1
749         ld1             {v23.d}[1], [x0], x1
750         ld1             {v24.8b},   [x9], x1
751         ld1             {v24.d}[1], [x0], x1
752         ld1             {v25.8b},   [x9], x1
753         ld1             {v25.d}[1], [x0], x1
754         ld1             {v26.8b},   [x9], x1
755         ld1             {v26.d}[1], [x0], x1
756         ld1             {v27.8b},   [x9], x1
757         ld1             {v27.d}[1], [x0], x1
758
759         sub             x9,  x9,  x1, lsl #3
760         sub             x0,  x0,  x1, lsl #3
761         add             x9,  x9,  #2
762         add             x0,  x0,  #2
763
764         transpose_8x16B v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
765
766         loop_filter_4_16b_mix 44
767
768         transpose_4x16B v22, v23, v24, v25, v26, v27, v28, v29
769
770         st1             {v22.s}[0], [x9], x1
771         st1             {v22.s}[2], [x0], x1
772         st1             {v23.s}[0], [x9], x1
773         st1             {v23.s}[2], [x0], x1
774         st1             {v24.s}[0], [x9], x1
775         st1             {v24.s}[2], [x0], x1
776         st1             {v25.s}[0], [x9], x1
777         st1             {v25.s}[2], [x0], x1
778         st1             {v22.s}[1], [x9], x1
779         st1             {v22.s}[3], [x0], x1
780         st1             {v23.s}[1], [x9], x1
781         st1             {v23.s}[3], [x0], x1
782         st1             {v24.s}[1], [x9], x1
783         st1             {v24.s}[3], [x0], x1
784         st1             {v25.s}[1], [x9], x1
785         st1             {v25.s}[3], [x0], x1
786
787         br              x10
788 endfunc
789
790 function ff_vp9_loop_filter_v_8_8_neon, export=1
791         mov             x10, x30
792         sub             x9,  x0,  x1, lsl #2
793         ld1             {v20.8b}, [x9], x1 // p3
794         ld1             {v24.8b}, [x0], x1 // q0
795         ld1             {v21.8b}, [x9], x1 // p2
796         ld1             {v25.8b}, [x0], x1 // q1
797         ld1             {v22.8b}, [x9], x1 // p1
798         ld1             {v26.8b}, [x0], x1 // q2
799         ld1             {v23.8b}, [x9], x1 // p0
800         ld1             {v27.8b}, [x0], x1 // q3
801         sub             x9,  x9,  x1, lsl #2
802         sub             x0,  x0,  x1, lsl #2
803         add             x9,  x9,  x1
804
805         loop_filter_8
806
807         st1             {v21.8b}, [x9], x1
808         st1             {v24.8b}, [x0], x1
809         st1             {v22.8b}, [x9], x1
810         st1             {v25.8b}, [x0], x1
811         st1             {v23.8b}, [x9], x1
812         st1             {v26.8b}, [x0], x1
813
814         br              x10
815 6:
816         sub             x9,  x0,  x1, lsl #1
817         st1             {v22.8b}, [x9], x1
818         st1             {v24.8b}, [x0], x1
819         st1             {v23.8b}, [x9], x1
820         st1             {v25.8b}, [x0], x1
821         br              x10
822 endfunc
823
824 .macro mix_v_16 mix
825 function ff_vp9_loop_filter_v_\mix\()_16_neon, export=1
826         mov             x10, x30
827         sub             x9,  x0,  x1, lsl #2
828         ld1             {v20.16b}, [x9], x1 // p3
829         ld1             {v24.16b}, [x0], x1 // q0
830         ld1             {v21.16b}, [x9], x1 // p2
831         ld1             {v25.16b}, [x0], x1 // q1
832         ld1             {v22.16b}, [x9], x1 // p1
833         ld1             {v26.16b}, [x0], x1 // q2
834         ld1             {v23.16b}, [x9], x1 // p0
835         ld1             {v27.16b}, [x0], x1 // q3
836         sub             x9,  x9,  x1, lsl #2
837         sub             x0,  x0,  x1, lsl #2
838         add             x9,  x9,  x1
839
840         loop_filter_8_16b_mix \mix
841
842         st1             {v21.16b}, [x9], x1
843         st1             {v24.16b}, [x0], x1
844         st1             {v22.16b}, [x9], x1
845         st1             {v25.16b}, [x0], x1
846         st1             {v23.16b}, [x9], x1
847         st1             {v26.16b}, [x0], x1
848
849         br              x10
850 6:
851         sub             x9,  x0,  x1, lsl #1
852         st1             {v22.16b}, [x9], x1
853         st1             {v24.16b}, [x0], x1
854         st1             {v23.16b}, [x9], x1
855         st1             {v25.16b}, [x0], x1
856         br              x10
857 endfunc
858 .endm
859
860 mix_v_16 48
861 mix_v_16 84
862 mix_v_16 88
863
864 function ff_vp9_loop_filter_h_8_8_neon, export=1
865         mov             x10, x30
866         sub             x9,  x0,  #4
867         add             x0,  x9,  x1, lsl #2
868         ld1             {v20.8b}, [x9], x1
869         ld1             {v24.8b}, [x0], x1
870         ld1             {v21.8b}, [x9], x1
871         ld1             {v25.8b}, [x0], x1
872         ld1             {v22.8b}, [x9], x1
873         ld1             {v26.8b}, [x0], x1
874         ld1             {v23.8b}, [x9], x1
875         ld1             {v27.8b}, [x0], x1
876
877         sub             x9,  x9,  x1, lsl #2
878         sub             x0,  x0,  x1, lsl #2
879
880         transpose_8x8B  v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
881
882         loop_filter_8
883
884         // Even though only 6 pixels per row have been changed, we write the
885         // full 8 pixel registers.
886         transpose_8x8B  v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
887
888         st1             {v20.8b}, [x9], x1
889         st1             {v24.8b}, [x0], x1
890         st1             {v21.8b}, [x9], x1
891         st1             {v25.8b}, [x0], x1
892         st1             {v22.8b}, [x9], x1
893         st1             {v26.8b}, [x0], x1
894         st1             {v23.8b}, [x9], x1
895         st1             {v27.8b}, [x0], x1
896
897         br              x10
898 6:
899         // If we didn't need to do the flat8in part, we use the same writeback
900         // as in loop_filter_h_4_8.
901         add             x9,  x9,  #2
902         add             x0,  x0,  #2
903         transpose_4x8B  v22, v23, v24, v25, v26, v27, v28, v29
904         st1             {v22.s}[0], [x9], x1
905         st1             {v22.s}[1], [x0], x1
906         st1             {v23.s}[0], [x9], x1
907         st1             {v23.s}[1], [x0], x1
908         st1             {v24.s}[0], [x9], x1
909         st1             {v24.s}[1], [x0], x1
910         st1             {v25.s}[0], [x9], x1
911         st1             {v25.s}[1], [x0], x1
912         br              x10
913 endfunc
914
915 .macro mix_h_16 mix
916 function ff_vp9_loop_filter_h_\mix\()_16_neon, export=1
917         mov             x10, x30
918         sub             x9,  x0,  #4
919         add             x0,  x9,  x1, lsl #3
920         ld1             {v20.8b},   [x9], x1
921         ld1             {v20.d}[1], [x0], x1
922         ld1             {v21.8b},   [x9], x1
923         ld1             {v21.d}[1], [x0], x1
924         ld1             {v22.8b},   [x9], x1
925         ld1             {v22.d}[1], [x0], x1
926         ld1             {v23.8b},   [x9], x1
927         ld1             {v23.d}[1], [x0], x1
928         ld1             {v24.8b},   [x9], x1
929         ld1             {v24.d}[1], [x0], x1
930         ld1             {v25.8b},   [x9], x1
931         ld1             {v25.d}[1], [x0], x1
932         ld1             {v26.8b},   [x9], x1
933         ld1             {v26.d}[1], [x0], x1
934         ld1             {v27.8b},   [x9], x1
935         ld1             {v27.d}[1], [x0], x1
936
937         sub             x9,  x9,  x1, lsl #3
938         sub             x0,  x0,  x1, lsl #3
939
940         transpose_8x16B v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
941
942         loop_filter_8_16b_mix \mix
943
944         transpose_8x16B v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
945
946         st1             {v20.8b},   [x9], x1
947         st1             {v20.d}[1], [x0], x1
948         st1             {v21.8b},   [x9], x1
949         st1             {v21.d}[1], [x0], x1
950         st1             {v22.8b},   [x9], x1
951         st1             {v22.d}[1], [x0], x1
952         st1             {v23.8b},   [x9], x1
953         st1             {v23.d}[1], [x0], x1
954         st1             {v24.8b},   [x9], x1
955         st1             {v24.d}[1], [x0], x1
956         st1             {v25.8b},   [x9], x1
957         st1             {v25.d}[1], [x0], x1
958         st1             {v26.8b},   [x9], x1
959         st1             {v26.d}[1], [x0], x1
960         st1             {v27.8b},   [x9], x1
961         st1             {v27.d}[1], [x0], x1
962
963         br              x10
964 6:
965         add             x9,  x9,  #2
966         add             x0,  x0,  #2
967         transpose_4x16B v22, v23, v24, v25, v26, v27, v28, v29
968         st1             {v22.s}[0], [x9], x1
969         st1             {v22.s}[2], [x0], x1
970         st1             {v23.s}[0], [x9], x1
971         st1             {v23.s}[2], [x0], x1
972         st1             {v24.s}[0], [x9], x1
973         st1             {v24.s}[2], [x0], x1
974         st1             {v25.s}[0], [x9], x1
975         st1             {v25.s}[2], [x0], x1
976         st1             {v22.s}[1], [x9], x1
977         st1             {v22.s}[3], [x0], x1
978         st1             {v23.s}[1], [x9], x1
979         st1             {v23.s}[3], [x0], x1
980         st1             {v24.s}[1], [x9], x1
981         st1             {v24.s}[3], [x0], x1
982         st1             {v25.s}[1], [x9], x1
983         st1             {v25.s}[3], [x0], x1
984         br              x10
985 endfunc
986 .endm
987
988 mix_h_16 48
989 mix_h_16 84
990 mix_h_16 88
991
992 function ff_vp9_loop_filter_v_16_8_neon, export=1
993         mov             x10, x30
994         stp             d14, d15, [sp, #-0x10]!
995         stp             d12, d13, [sp, #-0x10]!
996         stp             d10, d11, [sp, #-0x10]!
997         stp             d8,  d9,  [sp, #-0x10]!
998         sub             x9,  x0,  x1, lsl #3
999         ld1             {v16.8b}, [x9], x1 // p7
1000         ld1             {v24.8b}, [x0], x1 // q0
1001         ld1             {v17.8b}, [x9], x1 // p6
1002         ld1             {v25.8b}, [x0], x1 // q1
1003         ld1             {v18.8b}, [x9], x1 // p5
1004         ld1             {v26.8b}, [x0], x1 // q2
1005         ld1             {v19.8b}, [x9], x1 // p4
1006         ld1             {v27.8b}, [x0], x1 // q3
1007         ld1             {v20.8b}, [x9], x1 // p3
1008         ld1             {v28.8b}, [x0], x1 // q4
1009         ld1             {v21.8b}, [x9], x1 // p2
1010         ld1             {v29.8b}, [x0], x1 // q5
1011         ld1             {v22.8b}, [x9], x1 // p1
1012         ld1             {v30.8b}, [x0], x1 // q6
1013         ld1             {v23.8b}, [x9], x1 // p0
1014         ld1             {v31.8b}, [x0], x1 // q7
1015         sub             x9,  x9,  x1, lsl #3
1016         sub             x0,  x0,  x1, lsl #3
1017         add             x9,  x9,  x1
1018
1019         loop_filter_16
1020
1021         // If we did the flat8out part, we get the output in
1022         // v2-v17 (skipping v7 and v16). x9 points to x0 - 7 * stride,
1023         // store v2-v9 there, and v10-v17 into x0.
1024         st1             {v2.8b},  [x9], x1
1025         st1             {v10.8b}, [x0], x1
1026         st1             {v3.8b},  [x9], x1
1027         st1             {v11.8b}, [x0], x1
1028         st1             {v4.8b},  [x9], x1
1029         st1             {v12.8b}, [x0], x1
1030         st1             {v5.8b},  [x9], x1
1031         st1             {v13.8b}, [x0], x1
1032         st1             {v6.8b},  [x9], x1
1033         st1             {v14.8b}, [x0], x1
1034         st1             {v8.8b},  [x9], x1
1035         st1             {v15.8b}, [x0], x1
1036         st1             {v9.8b},  [x9], x1
1037         st1             {v17.8b}, [x0], x1
1038 9:
1039         ldp             d8,  d9,  [sp], 0x10
1040         ldp             d10, d11, [sp], 0x10
1041         ldp             d12, d13, [sp], 0x10
1042         ldp             d14, d15, [sp], 0x10
1043         br              x10
1044 8:
1045         add             x9,  x9,  x1, lsl #2
1046         // If we didn't do the flat8out part, the output is left in the
1047         // input registers.
1048         st1             {v21.8b}, [x9], x1
1049         st1             {v24.8b}, [x0], x1
1050         st1             {v22.8b}, [x9], x1
1051         st1             {v25.8b}, [x0], x1
1052         st1             {v23.8b}, [x9], x1
1053         st1             {v26.8b}, [x0], x1
1054         b               9b
1055 7:
1056         sub             x9,  x0,  x1, lsl #1
1057         st1             {v22.8b}, [x9], x1
1058         st1             {v24.8b}, [x0], x1
1059         st1             {v23.8b}, [x9], x1
1060         st1             {v25.8b}, [x0], x1
1061         b               9b
1062 endfunc
1063
1064 function ff_vp9_loop_filter_v_16_16_neon, export=1
1065         mov             x10, x30
1066         stp             d14, d15, [sp, #-0x10]!
1067         stp             d12, d13, [sp, #-0x10]!
1068         stp             d10, d11, [sp, #-0x10]!
1069         stp             d8,  d9,  [sp, #-0x10]!
1070         sub             x9,  x0,  x1, lsl #3
1071         ld1             {v16.16b}, [x9], x1 // p7
1072         ld1             {v24.16b}, [x0], x1 // q0
1073         ld1             {v17.16b}, [x9], x1 // p6
1074         ld1             {v25.16b}, [x0], x1 // q1
1075         ld1             {v18.16b}, [x9], x1 // p5
1076         ld1             {v26.16b}, [x0], x1 // q2
1077         ld1             {v19.16b}, [x9], x1 // p4
1078         ld1             {v27.16b}, [x0], x1 // q3
1079         ld1             {v20.16b}, [x9], x1 // p3
1080         ld1             {v28.16b}, [x0], x1 // q4
1081         ld1             {v21.16b}, [x9], x1 // p2
1082         ld1             {v29.16b}, [x0], x1 // q5
1083         ld1             {v22.16b}, [x9], x1 // p1
1084         ld1             {v30.16b}, [x0], x1 // q6
1085         ld1             {v23.16b}, [x9], x1 // p0
1086         ld1             {v31.16b}, [x0], x1 // q7
1087         sub             x9,  x9,  x1, lsl #3
1088         sub             x0,  x0,  x1, lsl #3
1089         add             x9,  x9,  x1
1090
1091         loop_filter_16_16b
1092
1093         st1             {v2.16b},  [x9], x1
1094         st1             {v10.16b}, [x0], x1
1095         st1             {v3.16b},  [x9], x1
1096         st1             {v11.16b}, [x0], x1
1097         st1             {v4.16b},  [x9], x1
1098         st1             {v12.16b}, [x0], x1
1099         st1             {v5.16b},  [x9], x1
1100         st1             {v13.16b}, [x0], x1
1101         st1             {v6.16b},  [x9], x1
1102         st1             {v14.16b}, [x0], x1
1103         st1             {v8.16b},  [x9], x1
1104         st1             {v15.16b}, [x0], x1
1105         st1             {v9.16b},  [x9], x1
1106         st1             {v17.16b}, [x0], x1
1107 9:
1108         ldp             d8,  d9,  [sp], 0x10
1109         ldp             d10, d11, [sp], 0x10
1110         ldp             d12, d13, [sp], 0x10
1111         ldp             d14, d15, [sp], 0x10
1112         br              x10
1113 8:
1114         add             x9,  x9,  x1, lsl #2
1115         st1             {v21.16b}, [x9], x1
1116         st1             {v24.16b}, [x0], x1
1117         st1             {v22.16b}, [x9], x1
1118         st1             {v25.16b}, [x0], x1
1119         st1             {v23.16b}, [x9], x1
1120         st1             {v26.16b}, [x0], x1
1121         b               9b
1122 7:
1123         sub             x9,  x0,  x1, lsl #1
1124         st1             {v22.16b}, [x9], x1
1125         st1             {v24.16b}, [x0], x1
1126         st1             {v23.16b}, [x9], x1
1127         st1             {v25.16b}, [x0], x1
1128         b               9b
1129 endfunc
1130
1131 function ff_vp9_loop_filter_h_16_8_neon, export=1
1132         mov             x10, x30
1133         stp             d14, d15, [sp, #-0x10]!
1134         stp             d12, d13, [sp, #-0x10]!
1135         stp             d10, d11, [sp, #-0x10]!
1136         stp             d8,  d9,  [sp, #-0x10]!
1137         sub             x9,  x0,  #8
1138         ld1             {v16.8b}, [x9], x1
1139         ld1             {v24.8b}, [x0], x1
1140         ld1             {v17.8b}, [x9], x1
1141         ld1             {v25.8b}, [x0], x1
1142         ld1             {v18.8b}, [x9], x1
1143         ld1             {v26.8b}, [x0], x1
1144         ld1             {v19.8b}, [x9], x1
1145         ld1             {v27.8b}, [x0], x1
1146         ld1             {v20.8b}, [x9], x1
1147         ld1             {v28.8b}, [x0], x1
1148         ld1             {v21.8b}, [x9], x1
1149         ld1             {v29.8b}, [x0], x1
1150         ld1             {v22.8b}, [x9], x1
1151         ld1             {v30.8b}, [x0], x1
1152         ld1             {v23.8b}, [x9], x1
1153         ld1             {v31.8b}, [x0], x1
1154         sub             x0,  x0,  x1, lsl #3
1155         sub             x9,  x9,  x1, lsl #3
1156
1157         // The 16x8 pixels read above is in two 8x8 blocks; the left
1158         // half in v16-v23, and the right half in v24-v31. Do two 8x8 transposes
1159         // of this, to get one column per register.
1160         transpose_8x8B  v16, v17, v18, v19, v20, v21, v22, v23, v0, v1
1161         transpose_8x8B  v24, v25, v26, v27, v28, v29, v30, v31, v0, v1
1162
1163         loop_filter_16
1164
1165         transpose_8x8B  v16, v2,  v3,  v4,  v5,  v6,  v8,  v9,  v0, v1
1166         transpose_8x8B  v10, v11, v12, v13, v14, v15, v17, v31, v0, v1
1167
1168         st1             {v16.8b}, [x9], x1
1169         st1             {v10.8b}, [x0], x1
1170         st1             {v2.8b},  [x9], x1
1171         st1             {v11.8b}, [x0], x1
1172         st1             {v3.8b},  [x9], x1
1173         st1             {v12.8b}, [x0], x1
1174         st1             {v4.8b},  [x9], x1
1175         st1             {v13.8b}, [x0], x1
1176         st1             {v5.8b},  [x9], x1
1177         st1             {v14.8b}, [x0], x1
1178         st1             {v6.8b},  [x9], x1
1179         st1             {v15.8b}, [x0], x1
1180         st1             {v8.8b},  [x9], x1
1181         st1             {v17.8b}, [x0], x1
1182         st1             {v9.8b},  [x9], x1
1183         st1             {v31.8b}, [x0], x1
1184 9:
1185         ldp             d8,  d9,  [sp], 0x10
1186         ldp             d10, d11, [sp], 0x10
1187         ldp             d12, d13, [sp], 0x10
1188         ldp             d14, d15, [sp], 0x10
1189         br              x10
1190 8:
1191         // The same writeback as in loop_filter_h_8_8
1192         sub             x9,  x0,  #4
1193         add             x0,  x9,  x1, lsl #2
1194         transpose_8x8B  v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
1195
1196         st1             {v20.8b}, [x9], x1
1197         st1             {v24.8b}, [x0], x1
1198         st1             {v21.8b}, [x9], x1
1199         st1             {v25.8b}, [x0], x1
1200         st1             {v22.8b}, [x9], x1
1201         st1             {v26.8b}, [x0], x1
1202         st1             {v23.8b}, [x9], x1
1203         st1             {v27.8b}, [x0], x1
1204         b               9b
1205 7:
1206         // The same writeback as in loop_filter_h_4_8
1207         sub             x9,  x0,  #2
1208         add             x0,  x9,  x1, lsl #2
1209         transpose_4x8B  v22, v23, v24, v25, v26, v27, v28, v29
1210         st1             {v22.s}[0], [x9], x1
1211         st1             {v22.s}[1], [x0], x1
1212         st1             {v23.s}[0], [x9], x1
1213         st1             {v23.s}[1], [x0], x1
1214         st1             {v24.s}[0], [x9], x1
1215         st1             {v24.s}[1], [x0], x1
1216         st1             {v25.s}[0], [x9], x1
1217         st1             {v25.s}[1], [x0], x1
1218         b               9b
1219 endfunc
1220
1221 function ff_vp9_loop_filter_h_16_16_neon, export=1
1222         mov             x10, x30
1223         stp             d14, d15, [sp, #-0x10]!
1224         stp             d12, d13, [sp, #-0x10]!
1225         stp             d10, d11, [sp, #-0x10]!
1226         stp             d8,  d9,  [sp, #-0x10]!
1227         sub             x9,  x0,  #8
1228         ld1             {v16.8b},   [x9], x1
1229         ld1             {v24.8b},   [x0], x1
1230         ld1             {v17.8b},   [x9], x1
1231         ld1             {v25.8b},   [x0], x1
1232         ld1             {v18.8b},   [x9], x1
1233         ld1             {v26.8b},   [x0], x1
1234         ld1             {v19.8b},   [x9], x1
1235         ld1             {v27.8b},   [x0], x1
1236         ld1             {v20.8b},   [x9], x1
1237         ld1             {v28.8b},   [x0], x1
1238         ld1             {v21.8b},   [x9], x1
1239         ld1             {v29.8b},   [x0], x1
1240         ld1             {v22.8b},   [x9], x1
1241         ld1             {v30.8b},   [x0], x1
1242         ld1             {v23.8b},   [x9], x1
1243         ld1             {v31.8b},   [x0], x1
1244         ld1             {v16.d}[1], [x9], x1
1245         ld1             {v24.d}[1], [x0], x1
1246         ld1             {v17.d}[1], [x9], x1
1247         ld1             {v25.d}[1], [x0], x1
1248         ld1             {v18.d}[1], [x9], x1
1249         ld1             {v26.d}[1], [x0], x1
1250         ld1             {v19.d}[1], [x9], x1
1251         ld1             {v27.d}[1], [x0], x1
1252         ld1             {v20.d}[1], [x9], x1
1253         ld1             {v28.d}[1], [x0], x1
1254         ld1             {v21.d}[1], [x9], x1
1255         ld1             {v29.d}[1], [x0], x1
1256         ld1             {v22.d}[1], [x9], x1
1257         ld1             {v30.d}[1], [x0], x1
1258         ld1             {v23.d}[1], [x9], x1
1259         ld1             {v31.d}[1], [x0], x1
1260         sub             x0,  x0,  x1, lsl #4
1261         sub             x9,  x9,  x1, lsl #4
1262
1263         transpose_8x16B v16, v17, v18, v19, v20, v21, v22, v23, v0, v1
1264         transpose_8x16B v24, v25, v26, v27, v28, v29, v30, v31, v0, v1
1265
1266         loop_filter_16_16b
1267
1268         transpose_8x16B v16, v2,  v3,  v4,  v5,  v6,  v8,  v9,  v0, v1
1269         transpose_8x16B v10, v11, v12, v13, v14, v15, v17, v31, v0, v1
1270
1271         st1             {v16.8b},   [x9], x1
1272         st1             {v10.8b},   [x0], x1
1273         st1             {v2.8b},    [x9], x1
1274         st1             {v11.8b},   [x0], x1
1275         st1             {v3.8b},    [x9], x1
1276         st1             {v12.8b},   [x0], x1
1277         st1             {v4.8b},    [x9], x1
1278         st1             {v13.8b},   [x0], x1
1279         st1             {v5.8b},    [x9], x1
1280         st1             {v14.8b},   [x0], x1
1281         st1             {v6.8b},    [x9], x1
1282         st1             {v15.8b},   [x0], x1
1283         st1             {v8.8b},    [x9], x1
1284         st1             {v17.8b},   [x0], x1
1285         st1             {v9.8b},    [x9], x1
1286         st1             {v31.8b},   [x0], x1
1287         st1             {v16.d}[1], [x9], x1
1288         st1             {v10.d}[1], [x0], x1
1289         st1             {v2.d}[1],  [x9], x1
1290         st1             {v11.d}[1], [x0], x1
1291         st1             {v3.d}[1],  [x9], x1
1292         st1             {v12.d}[1], [x0], x1
1293         st1             {v4.d}[1],  [x9], x1
1294         st1             {v13.d}[1], [x0], x1
1295         st1             {v5.d}[1],  [x9], x1
1296         st1             {v14.d}[1], [x0], x1
1297         st1             {v6.d}[1],  [x9], x1
1298         st1             {v15.d}[1], [x0], x1
1299         st1             {v8.d}[1],  [x9], x1
1300         st1             {v17.d}[1], [x0], x1
1301         st1             {v9.d}[1],  [x9], x1
1302         st1             {v31.d}[1], [x0], x1
1303 9:
1304         ldp             d8,  d9,  [sp], 0x10
1305         ldp             d10, d11, [sp], 0x10
1306         ldp             d12, d13, [sp], 0x10
1307         ldp             d14, d15, [sp], 0x10
1308         br              x10
1309 8:
1310         sub             x9,  x0,  #4
1311         add             x0,  x9,  x1, lsl #3
1312         transpose_8x16B v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
1313
1314         st1             {v20.8b},   [x9], x1
1315         st1             {v20.d}[1], [x0], x1
1316         st1             {v21.8b},   [x9], x1
1317         st1             {v21.d}[1], [x0], x1
1318         st1             {v22.8b},   [x9], x1
1319         st1             {v22.d}[1], [x0], x1
1320         st1             {v23.8b},   [x9], x1
1321         st1             {v23.d}[1], [x0], x1
1322         st1             {v24.8b},   [x9], x1
1323         st1             {v24.d}[1], [x0], x1
1324         st1             {v25.8b},   [x9], x1
1325         st1             {v25.d}[1], [x0], x1
1326         st1             {v26.8b},   [x9], x1
1327         st1             {v26.d}[1], [x0], x1
1328         st1             {v27.8b},   [x9], x1
1329         st1             {v27.d}[1], [x0], x1
1330         b               9b
1331 7:
1332         sub             x9,  x0,  #2
1333         add             x0,  x9,  x1, lsl #3
1334         transpose_4x16B v22, v23, v24, v25, v26, v27, v28, v29
1335         st1             {v22.s}[0], [x9], x1
1336         st1             {v22.s}[2], [x0], x1
1337         st1             {v23.s}[0], [x9], x1
1338         st1             {v23.s}[2], [x0], x1
1339         st1             {v24.s}[0], [x9], x1
1340         st1             {v24.s}[2], [x0], x1
1341         st1             {v25.s}[0], [x9], x1
1342         st1             {v25.s}[2], [x0], x1
1343         st1             {v22.s}[1], [x9], x1
1344         st1             {v22.s}[3], [x0], x1
1345         st1             {v23.s}[1], [x9], x1
1346         st1             {v23.s}[3], [x0], x1
1347         st1             {v24.s}[1], [x9], x1
1348         st1             {v24.s}[3], [x0], x1
1349         st1             {v25.s}[1], [x9], x1
1350         st1             {v25.s}[3], [x0], x1
1351         b               9b
1352 endfunc