1/*
2 * Copyright © 2018, VideoLAN and dav1d authors
3 * Copyright © 2018, Janne Grunau
4 * Copyright © 2020, Martin Storsjo
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 *    list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 *    this list of conditions and the following disclaimer in the documentation
15 *    and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "src/arm/asm.S"
30#include "util.S"
31
32#define PREP_BIAS 8192
33
34.macro avg d0, d00, d01, d1, d10, d11
35        vld1.16         {q0, q1}, [r2, :128]!
36        vld1.16         {q2, q3}, [r3, :128]!
37        vqadd.s16       q0,  q0,  q2
38        vqadd.s16       q1,  q1,  q3
39        vmax.s16        q0,  q0,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
40        vmax.s16        q1,  q1,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
41        vqsub.s16       q0,  q0,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
42        vqsub.s16       q1,  q1,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
43        vshl.s16        \d0, q0,  q13 // -(intermediate_bits+1)
44        vshl.s16        \d1, q1,  q13 // -(intermediate_bits+1)
45.endm
46
47.macro w_avg d0, d00, d01, d1, d10, d11
48        vld1.16         {q0, q1}, [r2, :128]!
49        vld1.16         {q2, q3}, [r3, :128]!
50        // This difference requires a 17 bit range, and all bits are
51        // significant for the following multiplication.
52        vsubl.s16       \d0, d4,  d0
53        vsubl.s16       q0,  d5,  d1
54        vsubl.s16       \d1, d6,  d2
55        vsubl.s16       q1,  d7,  d3
56        vmul.s32        \d0, \d0, q4
57        vmul.s32        q0,  q0,  q4
58        vmul.s32        \d1, \d1, q4
59        vmul.s32        q1,  q1,  q4
60        vshr.s32        \d0, \d0, #4
61        vshr.s32        q0,  q0,  #4
62        vshr.s32        \d1, \d1, #4
63        vshr.s32        q1,  q1,  #4
64        vaddw.s16       \d0, \d0, d4
65        vaddw.s16       q0,  q0,  d5
66        vaddw.s16       \d1, \d1, d6
67        vaddw.s16       q1,  q1,  d7
68        vmovn.i32       \d00, \d0
69        vmovn.i32       \d01, q0
70        vmovn.i32       \d10, \d1
71        vmovn.i32       \d11, q1
72        vrshl.s16       \d0, \d0, q13 // -intermediate_bits
73        vrshl.s16       \d1, \d1, q13 // -intermediate_bits
74        vadd.s16        \d0, \d0, q12 // PREP_BIAS >> intermediate_bits
75        vadd.s16        \d1, \d1, q12 // PREP_BIAS >> intermediate_bits
76        vmin.s16        \d0, \d0, q15 // bitdepth_max
77        vmin.s16        \d1, \d1, q15 // bitdepth_max
78        vmax.s16        \d0, \d0, q14 // 0
79        vmax.s16        \d1, \d1, q14 // 0
80.endm
81
82.macro mask d0, d00, d01, d1, d10, d11
83        vld1.8          {q7},     [r6, :128]!
84        vld1.16         {q0, q1}, [r2, :128]!
85        vneg.s8         q7,  q7
86        vld1.16         {q2, q3}, [r3, :128]!
87        vmovl.s8        q6,  d14
88        vmovl.s8        q7,  d15
89        vmovl.s16       q4,  d12
90        vmovl.s16       q5,  d13
91        vmovl.s16       q6,  d14
92        vmovl.s16       q7,  d15
93        vsubl.s16       \d0, d4,  d0
94        vsubl.s16       q0,  d5,  d1
95        vsubl.s16       \d1, d6,  d2
96        vsubl.s16       q1,  d7,  d3
97        vmul.s32        \d0, \d0, q4
98        vmul.s32        q0,  q0,  q5
99        vmul.s32        \d1, \d1, q6
100        vmul.s32        q1,  q1,  q7
101        vshr.s32        \d0, \d0, #6
102        vshr.s32        q0,  q0,  #6
103        vshr.s32        \d1, \d1, #6
104        vshr.s32        q1,  q1,  #6
105        vaddw.s16       \d0, \d0, d4
106        vaddw.s16       q0,  q0,  d5
107        vaddw.s16       \d1, \d1, d6
108        vaddw.s16       q1,  q1,  d7
109        vmovn.i32       \d00, \d0
110        vmovn.i32       \d01, q0
111        vmovn.i32       \d10, \d1
112        vmovn.i32       \d11, q1
113        vrshl.s16       \d0, \d0, q13 // -intermediate_bits
114        vrshl.s16       \d1, \d1, q13 // -intermediate_bits
115        vadd.s16        \d0, \d0, q12 // PREP_BIAS >> intermediate_bits
116        vadd.s16        \d1, \d1, q12 // PREP_BIAS >> intermediate_bits
117        vmin.s16        \d0, \d0, q15 // bitdepth_max
118        vmin.s16        \d1, \d1, q15 // bitdepth_max
119        vmax.s16        \d0, \d0, q14 // 0
120        vmax.s16        \d1, \d1, q14 // 0
121.endm
122
123.macro bidir_fn type, bdmax
124function \type\()_16bpc_neon, export=1
125        push            {r4-r7,lr}
126        ldr             r4,  [sp, #20]
127        ldr             r5,  [sp, #24]
128        ldr             r6,  [sp, #28]
129        clz             r4,  r4
130.ifnc \type, avg
131        ldr             r7,  [sp, #32]
132        vmov.i16        q14, #0
133        vdup.16         q15, r7         // bitdepth_max
134.endif
135.ifc \type, w_avg
136        vpush           {q4}
137.endif
138.ifc \type, mask
139        vpush           {q4-q7}
140.endif
141        clz             r7,  \bdmax
142        sub             r7,  r7,  #18   // intermediate_bits = clz(bitdepth_max) - 18
143.ifc \type, avg
144        mov             lr,  #1
145        movw            r12, #2*PREP_BIAS
146        lsl             lr,  lr,  r7    // 1 << intermediate_bits
147        neg             r12, r12         // -2*PREP_BIAS
148        add             r7,  r7,  #1
149        sub             r12, r12, lr    // -2*PREP_BIAS - 1 << intermediate_bits
150        neg             r7,  r7         // -(intermediate_bits+1)
151        vdup.16         q12, r12         // -2*PREP_BIAS - 1 << intermediate_bits
152        vdup.16         q13, r7         // -(intermediate_bits+1)
153.else
154        mov             r12, #PREP_BIAS
155        lsr             r12, r12, r7    // PREP_BIAS >> intermediate_bits
156        neg             r7,  r7         // -intermediate_bits
157        vdup.16         q12, r12         // PREP_BIAS >> intermediate_bits
158        vdup.16         q13, r7         // -intermediate_bits
159.endif
160.ifc \type, w_avg
161        vdup.32         q4,  r6
162        vneg.s32        q4,  q4
163.endif
164        adr             r7,  L(\type\()_tbl)
165        sub             r4,  r4,  #24
166        \type           q8,  d16, d17, q9,  d18, d19
167        ldr             r4,  [r7, r4, lsl #2]
168        add             r7,  r7,  r4
169        bx              r7
170
171        .align 2
172L(\type\()_tbl):
173        .word 1280f - L(\type\()_tbl) + CONFIG_THUMB
174        .word 640f  - L(\type\()_tbl) + CONFIG_THUMB
175        .word 320f  - L(\type\()_tbl) + CONFIG_THUMB
176        .word 160f  - L(\type\()_tbl) + CONFIG_THUMB
177        .word 80f   - L(\type\()_tbl) + CONFIG_THUMB
178        .word 40f   - L(\type\()_tbl) + CONFIG_THUMB
179
18040:
181        add             r7,  r0,  r1
182        lsl             r1,  r1,  #1
1834:
184        subs            r5,  r5,  #4
185        vst1.16         {d16},  [r0, :64], r1
186        vst1.16         {d17},  [r7, :64], r1
187        vst1.16         {d18},  [r0, :64], r1
188        vst1.16         {d19},  [r7, :64], r1
189        ble             0f
190        \type           q8,  d16, d17, q9,  d18, d19
191        b               4b
19280:
193        add             r7,  r0,  r1
194        lsl             r1,  r1,  #1
1958:
196        vst1.16         {q8},  [r0, :128], r1
197        subs            r5,  r5,  #2
198        vst1.16         {q9},  [r7, :128], r1
199        ble             0f
200        \type           q8,  d16, d17, q9,  d18, d19
201        b               8b
202160:
20316:
204        \type           q10, d20, d21, q11, d22, d23
205        vst1.16         {q8,  q9},  [r0, :128], r1
206        subs            r5,  r5,  #2
207        vst1.16         {q10, q11}, [r0, :128], r1
208        ble             0f
209        \type           q8,  d16, d17, q9,  d18, d19
210        b               16b
211320:
212        add             r7,  r0,  #32
21332:
214        \type           q10, d20, d21, q11, d22, d23
215        vst1.16         {q8,  q9},  [r0, :128], r1
216        subs            r5,  r5,  #1
217        vst1.16         {q10, q11}, [r7, :128], r1
218        ble             0f
219        \type           q8,  d16, d17, q9,  d18, d19
220        b               32b
221640:
222        add             r7,  r0,  #32
223        mov             r12, #64
224        sub             r1,  r1,  #64
22564:
226        \type           q10, d20, d21, q11, d22, d23
227        vst1.16         {q8,  q9},  [r0, :128], r12
228        \type           q8,  d16, d17, q9,  d18, d19
229        vst1.16         {q10, q11}, [r7, :128], r12
230        \type           q10, d20, d21, q11, d22, d23
231        vst1.16         {q8,  q9},  [r0, :128], r1
232        subs            r5,  r5,  #1
233        vst1.16         {q10, q11}, [r7, :128], r1
234        ble             0f
235        \type           q8,  d16, d17, q9,  d18, d19
236        b               64b
2371280:
238        add             r7,  r0,  #32
239        mov             r12, #64
240        sub             r1,  r1,  #192
241128:
242        \type           q10, d20, d21, q11, d22, d23
243        vst1.16         {q8,  q9},  [r0, :128], r12
244        \type           q8,  d16, d17, q9,  d18, d19
245        vst1.16         {q10, q11}, [r7, :128], r12
246        \type           q10, d20, d21, q11, d22, d23
247        vst1.16         {q8,  q9},  [r0, :128], r12
248        \type           q8,  d16, d17, q9,  d18, d19
249        vst1.16         {q10, q11}, [r7, :128], r12
250        \type           q10, d20, d21, q11, d22, d23
251        vst1.16         {q8,  q9},  [r0, :128], r12
252        \type           q8,  d16, d17, q9,  d18, d19
253        vst1.16         {q10, q11}, [r7, :128], r12
254        \type           q10, d20, d21, q11, d22, d23
255        vst1.16         {q8,  q9},  [r0, :128], r1
256        subs            r5,  r5,  #1
257        vst1.16         {q10, q11}, [r7, :128], r1
258        ble             0f
259        \type           q8,  d16, d17, q9,  d18, d19
260        b               128b
2610:
262.ifc \type, mask
263        vpop            {q4-q7}
264.endif
265.ifc \type, w_avg
266        vpop            {q4}
267.endif
268        pop             {r4-r7,pc}
269endfunc
270.endm
271
272bidir_fn avg, r6
273bidir_fn w_avg, r7
274bidir_fn mask, r7
275
276
277// This has got the same signature as the put_8tap functions,
278// and assumes that r9 is set to (clz(w)-24).
279function put_neon
280        adr             r10, L(put_tbl)
281        ldr             r9,  [r10, r9, lsl #2]
282        add             r10, r10, r9
283        bx              r10
284
285        .align 2
286L(put_tbl):
287        .word 1280f - L(put_tbl) + CONFIG_THUMB
288        .word 640f  - L(put_tbl) + CONFIG_THUMB
289        .word 320f  - L(put_tbl) + CONFIG_THUMB
290        .word 16f   - L(put_tbl) + CONFIG_THUMB
291        .word 80f   - L(put_tbl) + CONFIG_THUMB
292        .word 4f    - L(put_tbl) + CONFIG_THUMB
293        .word 2f    - L(put_tbl) + CONFIG_THUMB
294
2952:
296        vld1.32         {d0[]}, [r2], r3
297        vld1.32         {d1[]}, [r2], r3
298        subs            r5,  r5,  #2
299        vst1.32         {d0[0]}, [r0, :32], r1
300        vst1.32         {d1[1]}, [r0, :32], r1
301        bgt             2b
302        pop             {r4-r11,pc}
3034:
304        vld1.16         {d0}, [r2], r3
305        vld1.16         {d1}, [r2], r3
306        subs            r5,  r5,  #2
307        vst1.16         {d0}, [r0, :64], r1
308        vst1.16         {d1}, [r0, :64], r1
309        bgt             4b
310        pop             {r4-r11,pc}
31180:
312        add             r8,  r0,  r1
313        lsl             r1,  r1,  #1
314        add             r9,  r2,  r3
315        lsl             r3,  r3,  #1
3168:
317        vld1.16         {q0}, [r2], r3
318        vld1.16         {q1}, [r9], r3
319        subs            r5,  r5,  #2
320        vst1.16         {q0}, [r0, :128], r1
321        vst1.16         {q1}, [r8, :128], r1
322        bgt             8b
323        pop             {r4-r11,pc}
32416:
325        vld1.16         {q0,  q1},  [r2], r3
326        subs            r5,  r5,  #1
327        vst1.16         {q0,  q1},  [r0, :128], r1
328        bgt             16b
329        pop             {r4-r11,pc}
330320:
331        sub             r1,  r1,  #32
332        sub             r3,  r3,  #32
33332:
334        vld1.16         {q0,  q1},  [r2]!
335        vst1.16         {q0,  q1},  [r0, :128]!
336        vld1.16         {q2,  q3},  [r2], r3
337        subs            r5,  r5,  #1
338        vst1.16         {q2,  q3},  [r0, :128], r1
339        bgt             32b
340        pop             {r4-r11,pc}
341640:
342        sub             r1,  r1,  #96
343        sub             r3,  r3,  #96
34464:
345        vld1.16         {q8,  q9},  [r2]!
346        vst1.16         {q8,  q9},  [r0, :128]!
347        vld1.16         {q10, q11}, [r2]!
348        vst1.16         {q10, q11}, [r0, :128]!
349        vld1.16         {q12, q13}, [r2]!
350        vst1.16         {q12, q13}, [r0, :128]!
351        vld1.16         {q14, q15}, [r2], r3
352        subs            r5,  r5,  #1
353        vst1.16         {q14, q15}, [r0, :128], r1
354        bgt             64b
355        pop             {r4-r11,pc}
3561280:
357        sub             r1,  r1,  #224
358        sub             r3,  r3,  #224
359128:
360        vld1.16         {q8,  q9},  [r2]!
361        vst1.16         {q8,  q9},  [r0, :128]!
362        vld1.16         {q10, q11}, [r2]!
363        vst1.16         {q10, q11}, [r0, :128]!
364        vld1.16         {q12, q13}, [r2]!
365        vst1.16         {q12, q13}, [r0, :128]!
366        vld1.16         {q14, q15}, [r2]!
367        vst1.16         {q14, q15}, [r0, :128]!
368        vld1.16         {q8,  q9},  [r2]!
369        vst1.16         {q8,  q9},  [r0, :128]!
370        vld1.16         {q10, q11}, [r2]!
371        vst1.16         {q10, q11}, [r0, :128]!
372        vld1.16         {q12, q13}, [r2]!
373        vst1.16         {q12, q13}, [r0, :128]!
374        vld1.16         {q14, q15}, [r2], r3
375        subs            r5,  r5,  #1
376        vst1.16         {q14, q15}, [r0, :128], r1
377        bgt             128b
378        pop             {r4-r11,pc}
379endfunc
380
381// This has got the same signature as the prep_8tap functions,
382// and assumes that r9 is set to (clz(w)-24), r7 to intermediate_bits and
383// r8 to w*2.
384function prep_neon
385        adr             r10, L(prep_tbl)
386        ldr             r9,  [r10, r9, lsl #2]
387        vdup.16         q15, r7   // intermediate_bits
388        vmov.i16        q14, #PREP_BIAS
389        add             r10, r10, r9
390        bx              r10
391
392        .align 2
393L(prep_tbl):
394        .word 1280f - L(prep_tbl) + CONFIG_THUMB
395        .word 640f  - L(prep_tbl) + CONFIG_THUMB
396        .word 320f  - L(prep_tbl) + CONFIG_THUMB
397        .word 16f   - L(prep_tbl) + CONFIG_THUMB
398        .word 80f   - L(prep_tbl) + CONFIG_THUMB
399        .word 40f   - L(prep_tbl) + CONFIG_THUMB
400
40140:
402        add             r9,  r1,  r2
403        lsl             r2,  r2,  #1
4044:
405        vld1.16         {d0}, [r1], r2
406        vld1.16         {d1}, [r9], r2
407        subs            r4,  r4,  #2
408        vshl.s16        q0,  q0,  q15
409        vsub.i16        q0,  q0,  q14
410        vst1.16         {q0}, [r0, :128]!
411        bgt             4b
412        pop             {r4-r11,pc}
41380:
414        add             r9,  r1,  r2
415        lsl             r2,  r2,  #1
4168:
417        vld1.16         {q0}, [r1], r2
418        vld1.16         {q1}, [r9], r2
419        subs            r4,  r4,  #2
420        vshl.s16        q0,  q0,  q15
421        vshl.s16        q1,  q1,  q15
422        vsub.i16        q0,  q0,  q14
423        vsub.i16        q1,  q1,  q14
424        vst1.16         {q0, q1}, [r0, :128]!
425        bgt             8b
426        pop             {r4-r11,pc}
42716:
428        vld1.16         {q0, q1}, [r1], r2
429        vshl.s16        q0,  q0,  q15
430        vld1.16         {q2, q3}, [r1], r2
431        subs            r4,  r4,  #2
432        vshl.s16        q1,  q1,  q15
433        vshl.s16        q2,  q2,  q15
434        vshl.s16        q3,  q3,  q15
435        vsub.i16        q0,  q0,  q14
436        vsub.i16        q1,  q1,  q14
437        vsub.i16        q2,  q2,  q14
438        vst1.16         {q0, q1}, [r0, :128]!
439        vsub.i16        q3,  q3,  q14
440        vst1.16         {q2, q3}, [r0, :128]!
441        bgt             16b
442        pop             {r4-r11,pc}
443320:
444        sub             r2,  r2,  #32
44532:
446        vld1.16         {q0, q1}, [r1]!
447        subs            r4,  r4,  #1
448        vshl.s16        q0,  q0,  q15
449        vld1.16         {q2, q3}, [r1], r2
450        vshl.s16        q1,  q1,  q15
451        vshl.s16        q2,  q2,  q15
452        vshl.s16        q3,  q3,  q15
453        vsub.i16        q0,  q0,  q14
454        vsub.i16        q1,  q1,  q14
455        vsub.i16        q2,  q2,  q14
456        vst1.16         {q0, q1}, [r0, :128]!
457        vsub.i16        q3,  q3,  q14
458        vst1.16         {q2, q3}, [r0, :128]!
459        bgt             32b
460        pop             {r4-r11,pc}
461640:
462        sub             r2,  r2,  #96
46364:
464        vld1.16         {q0,  q1},  [r1]!
465        subs            r4,  r4,  #1
466        vshl.s16        q0,  q0,  q15
467        vld1.16         {q2,  q3},  [r1]!
468        vshl.s16        q1,  q1,  q15
469        vld1.16         {q8,  q9},  [r1]!
470        vshl.s16        q2,  q2,  q15
471        vld1.16         {q10, q11}, [r1], r2
472        vshl.s16        q3,  q3,  q15
473        vshl.s16        q8,  q8,  q15
474        vshl.s16        q9,  q9,  q15
475        vshl.s16        q10, q10, q15
476        vshl.s16        q11, q11, q15
477        vsub.i16        q0,  q0,  q14
478        vsub.i16        q1,  q1,  q14
479        vsub.i16        q2,  q2,  q14
480        vsub.i16        q3,  q3,  q14
481        vsub.i16        q8,  q8,  q14
482        vst1.16         {q0,  q1},  [r0, :128]!
483        vsub.i16        q9,  q9,  q14
484        vst1.16         {q2,  q3},  [r0, :128]!
485        vsub.i16        q10, q10, q14
486        vst1.16         {q8,  q9},  [r0, :128]!
487        vsub.i16        q11, q11, q14
488        vst1.16         {q10, q11}, [r0, :128]!
489        bgt             64b
490        pop             {r4-r11,pc}
4911280:
492        sub             r2,  r2,  #224
493128:
494        vld1.16         {q0,  q1},  [r1]!
495        subs            r4,  r4,  #1
496        vshl.s16        q0,  q0,  q15
497        vld1.16         {q2,  q3},  [r1]!
498        vshl.s16        q1,  q1,  q15
499        vld1.16         {q8,  q9},  [r1]!
500        vshl.s16        q2,  q2,  q15
501        vld1.16         {q10, q11}, [r1]!
502        vshl.s16        q3,  q3,  q15
503        vshl.s16        q8,  q8,  q15
504        vshl.s16        q9,  q9,  q15
505        vshl.s16        q10, q10, q15
506        vshl.s16        q11, q11, q15
507        vsub.i16        q0,  q0,  q14
508        vsub.i16        q1,  q1,  q14
509        vsub.i16        q2,  q2,  q14
510        vsub.i16        q3,  q3,  q14
511        vsub.i16        q8,  q8,  q14
512        vst1.16         {q0,  q1},  [r0, :128]!
513        vld1.16         {q0,  q1},  [r1]!
514        vsub.i16        q9,  q9,  q14
515        vsub.i16        q10, q10, q14
516        vst1.16         {q2,  q3},  [r0, :128]!
517        vld1.16         {q2,  q3},  [r1]!
518        vsub.i16        q11, q11, q14
519        vshl.s16        q0,  q0,  q15
520        vst1.16         {q8,  q9},  [r0, :128]!
521        vld1.16         {q8,  q9},  [r1]!
522        vshl.s16        q1,  q1,  q15
523        vshl.s16        q2,  q2,  q15
524        vst1.16         {q10, q11}, [r0, :128]!
525        vld1.16         {q10, q11}, [r1], r2
526        vshl.s16        q3,  q3,  q15
527        vshl.s16        q8,  q8,  q15
528        vshl.s16        q9,  q9,  q15
529        vshl.s16        q10, q10, q15
530        vshl.s16        q11, q11, q15
531        vsub.i16        q0,  q0,  q14
532        vsub.i16        q1,  q1,  q14
533        vsub.i16        q2,  q2,  q14
534        vsub.i16        q3,  q3,  q14
535        vsub.i16        q8,  q8,  q14
536        vst1.16         {q0,  q1},  [r0, :128]!
537        vsub.i16        q9,  q9,  q14
538        vst1.16         {q2,  q3},  [r0, :128]!
539        vsub.i16        q10, q10, q14
540        vst1.16         {q8,  q9},  [r0, :128]!
541        vsub.i16        q11, q11, q14
542        vst1.16         {q10, q11}, [r0, :128]!
543        bgt             128b
544        pop             {r4-r11,pc}
545endfunc
546
547.macro load_slice s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6
548        vld1.\wd        {\d0[]}, [\s0], \strd
549        vld1.\wd        {\d1[]}, [\s1], \strd
550.ifnb \d2
551        vld1.\wd        {\d2[]}, [\s0], \strd
552        vld1.\wd        {\d3[]}, [\s1], \strd
553.endif
554.ifnb \d4
555        vld1.\wd        {\d4[]}, [\s0], \strd
556.endif
557.ifnb \d5
558        vld1.\wd        {\d5[]}, [\s1], \strd
559.endif
560.ifnb \d6
561        vld1.\wd        {\d6[]}, [\s0], \strd
562.endif
563.endm
564.macro load_reg s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
565        vld1.16         {\d0}, [\s0], \strd
566        vld1.16         {\d1}, [\s1], \strd
567.ifnb \d2
568        vld1.16         {\d2}, [\s0], \strd
569        vld1.16         {\d3}, [\s1], \strd
570.endif
571.ifnb \d4
572        vld1.16         {\d4}, [\s0], \strd
573.endif
574.ifnb \d5
575        vld1.16         {\d5}, [\s1], \strd
576.endif
577.ifnb \d6
578        vld1.16         {\d6}, [\s0], \strd
579.endif
580.endm
581.macro load_regpair s0, s1, strd, d0, d1, d2, d3, d4, d5
582        vld1.16         {\d0, \d1}, [\s0], \strd
583.ifnb \d2
584        vld1.16         {\d2, \d3}, [\s1], \strd
585.endif
586.ifnb \d4
587        vld1.16         {\d4, \d5}, [\s0], \strd
588.endif
589.endm
590.macro load_32 s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
591        load_slice      \s0, \s1, \strd, 32, \d0, \d1, \d2, \d3, \d4, \d5, \d6
592.endm
593.macro load_16s16 s0, s1, strd, d0, d1, d2, d3, d4, d5
594        load_regpair    \s0, \s1, \strd, \d0, \d1, \d2, \d3, \d4, \d5
595.endm
596.macro interleave_1_32 r0, r1, r2, r3, r4
597        vext.8          \r0, \r0, \r1, #4
598        vext.8          \r1, \r1, \r2, #4
599.ifnb \r3
600        vext.8          \r2, \r2, \r3, #4
601        vext.8          \r3, \r3, \r4, #4
602.endif
603.endm
604.macro vmin_u16 c, r0, r1, r2, r3
605        vmin.u16        \r0, \r0, \c
606.ifnb \r1
607        vmin.u16        \r1, \r1, \c
608.endif
609.ifnb \r2
610        vmin.u16        \r2, \r2, \c
611        vmin.u16        \r3, \r3, \c
612.endif
613.endm
614.macro vsub_i16 c, r0, r1, r2, r3
615        vsub.i16        \r0, \r0, \c
616.ifnb \r1
617        vsub.i16        \r1, \r1, \c
618.endif
619.ifnb \r2
620        vsub.i16        \r2, \r2, \c
621        vsub.i16        \r3, \r3, \c
622.endif
623.endm
624.macro vmull_vmlal_4 d, s0, s1, s2, s3
625        vmull.s16       \d,  \s0, d0[0]
626        vmlal.s16       \d,  \s1, d0[1]
627        vmlal.s16       \d,  \s2, d0[2]
628        vmlal.s16       \d,  \s3, d0[3]
629.endm
630.macro vmull_vmlal_8 d, s0, s1, s2, s3, s4, s5, s6, s7
631        vmull.s16       \d,  \s0, d0[0]
632        vmlal.s16       \d,  \s1, d0[1]
633        vmlal.s16       \d,  \s2, d0[2]
634        vmlal.s16       \d,  \s3, d0[3]
635        vmlal.s16       \d,  \s4, d1[0]
636        vmlal.s16       \d,  \s5, d1[1]
637        vmlal.s16       \d,  \s6, d1[2]
638        vmlal.s16       \d,  \s7, d1[3]
639.endm
640.macro vqrshrun_s32 shift, q0, d0, q1, d1, q2, d2, q3, d3
641        vqrshrun.s32    \d0, \q0, #\shift
642.ifnb \q1
643        vqrshrun.s32    \d1, \q1, #\shift
644.endif
645.ifnb \q2
646        vqrshrun.s32    \d2, \q2, #\shift
647        vqrshrun.s32    \d3, \q3, #\shift
648.endif
649.endm
650.macro vmovn_i32 q0, d0, q1, d1, q2, d2, q3, d3
651        vmovn.i32       \d0, \q0
652.ifnb \q1
653        vmovn.i32       \d1, \q1
654.endif
655.ifnb \q2
656        vmovn.i32       \d2, \q2
657        vmovn.i32       \d3, \q3
658.endif
659.endm
660.macro vrshl_s32 shift, r0, r1, r2, r3
661        vrshl.s32       \r0, \r0, \shift
662        vrshl.s32       \r1, \r1, \shift
663.ifnb \r2
664        vrshl.s32       \r2, \r2, \shift
665        vrshl.s32       \r3, \r3, \shift
666.endif
667.endm
668.macro vst1_32 strd, r0, r1
669        vst1.32         {\r0[0]}, [r0, :32], \strd
670        vst1.32         {\r0[1]}, [r9, :32], \strd
671.ifnb \r1
672        vst1.32         {\r1[0]}, [r0, :32], \strd
673        vst1.32         {\r1[1]}, [r9, :32], \strd
674.endif
675.endm
676.macro vst1_reg strd, align, r0, r1, r2, r3, r4, r5, r6, r7
677        vst1.16         {\r0}, [r0, \align], \strd
678        vst1.16         {\r1}, [r9, \align], \strd
679.ifnb \r2
680        vst1.16         {\r2}, [r0, \align], \strd
681        vst1.16         {\r3}, [r9, \align], \strd
682.endif
683.ifnb \r4
684        vst1.16         {\r4}, [r0, \align], \strd
685        vst1.16         {\r5}, [r9, \align], \strd
686        vst1.16         {\r6}, [r0, \align], \strd
687        vst1.16         {\r7}, [r9, \align], \strd
688.endif
689.endm
690.macro finalize type, q0, q1, d0, d1, q2, q3, d2, d3
691.ifc \type, put
692        vqrshrun_s32    6,   \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3
693        vmin_u16        q15, \q0, \q1
694.else
695        vrshl_s32       q14, \q0, \q1, \q2, \q3 // -(6-intermediate_bits)
696        vmovn_i32       \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3
697        vsub_i16        q15, \q0, \q1           // PREP_BIAS
698.endif
699.endm
700.macro shift_store_4 type, strd, q0, q1, d0, d1, q2, q3, d2, d3
701        finalize        \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3
702        vst1_reg        \strd, :64, \d0, \d1, \d2, \d3
703.endm
704.macro shift_store_8 type, strd, q0, q1, d0, d1, q2, q3, d2, d3
705        finalize        \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3
706        vst1_reg        \strd, :128, \q0, \q1
707.endm
708.macro shift_store_16 type, strd, q0, q1, d0, d1, q2, q3, d2, d3
709        finalize        \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3
710        vst1.16         {\q0, \q1}, [r0, :128], \strd
711.endm
712
713.macro make_8tap_fn op, type, type_h, type_v
714function \op\()_8tap_\type\()_16bpc_neon, export=1
715        push            {r4-r11,lr}
716        movw            r9,  \type_h
717        movw            r10, \type_v
718        b               \op\()_8tap_neon
719endfunc
720.endm
721
722// No spaces in these expressions, due to gas-preprocessor.
723#define REGULAR ((0*15<<7)|3*15)
724#define SMOOTH  ((1*15<<7)|4*15)
725#define SHARP   ((2*15<<7)|3*15)
726
727.macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, my, bdmax, ds2, sr2
728make_8tap_fn \type, regular,        REGULAR, REGULAR
729make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH
730make_8tap_fn \type, regular_sharp,  REGULAR, SHARP
731make_8tap_fn \type, smooth,         SMOOTH,  SMOOTH
732make_8tap_fn \type, smooth_regular, SMOOTH,  REGULAR
733make_8tap_fn \type, smooth_sharp,   SMOOTH,  SHARP
734make_8tap_fn \type, sharp,          SHARP,   SHARP
735make_8tap_fn \type, sharp_regular,  SHARP,   REGULAR
736make_8tap_fn \type, sharp_smooth,   SHARP,   SMOOTH
737
738function \type\()_8tap_neon
739        ldrd            r4,  r5,  [sp, #36]
740        ldrd            r6,  r7,  [sp, #44]
741.ifc \bdmax, r8
742        ldr             r8,  [sp, #52]
743.endif
744        movw            r11, #0x4081  // (1 << 14) | (1 << 7) | (1 << 0)
745        mul             \mx, \mx, r11
746        mul             \my, \my, r11
747        add             \mx, \mx, r9  // mx, 8tap_h, 4tap_h
748        add             \my, \my, r10 // my, 8tap_v, 4tap_v
749
750.ifc \type, prep
751        lsl             \d_strd, \w, #1
752.endif
753
754        vdup.16         q15, \bdmax            // bitdepth_max
755        clz             \bdmax,  \bdmax
756        clz             r9,  \w
757        sub             \bdmax,  \bdmax,  #18  // intermediate_bits = clz(bitdepth_max) - 18
758        tst             \mx, #(0x7f << 14)
759        sub             r9,  r9,  #24
760        add             lr,  \bdmax, #6        // 6 + intermediate_bits
761        rsb             r12, \bdmax, #6        // 6 - intermediate_bits
762        movrel          r11, X(mc_subpel_filters), -8
763        bne             L(\type\()_8tap_h)
764        tst             \my, #(0x7f << 14)
765        bne             L(\type\()_8tap_v)
766        b               \type\()_neon
767
768L(\type\()_8tap_h):
769        cmp             \w,  #4
770        ubfx            r10, \mx, #7,  #7
771        and             \mx, \mx, #0x7f
772        it              gt
773        movgt           \mx, r10
774        tst             \my, #(0x7f << 14)
775        add             \mx, r11, \mx, lsl #3
776        bne             L(\type\()_8tap_hv)
777
778        adr             r10, L(\type\()_8tap_h_tbl)
779        vdup.32         q14, r12           // 6 - intermediate_bits
780        ldr             r9,  [r10, r9, lsl #2]
781        vneg.s32        q14, q14           // -(6-intermediate_bits)
782.ifc \type, put
783        vdup.16         q13, \bdmax        // intermediate_bits
784.else
785        vmov.i16        q13, #PREP_BIAS
786.endif
787        add             r10, r10, r9
788.ifc \type, put
789        vneg.s16        q13, q13           // -intermediate_bits
790.endif
791        bx              r10
792
793        .align 2
794L(\type\()_8tap_h_tbl):
795        .word 1280f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
796        .word 640f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
797        .word 320f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
798        .word 160f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
799        .word 80f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
800        .word 40f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
801        .word 20f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
802
80320:     // 2xN h
804.ifc \type, put
805        add             \mx, \mx, #2
806        vld1.32         {d0[]}, [\mx]
807        sub             \src,  \src,  #2
808        add             \ds2,  \dst,  \d_strd
809        add             \sr2,  \src,  \s_strd
810        lsl             \d_strd,  \d_strd,  #1
811        lsl             \s_strd,  \s_strd,  #1
812        vmovl.s8        q0,  d0
8132:
814        vld1.16         {q2}, [\src], \s_strd
815        vld1.16         {q3}, [\sr2], \s_strd
816        vext.8          d5,  d4,  d5,  #2
817        vext.8          d7,  d6,  d7,  #2
818        subs            \h,  \h,  #2
819        vtrn.32         d4,  d6
820        vtrn.32         d5,  d7
821        vmull.s16       q1,  d4,  d0[0]
822        vmlal.s16       q1,  d5,  d0[1]
823        vmlal.s16       q1,  d6,  d0[2]
824        vmlal.s16       q1,  d7,  d0[3]
825        vrshl.s32       q1,  q1,  q14 // -(6-intermediate_bits)
826        vqmovun.s32     d2,  q1
827        vrshl.s16       d2,  d2,  d26 // -intermediate_bits
828        vmin.u16        d2,  d2,  d30
829        vst1.32         {d2[0]}, [\dst, :32], \d_strd
830        vst1.32         {d2[1]}, [\ds2, :32], \d_strd
831        bgt             2b
832        pop             {r4-r11,pc}
833.endif
834
83540:     // 4xN h
836        add             \mx, \mx, #2
837        vld1.32         {d0[]}, [\mx]
838        sub             \src,  \src,  #2
839        add             \ds2,  \dst,  \d_strd
840        add             \sr2,  \src,  \s_strd
841        lsl             \d_strd,  \d_strd,  #1
842        lsl             \s_strd,  \s_strd,  #1
843        vmovl.s8        q0,  d0
8444:
845        vld1.16         {q8},  [\src], \s_strd
846        vld1.16         {q11}, [\sr2], \s_strd
847        vext.8          d18, d16, d17, #2
848        vext.8          d19, d16, d17, #4
849        vext.8          d20, d16, d17, #6
850        vext.8          d24, d22, d23, #2
851        vext.8          d25, d22, d23, #4
852        vext.8          d21, d22, d23, #6
853        subs            \h,  \h,  #2
854        vmull.s16       q2,  d16, d0[0]
855        vmlal.s16       q2,  d18, d0[1]
856        vmlal.s16       q2,  d19, d0[2]
857        vmlal.s16       q2,  d20, d0[3]
858        vmull.s16       q3,  d22, d0[0]
859        vmlal.s16       q3,  d24, d0[1]
860        vmlal.s16       q3,  d25, d0[2]
861        vmlal.s16       q3,  d21, d0[3]
862        vrshl.s32       q2,  q2,  q14 // -(6-intermediate_bits)
863        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
864.ifc \type, put
865        vqmovun.s32     d4,  q2
866        vqmovun.s32     d5,  q3
867        vrshl.s16       q2,  q2,  q13 // -intermediate_bits
868        vmin.u16        q2,  q2,  q15
869.else
870        vmovn.s32       d4,  q2
871        vmovn.s32       d5,  q3
872        vsub.i16        q2,  q2,  q13 // PREP_BIAS
873.endif
874        vst1.16         {d4}, [\dst, :64], \d_strd
875        vst1.16         {d5}, [\ds2, :64], \d_strd
876        bgt             4b
877        pop             {r4-r11,pc}
878
87980:
880160:
881320:
882640:
8831280:   // 8xN, 16xN, 32xN, ... h
884        vpush           {q4-q5}
885        vld1.8          {d0}, [\mx, :64]
886        sub             \src,  \src,  #6
887        add             \ds2,  \dst,  \d_strd
888        add             \sr2,  \src,  \s_strd
889        lsl             \s_strd,  \s_strd,  #1
890        vmovl.s8        q0,  d0
891
892        sub             \s_strd,  \s_strd,  \w, lsl #1
893        sub             \s_strd,  \s_strd,  #16
894.ifc \type, put
895        lsl             \d_strd,  \d_strd,  #1
896        sub             \d_strd,  \d_strd,  \w, lsl #1
897.endif
89881:
899        vld1.16         {q8,  q9},  [\src]!
900        vld1.16         {q10, q11}, [\sr2]!
901        mov             \mx, \w
902
9038:
904        vmull.s16       q1,  d16, d0[0]
905        vmull.s16       q2,  d17, d0[0]
906        vmull.s16       q3,  d20, d0[0]
907        vmull.s16       q4,  d21, d0[0]
908.irpc i, 1234567
909        vext.8          q12, q8,  q9,  #(2*\i)
910        vext.8          q5,  q10, q11, #(2*\i)
911.if \i < 4
912        vmlal.s16       q1,  d24, d0[\i]
913        vmlal.s16       q2,  d25, d0[\i]
914        vmlal.s16       q3,  d10, d0[\i]
915        vmlal.s16       q4,  d11, d0[\i]
916.else
917        vmlal.s16       q1,  d24, d1[\i-4]
918        vmlal.s16       q2,  d25, d1[\i-4]
919        vmlal.s16       q3,  d10, d1[\i-4]
920        vmlal.s16       q4,  d11, d1[\i-4]
921.endif
922.endr
923        subs            \mx, \mx, #8
924        vrshl.s32       q1,  q1,  q14 // -(6-intermediate_bits)
925        vrshl.s32       q2,  q2,  q14 // -(6-intermediate_bits)
926        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
927        vrshl.s32       q4,  q4,  q14 // -(6-intermediate_bits)
928.ifc \type, put
929        vqmovun.s32     d2,  q1
930        vqmovun.s32     d3,  q2
931        vqmovun.s32     d4,  q3
932        vqmovun.s32     d5,  q4
933        vrshl.s16       q1,  q1,  q13 // -intermediate_bits
934        vrshl.s16       q2,  q2,  q13 // -intermediate_bits
935        vmin.u16        q1,  q1,  q15
936        vmin.u16        q2,  q2,  q15
937.else
938        vmovn.s32       d2,  q1
939        vmovn.s32       d3,  q2
940        vmovn.s32       d4,  q3
941        vmovn.s32       d5,  q4
942        vsub.i16        q1,  q1,  q13 // PREP_BIAS
943        vsub.i16        q2,  q2,  q13 // PREP_BIAS
944.endif
945        vst1.16         {q1}, [\dst, :128]!
946        vst1.16         {q2}, [\ds2, :128]!
947        ble             9f
948
949        vmov            q8,  q9
950        vmov            q10, q11
951        vld1.16         {q9},  [\src]!
952        vld1.16         {q11}, [\sr2]!
953        b               8b
954
9559:
956        add             \dst,  \dst,  \d_strd
957        add             \ds2,  \ds2,  \d_strd
958        add             \src,  \src,  \s_strd
959        add             \sr2,  \sr2,  \s_strd
960
961        subs            \h,  \h,  #2
962        bgt             81b
963        vpop            {q4-q5}
964        pop             {r4-r11,pc}
965
966
967L(\type\()_8tap_v):
968        cmp             \h,  #4
969        ubfx            r10, \my, #7,  #7
970        and             \my, \my, #0x7f
971        it              gt
972        movgt           \my, r10
973        add             \my, r11, \my, lsl #3
974
975.ifc \type, prep
976        vdup.32         q14, r12        // 6 - intermediate_bits
977        vmov.i16        q15, #PREP_BIAS
978.endif
979        adr             r10, L(\type\()_8tap_v_tbl)
980        ldr             r9,  [r10, r9, lsl #2]
981.ifc \type, prep
982        vneg.s32        q14, q14        // -(6-intermediate_bits)
983.endif
984        add             r10, r10, r9
985        bx              r10
986
987        .align 2
988L(\type\()_8tap_v_tbl):
989        .word 1280f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
990        .word 640f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
991        .word 320f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
992        .word 160f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
993        .word 80f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
994        .word 40f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
995        .word 20f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
996
99720:     // 2xN v
998.ifc \type, put
999        bgt             28f
1000
1001        cmp             \h,  #2
1002        add             \my, \my, #2
1003        vld1.32         {d0[]}, [\my]
1004        sub             \src,  \src,  \s_strd
1005        add             \ds2,  \dst,  \d_strd
1006        add             \sr2,  \src,  \s_strd
1007        lsl             \s_strd,  \s_strd,  #1
1008        lsl             \d_strd,  \d_strd,  #1
1009        vmovl.s8        q0,  d0
1010
1011        // 2x2 v
1012        load_32         \src, \sr2, \s_strd, d1, d2, d3, d4, d5
1013        interleave_1_32 d1,  d2,  d3,  d4,  d5
1014        bgt             24f
1015        vmull_vmlal_4   q8,  d1,  d2,  d3,  d4
1016        vqrshrun_s32    6,   q8,  d16
1017        vmin_u16        d30, d16
1018        vst1_32         \d_strd,  d16
1019        pop             {r4-r11,pc}
1020
102124:     // 2x4 v
1022        load_32         \sr2, \src, \s_strd, d6, d7
1023        interleave_1_32 d5,  d6,  d7
1024        vmull_vmlal_4   q8,  d1,  d2,  d3,  d4
1025        vmull_vmlal_4   q9,  d3,  d4,  d5,  d6
1026        vqrshrun_s32    6,   q8,  d16, q9,  d17
1027        vmin_u16        q15, q8
1028        vst1_32         \d_strd,  d16, d17
1029        pop             {r4-r11,pc}
1030
103128:     // 2x8, 2x16 v
1032        vld1.8          {d0}, [\my, :64]
1033        sub             \sr2,  \src,  \s_strd, lsl #1
1034        add             \ds2,  \dst,  \d_strd
1035        sub             \src,  \sr2,  \s_strd
1036        lsl             \d_strd,  \d_strd,  #1
1037        lsl             \s_strd,  \s_strd,  #1
1038        vmovl.s8        q0,  d0
1039
1040        load_32         \src, \sr2, \s_strd, d2, d3, d4, d5, d6, d7, d16
1041        interleave_1_32 d2,  d3,  d4,  d5,  d6
1042        interleave_1_32 d6,  d7,  d16
1043216:
1044        subs            \h,  \h,  #8
1045        load_32         \sr2, \src, \s_strd, d17, d18, d19, d20
1046        load_32         \sr2, \src, \s_strd, d21, d22, d23, d24
1047        interleave_1_32 d16, d17, d18, d19, d20
1048        interleave_1_32 d20, d21, d22, d23, d24
1049        vmull_vmlal_8   q13, d2,  d3,  d4,  d5,  d6,  d7,  d16, d17
1050        vmull_vmlal_8   q1,  d4,  d5,  d6,  d7,  d16, d17, d18, d19
1051        vmull_vmlal_8   q2,  d6,  d7,  d16, d17, d18, d19, d20, d21
1052        vmull_vmlal_8   q3,  d16, d17, d18, d19, d20, d21, d22, d23
1053        vqrshrun_s32    6,   q13, d26, q1,  d27, q2,  d2,  q3,  d3
1054        vmin_u16        q15, q13, q1
1055        vst1_32         \d_strd,  d26, d27
1056        vst1_32         \d_strd,  d2,  d3
1057        ble             0f
1058        vmov            q1,  q9
1059        vmov            q2,  q10
1060        vmov            q3,  q11
1061        vmov            d16, d24
1062        b               216b
10630:
1064        pop             {r4-r11,pc}
1065.endif
1066
106740:
1068        bgt             480f
1069
1070        // 4x2, 4x4 v
1071        cmp             \h,  #2
1072        add             \my, \my, #2
1073        vld1.32         {d0[]}, [\my]
1074        sub             \src, \src, \s_strd
1075        add             \ds2, \dst, \d_strd
1076        add             \sr2, \src, \s_strd
1077        lsl             \s_strd, \s_strd, #1
1078        lsl             \d_strd, \d_strd, #1
1079        vmovl.s8        q0,  d0
1080
1081        load_reg        \src, \sr2, \s_strd, d1, d2, d3, d4, d5
1082        vmull_vmlal_4   q8,  d1,  d2,  d3,  d4
1083        vmull_vmlal_4   q9,  d2,  d3,  d4,  d5
1084        shift_store_4   \type, \d_strd, q8, q9, d16, d17
1085        ble             0f
1086        load_reg        \sr2, \src, \s_strd, d6, d7
1087        vmull_vmlal_4   q8,  d3,  d4,  d5,  d6
1088        vmull_vmlal_4   q9,  d4,  d5,  d6,  d7
1089        shift_store_4   \type, \d_strd, q8, q9, d16, d17
10900:
1091        pop             {r4-r11,pc}
1092
1093480:    // 4x8, 4x16 v
1094        vld1.8          {d0}, [\my, :64]
1095        sub             \sr2, \src, \s_strd, lsl #1
1096        add             \ds2, \dst, \d_strd
1097        sub             \src, \sr2, \s_strd
1098        lsl             \s_strd, \s_strd, #1
1099        lsl             \d_strd, \d_strd, #1
1100        vmovl.s8        q0,  d0
1101
1102        load_reg        \src, \sr2, \s_strd, d16, d17, d18, d19, d20, d21, d22
1103
110448:
1105        subs            \h,  \h,  #4
1106        load_reg        \sr2, \src, \s_strd, d23, d24, d25, d26
1107        vmull_vmlal_8   q1,  d16, d17, d18, d19, d20, d21, d22, d23
1108        vmull_vmlal_8   q2,  d17, d18, d19, d20, d21, d22, d23, d24
1109        vmull_vmlal_8   q3,  d18, d19, d20, d21, d22, d23, d24, d25
1110        vmull_vmlal_8   q8,  d19, d20, d21, d22, d23, d24, d25, d26
1111        shift_store_4   \type, \d_strd, q1, q2, d2, d3, q3, q8, d4, d5
1112        ble             0f
1113        vmov            q8,  q10
1114        vmov            q9,  q11
1115        vmov            q10, q12
1116        vmov            d22, d26
1117        b               48b
11180:
1119        pop             {r4-r11,pc}
1120
112180:
1122        bgt             880f
1123
1124        // 8x2, 8x4 v
1125        cmp             \h,  #2
1126        add             \my, \my, #2
1127        vld1.32         {d0[]}, [\my]
1128        sub             \src, \src, \s_strd
1129        add             \ds2, \dst, \d_strd
1130        add             \sr2, \src, \s_strd
1131        lsl             \s_strd, \s_strd, #1
1132        lsl             \d_strd, \d_strd, #1
1133        vmovl.s8        q0,  d0
1134
1135        load_reg        \src, \sr2, \s_strd, q1, q2, q3, q8, q9
1136        vmull_vmlal_4   q10, d2,  d4,  d6,  d16
1137        vmull_vmlal_4   q11, d3,  d5,  d7,  d17
1138        vmull_vmlal_4   q12, d4,  d6,  d16, d18
1139        vmull_vmlal_4   q13, d5,  d7,  d17, d19
1140        shift_store_8   \type, \d_strd, q10, q11, d20, d21, q12, q13, d22, d23
1141        ble             0f
1142        load_reg        \sr2, \src, \s_strd, q10, q11
1143        vmull_vmlal_4   q1,  d6,  d16, d18, d20
1144        vmull_vmlal_4   q2,  d7,  d17, d19, d21
1145        vmull_vmlal_4   q12, d16, d18, d20, d22
1146        vmull_vmlal_4   q13, d17, d19, d21, d23
1147        shift_store_8   \type, \d_strd, q1, q2, d2, d3, q12, q13, d4, d5
11480:
1149        pop             {r4-r11,pc}
1150
1151880:    // 8x6, 8x8, 8x16, 8x32 v
11521680:   // 16x8, 16x16, ...
1153320:    // 32x8, 32x16, ...
1154640:
11551280:
1156        vpush           {q4-q7}
1157        vld1.8          {d0}, [\my, :64]
1158        sub             \src, \src, \s_strd
1159        sub             \src, \src, \s_strd, lsl #1
1160        vmovl.s8        q0,  d0
1161        mov             \my, \h
1162168:
1163        add             \ds2, \dst, \d_strd
1164        add             \sr2, \src, \s_strd
1165        lsl             \s_strd, \s_strd, #1
1166        lsl             \d_strd, \d_strd, #1
1167
1168        load_reg        \src, \sr2, \s_strd, q5, q6, q7, q8, q9, q10, q11
1169
117088:
1171        subs            \h,  \h,  #2
1172        load_reg        \sr2, \src, \s_strd, q12, q13
1173        vmull_vmlal_8   q1,  d10, d12, d14, d16, d18, d20, d22, d24
1174        vmull_vmlal_8   q2,  d11, d13, d15, d17, d19, d21, d23, d25
1175        vmull_vmlal_8   q3,  d12, d14, d16, d18, d20, d22, d24, d26
1176        vmull_vmlal_8   q4,  d13, d15, d17, d19, d21, d23, d25, d27
1177        shift_store_8   \type, \d_strd, q1, q2,  d2,  d3,  q3,  q4,  d4,  d5
1178        ble             9f
1179        subs            \h,  \h,  #2
1180        load_reg        \sr2, \src, \s_strd, q1,  q2
1181        vmull_vmlal_8   q3,  d14, d16, d18, d20, d22, d24, d26, d2
1182        vmull_vmlal_8   q4,  d15, d17, d19, d21, d23, d25, d27, d3
1183        vmull_vmlal_8   q5,  d16, d18, d20, d22, d24, d26, d2,  d4
1184        vmull_vmlal_8   q6,  d17, d19, d21, d23, d25, d27, d3,  d5
1185        shift_store_8   \type, \d_strd, q3, q4,  d6,  d7,  q5,  q6,  d8,  d9
1186        ble             9f
1187        vmov            q5,  q9
1188        vmov            q6,  q10
1189        vmov            q7,  q11
1190        vmov            q8,  q12
1191        vmov            q9,  q13
1192        vmov            q10, q1
1193        vmov            q11, q2
1194        b               88b
11959:
1196        subs            \w,  \w,  #8
1197        ble             0f
1198        asr             \s_strd, \s_strd, #1
1199        asr             \d_strd, \d_strd, #1
1200        mls             \src, \s_strd, \my, \src
1201        mls             \dst, \d_strd, \my, \dst
1202        sub             \src, \src, \s_strd, lsl #3
1203        mov             \h,  \my
1204        add             \src, \src, #16
1205        add             \dst, \dst, #16
1206        b               168b
12070:
1208        vpop            {q4-q7}
1209        pop             {r4-r11,pc}
1210
1211160:
1212        bgt             1680b
1213
1214        // 16x2, 16x4 v
1215        vpush           {q6-q7}
1216        add             \my, \my, #2
1217        vld1.32         {d0[]}, [\my]
1218        sub             \src, \src, \s_strd
1219        vmovl.s8        q0,  d0
1220
1221        load_16s16      \src, \src, \s_strd, q6,  q7,  q8,  q9, q10, q11
122216:
1223        load_16s16      \src, \src, \s_strd, q12, q13
1224        subs            \h,  \h,  #1
1225        vmull_vmlal_4   q1,  d12, d16, d20, d24
1226        vmull_vmlal_4   q2,  d13, d17, d21, d25
1227        vmull_vmlal_4   q3,  d14, d18, d22, d26
1228        vmull_vmlal_4   q6,  d15, d19, d23, d27
1229        shift_store_16  \type, \d_strd, q1, q2, d2, d3, q3, q6, d4, d5
1230        ble             0f
1231        vmov            q6,  q8
1232        vmov            q7,  q9
1233        vmov            q8,  q10
1234        vmov            q9,  q11
1235        vmov            q10, q12
1236        vmov            q11, q13
1237        b               16b
12380:
1239        vpop            {q6-q7}
1240        pop             {r4-r11,pc}
1241
1242
1243L(\type\()_8tap_hv):
1244        cmp             \h,  #4
1245        ubfx            r10, \my, #7,  #7
1246        and             \my, \my, #0x7f
1247        it              gt
1248        movgt           \my, r10
12494:
1250        add             \my, r11, \my, lsl #3
1251
1252        adr             r10, L(\type\()_8tap_hv_tbl)
1253        neg             r12, r12           // -(6-intermediate_bits)
1254        ldr             r9,  [r10, r9, lsl #2]
1255        vdup.32         q14, r12           // -(6-intermediate_bits)
1256.ifc \type, put
1257        neg             r8,  lr            // -(6+intermeidate_bits)
1258.else
1259        vmov.i16        q13, #PREP_BIAS
1260.endif
1261        add             r10, r10, r9
1262.ifc \type, put
1263        vdup.32         q13, r8            // -(6+intermediate_bits)
1264.endif
1265        bx              r10
1266
1267        .align 2
1268L(\type\()_8tap_hv_tbl):
1269        .word 1280f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1270        .word 640f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1271        .word 320f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1272        .word 160f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1273        .word 80f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1274        .word 40f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1275        .word 20f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1276
127720:
1278.ifc \type, put
1279        add             \mx, \mx, #2
1280        vld1.32         {d0[]}, [\mx]
1281        bgt             280f
1282        add             \my, \my, #2
1283        vld1.32         {d2[]}, [\my]
1284
1285        // 2x2, 2x4 hv
1286        sub             \sr2, \src, #2
1287        sub             \src, \sr2, \s_strd
1288        add             \ds2, \dst, \d_strd
1289        lsl             \s_strd, \s_strd, #1
1290        lsl             \d_strd, \d_strd, #1
1291        vmovl.s8        q0,  d0
1292        vmovl.s8        q1,  d2
1293
1294        vld1.16         {q11}, [\src], \s_strd
1295        vext.8          d24, d22, d23, #2
1296        vmull.s16       q11, d22, d0
1297        vmull.s16       q12, d24, d0
1298        vpadd.s32       d22, d22, d23
1299        vpadd.s32       d23, d24, d25
1300        vpadd.s32       d22, d22, d23
1301        vrshl.s32       d16, d22, d28 // -(6-intermediate_bits)
1302        vmovn.i32       d16, q8
1303        bl              L(\type\()_8tap_filter_2)
1304
1305        vext.8          d16, d16, d16, #4
1306        vext.8          d16, d16, d24, #4
1307        vmov            d17, d24
1308
13092:
1310        bl              L(\type\()_8tap_filter_2)
1311
1312        vext.8          d18, d17, d24, #4
1313        vmull.s16       q2,  d16, d2[0]
1314        vmlal.s16       q2,  d17, d2[1]
1315        vmlal.s16       q2,  d18, d2[2]
1316        vmlal.s16       q2,  d24, d2[3]
1317
1318        vrshl.s32       q2,  q2,  q13 // -(6+intermediate_bits)
1319        vqmovun.s32     d4,  q2
1320        vmin.u16        d4,  d4,  d30
1321        subs            \h,  \h,  #2
1322        vst1.32         {d4[0]}, [\dst, :32], \d_strd
1323        vst1.32         {d4[1]}, [\ds2, :32], \d_strd
1324        ble             0f
1325        vmov            d16, d18
1326        vmov            d17, d24
1327        b               2b
1328
1329280:    // 2x8, 2x16, 2x32 hv
1330        vld1.8          {d2},  [\my, :64]
1331        sub             \src, \src, #2
1332        sub             \sr2, \src, \s_strd, lsl #1
1333        sub             \src, \sr2, \s_strd
1334        add             \ds2, \dst, \d_strd
1335        lsl             \s_strd, \s_strd, #1
1336        lsl             \d_strd, \d_strd, #1
1337        vmovl.s8        q0,  d0
1338        vmovl.s8        q1,  d2
1339
1340        vld1.16         {q11}, [\src], \s_strd
1341        vext.8          d24, d22, d23, #2
1342        vmull.s16       q11, d22, d0
1343        vmull.s16       q12, d24, d0
1344        vpadd.s32       d22, d22, d23
1345        vpadd.s32       d23, d24, d25
1346        vpadd.s32       d22, d22, d23
1347        vrshl.s32       d16, d22, d28 // -(6-intermediate_bits)
1348        vmovn.i32       d16, q8
1349
1350        bl              L(\type\()_8tap_filter_2)
1351
1352        vext.8          d16, d16, d16, #4
1353        vext.8          d16, d16, d24, #4
1354        vmov            d17, d24
1355        bl              L(\type\()_8tap_filter_2)
1356        vext.8          d18, d17, d24, #4
1357        vmov            d19, d24
1358        bl              L(\type\()_8tap_filter_2)
1359        vext.8          d20, d19, d24, #4
1360        vmov            d21, d24
1361
136228:
1363        bl              L(\type\()_8tap_filter_2)
1364        vext.8          d22, d21, d24, #4
1365        vmull.s16       q3,  d16, d2[0]
1366        vmlal.s16       q3,  d17, d2[1]
1367        vmlal.s16       q3,  d18, d2[2]
1368        vmlal.s16       q3,  d19, d2[3]
1369        vmlal.s16       q3,  d20, d3[0]
1370        vmlal.s16       q3,  d21, d3[1]
1371        vmlal.s16       q3,  d22, d3[2]
1372        vmlal.s16       q3,  d24, d3[3]
1373
1374        vrshl.s32       q3,  q3,  q13 // -(6+intermediate_bits)
1375        vqmovun.s32     d6,  q3
1376        vmin.u16        d6,  d6,  d30
1377        subs            \h,  \h,  #2
1378        vst1.32         {d6[0]}, [\dst, :32], \d_strd
1379        vst1.32         {d6[1]}, [\ds2, :32], \d_strd
1380        ble             0f
1381        vmov            q8,  q9
1382        vmov            q9,  q10
1383        vmov            d20, d22
1384        vmov            d21, d24
1385        b               28b
13860:
1387        pop             {r4-r11,pc}
1388
1389L(\type\()_8tap_filter_2):
1390        vld1.16         {q11}, [\sr2], \s_strd
1391        vld1.16         {q12}, [\src], \s_strd
1392        vext.8          d23, d22, d23, #2
1393        vext.8          d25, d24, d25, #2
1394        vtrn.32         q11, q12
1395        vmull.s16       q3,  d22, d0[0]
1396        vmlal.s16       q3,  d23, d0[1]
1397        vmlal.s16       q3,  d24, d0[2]
1398        vmlal.s16       q3,  d25, d0[3]
1399        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
1400        vmovn.i32       d24, q3
1401        bx              lr
1402.endif
1403
140440:
1405        add             \mx, \mx, #2
1406        vld1.32         {d0[]}, [\mx]
1407        bgt             480f
1408        add             \my, \my, #2
1409        vld1.32         {d2[]}, [\my]
1410        sub             \sr2, \src, #2
1411        sub             \src, \sr2, \s_strd
1412        add             \ds2, \dst, \d_strd
1413        lsl             \s_strd, \s_strd, #1
1414        lsl             \d_strd, \d_strd, #1
1415        vmovl.s8        q0,  d0
1416        vmovl.s8        q1,  d2
1417
1418        // 4x2, 4x4 hv
1419        vld1.16         {q11}, [\src], \s_strd
1420        vext.8          d24, d22, d23, #2
1421        vext.8          d25, d22, d23, #4
1422        vext.8          d23, d22, d23, #6
1423        vmull.s16       q10, d22, d0[0]
1424        vmlal.s16       q10, d24, d0[1]
1425        vmlal.s16       q10, d25, d0[2]
1426        vmlal.s16       q10, d23, d0[3]
1427        vrshl.s32       q10, q10, q14 // -(6-intermediate_bits)
1428        vmovn.i32       d17, q10
1429
1430        bl              L(\type\()_8tap_filter_4)
1431        vmov            q9,  q12
1432
14334:
1434        bl              L(\type\()_8tap_filter_4)
1435        vmull.s16       q2,  d17, d2[0]
1436        vmlal.s16       q2,  d18, d2[1]
1437        vmlal.s16       q2,  d19, d2[2]
1438        vmlal.s16       q2,  d24, d2[3]
1439        vmull.s16       q3,  d18, d2[0]
1440        vmlal.s16       q3,  d19, d2[1]
1441        vmlal.s16       q3,  d24, d2[2]
1442        vmlal.s16       q3,  d25, d2[3]
1443.ifc \type, put
1444        vrshl.s32       q2,  q2,  q13 // -(6+intermediate_bits)
1445        vrshl.s32       q3,  q3,  q13 // -(6+intermediate_bits)
1446        vqmovun.s32     d4,  q2
1447        vqmovun.s32     d5,  q3
1448        vmin.u16        q2,  q2,  q15
1449.else
1450        vrshrn.i32      d4,  q2,  #6
1451        vrshrn.i32      d5,  q3,  #6
1452        vsub.i16        q2,  q2,  q13 // PREP_BIAS
1453.endif
1454        subs            \h,  \h,  #2
1455
1456        vst1.16         {d4}, [\dst, :64], \d_strd
1457        vst1.16         {d5}, [\ds2, :64], \d_strd
1458        ble             0f
1459        vmov            d17, d19
1460        vmov            q9,  q12
1461        b               4b
14620:
1463        pop             {r4-r11,pc}
1464
1465480:    // 4x8, 4x16, 4x32 hv
1466        vpush           {d13-d15}
1467        vld1.8          {d2},  [\my, :64]
1468        sub             \src, \src, #2
1469        sub             \sr2, \src, \s_strd, lsl #1
1470        sub             \src, \sr2, \s_strd
1471        add             \ds2, \dst, \d_strd
1472        lsl             \s_strd, \s_strd, #1
1473        lsl             \d_strd, \d_strd, #1
1474        vmovl.s8        q0,  d0
1475        vmovl.s8        q1,  d2
1476
1477        vld1.16         {q11}, [\src], \s_strd
1478        vext.8          d24, d22, d23, #2
1479        vext.8          d25, d22, d23, #4
1480        vext.8          d23, d22, d23, #6
1481        vmull.s16       q10, d22, d0[0]
1482        vmlal.s16       q10, d24, d0[1]
1483        vmlal.s16       q10, d25, d0[2]
1484        vmlal.s16       q10, d23, d0[3]
1485        vrshl.s32       q10, q10, q14 // -(6-intermediate_bits)
1486        vmovn.i32       d13, q10
1487
1488        bl              L(\type\()_8tap_filter_4)
1489        vmov            q7,  q12
1490        bl              L(\type\()_8tap_filter_4)
1491        vmov            q8,  q12
1492        bl              L(\type\()_8tap_filter_4)
1493        vmov            q9,  q12
1494
149548:
1496        bl              L(\type\()_8tap_filter_4)
1497        vmull.s16       q2,  d13, d2[0]
1498        vmlal.s16       q2,  d14, d2[1]
1499        vmlal.s16       q2,  d15, d2[2]
1500        vmlal.s16       q2,  d16, d2[3]
1501        vmlal.s16       q2,  d17, d3[0]
1502        vmlal.s16       q2,  d18, d3[1]
1503        vmlal.s16       q2,  d19, d3[2]
1504        vmlal.s16       q2,  d24, d3[3]
1505        vmull.s16       q3,  d14, d2[0]
1506        vmlal.s16       q3,  d15, d2[1]
1507        vmlal.s16       q3,  d16, d2[2]
1508        vmlal.s16       q3,  d17, d2[3]
1509        vmlal.s16       q3,  d18, d3[0]
1510        vmlal.s16       q3,  d19, d3[1]
1511        vmlal.s16       q3,  d24, d3[2]
1512        vmlal.s16       q3,  d25, d3[3]
1513.ifc \type, put
1514        vrshl.s32       q2,  q2,  q13 // -(6+intermediate_bits)
1515        vrshl.s32       q3,  q3,  q13 // -(6+intermediate_bits)
1516        vqmovun.s32     d4,  q2
1517        vqmovun.s32     d5,  q3
1518        vmin.u16        q2,  q2,  q15
1519.else
1520        vrshrn.i32      d4,  q2,  #6
1521        vrshrn.i32      d5,  q3,  #6
1522        vsub.i16        q2,  q2,  q13 // PREP_BIAS
1523.endif
1524        subs            \h,  \h,  #2
1525        vst1.16         {d4}, [\dst, :64], \d_strd
1526        vst1.16         {d5}, [\ds2, :64], \d_strd
1527        ble             0f
1528        vmov            d13, d15
1529        vmov            q7,  q8
1530        vmov            q8,  q9
1531        vmov            q9,  q12
1532        b               48b
15330:
1534        vpop            {d13-d15}
1535        pop             {r4-r11,pc}
1536
1537L(\type\()_8tap_filter_4):
1538        vld1.16         {q10}, [\sr2], \s_strd
1539        vld1.16         {q11}, [\src], \s_strd
1540        vext.8          d24, d20, d21, #2
1541        vext.8          d25, d20, d21, #4
1542        vext.8          d21, d20, d21, #6
1543        vmull.s16       q3,  d20, d0[0]
1544        vmlal.s16       q3,  d24, d0[1]
1545        vmlal.s16       q3,  d25, d0[2]
1546        vmlal.s16       q3,  d21, d0[3]
1547        vext.8          d24, d22, d23, #2
1548        vext.8          d25, d22, d23, #4
1549        vext.8          d23, d22, d23, #6
1550        vmull.s16       q10, d22, d0[0]
1551        vmlal.s16       q10, d24, d0[1]
1552        vmlal.s16       q10, d25, d0[2]
1553        vmlal.s16       q10, d23, d0[3]
1554        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
1555        vrshl.s32       q10, q10, q14 // -(6-intermediate_bits)
1556        vmovn.i32       d24, q3
1557        vmovn.i32       d25, q10
1558        bx              lr
1559
156080:
1561160:
1562320:
1563        bgt             880f
1564        add             \my, \my, #2
1565        vld1.8          {d0},  [\mx, :64]
1566        vld1.32         {d2[]}, [\my]
1567        sub             \src,  \src,  #6
1568        sub             \src,  \src,  \s_strd
1569        vmovl.s8        q0,  d0
1570        vmovl.s8        q1,  d2
1571        mov             \my, \h
1572
1573164:    // 8x2, 8x4, 16x2, 16x4, 32x2, 32x4 hv
1574        add             \ds2, \dst, \d_strd
1575        add             \sr2,  \src,  \s_strd
1576        lsl             \d_strd, \d_strd, #1
1577        lsl             \s_strd, \s_strd, #1
1578
1579        vld1.16         {q11, q12}, [\src], \s_strd
1580        vmull.s16       q2,  d22, d0[0]
1581        vmull.s16       q3,  d23, d0[0]
1582        vdup.32         q14, r12      // -(6-intermediate_bits)
1583.irpc i, 1234567
1584        vext.8          q10, q11, q12, #(2*\i)
1585.if \i < 4
1586        vmlal.s16       q2,  d20, d0[\i]
1587        vmlal.s16       q3,  d21, d0[\i]
1588.else
1589        vmlal.s16       q2,  d20, d1[\i - 4]
1590        vmlal.s16       q3,  d21, d1[\i - 4]
1591.endif
1592.endr
1593        vrshl.s32       q2,  q2,  q14 // -(6-intermediate_bits)
1594        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
1595        vmovn.i32       d16, q2
1596        vmovn.i32       d17, q3
1597
1598        bl              L(\type\()_8tap_filter_8)
1599        vmov            q9,  q11
1600        vmov            q10, q12
1601
16028:
1603        bl              L(\type\()_8tap_filter_8)
1604        vmull.s16       q2,  d16, d2[0]
1605        vmull.s16       q3,  d17, d2[0]
1606        vmull.s16       q13, d18, d2[0]
1607        vmull.s16       q14, d19, d2[0]
1608.ifc \type, put
1609        vdup.32         q8,  r8      // -(6+intermediate_bits)
1610.endif
1611        vmlal.s16       q2,  d18, d2[1]
1612        vmlal.s16       q3,  d19, d2[1]
1613        vmlal.s16       q13, d20, d2[1]
1614        vmlal.s16       q14, d21, d2[1]
1615        vmlal.s16       q2,  d20, d2[2]
1616        vmlal.s16       q3,  d21, d2[2]
1617        vmlal.s16       q13, d22, d2[2]
1618        vmlal.s16       q14, d23, d2[2]
1619        vmlal.s16       q2,  d22, d2[3]
1620        vmlal.s16       q3,  d23, d2[3]
1621        vmlal.s16       q13, d24, d2[3]
1622        vmlal.s16       q14, d25, d2[3]
1623.ifc \type, put
1624        vdup.16         q9,  \bdmax  // bitdepth_max
1625        vrshl.s32       q2,  q2,  q8 // -(6+intermediate_bits)
1626        vrshl.s32       q3,  q3,  q8 // -(6+intermediate_bits)
1627        vrshl.s32       q13, q13, q8 // -(6+intermediate_bits)
1628        vrshl.s32       q14, q14, q8 // -(6+intermediate_bits)
1629        vqmovun.s32     d4,  q2
1630        vqmovun.s32     d5,  q3
1631        vqmovun.s32     d6,  q13
1632        vqmovun.s32     d7,  q14
1633        vmin.u16        q2,  q2,  q15
1634        vmin.u16        q3,  q3,  q15
1635.else
1636        vmov.i16        q9,  #PREP_BIAS
1637        vrshrn.i32      d4,  q2,  #6
1638        vrshrn.i32      d5,  q3,  #6
1639        vrshrn.i32      d6,  q13, #6
1640        vrshrn.i32      d7,  q14, #6
1641        vsub.i16        q2,  q2,  q9 // PREP_BIAS
1642        vsub.i16        q3,  q3,  q9 // PREP_BIAS
1643.endif
1644        subs            \h,  \h,  #2
1645        vst1.16         {q2}, [\dst, :128], \d_strd
1646        vst1.16         {q3}, [\ds2, :128], \d_strd
1647        ble             9f
1648        vmov            q8,  q10
1649        vmov            q9,  q11
1650        vmov            q10, q12
1651        b               8b
16529:
1653        subs            \w,  \w,  #8
1654        ble             0f
1655        asr             \s_strd,  \s_strd,  #1
1656        asr             \d_strd,  \d_strd,  #1
1657        mls             \src,  \s_strd,  \my,  \src
1658        mls             \dst,  \d_strd,  \my,  \dst
1659        sub             \src,  \src,  \s_strd,  lsl #2
1660        mov             \h,  \my
1661        add             \src,  \src,  #16
1662        add             \dst,  \dst,  #16
1663        b               164b
16640:
1665        pop             {r4-r11,pc}
1666
1667880:    // 8x8, 8x16, ..., 16x8, ..., 32x8, ... hv
1668640:
16691280:
1670        vpush           {q4-q7}
1671        vld1.8          {d0}, [\mx, :64]
1672        vld1.8          {d2}, [\my, :64]
1673        sub             \src,  \src,  #6
1674        sub             \src,  \src,  \s_strd
1675        sub             \src,  \src,  \s_strd, lsl #1
1676        vmovl.s8        q0,  d0
1677        vmovl.s8        q1,  d2
1678        mov             \my, \h
1679
1680168:
1681        add             \ds2, \dst, \d_strd
1682        add             \sr2,  \src,  \s_strd
1683        lsl             \d_strd, \d_strd, #1
1684        lsl             \s_strd, \s_strd, #1
1685
1686        vld1.16         {q11, q12}, [\src], \s_strd
1687        vmull.s16       q2,  d22, d0[0]
1688        vmull.s16       q3,  d23, d0[0]
1689        vdup.32         q14, r12      // -(6-intermediate_bits)
1690.irpc i, 1234567
1691        vext.8          q10, q11, q12, #(2*\i)
1692.if \i < 4
1693        vmlal.s16       q2,  d20, d0[\i]
1694        vmlal.s16       q3,  d21, d0[\i]
1695.else
1696        vmlal.s16       q2,  d20, d1[\i - 4]
1697        vmlal.s16       q3,  d21, d1[\i - 4]
1698.endif
1699.endr
1700        vrshl.s32       q2,  q2,  q14 // -(6-intermediate_bits)
1701        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
1702        vmovn.i32       d8,  q2
1703        vmovn.i32       d9,  q3
1704
1705        bl              L(\type\()_8tap_filter_8)
1706        vmov            q5,  q11
1707        vmov            q6,  q12
1708        bl              L(\type\()_8tap_filter_8)
1709        vmov            q7,  q11
1710        vmov            q8,  q12
1711        bl              L(\type\()_8tap_filter_8)
1712        vmov            q9,  q11
1713        vmov            q10, q12
1714
171588:
1716        bl              L(\type\()_8tap_filter_8)
1717        vmull.s16       q2,  d8,  d2[0]
1718        vmull.s16       q3,  d9,  d2[0]
1719        vmull.s16       q13, d10, d2[0]
1720        vmull.s16       q14, d11, d2[0]
1721.ifc \type, put
1722        vdup.32         q4,  r8      // -(6+intermediate_bits)
1723.endif
1724        vmlal.s16       q2,  d10, d2[1]
1725        vmlal.s16       q3,  d11, d2[1]
1726        vmlal.s16       q13, d12, d2[1]
1727        vmlal.s16       q14, d13, d2[1]
1728        vmlal.s16       q2,  d12, d2[2]
1729        vmlal.s16       q3,  d13, d2[2]
1730        vmlal.s16       q13, d14, d2[2]
1731        vmlal.s16       q14, d15, d2[2]
1732        vmlal.s16       q2,  d14, d2[3]
1733        vmlal.s16       q3,  d15, d2[3]
1734        vmlal.s16       q13, d16, d2[3]
1735        vmlal.s16       q14, d17, d2[3]
1736        vmlal.s16       q2,  d16, d3[0]
1737        vmlal.s16       q3,  d17, d3[0]
1738        vmlal.s16       q13, d18, d3[0]
1739        vmlal.s16       q14, d19, d3[0]
1740        vmlal.s16       q2,  d18, d3[1]
1741        vmlal.s16       q3,  d19, d3[1]
1742        vmlal.s16       q13, d20, d3[1]
1743        vmlal.s16       q14, d21, d3[1]
1744        vmlal.s16       q2,  d20, d3[2]
1745        vmlal.s16       q3,  d21, d3[2]
1746        vmlal.s16       q13, d22, d3[2]
1747        vmlal.s16       q14, d23, d3[2]
1748        vmlal.s16       q2,  d22, d3[3]
1749        vmlal.s16       q3,  d23, d3[3]
1750        vmlal.s16       q13, d24, d3[3]
1751        vmlal.s16       q14, d25, d3[3]
1752.ifc \type, put
1753        vrshl.s32       q2,  q2,  q4 // -(6+intermediate_bits)
1754        vrshl.s32       q3,  q3,  q4 // -(6+intermediate_bits)
1755        vrshl.s32       q13, q13, q4 // -(6+intermediate_bits)
1756        vrshl.s32       q14, q14, q4 // -(6+intermediate_bits)
1757        vqmovun.s32     d4,  q2
1758        vqmovun.s32     d5,  q3
1759        vqmovun.s32     d6,  q13
1760        vqmovun.s32     d7,  q14
1761        vmin.u16        q2,  q2,  q15
1762        vmin.u16        q3,  q3,  q15
1763.else
1764        vmov.i16        q5,  #PREP_BIAS
1765        vrshrn.i32      d4,  q2,  #6
1766        vrshrn.i32      d5,  q3,  #6
1767        vrshrn.i32      d6,  q13, #6
1768        vrshrn.i32      d7,  q14, #6
1769        vsub.i16        q2,  q2,  q5 // PREP_BIAS
1770        vsub.i16        q3,  q3,  q5 // PREP_BIAS
1771.endif
1772        subs            \h,  \h,  #2
1773        vst1.16         {q2}, [\dst, :128], \d_strd
1774        vst1.16         {q3}, [\ds2, :128], \d_strd
1775        ble             9f
1776        vmov            q4,  q6
1777        vmov            q5,  q7
1778        vmov            q6,  q8
1779        vmov            q7,  q9
1780        vmov            q8,  q10
1781        vmov            q9,  q11
1782        vmov            q10, q12
1783        b               88b
17849:
1785        subs            \w,  \w,  #8
1786        ble             0f
1787        asr             \s_strd,  \s_strd,  #1
1788        asr             \d_strd,  \d_strd,  #1
1789        mls             \src,  \s_strd,  \my,  \src
1790        mls             \dst,  \d_strd,  \my,  \dst
1791        sub             \src,  \src,  \s_strd,  lsl #3
1792        mov             \h,  \my
1793        add             \src,  \src,  #16
1794        add             \dst,  \dst,  #16
1795        b               168b
17960:
1797        vpop            {q4-q7}
1798        pop             {r4-r11,pc}
1799
1800L(\type\()_8tap_filter_8):
1801        vld1.16         {q13, q14}, [\sr2], \s_strd
1802        vmull.s16       q2,  d26, d0[0]
1803        vmull.s16       q3,  d27, d0[0]
1804.irpc i, 1234567
1805        vext.8          q12, q13, q14, #(2*\i)
1806.if \i < 4
1807        vmlal.s16       q2,  d24, d0[\i]
1808        vmlal.s16       q3,  d25, d0[\i]
1809.else
1810        vmlal.s16       q2,  d24, d1[\i - 4]
1811        vmlal.s16       q3,  d25, d1[\i - 4]
1812.endif
1813.endr
1814        vdup.32         q12, r12      // -(6-intermediate_bits)
1815        vld1.16         {q13, q14}, [\src], \s_strd
1816        vrshl.s32       q2,  q2,  q12 // -(6-intermediate_bits)
1817        vrshl.s32       q3,  q3,  q12 // -(6-intermediate_bits)
1818        vmovn.i32       d4,  q2
1819        vmovn.i32       d5,  q3
1820
1821        vmull.s16       q3,  d26, d0[0]
1822        vmull.s16       q11, d27, d0[0]
1823.irpc i, 1234567
1824        vext.8          q12, q13, q14, #(2*\i)
1825.if \i < 4
1826        vmlal.s16       q3,  d24, d0[\i]
1827        vmlal.s16       q11, d25, d0[\i]
1828.else
1829        vmlal.s16       q3,  d24, d1[\i - 4]
1830        vmlal.s16       q11, d25, d1[\i - 4]
1831.endif
1832.endr
1833        vdup.32         q13, r12      // -(6-intermediate_bits)
1834        vrshl.s32       q3,  q3,  q13 // -(6-intermediate_bits)
1835        vrshl.s32       q11, q11, q13 // -(6-intermediate_bits)
1836
1837        vmovn.i32       d24, q3
1838        vmovn.i32       d25, q11
1839        vmov            q11, q2
1840        bx              lr
1841endfunc
1842
1843function \type\()_bilin_16bpc_neon, export=1
1844        push            {r4-r11,lr}
1845        ldrd            r4,  r5,  [sp, #36]
1846        ldrd            r6,  r7,  [sp, #44]
1847.ifc \bdmax, r8
1848        ldr             r8,  [sp, #52]
1849.endif
1850        vdup.16         q1,  \mx
1851        vdup.16         q3,  \my
1852        rsb             r9,  \mx, #16
1853        rsb             r10, \my, #16
1854        vdup.16         q0,  r9
1855        vdup.16         q2,  r10
1856.ifc \type, prep
1857        lsl             \d_strd, \w, #1
1858.endif
1859        clz             \bdmax,   \bdmax       // bitdepth_max
1860        clz             r9,  \w
1861        sub             \bdmax,   \bdmax,  #18 // intermediate_bits = clz(bitdepth_max) - 18
1862        cmp             \mx, #0
1863        sub             r9,  r9,  #24
1864        rsb             r11, \bdmax, #4        // 4 - intermediate_bits
1865        add             r12, \bdmax, #4        // 4 + intermediate_bits
1866        bne             L(\type\()_bilin_h)
1867        cmp             \my, #0
1868        bne             L(\type\()_bilin_v)
1869        b               \type\()_neon
1870
1871L(\type\()_bilin_h):
1872        cmp             \my, #0
1873        bne             L(\type\()_bilin_hv)
1874
1875        adr             r10, L(\type\()_bilin_h_tbl)
1876        vdup.16         q15, r11               // 4 - intermediate_bits
1877        ldr             r9,  [r10, r9, lsl #2]
1878        vneg.s16        q15, q15               // -(4-intermediate_bits)
1879.ifc \type, put
1880        vdup.16         q14, \bdmax            // intermediate_bits
1881.else
1882        vmov.i16        q14, #PREP_BIAS
1883.endif
1884        add             r10, r10, r9
1885.ifc \type, put
1886        vneg.s16        q14, q14               // -intermediate_bits
1887.endif
1888        bx              r10
1889
1890        .align 2
1891L(\type\()_bilin_h_tbl):
1892        .word 1280f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
1893        .word 640f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
1894        .word 320f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
1895        .word 160f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
1896        .word 80f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
1897        .word 40f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
1898        .word 20f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
1899
190020:     // 2xN h
1901.ifc \type, put
1902        add             \ds2,  \dst,  \d_strd
1903        add             \sr2,  \src,  \s_strd
1904        lsl             \d_strd,  \d_strd,  #1
1905        lsl             \s_strd,  \s_strd,  #1
19062:
1907        vld1.16         {d16}, [\src], \s_strd
1908        vld1.16         {d18}, [\sr2], \s_strd
1909        vext.8          d17, d16, d16, #2
1910        vext.8          d19, d18, d18, #2
1911        vtrn.32         d16, d18
1912        vtrn.32         d17, d19
1913        subs            \h,  \h,  #2
1914        vmul.i16        d16, d16, d0
1915        vmla.i16        d16, d17, d2
1916        vrshl.u16       d16, d16, d30
1917        vrshl.u16       d16, d16, d28
1918        vst1.32         {d16[0]}, [\dst, :32], \d_strd
1919        vst1.32         {d16[1]}, [\ds2, :32], \d_strd
1920        bgt             2b
1921        pop             {r4-r11,pc}
1922.endif
1923
192440:     // 4xN h
1925        add             \ds2,  \dst,  \d_strd
1926        add             \sr2,  \src,  \s_strd
1927        lsl             \d_strd,  \d_strd,  #1
1928        lsl             \s_strd,  \s_strd,  #1
19294:
1930        vld1.16         {q8},  [\src], \s_strd
1931        vld1.16         {q10}, [\sr2], \s_strd
1932        vext.8          q9,  q8,  q8,  #2
1933        vext.8          q11, q10, q10, #2
1934        vmov            d17, d20
1935        vmov            d19, d22
1936        subs            \h,  \h,  #2
1937        vmul.i16        q8,  q8,  q0
1938        vmla.i16        q8,  q9,  q1
1939        vrshl.u16       q8,  q8,  q15
1940.ifc \type, put
1941        vrshl.u16       q8,  q8,  q14
1942.else
1943        vsub.i16        q8,  q8,  q14
1944.endif
1945        vst1.16         {d16}, [\dst, :64], \d_strd
1946        vst1.16         {d17}, [\ds2, :64], \d_strd
1947        bgt             4b
1948        pop             {r4-r11,pc}
1949
195080:     // 8xN h
1951        add             \ds2,  \dst,  \d_strd
1952        add             \sr2,  \src,  \s_strd
1953        lsl             \d_strd,  \d_strd,  #1
1954        lsl             \s_strd,  \s_strd,  #1
19558:
1956        vld1.16         {d16, d17, d18}, [\src], \s_strd
1957        vld1.16         {d20, d21, d22}, [\sr2], \s_strd
1958        vext.8          q9,  q8,  q9,  #2
1959        vext.8          q11, q10, q11, #2
1960        subs            \h,  \h,  #2
1961        vmul.i16        q8,  q8,  q0
1962        vmla.i16        q8,  q9,  q1
1963        vmul.i16        q10, q10, q0
1964        vmla.i16        q10, q11, q1
1965        vrshl.u16       q8,  q8,  q15
1966        vrshl.u16       q10, q10, q15
1967.ifc \type, put
1968        vrshl.u16       q8,  q8,  q14
1969        vrshl.u16       q10, q10, q14
1970.else
1971        vsub.i16        q8,  q8,  q14
1972        vsub.i16        q10, q10, q14
1973.endif
1974        vst1.16         {q8},  [\dst, :128], \d_strd
1975        vst1.16         {q10}, [\ds2, :128], \d_strd
1976        bgt             8b
1977        pop             {r4-r11,pc}
1978160:
1979320:
1980640:
19811280:   // 16xN, 32xN, ... h
1982        vpush           {q4-q7}
1983        add             \ds2,  \dst,  \d_strd
1984        add             \sr2,  \src,  \s_strd
1985        lsl             \s_strd,  \s_strd,  #1
1986
1987        sub             \s_strd,  \s_strd,  \w, lsl #1
1988        sub             \s_strd,  \s_strd,  #16
1989.ifc \type, put
1990        lsl             \d_strd,  \d_strd,  #1
1991        sub             \d_strd,  \d_strd,  \w, lsl #1
1992.endif
1993161:
1994        vld1.16         {q4}, [\src]!
1995        vld1.16         {q9}, [\sr2]!
1996        mov             \mx, \w
1997
199816:
1999        vld1.16         {q5,  q6},  [\src]!
2000        vld1.16         {q10, q11}, [\sr2]!
2001        vext.8          q7,  q4,  q5,  #2
2002        vext.8          q8,  q5,  q6,  #2
2003        vext.8          q12, q9,  q10, #2
2004        vext.8          q13, q10, q11, #2
2005        vmul.i16        q4,  q4,  q0
2006        vmla.i16        q4,  q7,  q1
2007        vmul.i16        q5,  q5,  q0
2008        vmla.i16        q5,  q8,  q1
2009        vmul.i16        q9,  q9,  q0
2010        vmla.i16        q9,  q12, q1
2011        vmul.i16        q10, q10, q0
2012        vmla.i16        q10, q13, q1
2013        vrshl.u16       q4,  q4,  q15
2014        vrshl.u16       q5,  q5,  q15
2015        vrshl.u16       q9,  q9,  q15
2016        vrshl.u16       q10, q10, q15
2017        subs            \mx, \mx, #16
2018.ifc \type, put
2019        vrshl.u16       q4,  q4,  q14
2020        vrshl.u16       q5,  q5,  q14
2021        vrshl.u16       q9,  q9,  q14
2022        vrshl.u16       q10, q10, q14
2023.else
2024        vsub.i16        q4,  q4,  q14
2025        vsub.i16        q5,  q5,  q14
2026        vsub.i16        q9,  q9,  q14
2027        vsub.i16        q10, q10, q14
2028.endif
2029        vst1.16         {q4, q5},  [\dst, :128]!
2030        vst1.16         {q9, q10}, [\ds2, :128]!
2031        ble             9f
2032
2033        vmov            q4,  q6
2034        vmov            q9,  q11
2035        b               16b
2036
20379:
2038        add             \dst,  \dst,  \d_strd
2039        add             \ds2,  \ds2,  \d_strd
2040        add             \src,  \src,  \s_strd
2041        add             \sr2,  \sr2,  \s_strd
2042
2043        subs            \h,  \h,  #2
2044        bgt             161b
2045        vpop            {q4-q7}
2046        pop             {r4-r11,pc}
2047
2048
2049L(\type\()_bilin_v):
2050        cmp             \h,  #4
2051        adr             r10, L(\type\()_bilin_v_tbl)
2052.ifc \type, prep
2053        vdup.16         q15, r11      // 4 - intermediate_bits
2054.endif
2055        ldr             r9,  [r10, r9, lsl #2]
2056.ifc \type, prep
2057        vmov.i16        q14, #PREP_BIAS
2058        vneg.s16        q15, q15      // -(4-intermediate_bits)
2059.endif
2060        add             r10, r10, r9
2061        bx              r10
2062
2063        .align 2
2064L(\type\()_bilin_v_tbl):
2065        .word 1280f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2066        .word 640f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2067        .word 320f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2068        .word 160f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2069        .word 80f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2070        .word 40f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2071        .word 20f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2072
207320:     // 2xN v
2074.ifc \type, put
2075        cmp             \h,  #2
2076        add             \ds2,  \dst,  \d_strd
2077        add             \sr2,  \src,  \s_strd
2078        lsl             \s_strd,  \s_strd,  #1
2079        lsl             \d_strd,  \d_strd,  #1
2080
2081        // 2x2 v
2082        vld1.32         {d16[]}, [\src], \s_strd
2083        bgt             24f
2084        vld1.32         {d17[]}, [\sr2], \s_strd
2085        vld1.32         {d18[]}, [\src], \s_strd
2086        vext.8          d16, d16, d17, #4
2087        vext.8          d17, d17, d18, #4
2088        vmul.i16        d16, d16, d4
2089        vmla.i16        d16, d17, d6
2090        vrshr.u16       d16, d16, #4
2091        vst1.32         {d16[0]}, [\dst, :32]
2092        vst1.32         {d16[1]}, [\ds2, :32]
2093        pop             {r4-r11,pc}
209424:     // 2x4, 2x8, ... v
2095        vld1.32         {d17[]}, [\sr2], \s_strd
2096        vld1.32         {d18[]}, [\src], \s_strd
2097        vld1.32         {d19[]}, [\sr2], \s_strd
2098        vld1.32         {d20[]}, [\src], \s_strd
2099        vext.8          d16, d16, d17, #4
2100        vext.8          d17, d17, d18, #4
2101        vext.8          d18, d18, d19, #4
2102        vext.8          d19, d19, d20, #4
2103        vswp            d17, d18
2104        vmul.i16        q8,  q8,  q2
2105        vmla.i16        q8,  q9,  q3
2106        subs            \h,  \h,  #4
2107        vrshr.u16       q8,  q8,  #4
2108        vst1.32         {d16[0]}, [\dst, :32], \d_strd
2109        vst1.32         {d16[1]}, [\ds2, :32], \d_strd
2110        vst1.32         {d17[0]}, [\dst, :32], \d_strd
2111        vst1.32         {d17[1]}, [\ds2, :32], \d_strd
2112        ble             0f
2113        vmov            d16, d20
2114        b               24b
21150:
2116        pop             {r4-r11,pc}
2117.endif
2118
211940:     // 4xN v
2120        add             \ds2,  \dst,  \d_strd
2121        add             \sr2,  \src,  \s_strd
2122        lsl             \s_strd,  \s_strd,  #1
2123        lsl             \d_strd,  \d_strd,  #1
2124        vld1.16         {d16}, [\src], \s_strd
21254:
2126        vld1.16         {d17}, [\sr2], \s_strd
2127        vld1.16         {d19}, [\src], \s_strd
2128        vmov            d18, d17
2129        vmul.i16        q8,  q8,  q2
2130        vmla.i16        q8,  q9,  q3
2131        subs            \h,  \h,  #2
2132.ifc \type, put
2133        vrshr.u16       q8,  q8,  #4
2134.else
2135        vrshl.u16       q8,  q8,  q15
2136        vsub.i16        q8,  q8,  q14
2137.endif
2138        vst1.16         {d16}, [\dst, :64], \d_strd
2139        vst1.16         {d17}, [\ds2, :64], \d_strd
2140        ble             0f
2141        vmov            d16, d19
2142        b               4b
21430:
2144        pop             {r4-r11,pc}
2145
214680:     // 8xN v
2147        add             \ds2,  \dst,  \d_strd
2148        add             \sr2,  \src,  \s_strd
2149        lsl             \s_strd,  \s_strd,  #1
2150        lsl             \d_strd,  \d_strd,  #1
2151        vld1.16         {q8},  [\src], \s_strd
21528:
2153        vld1.16         {q9},  [\sr2], \s_strd
2154        vld1.16         {q10}, [\src], \s_strd
2155        vmul.i16        q8,  q8,  q2
2156        vmla.i16        q8,  q9,  q3
2157        vmul.i16        q9,  q9,  q2
2158        vmla.i16        q9,  q10, q3
2159        subs            \h,  \h,  #2
2160.ifc \type, put
2161        vrshr.u16       q8,  q8,  #4
2162        vrshr.u16       q9,  q9,  #4
2163.else
2164        vrshl.u16       q8,  q8,  q15
2165        vrshl.u16       q9,  q9,  q15
2166        vsub.i16        q8,  q8,  q14
2167        vsub.i16        q9,  q9,  q14
2168.endif
2169        vst1.16         {q8}, [\dst, :128], \d_strd
2170        vst1.16         {q9}, [\ds2, :128], \d_strd
2171        ble             0f
2172        vmov            q8,  q10
2173        b               8b
21740:
2175        pop             {r4-r11,pc}
2176
2177160:    // 16xN, 32xN, ...
2178320:
2179640:
21801280:
2181        mov             \my, \h
21821:
2183        add             \ds2, \dst, \d_strd
2184        add             \sr2, \src, \s_strd
2185        lsl             \s_strd, \s_strd, #1
2186        lsl             \d_strd, \d_strd, #1
2187
2188        vld1.16         {q8,  q9},  [\src], \s_strd
21892:
2190        vld1.16         {q10, q11}, [\sr2], \s_strd
2191        vld1.16         {q12, q13}, [\src], \s_strd
2192        vmul.i16        q8,  q8,  q2
2193        vmla.i16        q8,  q10, q3
2194        vmul.i16        q9,  q9,  q2
2195        vmla.i16        q9,  q11, q3
2196        vmul.i16        q10, q10, q2
2197        vmla.i16        q10, q12, q3
2198        vmul.i16        q11, q11, q2
2199        vmla.i16        q11, q13, q3
2200        subs            \h,  \h,  #2
2201.ifc \type, put
2202        vrshr.u16       q8,  q8,  #4
2203        vrshr.u16       q9,  q9,  #4
2204        vrshr.u16       q10, q10, #4
2205        vrshr.u16       q11, q11, #4
2206.else
2207        vrshl.u16       q8,  q8,  q15
2208        vrshl.u16       q9,  q9,  q15
2209        vrshl.u16       q10, q10, q15
2210        vrshl.u16       q11, q11, q15
2211        vsub.i16        q8,  q8,  q14
2212        vsub.i16        q9,  q9,  q14
2213        vsub.i16        q10, q10, q14
2214        vsub.i16        q11, q11, q14
2215.endif
2216        vst1.16         {q8,  q9},  [\dst, :128], \d_strd
2217        vst1.16         {q10, q11}, [\ds2, :128], \d_strd
2218        ble             9f
2219        vmov            q8,  q12
2220        vmov            q9,  q13
2221        b               2b
22229:
2223        subs            \w,  \w,  #16
2224        ble             0f
2225        asr             \s_strd, \s_strd, #1
2226        asr             \d_strd, \d_strd, #1
2227        mls             \src, \s_strd, \my, \src
2228        mls             \dst, \d_strd, \my, \dst
2229        sub             \src, \src, \s_strd, lsl #1
2230        mov             \h,  \my
2231        add             \src, \src, #32
2232        add             \dst, \dst, #32
2233        b               1b
22340:
2235        pop             {r4-r11,pc}
2236
2237L(\type\()_bilin_hv):
2238        adr             r10, L(\type\()_bilin_hv_tbl)
2239        vdup.16         q15, r11          // 4 - intermediate_bits
2240        ldr             r9,  [r10, r9, lsl #2]
2241        vneg.s16        q15, q15          // -(4-intermediate_bits)
2242.ifc \type, put
2243        vdup.32         q14, r12          // 4 + intermediate_bits
2244.else
2245        vmov.i16        q14, #PREP_BIAS
2246.endif
2247        add             r10, r10, r9
2248.ifc \type, put
2249        vneg.s32        q14, q14          // -(4+intermediate_bits)
2250.endif
2251        bx              r10
2252
2253        .align 2
2254L(\type\()_bilin_hv_tbl):
2255        .word 1280f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2256        .word 640f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2257        .word 320f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2258        .word 160f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2259        .word 80f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2260        .word 40f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2261        .word 20f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2262
226320:     // 2xN hv
2264.ifc \type, put
2265        add             \sr2, \src, \s_strd
2266        add             \ds2, \dst, \d_strd
2267        lsl             \s_strd, \s_strd, #1
2268        lsl             \d_strd, \d_strd, #1
2269
2270        vld1.16         {d20}, [\src], \s_strd
2271        vext.8          d21, d20, d20, #2
2272        vmul.i16        d16, d20, d0
2273        vmla.i16        d16, d21, d2
2274        vrshl.u16       d16, d16, d30
2275        vext.8          d16, d16, d16, #4
2276
22772:
2278        vld1.16         {d20}, [\sr2], \s_strd
2279        vld1.16         {d22}, [\src], \s_strd
2280        vext.8          d21, d20, d20, #2
2281        vext.8          d23, d22, d22, #2
2282        vtrn.32         d20, d22
2283        vtrn.32         d21, d23
2284        vmul.i16        d18, d20, d0
2285        vmla.i16        d18, d21, d2
2286        vrshl.u16       d18, d18, d30
2287
2288        vext.8          d16, d16, d18, #4
2289
2290        vmull.u16       q8,  d16, d4
2291        vmlal.u16       q8,  d18, d6
2292        vrshl.u32       q8,  q8,  q14
2293        vmovn.i32       d16, q8
2294        subs            \h,  \h,  #2
2295        vst1.32         {d16[0]}, [\dst, :32], \d_strd
2296        vst1.32         {d16[1]}, [\ds2, :32], \d_strd
2297        ble             0f
2298        vmov            d16, d18
2299        b               2b
23000:
2301        pop             {r4-r11,pc}
2302.endif
2303
230440:     // 4xN hv
2305        add             \sr2, \src, \s_strd
2306        add             \ds2, \dst, \d_strd
2307        lsl             \s_strd, \s_strd, #1
2308        lsl             \d_strd, \d_strd, #1
2309
2310        vld1.16         {q10}, [\src], \s_strd
2311        vext.8          d21, d20, d21, #2
2312        vmul.i16        d16, d20, d0
2313        vmla.i16        d16, d21, d2
2314        vrshl.u16       d16, d16, d30
2315
23164:
2317        vld1.16         {q10}, [\sr2], \s_strd
2318        vld1.16         {q11}, [\src], \s_strd
2319        vext.8          d21, d20, d21, #2
2320        vext.8          d23, d22, d23, #2
2321        vswp            d21, d22
2322        vmul.i16        q9,  q10, q0
2323        vmla.i16        q9,  q11, q1
2324        vrshl.u16       q9,  q9,  q15
2325
2326        vmull.u16       q10, d16, d4
2327        vmlal.u16       q10, d18, d6
2328        vmull.u16       q11, d18, d4
2329        vmlal.u16       q11, d19, d6
2330.ifc \type, put
2331        vrshl.u32       q10, q10, q14
2332        vrshl.u32       q11, q11, q14
2333        vmovn.i32       d20, q10
2334        vmovn.i32       d21, q11
2335.else
2336        vrshrn.i32      d20, q10, #4
2337        vrshrn.i32      d21, q11, #4
2338        vsub.i16        q10, q10, q14
2339.endif
2340        subs            \h,  \h,  #2
2341        vst1.16         {d20}, [\dst, :64], \d_strd
2342        vst1.16         {d21}, [\ds2, :64], \d_strd
2343        ble             0f
2344        vmov            d16, d19
2345        b               4b
23460:
2347        pop             {r4-r11,pc}
2348
234980:     // 8xN, 16xN, ... hv
2350160:
2351320:
2352640:
23531280:
2354        mov             \my, \h
2355
23561:
2357        add             \sr2, \src, \s_strd
2358        add             \ds2, \dst, \d_strd
2359        lsl             \s_strd, \s_strd, #1
2360        lsl             \d_strd, \d_strd, #1
2361
2362        vld1.16         {d20, d21, d22}, [\src], \s_strd
2363        vext.8          q11, q10, q11, #2
2364        vmul.i16        q8,  q10, q0
2365        vmla.i16        q8,  q11, q1
2366        vrshl.u16       q8,  q8,  q15
2367
23682:
2369        vld1.16         {d20, d21, d22}, [\sr2], \s_strd
2370        vld1.16         {d24, d25, d26}, [\src], \s_strd
2371        vext.8          q11, q10, q11, #2
2372        vext.8          q13, q12, q13, #2
2373        vmul.i16        q9,  q10, q0
2374        vmla.i16        q9,  q11, q1
2375        vmul.i16        q10, q12, q0
2376        vmla.i16        q10, q13, q1
2377        vrshl.u16       q9,  q9,  q15
2378        vrshl.u16       q10, q10, q15
2379
2380        vmull.u16       q11, d16, d4
2381        vmlal.u16       q11, d18, d6
2382        vmull.u16       q12, d17, d4
2383        vmlal.u16       q12, d19, d6
2384        vmull.u16       q8,  d18, d4
2385        vmlal.u16       q8,  d20, d6
2386        vmull.u16       q9,  d19, d4
2387        vmlal.u16       q9,  d21, d6
2388.ifc \type, put
2389        vrshl.u32       q11, q11, q14
2390        vrshl.u32       q12, q12, q14
2391        vrshl.u32       q8,  q8,  q14
2392        vrshl.u32       q9,  q9,  q14
2393        vmovn.i32       d22, q11
2394        vmovn.i32       d23, q12
2395        vmovn.i32       d16, q8
2396        vmovn.i32       d17, q9
2397.else
2398        vrshrn.i32      d22, q11, #4
2399        vrshrn.i32      d23, q12, #4
2400        vrshrn.i32      d16, q8,  #4
2401        vrshrn.i32      d17, q9,  #4
2402        vsub.i16        q11, q11, q14
2403        vsub.i16        q8,  q8,  q14
2404.endif
2405        subs            \h,  \h,  #2
2406        vst1.16         {q11}, [\dst, :128], \d_strd
2407        vst1.16         {q8},  [\ds2, :128], \d_strd
2408        ble             9f
2409        vmov            q8,  q10
2410        b               2b
24119:
2412        subs            \w,  \w,  #8
2413        ble             0f
2414        asr             \s_strd,  \s_strd,  #1
2415        asr             \d_strd,  \d_strd,  #1
2416        mls             \src,  \s_strd,  \my,  \src
2417        mls             \dst,  \d_strd,  \my,  \dst
2418        sub             \src,  \src,  \s_strd,  lsl #1
2419        mov             \h,  \my
2420        add             \src,  \src,  #16
2421        add             \dst,  \dst,  #16
2422        b               1b
24230:
2424        pop             {r4-r11,pc}
2425endfunc
2426.endm
2427
2428filter_fn put,  r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10
2429filter_fn prep, r0, r8, r1, r2, r3, r4, r5, r6, r7, r9, r10
2430
2431.macro load_filter_ptr src
2432        asr             r12, \src, #10
2433        add             r12, r11, r12, lsl #3
2434.endm
2435
2436.macro load_filter_coef dst, src, inc
2437        vld1.8          {\dst}, [r12, :64]
2438        add             \src, \src, \inc
2439.endm
2440
2441.macro load_filter_row dst, src, inc
2442        load_filter_ptr \src
2443        load_filter_coef \dst, \src, \inc
2444.endm
2445
2446function warp_filter_horz_neon
2447        load_filter_ptr r5                  // filter 0
2448        vld1.16         {q6,q7}, [r2], r3
2449
2450        load_filter_coef d0, r5,  r7        // filter 0
2451        load_filter_row d2,  r5,  r7        // filter 1
2452        vmovl.s8        q0,  d0             // filter 0
2453        vext.8          q3,  q6,  q7,  #2*1 // filter 1 pixels
2454        vmovl.s8        q1,  d2             // filter 1
2455
2456        vmull.s16       q4,  d12, d0        // filter 0 output (0-3)
2457        vmull.s16       q5,  d13, d1        // filter 0 output (4-7)
2458
2459        load_filter_ptr r5                  // filter 2
2460
2461        vmull.s16       q2,  d6,  d2        // filter 1 output (0-3)
2462        vmull.s16       q3,  d7,  d3        // filter 1 output (4-7)
2463
2464        load_filter_coef d0, r5,  r7        // filter 2
2465
2466        vpadd.i32       d8,  d8,  d9        // half pixel 0 (2x32)
2467        vpadd.i32       d9,  d10, d11       // half pixel 0 (2x32)
2468
2469        load_filter_ptr r5                  // filter 3
2470
2471        vpadd.i32       d4,  d4,  d5        // half pixel 1 (2x32)
2472        vpadd.i32       d5,  d6,  d7        // half pixel 1 (2x32)
2473
2474        vmovl.s8        q0,  d0             // filter 2
2475        vext.8          q3,  q6,  q7,  #2*2 // filter 2 pixels
2476
2477        vpadd.i32       d8,  d8,  d9        // pixel 0 (2x32)
2478        vpadd.i32       d9,  d4,  d5        // pixel 1 (2x32)
2479
2480        load_filter_coef d2, r5,  r7        // filter 3
2481
2482        vmull.s16       q2,  d6,  d0        // filter 2 output (0-3)
2483        vmull.s16       q3,  d7,  d1        // filter 2 output (4-7)
2484
2485        load_filter_ptr r5                  // filter 4
2486
2487        vpadd.i32       d8,  d8,  d9        // pixel 0,1
2488
2489        vpadd.i32       d9,  d4,  d5        // half pixel 2 (2x32)
2490        vpadd.i32       d10, d6,  d7        // half pixel 2 (2x32)
2491
2492        vmovl.s8        q1,  d2             // filter 3
2493        vext.8          q3,  q6,  q7,  #2*3 // filter 3 pixels
2494
2495        load_filter_coef d0, r5,  r7        // filter 4
2496
2497        vpadd.i32       d9,  d9,  d10       // pixel 2 (2x32)
2498
2499        vmull.s16       q2,  d6,  d2        // filter 3 output (0-3)
2500        vmull.s16       q3,  d7,  d3        // filter 3 output (4-7)
2501
2502        vmovl.s8        q0,  d0             // filter 4
2503        load_filter_ptr r5                  // filter 5
2504
2505        vpadd.i32       d10, d4,  d5        // half pixel 3 (2x32)
2506        vpadd.i32       d11, d6,  d7        // half pixel 3 (2x32)
2507
2508        vext.8          q3,  q6,  q7,  #2*4 // filter 4 pixels
2509        load_filter_coef d2, r5,  r7        // filter 5
2510
2511        vpadd.i32       d10, d10, d11       // pixel 3 (2x32)
2512
2513        vpadd.i32       d9,  d9,  d10       // pixel 2,3
2514
2515        vmull.s16       q2,  d6,  d0        // filter 4 output (0-3)
2516        vmull.s16       q3,  d7,  d1        // filter 4 output (4-7)
2517
2518        vmovl.s8        q1,  d2             // filter 5
2519        load_filter_ptr r5                  // filter 6
2520
2521        vpadd.i32       d10, d4,  d5        // half pixel 4 (2x32)
2522        vpadd.i32       d11, d6,  d7        // half pixel 4 (2x32)
2523
2524        vext.8          q3,  q6,  q7,  #2*5 // filter 5 pixels
2525        load_filter_coef d0, r5,  r7        // filter 6
2526
2527        vpadd.i32       d10, d10, d11       // pixel 4 (2x32)
2528
2529        vmull.s16       q2,  d6,  d2        // filter 5 output (0-3)
2530        vmull.s16       q3,  d7,  d3        // filter 5 output (4-7)
2531
2532        vmovl.s8        q0,  d0             // filter 6
2533        load_filter_ptr r5                  // filter 7
2534
2535        vpadd.i32       d4,  d4,  d5        // half pixel 5 (2x32)
2536        vpadd.i32       d5,  d6,  d7        // half pixel 5 (2x32)
2537
2538        vext.8          q3,  q6,  q7,  #2*6 // filter 6 pixels
2539        load_filter_coef d2, r5,  r7        // filter 7
2540
2541        vpadd.i32       d11, d4,  d5        // pixel 5 (2x32)
2542
2543        vmull.s16       q2,  d6,  d0        // filter 6 output (0-3)
2544        vmull.s16       q3,  d7,  d1        // filter 6 output (4-7)
2545
2546        vmovl.s8        q1,  d2             // filter 7
2547
2548        vpadd.i32       d10, d10, d11       // pixel 4,5
2549
2550        vpadd.i32       d4,  d4,  d5        // half pixel 6 (2x32)
2551        vpadd.i32       d5,  d6,  d7        // half pixel 6 (2x32)
2552
2553        vext.8          q3,  q6,  q7,  #2*7 // filter 7 pixels
2554
2555        vpadd.i32       d11, d4,  d5        // pixel 6 (2x32)
2556
2557        vmull.s16       q2,  d6,  d2        // filter 7 output (0-3)
2558        vmull.s16       q3,  d7,  d3        // filter 7 output (4-7)
2559
2560        vld1.32         {d14[],d15[]}, [sp] // -(7 - intermediate_bits)
2561
2562        vpadd.i32       d4,  d4,  d5        // half pixel 7 (2x32)
2563        vpadd.i32       d5,  d6,  d7        // half pixel 7 (2x32)
2564
2565        sub             r5,  r5,  r7, lsl #3
2566
2567        vpadd.i32       d4,  d4,  d5        // pixel 7 (2x32)
2568
2569        add             r5,  r5,  r8
2570
2571        vpadd.i32       d11, d11, d4        // pixel 6,7
2572
2573        vrshl.s32       q4,  q4,  q7        // -(7 - intermediate_bits)
2574        vrshl.s32       q5,  q5,  q7        // -(7 - intermediate_bits)
2575
2576        bx              lr
2577endfunc
2578
2579// void dav1d_warp_affine_8x8_16bpc_neon(
2580//         pixel *dst, const ptrdiff_t dst_stride,
2581//         const pixel *src, const ptrdiff_t src_stride,
2582//         const int16_t *const abcd, int mx, int my,
2583//         const int bitdepth_max)
2584.macro warp t
2585function warp_affine_8x8\t\()_16bpc_neon, export=1
2586        push            {r4-r11,lr}
2587        vpush           {q4-q7}
2588        ldrd            r4,  r5,  [sp, #100]
2589        ldrd            r6,  r7,  [sp, #108]
2590        sub             sp,  sp,  #8
2591
2592        clz             r7,  r7
2593                                      // intermediate_bits = clz(bitdepth_max) - 18
2594.ifb \t
2595        sub             r8,  r7,  #11 // 7 + intermediate_bits = clz(bitdepth_max) - 18 + 7
2596.endif
2597        sub             r7,  r7,  #25 // -(7 - intermediate_bits)
2598.ifb \t
2599        neg             r8,  r8       // -(7 + intermediate_bits)
2600.endif
2601        str             r7,  [sp]     // spill -(7 - intermediate_bits) on stack
2602.ifb \t
2603        str             r8,  [sp, #4] // spill -(7 + intermediate_bits) on stack
2604.endif
2605
2606        ldrd            r8,  r9,  [r4]
2607        sxth            r7,  r8
2608        asr             r8,  r8, #16
2609        asr             r4,  r9, #16
2610        sxth            r9,  r9
2611        mov             r10, #8
2612        sub             r2,  r2,  r3, lsl #1
2613        sub             r2,  r2,  r3
2614        sub             r2,  r2,  #6
2615        movrel          r11, X(mc_warp_filter), 64*8
2616.ifnb \t
2617        lsl             r1,  r1,  #1
2618.endif
2619        add             r5,  r5,  #512
2620        add             r6,  r6,  #512
2621
2622        bl              warp_filter_horz_neon
2623        vmovn.i32       d16, q4
2624        vmovn.i32       d17, q5
2625        bl              warp_filter_horz_neon
2626        vmovn.i32       d18, q4
2627        vmovn.i32       d19, q5
2628        bl              warp_filter_horz_neon
2629        vmovn.i32       d20, q4
2630        vmovn.i32       d21, q5
2631        bl              warp_filter_horz_neon
2632        vmovn.i32       d22, q4
2633        vmovn.i32       d23, q5
2634        bl              warp_filter_horz_neon
2635        vmovn.i32       d24, q4
2636        vmovn.i32       d25, q5
2637        bl              warp_filter_horz_neon
2638        vmovn.i32       d26, q4
2639        vmovn.i32       d27, q5
2640        bl              warp_filter_horz_neon
2641        vmovn.i32       d28, q4
2642        vmovn.i32       d29, q5
2643
26441:
2645        bl              warp_filter_horz_neon
2646        vmovn.i32       d30, q4
2647        vmovn.i32       d31, q5
2648
2649        load_filter_row d8,  r6,  r9
2650        load_filter_row d9,  r6,  r9
2651        load_filter_row d10, r6,  r9
2652        load_filter_row d11, r6,  r9
2653        load_filter_row d12, r6,  r9
2654        load_filter_row d13, r6,  r9
2655        load_filter_row d14, r6,  r9
2656        load_filter_row d15, r6,  r9
2657        transpose_8x8b  q4,  q5,  q6,  q7,  d8,  d9,  d10, d11, d12, d13, d14, d15
2658        vmovl.s8        q1,  d8
2659        vmovl.s8        q2,  d9
2660        vmovl.s8        q3,  d10
2661        vmovl.s8        q4,  d11
2662        vmovl.s8        q5,  d12
2663        vmovl.s8        q6,  d13
2664
2665        sub             r6,  r6,  r9, lsl #3
2666
2667        // This ordering of vmull/vmlal is highly beneficial for
2668        // Cortex A8/A9/A53 here, but harmful for Cortex A7.
2669        vmull.s16       q0,  d16,  d2
2670        vmlal.s16       q0,  d18,  d4
2671        vmlal.s16       q0,  d20,  d6
2672        vmlal.s16       q0,  d22,  d8
2673        vmlal.s16       q0,  d24,  d10
2674        vmlal.s16       q0,  d26,  d12
2675        vmull.s16       q1,  d17,  d3
2676        vmlal.s16       q1,  d19,  d5
2677        vmlal.s16       q1,  d21,  d7
2678        vmlal.s16       q1,  d23,  d9
2679        vmlal.s16       q1,  d25,  d11
2680        vmlal.s16       q1,  d27,  d13
2681
2682        vmovl.s8        q2,  d14
2683        vmovl.s8        q3,  d15
2684
2685        vmlal.s16       q0,  d28,  d4
2686        vmlal.s16       q0,  d30,  d6
2687        vmlal.s16       q1,  d29,  d5
2688        vmlal.s16       q1,  d31,  d7
2689
2690.ifb \t
2691        ldr             lr,  [sp, #4]   // -(7 + intermediate_bits)
2692        ldr             r12, [sp, #120] // bitdepth_max
2693        vdup.32         q2,  lr         // -(7 + intermediate_bits)
2694        vdup.16         q3,  r12        // bitdepth_max
2695.endif
2696
2697        vmov            q8,  q9
2698        vmov            q9,  q10
2699.ifb \t
2700        vrshl.s32       q0,  q0,  q2    // -(7 + intermediate_bits)
2701        vrshl.s32       q1,  q1,  q2    // -(7 + intermediate_bits)
2702.else
2703        vrshrn.s32      d0,  q0,  #7
2704        vrshrn.s32      d1,  q1,  #7
2705        vmov.i16        q3,  #PREP_BIAS
2706.endif
2707        vmov            q10, q11
2708.ifb \t
2709        vqmovun.s32     d0,  q0
2710        vqmovun.s32     d1,  q1
2711.else
2712        vsub.i16        q0,  q0,  q3    // PREP_BIAS
2713.endif
2714        vmov            q11, q12
2715        vmov            q12, q13
2716.ifb \t
2717        vmin.u16        q0,  q0,  q3    // bitdepth_max
2718.endif
2719        vmov            q13, q14
2720        vmov            q14, q15
2721        subs            r10, r10, #1
2722        vst1.16         {q0}, [r0, :128], r1
2723
2724        add             r6,  r6,  r4
2725        bgt             1b
2726
2727        add             sp,  sp,  #8
2728        vpop            {q4-q7}
2729        pop             {r4-r11,pc}
2730endfunc
2731.endm
2732
2733warp
2734warp t
2735