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        ldrd            r4,  r5,  [sp, #20]
127        ldr             r6,  [sp, #28]
128        clz             r4,  r4
129.ifnc \type, avg
130        ldr             r7,  [sp, #32]
131        vmov.i16        q14, #0
132        vdup.16         q15, r7         // bitdepth_max
133.endif
134.ifc \type, w_avg
135        vpush           {q4}
136.endif
137.ifc \type, mask
138        vpush           {q4-q7}
139.endif
140        clz             r7,  \bdmax
141        sub             r7,  r7,  #18   // intermediate_bits = clz(bitdepth_max) - 18
142.ifc \type, avg
143        mov             lr,  #1
144        movw            r12, #2*PREP_BIAS
145        lsl             lr,  lr,  r7    // 1 << intermediate_bits
146        neg             r12, r12         // -2*PREP_BIAS
147        add             r7,  r7,  #1
148        sub             r12, r12, lr    // -2*PREP_BIAS - 1 << intermediate_bits
149        neg             r7,  r7         // -(intermediate_bits+1)
150        vdup.16         q12, r12         // -2*PREP_BIAS - 1 << intermediate_bits
151        vdup.16         q13, r7         // -(intermediate_bits+1)
152.else
153        mov             r12, #PREP_BIAS
154        lsr             r12, r12, r7    // PREP_BIAS >> intermediate_bits
155        neg             r7,  r7         // -intermediate_bits
156        vdup.16         q12, r12         // PREP_BIAS >> intermediate_bits
157        vdup.16         q13, r7         // -intermediate_bits
158.endif
159.ifc \type, w_avg
160        vdup.32         q4,  r6
161        vneg.s32        q4,  q4
162.endif
163        adr             r7,  L(\type\()_tbl)
164        sub             r4,  r4,  #24
165        \type           q8,  d16, d17, q9,  d18, d19
166        ldr             r4,  [r7, r4, lsl #2]
167        add             r7,  r7,  r4
168        bx              r7
169
170        .align 2
171L(\type\()_tbl):
172        .word 1280f - L(\type\()_tbl) + CONFIG_THUMB
173        .word 640f  - L(\type\()_tbl) + CONFIG_THUMB
174        .word 320f  - L(\type\()_tbl) + CONFIG_THUMB
175        .word 160f  - L(\type\()_tbl) + CONFIG_THUMB
176        .word 80f   - L(\type\()_tbl) + CONFIG_THUMB
177        .word 40f   - L(\type\()_tbl) + CONFIG_THUMB
178
17940:
180        add             r7,  r0,  r1
181        lsl             r1,  r1,  #1
1824:
183        subs            r5,  r5,  #4
184        vst1.16         {d16},  [r0, :64], r1
185        vst1.16         {d17},  [r7, :64], r1
186        vst1.16         {d18},  [r0, :64], r1
187        vst1.16         {d19},  [r7, :64], r1
188        ble             0f
189        \type           q8,  d16, d17, q9,  d18, d19
190        b               4b
19180:
192        add             r7,  r0,  r1
193        lsl             r1,  r1,  #1
1948:
195        vst1.16         {q8},  [r0, :128], r1
196        subs            r5,  r5,  #2
197        vst1.16         {q9},  [r7, :128], r1
198        ble             0f
199        \type           q8,  d16, d17, q9,  d18, d19
200        b               8b
201160:
20216:
203        \type           q10, d20, d21, q11, d22, d23
204        vst1.16         {q8,  q9},  [r0, :128], r1
205        subs            r5,  r5,  #2
206        vst1.16         {q10, q11}, [r0, :128], r1
207        ble             0f
208        \type           q8,  d16, d17, q9,  d18, d19
209        b               16b
210320:
211        add             r7,  r0,  #32
21232:
213        \type           q10, d20, d21, q11, d22, d23
214        vst1.16         {q8,  q9},  [r0, :128], r1
215        subs            r5,  r5,  #1
216        vst1.16         {q10, q11}, [r7, :128], r1
217        ble             0f
218        \type           q8,  d16, d17, q9,  d18, d19
219        b               32b
220640:
221        add             r7,  r0,  #32
222        mov             r12, #64
223        sub             r1,  r1,  #64
22464:
225        \type           q10, d20, d21, q11, d22, d23
226        vst1.16         {q8,  q9},  [r0, :128], r12
227        \type           q8,  d16, d17, q9,  d18, d19
228        vst1.16         {q10, q11}, [r7, :128], r12
229        \type           q10, d20, d21, q11, d22, d23
230        vst1.16         {q8,  q9},  [r0, :128], r1
231        subs            r5,  r5,  #1
232        vst1.16         {q10, q11}, [r7, :128], r1
233        ble             0f
234        \type           q8,  d16, d17, q9,  d18, d19
235        b               64b
2361280:
237        add             r7,  r0,  #32
238        mov             r12, #64
239        sub             r1,  r1,  #192
240128:
241        \type           q10, d20, d21, q11, d22, d23
242        vst1.16         {q8,  q9},  [r0, :128], r12
243        \type           q8,  d16, d17, q9,  d18, d19
244        vst1.16         {q10, q11}, [r7, :128], r12
245        \type           q10, d20, d21, q11, d22, d23
246        vst1.16         {q8,  q9},  [r0, :128], r12
247        \type           q8,  d16, d17, q9,  d18, d19
248        vst1.16         {q10, q11}, [r7, :128], r12
249        \type           q10, d20, d21, q11, d22, d23
250        vst1.16         {q8,  q9},  [r0, :128], r12
251        \type           q8,  d16, d17, q9,  d18, d19
252        vst1.16         {q10, q11}, [r7, :128], r12
253        \type           q10, d20, d21, q11, d22, d23
254        vst1.16         {q8,  q9},  [r0, :128], r1
255        subs            r5,  r5,  #1
256        vst1.16         {q10, q11}, [r7, :128], r1
257        ble             0f
258        \type           q8,  d16, d17, q9,  d18, d19
259        b               128b
2600:
261.ifc \type, mask
262        vpop            {q4-q7}
263.endif
264.ifc \type, w_avg
265        vpop            {q4}
266.endif
267        pop             {r4-r7,pc}
268endfunc
269.endm
270
271bidir_fn avg, r6
272bidir_fn w_avg, r7
273bidir_fn mask, r7
274
275
276.macro w_mask_fn type
277function w_mask_\type\()_16bpc_neon, export=1
278        push            {r4-r10,lr}
279        vpush           {q4-q7}
280        ldrd            r4,  r5,  [sp, #96]
281        ldrd            r6,  r7,  [sp, #104]
282        ldr             r8,  [sp, #112]
283        clz             r9,  r4
284        adr             lr,  L(w_mask_\type\()_tbl)
285        vdup.16         q15, r8       // bitdepth_max
286        sub             r9,  r9,  #24
287        clz             r8,  r8       // clz(bitdepth_max)
288        ldr             r9,  [lr,  r9,  lsl #2]
289        add             r9,  lr,  r9
290        sub             r8,  r8,  #12 // sh = intermediate_bits + 6 = clz(bitdepth_max) - 12
291        mov             r10, #PREP_BIAS*64
292        neg             r8,  r8       // -sh
293        movw            r12, #27615   // (64 + 1 - 38)<<mask_sh - 1 - mask_rnd
294        vdup.32         q14, r8       // -sh
295        vdup.16         q0,  r12
296.if \type == 444
297        vmov.i8         q1,  #64
298.elseif \type == 422
299        vdup.8          d4,  r7
300        vmov.i8         d2,  #129
301        vsub.i16        d2,  d2,  d4
302.elseif \type == 420
303        vdup.16         q2,  r7
304        vmov.i16        q1,  #0x100
305        vsub.i16        q1,  q1,  q2
306.endif
307        add             r12, r0,  r1
308        lsl             r1,  r1,  #1
309        bx              r9
310
311        .align 2
312L(w_mask_\type\()_tbl):
313        .word 1280f - L(w_mask_\type\()_tbl) + CONFIG_THUMB
314        .word 640f  - L(w_mask_\type\()_tbl) + CONFIG_THUMB
315        .word 320f  - L(w_mask_\type\()_tbl) + CONFIG_THUMB
316        .word 160f  - L(w_mask_\type\()_tbl) + CONFIG_THUMB
317        .word 8f    - L(w_mask_\type\()_tbl) + CONFIG_THUMB
318        .word 4f    - L(w_mask_\type\()_tbl) + CONFIG_THUMB
319
3204:
321        vld1.16         {q2, q3}, [r2, :128]! // tmp1 (four rows at once)
322        vld1.16         {q4, q5}, [r3, :128]! // tmp2 (four rows at once)
323        subs            r5,  r5,  #4
324        vdup.32         q13, r10       // PREP_BIAS*64
325        vabd.s16        q6,  q2,  q4   // abs(tmp1 - tmp2)
326        vabd.s16        q7,  q3,  q5
327        vsubl.s16       q8,  d8,  d4   // tmp2 - tmp1 (requires 17 bit)
328        vsubl.s16       q9,  d9,  d5
329        vsubl.s16       q10, d10, d6
330        vsubl.s16       q11, d11, d7
331        vqsub.u16       q6,  q0,  q6   // 27615 - abs()
332        vqsub.u16       q7,  q0,  q7
333        vshll.s16       q5,  d7,  #6   // tmp1 << 6
334        vshll.s16       q4,  d6,  #6
335        vshll.s16       q3,  d5,  #6
336        vshll.s16       q2,  d4,  #6
337        vshr.u16        q6,  q6,  #10  // 64-m = (27615 - abs()) >> mask_sh
338        vshr.u16        q7,  q7,  #10
339        vadd.i32        q2,  q2,  q13  // += PREP_BIAS*64
340        vadd.i32        q3,  q3,  q13
341        vadd.i32        q4,  q4,  q13
342        vadd.i32        q5,  q5,  q13
343        vmovl.u16       q12, d12
344        vmovl.u16       q13, d13
345        vmla.i32        q2,  q8,  q12  // (tmp2-tmp1)*(64-m)
346        vmovl.u16       q12, d14
347        vmla.i32        q3,  q9,  q13
348        vmovl.u16       q13, d15
349        vmla.i32        q4,  q10, q12
350        vmla.i32        q5,  q11, q13
351        vrshl.s32       q2,  q2,  q14  // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh
352        vrshl.s32       q3,  q3,  q14
353        vrshl.s32       q4,  q4,  q14
354        vrshl.s32       q5,  q5,  q14
355        vqmovun.s32     d4,  q2        // iclip_pixel
356        vqmovun.s32     d5,  q3
357        vqmovun.s32     d6,  q4
358        vqmovun.s32     d7,  q5
359        vmin.u16        q2,  q2,  q15  // iclip_pixel
360        vmin.u16        q3,  q3,  q15  // iclip_pixel
361.if \type == 444
362        vmovn.i16       d12, q6        // 64 - m
363        vmovn.i16       d13, q7
364        vsub.i16        q6,  q1,  q6   // m
365        vst1.8          {q6}, [r6, :128]!
366.elseif \type == 422
367        vpadd.i16       d12, d12, d13  // (64 - m) + (64 - n) (column wise addition)
368        vpadd.i16       d13, d14, d15
369        vmovn.i16       d12, q6
370        vhsub.u8        d12, d2,  d12  // ((129 - sign) - ((64 - m) + (64 - n)) >> 1
371        vst1.8          {d12}, [r6, :64]!
372.elseif \type == 420
373        vadd.i16        d12, d12, d13  // (64 - my1) + (64 - my2) (row wise addition)
374        vadd.i16        d13, d14, d15
375        vpadd.i16       d12, d12, d13  // (128 - m) + (128 - n) (column wise addition)
376        vsub.i16        d12, d2,  d12  // (256 - sign) - ((128 - m) + (128 - n))
377        vrshrn.i16      d12, q6,  #2   // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
378        vst1.32         {d12[0]}, [r6, :32]!
379.endif
380        vst1.16         {d4}, [r0,  :64], r1
381        vst1.16         {d5}, [r12, :64], r1
382        vst1.16         {d6}, [r0,  :64], r1
383        vst1.16         {d7}, [r12, :64], r1
384        bgt             4b
385        vpop            {q4-q7}
386        pop             {r4-r10,pc}
3878:
388        vld1.16         {q2, q3}, [r2, :128]! // tmp1
389        vld1.16         {q4, q5}, [r3, :128]! // tmp2
390        subs            r5,  r5,  #2
391        vdup.32         q13, r10       // PREP_BIAS*64
392        vabd.s16        q6,  q2,  q4   // abs(tmp1 - tmp2)
393        vabd.s16        q7,  q3,  q5
394        vsubl.s16       q8,  d8,  d4   // tmp2 - tmp1 (requires 17 bit)
395        vsubl.s16       q9,  d9,  d5
396        vsubl.s16       q10, d10, d6
397        vsubl.s16       q11, d11, d7
398        vqsub.u16       q6,  q0,  q6   // 27615 - abs()
399        vqsub.u16       q7,  q0,  q7
400        vshll.s16       q5,  d7,  #6   // tmp1 << 6
401        vshll.s16       q4,  d6,  #6
402        vshll.s16       q3,  d5,  #6
403        vshll.s16       q2,  d4,  #6
404        vshr.u16        q6,  q6,  #10  // 64-m = (27615 - abs()) >> mask_sh
405        vshr.u16        q7,  q7,  #10
406        vadd.i32        q2,  q2,  q13  // += PREP_BIAS*64
407        vadd.i32        q3,  q3,  q13
408        vadd.i32        q4,  q4,  q13
409        vadd.i32        q5,  q5,  q13
410        vmovl.u16       q12, d12
411        vmovl.u16       q13, d13
412        vmla.i32        q2,  q8,  q12  // (tmp2-tmp1)*(64-m)
413        vmovl.u16       q12, d14
414        vmla.i32        q3,  q9,  q13
415        vmovl.u16       q13, d15
416        vmla.i32        q4,  q10, q12
417        vmla.i32        q5,  q11, q13
418        vrshl.s32       q2,  q2,  q14  // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh
419        vrshl.s32       q3,  q3,  q14
420        vrshl.s32       q4,  q4,  q14
421        vrshl.s32       q5,  q5,  q14
422        vqmovun.s32     d4,  q2        // iclip_pixel
423        vqmovun.s32     d5,  q3
424        vqmovun.s32     d6,  q4
425        vqmovun.s32     d7,  q5
426        vmin.u16        q2,  q2,  q15  // iclip_pixel
427        vmin.u16        q3,  q3,  q15  // iclip_pixel
428.if \type == 444
429        vmovn.i16       d12, q6        // 64 - m
430        vmovn.i16       d13, q7
431        vsub.i16        q6,  q1,  q6   // m
432        vst1.8          {q6}, [r6, :128]!
433.elseif \type == 422
434        vpadd.i16       d12, d12, d13  // (64 - m) + (64 - n) (column wise addition)
435        vpadd.i16       d13, d14, d15
436        vmovn.i16       d12, q6
437        vhsub.u8        d12, d2,  d12  // ((129 - sign) - ((64 - m) + (64 - n)) >> 1
438        vst1.8          {d12}, [r6, :64]!
439.elseif \type == 420
440        vadd.i16        q6,  q6,  q7   // (64 - my1) + (64 - my2) (row wise addition)
441        vpadd.i16       d12, d12, d13  // (128 - m) + (128 - n) (column wise addition)
442        vsub.i16        d12, d2,  d12  // (256 - sign) - ((128 - m) + (128 - n))
443        vrshrn.i16      d12, q6,  #2   // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
444        vst1.32         {d12[0]}, [r6, :32]!
445.endif
446        vst1.16         {q2}, [r0,  :128], r1
447        vst1.16         {q3}, [r12, :128], r1
448        bgt             8b
449        vpop            {q4-q7}
450        pop             {r4-r10,pc}
4511280:
452640:
453320:
454160:
455        sub             r1,  r1,  r4,  lsl #1
456.if \type == 444
457        add             lr,  r6,  r4
458.elseif \type == 422
459        add             lr,  r6,  r4,  lsr #1
460.endif
461        add             r7,  r2,  r4,  lsl #1
462        add             r9,  r3,  r4,  lsl #1
463161:
464        mov             r8,  r4
46516:
466        vld1.16         {q2}, [r2, :128]! // tmp1
467        vld1.16         {q4}, [r3, :128]! // tmp2
468        vld1.16         {q3}, [r7, :128]!
469        vld1.16         {q5}, [r9, :128]!
470        subs            r8,  r8,  #8
471        vdup.32         q13, r10       // PREP_BIAS*64
472        vabd.s16        q6,  q2,  q4   // abs(tmp1 - tmp2)
473        vabd.s16        q7,  q3,  q5
474        vsubl.s16       q8,  d8,  d4   // tmp2 - tmp1 (requires 17 bit)
475        vsubl.s16       q9,  d9,  d5
476        vsubl.s16       q10, d10, d6
477        vsubl.s16       q11, d11, d7
478        vqsub.u16       q6,  q0,  q6   // 27615 - abs()
479        vqsub.u16       q7,  q0,  q7
480        vshll.s16       q5,  d7,  #6   // tmp1 << 6
481        vshll.s16       q4,  d6,  #6
482        vshll.s16       q3,  d5,  #6
483        vshll.s16       q2,  d4,  #6
484        vshr.u16        q6,  q6,  #10  // 64-m = (27615 - abs()) >> mask_sh
485        vshr.u16        q7,  q7,  #10
486        vadd.i32        q2,  q2,  q13  // += PREP_BIAS*64
487        vadd.i32        q3,  q3,  q13
488        vadd.i32        q4,  q4,  q13
489        vadd.i32        q5,  q5,  q13
490        vmovl.u16       q12, d12
491        vmovl.u16       q13, d13
492        vmla.i32        q2,  q8,  q12  // (tmp2-tmp1)*(64-m)
493        vmovl.u16       q12, d14
494        vmla.i32        q3,  q9,  q13
495        vmovl.u16       q13, d15
496        vmla.i32        q4,  q10, q12
497        vmla.i32        q5,  q11, q13
498        vrshl.s32       q2,  q2,  q14  // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh
499        vrshl.s32       q3,  q3,  q14
500        vrshl.s32       q4,  q4,  q14
501        vrshl.s32       q5,  q5,  q14
502        vqmovun.s32     d4,  q2        // iclip_pixel
503        vqmovun.s32     d5,  q3
504        vqmovun.s32     d6,  q4
505        vqmovun.s32     d7,  q5
506        vmin.u16        q2,  q2,  q15  // iclip_pixel
507        vmin.u16        q3,  q3,  q15  // iclip_pixel
508.if \type == 444
509        vmovn.i16       d12, q6        // 64 - m
510        vmovn.i16       d13, q7
511        vsub.i16        q6,  q1,  q6   // m
512        vst1.8          {d12}, [r6, :64]!
513        vst1.8          {d13}, [lr, :64]!
514.elseif \type == 422
515        vpadd.i16       d12, d12, d13  // (64 - m) + (64 - n) (column wise addition)
516        vpadd.i16       d13, d14, d15
517        vmovn.i16       d12, q6
518        vhsub.u8        d12, d2,  d12  // ((129 - sign) - ((64 - m) + (64 - n)) >> 1
519        vst1.32         {d12[0]}, [r6, :32]!
520        vst1.32         {d12[1]}, [lr, :32]!
521.elseif \type == 420
522        vadd.i16        q6,  q6,  q7   // (64 - my1) + (64 - my2) (row wise addition)
523        vpadd.i16       d12, d12, d13  // (128 - m) + (128 - n) (column wise addition)
524        vsub.i16        d12, d2,  d12  // (256 - sign) - ((128 - m) + (128 - n))
525        vrshrn.i16      d12, q6,  #2   // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
526        vst1.32         {d12[0]}, [r6, :32]!
527.endif
528        vst1.16         {q2}, [r0,  :128]!
529        vst1.16         {q3}, [r12, :128]!
530        bgt             16b
531        subs            r5,  r5,  #2
532        add             r2,  r2,  r4,  lsl #1
533        add             r3,  r3,  r4,  lsl #1
534        add             r7,  r7,  r4,  lsl #1
535        add             r9,  r9,  r4,  lsl #1
536.if \type == 444
537        add             r6,  r6,  r4
538        add             lr,  lr,  r4
539.elseif \type == 422
540        add             r6,  r6,  r4,  lsr #1
541        add             lr,  lr,  r4,  lsr #1
542.endif
543        add             r0,  r0,  r1
544        add             r12, r12, r1
545        bgt             161b
546        vpop            {q4-q7}
547        pop             {r4-r10,pc}
548endfunc
549.endm
550
551w_mask_fn 444
552w_mask_fn 422
553w_mask_fn 420
554
555function blend_16bpc_neon, export=1
556        push            {r4-r5,lr}
557        ldrd            r4,  r5,  [sp, #12]
558        clz             lr,  r3
559        adr             r3,  L(blend_tbl)
560        sub             lr,  lr,  #26
561        ldr             lr,  [r3,  lr,  lsl #2]
562        add             r3,  r3,  lr
563        bx              r3
564
565        .align 2
566L(blend_tbl):
567        .word 320f - L(blend_tbl) + CONFIG_THUMB
568        .word 160f - L(blend_tbl) + CONFIG_THUMB
569        .word 80f  - L(blend_tbl) + CONFIG_THUMB
570        .word 40f  - L(blend_tbl) + CONFIG_THUMB
571
57240:
573        add             r12, r0,  r1
574        lsl             r1,  r1,  #1
5754:
576        vld1.8          {d4}, [r5, :64]!
577        vld1.16         {q1}, [r2, :128]!
578        vld1.16         {d0}, [r0, :64]
579        vneg.s8         d4,  d4       // -m
580        subs            r4,  r4,  #2
581        vld1.16         {d1}, [r12, :64]
582        vmovl.s8        q2,  d4
583        vshl.i16        q2,  q2,  #9  // -m << 9
584        vsub.i16        q1,  q0,  q1  // a - b
585        vqrdmulh.s16    q1,  q1,  q2  // ((a-b)*-m + 32) >> 6
586        vadd.i16        q0,  q0,  q1
587        vst1.16         {d0}, [r0,  :64], r1
588        vst1.16         {d1}, [r12, :64], r1
589        bgt             4b
590        pop             {r4-r5,pc}
59180:
592        add             r12, r0,  r1
593        lsl             r1,  r1,  #1
5948:
595        vld1.8          {q8},     [r5, :128]!
596        vld1.16         {q2, q3}, [r2, :128]!
597        vneg.s8         q9,  q8       // -m
598        vld1.16         {q0},     [r0,  :128]
599        vld1.16         {q1},     [r12, :128]
600        vmovl.s8        q8,  d18
601        vmovl.s8        q9,  d19
602        vshl.i16        q8,  q8,  #9  // -m << 9
603        vshl.i16        q9,  q9,  #9
604        vsub.i16        q2,  q0,  q2  // a - b
605        vsub.i16        q3,  q1,  q3
606        subs            r4,  r4,  #2
607        vqrdmulh.s16    q2,  q2,  q8  // ((a-b)*-m + 32) >> 6
608        vqrdmulh.s16    q3,  q3,  q9
609        vadd.i16        q0,  q0,  q2
610        vadd.i16        q1,  q1,  q3
611        vst1.16         {q0}, [r0,  :128], r1
612        vst1.16         {q1}, [r12, :128], r1
613        bgt             8b
614        pop             {r4-r5,pc}
615160:
616        add             r12, r0,  r1
617        lsl             r1,  r1,  #1
61816:
619        vld1.8          {q12, q13}, [r5, :128]!
620        vld1.16         {q8,  q9},  [r2, :128]!
621        subs            r4,  r4,  #2
622        vneg.s8         q14, q12      // -m
623        vld1.16         {q0,  q1},  [r0, :128]
624        vneg.s8         q15, q13
625        vld1.16         {q10, q11}, [r2, :128]!
626        vmovl.s8        q12, d28
627        vmovl.s8        q13, d29
628        vmovl.s8        q14, d30
629        vmovl.s8        q15, d31
630        vld1.16         {q2,  q3},  [r12, :128]
631        vshl.i16        q12, q12, #9  // -m << 9
632        vshl.i16        q13, q13, #9
633        vshl.i16        q14, q14, #9
634        vshl.i16        q15, q15, #9
635        vsub.i16        q8,  q0,  q8  // a - b
636        vsub.i16        q9,  q1,  q9
637        vsub.i16        q10, q2,  q10
638        vsub.i16        q11, q3,  q11
639        vqrdmulh.s16    q8,  q8,  q12 // ((a-b)*-m + 32) >> 6
640        vqrdmulh.s16    q9,  q9,  q13
641        vqrdmulh.s16    q10, q10, q14
642        vqrdmulh.s16    q11, q11, q15
643        vadd.i16        q0,  q0,  q8
644        vadd.i16        q1,  q1,  q9
645        vadd.i16        q2,  q2,  q10
646        vst1.16         {q0, q1}, [r0,  :128], r1
647        vadd.i16        q3,  q3,  q11
648        vst1.16         {q2, q3}, [r12, :128], r1
649        bgt             16b
650        pop             {r4-r5,pc}
651320:
652        add             r12, r0,  #32
65332:
654        vld1.8          {q12, q13}, [r5, :128]!
655        vld1.16         {q8,  q9},  [r2, :128]!
656        subs            r4,  r4,  #1
657        vneg.s8         q14, q12      // -m
658        vld1.16         {q0,  q1},  [r0, :128]
659        vneg.s8         q15, q13
660        vld1.16         {q10, q11}, [r2, :128]!
661        vmovl.s8        q12, d28
662        vmovl.s8        q13, d29
663        vmovl.s8        q14, d30
664        vmovl.s8        q15, d31
665        vld1.16         {q2,  q3},  [r12, :128]
666        vshl.i16        q12, q12, #9  // -m << 9
667        vshl.i16        q13, q13, #9
668        vshl.i16        q14, q14, #9
669        vshl.i16        q15, q15, #9
670        vsub.i16        q8,  q0,  q8  // a - b
671        vsub.i16        q9,  q1,  q9
672        vsub.i16        q10, q2,  q10
673        vsub.i16        q11, q3,  q11
674        vqrdmulh.s16    q8,  q8,  q12 // ((a-b)*-m + 32) >> 6
675        vqrdmulh.s16    q9,  q9,  q13
676        vqrdmulh.s16    q10, q10, q14
677        vqrdmulh.s16    q11, q11, q15
678        vadd.i16        q0,  q0,  q8
679        vadd.i16        q1,  q1,  q9
680        vadd.i16        q2,  q2,  q10
681        vst1.16         {q0, q1}, [r0,  :128], r1
682        vadd.i16        q3,  q3,  q11
683        vst1.16         {q2, q3}, [r12, :128], r1
684        bgt             32b
685        pop             {r4-r5,pc}
686endfunc
687
688function blend_h_16bpc_neon, export=1
689        push            {r4-r5,lr}
690        ldr             r4,  [sp, #12]
691        movrel          r5,  X(obmc_masks)
692        add             r5,  r5,  r4
693        sub             r4,  r4,  r4,  lsr #2
694        clz             lr,  r3
695        adr             r12, L(blend_h_tbl)
696        sub             lr,  lr,  #24
697        ldr             lr,  [r12, lr,  lsl #2]
698        add             r12, r12, lr
699        bx              r12
700
701        .align 2
702L(blend_h_tbl):
703        .word 1280f - L(blend_h_tbl) + CONFIG_THUMB
704        .word 640f  - L(blend_h_tbl) + CONFIG_THUMB
705        .word 320f  - L(blend_h_tbl) + CONFIG_THUMB
706        .word 160f  - L(blend_h_tbl) + CONFIG_THUMB
707        .word 80f   - L(blend_h_tbl) + CONFIG_THUMB
708        .word 40f   - L(blend_h_tbl) + CONFIG_THUMB
709        .word 20f   - L(blend_h_tbl) + CONFIG_THUMB
710
71120:
712        add             r12, r0,  r1
713        lsl             r1,  r1,  #1
7142:
715        vld2.8          {d4[], d5[]}, [r5, :16]!
716        vld1.16         {d2},         [r2, :64]!
717        vext.8          d4,  d4,  d5,  #6
718        subs            r4,  r4,  #2
719        vneg.s8         d4,  d4       // -m
720        vld1.32         {d0[]},  [r0, :32]
721        vld1.32         {d0[1]}, [r12, :32]
722        vmovl.s8        q2,  d4
723        vshl.i16        d4,  d4,  #9  // -m << 9
724        vsub.i16        d2,  d0,  d2  // a - b
725        vqrdmulh.s16    d2,  d2,  d4  // ((a-b)*-m + 32) >> 6
726        vadd.i16        d0,  d0,  d2
727        vst1.32         {d0[0]}, [r0,  :32], r1
728        vst1.32         {d0[1]}, [r12, :32], r1
729        bgt             2b
730        pop             {r4-r5,pc}
73140:
732        add             r12, r0,  r1
733        lsl             r1,  r1,  #1
7344:
735        vld2.8          {d4[], d5[]}, [r5, :16]!
736        vld1.16         {q1},         [r2, :128]!
737        vext.8          d4,  d4,  d5,  #4
738        subs            r4,  r4,  #2
739        vneg.s8         d4,  d4       // -m
740        vld1.16         {d0}, [r0,  :64]
741        vld1.16         {d1}, [r12, :64]
742        vmovl.s8        q2,  d4
743        vshl.i16        q2,  q2,  #9  // -m << 9
744        vsub.i16        q1,  q0,  q1  // a - b
745        vqrdmulh.s16    q1,  q1,  q2  // ((a-b)*-m + 32) >> 6
746        vadd.i16        q0,  q0,  q1
747        vst1.16         {d0}, [r0,  :64], r1
748        vst1.16         {d1}, [r12, :64], r1
749        bgt             4b
750        pop             {r4-r5,pc}
75180:
752        add             r12, r0,  r1
753        lsl             r1,  r1,  #1
7548:
755        vld2.8          {d16[], d17[]}, [r5, :16]!
756        vld1.16         {q2, q3},       [r2, :128]!
757        vneg.s8         q9,  q8      // -m
758        vld1.16         {q0}, [r0, :128]
759        subs            r4,  r4,  #2
760        vmovl.s8        q8,  d18
761        vmovl.s8        q9,  d19
762        vld1.16         {q1}, [r12, :128]
763        vshl.i16        q8,  q8,  #9  // -m << 9
764        vshl.i16        q9,  q9,  #9
765        vsub.i16        q2,  q0,  q2  // a - b
766        vsub.i16        q3,  q1,  q3
767        vqrdmulh.s16    q2,  q2,  q8  // ((a-b)*-m + 32) >> 6
768        vqrdmulh.s16    q3,  q3,  q9
769        vadd.i16        q0,  q0,  q2
770        vadd.i16        q1,  q1,  q3
771        vst1.16         {q0}, [r0,  :128], r1
772        vst1.16         {q1}, [r12, :128], r1
773        bgt             8b
774        pop             {r4-r5,pc}
775160:
776        add             r12, r0,  r1
777        lsl             r1,  r1,  #1
77816:
779        vld2.8          {d24[], d25[]}, [r5, :16]!
780        vld1.16         {q8,  q9},  [r2, :128]!
781        subs            r4,  r4,  #2
782        vneg.s8         q13, q12      // -m
783        vld1.16         {q0,  q1},  [r0, :128]
784        vmovl.s8        q12, d26
785        vld1.16         {q10, q11}, [r2, :128]!
786        vmovl.s8        q13, d27
787        vld1.16         {q2,  q3},  [r12, :128]
788        vshl.i16        q12, q12, #9  // -m << 9
789        vshl.i16        q13, q13, #9
790        vsub.i16        q8,  q0,  q8  // a - b
791        vsub.i16        q9,  q1,  q9
792        vsub.i16        q10, q2,  q10
793        vsub.i16        q11, q3,  q11
794        vqrdmulh.s16    q8,  q8,  q12 // ((a-b)*-m + 32) >> 6
795        vqrdmulh.s16    q9,  q9,  q12
796        vqrdmulh.s16    q10, q10, q13
797        vqrdmulh.s16    q11, q11, q13
798        vadd.i16        q0,  q0,  q8
799        vadd.i16        q1,  q1,  q9
800        vadd.i16        q2,  q2,  q10
801        vadd.i16        q3,  q3,  q11
802        vst1.16         {q0, q1}, [r0,  :128], r1
803        vst1.16         {q2, q3}, [r12, :128], r1
804        bgt             16b
805        pop             {r4-r5,pc}
8061280:
807640:
808320:
809        sub             r1,  r1,  r3,  lsl #1
810321:
811        vld1.8          {d24[]}, [r5]!
812        mov             r12, r3
813        vneg.s8         d24, d24      // -m
814        vmovl.s8        q12, d24
815        vshl.i16        q12, q12, #9  // -m << 9
81632:
817        vld1.16         {q8,  q9},  [r2, :128]!
818        vld1.16         {q0,  q1},  [r0, :128]!
819        subs            r12, r12, #32
820        vld1.16         {q10, q11}, [r2, :128]!
821        vld1.16         {q2,  q3},  [r0, :128]
822        vsub.i16        q8,  q0,  q8  // a - b
823        vsub.i16        q9,  q1,  q9
824        vsub.i16        q10, q2,  q10
825        vsub.i16        q11, q3,  q11
826        sub             r0,  r0,  #32
827        vqrdmulh.s16    q8,  q8,  q12 // ((a-b)*-m + 32) >> 6
828        vqrdmulh.s16    q9,  q9,  q12
829        vqrdmulh.s16    q10, q10, q12
830        vqrdmulh.s16    q11, q11, q12
831        vadd.i16        q0,  q0,  q8
832        vadd.i16        q1,  q1,  q9
833        vadd.i16        q2,  q2,  q10
834        vst1.16         {q0, q1}, [r0, :128]!
835        vadd.i16        q3,  q3,  q11
836        vst1.16         {q2, q3}, [r0, :128]!
837        bgt             32b
838        subs            r4,  r4,  #1
839        add             r0,  r0,  r1
840        bgt             321b
841        pop             {r4-r5,pc}
842endfunc
843
844function blend_v_16bpc_neon, export=1
845        push            {r4,lr}
846        ldr             r4,  [sp, #8]
847        movrel          lr,  X(obmc_masks)
848        add             lr,  lr,  r3
849        clz             r12, r3
850        adr             r3,  L(blend_v_tbl)
851        sub             r12, r12, #26
852        ldr             r12, [r3,  r12, lsl #2]
853        add             r3,  r3,  r12
854        bx              r3
855
856        .align 2
857L(blend_v_tbl):
858        .word 320f - L(blend_v_tbl) + CONFIG_THUMB
859        .word 160f - L(blend_v_tbl) + CONFIG_THUMB
860        .word 80f  - L(blend_v_tbl) + CONFIG_THUMB
861        .word 40f  - L(blend_v_tbl) + CONFIG_THUMB
862        .word 20f  - L(blend_v_tbl) + CONFIG_THUMB
863
86420:
865        add             r12, r0,  r1
866        lsl             r1,  r1,  #1
867        vld1.8          {d4[]}, [lr]
868        vneg.s8         d4,  d4       // -m
869        vmovl.s8        q2,  d4
870        vshl.i16        d4,  d4,  #9  // -m << 9
8712:
872        vld1.32         {d2[]},  [r2, :32]!
873        vld1.16         {d0[]},  [r0, :16]
874        subs            r4,  r4,  #2
875        vld1.16         {d2[1]}, [r2,  :16]
876        vld1.16         {d0[1]}, [r12, :16]
877        add             r2,  r2,  #4
878        vsub.i16        d2,  d0,  d2  // a - b
879        vqrdmulh.s16    d2,  d2,  d4  // ((a-b)*-m + 32) >> 6
880        vadd.i16        d0,  d0,  d2
881        vst1.16         {d0[0]}, [r0,  :16], r1
882        vst1.16         {d0[1]}, [r12, :16], r1
883        bgt             2b
884        pop             {r4,pc}
88540:
886        vld1.32         {d4[]}, [lr, :32]
887        add             r12, r0,  r1
888        vneg.s8         d4,  d4       // -m
889        lsl             r1,  r1,  #1
890        vmovl.s8        q2,  d4
891        sub             r1,  r1,  #4
892        vshl.i16        q2,  q2,  #9  // -m << 9
8934:
894        vld1.16         {q1}, [r2, :128]!
895        vld1.16         {d0}, [r0,  :64]
896        vld1.16         {d1}, [r12, :64]
897        subs            r4,  r4,  #2
898        vsub.i16        q1,  q0,  q1  // a - b
899        vqrdmulh.s16    q1,  q1,  q2  // ((a-b)*-m + 32) >> 6
900        vadd.i16        q0,  q0,  q1
901        vst1.32         {d0[0]}, [r0,  :32]!
902        vst1.32         {d1[0]}, [r12, :32]!
903        vst1.16         {d0[2]}, [r0,  :16], r1
904        vst1.16         {d1[2]}, [r12, :16], r1
905        bgt             4b
906        pop             {r4,pc}
90780:
908        vld1.8          {d16}, [lr, :64]
909        add             r12, r0,  r1
910        vneg.s8         d16, d16      // -m
911        lsl             r1,  r1,  #1
912        vmovl.s8        q8,  d16
913        sub             r1,  r1,  #8
914        vshl.i16        q8,  q8,  #9  // -m << 9
9158:
916        vld1.16         {q2, q3}, [r2,  :128]!
917        vld1.16         {q0},     [r0,  :128]
918        vld1.16         {q1},     [r12, :128]
919        subs            r4,  r4,  #2
920        vsub.i16        q2,  q0,  q2  // a - b
921        vsub.i16        q3,  q1,  q3
922        vqrdmulh.s16    q2,  q2,  q8  // ((a-b)*-m + 32) >> 6
923        vqrdmulh.s16    q3,  q3,  q8
924        vadd.i16        q0,  q0,  q2
925        vadd.i16        q1,  q1,  q3
926        vst1.16         {d0},    [r0,  :64]!
927        vst1.16         {d2},    [r12, :64]!
928        vst1.32         {d1[0]}, [r0,  :32], r1
929        vst1.32         {d3[0]}, [r12, :32], r1
930        bgt             8b
931        pop             {r4,pc}
932160:
933        vld1.8          {q12}, [lr, :128]
934        add             r12, r0,  r1
935        vneg.s8         q13, q12      // -m
936        lsl             r1,  r1,  #1
937        vmovl.s8        q12, d26
938        vmovl.s8        q13, d27
939        vshl.i16        q12, q12, #9  // -m << 9
940        vshl.i16        d26, d26, #9
94116:
942        vld1.16         {q8,  q9},      [r2,  :128]!
943        vld1.16         {d0,  d1,  d2}, [r0,  :64]
944        subs            r4,  r4,  #2
945        vld1.16         {q10, q11},     [r2,  :128]!
946        vsub.i16        q8,  q0,  q8  // a - b
947        vld1.16         {d4,  d5,  d6}, [r12, :64]
948        vsub.i16        d18, d2,  d18
949        vsub.i16        q10, q2,  q10
950        vsub.i16        d22, d6,  d22
951        vqrdmulh.s16    q8,  q8,  q12  // ((a-b)*-m + 32) >> 6
952        vqrdmulh.s16    d18, d18, d26
953        vqrdmulh.s16    q10, q10, q12
954        vqrdmulh.s16    d22, d22, d26
955        vadd.i16        q0,  q0,  q8
956        vadd.i16        d2,  d2,  d18
957        vadd.i16        q2,  q2,  q10
958        vst1.16         {d0,  d1,  d2}, [r0,  :64], r1
959        vadd.i16        d6,  d6,  d22
960        vst1.16         {d4,  d5,  d6}, [r12, :64], r1
961        bgt             16b
962        pop             {r4,pc}
963320:
964        vld1.8          {d24, d25, d26}, [lr, :64]
965        vneg.s8         q14, q12      // -m
966        vneg.s8         d30, d26
967        vmovl.s8        q12, d28
968        vmovl.s8        q13, d29
969        vmovl.s8        q14, d30
970        sub             r1,  r1,  #32
971        vshl.i16        q12, q12, #9  // -m << 9
972        vshl.i16        q13, q13, #9
973        vshl.i16        q14, q14, #9
97432:
975        vld1.16         {q8,  q9},  [r2, :128]!
976        vld1.16         {q0,  q1},  [r0, :128]!
977        subs            r4,  r4,  #1
978        vld1.16         {q10},      [r2, :128]
979        vsub.i16        q8,  q0,  q8  // a - b
980        vld1.16         {q2},       [r0, :128]
981        sub             r0,  r0,  #32
982        vsub.i16        q9,  q1,  q9
983        vsub.i16        q10, q2,  q10
984        vqrdmulh.s16    q8,  q8,  q12  // ((a-b)*-m + 32) >> 6
985        vqrdmulh.s16    q9,  q9,  q13
986        vqrdmulh.s16    q10, q10, q14
987        vadd.i16        q0,  q0,  q8
988        vadd.i16        q1,  q1,  q9
989        vadd.i16        q2,  q2,  q10
990        vst1.16         {q0, q1}, [r0, :128]!
991        add             r2,  r2,  #32
992        vst1.16         {q2},     [r0, :128], r1
993        bgt             32b
994        pop             {r4,pc}
995endfunc
996
997// This has got the same signature as the put_8tap functions,
998// and assumes that r9 is set to (clz(w)-24).
999function put_neon
1000        adr             r10, L(put_tbl)
1001        ldr             r9,  [r10, r9, lsl #2]
1002        add             r10, r10, r9
1003        bx              r10
1004
1005        .align 2
1006L(put_tbl):
1007        .word 1280f - L(put_tbl) + CONFIG_THUMB
1008        .word 640f  - L(put_tbl) + CONFIG_THUMB
1009        .word 320f  - L(put_tbl) + CONFIG_THUMB
1010        .word 16f   - L(put_tbl) + CONFIG_THUMB
1011        .word 80f   - L(put_tbl) + CONFIG_THUMB
1012        .word 4f    - L(put_tbl) + CONFIG_THUMB
1013        .word 2f    - L(put_tbl) + CONFIG_THUMB
1014
10152:
1016        vld1.32         {d0[]}, [r2], r3
1017        vld1.32         {d1[]}, [r2], r3
1018        subs            r5,  r5,  #2
1019        vst1.32         {d0[0]}, [r0, :32], r1
1020        vst1.32         {d1[1]}, [r0, :32], r1
1021        bgt             2b
1022        pop             {r4-r11,pc}
10234:
1024        vld1.16         {d0}, [r2], r3
1025        vld1.16         {d1}, [r2], r3
1026        subs            r5,  r5,  #2
1027        vst1.16         {d0}, [r0, :64], r1
1028        vst1.16         {d1}, [r0, :64], r1
1029        bgt             4b
1030        pop             {r4-r11,pc}
103180:
1032        add             r8,  r0,  r1
1033        lsl             r1,  r1,  #1
1034        add             r9,  r2,  r3
1035        lsl             r3,  r3,  #1
10368:
1037        vld1.16         {q0}, [r2], r3
1038        vld1.16         {q1}, [r9], r3
1039        subs            r5,  r5,  #2
1040        vst1.16         {q0}, [r0, :128], r1
1041        vst1.16         {q1}, [r8, :128], r1
1042        bgt             8b
1043        pop             {r4-r11,pc}
104416:
1045        vld1.16         {q0,  q1},  [r2], r3
1046        subs            r5,  r5,  #1
1047        vst1.16         {q0,  q1},  [r0, :128], r1
1048        bgt             16b
1049        pop             {r4-r11,pc}
1050320:
1051        sub             r1,  r1,  #32
1052        sub             r3,  r3,  #32
105332:
1054        vld1.16         {q0,  q1},  [r2]!
1055        vst1.16         {q0,  q1},  [r0, :128]!
1056        vld1.16         {q2,  q3},  [r2], r3
1057        subs            r5,  r5,  #1
1058        vst1.16         {q2,  q3},  [r0, :128], r1
1059        bgt             32b
1060        pop             {r4-r11,pc}
1061640:
1062        sub             r1,  r1,  #96
1063        sub             r3,  r3,  #96
106464:
1065        vld1.16         {q8,  q9},  [r2]!
1066        vst1.16         {q8,  q9},  [r0, :128]!
1067        vld1.16         {q10, q11}, [r2]!
1068        vst1.16         {q10, q11}, [r0, :128]!
1069        vld1.16         {q12, q13}, [r2]!
1070        vst1.16         {q12, q13}, [r0, :128]!
1071        vld1.16         {q14, q15}, [r2], r3
1072        subs            r5,  r5,  #1
1073        vst1.16         {q14, q15}, [r0, :128], r1
1074        bgt             64b
1075        pop             {r4-r11,pc}
10761280:
1077        sub             r1,  r1,  #224
1078        sub             r3,  r3,  #224
1079128:
1080        vld1.16         {q8,  q9},  [r2]!
1081        vst1.16         {q8,  q9},  [r0, :128]!
1082        vld1.16         {q10, q11}, [r2]!
1083        vst1.16         {q10, q11}, [r0, :128]!
1084        vld1.16         {q12, q13}, [r2]!
1085        vst1.16         {q12, q13}, [r0, :128]!
1086        vld1.16         {q14, q15}, [r2]!
1087        vst1.16         {q14, q15}, [r0, :128]!
1088        vld1.16         {q8,  q9},  [r2]!
1089        vst1.16         {q8,  q9},  [r0, :128]!
1090        vld1.16         {q10, q11}, [r2]!
1091        vst1.16         {q10, q11}, [r0, :128]!
1092        vld1.16         {q12, q13}, [r2]!
1093        vst1.16         {q12, q13}, [r0, :128]!
1094        vld1.16         {q14, q15}, [r2], r3
1095        subs            r5,  r5,  #1
1096        vst1.16         {q14, q15}, [r0, :128], r1
1097        bgt             128b
1098        pop             {r4-r11,pc}
1099endfunc
1100
1101// This has got the same signature as the prep_8tap functions,
1102// and assumes that r9 is set to (clz(w)-24), r7 to intermediate_bits and
1103// r8 to w*2.
1104function prep_neon
1105        adr             r10, L(prep_tbl)
1106        ldr             r9,  [r10, r9, lsl #2]
1107        vdup.16         q15, r7   // intermediate_bits
1108        vmov.i16        q14, #PREP_BIAS
1109        add             r10, r10, r9
1110        bx              r10
1111
1112        .align 2
1113L(prep_tbl):
1114        .word 1280f - L(prep_tbl) + CONFIG_THUMB
1115        .word 640f  - L(prep_tbl) + CONFIG_THUMB
1116        .word 320f  - L(prep_tbl) + CONFIG_THUMB
1117        .word 16f   - L(prep_tbl) + CONFIG_THUMB
1118        .word 80f   - L(prep_tbl) + CONFIG_THUMB
1119        .word 40f   - L(prep_tbl) + CONFIG_THUMB
1120
112140:
1122        add             r9,  r1,  r2
1123        lsl             r2,  r2,  #1
11244:
1125        vld1.16         {d0}, [r1], r2
1126        vld1.16         {d1}, [r9], r2
1127        subs            r4,  r4,  #2
1128        vshl.s16        q0,  q0,  q15
1129        vsub.i16        q0,  q0,  q14
1130        vst1.16         {q0}, [r0, :128]!
1131        bgt             4b
1132        pop             {r4-r11,pc}
113380:
1134        add             r9,  r1,  r2
1135        lsl             r2,  r2,  #1
11368:
1137        vld1.16         {q0}, [r1], r2
1138        vld1.16         {q1}, [r9], r2
1139        subs            r4,  r4,  #2
1140        vshl.s16        q0,  q0,  q15
1141        vshl.s16        q1,  q1,  q15
1142        vsub.i16        q0,  q0,  q14
1143        vsub.i16        q1,  q1,  q14
1144        vst1.16         {q0, q1}, [r0, :128]!
1145        bgt             8b
1146        pop             {r4-r11,pc}
114716:
1148        vld1.16         {q0, q1}, [r1], r2
1149        vshl.s16        q0,  q0,  q15
1150        vld1.16         {q2, q3}, [r1], r2
1151        subs            r4,  r4,  #2
1152        vshl.s16        q1,  q1,  q15
1153        vshl.s16        q2,  q2,  q15
1154        vshl.s16        q3,  q3,  q15
1155        vsub.i16        q0,  q0,  q14
1156        vsub.i16        q1,  q1,  q14
1157        vsub.i16        q2,  q2,  q14
1158        vst1.16         {q0, q1}, [r0, :128]!
1159        vsub.i16        q3,  q3,  q14
1160        vst1.16         {q2, q3}, [r0, :128]!
1161        bgt             16b
1162        pop             {r4-r11,pc}
1163320:
1164        sub             r2,  r2,  #32
116532:
1166        vld1.16         {q0, q1}, [r1]!
1167        subs            r4,  r4,  #1
1168        vshl.s16        q0,  q0,  q15
1169        vld1.16         {q2, q3}, [r1], r2
1170        vshl.s16        q1,  q1,  q15
1171        vshl.s16        q2,  q2,  q15
1172        vshl.s16        q3,  q3,  q15
1173        vsub.i16        q0,  q0,  q14
1174        vsub.i16        q1,  q1,  q14
1175        vsub.i16        q2,  q2,  q14
1176        vst1.16         {q0, q1}, [r0, :128]!
1177        vsub.i16        q3,  q3,  q14
1178        vst1.16         {q2, q3}, [r0, :128]!
1179        bgt             32b
1180        pop             {r4-r11,pc}
1181640:
1182        sub             r2,  r2,  #96
118364:
1184        vld1.16         {q0,  q1},  [r1]!
1185        subs            r4,  r4,  #1
1186        vshl.s16        q0,  q0,  q15
1187        vld1.16         {q2,  q3},  [r1]!
1188        vshl.s16        q1,  q1,  q15
1189        vld1.16         {q8,  q9},  [r1]!
1190        vshl.s16        q2,  q2,  q15
1191        vld1.16         {q10, q11}, [r1], r2
1192        vshl.s16        q3,  q3,  q15
1193        vshl.s16        q8,  q8,  q15
1194        vshl.s16        q9,  q9,  q15
1195        vshl.s16        q10, q10, q15
1196        vshl.s16        q11, q11, q15
1197        vsub.i16        q0,  q0,  q14
1198        vsub.i16        q1,  q1,  q14
1199        vsub.i16        q2,  q2,  q14
1200        vsub.i16        q3,  q3,  q14
1201        vsub.i16        q8,  q8,  q14
1202        vst1.16         {q0,  q1},  [r0, :128]!
1203        vsub.i16        q9,  q9,  q14
1204        vst1.16         {q2,  q3},  [r0, :128]!
1205        vsub.i16        q10, q10, q14
1206        vst1.16         {q8,  q9},  [r0, :128]!
1207        vsub.i16        q11, q11, q14
1208        vst1.16         {q10, q11}, [r0, :128]!
1209        bgt             64b
1210        pop             {r4-r11,pc}
12111280:
1212        sub             r2,  r2,  #224
1213128:
1214        vld1.16         {q0,  q1},  [r1]!
1215        subs            r4,  r4,  #1
1216        vshl.s16        q0,  q0,  q15
1217        vld1.16         {q2,  q3},  [r1]!
1218        vshl.s16        q1,  q1,  q15
1219        vld1.16         {q8,  q9},  [r1]!
1220        vshl.s16        q2,  q2,  q15
1221        vld1.16         {q10, q11}, [r1]!
1222        vshl.s16        q3,  q3,  q15
1223        vshl.s16        q8,  q8,  q15
1224        vshl.s16        q9,  q9,  q15
1225        vshl.s16        q10, q10, q15
1226        vshl.s16        q11, q11, q15
1227        vsub.i16        q0,  q0,  q14
1228        vsub.i16        q1,  q1,  q14
1229        vsub.i16        q2,  q2,  q14
1230        vsub.i16        q3,  q3,  q14
1231        vsub.i16        q8,  q8,  q14
1232        vst1.16         {q0,  q1},  [r0, :128]!
1233        vld1.16         {q0,  q1},  [r1]!
1234        vsub.i16        q9,  q9,  q14
1235        vsub.i16        q10, q10, q14
1236        vst1.16         {q2,  q3},  [r0, :128]!
1237        vld1.16         {q2,  q3},  [r1]!
1238        vsub.i16        q11, q11, q14
1239        vshl.s16        q0,  q0,  q15
1240        vst1.16         {q8,  q9},  [r0, :128]!
1241        vld1.16         {q8,  q9},  [r1]!
1242        vshl.s16        q1,  q1,  q15
1243        vshl.s16        q2,  q2,  q15
1244        vst1.16         {q10, q11}, [r0, :128]!
1245        vld1.16         {q10, q11}, [r1], r2
1246        vshl.s16        q3,  q3,  q15
1247        vshl.s16        q8,  q8,  q15
1248        vshl.s16        q9,  q9,  q15
1249        vshl.s16        q10, q10, q15
1250        vshl.s16        q11, q11, q15
1251        vsub.i16        q0,  q0,  q14
1252        vsub.i16        q1,  q1,  q14
1253        vsub.i16        q2,  q2,  q14
1254        vsub.i16        q3,  q3,  q14
1255        vsub.i16        q8,  q8,  q14
1256        vst1.16         {q0,  q1},  [r0, :128]!
1257        vsub.i16        q9,  q9,  q14
1258        vst1.16         {q2,  q3},  [r0, :128]!
1259        vsub.i16        q10, q10, q14
1260        vst1.16         {q8,  q9},  [r0, :128]!
1261        vsub.i16        q11, q11, q14
1262        vst1.16         {q10, q11}, [r0, :128]!
1263        bgt             128b
1264        pop             {r4-r11,pc}
1265endfunc
1266
1267.macro load_slice s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6
1268        vld1.\wd        {\d0[]}, [\s0], \strd
1269        vld1.\wd        {\d1[]}, [\s1], \strd
1270.ifnb \d2
1271        vld1.\wd        {\d2[]}, [\s0], \strd
1272        vld1.\wd        {\d3[]}, [\s1], \strd
1273.endif
1274.ifnb \d4
1275        vld1.\wd        {\d4[]}, [\s0], \strd
1276.endif
1277.ifnb \d5
1278        vld1.\wd        {\d5[]}, [\s1], \strd
1279.endif
1280.ifnb \d6
1281        vld1.\wd        {\d6[]}, [\s0], \strd
1282.endif
1283.endm
1284.macro load_reg s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
1285        vld1.16         {\d0}, [\s0], \strd
1286        vld1.16         {\d1}, [\s1], \strd
1287.ifnb \d2
1288        vld1.16         {\d2}, [\s0], \strd
1289        vld1.16         {\d3}, [\s1], \strd
1290.endif
1291.ifnb \d4
1292        vld1.16         {\d4}, [\s0], \strd
1293.endif
1294.ifnb \d5
1295        vld1.16         {\d5}, [\s1], \strd
1296.endif
1297.ifnb \d6
1298        vld1.16         {\d6}, [\s0], \strd
1299.endif
1300.endm
1301.macro load_regpair s0, s1, strd, d0, d1, d2, d3, d4, d5
1302        vld1.16         {\d0, \d1}, [\s0], \strd
1303.ifnb \d2
1304        vld1.16         {\d2, \d3}, [\s1], \strd
1305.endif
1306.ifnb \d4
1307        vld1.16         {\d4, \d5}, [\s0], \strd
1308.endif
1309.endm
1310.macro load_32 s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
1311        load_slice      \s0, \s1, \strd, 32, \d0, \d1, \d2, \d3, \d4, \d5, \d6
1312.endm
1313.macro load_16s16 s0, s1, strd, d0, d1, d2, d3, d4, d5
1314        load_regpair    \s0, \s1, \strd, \d0, \d1, \d2, \d3, \d4, \d5
1315.endm
1316.macro interleave_1_32 r0, r1, r2, r3, r4
1317        vext.8          \r0, \r0, \r1, #4
1318        vext.8          \r1, \r1, \r2, #4
1319.ifnb \r3
1320        vext.8          \r2, \r2, \r3, #4
1321        vext.8          \r3, \r3, \r4, #4
1322.endif
1323.endm
1324.macro vmin_u16 c, r0, r1, r2, r3
1325        vmin.u16        \r0, \r0, \c
1326.ifnb \r1
1327        vmin.u16        \r1, \r1, \c
1328.endif
1329.ifnb \r2
1330        vmin.u16        \r2, \r2, \c
1331        vmin.u16        \r3, \r3, \c
1332.endif
1333.endm
1334.macro vsub_i16 c, r0, r1, r2, r3
1335        vsub.i16        \r0, \r0, \c
1336.ifnb \r1
1337        vsub.i16        \r1, \r1, \c
1338.endif
1339.ifnb \r2
1340        vsub.i16        \r2, \r2, \c
1341        vsub.i16        \r3, \r3, \c
1342.endif
1343.endm
1344.macro vmull_vmlal_4 d, s0, s1, s2, s3
1345        vmull.s16       \d,  \s0, d0[0]
1346        vmlal.s16       \d,  \s1, d0[1]
1347        vmlal.s16       \d,  \s2, d0[2]
1348        vmlal.s16       \d,  \s3, d0[3]
1349.endm
1350.macro vmull_vmlal_8 d, s0, s1, s2, s3, s4, s5, s6, s7
1351        vmull.s16       \d,  \s0, d0[0]
1352        vmlal.s16       \d,  \s1, d0[1]
1353        vmlal.s16       \d,  \s2, d0[2]
1354        vmlal.s16       \d,  \s3, d0[3]
1355        vmlal.s16       \d,  \s4, d1[0]
1356        vmlal.s16       \d,  \s5, d1[1]
1357        vmlal.s16       \d,  \s6, d1[2]
1358        vmlal.s16       \d,  \s7, d1[3]
1359.endm
1360.macro vqrshrun_s32 shift, q0, d0, q1, d1, q2, d2, q3, d3
1361        vqrshrun.s32    \d0, \q0, #\shift
1362.ifnb \q1
1363        vqrshrun.s32    \d1, \q1, #\shift
1364.endif
1365.ifnb \q2
1366        vqrshrun.s32    \d2, \q2, #\shift
1367        vqrshrun.s32    \d3, \q3, #\shift
1368.endif
1369.endm
1370.macro vmovn_i32 q0, d0, q1, d1, q2, d2, q3, d3
1371        vmovn.i32       \d0, \q0
1372.ifnb \q1
1373        vmovn.i32       \d1, \q1
1374.endif
1375.ifnb \q2
1376        vmovn.i32       \d2, \q2
1377        vmovn.i32       \d3, \q3
1378.endif
1379.endm
1380.macro vrshl_s32 shift, r0, r1, r2, r3
1381        vrshl.s32       \r0, \r0, \shift
1382        vrshl.s32       \r1, \r1, \shift
1383.ifnb \r2
1384        vrshl.s32       \r2, \r2, \shift
1385        vrshl.s32       \r3, \r3, \shift
1386.endif
1387.endm
1388.macro vst1_32 strd, r0, r1
1389        vst1.32         {\r0[0]}, [r0, :32], \strd
1390        vst1.32         {\r0[1]}, [r9, :32], \strd
1391.ifnb \r1
1392        vst1.32         {\r1[0]}, [r0, :32], \strd
1393        vst1.32         {\r1[1]}, [r9, :32], \strd
1394.endif
1395.endm
1396.macro vst1_reg strd, align, r0, r1, r2, r3, r4, r5, r6, r7
1397        vst1.16         {\r0}, [r0, \align], \strd
1398        vst1.16         {\r1}, [r9, \align], \strd
1399.ifnb \r2
1400        vst1.16         {\r2}, [r0, \align], \strd
1401        vst1.16         {\r3}, [r9, \align], \strd
1402.endif
1403.ifnb \r4
1404        vst1.16         {\r4}, [r0, \align], \strd
1405        vst1.16         {\r5}, [r9, \align], \strd
1406        vst1.16         {\r6}, [r0, \align], \strd
1407        vst1.16         {\r7}, [r9, \align], \strd
1408.endif
1409.endm
1410.macro finalize type, q0, q1, d0, d1, q2, q3, d2, d3
1411.ifc \type, put
1412        vqrshrun_s32    6,   \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3
1413        vmin_u16        q15, \q0, \q1
1414.else
1415        vrshl_s32       q14, \q0, \q1, \q2, \q3 // -(6-intermediate_bits)
1416        vmovn_i32       \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3
1417        vsub_i16        q15, \q0, \q1           // PREP_BIAS
1418.endif
1419.endm
1420.macro shift_store_4 type, strd, q0, q1, d0, d1, q2, q3, d2, d3
1421        finalize        \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3
1422        vst1_reg        \strd, :64, \d0, \d1, \d2, \d3
1423.endm
1424.macro shift_store_8 type, strd, q0, q1, d0, d1, q2, q3, d2, d3
1425        finalize        \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3
1426        vst1_reg        \strd, :128, \q0, \q1
1427.endm
1428.macro shift_store_16 type, strd, q0, q1, d0, d1, q2, q3, d2, d3
1429        finalize        \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3
1430        vst1.16         {\q0, \q1}, [r0, :128], \strd
1431.endm
1432
1433.macro make_8tap_fn op, type, type_h, type_v
1434function \op\()_8tap_\type\()_16bpc_neon, export=1
1435        push            {r4-r11,lr}
1436        movw            r9,  \type_h
1437        movw            r10, \type_v
1438        b               \op\()_8tap_neon
1439endfunc
1440.endm
1441
1442// No spaces in these expressions, due to gas-preprocessor.
1443#define REGULAR ((0*15<<7)|3*15)
1444#define SMOOTH  ((1*15<<7)|4*15)
1445#define SHARP   ((2*15<<7)|3*15)
1446
1447.macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, my, bdmax, ds2, sr2
1448make_8tap_fn \type, regular,        REGULAR, REGULAR
1449make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH
1450make_8tap_fn \type, regular_sharp,  REGULAR, SHARP
1451make_8tap_fn \type, smooth,         SMOOTH,  SMOOTH
1452make_8tap_fn \type, smooth_regular, SMOOTH,  REGULAR
1453make_8tap_fn \type, smooth_sharp,   SMOOTH,  SHARP
1454make_8tap_fn \type, sharp,          SHARP,   SHARP
1455make_8tap_fn \type, sharp_regular,  SHARP,   REGULAR
1456make_8tap_fn \type, sharp_smooth,   SHARP,   SMOOTH
1457
1458function \type\()_8tap_neon
1459        ldrd            r4,  r5,  [sp, #36]
1460        ldrd            r6,  r7,  [sp, #44]
1461.ifc \bdmax, r8
1462        ldr             r8,  [sp, #52]
1463.endif
1464        movw            r11, #0x4081  // (1 << 14) | (1 << 7) | (1 << 0)
1465        mul             \mx, \mx, r11
1466        mul             \my, \my, r11
1467        add             \mx, \mx, r9  // mx, 8tap_h, 4tap_h
1468        add             \my, \my, r10 // my, 8tap_v, 4tap_v
1469
1470.ifc \type, prep
1471        lsl             \d_strd, \w, #1
1472.endif
1473
1474        vdup.16         q15, \bdmax            // bitdepth_max
1475        clz             \bdmax,  \bdmax
1476        clz             r9,  \w
1477        sub             \bdmax,  \bdmax,  #18  // intermediate_bits = clz(bitdepth_max) - 18
1478        tst             \mx, #(0x7f << 14)
1479        sub             r9,  r9,  #24
1480        add             lr,  \bdmax, #6        // 6 + intermediate_bits
1481        rsb             r12, \bdmax, #6        // 6 - intermediate_bits
1482        movrel          r11, X(mc_subpel_filters), -8
1483        bne             L(\type\()_8tap_h)
1484        tst             \my, #(0x7f << 14)
1485        bne             L(\type\()_8tap_v)
1486        b               \type\()_neon
1487
1488L(\type\()_8tap_h):
1489        cmp             \w,  #4
1490        ubfx            r10, \mx, #7,  #7
1491        and             \mx, \mx, #0x7f
1492        it              gt
1493        movgt           \mx, r10
1494        tst             \my, #(0x7f << 14)
1495        add             \mx, r11, \mx, lsl #3
1496        bne             L(\type\()_8tap_hv)
1497
1498        adr             r10, L(\type\()_8tap_h_tbl)
1499        vdup.32         q14, r12           // 6 - intermediate_bits
1500        ldr             r9,  [r10, r9, lsl #2]
1501        vneg.s32        q14, q14           // -(6-intermediate_bits)
1502.ifc \type, put
1503        vdup.16         q13, \bdmax        // intermediate_bits
1504.else
1505        vmov.i16        q13, #PREP_BIAS
1506.endif
1507        add             r10, r10, r9
1508.ifc \type, put
1509        vneg.s16        q13, q13           // -intermediate_bits
1510.endif
1511        bx              r10
1512
1513        .align 2
1514L(\type\()_8tap_h_tbl):
1515        .word 1280f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1516        .word 640f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1517        .word 320f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1518        .word 160f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1519        .word 80f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1520        .word 40f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1521        .word 20f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1522
152320:     // 2xN h
1524.ifc \type, put
1525        add             \mx, \mx, #2
1526        vld1.32         {d0[]}, [\mx]
1527        sub             \src,  \src,  #2
1528        add             \ds2,  \dst,  \d_strd
1529        add             \sr2,  \src,  \s_strd
1530        lsl             \d_strd,  \d_strd,  #1
1531        lsl             \s_strd,  \s_strd,  #1
1532        vmovl.s8        q0,  d0
15332:
1534        vld1.16         {q2}, [\src], \s_strd
1535        vld1.16         {q3}, [\sr2], \s_strd
1536        vext.8          d5,  d4,  d5,  #2
1537        vext.8          d7,  d6,  d7,  #2
1538        subs            \h,  \h,  #2
1539        vtrn.32         d4,  d6
1540        vtrn.32         d5,  d7
1541        vmull.s16       q1,  d4,  d0[0]
1542        vmlal.s16       q1,  d5,  d0[1]
1543        vmlal.s16       q1,  d6,  d0[2]
1544        vmlal.s16       q1,  d7,  d0[3]
1545        vrshl.s32       q1,  q1,  q14 // -(6-intermediate_bits)
1546        vqmovun.s32     d2,  q1
1547        vrshl.s16       d2,  d2,  d26 // -intermediate_bits
1548        vmin.u16        d2,  d2,  d30
1549        vst1.32         {d2[0]}, [\dst, :32], \d_strd
1550        vst1.32         {d2[1]}, [\ds2, :32], \d_strd
1551        bgt             2b
1552        pop             {r4-r11,pc}
1553.endif
1554
155540:     // 4xN h
1556        add             \mx, \mx, #2
1557        vld1.32         {d0[]}, [\mx]
1558        sub             \src,  \src,  #2
1559        add             \ds2,  \dst,  \d_strd
1560        add             \sr2,  \src,  \s_strd
1561        lsl             \d_strd,  \d_strd,  #1
1562        lsl             \s_strd,  \s_strd,  #1
1563        vmovl.s8        q0,  d0
15644:
1565        vld1.16         {q8},  [\src], \s_strd
1566        vld1.16         {q11}, [\sr2], \s_strd
1567        vext.8          d18, d16, d17, #2
1568        vext.8          d19, d16, d17, #4
1569        vext.8          d20, d16, d17, #6
1570        vext.8          d24, d22, d23, #2
1571        vext.8          d25, d22, d23, #4
1572        vext.8          d21, d22, d23, #6
1573        subs            \h,  \h,  #2
1574        vmull.s16       q2,  d16, d0[0]
1575        vmlal.s16       q2,  d18, d0[1]
1576        vmlal.s16       q2,  d19, d0[2]
1577        vmlal.s16       q2,  d20, d0[3]
1578        vmull.s16       q3,  d22, d0[0]
1579        vmlal.s16       q3,  d24, d0[1]
1580        vmlal.s16       q3,  d25, d0[2]
1581        vmlal.s16       q3,  d21, d0[3]
1582        vrshl.s32       q2,  q2,  q14 // -(6-intermediate_bits)
1583        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
1584.ifc \type, put
1585        vqmovun.s32     d4,  q2
1586        vqmovun.s32     d5,  q3
1587        vrshl.s16       q2,  q2,  q13 // -intermediate_bits
1588        vmin.u16        q2,  q2,  q15
1589.else
1590        vmovn.s32       d4,  q2
1591        vmovn.s32       d5,  q3
1592        vsub.i16        q2,  q2,  q13 // PREP_BIAS
1593.endif
1594        vst1.16         {d4}, [\dst, :64], \d_strd
1595        vst1.16         {d5}, [\ds2, :64], \d_strd
1596        bgt             4b
1597        pop             {r4-r11,pc}
1598
159980:
1600160:
1601320:
1602640:
16031280:   // 8xN, 16xN, 32xN, ... h
1604        vpush           {q4-q5}
1605        vld1.8          {d0}, [\mx, :64]
1606        sub             \src,  \src,  #6
1607        add             \ds2,  \dst,  \d_strd
1608        add             \sr2,  \src,  \s_strd
1609        lsl             \s_strd,  \s_strd,  #1
1610        vmovl.s8        q0,  d0
1611
1612        sub             \s_strd,  \s_strd,  \w, lsl #1
1613        sub             \s_strd,  \s_strd,  #16
1614.ifc \type, put
1615        lsl             \d_strd,  \d_strd,  #1
1616        sub             \d_strd,  \d_strd,  \w, lsl #1
1617.endif
161881:
1619        vld1.16         {q8,  q9},  [\src]!
1620        vld1.16         {q10, q11}, [\sr2]!
1621        mov             \mx, \w
1622
16238:
1624        vmull.s16       q1,  d16, d0[0]
1625        vmull.s16       q2,  d17, d0[0]
1626        vmull.s16       q3,  d20, d0[0]
1627        vmull.s16       q4,  d21, d0[0]
1628.irpc i, 1234567
1629        vext.8          q12, q8,  q9,  #(2*\i)
1630        vext.8          q5,  q10, q11, #(2*\i)
1631.if \i < 4
1632        vmlal.s16       q1,  d24, d0[\i]
1633        vmlal.s16       q2,  d25, d0[\i]
1634        vmlal.s16       q3,  d10, d0[\i]
1635        vmlal.s16       q4,  d11, d0[\i]
1636.else
1637        vmlal.s16       q1,  d24, d1[\i-4]
1638        vmlal.s16       q2,  d25, d1[\i-4]
1639        vmlal.s16       q3,  d10, d1[\i-4]
1640        vmlal.s16       q4,  d11, d1[\i-4]
1641.endif
1642.endr
1643        subs            \mx, \mx, #8
1644        vrshl.s32       q1,  q1,  q14 // -(6-intermediate_bits)
1645        vrshl.s32       q2,  q2,  q14 // -(6-intermediate_bits)
1646        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
1647        vrshl.s32       q4,  q4,  q14 // -(6-intermediate_bits)
1648.ifc \type, put
1649        vqmovun.s32     d2,  q1
1650        vqmovun.s32     d3,  q2
1651        vqmovun.s32     d4,  q3
1652        vqmovun.s32     d5,  q4
1653        vrshl.s16       q1,  q1,  q13 // -intermediate_bits
1654        vrshl.s16       q2,  q2,  q13 // -intermediate_bits
1655        vmin.u16        q1,  q1,  q15
1656        vmin.u16        q2,  q2,  q15
1657.else
1658        vmovn.s32       d2,  q1
1659        vmovn.s32       d3,  q2
1660        vmovn.s32       d4,  q3
1661        vmovn.s32       d5,  q4
1662        vsub.i16        q1,  q1,  q13 // PREP_BIAS
1663        vsub.i16        q2,  q2,  q13 // PREP_BIAS
1664.endif
1665        vst1.16         {q1}, [\dst, :128]!
1666        vst1.16         {q2}, [\ds2, :128]!
1667        ble             9f
1668
1669        vmov            q8,  q9
1670        vmov            q10, q11
1671        vld1.16         {q9},  [\src]!
1672        vld1.16         {q11}, [\sr2]!
1673        b               8b
1674
16759:
1676        add             \dst,  \dst,  \d_strd
1677        add             \ds2,  \ds2,  \d_strd
1678        add             \src,  \src,  \s_strd
1679        add             \sr2,  \sr2,  \s_strd
1680
1681        subs            \h,  \h,  #2
1682        bgt             81b
1683        vpop            {q4-q5}
1684        pop             {r4-r11,pc}
1685
1686
1687L(\type\()_8tap_v):
1688        cmp             \h,  #4
1689        ubfx            r10, \my, #7,  #7
1690        and             \my, \my, #0x7f
1691        it              gt
1692        movgt           \my, r10
1693        add             \my, r11, \my, lsl #3
1694
1695.ifc \type, prep
1696        vdup.32         q14, r12        // 6 - intermediate_bits
1697        vmov.i16        q15, #PREP_BIAS
1698.endif
1699        adr             r10, L(\type\()_8tap_v_tbl)
1700        ldr             r9,  [r10, r9, lsl #2]
1701.ifc \type, prep
1702        vneg.s32        q14, q14        // -(6-intermediate_bits)
1703.endif
1704        add             r10, r10, r9
1705        bx              r10
1706
1707        .align 2
1708L(\type\()_8tap_v_tbl):
1709        .word 1280f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1710        .word 640f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1711        .word 320f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1712        .word 160f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1713        .word 80f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1714        .word 40f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1715        .word 20f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1716
171720:     // 2xN v
1718.ifc \type, put
1719        bgt             28f
1720
1721        cmp             \h,  #2
1722        add             \my, \my, #2
1723        vld1.32         {d0[]}, [\my]
1724        sub             \src,  \src,  \s_strd
1725        add             \ds2,  \dst,  \d_strd
1726        add             \sr2,  \src,  \s_strd
1727        lsl             \s_strd,  \s_strd,  #1
1728        lsl             \d_strd,  \d_strd,  #1
1729        vmovl.s8        q0,  d0
1730
1731        // 2x2 v
1732        load_32         \src, \sr2, \s_strd, d1, d2, d3, d4, d5
1733        interleave_1_32 d1,  d2,  d3,  d4,  d5
1734        bgt             24f
1735        vmull_vmlal_4   q8,  d1,  d2,  d3,  d4
1736        vqrshrun_s32    6,   q8,  d16
1737        vmin_u16        d30, d16
1738        vst1_32         \d_strd,  d16
1739        pop             {r4-r11,pc}
1740
174124:     // 2x4 v
1742        load_32         \sr2, \src, \s_strd, d6, d7
1743        interleave_1_32 d5,  d6,  d7
1744        vmull_vmlal_4   q8,  d1,  d2,  d3,  d4
1745        vmull_vmlal_4   q9,  d3,  d4,  d5,  d6
1746        vqrshrun_s32    6,   q8,  d16, q9,  d17
1747        vmin_u16        q15, q8
1748        vst1_32         \d_strd,  d16, d17
1749        pop             {r4-r11,pc}
1750
175128:     // 2x6, 2x8, 2x12, 2x16 v
1752        vld1.8          {d0}, [\my, :64]
1753        sub             \sr2,  \src,  \s_strd, lsl #1
1754        add             \ds2,  \dst,  \d_strd
1755        sub             \src,  \sr2,  \s_strd
1756        lsl             \d_strd,  \d_strd,  #1
1757        lsl             \s_strd,  \s_strd,  #1
1758        vmovl.s8        q0,  d0
1759
1760        load_32         \src, \sr2, \s_strd, d2, d3, d4, d5, d6, d7, d16
1761        interleave_1_32 d2,  d3,  d4,  d5,  d6
1762        interleave_1_32 d6,  d7,  d16
1763216:
1764        subs            \h,  \h,  #4
1765        load_32         \sr2, \src, \s_strd, d17, d18, d19, d20
1766        interleave_1_32 d16, d17, d18, d19, d20
1767        vmull_vmlal_8   q13, d2,  d3,  d4,  d5,  d6,  d7,  d16, d17
1768        vmull_vmlal_8   q1,  d4,  d5,  d6,  d7,  d16, d17, d18, d19
1769        vqrshrun_s32    6,   q13, d26, q1,  d27
1770        vmin_u16        q15, q13
1771        vst1_32         \d_strd,  d26, d27
1772        ble             0f
1773        cmp             \h,  #2
1774        vmov            q1,  q3
1775        vmov            q2,  q8
1776        vmov            q3,  q9
1777        vmov            d16, d20
1778        beq             26f
1779        b               216b
178026:
1781        load_32         \sr2, \src, \s_strd, d17, d18
1782        interleave_1_32 d16, d17, d18
1783        vmull_vmlal_8   q13, d2,  d3,  d4,  d5,  d6,  d7,  d16, d17
1784        vqrshrun_s32    6,   q13, d26
1785        vmin_u16        d30, d26
1786        vst1_32         \d_strd,  d26
17870:
1788        pop             {r4-r11,pc}
1789.endif
1790
179140:
1792        bgt             480f
1793
1794        // 4x2, 4x4 v
1795        cmp             \h,  #2
1796        add             \my, \my, #2
1797        vld1.32         {d0[]}, [\my]
1798        sub             \src, \src, \s_strd
1799        add             \ds2, \dst, \d_strd
1800        add             \sr2, \src, \s_strd
1801        lsl             \s_strd, \s_strd, #1
1802        lsl             \d_strd, \d_strd, #1
1803        vmovl.s8        q0,  d0
1804
1805        load_reg        \src, \sr2, \s_strd, d1, d2, d3, d4, d5
1806        vmull_vmlal_4   q8,  d1,  d2,  d3,  d4
1807        vmull_vmlal_4   q9,  d2,  d3,  d4,  d5
1808        shift_store_4   \type, \d_strd, q8, q9, d16, d17
1809        ble             0f
1810        load_reg        \sr2, \src, \s_strd, d6, d7
1811        vmull_vmlal_4   q8,  d3,  d4,  d5,  d6
1812        vmull_vmlal_4   q9,  d4,  d5,  d6,  d7
1813        shift_store_4   \type, \d_strd, q8, q9, d16, d17
18140:
1815        pop             {r4-r11,pc}
1816
1817480:    // 4x6, 4x8, 4x12, 4x16 v
1818        vld1.8          {d0}, [\my, :64]
1819        sub             \sr2, \src, \s_strd, lsl #1
1820        add             \ds2, \dst, \d_strd
1821        sub             \src, \sr2, \s_strd
1822        lsl             \s_strd, \s_strd, #1
1823        lsl             \d_strd, \d_strd, #1
1824        vmovl.s8        q0,  d0
1825
1826        load_reg        \src, \sr2, \s_strd, d16, d17, d18, d19, d20, d21, d22
1827
182848:
1829        subs            \h,  \h,  #4
1830        load_reg        \sr2, \src, \s_strd, d23, d24, d25, d26
1831        vmull_vmlal_8   q1,  d16, d17, d18, d19, d20, d21, d22, d23
1832        vmull_vmlal_8   q2,  d17, d18, d19, d20, d21, d22, d23, d24
1833        vmull_vmlal_8   q3,  d18, d19, d20, d21, d22, d23, d24, d25
1834        vmull_vmlal_8   q8,  d19, d20, d21, d22, d23, d24, d25, d26
1835        shift_store_4   \type, \d_strd, q1, q2, d2, d3, q3, q8, d4, d5
1836        ble             0f
1837        cmp             \h,  #2
1838        vmov            q8,  q10
1839        vmov            q9,  q11
1840        vmov            q10, q12
1841        vmov            d22, d26
1842        beq             46f
1843        b               48b
184446:
1845        load_reg        \sr2, \src, \s_strd, d23, d24
1846        vmull_vmlal_8   q1,  d16, d17, d18, d19, d20, d21, d22, d23
1847        vmull_vmlal_8   q2,  d17, d18, d19, d20, d21, d22, d23, d24
1848        shift_store_4   \type, \d_strd, q1, q2, d2, d3
18490:
1850        pop             {r4-r11,pc}
1851
185280:
1853        bgt             880f
1854
1855        // 8x2, 8x4 v
1856        cmp             \h,  #2
1857        add             \my, \my, #2
1858        vld1.32         {d0[]}, [\my]
1859        sub             \src, \src, \s_strd
1860        add             \ds2, \dst, \d_strd
1861        add             \sr2, \src, \s_strd
1862        lsl             \s_strd, \s_strd, #1
1863        lsl             \d_strd, \d_strd, #1
1864        vmovl.s8        q0,  d0
1865
1866        load_reg        \src, \sr2, \s_strd, q1, q2, q3, q8, q9
1867        vmull_vmlal_4   q10, d2,  d4,  d6,  d16
1868        vmull_vmlal_4   q11, d3,  d5,  d7,  d17
1869        vmull_vmlal_4   q12, d4,  d6,  d16, d18
1870        vmull_vmlal_4   q13, d5,  d7,  d17, d19
1871        shift_store_8   \type, \d_strd, q10, q11, d20, d21, q12, q13, d22, d23
1872        ble             0f
1873        load_reg        \sr2, \src, \s_strd, q10, q11
1874        vmull_vmlal_4   q1,  d6,  d16, d18, d20
1875        vmull_vmlal_4   q2,  d7,  d17, d19, d21
1876        vmull_vmlal_4   q12, d16, d18, d20, d22
1877        vmull_vmlal_4   q13, d17, d19, d21, d23
1878        shift_store_8   \type, \d_strd, q1, q2, d2, d3, q12, q13, d4, d5
18790:
1880        pop             {r4-r11,pc}
1881
1882880:    // 8x6, 8x8, 8x16, 8x32 v
18831680:   // 16x8, 16x16, ...
1884320:    // 32x8, 32x16, ...
1885640:
18861280:
1887        vpush           {q4-q7}
1888        vld1.8          {d0}, [\my, :64]
1889        sub             \src, \src, \s_strd
1890        sub             \src, \src, \s_strd, lsl #1
1891        vmovl.s8        q0,  d0
1892        mov             \my, \h
1893168:
1894        add             \ds2, \dst, \d_strd
1895        add             \sr2, \src, \s_strd
1896        lsl             \s_strd, \s_strd, #1
1897        lsl             \d_strd, \d_strd, #1
1898
1899        load_reg        \src, \sr2, \s_strd, q5, q6, q7, q8, q9, q10, q11
1900
190188:
1902        subs            \h,  \h,  #2
1903        load_reg        \sr2, \src, \s_strd, q12, q13
1904        vmull_vmlal_8   q1,  d10, d12, d14, d16, d18, d20, d22, d24
1905        vmull_vmlal_8   q2,  d11, d13, d15, d17, d19, d21, d23, d25
1906        vmull_vmlal_8   q3,  d12, d14, d16, d18, d20, d22, d24, d26
1907        vmull_vmlal_8   q4,  d13, d15, d17, d19, d21, d23, d25, d27
1908        shift_store_8   \type, \d_strd, q1, q2,  d2,  d3,  q3,  q4,  d4,  d5
1909        ble             9f
1910        subs            \h,  \h,  #2
1911        load_reg        \sr2, \src, \s_strd, q1,  q2
1912        vmull_vmlal_8   q3,  d14, d16, d18, d20, d22, d24, d26, d2
1913        vmull_vmlal_8   q4,  d15, d17, d19, d21, d23, d25, d27, d3
1914        vmull_vmlal_8   q5,  d16, d18, d20, d22, d24, d26, d2,  d4
1915        vmull_vmlal_8   q6,  d17, d19, d21, d23, d25, d27, d3,  d5
1916        shift_store_8   \type, \d_strd, q3, q4,  d6,  d7,  q5,  q6,  d8,  d9
1917        ble             9f
1918        vmov            q5,  q9
1919        vmov            q6,  q10
1920        vmov            q7,  q11
1921        vmov            q8,  q12
1922        vmov            q9,  q13
1923        vmov            q10, q1
1924        vmov            q11, q2
1925        b               88b
19269:
1927        subs            \w,  \w,  #8
1928        ble             0f
1929        asr             \s_strd, \s_strd, #1
1930        asr             \d_strd, \d_strd, #1
1931        mls             \src, \s_strd, \my, \src
1932        mls             \dst, \d_strd, \my, \dst
1933        sub             \src, \src, \s_strd, lsl #3
1934        mov             \h,  \my
1935        add             \src, \src, #16
1936        add             \dst, \dst, #16
1937        b               168b
19380:
1939        vpop            {q4-q7}
1940        pop             {r4-r11,pc}
1941
1942160:
1943        bgt             1680b
1944
1945        // 16x2, 16x4 v
1946        vpush           {q6-q7}
1947        add             \my, \my, #2
1948        vld1.32         {d0[]}, [\my]
1949        sub             \src, \src, \s_strd
1950        vmovl.s8        q0,  d0
1951
1952        load_16s16      \src, \src, \s_strd, q6,  q7,  q8,  q9, q10, q11
195316:
1954        load_16s16      \src, \src, \s_strd, q12, q13
1955        subs            \h,  \h,  #1
1956        vmull_vmlal_4   q1,  d12, d16, d20, d24
1957        vmull_vmlal_4   q2,  d13, d17, d21, d25
1958        vmull_vmlal_4   q3,  d14, d18, d22, d26
1959        vmull_vmlal_4   q6,  d15, d19, d23, d27
1960        shift_store_16  \type, \d_strd, q1, q2, d2, d3, q3, q6, d4, d5
1961        ble             0f
1962        vmov            q6,  q8
1963        vmov            q7,  q9
1964        vmov            q8,  q10
1965        vmov            q9,  q11
1966        vmov            q10, q12
1967        vmov            q11, q13
1968        b               16b
19690:
1970        vpop            {q6-q7}
1971        pop             {r4-r11,pc}
1972
1973
1974L(\type\()_8tap_hv):
1975        cmp             \h,  #4
1976        ubfx            r10, \my, #7,  #7
1977        and             \my, \my, #0x7f
1978        it              gt
1979        movgt           \my, r10
19804:
1981        add             \my, r11, \my, lsl #3
1982
1983        adr             r10, L(\type\()_8tap_hv_tbl)
1984        neg             r12, r12           // -(6-intermediate_bits)
1985        ldr             r9,  [r10, r9, lsl #2]
1986        vdup.32         q14, r12           // -(6-intermediate_bits)
1987.ifc \type, put
1988        neg             r8,  lr            // -(6+intermeidate_bits)
1989.else
1990        vmov.i16        q13, #PREP_BIAS
1991.endif
1992        add             r10, r10, r9
1993.ifc \type, put
1994        vdup.32         q13, r8            // -(6+intermediate_bits)
1995.endif
1996        bx              r10
1997
1998        .align 2
1999L(\type\()_8tap_hv_tbl):
2000        .word 1280f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
2001        .word 640f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
2002        .word 320f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
2003        .word 160f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
2004        .word 80f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
2005        .word 40f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
2006        .word 20f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
2007
200820:
2009.ifc \type, put
2010        add             \mx, \mx, #2
2011        vld1.32         {d0[]}, [\mx]
2012        bgt             280f
2013        add             \my, \my, #2
2014        vld1.32         {d2[]}, [\my]
2015
2016        // 2x2, 2x4 hv
2017        sub             \sr2, \src, #2
2018        sub             \src, \sr2, \s_strd
2019        add             \ds2, \dst, \d_strd
2020        lsl             \s_strd, \s_strd, #1
2021        lsl             \d_strd, \d_strd, #1
2022        vmovl.s8        q0,  d0
2023        vmovl.s8        q1,  d2
2024
2025        vld1.16         {q11}, [\src], \s_strd
2026        vext.8          d24, d22, d23, #2
2027        vmull.s16       q11, d22, d0
2028        vmull.s16       q12, d24, d0
2029        vpadd.s32       d22, d22, d23
2030        vpadd.s32       d23, d24, d25
2031        vpadd.s32       d22, d22, d23
2032        vrshl.s32       d16, d22, d28 // -(6-intermediate_bits)
2033        vmovn.i32       d16, q8
2034        bl              L(\type\()_8tap_filter_2)
2035
2036        vext.8          d16, d16, d16, #4
2037        vext.8          d16, d16, d24, #4
2038        vmov            d17, d24
2039
20402:
2041        bl              L(\type\()_8tap_filter_2)
2042
2043        vext.8          d18, d17, d24, #4
2044        vmull.s16       q2,  d16, d2[0]
2045        vmlal.s16       q2,  d17, d2[1]
2046        vmlal.s16       q2,  d18, d2[2]
2047        vmlal.s16       q2,  d24, d2[3]
2048
2049        vrshl.s32       q2,  q2,  q13 // -(6+intermediate_bits)
2050        vqmovun.s32     d4,  q2
2051        vmin.u16        d4,  d4,  d30
2052        subs            \h,  \h,  #2
2053        vst1.32         {d4[0]}, [\dst, :32], \d_strd
2054        vst1.32         {d4[1]}, [\ds2, :32], \d_strd
2055        ble             0f
2056        vmov            d16, d18
2057        vmov            d17, d24
2058        b               2b
2059
2060280:    // 2x8, 2x16, 2x32 hv
2061        vld1.8          {d2},  [\my, :64]
2062        sub             \src, \src, #2
2063        sub             \sr2, \src, \s_strd, lsl #1
2064        sub             \src, \sr2, \s_strd
2065        add             \ds2, \dst, \d_strd
2066        lsl             \s_strd, \s_strd, #1
2067        lsl             \d_strd, \d_strd, #1
2068        vmovl.s8        q0,  d0
2069        vmovl.s8        q1,  d2
2070
2071        vld1.16         {q11}, [\src], \s_strd
2072        vext.8          d24, d22, d23, #2
2073        vmull.s16       q11, d22, d0
2074        vmull.s16       q12, d24, d0
2075        vpadd.s32       d22, d22, d23
2076        vpadd.s32       d23, d24, d25
2077        vpadd.s32       d22, d22, d23
2078        vrshl.s32       d16, d22, d28 // -(6-intermediate_bits)
2079        vmovn.i32       d16, q8
2080
2081        bl              L(\type\()_8tap_filter_2)
2082
2083        vext.8          d16, d16, d16, #4
2084        vext.8          d16, d16, d24, #4
2085        vmov            d17, d24
2086        bl              L(\type\()_8tap_filter_2)
2087        vext.8          d18, d17, d24, #4
2088        vmov            d19, d24
2089        bl              L(\type\()_8tap_filter_2)
2090        vext.8          d20, d19, d24, #4
2091        vmov            d21, d24
2092
209328:
2094        bl              L(\type\()_8tap_filter_2)
2095        vext.8          d22, d21, d24, #4
2096        vmull.s16       q3,  d16, d2[0]
2097        vmlal.s16       q3,  d17, d2[1]
2098        vmlal.s16       q3,  d18, d2[2]
2099        vmlal.s16       q3,  d19, d2[3]
2100        vmlal.s16       q3,  d20, d3[0]
2101        vmlal.s16       q3,  d21, d3[1]
2102        vmlal.s16       q3,  d22, d3[2]
2103        vmlal.s16       q3,  d24, d3[3]
2104
2105        vrshl.s32       q3,  q3,  q13 // -(6+intermediate_bits)
2106        vqmovun.s32     d6,  q3
2107        vmin.u16        d6,  d6,  d30
2108        subs            \h,  \h,  #2
2109        vst1.32         {d6[0]}, [\dst, :32], \d_strd
2110        vst1.32         {d6[1]}, [\ds2, :32], \d_strd
2111        ble             0f
2112        vmov            q8,  q9
2113        vmov            q9,  q10
2114        vmov            d20, d22
2115        vmov            d21, d24
2116        b               28b
21170:
2118        pop             {r4-r11,pc}
2119
2120L(\type\()_8tap_filter_2):
2121        vld1.16         {q11}, [\sr2], \s_strd
2122        vld1.16         {q12}, [\src], \s_strd
2123        vext.8          d23, d22, d23, #2
2124        vext.8          d25, d24, d25, #2
2125        vtrn.32         q11, q12
2126        vmull.s16       q3,  d22, d0[0]
2127        vmlal.s16       q3,  d23, d0[1]
2128        vmlal.s16       q3,  d24, d0[2]
2129        vmlal.s16       q3,  d25, d0[3]
2130        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
2131        vmovn.i32       d24, q3
2132        bx              lr
2133.endif
2134
213540:
2136        add             \mx, \mx, #2
2137        vld1.32         {d0[]}, [\mx]
2138        bgt             480f
2139        add             \my, \my, #2
2140        vld1.32         {d2[]}, [\my]
2141        sub             \sr2, \src, #2
2142        sub             \src, \sr2, \s_strd
2143        add             \ds2, \dst, \d_strd
2144        lsl             \s_strd, \s_strd, #1
2145        lsl             \d_strd, \d_strd, #1
2146        vmovl.s8        q0,  d0
2147        vmovl.s8        q1,  d2
2148
2149        // 4x2, 4x4 hv
2150        vld1.16         {q11}, [\src], \s_strd
2151        vext.8          d24, d22, d23, #2
2152        vext.8          d25, d22, d23, #4
2153        vext.8          d23, d22, d23, #6
2154        vmull.s16       q10, d22, d0[0]
2155        vmlal.s16       q10, d24, d0[1]
2156        vmlal.s16       q10, d25, d0[2]
2157        vmlal.s16       q10, d23, d0[3]
2158        vrshl.s32       q10, q10, q14 // -(6-intermediate_bits)
2159        vmovn.i32       d17, q10
2160
2161        bl              L(\type\()_8tap_filter_4)
2162        vmov            q9,  q12
2163
21644:
2165        bl              L(\type\()_8tap_filter_4)
2166        vmull.s16       q2,  d17, d2[0]
2167        vmlal.s16       q2,  d18, d2[1]
2168        vmlal.s16       q2,  d19, d2[2]
2169        vmlal.s16       q2,  d24, d2[3]
2170        vmull.s16       q3,  d18, d2[0]
2171        vmlal.s16       q3,  d19, d2[1]
2172        vmlal.s16       q3,  d24, d2[2]
2173        vmlal.s16       q3,  d25, d2[3]
2174.ifc \type, put
2175        vrshl.s32       q2,  q2,  q13 // -(6+intermediate_bits)
2176        vrshl.s32       q3,  q3,  q13 // -(6+intermediate_bits)
2177        vqmovun.s32     d4,  q2
2178        vqmovun.s32     d5,  q3
2179        vmin.u16        q2,  q2,  q15
2180.else
2181        vrshrn.i32      d4,  q2,  #6
2182        vrshrn.i32      d5,  q3,  #6
2183        vsub.i16        q2,  q2,  q13 // PREP_BIAS
2184.endif
2185        subs            \h,  \h,  #2
2186
2187        vst1.16         {d4}, [\dst, :64], \d_strd
2188        vst1.16         {d5}, [\ds2, :64], \d_strd
2189        ble             0f
2190        vmov            d17, d19
2191        vmov            q9,  q12
2192        b               4b
21930:
2194        pop             {r4-r11,pc}
2195
2196480:    // 4x8, 4x16, 4x32 hv
2197        vpush           {d13-d15}
2198        vld1.8          {d2},  [\my, :64]
2199        sub             \src, \src, #2
2200        sub             \sr2, \src, \s_strd, lsl #1
2201        sub             \src, \sr2, \s_strd
2202        add             \ds2, \dst, \d_strd
2203        lsl             \s_strd, \s_strd, #1
2204        lsl             \d_strd, \d_strd, #1
2205        vmovl.s8        q0,  d0
2206        vmovl.s8        q1,  d2
2207
2208        vld1.16         {q11}, [\src], \s_strd
2209        vext.8          d24, d22, d23, #2
2210        vext.8          d25, d22, d23, #4
2211        vext.8          d23, d22, d23, #6
2212        vmull.s16       q10, d22, d0[0]
2213        vmlal.s16       q10, d24, d0[1]
2214        vmlal.s16       q10, d25, d0[2]
2215        vmlal.s16       q10, d23, d0[3]
2216        vrshl.s32       q10, q10, q14 // -(6-intermediate_bits)
2217        vmovn.i32       d13, q10
2218
2219        bl              L(\type\()_8tap_filter_4)
2220        vmov            q7,  q12
2221        bl              L(\type\()_8tap_filter_4)
2222        vmov            q8,  q12
2223        bl              L(\type\()_8tap_filter_4)
2224        vmov            q9,  q12
2225
222648:
2227        bl              L(\type\()_8tap_filter_4)
2228        vmull.s16       q2,  d13, d2[0]
2229        vmlal.s16       q2,  d14, d2[1]
2230        vmlal.s16       q2,  d15, d2[2]
2231        vmlal.s16       q2,  d16, d2[3]
2232        vmlal.s16       q2,  d17, d3[0]
2233        vmlal.s16       q2,  d18, d3[1]
2234        vmlal.s16       q2,  d19, d3[2]
2235        vmlal.s16       q2,  d24, d3[3]
2236        vmull.s16       q3,  d14, d2[0]
2237        vmlal.s16       q3,  d15, d2[1]
2238        vmlal.s16       q3,  d16, d2[2]
2239        vmlal.s16       q3,  d17, d2[3]
2240        vmlal.s16       q3,  d18, d3[0]
2241        vmlal.s16       q3,  d19, d3[1]
2242        vmlal.s16       q3,  d24, d3[2]
2243        vmlal.s16       q3,  d25, d3[3]
2244.ifc \type, put
2245        vrshl.s32       q2,  q2,  q13 // -(6+intermediate_bits)
2246        vrshl.s32       q3,  q3,  q13 // -(6+intermediate_bits)
2247        vqmovun.s32     d4,  q2
2248        vqmovun.s32     d5,  q3
2249        vmin.u16        q2,  q2,  q15
2250.else
2251        vrshrn.i32      d4,  q2,  #6
2252        vrshrn.i32      d5,  q3,  #6
2253        vsub.i16        q2,  q2,  q13 // PREP_BIAS
2254.endif
2255        subs            \h,  \h,  #2
2256        vst1.16         {d4}, [\dst, :64], \d_strd
2257        vst1.16         {d5}, [\ds2, :64], \d_strd
2258        ble             0f
2259        vmov            d13, d15
2260        vmov            q7,  q8
2261        vmov            q8,  q9
2262        vmov            q9,  q12
2263        b               48b
22640:
2265        vpop            {d13-d15}
2266        pop             {r4-r11,pc}
2267
2268L(\type\()_8tap_filter_4):
2269        vld1.16         {q10}, [\sr2], \s_strd
2270        vld1.16         {q11}, [\src], \s_strd
2271        vext.8          d24, d20, d21, #2
2272        vext.8          d25, d20, d21, #4
2273        vext.8          d21, d20, d21, #6
2274        vmull.s16       q3,  d20, d0[0]
2275        vmlal.s16       q3,  d24, d0[1]
2276        vmlal.s16       q3,  d25, d0[2]
2277        vmlal.s16       q3,  d21, d0[3]
2278        vext.8          d24, d22, d23, #2
2279        vext.8          d25, d22, d23, #4
2280        vext.8          d23, d22, d23, #6
2281        vmull.s16       q10, d22, d0[0]
2282        vmlal.s16       q10, d24, d0[1]
2283        vmlal.s16       q10, d25, d0[2]
2284        vmlal.s16       q10, d23, d0[3]
2285        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
2286        vrshl.s32       q10, q10, q14 // -(6-intermediate_bits)
2287        vmovn.i32       d24, q3
2288        vmovn.i32       d25, q10
2289        bx              lr
2290
229180:
2292160:
2293320:
2294        bgt             880f
2295        add             \my, \my, #2
2296        vld1.8          {d0},  [\mx, :64]
2297        vld1.32         {d2[]}, [\my]
2298        sub             \src,  \src,  #6
2299        sub             \src,  \src,  \s_strd
2300        vmovl.s8        q0,  d0
2301        vmovl.s8        q1,  d2
2302        mov             \my, \h
2303
2304164:    // 8x2, 8x4, 16x2, 16x4, 32x2, 32x4 hv
2305        add             \ds2, \dst, \d_strd
2306        add             \sr2,  \src,  \s_strd
2307        lsl             \d_strd, \d_strd, #1
2308        lsl             \s_strd, \s_strd, #1
2309
2310        vld1.16         {q11, q12}, [\src], \s_strd
2311        vmull.s16       q2,  d22, d0[0]
2312        vmull.s16       q3,  d23, d0[0]
2313        vdup.32         q14, r12      // -(6-intermediate_bits)
2314.irpc i, 1234567
2315        vext.8          q10, q11, q12, #(2*\i)
2316.if \i < 4
2317        vmlal.s16       q2,  d20, d0[\i]
2318        vmlal.s16       q3,  d21, d0[\i]
2319.else
2320        vmlal.s16       q2,  d20, d1[\i - 4]
2321        vmlal.s16       q3,  d21, d1[\i - 4]
2322.endif
2323.endr
2324        vrshl.s32       q2,  q2,  q14 // -(6-intermediate_bits)
2325        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
2326        vmovn.i32       d16, q2
2327        vmovn.i32       d17, q3
2328
2329        bl              L(\type\()_8tap_filter_8)
2330        vmov            q9,  q11
2331        vmov            q10, q12
2332
23338:
2334        bl              L(\type\()_8tap_filter_8)
2335        vmull.s16       q2,  d16, d2[0]
2336        vmull.s16       q3,  d17, d2[0]
2337        vmull.s16       q13, d18, d2[0]
2338        vmull.s16       q14, d19, d2[0]
2339.ifc \type, put
2340        vdup.32         q8,  r8      // -(6+intermediate_bits)
2341.endif
2342        vmlal.s16       q2,  d18, d2[1]
2343        vmlal.s16       q3,  d19, d2[1]
2344        vmlal.s16       q13, d20, d2[1]
2345        vmlal.s16       q14, d21, d2[1]
2346        vmlal.s16       q2,  d20, d2[2]
2347        vmlal.s16       q3,  d21, d2[2]
2348        vmlal.s16       q13, d22, d2[2]
2349        vmlal.s16       q14, d23, d2[2]
2350        vmlal.s16       q2,  d22, d2[3]
2351        vmlal.s16       q3,  d23, d2[3]
2352        vmlal.s16       q13, d24, d2[3]
2353        vmlal.s16       q14, d25, d2[3]
2354.ifc \type, put
2355        vdup.16         q9,  \bdmax  // bitdepth_max
2356        vrshl.s32       q2,  q2,  q8 // -(6+intermediate_bits)
2357        vrshl.s32       q3,  q3,  q8 // -(6+intermediate_bits)
2358        vrshl.s32       q13, q13, q8 // -(6+intermediate_bits)
2359        vrshl.s32       q14, q14, q8 // -(6+intermediate_bits)
2360        vqmovun.s32     d4,  q2
2361        vqmovun.s32     d5,  q3
2362        vqmovun.s32     d6,  q13
2363        vqmovun.s32     d7,  q14
2364        vmin.u16        q2,  q2,  q15
2365        vmin.u16        q3,  q3,  q15
2366.else
2367        vmov.i16        q9,  #PREP_BIAS
2368        vrshrn.i32      d4,  q2,  #6
2369        vrshrn.i32      d5,  q3,  #6
2370        vrshrn.i32      d6,  q13, #6
2371        vrshrn.i32      d7,  q14, #6
2372        vsub.i16        q2,  q2,  q9 // PREP_BIAS
2373        vsub.i16        q3,  q3,  q9 // PREP_BIAS
2374.endif
2375        subs            \h,  \h,  #2
2376        vst1.16         {q2}, [\dst, :128], \d_strd
2377        vst1.16         {q3}, [\ds2, :128], \d_strd
2378        ble             9f
2379        vmov            q8,  q10
2380        vmov            q9,  q11
2381        vmov            q10, q12
2382        b               8b
23839:
2384        subs            \w,  \w,  #8
2385        ble             0f
2386        asr             \s_strd,  \s_strd,  #1
2387        asr             \d_strd,  \d_strd,  #1
2388        mls             \src,  \s_strd,  \my,  \src
2389        mls             \dst,  \d_strd,  \my,  \dst
2390        sub             \src,  \src,  \s_strd,  lsl #2
2391        mov             \h,  \my
2392        add             \src,  \src,  #16
2393        add             \dst,  \dst,  #16
2394        b               164b
23950:
2396        pop             {r4-r11,pc}
2397
2398880:    // 8x8, 8x16, ..., 16x8, ..., 32x8, ... hv
2399640:
24001280:
2401        vpush           {q4-q7}
2402        vld1.8          {d0}, [\mx, :64]
2403        vld1.8          {d2}, [\my, :64]
2404        sub             \src,  \src,  #6
2405        sub             \src,  \src,  \s_strd
2406        sub             \src,  \src,  \s_strd, lsl #1
2407        vmovl.s8        q0,  d0
2408        vmovl.s8        q1,  d2
2409        mov             \my, \h
2410
2411168:
2412        add             \ds2, \dst, \d_strd
2413        add             \sr2,  \src,  \s_strd
2414        lsl             \d_strd, \d_strd, #1
2415        lsl             \s_strd, \s_strd, #1
2416
2417        vld1.16         {q11, q12}, [\src], \s_strd
2418        vmull.s16       q2,  d22, d0[0]
2419        vmull.s16       q3,  d23, d0[0]
2420        vdup.32         q14, r12      // -(6-intermediate_bits)
2421.irpc i, 1234567
2422        vext.8          q10, q11, q12, #(2*\i)
2423.if \i < 4
2424        vmlal.s16       q2,  d20, d0[\i]
2425        vmlal.s16       q3,  d21, d0[\i]
2426.else
2427        vmlal.s16       q2,  d20, d1[\i - 4]
2428        vmlal.s16       q3,  d21, d1[\i - 4]
2429.endif
2430.endr
2431        vrshl.s32       q2,  q2,  q14 // -(6-intermediate_bits)
2432        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
2433        vmovn.i32       d8,  q2
2434        vmovn.i32       d9,  q3
2435
2436        bl              L(\type\()_8tap_filter_8)
2437        vmov            q5,  q11
2438        vmov            q6,  q12
2439        bl              L(\type\()_8tap_filter_8)
2440        vmov            q7,  q11
2441        vmov            q8,  q12
2442        bl              L(\type\()_8tap_filter_8)
2443        vmov            q9,  q11
2444        vmov            q10, q12
2445
244688:
2447        bl              L(\type\()_8tap_filter_8)
2448        vmull.s16       q2,  d8,  d2[0]
2449        vmull.s16       q3,  d9,  d2[0]
2450        vmull.s16       q13, d10, d2[0]
2451        vmull.s16       q14, d11, d2[0]
2452.ifc \type, put
2453        vdup.32         q4,  r8      // -(6+intermediate_bits)
2454.endif
2455        vmlal.s16       q2,  d10, d2[1]
2456        vmlal.s16       q3,  d11, d2[1]
2457        vmlal.s16       q13, d12, d2[1]
2458        vmlal.s16       q14, d13, d2[1]
2459        vmlal.s16       q2,  d12, d2[2]
2460        vmlal.s16       q3,  d13, d2[2]
2461        vmlal.s16       q13, d14, d2[2]
2462        vmlal.s16       q14, d15, d2[2]
2463        vmlal.s16       q2,  d14, d2[3]
2464        vmlal.s16       q3,  d15, d2[3]
2465        vmlal.s16       q13, d16, d2[3]
2466        vmlal.s16       q14, d17, d2[3]
2467        vmlal.s16       q2,  d16, d3[0]
2468        vmlal.s16       q3,  d17, d3[0]
2469        vmlal.s16       q13, d18, d3[0]
2470        vmlal.s16       q14, d19, d3[0]
2471        vmlal.s16       q2,  d18, d3[1]
2472        vmlal.s16       q3,  d19, d3[1]
2473        vmlal.s16       q13, d20, d3[1]
2474        vmlal.s16       q14, d21, d3[1]
2475        vmlal.s16       q2,  d20, d3[2]
2476        vmlal.s16       q3,  d21, d3[2]
2477        vmlal.s16       q13, d22, d3[2]
2478        vmlal.s16       q14, d23, d3[2]
2479        vmlal.s16       q2,  d22, d3[3]
2480        vmlal.s16       q3,  d23, d3[3]
2481        vmlal.s16       q13, d24, d3[3]
2482        vmlal.s16       q14, d25, d3[3]
2483.ifc \type, put
2484        vrshl.s32       q2,  q2,  q4 // -(6+intermediate_bits)
2485        vrshl.s32       q3,  q3,  q4 // -(6+intermediate_bits)
2486        vrshl.s32       q13, q13, q4 // -(6+intermediate_bits)
2487        vrshl.s32       q14, q14, q4 // -(6+intermediate_bits)
2488        vqmovun.s32     d4,  q2
2489        vqmovun.s32     d5,  q3
2490        vqmovun.s32     d6,  q13
2491        vqmovun.s32     d7,  q14
2492        vmin.u16        q2,  q2,  q15
2493        vmin.u16        q3,  q3,  q15
2494.else
2495        vmov.i16        q5,  #PREP_BIAS
2496        vrshrn.i32      d4,  q2,  #6
2497        vrshrn.i32      d5,  q3,  #6
2498        vrshrn.i32      d6,  q13, #6
2499        vrshrn.i32      d7,  q14, #6
2500        vsub.i16        q2,  q2,  q5 // PREP_BIAS
2501        vsub.i16        q3,  q3,  q5 // PREP_BIAS
2502.endif
2503        subs            \h,  \h,  #2
2504        vst1.16         {q2}, [\dst, :128], \d_strd
2505        vst1.16         {q3}, [\ds2, :128], \d_strd
2506        ble             9f
2507        vmov            q4,  q6
2508        vmov            q5,  q7
2509        vmov            q6,  q8
2510        vmov            q7,  q9
2511        vmov            q8,  q10
2512        vmov            q9,  q11
2513        vmov            q10, q12
2514        b               88b
25159:
2516        subs            \w,  \w,  #8
2517        ble             0f
2518        asr             \s_strd,  \s_strd,  #1
2519        asr             \d_strd,  \d_strd,  #1
2520        mls             \src,  \s_strd,  \my,  \src
2521        mls             \dst,  \d_strd,  \my,  \dst
2522        sub             \src,  \src,  \s_strd,  lsl #3
2523        mov             \h,  \my
2524        add             \src,  \src,  #16
2525        add             \dst,  \dst,  #16
2526        b               168b
25270:
2528        vpop            {q4-q7}
2529        pop             {r4-r11,pc}
2530
2531L(\type\()_8tap_filter_8):
2532        vld1.16         {q13, q14}, [\sr2], \s_strd
2533        vmull.s16       q2,  d26, d0[0]
2534        vmull.s16       q3,  d27, d0[0]
2535.irpc i, 1234567
2536        vext.8          q12, q13, q14, #(2*\i)
2537.if \i < 4
2538        vmlal.s16       q2,  d24, d0[\i]
2539        vmlal.s16       q3,  d25, d0[\i]
2540.else
2541        vmlal.s16       q2,  d24, d1[\i - 4]
2542        vmlal.s16       q3,  d25, d1[\i - 4]
2543.endif
2544.endr
2545        vdup.32         q12, r12      // -(6-intermediate_bits)
2546        vld1.16         {q13, q14}, [\src], \s_strd
2547        vrshl.s32       q2,  q2,  q12 // -(6-intermediate_bits)
2548        vrshl.s32       q3,  q3,  q12 // -(6-intermediate_bits)
2549        vmovn.i32       d4,  q2
2550        vmovn.i32       d5,  q3
2551
2552        vmull.s16       q3,  d26, d0[0]
2553        vmull.s16       q11, d27, d0[0]
2554.irpc i, 1234567
2555        vext.8          q12, q13, q14, #(2*\i)
2556.if \i < 4
2557        vmlal.s16       q3,  d24, d0[\i]
2558        vmlal.s16       q11, d25, d0[\i]
2559.else
2560        vmlal.s16       q3,  d24, d1[\i - 4]
2561        vmlal.s16       q11, d25, d1[\i - 4]
2562.endif
2563.endr
2564        vdup.32         q13, r12      // -(6-intermediate_bits)
2565        vrshl.s32       q3,  q3,  q13 // -(6-intermediate_bits)
2566        vrshl.s32       q11, q11, q13 // -(6-intermediate_bits)
2567
2568        vmovn.i32       d24, q3
2569        vmovn.i32       d25, q11
2570        vmov            q11, q2
2571        bx              lr
2572endfunc
2573
2574function \type\()_bilin_16bpc_neon, export=1
2575        push            {r4-r11,lr}
2576        ldrd            r4,  r5,  [sp, #36]
2577        ldrd            r6,  r7,  [sp, #44]
2578.ifc \bdmax, r8
2579        ldr             r8,  [sp, #52]
2580.endif
2581        vdup.16         q1,  \mx
2582        vdup.16         q3,  \my
2583        rsb             r9,  \mx, #16
2584        rsb             r10, \my, #16
2585        vdup.16         q0,  r9
2586        vdup.16         q2,  r10
2587.ifc \type, prep
2588        lsl             \d_strd, \w, #1
2589.endif
2590        clz             \bdmax,   \bdmax       // bitdepth_max
2591        clz             r9,  \w
2592        sub             \bdmax,   \bdmax,  #18 // intermediate_bits = clz(bitdepth_max) - 18
2593        cmp             \mx, #0
2594        sub             r9,  r9,  #24
2595        rsb             r11, \bdmax, #4        // 4 - intermediate_bits
2596        add             r12, \bdmax, #4        // 4 + intermediate_bits
2597        bne             L(\type\()_bilin_h)
2598        cmp             \my, #0
2599        bne             L(\type\()_bilin_v)
2600        b               \type\()_neon
2601
2602L(\type\()_bilin_h):
2603        cmp             \my, #0
2604        bne             L(\type\()_bilin_hv)
2605
2606        adr             r10, L(\type\()_bilin_h_tbl)
2607        vdup.16         q15, r11               // 4 - intermediate_bits
2608        ldr             r9,  [r10, r9, lsl #2]
2609        vneg.s16        q15, q15               // -(4-intermediate_bits)
2610.ifc \type, put
2611        vdup.16         q14, \bdmax            // intermediate_bits
2612.else
2613        vmov.i16        q14, #PREP_BIAS
2614.endif
2615        add             r10, r10, r9
2616.ifc \type, put
2617        vneg.s16        q14, q14               // -intermediate_bits
2618.endif
2619        bx              r10
2620
2621        .align 2
2622L(\type\()_bilin_h_tbl):
2623        .word 1280f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2624        .word 640f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2625        .word 320f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2626        .word 160f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2627        .word 80f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2628        .word 40f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2629        .word 20f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2630
263120:     // 2xN h
2632.ifc \type, put
2633        add             \ds2,  \dst,  \d_strd
2634        add             \sr2,  \src,  \s_strd
2635        lsl             \d_strd,  \d_strd,  #1
2636        lsl             \s_strd,  \s_strd,  #1
26372:
2638        vld1.16         {d16}, [\src], \s_strd
2639        vld1.16         {d18}, [\sr2], \s_strd
2640        vext.8          d17, d16, d16, #2
2641        vext.8          d19, d18, d18, #2
2642        vtrn.32         d16, d18
2643        vtrn.32         d17, d19
2644        subs            \h,  \h,  #2
2645        vmul.i16        d16, d16, d0
2646        vmla.i16        d16, d17, d2
2647        vrshl.u16       d16, d16, d30
2648        vrshl.u16       d16, d16, d28
2649        vst1.32         {d16[0]}, [\dst, :32], \d_strd
2650        vst1.32         {d16[1]}, [\ds2, :32], \d_strd
2651        bgt             2b
2652        pop             {r4-r11,pc}
2653.endif
2654
265540:     // 4xN h
2656        add             \ds2,  \dst,  \d_strd
2657        add             \sr2,  \src,  \s_strd
2658        lsl             \d_strd,  \d_strd,  #1
2659        lsl             \s_strd,  \s_strd,  #1
26604:
2661        vld1.16         {q8},  [\src], \s_strd
2662        vld1.16         {q10}, [\sr2], \s_strd
2663        vext.8          q9,  q8,  q8,  #2
2664        vext.8          q11, q10, q10, #2
2665        vmov            d17, d20
2666        vmov            d19, d22
2667        subs            \h,  \h,  #2
2668        vmul.i16        q8,  q8,  q0
2669        vmla.i16        q8,  q9,  q1
2670        vrshl.u16       q8,  q8,  q15
2671.ifc \type, put
2672        vrshl.u16       q8,  q8,  q14
2673.else
2674        vsub.i16        q8,  q8,  q14
2675.endif
2676        vst1.16         {d16}, [\dst, :64], \d_strd
2677        vst1.16         {d17}, [\ds2, :64], \d_strd
2678        bgt             4b
2679        pop             {r4-r11,pc}
2680
268180:     // 8xN h
2682        add             \ds2,  \dst,  \d_strd
2683        add             \sr2,  \src,  \s_strd
2684        lsl             \d_strd,  \d_strd,  #1
2685        lsl             \s_strd,  \s_strd,  #1
26868:
2687        vld1.16         {d16, d17, d18}, [\src], \s_strd
2688        vld1.16         {d20, d21, d22}, [\sr2], \s_strd
2689        vext.8          q9,  q8,  q9,  #2
2690        vext.8          q11, q10, q11, #2
2691        subs            \h,  \h,  #2
2692        vmul.i16        q8,  q8,  q0
2693        vmla.i16        q8,  q9,  q1
2694        vmul.i16        q10, q10, q0
2695        vmla.i16        q10, q11, q1
2696        vrshl.u16       q8,  q8,  q15
2697        vrshl.u16       q10, q10, q15
2698.ifc \type, put
2699        vrshl.u16       q8,  q8,  q14
2700        vrshl.u16       q10, q10, q14
2701.else
2702        vsub.i16        q8,  q8,  q14
2703        vsub.i16        q10, q10, q14
2704.endif
2705        vst1.16         {q8},  [\dst, :128], \d_strd
2706        vst1.16         {q10}, [\ds2, :128], \d_strd
2707        bgt             8b
2708        pop             {r4-r11,pc}
2709160:
2710320:
2711640:
27121280:   // 16xN, 32xN, ... h
2713        vpush           {q4-q7}
2714        add             \ds2,  \dst,  \d_strd
2715        add             \sr2,  \src,  \s_strd
2716        lsl             \s_strd,  \s_strd,  #1
2717
2718        sub             \s_strd,  \s_strd,  \w, lsl #1
2719        sub             \s_strd,  \s_strd,  #16
2720.ifc \type, put
2721        lsl             \d_strd,  \d_strd,  #1
2722        sub             \d_strd,  \d_strd,  \w, lsl #1
2723.endif
2724161:
2725        vld1.16         {q4}, [\src]!
2726        vld1.16         {q9}, [\sr2]!
2727        mov             \mx, \w
2728
272916:
2730        vld1.16         {q5,  q6},  [\src]!
2731        vld1.16         {q10, q11}, [\sr2]!
2732        vext.8          q7,  q4,  q5,  #2
2733        vext.8          q8,  q5,  q6,  #2
2734        vext.8          q12, q9,  q10, #2
2735        vext.8          q13, q10, q11, #2
2736        vmul.i16        q4,  q4,  q0
2737        vmla.i16        q4,  q7,  q1
2738        vmul.i16        q5,  q5,  q0
2739        vmla.i16        q5,  q8,  q1
2740        vmul.i16        q9,  q9,  q0
2741        vmla.i16        q9,  q12, q1
2742        vmul.i16        q10, q10, q0
2743        vmla.i16        q10, q13, q1
2744        vrshl.u16       q4,  q4,  q15
2745        vrshl.u16       q5,  q5,  q15
2746        vrshl.u16       q9,  q9,  q15
2747        vrshl.u16       q10, q10, q15
2748        subs            \mx, \mx, #16
2749.ifc \type, put
2750        vrshl.u16       q4,  q4,  q14
2751        vrshl.u16       q5,  q5,  q14
2752        vrshl.u16       q9,  q9,  q14
2753        vrshl.u16       q10, q10, q14
2754.else
2755        vsub.i16        q4,  q4,  q14
2756        vsub.i16        q5,  q5,  q14
2757        vsub.i16        q9,  q9,  q14
2758        vsub.i16        q10, q10, q14
2759.endif
2760        vst1.16         {q4, q5},  [\dst, :128]!
2761        vst1.16         {q9, q10}, [\ds2, :128]!
2762        ble             9f
2763
2764        vmov            q4,  q6
2765        vmov            q9,  q11
2766        b               16b
2767
27689:
2769        add             \dst,  \dst,  \d_strd
2770        add             \ds2,  \ds2,  \d_strd
2771        add             \src,  \src,  \s_strd
2772        add             \sr2,  \sr2,  \s_strd
2773
2774        subs            \h,  \h,  #2
2775        bgt             161b
2776        vpop            {q4-q7}
2777        pop             {r4-r11,pc}
2778
2779
2780L(\type\()_bilin_v):
2781        cmp             \h,  #4
2782        adr             r10, L(\type\()_bilin_v_tbl)
2783.ifc \type, prep
2784        vdup.16         q15, r11      // 4 - intermediate_bits
2785.endif
2786        ldr             r9,  [r10, r9, lsl #2]
2787.ifc \type, prep
2788        vmov.i16        q14, #PREP_BIAS
2789        vneg.s16        q15, q15      // -(4-intermediate_bits)
2790.endif
2791        add             r10, r10, r9
2792        bx              r10
2793
2794        .align 2
2795L(\type\()_bilin_v_tbl):
2796        .word 1280f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2797        .word 640f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2798        .word 320f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2799        .word 160f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2800        .word 80f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2801        .word 40f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2802        .word 20f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2803
280420:     // 2xN v
2805.ifc \type, put
2806        cmp             \h,  #2
2807        add             \ds2,  \dst,  \d_strd
2808        add             \sr2,  \src,  \s_strd
2809        lsl             \s_strd,  \s_strd,  #1
2810        lsl             \d_strd,  \d_strd,  #1
2811
2812        // 2x2 v
2813        vld1.32         {d16[]}, [\src], \s_strd
2814        bgt             24f
281522:
2816        vld1.32         {d17[]}, [\sr2], \s_strd
2817        vld1.32         {d18[]}, [\src], \s_strd
2818        vext.8          d16, d16, d17, #4
2819        vext.8          d17, d17, d18, #4
2820        vmul.i16        d16, d16, d4
2821        vmla.i16        d16, d17, d6
2822        vrshr.u16       d16, d16, #4
2823        vst1.32         {d16[0]}, [\dst, :32]
2824        vst1.32         {d16[1]}, [\ds2, :32]
2825        pop             {r4-r11,pc}
282624:     // 2x4, 2x6, 2x8, ... v
2827        vld1.32         {d17[]}, [\sr2], \s_strd
2828        vld1.32         {d18[]}, [\src], \s_strd
2829        vld1.32         {d19[]}, [\sr2], \s_strd
2830        vld1.32         {d20[]}, [\src], \s_strd
2831        subs            \h,  \h,  #4
2832        vext.8          d16, d16, d17, #4
2833        vext.8          d17, d17, d18, #4
2834        vext.8          d18, d18, d19, #4
2835        vext.8          d19, d19, d20, #4
2836        vswp            d17, d18
2837        vmul.i16        q8,  q8,  q2
2838        vmla.i16        q8,  q9,  q3
2839        cmp             \h,  #2
2840        vrshr.u16       q8,  q8,  #4
2841        vst1.32         {d16[0]}, [\dst, :32], \d_strd
2842        vst1.32         {d16[1]}, [\ds2, :32], \d_strd
2843        vst1.32         {d17[0]}, [\dst, :32], \d_strd
2844        vst1.32         {d17[1]}, [\ds2, :32], \d_strd
2845        blt             0f
2846        vmov            d16, d20
2847        beq             22b
2848        b               24b
28490:
2850        pop             {r4-r11,pc}
2851.endif
2852
285340:     // 4xN v
2854        add             \ds2,  \dst,  \d_strd
2855        add             \sr2,  \src,  \s_strd
2856        lsl             \s_strd,  \s_strd,  #1
2857        lsl             \d_strd,  \d_strd,  #1
2858        vld1.16         {d16}, [\src], \s_strd
28594:
2860        vld1.16         {d17}, [\sr2], \s_strd
2861        vld1.16         {d19}, [\src], \s_strd
2862        vmov            d18, d17
2863        vmul.i16        q8,  q8,  q2
2864        vmla.i16        q8,  q9,  q3
2865        subs            \h,  \h,  #2
2866.ifc \type, put
2867        vrshr.u16       q8,  q8,  #4
2868.else
2869        vrshl.u16       q8,  q8,  q15
2870        vsub.i16        q8,  q8,  q14
2871.endif
2872        vst1.16         {d16}, [\dst, :64], \d_strd
2873        vst1.16         {d17}, [\ds2, :64], \d_strd
2874        ble             0f
2875        vmov            d16, d19
2876        b               4b
28770:
2878        pop             {r4-r11,pc}
2879
288080:     // 8xN v
2881        add             \ds2,  \dst,  \d_strd
2882        add             \sr2,  \src,  \s_strd
2883        lsl             \s_strd,  \s_strd,  #1
2884        lsl             \d_strd,  \d_strd,  #1
2885        vld1.16         {q8},  [\src], \s_strd
28868:
2887        vld1.16         {q9},  [\sr2], \s_strd
2888        vld1.16         {q10}, [\src], \s_strd
2889        vmul.i16        q8,  q8,  q2
2890        vmla.i16        q8,  q9,  q3
2891        vmul.i16        q9,  q9,  q2
2892        vmla.i16        q9,  q10, q3
2893        subs            \h,  \h,  #2
2894.ifc \type, put
2895        vrshr.u16       q8,  q8,  #4
2896        vrshr.u16       q9,  q9,  #4
2897.else
2898        vrshl.u16       q8,  q8,  q15
2899        vrshl.u16       q9,  q9,  q15
2900        vsub.i16        q8,  q8,  q14
2901        vsub.i16        q9,  q9,  q14
2902.endif
2903        vst1.16         {q8}, [\dst, :128], \d_strd
2904        vst1.16         {q9}, [\ds2, :128], \d_strd
2905        ble             0f
2906        vmov            q8,  q10
2907        b               8b
29080:
2909        pop             {r4-r11,pc}
2910
2911160:    // 16xN, 32xN, ...
2912320:
2913640:
29141280:
2915        mov             \my, \h
29161:
2917        add             \ds2, \dst, \d_strd
2918        add             \sr2, \src, \s_strd
2919        lsl             \s_strd, \s_strd, #1
2920        lsl             \d_strd, \d_strd, #1
2921
2922        vld1.16         {q8,  q9},  [\src], \s_strd
29232:
2924        vld1.16         {q10, q11}, [\sr2], \s_strd
2925        vld1.16         {q12, q13}, [\src], \s_strd
2926        vmul.i16        q8,  q8,  q2
2927        vmla.i16        q8,  q10, q3
2928        vmul.i16        q9,  q9,  q2
2929        vmla.i16        q9,  q11, q3
2930        vmul.i16        q10, q10, q2
2931        vmla.i16        q10, q12, q3
2932        vmul.i16        q11, q11, q2
2933        vmla.i16        q11, q13, q3
2934        subs            \h,  \h,  #2
2935.ifc \type, put
2936        vrshr.u16       q8,  q8,  #4
2937        vrshr.u16       q9,  q9,  #4
2938        vrshr.u16       q10, q10, #4
2939        vrshr.u16       q11, q11, #4
2940.else
2941        vrshl.u16       q8,  q8,  q15
2942        vrshl.u16       q9,  q9,  q15
2943        vrshl.u16       q10, q10, q15
2944        vrshl.u16       q11, q11, q15
2945        vsub.i16        q8,  q8,  q14
2946        vsub.i16        q9,  q9,  q14
2947        vsub.i16        q10, q10, q14
2948        vsub.i16        q11, q11, q14
2949.endif
2950        vst1.16         {q8,  q9},  [\dst, :128], \d_strd
2951        vst1.16         {q10, q11}, [\ds2, :128], \d_strd
2952        ble             9f
2953        vmov            q8,  q12
2954        vmov            q9,  q13
2955        b               2b
29569:
2957        subs            \w,  \w,  #16
2958        ble             0f
2959        asr             \s_strd, \s_strd, #1
2960        asr             \d_strd, \d_strd, #1
2961        mls             \src, \s_strd, \my, \src
2962        mls             \dst, \d_strd, \my, \dst
2963        sub             \src, \src, \s_strd, lsl #1
2964        mov             \h,  \my
2965        add             \src, \src, #32
2966        add             \dst, \dst, #32
2967        b               1b
29680:
2969        pop             {r4-r11,pc}
2970
2971L(\type\()_bilin_hv):
2972        adr             r10, L(\type\()_bilin_hv_tbl)
2973        vdup.16         q15, r11          // 4 - intermediate_bits
2974        ldr             r9,  [r10, r9, lsl #2]
2975        vneg.s16        q15, q15          // -(4-intermediate_bits)
2976.ifc \type, put
2977        vdup.32         q14, r12          // 4 + intermediate_bits
2978.else
2979        vmov.i16        q14, #PREP_BIAS
2980.endif
2981        add             r10, r10, r9
2982.ifc \type, put
2983        vneg.s32        q14, q14          // -(4+intermediate_bits)
2984.endif
2985        bx              r10
2986
2987        .align 2
2988L(\type\()_bilin_hv_tbl):
2989        .word 1280f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2990        .word 640f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2991        .word 320f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2992        .word 160f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2993        .word 80f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2994        .word 40f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2995        .word 20f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2996
299720:     // 2xN hv
2998.ifc \type, put
2999        add             \sr2, \src, \s_strd
3000        add             \ds2, \dst, \d_strd
3001        lsl             \s_strd, \s_strd, #1
3002        lsl             \d_strd, \d_strd, #1
3003
3004        vld1.16         {d20}, [\src], \s_strd
3005        vext.8          d21, d20, d20, #2
3006        vmul.i16        d16, d20, d0
3007        vmla.i16        d16, d21, d2
3008        vrshl.u16       d16, d16, d30
3009        vext.8          d16, d16, d16, #4
3010
30112:
3012        vld1.16         {d20}, [\sr2], \s_strd
3013        vld1.16         {d22}, [\src], \s_strd
3014        vext.8          d21, d20, d20, #2
3015        vext.8          d23, d22, d22, #2
3016        vtrn.32         d20, d22
3017        vtrn.32         d21, d23
3018        vmul.i16        d18, d20, d0
3019        vmla.i16        d18, d21, d2
3020        vrshl.u16       d18, d18, d30
3021
3022        vext.8          d16, d16, d18, #4
3023
3024        vmull.u16       q8,  d16, d4
3025        vmlal.u16       q8,  d18, d6
3026        vrshl.u32       q8,  q8,  q14
3027        vmovn.i32       d16, q8
3028        subs            \h,  \h,  #2
3029        vst1.32         {d16[0]}, [\dst, :32], \d_strd
3030        vst1.32         {d16[1]}, [\ds2, :32], \d_strd
3031        ble             0f
3032        vmov            d16, d18
3033        b               2b
30340:
3035        pop             {r4-r11,pc}
3036.endif
3037
303840:     // 4xN hv
3039        add             \sr2, \src, \s_strd
3040        add             \ds2, \dst, \d_strd
3041        lsl             \s_strd, \s_strd, #1
3042        lsl             \d_strd, \d_strd, #1
3043
3044        vld1.16         {q10}, [\src], \s_strd
3045        vext.8          d21, d20, d21, #2
3046        vmul.i16        d16, d20, d0
3047        vmla.i16        d16, d21, d2
3048        vrshl.u16       d16, d16, d30
3049
30504:
3051        vld1.16         {q10}, [\sr2], \s_strd
3052        vld1.16         {q11}, [\src], \s_strd
3053        vext.8          d21, d20, d21, #2
3054        vext.8          d23, d22, d23, #2
3055        vswp            d21, d22
3056        vmul.i16        q9,  q10, q0
3057        vmla.i16        q9,  q11, q1
3058        vrshl.u16       q9,  q9,  q15
3059
3060        vmull.u16       q10, d16, d4
3061        vmlal.u16       q10, d18, d6
3062        vmull.u16       q11, d18, d4
3063        vmlal.u16       q11, d19, d6
3064.ifc \type, put
3065        vrshl.u32       q10, q10, q14
3066        vrshl.u32       q11, q11, q14
3067        vmovn.i32       d20, q10
3068        vmovn.i32       d21, q11
3069.else
3070        vrshrn.i32      d20, q10, #4
3071        vrshrn.i32      d21, q11, #4
3072        vsub.i16        q10, q10, q14
3073.endif
3074        subs            \h,  \h,  #2
3075        vst1.16         {d20}, [\dst, :64], \d_strd
3076        vst1.16         {d21}, [\ds2, :64], \d_strd
3077        ble             0f
3078        vmov            d16, d19
3079        b               4b
30800:
3081        pop             {r4-r11,pc}
3082
308380:     // 8xN, 16xN, ... hv
3084160:
3085320:
3086640:
30871280:
3088        mov             \my, \h
3089
30901:
3091        add             \sr2, \src, \s_strd
3092        add             \ds2, \dst, \d_strd
3093        lsl             \s_strd, \s_strd, #1
3094        lsl             \d_strd, \d_strd, #1
3095
3096        vld1.16         {d20, d21, d22}, [\src], \s_strd
3097        vext.8          q11, q10, q11, #2
3098        vmul.i16        q8,  q10, q0
3099        vmla.i16        q8,  q11, q1
3100        vrshl.u16       q8,  q8,  q15
3101
31022:
3103        vld1.16         {d20, d21, d22}, [\sr2], \s_strd
3104        vld1.16         {d24, d25, d26}, [\src], \s_strd
3105        vext.8          q11, q10, q11, #2
3106        vext.8          q13, q12, q13, #2
3107        vmul.i16        q9,  q10, q0
3108        vmla.i16        q9,  q11, q1
3109        vmul.i16        q10, q12, q0
3110        vmla.i16        q10, q13, q1
3111        vrshl.u16       q9,  q9,  q15
3112        vrshl.u16       q10, q10, q15
3113
3114        vmull.u16       q11, d16, d4
3115        vmlal.u16       q11, d18, d6
3116        vmull.u16       q12, d17, d4
3117        vmlal.u16       q12, d19, d6
3118        vmull.u16       q8,  d18, d4
3119        vmlal.u16       q8,  d20, d6
3120        vmull.u16       q9,  d19, d4
3121        vmlal.u16       q9,  d21, d6
3122.ifc \type, put
3123        vrshl.u32       q11, q11, q14
3124        vrshl.u32       q12, q12, q14
3125        vrshl.u32       q8,  q8,  q14
3126        vrshl.u32       q9,  q9,  q14
3127        vmovn.i32       d22, q11
3128        vmovn.i32       d23, q12
3129        vmovn.i32       d16, q8
3130        vmovn.i32       d17, q9
3131.else
3132        vrshrn.i32      d22, q11, #4
3133        vrshrn.i32      d23, q12, #4
3134        vrshrn.i32      d16, q8,  #4
3135        vrshrn.i32      d17, q9,  #4
3136        vsub.i16        q11, q11, q14
3137        vsub.i16        q8,  q8,  q14
3138.endif
3139        subs            \h,  \h,  #2
3140        vst1.16         {q11}, [\dst, :128], \d_strd
3141        vst1.16         {q8},  [\ds2, :128], \d_strd
3142        ble             9f
3143        vmov            q8,  q10
3144        b               2b
31459:
3146        subs            \w,  \w,  #8
3147        ble             0f
3148        asr             \s_strd,  \s_strd,  #1
3149        asr             \d_strd,  \d_strd,  #1
3150        mls             \src,  \s_strd,  \my,  \src
3151        mls             \dst,  \d_strd,  \my,  \dst
3152        sub             \src,  \src,  \s_strd,  lsl #1
3153        mov             \h,  \my
3154        add             \src,  \src,  #16
3155        add             \dst,  \dst,  #16
3156        b               1b
31570:
3158        pop             {r4-r11,pc}
3159endfunc
3160.endm
3161
3162filter_fn put,  r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10
3163filter_fn prep, r0, r8, r1, r2, r3, r4, r5, r6, r7, r9, r10
3164
3165.macro load_filter_ptr src
3166        asr             r12, \src, #10
3167        add             r12, r11, r12, lsl #3
3168.endm
3169
3170.macro load_filter_coef dst, src, inc
3171        add             \src, \src, \inc
3172        vld1.8          {\dst}, [r12, :64]
3173.endm
3174
3175.macro load_filter_row dst, src, inc
3176        load_filter_ptr \src
3177        load_filter_coef \dst, \src, \inc
3178.endm
3179
3180function warp_filter_horz_neon
3181        load_filter_ptr r5                  // filter 0
3182        vld1.16         {q6,q7}, [r2], r3
3183
3184        load_filter_coef d0, r5,  r7        // filter 0
3185        load_filter_row d2,  r5,  r7        // filter 1
3186        vmovl.s8        q0,  d0             // filter 0
3187        vext.8          q3,  q6,  q7,  #2*1 // filter 1 pixels
3188        vmovl.s8        q1,  d2             // filter 1
3189
3190        vmull.s16       q4,  d12, d0        // filter 0 output (0-3)
3191        vmull.s16       q5,  d13, d1        // filter 0 output (4-7)
3192
3193        load_filter_ptr r5                  // filter 2
3194
3195        vmull.s16       q2,  d6,  d2        // filter 1 output (0-3)
3196        vmull.s16       q3,  d7,  d3        // filter 1 output (4-7)
3197
3198        load_filter_coef d0, r5,  r7        // filter 2
3199
3200        vpadd.i32       d8,  d8,  d9        // half pixel 0 (2x32)
3201        vpadd.i32       d9,  d10, d11       // half pixel 0 (2x32)
3202
3203        load_filter_ptr r5                  // filter 3
3204
3205        vpadd.i32       d4,  d4,  d5        // half pixel 1 (2x32)
3206        vpadd.i32       d5,  d6,  d7        // half pixel 1 (2x32)
3207
3208        vmovl.s8        q0,  d0             // filter 2
3209        vext.8          q3,  q6,  q7,  #2*2 // filter 2 pixels
3210
3211        vpadd.i32       d8,  d8,  d9        // pixel 0 (2x32)
3212        vpadd.i32       d9,  d4,  d5        // pixel 1 (2x32)
3213
3214        load_filter_coef d2, r5,  r7        // filter 3
3215
3216        vmull.s16       q2,  d6,  d0        // filter 2 output (0-3)
3217        vmull.s16       q3,  d7,  d1        // filter 2 output (4-7)
3218
3219        load_filter_ptr r5                  // filter 4
3220
3221        vpadd.i32       d8,  d8,  d9        // pixel 0,1
3222
3223        vpadd.i32       d9,  d4,  d5        // half pixel 2 (2x32)
3224        vpadd.i32       d10, d6,  d7        // half pixel 2 (2x32)
3225
3226        vmovl.s8        q1,  d2             // filter 3
3227        vext.8          q3,  q6,  q7,  #2*3 // filter 3 pixels
3228
3229        load_filter_coef d0, r5,  r7        // filter 4
3230
3231        vpadd.i32       d9,  d9,  d10       // pixel 2 (2x32)
3232
3233        vmull.s16       q2,  d6,  d2        // filter 3 output (0-3)
3234        vmull.s16       q3,  d7,  d3        // filter 3 output (4-7)
3235
3236        vmovl.s8        q0,  d0             // filter 4
3237        load_filter_ptr r5                  // filter 5
3238
3239        vpadd.i32       d10, d4,  d5        // half pixel 3 (2x32)
3240        vpadd.i32       d11, d6,  d7        // half pixel 3 (2x32)
3241
3242        vext.8          q3,  q6,  q7,  #2*4 // filter 4 pixels
3243        load_filter_coef d2, r5,  r7        // filter 5
3244
3245        vpadd.i32       d10, d10, d11       // pixel 3 (2x32)
3246
3247        vpadd.i32       d9,  d9,  d10       // pixel 2,3
3248
3249        vmull.s16       q2,  d6,  d0        // filter 4 output (0-3)
3250        vmull.s16       q3,  d7,  d1        // filter 4 output (4-7)
3251
3252        vmovl.s8        q1,  d2             // filter 5
3253        load_filter_ptr r5                  // filter 6
3254
3255        vpadd.i32       d10, d4,  d5        // half pixel 4 (2x32)
3256        vpadd.i32       d11, d6,  d7        // half pixel 4 (2x32)
3257
3258        vext.8          q3,  q6,  q7,  #2*5 // filter 5 pixels
3259        load_filter_coef d0, r5,  r7        // filter 6
3260
3261        vpadd.i32       d10, d10, d11       // pixel 4 (2x32)
3262
3263        vmull.s16       q2,  d6,  d2        // filter 5 output (0-3)
3264        vmull.s16       q3,  d7,  d3        // filter 5 output (4-7)
3265
3266        vmovl.s8        q0,  d0             // filter 6
3267        load_filter_ptr r5                  // filter 7
3268
3269        vpadd.i32       d4,  d4,  d5        // half pixel 5 (2x32)
3270        vpadd.i32       d5,  d6,  d7        // half pixel 5 (2x32)
3271
3272        vext.8          q3,  q6,  q7,  #2*6 // filter 6 pixels
3273        load_filter_coef d2, r5,  r7        // filter 7
3274
3275        vpadd.i32       d11, d4,  d5        // pixel 5 (2x32)
3276
3277        vmull.s16       q2,  d6,  d0        // filter 6 output (0-3)
3278        vmull.s16       q3,  d7,  d1        // filter 6 output (4-7)
3279
3280        vmovl.s8        q1,  d2             // filter 7
3281
3282        vpadd.i32       d10, d10, d11       // pixel 4,5
3283
3284        vpadd.i32       d4,  d4,  d5        // half pixel 6 (2x32)
3285        vpadd.i32       d5,  d6,  d7        // half pixel 6 (2x32)
3286
3287        vext.8          q3,  q6,  q7,  #2*7 // filter 7 pixels
3288
3289        vpadd.i32       d11, d4,  d5        // pixel 6 (2x32)
3290
3291        vmull.s16       q2,  d6,  d2        // filter 7 output (0-3)
3292        vmull.s16       q3,  d7,  d3        // filter 7 output (4-7)
3293
3294        vld1.32         {d14[],d15[]}, [sp] // -(7 - intermediate_bits)
3295
3296        vpadd.i32       d4,  d4,  d5        // half pixel 7 (2x32)
3297        vpadd.i32       d5,  d6,  d7        // half pixel 7 (2x32)
3298
3299        sub             r5,  r5,  r7, lsl #3
3300
3301        vpadd.i32       d4,  d4,  d5        // pixel 7 (2x32)
3302
3303        add             r5,  r5,  r8
3304
3305        vpadd.i32       d11, d11, d4        // pixel 6,7
3306
3307        vrshl.s32       q4,  q4,  q7        // -(7 - intermediate_bits)
3308        vrshl.s32       q5,  q5,  q7        // -(7 - intermediate_bits)
3309
3310        bx              lr
3311endfunc
3312
3313// void dav1d_warp_affine_8x8_16bpc_neon(
3314//         pixel *dst, const ptrdiff_t dst_stride,
3315//         const pixel *src, const ptrdiff_t src_stride,
3316//         const int16_t *const abcd, int mx, int my,
3317//         const int bitdepth_max)
3318.macro warp t
3319function warp_affine_8x8\t\()_16bpc_neon, export=1
3320        push            {r4-r11,lr}
3321        vpush           {q4-q7}
3322        ldrd            r4,  r5,  [sp, #100]
3323        ldrd            r6,  r7,  [sp, #108]
3324        sub             sp,  sp,  #8
3325
3326        clz             r7,  r7
3327                                      // intermediate_bits = clz(bitdepth_max) - 18
3328.ifb \t
3329        sub             r8,  r7,  #11 // 7 + intermediate_bits = clz(bitdepth_max) - 18 + 7
3330.endif
3331        sub             r7,  r7,  #25 // -(7 - intermediate_bits)
3332.ifb \t
3333        neg             r8,  r8       // -(7 + intermediate_bits)
3334.endif
3335        str             r7,  [sp]     // spill -(7 - intermediate_bits) on stack
3336.ifb \t
3337        str             r8,  [sp, #4] // spill -(7 + intermediate_bits) on stack
3338.endif
3339
3340        ldrd            r8,  r9,  [r4]
3341        sxth            r7,  r8
3342        asr             r8,  r8,  #16
3343        asr             r4,  r9,  #16
3344        sxth            r9,  r9
3345        mov             r10, #8
3346        sub             r2,  r2,  r3, lsl #1
3347        sub             r2,  r2,  r3
3348        sub             r2,  r2,  #6
3349        movrel          r11, X(mc_warp_filter), 64*8
3350.ifnb \t
3351        lsl             r1,  r1,  #1
3352.endif
3353        add             r5,  r5,  #512
3354        add             r6,  r6,  #512
3355
3356        bl              warp_filter_horz_neon
3357        vmovn.i32       d16, q4
3358        vmovn.i32       d17, q5
3359        bl              warp_filter_horz_neon
3360        vmovn.i32       d18, q4
3361        vmovn.i32       d19, q5
3362        bl              warp_filter_horz_neon
3363        vmovn.i32       d20, q4
3364        vmovn.i32       d21, q5
3365        bl              warp_filter_horz_neon
3366        vmovn.i32       d22, q4
3367        vmovn.i32       d23, q5
3368        bl              warp_filter_horz_neon
3369        vmovn.i32       d24, q4
3370        vmovn.i32       d25, q5
3371        bl              warp_filter_horz_neon
3372        vmovn.i32       d26, q4
3373        vmovn.i32       d27, q5
3374        bl              warp_filter_horz_neon
3375        vmovn.i32       d28, q4
3376        vmovn.i32       d29, q5
3377
33781:
3379        bl              warp_filter_horz_neon
3380        vmovn.i32       d30, q4
3381        vmovn.i32       d31, q5
3382
3383        load_filter_row d8,  r6,  r9
3384        load_filter_row d9,  r6,  r9
3385        load_filter_row d10, r6,  r9
3386        load_filter_row d11, r6,  r9
3387        load_filter_row d12, r6,  r9
3388        load_filter_row d13, r6,  r9
3389        load_filter_row d14, r6,  r9
3390        load_filter_row d15, r6,  r9
3391        transpose_8x8b  q4,  q5,  q6,  q7,  d8,  d9,  d10, d11, d12, d13, d14, d15
3392        vmovl.s8        q1,  d8
3393        vmovl.s8        q2,  d9
3394        vmovl.s8        q3,  d10
3395        vmovl.s8        q4,  d11
3396        vmovl.s8        q5,  d12
3397        vmovl.s8        q6,  d13
3398
3399        sub             r6,  r6,  r9, lsl #3
3400
3401        // This ordering of vmull/vmlal is highly beneficial for
3402        // Cortex A8/A9/A53 here, but harmful for Cortex A7.
3403        vmull.s16       q0,  d16, d2
3404        vmlal.s16       q0,  d18, d4
3405        vmlal.s16       q0,  d20, d6
3406        vmlal.s16       q0,  d22, d8
3407        vmlal.s16       q0,  d24, d10
3408        vmlal.s16       q0,  d26, d12
3409        vmull.s16       q1,  d17, d3
3410        vmlal.s16       q1,  d19, d5
3411        vmlal.s16       q1,  d21, d7
3412        vmlal.s16       q1,  d23, d9
3413        vmlal.s16       q1,  d25, d11
3414        vmlal.s16       q1,  d27, d13
3415
3416        vmovl.s8        q2,  d14
3417        vmovl.s8        q3,  d15
3418
3419        vmlal.s16       q0,  d28, d4
3420        vmlal.s16       q0,  d30, d6
3421        vmlal.s16       q1,  d29, d5
3422        vmlal.s16       q1,  d31, d7
3423
3424.ifb \t
3425        ldr             lr,  [sp, #4]   // -(7 + intermediate_bits)
3426        ldr             r12, [sp, #120] // bitdepth_max
3427        vdup.32         q2,  lr         // -(7 + intermediate_bits)
3428        vdup.16         q3,  r12        // bitdepth_max
3429.endif
3430
3431        vmov            q8,  q9
3432        vmov            q9,  q10
3433.ifb \t
3434        vrshl.s32       q0,  q0,  q2    // -(7 + intermediate_bits)
3435        vrshl.s32       q1,  q1,  q2    // -(7 + intermediate_bits)
3436.else
3437        vrshrn.s32      d0,  q0,  #7
3438        vrshrn.s32      d1,  q1,  #7
3439        vmov.i16        q3,  #PREP_BIAS
3440.endif
3441        vmov            q10, q11
3442.ifb \t
3443        vqmovun.s32     d0,  q0
3444        vqmovun.s32     d1,  q1
3445.else
3446        vsub.i16        q0,  q0,  q3    // PREP_BIAS
3447.endif
3448        vmov            q11, q12
3449        vmov            q12, q13
3450.ifb \t
3451        vmin.u16        q0,  q0,  q3    // bitdepth_max
3452.endif
3453        vmov            q13, q14
3454        vmov            q14, q15
3455        subs            r10, r10, #1
3456        vst1.16         {q0}, [r0, :128], r1
3457
3458        add             r6,  r6,  r4
3459        bgt             1b
3460
3461        add             sp,  sp,  #8
3462        vpop            {q4-q7}
3463        pop             {r4-r11,pc}
3464endfunc
3465.endm
3466
3467warp
3468warp t
3469
3470// void dav1d_emu_edge_16bpc_neon(
3471//         const intptr_t bw, const intptr_t bh,
3472//         const intptr_t iw, const intptr_t ih,
3473//         const intptr_t x, const intptr_t y,
3474//         pixel *dst, const ptrdiff_t dst_stride,
3475//         const pixel *ref, const ptrdiff_t ref_stride)
3476function emu_edge_16bpc_neon, export=1
3477        push            {r4-r11,lr}
3478        ldrd            r4,  r5,  [sp, #36]
3479        ldrd            r6,  r7,  [sp, #44]
3480        ldrd            r8,  r9,  [sp, #52]
3481
3482        // ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride)
3483        // ref += iclip(x, 0, iw - 1)
3484        sub             r12, r3,  #1           // ih - 1
3485        cmp             r5,  r3
3486        sub             lr,  r2,  #1           // iw - 1
3487        it              lt
3488        movlt           r12, r5                // min(y, ih - 1)
3489        cmp             r4,  r2
3490        bic             r12, r12, r12, asr #31 // max(min(y, ih - 1), 0)
3491        it              lt
3492        movlt           lr,  r4                // min(x, iw - 1)
3493        bic             lr,  lr,  lr,  asr #31 // max(min(x, iw - 1), 0)
3494        mla             r8,  r12, r9,  r8      // ref += iclip() * stride
3495        add             r8,  r8,  lr,  lsl #1  // ref += iclip()
3496
3497        // bottom_ext = iclip(y + bh - ih, 0, bh - 1)
3498        // top_ext = iclip(-y, 0, bh - 1)
3499        add             r10, r5,  r1           // y + bh
3500        neg             r5,  r5                // -y
3501        sub             r10, r10, r3           // y + bh - ih
3502        sub             r12, r1,  #1           // bh - 1
3503        cmp             r10, r1
3504        bic             r5,  r5,  r5,  asr #31 // max(-y, 0)
3505        it              ge
3506        movge           r10, r12               // min(y + bh - ih, bh-1)
3507        cmp             r5,  r1
3508        bic             r10, r10, r10, asr #31 // max(min(y + bh - ih, bh-1), 0)
3509        it              ge
3510        movge           r5,  r12               // min(max(-y, 0), bh-1)
3511
3512        // right_ext = iclip(x + bw - iw, 0, bw - 1)
3513        // left_ext = iclip(-x, 0, bw - 1)
3514        add             r11, r4,  r0           // x + bw
3515        neg             r4,  r4                // -x
3516        sub             r11, r11, r2           // x + bw - iw
3517        sub             lr,  r0,  #1           // bw - 1
3518        cmp             r11, r0
3519        bic             r4,  r4,  r4,  asr #31 // max(-x, 0)
3520        it              ge
3521        movge           r11, lr                // min(x + bw - iw, bw-1)
3522        cmp             r4,  r0
3523        bic             r11, r11, r11, asr #31 // max(min(x + bw - iw, bw-1), 0)
3524        it              ge
3525        movge           r4,  lr                // min(max(-x, 0), bw - 1)
3526
3527        // center_h = bh - top_ext - bottom_ext
3528        // dst += top_ext * PXSTRIDE(dst_stride)
3529        // center_w = bw - left_ext - right_ext
3530        sub             r1,  r1,  r5           // bh - top_ext
3531        mla             r6,  r5,  r7,  r6
3532        sub             r2,  r0,  r4           // bw - left_ext
3533        sub             r1,  r1,  r10          // center_h = bh - top_ext - bottom_ext
3534        sub             r2,  r2,  r11          // center_w = bw - left_ext - right_ext
3535
3536        mov             r0,  r6                // backup of dst
3537
3538.macro v_loop need_left, need_right
35390:
3540.if \need_left
3541        vld1.16         {d0[], d1[]}, [r8]
3542        mov             r12, r6                // out = dst
3543        mov             r3,  r4
3544        vmov            q1,  q0
35451:
3546        subs            r3,  r3,  #16
3547        vst1.16         {q0, q1}, [r12, :128]!
3548        bgt             1b
3549.endif
3550        mov             lr,  r8
3551        add             r12, r6,  r4,  lsl #1  // out = dst + left_ext
3552        mov             r3,  r2
35531:
3554        vld1.16         {q0, q1}, [lr]!
3555        subs            r3,  r3,  #32
3556        vld1.16         {q2, q3}, [lr]!
3557.if \need_left
3558        vst1.16         {q0, q1}, [r12]!
3559        vst1.16         {q2, q3}, [r12]!
3560.else
3561        vst1.16         {q0, q1}, [r12, :128]!
3562        vst1.16         {q2, q3}, [r12, :128]!
3563.endif
3564        bgt             1b
3565.if \need_right
3566        add             r3,  r8,  r2,  lsl #1  // in + center_w
3567        sub             r3,  r3,  #2           // in + center_w - 1
3568        add             r12, r6,  r4,  lsl #1  // dst + left_ext
3569        vld1.16         {d0[], d1[]}, [r3]
3570        add             r12, r12, r2,  lsl #1  // out = dst + left_ext + center_w
3571        mov             r3,  r11
3572        vmov            q1,  q0
35731:
3574        subs            r3,  r3,  #16
3575        vst1.16         {q0, q1}, [r12]!
3576        bgt             1b
3577.endif
3578
3579        subs            r1,  r1,  #1           // center_h--
3580        add             r6,  r6,  r7
3581        add             r8,  r8,  r9
3582        bgt             0b
3583.endm
3584
3585        cmp             r4,  #0
3586        beq             2f
3587        // need_left
3588        cmp             r11, #0
3589        beq             3f
3590        // need_left + need_right
3591        v_loop          1,   1
3592        b               5f
3593
35942:
3595        // !need_left
3596        cmp             r11, #0
3597        beq             4f
3598        // !need_left + need_right
3599        v_loop          0,   1
3600        b               5f
3601
36023:
3603        // need_left + !need_right
3604        v_loop          1,   0
3605        b               5f
3606
36074:
3608        // !need_left + !need_right
3609        v_loop          0,   0
3610
36115:
3612        cmp             r10, #0
3613        // Storing the original dst in r0 overwrote bw, recalculate it here
3614        add             r2,  r2,  r4           // center_w + left_ext
3615        add             r2,  r2,  r11          // bw = center_w + left_ext + right_ext
3616
3617        beq             3f
3618        // need_bottom
3619        sub             r8,  r6,  r7           // ref = dst - stride
3620        mov             r4,  r2
3621        sub             r12, r7,  #32
36221:
3623        vld1.16         {q0, q1}, [r8, :128]!
3624        mov             r3,  r10
3625        vld1.16         {q2, q3}, [r8, :128]!
36262:
3627        vst1.16         {q0, q1}, [r6, :128]!
3628        subs            r3,  r3,  #1
3629        vst1.16         {q2, q3}, [r6, :128], r12
3630        bgt             2b
3631        mls             r6,  r7,  r10, r6      // dst -= bottom_ext * stride
3632        subs            r4,  r4,  #32          // bw -= 32
3633        add             r6,  r6,  #64          // dst += 32
3634        bgt             1b
3635
36363:
3637        cmp             r5,  #0
3638        beq             3f
3639        // need_top
3640        mls             r6,  r7,  r5,  r0      // dst = stored_dst - top_ext * stride
3641        sub             r12, r7,  #32
36421:
3643        vld1.16         {q0, q1}, [r0, :128]!
3644        mov             r3,  r5
3645        vld1.16         {q2, q3}, [r0, :128]!
36462:
3647        vst1.16         {q0, q1}, [r6, :128]!
3648        subs            r3,  r3,  #1
3649        vst1.16         {q2, q3}, [r6, :128], r12
3650        bgt             2b
3651        mls             r6,  r7,  r5,  r6      // dst -= top_ext * stride
3652        subs            r2,  r2,  #32          // bw -= 32
3653        add             r6,  r6,  #64          // dst += 32
3654        bgt             1b
3655
36563:
3657        pop             {r4-r11,pc}
3658endfunc
3659