]> git.sesse.net Git - ffmpeg/blob - libavcodec/arm/vp9mc_neon.S
Merge commit 'cc16da75c2f99d92f7a6461100f041352deb6d88'
[ffmpeg] / libavcodec / arm / vp9mc_neon.S
1 /*
2  * Copyright (c) 2016 Google Inc.
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "libavutil/arm/asm.S"
22
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.16         {q0},  [r12,:128]
279 1:
280 .if \size >= 16
281         mov             r12, r5
282 .endif
283         @ Load src
284 .if \size >= 16
285         vld1.8          {d18, d19, d20}, [r2]!
286         vld1.8          {d24, d25, d26}, [r7]!
287 .else
288         vld1.8          {q9},  [r2]
289         vld1.8          {q12}, [r7]
290 .endif
291         vmovl.u8        q8,  d18
292         vmovl.u8        q9,  d19
293         vmovl.u8        q11, d24
294         vmovl.u8        q12, d25
295 .if \size >= 16
296         vmovl.u8        q10, d20
297         vmovl.u8        q13, d26
298 .endif
299 2:
300
301         @ Accumulate, adding idx2 last with a separate
302         @ saturating add. The positive filter coefficients
303         @ for all indices except idx2 must add up to less
304         @ than 127 for this not to overflow.
305         vmul.s16        q1,  q8,  d0[0]
306         vmul.s16        q3,  q11, d0[0]
307 .if \size >= 16
308         vmul.s16        q2,  q9,  d0[0]
309         vmul.s16        q4,  q12, d0[0]
310 .endif
311         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, 1,     \size
312         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, 2,     \size
313         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, \idx1, \size
314         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, 5,     \size
315         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, 6,     \size
316         extmla          q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, 7,     \size
317         extmulqadd      q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12, q13, \idx2, \size
318
319         @ Round, shift and saturate
320         vqrshrun.s16    d2,  q1,  #7
321         vqrshrun.s16    d6,  q3,  #7
322 .if \size >= 16
323         vqrshrun.s16    d3,  q2,  #7
324         vqrshrun.s16    d7,  q4,  #7
325 .endif
326         @ Average
327 .ifc \type,avg
328 .if \size >= 16
329         vld1.8          {q14}, [r0,:128]
330         vld1.8          {q15}, [r6,:128]
331         vrhadd.u8       q1,  q1,  q14
332         vrhadd.u8       q3,  q3,  q15
333 .elseif \size == 8
334         vld1.8          {d28}, [r0,:64]
335         vld1.8          {d30}, [r6,:64]
336         vrhadd.u8       d2,  d2,  d28
337         vrhadd.u8       d6,  d6,  d30
338 .else
339         @ We only need d28[0], but [] is faster on some cores
340         vld1.32         {d28[]}, [r0,:32]
341         vld1.32         {d30[]}, [r6,:32]
342         vrhadd.u8       d2,  d2,  d28
343         vrhadd.u8       d6,  d6,  d30
344 .endif
345 .endif
346         @ Store and loop horizontally (for size >= 16)
347 .if \size >= 16
348         subs            r12, r12, #16
349         vst1.8          {q1}, [r0,:128]!
350         vst1.8          {q3}, [r6,:128]!
351         beq             3f
352         vmov            q8,  q10
353         vmov            q11, q13
354         vld1.8          {q10}, [r2]!
355         vld1.8          {q13}, [r7]!
356         vmovl.u8        q9,  d20
357         vmovl.u8        q10, d21
358         vmovl.u8        q12, d26
359         vmovl.u8        q13, d27
360         b               2b
361 .elseif \size == 8
362         vst1.8          {d2}, [r0,:64]
363         vst1.8          {d6}, [r6,:64]
364 .else @ \size == 4
365         vst1.32         {d2[0]}, [r0,:32]
366         vst1.32         {d6[0]}, [r6,:32]
367 .endif
368 3:
369         @ Loop vertically
370         add             r0,  r0,  r1
371         add             r6,  r6,  r1
372         add             r2,  r2,  r3
373         add             r7,  r7,  r3
374         subs            r4,  r4,  #2
375         bne             1b
376 .if \size >= 16
377         vpop            {q4-q6}
378 .endif
379         pop             {r4-r7}
380         bx              lr
381 endfunc
382 .endm
383
384 .macro do_8tap_h_size size
385 do_8tap_h put, \size, 3, 4
386 do_8tap_h avg, \size, 3, 4
387 do_8tap_h put, \size, 4, 3
388 do_8tap_h avg, \size, 4, 3
389 .endm
390
391 do_8tap_h_size 4
392 do_8tap_h_size 8
393 do_8tap_h_size 16
394
395 .macro do_8tap_h_func type, filter, offset, size
396 function ff_vp9_\type\()_\filter\()\size\()_h_neon, export=1
397         push            {r4-r7}
398 .if \size >= 16
399         vpush           {q4-q6}
400         ldr             r4,  [sp, #64]
401         ldr             r5,  [sp, #68]
402 .else
403         ldr             r4,  [sp, #16]
404         ldr             r5,  [sp, #20]
405 .endif
406         movrelx         r12, X(ff_vp9_subpel_filters), r6
407         add             r12, r12, 256*\offset
408         cmp             r5,  #8
409         add             r12, r12, r5, lsl #4
410         mov             r5,  #\size
411 .if \size >= 16
412         bge             \type\()_8tap_16h_34
413         b               \type\()_8tap_16h_43
414 .else
415         bge             \type\()_8tap_\size\()h_34
416         b               \type\()_8tap_\size\()h_43
417 .endif
418 endfunc
419 .endm
420
421 .macro do_8tap_h_filters size
422 do_8tap_h_func put, regular, 1, \size
423 do_8tap_h_func avg, regular, 1, \size
424 do_8tap_h_func put, sharp,   2, \size
425 do_8tap_h_func avg, sharp,   2, \size
426 do_8tap_h_func put, smooth,  0, \size
427 do_8tap_h_func avg, smooth,  0, \size
428 .endm
429
430 do_8tap_h_filters 64
431 do_8tap_h_filters 32
432 do_8tap_h_filters 16
433 do_8tap_h_filters 8
434 do_8tap_h_filters 4
435
436 .ltorg
437
438 @ Vertical filters
439
440 @ Round, shift and saturate and store qreg1-2 over 4 lines
441 .macro do_store4 qreg1, dreg1, qreg2, dreg2, tmp1, tmp2, type
442         vqrshrun.s16    \dreg1,  \qreg1, #7
443         vqrshrun.s16    \dreg2,  \qreg2, #7
444 .ifc \type,avg
445         vld1.32         {\tmp1[]},   [r0,:32], r1
446         vld1.32         {\tmp2[]},   [r0,:32], r1
447         vld1.32         {\tmp1[1]},  [r0,:32], r1
448         vld1.32         {\tmp2[1]},  [r0,:32], r1
449         vrhadd.u8       \dreg1,  \dreg1,  \tmp1
450         vrhadd.u8       \dreg2,  \dreg2,  \tmp2
451         sub             r0,  r0,  r1, lsl #2
452 .endif
453         vst1.32         {\dreg1[0]}, [r0,:32], r1
454         vst1.32         {\dreg2[0]}, [r0,:32], r1
455         vst1.32         {\dreg1[1]}, [r0,:32], r1
456         vst1.32         {\dreg2[1]}, [r0,:32], r1
457 .endm
458
459 @ Round, shift and saturate and store qreg1-4
460 .macro do_store qreg1, dreg1, qreg2, dreg2, qreg3, dreg3, qreg4, dreg4, tmp1, tmp2, tmp3, tmp4, type
461         vqrshrun.s16    \dreg1,  \qreg1, #7
462         vqrshrun.s16    \dreg2,  \qreg2, #7
463         vqrshrun.s16    \dreg3,  \qreg3, #7
464         vqrshrun.s16    \dreg4,  \qreg4, #7
465 .ifc \type,avg
466         vld1.8          {\tmp1},  [r0,:64], r1
467         vld1.8          {\tmp2},  [r0,:64], r1
468         vld1.8          {\tmp3},  [r0,:64], r1
469         vld1.8          {\tmp4},  [r0,:64], r1
470         vrhadd.u8       \dreg1,  \dreg1,  \tmp1
471         vrhadd.u8       \dreg2,  \dreg2,  \tmp2
472         vrhadd.u8       \dreg3,  \dreg3,  \tmp3
473         vrhadd.u8       \dreg4,  \dreg4,  \tmp4
474         sub             r0,  r0,  r1, lsl #2
475 .endif
476         vst1.8          {\dreg1}, [r0,:64], r1
477         vst1.8          {\dreg2}, [r0,:64], r1
478         vst1.8          {\dreg3}, [r0,:64], r1
479         vst1.8          {\dreg4}, [r0,:64], r1
480 .endm
481
482 @ Evaluate the filter twice in parallel, from the inputs src1-src9 into dst1-dst2
483 @ (src1-src8 into dst1, src2-src9 into dst2), adding idx2 separately
484 @ at the end with saturation. Indices 0 and 7 always have negative or zero
485 @ coefficients, so they can be accumulated into tmp1-tmp2 together with the
486 @ largest coefficient.
487 .macro convolve dst1, dst2, src1, src2, src3, src4, src5, src6, src7, src8, src9, idx1, idx2, tmp1, tmp2
488         vmul.s16        \dst1, \src2, d0[1]
489         vmul.s16        \dst2, \src3, d0[1]
490         vmul.s16        \tmp1, \src1, d0[0]
491         vmul.s16        \tmp2, \src2, d0[0]
492         vmla.s16        \dst1, \src3, d0[2]
493         vmla.s16        \dst2, \src4, d0[2]
494 .if \idx1 == 3
495         vmla.s16        \dst1, \src4, d0[3]
496         vmla.s16        \dst2, \src5, d0[3]
497 .else
498         vmla.s16        \dst1, \src5, d1[0]
499         vmla.s16        \dst2, \src6, d1[0]
500 .endif
501         vmla.s16        \dst1, \src6, d1[1]
502         vmla.s16        \dst2, \src7, d1[1]
503         vmla.s16        \tmp1, \src8, d1[3]
504         vmla.s16        \tmp2, \src9, d1[3]
505         vmla.s16        \dst1, \src7, d1[2]
506         vmla.s16        \dst2, \src8, d1[2]
507 .if \idx2 == 3
508         vmla.s16        \tmp1, \src4, d0[3]
509         vmla.s16        \tmp2, \src5, d0[3]
510 .else
511         vmla.s16        \tmp1, \src5, d1[0]
512         vmla.s16        \tmp2, \src6, d1[0]
513 .endif
514         vqadd.s16       \dst1, \dst1, \tmp1
515         vqadd.s16       \dst2, \dst2, \tmp2
516 .endm
517
518 @ Load pixels and extend them to 16 bit
519 .macro loadl dst1, dst2, dst3, dst4
520         vld1.8          {d2}, [r2], r3
521         vld1.8          {d3}, [r2], r3
522         vld1.8          {d4}, [r2], r3
523 .ifnb \dst4
524         vld1.8          {d5}, [r2], r3
525 .endif
526         vmovl.u8        \dst1, d2
527         vmovl.u8        \dst2, d3
528         vmovl.u8        \dst3, d4
529 .ifnb \dst4
530         vmovl.u8        \dst4, d5
531 .endif
532 .endm
533
534 @ Instantiate a vertical filter function for filtering 8 pixels at a time.
535 @ The height is passed in r4, the width in r5 and the filter coefficients
536 @ in r12. idx2 is the index of the largest filter coefficient (3 or 4)
537 @ and idx1 is the other one of them.
538 .macro do_8tap_8v type, idx1, idx2
539 function \type\()_8tap_8v_\idx1\idx2
540         sub             r2,  r2,  r3, lsl #1
541         sub             r2,  r2,  r3
542         vld1.16         {q0},  [r12, :128]
543 1:
544         mov             r12, r4
545
546         loadl           q5,  q6,  q7
547         loadl           q8,  q9,  q10, q11
548 2:
549         loadl           q12, q13, q14, q15
550         convolve        q1,  q2,  q5,  q6,  q7,  q8,  q9,  q10, q11, q12, q13, \idx1, \idx2, q4,  q5
551         convolve        q3,  q4,  q7,  q8,  q9,  q10, q11, q12, q13, q14, q15, \idx1, \idx2, q5,  q6
552         do_store        q1,  d2,  q2,  d4,  q3,  d6,  q4,  d8,  d3,  d5,  d7,  d9,  \type
553
554         subs            r12, r12, #4
555         beq             8f
556
557         loadl           q4,  q5,  q6,  q7
558         convolve        q1,  q2,  q9,  q10, q11, q12, q13, q14, q15, q4,  q5,  \idx1, \idx2, q8,  q9
559         convolve        q3,  q8,  q11, q12, q13, q14, q15, q4,  q5,  q6,  q7,  \idx1, \idx2, q9,  q10
560         do_store        q1,  d2,  q2,  d4,  q3,  d6,  q8,  d16, d3,  d5,  d7,  d17, \type
561
562         subs            r12, r12, #4
563         beq             8f
564
565         loadl           q8,  q9,  q10, q11
566         convolve        q1,  q2,  q13, q14, q15, q4,  q5,  q6,  q7,  q8,  q9,  \idx1, \idx2, q12, q13
567         convolve        q3,  q12, q15, q4,  q5,  q6,  q7,  q8,  q9,  q10, q11, \idx1, \idx2, q13, q14
568         do_store        q1,  d2,  q2,  d4,  q3,  d6,  q12, d24, d3,  d5,  d7,  d25, \type
569
570         subs            r12, r12, #4
571         bne             2b
572
573 8:
574         subs            r5,  r5,  #8
575         beq             9f
576         @ r0 -= h * dst_stride
577         mls             r0,  r1,  r4, r0
578         @ r2 -= h * src_stride
579         mls             r2,  r3,  r4, r2
580         @ r2 -= 8 * src_stride
581         sub             r2,  r2,  r3, lsl #3
582         @ r2 += 1 * src_stride
583         add             r2,  r2,  r3
584         add             r2,  r2,  #8
585         add             r0,  r0,  #8
586         b               1b
587 9:
588         vpop            {q4-q7}
589         pop             {r4-r5}
590         bx              lr
591 endfunc
592 .endm
593
594 do_8tap_8v put, 3, 4
595 do_8tap_8v put, 4, 3
596 do_8tap_8v avg, 3, 4
597 do_8tap_8v avg, 4, 3
598
599 @ Instantiate a vertical filter function for filtering a 4 pixels wide
600 @ slice. The first half of the registers contain one row, while the second
601 @ half of a register contains the second-next row (also stored in the first
602 @ half of the register two steps ahead). The convolution does two outputs
603 @ at a time; the output of q5-q12 into one, and q4-q13 into another one.
604 @ The first half of first output is the first output row, the first half
605 @ of the other output is the second output row. The second halves of the
606 @ registers are rows 3 and 4.
607 @ This only is designed to work for 4 or 8 output lines.
608 .macro do_8tap_4v type, idx1, idx2
609 function \type\()_8tap_4v_\idx1\idx2
610         sub             r2,  r2,  r3, lsl #1
611         sub             r2,  r2,  r3
612         vld1.16         {q0},  [r12, :128]
613
614         vld1.32         {d2[]},   [r2], r3
615         vld1.32         {d3[]},   [r2], r3
616         vld1.32         {d4[]},   [r2], r3
617         vld1.32         {d5[]},   [r2], r3
618         vld1.32         {d6[]},   [r2], r3
619         vld1.32         {d7[]},   [r2], r3
620         vext.8          d2,  d2,  d4,  #4
621         vld1.32         {d8[]},   [r2], r3
622         vext.8          d3,  d3,  d5,  #4
623         vld1.32         {d9[]},   [r2], r3
624         vmovl.u8        q5,  d2
625         vext.8          d4,  d4,  d6,  #4
626         vld1.32         {d28[]},  [r2], r3
627         vmovl.u8        q6,  d3
628         vext.8          d5,  d5,  d7,  #4
629         vld1.32         {d29[]},  [r2], r3
630         vmovl.u8        q7,  d4
631         vext.8          d6,  d6,  d8,  #4
632         vld1.32         {d30[]},  [r2], r3
633         vmovl.u8        q8,  d5
634         vext.8          d7,  d7,  d9,  #4
635         vmovl.u8        q9,  d6
636         vext.8          d8,  d8,  d28, #4
637         vmovl.u8        q10, d7
638         vext.8          d9,  d9,  d29, #4
639         vmovl.u8        q11, d8
640         vext.8          d28, d28, d30, #4
641         vmovl.u8        q12, d9
642         vmovl.u8        q13, d28
643
644         convolve        q1,  q2,  q5,  q6,  q7,  q8,  q9,  q10, q11, q12, q13, \idx1, \idx2, q4, q3
645         do_store4       q1,  d2,  q2,  d4,  d3,  d5,  \type
646         subs            r4,  r4,  #4
647         beq             9f
648
649         vld1.32         {d2[]},   [r2], r3
650         vld1.32         {d3[]},   [r2], r3
651         vext.8          d29, d29, d2,  #4
652         vext.8          d30, d30, d3,  #4
653         vld1.32         {d2[1]},  [r2], r3
654         vmovl.u8        q14, d29
655         vld1.32         {d3[1]},  [r2], r3
656         vmovl.u8        q15, d30
657         vmovl.u8        q5,  d2
658         vmovl.u8        q6,  d3
659
660         convolve        q1,  q2,  q9,  q10, q11, q12, q13, q14, q15, q5,  q6,  \idx1, \idx2, q4, q3
661         do_store4       q1,  d2,  q2,  d4,  d3,  d5,  \type
662
663 9:
664         vpop            {q4-q7}
665         pop             {r4-r5}
666         bx              lr
667 endfunc
668 .endm
669
670 do_8tap_4v put, 3, 4
671 do_8tap_4v put, 4, 3
672 do_8tap_4v avg, 3, 4
673 do_8tap_4v avg, 4, 3
674
675 .macro do_8tap_v_func type, filter, offset, size
676 function ff_vp9_\type\()_\filter\()\size\()_v_neon, export=1
677         push            {r4-r5}
678         vpush           {q4-q7}
679         ldr             r4,  [sp, #72]
680         movrelx         r12, X(ff_vp9_subpel_filters), r5
681         ldr             r5,  [sp, #80]
682         add             r12, r12, 256*\offset
683         add             r12, r12, r5, lsl #4
684         cmp             r5,  #8
685         mov             r5,  #\size
686 .if \size >= 8
687         bge             \type\()_8tap_8v_34
688         b               \type\()_8tap_8v_43
689 .else
690         bge             \type\()_8tap_4v_34
691         b               \type\()_8tap_4v_43
692 .endif
693 endfunc
694 .endm
695
696 .macro do_8tap_v_filters size
697 do_8tap_v_func put, regular, 1, \size
698 do_8tap_v_func avg, regular, 1, \size
699 do_8tap_v_func put, sharp,   2, \size
700 do_8tap_v_func avg, sharp,   2, \size
701 do_8tap_v_func put, smooth,  0, \size
702 do_8tap_v_func avg, smooth,  0, \size
703 .endm
704
705 do_8tap_v_filters 64
706 do_8tap_v_filters 32
707 do_8tap_v_filters 16
708 do_8tap_v_filters 8
709 do_8tap_v_filters 4