9deb6562a5be73c0a01943054b22a2ff0ac709dd
[ffmpeg.git] / libavcodec / arm / vp9mc_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
23 @ All public functions in this file have the following signature:
24 @ typedef void (*vp9_mc_func)(uint8_t *dst, ptrdiff_t dst_stride,
25 @                            const uint8_t *ref, ptrdiff_t ref_stride,
26 @                            int h, int mx, int my);
27
28 function ff_vp9_copy64_neon, export=1
29         ldr             r12, [sp]
30         sub             r1,  r1,  #32
31         sub             r3,  r3,  #32
32 1:
33         vld1.8          {q0,  q1},  [r2]!
34         vst1.8          {q0,  q1},  [r0, :128]!
35         vld1.8          {q2,  q3},  [r2], r3
36         subs            r12, r12, #1
37         vst1.8          {q2,  q3},  [r0, :128], r1
38         bne             1b
39         bx              lr
40 endfunc
41
42 function ff_vp9_avg64_neon, export=1
43         push            {lr}
44         ldr             r12, [sp, #4]
45         sub             r1,  r1,  #32
46         sub             r3,  r3,  #32
47         mov             lr,  r0
48 1:
49         vld1.8          {q8,  q9},  [r2]!
50         vld1.8          {q0,  q1},  [r0, :128]!
51         vld1.8          {q10, q11}, [r2], r3
52         vrhadd.u8       q0,  q0,  q8
53         vld1.8          {q2,  q3},  [r0, :128], r1
54         vrhadd.u8       q1,  q1,  q9
55         vrhadd.u8       q2,  q2,  q10
56         vst1.8          {q0,  q1},  [lr, :128]!
57         vrhadd.u8       q3,  q3,  q11
58         vst1.8          {q2,  q3},  [lr, :128], r1
59         subs            r12, r12, #1
60         bne             1b
61         pop             {pc}
62 endfunc
63
64 function ff_vp9_copy32_neon, export=1
65         ldr             r12, [sp]
66 1:
67         vld1.8          {q0,  q1},  [r2], r3
68         subs            r12, r12, #1
69         vst1.8          {q0,  q1},  [r0, :128], r1
70         bne             1b
71         bx              lr
72 endfunc
73
74 function ff_vp9_avg32_neon, export=1
75         ldr             r12, [sp]
76 1:
77         vld1.8          {q2,  q3},  [r2], r3
78         vld1.8          {q0,  q1},  [r0, :128]
79         vrhadd.u8       q0,  q0,  q2
80         vrhadd.u8       q1,  q1,  q3
81         subs            r12, r12, #1
82         vst1.8          {q0, q1},  [r0, :128], r1
83         bne             1b
84         bx              lr
85 endfunc
86
87 function ff_vp9_copy16_neon, export=1
88         push            {r4,lr}
89         ldr             r12, [sp, #8]
90         add             r4,  r0,  r1
91         add             lr,  r2,  r3
92         add             r1,  r1,  r1
93         add             r3,  r3,  r3
94 1:
95         vld1.8          {q0},  [r2], r3
96         vld1.8          {q1},  [lr], r3
97         subs            r12, r12, #2
98         vst1.8          {q0},  [r0, :128], r1
99         vst1.8          {q1},  [r4, :128], r1
100         bne             1b
101         pop             {r4,pc}
102 endfunc
103
104 function ff_vp9_avg16_neon, export=1
105         push            {lr}
106         ldr             r12, [sp, #4]
107         mov             lr,  r0
108 1:
109         vld1.8          {q2},  [r2], r3
110         vld1.8          {q0},  [r0, :128], r1
111         vld1.8          {q3},  [r2], r3
112         vrhadd.u8       q0,  q0,  q2
113         vld1.8          {q1},  [r0, :128], r1
114         vrhadd.u8       q1,  q1,  q3
115         subs            r12, r12, #2
116         vst1.8          {q0},  [lr, :128], r1
117         vst1.8          {q1},  [lr, :128], r1
118         bne             1b
119         pop             {pc}
120 endfunc
121
122 function ff_vp9_copy8_neon, export=1
123         ldr             r12, [sp]
124 1:
125         vld1.8          {d0},  [r2], r3
126         vld1.8          {d1},  [r2], r3
127         subs            r12, r12, #2
128         vst1.8          {d0},  [r0, :64], r1
129         vst1.8          {d1},  [r0, :64], r1
130         bne             1b
131         bx              lr
132 endfunc
133
134 function ff_vp9_avg8_neon, export=1
135         ldr             r12, [sp]
136 1:
137         vld1.8          {d2},  [r2], r3
138         vld1.8          {d0},  [r0, :64], r1
139         vld1.8          {d3},  [r2], r3
140         vrhadd.u8       d0,  d0,  d2
141         vld1.8          {d1},  [r0, :64]
142         sub             r0,  r0,  r1
143         vrhadd.u8       d1,  d1,  d3
144         subs            r12, r12, #2
145         vst1.8          {d0},  [r0, :64], r1
146         vst1.8          {d1},  [r0, :64], r1
147         bne             1b
148         bx              lr
149 endfunc
150
151 function ff_vp9_copy4_neon, export=1
152         ldr             r12, [sp]
153 1:
154         vld1.32         {d0[]},   [r2], r3
155         vld1.32         {d1[]},   [r2], r3
156         vst1.32         {d0[0]},  [r0, :32], r1
157         vld1.32         {d2[]},   [r2], r3
158         vst1.32         {d1[0]},  [r0, :32], r1
159         vld1.32         {d3[]},   [r2], r3
160         subs            r12, r12, #4
161         vst1.32         {d2[0]},  [r0, :32], r1
162         vst1.32         {d3[0]},  [r0, :32], r1
163         bne             1b
164         bx              lr
165 endfunc
166
167 function ff_vp9_avg4_neon, export=1
168         push            {lr}
169         ldr             r12, [sp, #4]
170         mov             lr,  r0
171 1:
172         vld1.32         {d4[]},   [r2], r3
173         vld1.32         {d0[]},   [r0, :32], r1
174         vld1.32         {d5[]},   [r2], r3
175         vrhadd.u8       d0,  d0,  d4
176         vld1.32         {d1[]},   [r0, :32], r1
177         vld1.32         {d6[]},   [r2], r3
178         vrhadd.u8       d1,  d1,  d5
179         vld1.32         {d2[]},   [r0, :32], r1
180         vld1.32         {d7[]},   [r2], r3
181         vrhadd.u8       d2,  d2,  d6
182         vld1.32         {d3[]},   [r0, :32], r1
183         subs            r12, r12, #4
184         vst1.32         {d0[0]},  [lr, :32], r1
185         vrhadd.u8       d3,  d3,  d7
186         vst1.32         {d1[0]},  [lr, :32], r1
187         vst1.32         {d2[0]},  [lr, :32], r1
188         vst1.32         {d3[0]},  [lr, :32], r1
189         bne             1b
190         pop             {pc}
191 endfunc
192
193 @ Helper macros for vmul/vmla with a constant from either d0 or d1 depending on index
194 .macro vmul_lane dst, src, idx
195 .if \idx < 4
196        vmul.s16         \dst, \src, d0[\idx]
197 .else
198        vmul.s16         \dst, \src, d1[\idx - 4]
199 .endif
200 .endm
201 .macro vmla_lane dst, src, idx
202 .if \idx < 4
203        vmla.s16         \dst, \src, d0[\idx]
204 .else
205        vmla.s16         \dst, \src, d1[\idx - 4]
206 .endif
207 .endm
208
209 @ Extract a vector from src1-src2 and src4-src5 (src1-src3 and src4-src6
210 @ for size >= 16), and multiply-accumulate into dst1 and dst3 (or
211 @ dst1-dst2 and dst3-dst4 for size >= 16)
212 .macro extmla dst1, dst2, dst3, dst4, src1, src2, src3, src4, src5, src6, offset, size
213         vext.8          q14, \src1, \src2, #(2*\offset)
214         vext.8          q15, \src4, \src5, #(2*\offset)
215 .if \size >= 16
216         vmla_lane       \dst1,  q14, \offset
217         vext.8          q5,  \src2, \src3, #(2*\offset)
218         vmla_lane       \dst3,  q15, \offset
219         vext.8          q6,  \src5, \src6, #(2*\offset)
220         vmla_lane       \dst2,  q5,  \offset
221         vmla_lane       \dst4,  q6,  \offset
222 .else
223         vmla_lane       \dst1,  q14, \offset
224         vmla_lane       \dst3,  q15, \offset
225 .endif
226 .endm
227 @ The same as above, but don't accumulate straight into the
228 @ destination, but use a temp register and accumulate with saturation.
229 .macro extmulqadd dst1, dst2, dst3, dst4, src1, src2, src3, src4, src5, src6, offset, size
230         vext.8          q14, \src1, \src2, #(2*\offset)
231         vext.8          q15, \src4, \src5, #(2*\offset)
232 .if \size >= 16
233         vmul_lane       q14, q14, \offset
234         vext.8          q5,  \src2, \src3, #(2*\offset)
235         vmul_lane       q15, q15, \offset
236         vext.8          q6,  \src5, \src6, #(2*\offset)
237         vmul_lane       q5,  q5,  \offset
238         vmul_lane       q6,  q6,  \offset
239 .else
240         vmul_lane       q14, q14, \offset
241         vmul_lane       q15, q15, \offset
242 .endif
243         vqadd.s16       \dst1,  \dst1,  q14
244         vqadd.s16       \dst3,  \dst3,  q15
245 .if \size >= 16
246         vqadd.s16       \dst2,  \dst2,  q5
247         vqadd.s16       \dst4,  \dst4,  q6
248 .endif
249 .endm
250
251
252 @ Instantiate a horizontal filter function for the given size.
253 @ This can work on 4, 8 or 16 pixels in parallel; for larger
254 @ widths it will do 16 pixels at a time and loop horizontally.
255 @ The actual width is passed in r5, the height in r4 and
256 @ the filter coefficients in r12. idx2 is the index of the largest
257 @ filter coefficient (3 or 4) and idx1 is the other one of them.
258 .macro do_8tap_h type, size, idx1, idx2
259 function \type\()_8tap_\size\()h_\idx1\idx2
260         sub             r2,  r2,  #3
261         add             r6,  r0,  r1
262         add             r7,  r2,  r3
263         add             r1,  r1,  r1
264         add             r3,  r3,  r3
265         @ Only size >= 16 loops horizontally and needs
266         @ reduced dst stride
267 .if \size >= 16
268         sub             r1,  r1,  r5
269 .endif
270         @ size >= 16 loads two qwords and increments r2,
271         @ for size 4/8 it's enough with one qword and no
272         @ postincrement
273 .if \size >= 16
274         sub             r3,  r3,  r5
275         sub             r3,  r3,  #8
276 .endif
277         @ Load the filter vector
278         vld1.8          {d0},  [r12,:64]
279         vmovl.s8        q0,  d0
280 1:
281 .if \size >= 16
282         mov             r12, r5
283 .endif
284         @ Load src
285 .if \size >= 16
286         vld1.8          {d18, d19, d20}, [r2]!
287         vld1.8          {d24, d25, d26}, [r7]!
288 .else
289         vld1.8          {q9},  [r2]
290         vld1.8          {q12}, [r7]
291 .endif
292         vmovl.u8        q8,  d18
293         vmovl.u8        q9,  d19
294         vmovl.u8        q11, d24
295         vmovl.u8        q12, d25
296 .if \size >= 16
297         vmovl.u8        q10, d20
298         vmovl.u8        q13, d26
299 .endif
300 2:
301
302         @ Accumulate, adding idx2 last with a separate
303         @ saturating add. The positive filter coefficients
304         @ for all indices except idx2 must add up to less
305         @ than 127 for this not to overflow.
306         vmul.s16        q1,  q8,  d0[0]
307         vmul.s16        q3,  q11, d0[0]
308 .if \size >= 16
309         vmul.s16        q2,  q9,  d0[0]
310         vmul.s16        q4,  q12, d0[0]
311 .endif
312         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, 1,     \size
313         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, 2,     \size
314         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, \idx1, \size
315         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, 5,     \size
316         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, 6,     \size
317         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, 7,     \size
318         extmulqadd      q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, \idx2, \size
319
320         @ Round, shift and saturate
321         vqrshrun.s16    d2,  q1,  #7
322         vqrshrun.s16    d6,  q3,  #7
323 .if \size >= 16
324         vqrshrun.s16    d3,  q2,  #7
325         vqrshrun.s16    d7,  q4,  #7
326 .endif
327         @ Average
328 .ifc \type,avg
329 .if \size >= 16
330         vld1.8          {q14}, [r0,:128]
331         vld1.8          {q15}, [r6,:128]
332         vrhadd.u8       q1,  q1,  q14
333         vrhadd.u8       q3,  q3,  q15
334 .elseif \size == 8
335         vld1.8          {d28}, [r0,:64]
336         vld1.8          {d30}, [r6,:64]
337         vrhadd.u8       d2,  d2,  d28
338         vrhadd.u8       d6,  d6,  d30
339 .else
340         @ We only need d28[0], but [] is faster on some cores
341         vld1.32         {d28[]}, [r0,:32]
342         vld1.32         {d30[]}, [r6,:32]
343         vrhadd.u8       d2,  d2,  d28
344         vrhadd.u8       d6,  d6,  d30
345 .endif
346 .endif
347         @ Store and loop horizontally (for size >= 16)
348 .if \size >= 16
349         subs            r12, r12, #16
350         vst1.8          {q1}, [r0,:128]!
351         vst1.8          {q3}, [r6,:128]!
352         beq             3f
353         vmov            q8,  q10
354         vmov            q11, q13
355         vld1.8          {q10}, [r2]!
356         vld1.8          {q13}, [r7]!
357         vmovl.u8        q9,  d20
358         vmovl.u8        q10, d21
359         vmovl.u8        q12, d26
360         vmovl.u8        q13, d27
361         b               2b
362 .elseif \size == 8
363         vst1.8          {d2}, [r0,:64]
364         vst1.8          {d6}, [r6,:64]
365 .else @ \size == 4
366         vst1.32         {d2[0]}, [r0,:32]
367         vst1.32         {d6[0]}, [r6,:32]
368 .endif
369 3:
370         @ Loop vertically
371         add             r0,  r0,  r1
372         add             r6,  r6,  r1
373         add             r2,  r2,  r3
374         add             r7,  r7,  r3
375         subs            r4,  r4,  #2
376         bne             1b
377 .if \size >= 16
378         vpop            {q4-q6}
379 .endif
380         pop             {r4-r7}
381         bx              lr
382 endfunc
383 .endm
384
385 .macro do_8tap_h_size size
386 do_8tap_h put, \size, 3, 4
387 do_8tap_h avg, \size, 3, 4
388 do_8tap_h put, \size, 4, 3
389 do_8tap_h avg, \size, 4, 3
390 .endm
391
392 do_8tap_h_size 4
393 do_8tap_h_size 8
394 do_8tap_h_size 16
395
396 .macro do_8tap_h_func type, filter, offset, size
397 function ff_vp9_\type\()_\filter\()\size\()_h_neon, export=1
398         push            {r4-r7}
399 .if \size >= 16
400         vpush           {q4-q6}
401         ldr             r4,  [sp, #64]
402         ldr             r5,  [sp, #68]
403 .else
404         ldr             r4,  [sp, #16]
405         ldr             r5,  [sp, #20]
406 .endif
407         movrelx         r12, X(ff_vp9_subpel_filters)
408         add             r12, r12, 120*\offset - 8
409         cmp             r5,  #8
410         add             r12, r12, r5, lsl #3
411         mov             r5, #\size
412 .if \size >= 16
413         bge             \type\()_8tap_16h_34
414         b               \type\()_8tap_16h_43
415 .else
416         bge             \type\()_8tap_\size\()h_34
417         b               \type\()_8tap_\size\()h_43
418 .endif
419 endfunc
420 .endm
421
422 .macro do_8tap_h_filters size
423 do_8tap_h_func put, regular, 1, \size
424 do_8tap_h_func avg, regular, 1, \size
425 do_8tap_h_func put, sharp,   2, \size
426 do_8tap_h_func avg, sharp,   2, \size
427 do_8tap_h_func put, smooth,  0, \size
428 do_8tap_h_func avg, smooth,  0, \size
429 .endm
430
431 do_8tap_h_filters 64
432 do_8tap_h_filters 32
433 do_8tap_h_filters 16
434 do_8tap_h_filters 8
435 do_8tap_h_filters 4
436
437 .ltorg
438
439 @ Vertical filters
440
441 @ Round, shift and saturate and store qreg1-2 over 4 lines
442 .macro do_store4 qreg1, dreg1, qreg2, dreg2, tmp1, tmp2, type
443         vqrshrun.s16    \dreg1,  \qreg1, #7
444         vqrshrun.s16    \dreg2,  \qreg2, #7
445 .ifc \type,avg
446         vld1.32         {\tmp1[]},   [r0,:32], r1
447         vld1.32         {\tmp2[]},   [r0,:32], r1
448         vld1.32         {\tmp1[1]},  [r0,:32], r1
449         vld1.32         {\tmp2[1]},  [r0,:32], r1
450         vrhadd.u8       \dreg1,  \dreg1,  \tmp1
451         vrhadd.u8       \dreg2,  \dreg2,  \tmp2
452         sub             r0,  r0,  r1, lsl #2
453 .endif
454         vst1.32         {\dreg1[0]}, [r0,:32], r1
455         vst1.32         {\dreg2[0]}, [r0,:32], r1
456         vst1.32         {\dreg1[1]}, [r0,:32], r1
457         vst1.32         {\dreg2[1]}, [r0,:32], r1
458 .endm
459
460 @ Round, shift and saturate and store qreg1-4
461 .macro do_store qreg1, dreg1, qreg2, dreg2, qreg3, dreg3, qreg4, dreg4, tmp1, tmp2, tmp3, tmp4, type
462         vqrshrun.s16    \dreg1,  \qreg1, #7
463         vqrshrun.s16    \dreg2,  \qreg2, #7
464         vqrshrun.s16    \dreg3,  \qreg3, #7
465         vqrshrun.s16    \dreg4,  \qreg4, #7
466 .ifc \type,avg
467         vld1.8          {\tmp1},  [r0,:64], r1
468         vld1.8          {\tmp2},  [r0,:64], r1
469         vld1.8          {\tmp3},  [r0,:64], r1
470         vld1.8          {\tmp4},  [r0,:64], r1
471         vrhadd.u8       \dreg1,  \dreg1,  \tmp1
472         vrhadd.u8       \dreg2,  \dreg2,  \tmp2
473         vrhadd.u8       \dreg3,  \dreg3,  \tmp3
474         vrhadd.u8       \dreg4,  \dreg4,  \tmp4
475         sub             r0,  r0,  r1, lsl #2
476 .endif
477         vst1.8          {\dreg1}, [r0,:64], r1
478         vst1.8          {\dreg2}, [r0,:64], r1
479         vst1.8          {\dreg3}, [r0,:64], r1
480         vst1.8          {\dreg4}, [r0,:64], r1
481 .endm
482
483 @ Evaluate the filter twice in parallel, from the inputs src1-src9 into dst1-dst2
484 @ (src1-src8 into dst1, src2-src9 into dst2), adding idx2 separately
485 @ at the end with saturation. Indices 0 and 7 always have negative or zero
486 @ coefficients, so they can be accumulated into tmp1-tmp2 together with the
487 @ largest coefficient.
488 .macro convolve dst1, dst2, src1, src2, src3, src4, src5, src6, src7, src8, src9, idx1, idx2, tmp1, tmp2
489         vmul.s16        \dst1, \src2, d0[1]
490         vmul.s16        \dst2, \src3, d0[1]
491         vmul.s16        \tmp1, \src1, d0[0]
492         vmul.s16        \tmp2, \src2, d0[0]
493         vmla.s16        \dst1, \src3, d0[2]
494         vmla.s16        \dst2, \src4, d0[2]
495 .if \idx1 == 3
496         vmla.s16        \dst1, \src4, d0[3]
497         vmla.s16        \dst2, \src5, d0[3]
498 .else
499         vmla.s16        \dst1, \src5, d1[0]
500         vmla.s16        \dst2, \src6, d1[0]
501 .endif
502         vmla.s16        \dst1, \src6, d1[1]
503         vmla.s16        \dst2, \src7, d1[1]
504         vmla.s16        \tmp1, \src8, d1[3]
505         vmla.s16        \tmp2, \src9, d1[3]
506         vmla.s16        \dst1, \src7, d1[2]
507         vmla.s16        \dst2, \src8, d1[2]
508 .if \idx2 == 3
509         vmla.s16        \tmp1, \src4, d0[3]
510         vmla.s16        \tmp2, \src5, d0[3]
511 .else
512         vmla.s16        \tmp1, \src5, d1[0]
513         vmla.s16        \tmp2, \src6, d1[0]
514 .endif
515         vqadd.s16       \dst1, \dst1, \tmp1
516         vqadd.s16       \dst2, \dst2, \tmp2
517 .endm
518
519 @ Load pixels and extend them to 16 bit
520 .macro loadl dst1, dst2, dst3, dst4
521         vld1.8          {d2}, [r2], r3
522         vld1.8          {d3}, [r2], r3
523         vld1.8          {d4}, [r2], r3
524 .ifnb \dst4
525         vld1.8          {d5}, [r2], r3
526 .endif
527         vmovl.u8        \dst1, d2
528         vmovl.u8        \dst2, d3
529         vmovl.u8        \dst3, d4
530 .ifnb \dst4
531         vmovl.u8        \dst4, d5
532 .endif
533 .endm
534
535 @ Instantiate a vertical filter function for filtering 8 pixels at a time.
536 @ The height is passed in r4, the width in r5 and the filter coefficients
537 @ in r12. idx2 is the index of the largest filter coefficient (3 or 4)
538 @ and idx1 is the other one of them.
539 .macro do_8tap_8v type, idx1, idx2
540 function \type\()_8tap_8v_\idx1\idx2
541         sub             r2,  r2,  r3, lsl #1
542         sub             r2,  r2,  r3
543         vld1.8          {d0},  [r12, :64]
544         vmovl.s8        q0,  d0
545 1:
546         mov             r12,  r4
547
548         loadl           q5,  q6,  q7
549         loadl           q8,  q9,  q10, q11
550 2:
551         loadl           q12, q13, q14, q15
552         convolve        q1,  q2,  q5,  q6,  q7,  q8,  q9,  q10, q11, q12, q13, \idx1, \idx2, q4,  q5
553         convolve        q3,  q4,  q7,  q8,  q9,  q10, q11, q12, q13, q14, q15, \idx1, \idx2, q5,  q6
554         do_store        q1,  d2,  q2,  d4,  q3,  d6,  q4,  d8,  d3,  d5,  d7,  d9,  \type
555
556         subs            r12, r12, #4
557         beq             8f
558
559         loadl           q4,  q5,  q6,  q7
560         convolve        q1,  q2,  q9,  q10, q11, q12, q13, q14, q15, q4,  q5,  \idx1, \idx2, q8,  q9
561         convolve        q3,  q8,  q11, q12, q13, q14, q15, q4,  q5,  q6,  q7,  \idx1, \idx2, q9,  q10
562         do_store        q1,  d2,  q2,  d4,  q3,  d6,  q8,  d16, d3,  d5,  d7,  d17, \type
563
564         subs            r12, r12, #4
565         beq             8f
566
567         loadl           q8,  q9,  q10, q11
568         convolve        q1,  q2,  q13, q14, q15, q4,  q5,  q6,  q7,  q8,  q9,  \idx1, \idx2, q12, q13
569         convolve        q3,  q12, q15, q4,  q5,  q6,  q7,  q8,  q9,  q10, q11, \idx1, \idx2, q13, q14
570         do_store        q1,  d2,  q2,  d4,  q3,  d6,  q12, d24, d3,  d5,  d7,  d25, \type
571
572         subs            r12, r12, #4
573         bne             2b
574
575 8:
576         subs            r5,  r5,  #8
577         beq             9f
578         @ r0 -= h * dst_stride
579         mls             r0,  r1,  r4, r0
580         @ r2 -= h * src_stride
581         mls             r2,  r3,  r4, r2
582         @ r2 -= 8 * src_stride
583         sub             r2,  r2,  r3, lsl #3
584         @ r2 += 1 * src_stride
585         add             r2,  r2,  r3
586         add             r2,  r2,  #8
587         add             r0,  r0,  #8
588         b               1b
589 9:
590         vpop            {q4-q7}
591         pop             {r4-r5}
592         bx              lr
593 endfunc
594 .endm
595
596 do_8tap_8v put, 3, 4
597 do_8tap_8v put, 4, 3
598 do_8tap_8v avg, 3, 4
599 do_8tap_8v avg, 4, 3
600
601 @ Instantiate a vertical filter function for filtering a 4 pixels wide
602 @ slice. The first half of the registers contain one row, while the second
603 @ half of a register contains the second-next row (also stored in the first
604 @ half of the register two steps ahead). The convolution does two outputs
605 @ at a time; the output of q5-q12 into one, and q4-q13 into another one.
606 @ The first half of first output is the first output row, the first half
607 @ of the other output is the second output row. The second halves of the
608 @ registers are rows 3 and 4.
609 @ This only is designed to work for 4 or 8 output lines.
610 .macro do_8tap_4v type, idx1, idx2
611 function \type\()_8tap_4v_\idx1\idx2
612         sub             r2,  r2,  r3, lsl #1
613         sub             r2,  r2,  r3
614         vld1.8          {d0},  [r12, :64]
615         vmovl.s8        q0,  d0
616
617         vld1.32         {d2[]},   [r2], r3
618         vld1.32         {d3[]},   [r2], r3
619         vld1.32         {d4[]},   [r2], r3
620         vld1.32         {d5[]},   [r2], r3
621         vld1.32         {d6[]},   [r2], r3
622         vld1.32         {d7[]},   [r2], r3
623         vext.8          d2,  d2,  d4,  #4
624         vld1.32         {d8[]},   [r2], r3
625         vext.8          d3,  d3,  d5,  #4
626         vld1.32         {d9[]},   [r2], r3
627         vmovl.u8        q5,  d2
628         vext.8          d4,  d4,  d6,  #4
629         vld1.32         {d28[]},  [r2], r3
630         vmovl.u8        q6,  d3
631         vext.8          d5,  d5,  d7,  #4
632         vld1.32         {d29[]},  [r2], r3
633         vmovl.u8        q7,  d4
634         vext.8          d6,  d6,  d8,  #4
635         vld1.32         {d30[]},  [r2], r3
636         vmovl.u8        q8,  d5
637         vext.8          d7,  d7,  d9,  #4
638         vmovl.u8        q9,  d6
639         vext.8          d8,  d8,  d28, #4
640         vmovl.u8        q10, d7
641         vext.8          d9,  d9,  d29, #4
642         vmovl.u8        q11, d8
643         vext.8          d28, d28, d30, #4
644         vmovl.u8        q12, d9
645         vmovl.u8        q13, d28
646
647         convolve        q1,  q2,  q5,  q6,  q7,  q8,  q9,  q10, q11, q12, q13, \idx1, \idx2, q4, q3
648         do_store4       q1,  d2,  q2,  d4,  d3,  d5,  \type
649         subs            r4,  r4,  #4
650         beq             9f
651
652         vld1.32         {d2[]},   [r2], r3
653         vld1.32         {d3[]},   [r2], r3
654         vext.8          d29, d29, d2,  #4
655         vext.8          d30, d30, d3,  #4
656         vld1.32         {d2[1]},  [r2], r3
657         vmovl.u8        q14, d29
658         vld1.32         {d3[1]},  [r2], r3
659         vmovl.u8        q15, d30
660         vmovl.u8        q5,  d2
661         vmovl.u8        q6,  d3
662
663         convolve        q1,  q2,  q9,  q10, q11, q12, q13, q14, q15, q5,  q6,  \idx1, \idx2, q4, q3
664         do_store4       q1,  d2,  q2,  d4,  d3,  d5,  \type
665
666 9:
667         vpop            {q4-q7}
668         pop             {r4-r5}
669         bx              lr
670 endfunc
671 .endm
672
673 do_8tap_4v put, 3, 4
674 do_8tap_4v put, 4, 3
675 do_8tap_4v avg, 3, 4
676 do_8tap_4v avg, 4, 3
677
678 .macro do_8tap_v_func type, filter, offset, size
679 function ff_vp9_\type\()_\filter\()\size\()_v_neon, export=1
680         push            {r4-r5}
681         vpush           {q4-q7}
682         ldr             r4,  [sp, #72]
683         ldr             r5,  [sp, #80]
684         movrelx         r12, X(ff_vp9_subpel_filters)
685         add             r12, r12, 120*\offset - 8
686         add             r12, r12, r5, lsl #3
687         cmp             r5,  #8
688         mov             r5,  #\size
689 .if \size >= 8
690         bge             \type\()_8tap_8v_34
691         b               \type\()_8tap_8v_43
692 .else
693         bge             \type\()_8tap_4v_34
694         b               \type\()_8tap_4v_43
695 .endif
696 endfunc
697 .endm
698
699 .macro do_8tap_v_filters size
700 do_8tap_v_func put, regular, 1, \size
701 do_8tap_v_func avg, regular, 1, \size
702 do_8tap_v_func put, sharp,   2, \size
703 do_8tap_v_func avg, sharp,   2, \size
704 do_8tap_v_func put, smooth,  0, \size
705 do_8tap_v_func avg, smooth,  0, \size
706 .endm
707
708 do_8tap_v_filters 64
709 do_8tap_v_filters 32
710 do_8tap_v_filters 16
711 do_8tap_v_filters 8
712 do_8tap_v_filters 4