1/*
2 * Copyright © 2018, VideoLAN and dav1d authors
3 * Copyright © 2018, Janne Grunau
4 * Copyright © 2018, 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.macro avg dst0, dst1, t0, t1, t2, t3
33        vld1.16         {\t0,\t1},   [r2, :128]!
34        vld1.16         {\t2,\t3},   [r3, :128]!
35        vadd.i16        \t0,   \t0,  \t2
36        vadd.i16        \t1,   \t1,  \t3
37        vqrshrun.s16    \dst0, \t0,  #5
38        vqrshrun.s16    \dst1, \t1,  #5
39.endm
40
41.macro w_avg dst0, dst1, t0, t1, t2, t3
42        vld1.16         {\t0,\t1},   [r2, :128]!
43        vld1.16         {\t2,\t3},   [r3, :128]!
44        vsub.i16        \t0,   \t2,  \t0
45        vsub.i16        \t1,   \t3,  \t1
46        vqdmulh.s16     \t0,   \t0,  q15
47        vqdmulh.s16     \t1,   \t1,  q15
48        vadd.i16        \t0,   \t2,  \t0
49        vadd.i16        \t1,   \t3,  \t1
50        vqrshrun.s16    \dst0, \t0,  #4
51        vqrshrun.s16    \dst1, \t1,  #4
52.endm
53
54.macro mask dst0, dst1, t0, t1, t2, t3
55        vld1.8          {q14}, [lr, :128]!
56        vld1.16         {\t0,\t1},   [r2, :128]!
57        vmul.i8         q14,   q14,  q15
58        vld1.16         {\t2,\t3},   [r3, :128]!
59        vshll.i8        q13,   d28,  #8
60        vshll.i8        q14,   d29,  #8
61        vsub.i16        \t0,   \t2,  \t0
62        vsub.i16        \t1,   \t3,  \t1
63        vqdmulh.s16     \t0,   \t0,  q13
64        vqdmulh.s16     \t1,   \t1,  q14
65        vadd.i16        \t0,   \t2,  \t0
66        vadd.i16        \t1,   \t3,  \t1
67        vqrshrun.s16    \dst0, \t0,  #4
68        vqrshrun.s16    \dst1, \t1,  #4
69.endm
70
71.macro bidir_fn type
72function \type\()_8bpc_neon, export=1
73        push            {r4-r6,lr}
74        ldrd            r4,  r5,  [sp, #16]
75        clz             r4,  r4
76.ifnc \type, avg
77        ldr             lr, [sp, #24]
78.endif
79.ifc \type, w_avg
80        vdup.s16        q15, lr
81        vneg.s16        q15, q15
82        vshl.i16        q15, q15, #11
83.endif
84.ifc \type, mask
85        vmov.i8         q15, #256-2
86.endif
87        adr             r12, L(\type\()_tbl)
88        sub             r4,  r4,  #24
89        ldr             r4,  [r12, r4, lsl #2]
90        \type           d16, d17, q0,  q1,  q2,  q3
91        add             r12, r12, r4
92        bx              r12
93
94        .align 2
95L(\type\()_tbl):
96        .word 1280f - L(\type\()_tbl) + CONFIG_THUMB
97        .word 640f  - L(\type\()_tbl) + CONFIG_THUMB
98        .word 320f  - L(\type\()_tbl) + CONFIG_THUMB
99        .word 160f  - L(\type\()_tbl) + CONFIG_THUMB
100        .word 80f   - L(\type\()_tbl) + CONFIG_THUMB
101        .word 4f    - L(\type\()_tbl) + CONFIG_THUMB
102
1034:
104        add             r6,  r0,  r1
105        lsl             r1,  r1,  #1
106        cmp             r5,  #4
107        vst1.32         {d16[0]},  [r0, :32], r1
108        vst1.32         {d16[1]},  [r6, :32], r1
109        vst1.32         {d17[0]},  [r0, :32], r1
110        vst1.32         {d17[1]},  [r6, :32], r1
111        beq             0f
112        \type           d18, d19,  q0,  q1,  q2,  q3
113        cmp             r5,  #8
114        vst1.32         {d18[0]},  [r0, :32], r1
115        vst1.32         {d18[1]},  [r6, :32], r1
116        vst1.32         {d19[0]},  [r0, :32], r1
117        vst1.32         {d19[1]},  [r6, :32], r1
118        beq             0f
119        \type           d16, d17, q0,  q1,  q2,  q3
120        vst1.32         {d16[0]},  [r0, :32], r1
121        vst1.32         {d16[1]},  [r6, :32], r1
122        \type           d18, d19,  q0,  q1,  q2,  q3
123        vst1.32         {d17[0]},  [r0, :32], r1
124        vst1.32         {d17[1]},  [r6, :32], r1
125        vst1.32         {d18[0]},  [r0, :32], r1
126        vst1.32         {d18[1]},  [r6, :32], r1
127        vst1.32         {d19[0]},  [r0, :32], r1
128        vst1.32         {d19[1]},  [r6, :32], r1
129        pop             {r4-r6,pc}
13080:
131        add             r6,  r0,  r1
132        lsl             r1,  r1,  #1
1338:
134        vst1.8          {d16},  [r0, :64], r1
135        \type           d18, d19, q0,  q1,  q2,  q3
136        vst1.8          {d17},  [r6, :64], r1
137        vst1.8          {d18},  [r0, :64], r1
138        subs            r5,  r5,  #4
139        vst1.8          {d19},  [r6, :64], r1
140        ble             0f
141        \type           d16, d17, q0,  q1,  q2,  q3
142        b               8b
143160:
144        add             r6,  r0,  r1
145        lsl             r1,  r1,  #1
14616:
147        \type           d18, d19, q0, q1, q2, q3
148        vst1.8          {q8},  [r0, :128], r1
149        \type           d20, d21, q0, q1, q2, q3
150        vst1.8          {q9},  [r6, :128], r1
151        \type           d22, d23, q0, q1, q2, q3
152        vst1.8          {q10}, [r0, :128], r1
153        subs            r5,  r5,  #4
154        vst1.8          {q11}, [r6, :128], r1
155        ble             0f
156        \type           d16, d17, q0, q1, q2, q3
157        b               16b
158320:
159        add             r6,  r0,  r1
160        lsl             r1,  r1,  #1
16132:
162        \type           d18, d19, q0, q1, q2, q3
163        \type           d20, d21, q0, q1, q2, q3
164        vst1.8          {q8,  q9},  [r0, :128], r1
165        \type           d22, d23, q0, q1, q2, q3
166        subs            r5,  r5,  #2
167        vst1.8          {q10, q11}, [r6, :128], r1
168        ble             0f
169        \type           d16, d17, q0, q1, q2, q3
170        b               32b
171640:
172        add             r6,  r0,  #32
17364:
174        \type           d18, d19, q0, q1, q2, q3
175        \type           d20, d21, q0, q1, q2, q3
176        \type           d22, d23, q0, q1, q2, q3
177        vst1.8          {q8,  q9},  [r0, :128], r1
178        \type           d16, d17, q0, q1, q2, q3
179        vst1.8          {q10, q11}, [r6, :128], r1
180        \type           d18, d19, q0, q1, q2, q3
181        \type           d20, d21, q0, q1, q2, q3
182        vst1.8          {q8,  q9},  [r0, :128], r1
183        \type           d22, d23, q0, q1, q2, q3
184        subs            r5,  r5,  #2
185        vst1.8          {q10, q11}, [r6, :128], r1
186        ble             0f
187        \type           d16, d17, q0, q1, q2, q3
188        b               64b
1891280:
190        sub             r1,  r1,  #32
191        add             r6,  r0,  #64
192128:
193        \type           d18, d19, q0, q1, q2, q3
194        \type           d20, d21, q0, q1, q2, q3
195        \type           d22, d23, q0, q1, q2, q3
196        vst1.8          {q8,  q9},  [r0, :128]!
197        \type           d16, d17, q0, q1, q2, q3
198        vst1.8          {q10, q11}, [r0, :128], r1
199        \type           d18, d19, q0, q1, q2, q3
200        \type           d20, d21, q0, q1, q2, q3
201        vst1.8          {q8,  q9},  [r6, :128]!
202        \type           d22, d23, q0, q1, q2, q3
203        subs            r5,  r5,  #1
204        vst1.8          {q10, q11}, [r6, :128], r1
205        ble             0f
206        \type           d16, d17, q0, q1, q2, q3
207        b               128b
208
2090:
210        pop             {r4-r6,pc}
211endfunc
212.endm
213
214bidir_fn avg
215bidir_fn w_avg
216bidir_fn mask
217
218
219.macro w_mask_fn type
220function w_mask_\type\()_8bpc_neon, export=1
221        push            {r4-r9,lr}
222        ldrd            r4,  r5,  [sp, #28]
223        ldrd            r6,  r7,  [sp, #36]
224        clz             r8,  r4
225        adr             r9,  L(w_mask_\type\()_tbl)
226        sub             r8,  r8,  #24
227        ldr             r8,  [r9,  r8,  lsl #2]
228        add             r9,  r9,  r8
229        movw            r12, #6903
230        vdup.16         q14, r12
231.if \type == 444
232        vmov.i8         q15, #64
233.elseif \type == 422
234        vdup.8          d0,  r7         // d0[] <- sign
235        vmov.i8         d30, #129
236        vsub.i8         d30, d30, d0    // 129 - sign
237.elseif \type == 420
238        vdup.16         q0,  r7         // d0[] <- sign
239        vmov.i16        q15, #256
240        vsub.i16        q15, q15, q0    // 256 - sign
241.endif
242        add             r12, r0,  r1
243        lsl             r1,  r1,  #1
244        bx              r9
245
246        .align 2
247L(w_mask_\type\()_tbl):
248        .word 1280f  - L(w_mask_\type\()_tbl) + CONFIG_THUMB
249        .word 640f   - L(w_mask_\type\()_tbl) + CONFIG_THUMB
250        .word 320f   - L(w_mask_\type\()_tbl) + CONFIG_THUMB
251        .word 160f   - L(w_mask_\type\()_tbl) + CONFIG_THUMB
252        .word 8f     - L(w_mask_\type\()_tbl) + CONFIG_THUMB
253        .word 4f     - L(w_mask_\type\()_tbl) + CONFIG_THUMB
254
2554:
256        vld1.16         {d0,  d1,  d2,  d3},  [r2,  :128]! // tmp1 (four rows at once)
257        vld1.16         {d4,  d5,  d6,  d7},  [r3,  :128]! // tmp2 (four rows at once)
258        subs            r5,  r5,  #4
259        vsub.i16        q8,  q2,  q0    // tmp2-tmp1
260        vsub.i16        q9,  q3,  q1
261        vabd.s16        q10, q0,  q2    // (abs(tmp1[x] - tmp2[x]))
262        vabd.s16        q11, q1,  q3
263        vqsub.u16       q10, q14, q10   // 6903 - abs ()
264        vqsub.u16       q11, q14, q11
265        vshr.s16        q10, q10, #8    // 64-m = (6903 - abs()) >> 8
266        vshr.s16        q11, q11, #8
267        vshl.s16        q12, q10, #9    // (64-m)<<9
268        vshl.s16        q13, q11, #9
269        vqdmulh.s16     q12, q12, q8    // ((tmp2-tmp1)*(64-m)<<9)>>15
270        vqdmulh.s16     q13, q13, q9
271        vadd.i16        q12, q12, q0    // (((tmp2-tmp1)*(64-m)<<9)>>15) + tmp1
272        vadd.i16        q13, q13, q1
273        vqrshrun.s16    d24, q12, #4    // (((((tmp2-tmp1)*(64-m)<<9)>>15) + tmp1) + 8) >> 4
274        vqrshrun.s16    d25, q13, #4
275.if \type == 444
276        vmovn.u16       d20, q10        // 64 - m
277        vmovn.u16       d21, q11
278        vsub.i8         q10, q15, q10   // m
279        vst1.8          {d20, d21}, [r6,  :128]!
280.elseif \type == 422
281        vpadd.s16       d20, d20, d21   // (64 - m) + (64 - n) (column wise addition)
282        vpadd.s16       d21, d22, d23
283        vmovn.s16       d6,  q10
284        vhsub.u8        d6,  d30, d6    // ((129 - sign) - ((64 - m) + (64 - n))) >> 1
285        vst1.8          {d6},  [r6,  :64]!
286.elseif \type == 420
287        vadd.s16        d20, d20, d21   // (64 - my1) + (64 - my2) (row wise addition)
288        vadd.s16        d21, d22, d23
289        vpadd.s16       d20, d20, d21   // (128 - m) + (128 - n) (column wise addition)
290        vsub.s16        d20, d30, d20   // (256 - sign) - ((128 - m) + (128 - n))
291        vrshrn.u16      d20, q10,  #2   // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
292        vst1.32         {d20[0]}, [r6,  :32]!
293.endif
294        vst1.32         {d24[0]}, [r0,  :32], r1
295        vst1.32         {d24[1]}, [r12, :32], r1
296        vst1.32         {d25[0]}, [r0,  :32], r1
297        vst1.32         {d25[1]}, [r12, :32], r1
298        bgt             4b
299        pop             {r4-r9,pc}
3008:
301        vld1.16         {d0,  d1,  d2,  d3},  [r2,  :128]! // tmp1y1, tmp1y2
302        vld1.16         {d4,  d5,  d6,  d7},  [r3,  :128]! // tmp2y1, tmp2y2
303        subs            r5,  r5,  #2
304        vsub.i16        q8,  q2,  q0    // tmp2y1 - tmp1y1
305        vsub.i16        q9,  q3,  q1    // tmp2y2 - tmp1y2
306        vabd.s16        q10, q0,  q2    // abs(tmp1y1 - tmp2y1)
307        vabd.s16        q11, q1,  q3    // abs(tmp1y2 - tmp2y2)
308        vqsub.u16       q10, q14, q10   // 6903 - abs(tmp1y1 - tmp2y1)
309        vqsub.u16       q11, q14, q11   // 6903 - abs(tmp1y2 - tmp2y2)
310        vshr.s16        q10, q10, #8    // 64 - my1 = 6903 - abs(tmp1y1 - tmp2y1) >> 8
311        vshr.s16        q11, q11, #8    // 64 - my2 = 6903 - abs(tmp1y2 - tmp2y2) >> 8
312        vshl.s16        q12, q10, #9    // (64 - my1) << 9
313        vshl.s16        q13, q11, #9    // (64 - my2) << 9
314        vqdmulh.s16     q12, q12, q8    // ((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15
315        vqdmulh.s16     q13, q13, q9    // ((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15
316        vadd.s16        q12, q12, q0    // (((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15) + tmp1y1
317        vadd.s16        q13, q13, q1    // (((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15) + tmp1y2
318        vqrshrun.s16    d24, q12, #4    // (((((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15) + tmp1y1) + 8) >> 4
319        vqrshrun.s16    d25, q13, #4    // (((((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15) + tmp1y2) + 8) >> 4
320.if \type == 444
321        vmovn.u16       d20, q10        // 64 - m
322        vmovn.u16       d21, q11
323        vsub.i8         q10, q15, q10   // m
324        vst1.8          {d20, d21}, [r6,  :128]!
325.elseif \type == 422
326        vpadd.s16       d20, d20, d21   // (64 - my1) + (64 - ny1) (column wise addition)
327        vpadd.s16       d21, d22, d23   // (64 - my2) + (64 - ny2)
328        vmovn.s16       d20, q10
329        vhsub.u8        d20, d30, d20   // ((129 - sign) - ((64 - my1/y2) + (64 - ny1/y2))) >> 1
330        vst1.8          {d20}, [r6,  :64]!
331.elseif \type == 420
332        vadd.s16        q10, q10, q11   // (64 - my1) + (64 - my2) (row wise addition)
333        vpadd.s16       d20, d20, d21   // (128 - m) + (128 - n) (column wise addition)
334        vsub.s16        d20, d30, d20   // (256 - sign) - ((128 - m) + (128 - n))
335        vrshrn.u16      d20, q10, #2    // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
336        vst1.32         {d20[0]}, [r6,  :32]!
337.endif
338        vst1.16         {d24}, [r0,  :64], r1
339        vst1.16         {d25}, [r12, :64], r1
340        bgt             8b
341        pop             {r4-r9,pc}
3421280:
343640:
344320:
345160:
346        sub             r1,  r1,  r4
347.if \type == 444
348        add             lr,  r6,  r4
349.elseif \type == 422
350        add             lr,  r6,  r4,  lsr #1
351.endif
352        add             r9,  r3,  r4,  lsl #1
353        add             r7,  r2,  r4,  lsl #1
354161:
355        mov             r8,  r4
35616:
357        vld1.16         {d0,  d1,  d2,  d3},  [r2,  :128]! // tmp1y1
358        vld1.16         {d4,  d5,  d6,  d7},  [r3,  :128]! // tmp2y1
359        vld1.16         {d16, d17, d18, d19}, [r7,  :128]! // tmp1y2
360        subs            r8,  r8,  #16
361        vsub.i16        q2,  q2,  q0    // tmp2y1 - tmp1y1
362        vsub.i16        q3,  q3,  q1
363        vabs.s16        q10, q2         // abs(tm2y1 - tmp1y1)
364        vabs.s16        q11, q3
365        vqsub.u16       q10, q14, q10   // 6903 - abs(tmp1y1 - tmp2y1)
366        vqsub.u16       q11, q14, q11
367        vshr.s16        q10, q10, #8    // 64 - my1 = 6903 - abs(tmp1y1 - tmp2y1) >> 8
368        vshr.s16        q11, q11, #8
369        vshl.s16        q12, q10, #9    // (64 - my1) << 9
370        vshl.s16        q13, q11, #9
371        vqdmulh.s16     q12, q12, q2    // ((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15
372        vqdmulh.s16     q13, q13, q3
373        vadd.i16        q12, q12, q0    // (((tmp2y1 - tmp1y1) * (64 - my1) << 9) >> 15) + tmp1y1
374        vadd.i16        q13, q13, q1
375        vld1.16         {d0,  d1,  d2,  d3},  [r9,  :128]! // tmp2h2
376.if \type == 444
377        vmovn.u16       d20, q10        // 64 - my1
378        vmovn.u16       d21, q11
379        vsub.i8         q10, q15, q10   // my1
380        vst1.8          {d20, d21}, [r6,  :128]!
381.elseif \type == 422
382        vpadd.s16       d20, d20, d21   // (64 - my1) + (64 - ny1) (column wise addition)
383        vpadd.s16       d21, d22, d23
384        vmovn.s16       d20, q10
385        vhsub.u8        d20, d30, d20   // ((129 - sign) - ((64 - my1) + (64 - ny1))) >> 1
386        vst1.8          {d20}, [r6,  :64]!
387.endif
388        vqrshrun.s16    d24, q12, #4    // (((((tmp2y1 - tmp1y1)*(64 - my1) << 9) >> 15) + tmp1y1) + 8) >> 4
389        vqrshrun.s16    d25, q13, #4
390        vsub.i16        q0,  q0,  q8    // tmp2y2 - tmp1y2
391        vsub.i16        q1,  q1,  q9
392        vst1.16         {d24, d25}, [r0,  :128]!    // store dsty1
393        vabs.s16        q2,  q0         // abs(tmp2y2 - tmp1y2)
394        vabs.s16        q3,  q1
395        vqsub.u16       q2,  q14, q2    // 6903 - abs(tmp2y2 - tmp1y2)
396        vqsub.u16       q3,  q14, q3
397        vshr.s16        q2,  q2,  #8    // (6903 - abs(tmp2y2 - tmp1y2)) >> 8
398        vshr.s16        q3,  q3,  #8
399        vshl.s16        q12, q2,  #9    // (64 - my2) << 9
400        vshl.s16        q13, q3,  #9
401.if \type == 444
402        vmovn.u16       d4,  q2         // 64 - my2
403        vmovn.u16       d5,  q3
404        vsub.i8         q2,  q15, q2    // my2
405        vst1.8          {d4,  d5},  [lr,  :128]!
406.elseif \type == 422
407        vpadd.s16       d4,  d4,  d5    // (64 - my2) + (64 - ny2) (column wise addition)
408        vpadd.s16       d5,  d6,  d7
409        vmovn.s16       d4,  q2
410        vhsub.u8        d4,  d30, d4    // ((129 - sign) - ((64 - my2) + (64 - ny2))) >> 1
411        vst1.8          {d4},  [lr,  :64]!
412.elseif \type == 420
413        vadd.s16        q10, q10, q2    // (64 - my1) + (64 - my2) (row wise addition)
414        vadd.s16        q11, q11, q3
415        vpadd.s16       d20, d20, d21   // (128 - m) + (128 - n) (column wise addition)
416        vpadd.s16       d21, d22, d23
417        vsub.s16        q10, q15, q10   // (256 - sign) - ((128 - m) + (128 - n))
418        vrshrn.u16      d20, q10, #2    // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
419        vst1.8          {d20}, [r6,  :64]!
420.endif
421        vqdmulh.s16     q12, q12, q0    // ((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15
422        vqdmulh.s16     q13, q13, q1
423        vadd.i16        q12, q12, q8    // (((tmp2y2 - tmp1y2) * (64 - my2) << 9) >> 15) + tmp1y2
424        vadd.i16        q13, q13, q9
425        vqrshrun.s16    d24, q12, #4    // (((((tmp2y2 - tmp1y2)*(64 - my2) << 9) >> 15) + tmp1y2) + 8) >> 4
426        vqrshrun.s16    d25, q13, #4
427        vst1.16         {d24, d25}, [r12, :128]!   // store dsty2
428        bgt             16b
429        subs            r5,  r5,  #2
430        add             r2,  r2,  r4,  lsl #1
431        add             r3,  r3,  r4,  lsl #1
432        add             r7,  r7,  r4,  lsl #1
433        add             r9,  r9,  r4,  lsl #1
434.if \type == 444
435        add             r6,  r6,  r4
436        add             lr,  lr,  r4
437.elseif \type == 422
438        add             r6,  r6,  r4,  lsr #1
439        add             lr,  lr,  r4,  lsr #1
440.endif
441        add             r0,  r0,  r1
442        add             r12, r12, r1
443        bgt             161b
444        pop             {r4-r9,pc}
445endfunc
446.endm
447
448w_mask_fn 444
449w_mask_fn 422
450w_mask_fn 420
451
452
453function blend_8bpc_neon, export=1
454        push            {r4-r5,lr}
455        ldrd            r4,  r5,  [sp, #12]
456        clz             lr,  r3
457        adr             r3,  L(blend_tbl)
458        sub             lr,  lr,  #26
459        ldr             lr,  [r3, lr, lsl #2]
460        add             r3,  r3,  lr
461        bx              r3
462
463        .align 2
464L(blend_tbl):
465        .word 320f  - L(blend_tbl) + CONFIG_THUMB
466        .word 160f  - L(blend_tbl) + CONFIG_THUMB
467        .word 80f   - L(blend_tbl) + CONFIG_THUMB
468        .word 40f   - L(blend_tbl) + CONFIG_THUMB
469
47040:
471        vmov.i8         d22, #64
472        add             r12, r0,  r1
473        lsl             r1,  r1,  #1
4744:
475        vld1.u8         {d2},     [r5,  :64]!
476        vld1.u8         {d1},     [r2,  :64]!
477        vld1.32         {d0[]},   [r0,  :32]
478        subs            r4,  r4,  #2
479        vld1.32         {d0[1]},  [r12, :32]
480        vsub.i8         d3,  d22, d2
481        vmull.u8        q8,  d1,  d2
482        vmlal.u8        q8,  d0,  d3
483        vrshrn.i16      d20, q8,  #6
484        vst1.32         {d20[0]}, [r0,  :32], r1
485        vst1.32         {d20[1]}, [r12, :32], r1
486        bgt             4b
487        pop             {r4-r5,pc}
48880:
489        vmov.i8         d16, #64
490        add             r12, r0,  r1
491        lsl             r1,  r1,  #1
4928:
493        vld1.u8         {q1},  [r5,  :128]!
494        vld1.u8         {q2},  [r2,  :128]!
495        vld1.u8         {d0},  [r0,  :64]
496        vsub.i8         d17, d16, d2
497        vld1.u8         {d1},  [r12, :64]
498        subs            r4,  r4,  #2
499        vsub.i8         d18, d16, d3
500        vmull.u8        q3,  d2,  d4
501        vmlal.u8        q3,  d0,  d17
502        vmull.u8        q10, d3,  d5
503        vmlal.u8        q10, d1,  d18
504        vrshrn.i16      d22, q3,  #6
505        vrshrn.i16      d23, q10, #6
506        vst1.u8         {d22}, [r0,  :64], r1
507        vst1.u8         {d23}, [r12, :64], r1
508        bgt             8b
509        pop             {r4-r5,pc}
510160:
511        vmov.i8         q12, #64
512        add             r12, r0,  r1
513        lsl             r1,  r1,  #1
51416:
515        vld1.u8         {q1,  q2},  [r5,  :128]!
516        vld1.u8         {q8,  q9},  [r2,  :128]!
517        vld1.u8         {q0},  [r0,  :128]
518        subs            r4,  r4,  #2
519        vsub.i8         q15, q12, q1
520        vld1.u8         {q13}, [r12, :128]
521        vmull.u8        q3,  d16, d2
522        vmlal.u8        q3,  d0,  d30
523        vmull.u8        q14, d17, d3
524        vmlal.u8        q14, d1,  d31
525        vsub.i8         q15, q12, q2
526        vrshrn.i16      d20, q3,  #6
527        vrshrn.i16      d21, q14, #6
528        vmull.u8        q3,  d18, d4
529        vmlal.u8        q3,  d26, d30
530        vmull.u8        q14, d19, d5
531        vmlal.u8        q14, d27, d31
532        vrshrn.i16      d22, q3,  #6
533        vrshrn.i16      d23, q14, #6
534        vst1.u8         {q10}, [r0,  :128], r1
535        vst1.u8         {q11}, [r12, :128], r1
536        bgt             16b
537        pop             {r4-r5,pc}
538320:
539        vmov.i8         q10, #64
54032:
541        vld1.u8         {q2,  q3},  [r5,  :128]!
542        vld1.u8         {q8,  q9},  [r2,  :128]!
543        vld1.u8         {q0,  q1},  [r0,  :128]
544        subs            r4,  r4,  #1
545        vsub.i8         q11, q10, q2
546        vmull.u8        q15, d16, d4
547        vmlal.u8        q15, d0,  d22
548        vmull.u8        q14, d17, d5
549        vmlal.u8        q14, d1,  d23
550        vsub.i8         q11, q10, q3
551        vrshrn.i16      d24, q15, #6
552        vrshrn.i16      d25, q14, #6
553        vmull.u8        q15, d18, d6
554        vmlal.u8        q15, d2,  d22
555        vmull.u8        q14, d19, d7
556        vmlal.u8        q14, d3,  d23
557        vrshrn.i16      d26, q15, #6
558        vrshrn.i16      d27, q14, #6
559        vst1.u8         {q12, q13}, [r0,  :128],  r1
560        bgt             32b
561        pop             {r4-r5,pc}
562endfunc
563
564function blend_h_8bpc_neon, export=1
565        push            {r4-r5,lr}
566        ldr             r4,  [sp, #12]
567        movrel          r5,  X(obmc_masks)
568        add             r5,  r5,  r4
569        sub             r4,  r4,  r4,  lsr #2
570        clz             lr,  r3
571        adr             r12, L(blend_h_tbl)
572        sub             lr,  lr,  #24
573        ldr             lr,  [r12, lr, lsl #2]
574        add             r12, r12, lr
575        bx              r12
576
577        .align 2
578L(blend_h_tbl):
579        .word 1280f  - L(blend_h_tbl) + CONFIG_THUMB
580        .word 640f   - L(blend_h_tbl) + CONFIG_THUMB
581        .word 320f   - L(blend_h_tbl) + CONFIG_THUMB
582        .word 160f   - L(blend_h_tbl) + CONFIG_THUMB
583        .word 80f    - L(blend_h_tbl) + CONFIG_THUMB
584        .word 40f    - L(blend_h_tbl) + CONFIG_THUMB
585        .word 20f    - L(blend_h_tbl) + CONFIG_THUMB
586
58720:
588        vmov.i8         d22, #64
589        add             r12, r0,  r1
590        lsl             r1,  r1,  #1
5912:
592        vld1.16         {d2[], d3[]},  [r5,  :16]!
593        vld1.32         {d1[]},  [r2,  :32]!
594        subs            r4,  r4,  #2
595        vld1.16         {d0[]},   [r0,  :16]
596        vzip.8          d2,  d3
597        vsub.i8         d4,  d22, d2
598        vld1.16         {d0[1]},  [r12, :16]
599        vmull.u8        q8,  d1,  d2
600        vmlal.u8        q8,  d0,  d4
601        vrshrn.i16      d20, q8,  #6
602        vst1.16         {d20[0]}, [r0,  :16], r1
603        vst1.16         {d20[1]}, [r12, :16], r1
604        bgt             2b
605        pop             {r4-r5,pc}
60640:
607        vmov.i8         d22, #64
608        add             r12, r0,  r1
609        lsl             r1,  r1,  #1
6104:
611        vld2.u8         {d2[],  d3[]},   [r5,  :16]!
612        vld1.u8         {d1},     [r2,  :64]!
613        subs            r4,  r4,  #2
614        vext.u8         d2,  d2,  d3,   #4
615        vld1.32         {d0[]},   [r0,  :32]
616        vsub.i8         d6,  d22, d2
617        vld1.32         {d0[1]},  [r12, :32]
618        vmull.u8        q8,  d1,  d2
619        vmlal.u8        q8,  d0,  d6
620        vrshrn.i16      d20, q8,  #6
621        vst1.32         {d20[0]}, [r0,  :32], r1
622        vst1.32         {d20[1]}, [r12, :32], r1
623        bgt             4b
624        pop             {r4-r5,pc}
62580:
626        vmov.i8         q8, #64
627        add             r12, r0,  r1
628        lsl             r1,  r1,  #1
6298:
630        vld2.u8         {d2[],  d3[]},  [r5,  :16]!
631        vld1.u8         {d4,  d5},  [r2,  :128]!
632        vld1.u8         {d0},   [r0,  :64]
633        vsub.i8         q9,  q8,  q1
634        vld1.u8         {d1},   [r12, :64]
635        subs            r4,  r4,  #2
636        vmull.u8        q3,  d2,  d4
637        vmlal.u8        q3,  d0,  d18
638        vmull.u8        q10, d3,  d5
639        vmlal.u8        q10, d1,  d19
640        vrshrn.i16      d22, q3,  #6
641        vrshrn.i16      d23, q10, #6
642        vst1.u8         {d22}, [r0,  :64], r1
643        vst1.u8         {d23}, [r12, :64], r1
644        bgt             8b
645        pop             {r4-r5,pc}
646160:
647        vmov.i8         q12, #64
648        add             r12, r0,  r1
649        lsl             r1,  r1,  #1
65016:
651        vld2.u8         {d28[], d29[]}, [r5,  :16]!
652        vld1.u8         {d2,  d3,  d4,  d5},  [r2,  :128]!
653        vsub.i8         q15, q12, q14
654        vld1.u8         {q0},  [r0,  :128]
655        subs            r4,  r4,  #2
656        vld1.u8         {q13}, [r12, :128]
657        vmull.u8        q3,  d2,  d28
658        vmlal.u8        q3,  d0,  d30
659        vmull.u8        q8,  d3,  d28
660        vmlal.u8        q8,  d1,  d30
661        vrshrn.i16      d18, q3,  #6
662        vrshrn.i16      d19, q8,  #6
663        vmull.u8        q3,  d4,  d29
664        vmlal.u8        q3,  d26, d31
665        vmull.u8        q8,  d5,  d29
666        vmlal.u8        q8,  d27, d31
667        vrshrn.i16      d20, q3,  #6
668        vrshrn.i16      d21, q8,  #6
669        vst1.u8         {q9},  [r0,  :128], r1
670        vst1.u8         {q10}, [r12, :128], r1
671        bgt             16b
672        pop             {r4-r5,pc}
673320:
674640:
6751280:
676        vmov.i8         d20, #64
677        sub             r1,  r1,  r3
678321:
679        vld1.u8         {d6[]},  [r5]!
680        vsub.i8         d7,  d20, d6
681        mov             r12, r3
68232:
683        vld1.u8         {q8,  q9},  [r2,  :128]!
684        vld1.u8         {q0,  q1},  [r0,  :128]
685        vmull.u8        q15, d16, d6
686        vmlal.u8        q15, d0,  d7
687        vmull.u8        q14, d17, d6
688        vmlal.u8        q14, d1,  d7
689        vrshrn.i16      d0,  q15, #6
690        vrshrn.i16      d1,  q14, #6
691        vmull.u8        q15, d18, d6
692        vmlal.u8        q15, d2,  d7
693        vmull.u8        q14, d19, d6
694        vmlal.u8        q14, d3,  d7
695        vrshrn.i16      d2,  q15, #6
696        vrshrn.i16      d3,  q14, #6
697        subs            r12, r12, #32
698        vst1.u8         {q0,  q1},  [r0,  :128]!
699        bgt             32b
700        add             r0,  r0,  r1
701        subs            r4,  r4,  #1
702        bgt             321b
703        pop             {r4-r5,pc}
704endfunc
705
706function blend_v_8bpc_neon, export=1
707        push            {r4,lr}
708        ldr             r4,  [sp, #8]
709        movrel          lr,  X(obmc_masks)
710        add             lr,  lr,  r3
711        clz             r12, r3
712        adr             r3,  L(blend_v_tbl)
713        sub             r12, r12, #26
714        ldr             r12, [r3, r12, lsl #2]
715        add             r3,  r3,  r12
716        bx              r3
717
718        .align 2
719L(blend_v_tbl):
720        .word 320f  - L(blend_v_tbl) + CONFIG_THUMB
721        .word 160f  - L(blend_v_tbl) + CONFIG_THUMB
722        .word 80f   - L(blend_v_tbl) + CONFIG_THUMB
723        .word 40f   - L(blend_v_tbl) + CONFIG_THUMB
724        .word 20f   - L(blend_v_tbl) + CONFIG_THUMB
725
72620:
727        vmov.i8         d22, #64
728        vld1.8          {d2[]},   [lr]
729        add             r12, r0,  r1
730        lsl             r1,  r1,  #1
731        vsub.i8         d3,  d22, d2
7322:
733        vld1.16         {d1[0]},  [r2,  :16]!
734        vld1.8          {d0[]},   [r0]
735        subs            r4,  r4,  #2
736        vld1.8          {d1[1]},  [r2]
737        vld1.8          {d0[1]},  [r12]
738        vmull.u8        q2,  d1,  d2
739        vmlal.u8        q2,  d0,  d3
740        vrshrn.i16      d6,  q2,  #6
741        add             r2,  r2,  #2
742        vst1.8          {d6[0]},  [r0],  r1
743        vst1.8          {d6[1]},  [r12], r1
744        bgt             2b
745        pop             {r4,pc}
74640:
747        vmov.i8         d22, #64
748        vld1.32         {d4[]},   [lr,  :32]
749        add             r12, r0,  r1
750        lsl             r1,  r1,  #1
751        vsub.i8         d5,  d22, d4
752        sub             r1,  r1,  #2
7534:
754        vld1.u8         {d2},     [r2,  :64]!
755        vld1.32         {d0[]},   [r0,  :32]
756        vld1.32         {d0[1]},  [r12, :32]
757        subs            r4,  r4,  #2
758        vmull.u8        q3,  d2,  d4
759        vmlal.u8        q3,  d0,  d5
760        vrshrn.i16      d20, q3,  #6
761        vst1.16         {d20[0]}, [r0,  :16]!
762        vst1.16         {d20[2]}, [r12, :16]!
763        vst1.8          {d20[2]}, [r0],  r1
764        vst1.8          {d20[6]}, [r12], r1
765        bgt             4b
766        pop             {r4,pc}
76780:
768        vmov.i8         d16, #64
769        vld1.u8         {d2},  [lr,  :64]
770        add             r12, r0,  r1
771        lsl             r1,  r1,  #1
772        vsub.i8         d17, d16, d2
773        sub             r1,  r1,  #4
7748:
775        vld1.u8         {d4,  d5},  [r2,  :128]!
776        vld1.u8         {d0},  [r0,  :64]
777        vld1.u8         {d1},  [r12, :64]
778        subs            r4,  r4,  #2
779        vmull.u8        q3,  d2,  d4
780        vmlal.u8        q3,  d0,  d17
781        vmull.u8        q10, d2,  d5
782        vmlal.u8        q10, d1,  d17
783        vrshrn.i16      d22, q3,  #6
784        vrshrn.i16      d23, q10, #6
785        vst1.32         {d22[0]}, [r0,  :32]!
786        vst1.32         {d23[0]}, [r12, :32]!
787        vst1.16         {d22[2]}, [r0,  :16], r1
788        vst1.16         {d23[2]}, [r12, :16], r1
789        bgt             8b
790        pop             {r4,pc}
791160:
792        vmov.i8         q12, #64
793        vld1.u8         {q14}, [lr,  :128]
794        add             r12, r0,  r1
795        lsl             r1,  r1,  #1
796        vsub.i8         q11, q12, q14
797        sub             r1,  r1,  #8
79816:
799        vld1.u8         {q1,  q2},  [r2,  :128]!
800        vld1.u8         {q0},  [r0,  :128]
801        subs            r4,  r4,  #2
802        vld1.u8         {q13}, [r12, :128]
803        vmull.u8        q3,  d2,  d28
804        vmlal.u8        q3,  d0,  d22
805        vmull.u8        q8,  d3,  d29
806        vmlal.u8        q8,  d1,  d23
807        vrshrn.i16      d18, q3,  #6
808        vrshrn.i16      d19, q8,  #6
809        vmull.u8        q3,  d4,  d28
810        vmlal.u8        q3,  d26, d22
811        vmull.u8        q8,  d5,  d29
812        vmlal.u8        q8,  d27, d23
813        vrshrn.i16      d20, q3,  #6
814        vrshrn.i16      d21, q8,  #6
815        vst1.u8         {d18},    [r0,  :64]!
816        vst1.u8         {d20},    [r12, :64]!
817        vst1.32         {d19[0]}, [r0,  :32], r1
818        vst1.32         {d21[0]}, [r12, :32], r1
819        bgt             16b
820        pop             {r4,pc}
821320:
822        vmov.i8         q10, #64
823        vld1.u8         {q2,  q3},  [lr,  :128]
824        vsub.i8         q11, q10, q2
825        vsub.i8         d24, d20, d6
82632:
827        vld1.u8         {q8,  q9},  [r2,  :128]!
828        vld1.u8         {d0,  d1,  d2},  [r0,  :64]
829        subs            r4,  r4,  #1
830        vmull.u8        q15, d16, d4
831        vmlal.u8        q15, d0,  d22
832        vmull.u8        q14, d17, d5
833        vmlal.u8        q14, d1,  d23
834        vrshrn.i16      d0,  q15, #6
835        vrshrn.i16      d1,  q14, #6
836        vmull.u8        q15, d18, d6
837        vmlal.u8        q15, d2,  d24
838        vrshrn.i16      d2,  q15, #6
839        vst1.u8         {d0,  d1,  d2},  [r0,  :64],  r1
840        bgt             32b
841        pop             {r4,pc}
842endfunc
843
844
845// This has got the same signature as the put_8tap functions,
846// assumes that the caller has loaded the h argument into r5,
847// and assumes that r8 is set to (clz(w)-24).
848function put_neon
849        adr             r9,  L(put_tbl)
850        ldr             r8,  [r9, r8, lsl #2]
851        add             r9,  r9,  r8
852        bx              r9
853
854        .align 2
855L(put_tbl):
856        .word 1280f - L(put_tbl) + CONFIG_THUMB
857        .word 640f  - L(put_tbl) + CONFIG_THUMB
858        .word 32f   - L(put_tbl) + CONFIG_THUMB
859        .word 160f  - L(put_tbl) + CONFIG_THUMB
860        .word 8f    - L(put_tbl) + CONFIG_THUMB
861        .word 4f    - L(put_tbl) + CONFIG_THUMB
862        .word 2f    - L(put_tbl) + CONFIG_THUMB
863
8642:
865        vld1.16         {d0[]}, [r2], r3
866        vld1.16         {d1[]}, [r2], r3
867        subs            r5,  r5,  #2
868        vst1.16         {d0[0]}, [r0, :16], r1
869        vst1.16         {d1[0]}, [r0, :16], r1
870        bgt             2b
871        pop             {r4-r11,pc}
8724:
873        vld1.32         {d0[]}, [r2], r3
874        vld1.32         {d1[]}, [r2], r3
875        subs            r5,  r5,  #2
876        vst1.32         {d0[0]}, [r0, :32], r1
877        vst1.32         {d1[0]}, [r0, :32], r1
878        bgt             4b
879        pop             {r4-r11,pc}
8808:
881        vld1.8          {d0}, [r2], r3
882        vld1.8          {d1}, [r2], r3
883        subs            r5,  r5,  #2
884        vst1.8          {d0}, [r0, :64], r1
885        vst1.8          {d1}, [r0, :64], r1
886        bgt             8b
887        pop             {r4-r11,pc}
888160:
889        add             r8,  r0,  r1
890        lsl             r1,  r1,  #1
891        add             r9,  r2,  r3
892        lsl             r3,  r3,  #1
89316:
894        vld1.8          {q0}, [r2], r3
895        vld1.8          {q1}, [r9], r3
896        subs            r5,  r5,  #2
897        vst1.8          {q0}, [r0, :128], r1
898        vst1.8          {q1}, [r8, :128], r1
899        bgt             16b
900        pop             {r4-r11,pc}
90132:
902        vld1.8          {q0,  q1},  [r2], r3
903        subs            r5,  r5,  #1
904        vst1.8          {q0,  q1},  [r0, :128], r1
905        bgt             32b
906        pop             {r4-r11,pc}
907640:
908        sub             r1,  r1,  #32
909        sub             r3,  r3,  #32
91064:
911        vld1.8          {q0,  q1},  [r2]!
912        vst1.8          {q0,  q1},  [r0, :128]!
913        vld1.8          {q2,  q3},  [r2], r3
914        subs            r5,  r5,  #1
915        vst1.8          {q2,  q3},  [r0, :128], r1
916        bgt             64b
917        pop             {r4-r11,pc}
9181280:
919        sub             r1,  r1,  #96
920        sub             r3,  r3,  #96
921128:
922        vld1.8          {q8,  q9},  [r2]!
923        vst1.8          {q8,  q9},  [r0, :128]!
924        vld1.8          {q10, q11}, [r2]!
925        vst1.8          {q10, q11}, [r0, :128]!
926        vld1.8          {q12, q13}, [r2]!
927        vst1.8          {q12, q13}, [r0, :128]!
928        vld1.8          {q14, q15}, [r2], r3
929        subs            r5,  r5,  #1
930        vst1.8          {q14, q15}, [r0, :128], r1
931        bgt             128b
932        pop             {r4-r11,pc}
933endfunc
934
935
936// This has got the same signature as the put_8tap functions,
937// assumes that the caller has loaded the h argument into r4,
938// and assumes that r8 is set to (clz(w)-24), and r7 to w*2.
939function prep_neon
940        adr             r9,  L(prep_tbl)
941        ldr             r8,  [r9, r8, lsl #2]
942        add             r9,  r9,  r8
943        bx              r9
944
945        .align 2
946L(prep_tbl):
947        .word 1280f - L(prep_tbl) + CONFIG_THUMB
948        .word 640f  - L(prep_tbl) + CONFIG_THUMB
949        .word 320f  - L(prep_tbl) + CONFIG_THUMB
950        .word 160f  - L(prep_tbl) + CONFIG_THUMB
951        .word 8f    - L(prep_tbl) + CONFIG_THUMB
952        .word 4f    - L(prep_tbl) + CONFIG_THUMB
953
9544:
955        vld1.32         {d0[]}, [r1], r2
956        vld1.32         {d2[]}, [r1], r2
957        subs            r4,  r4,  #2
958        vshll.u8        q0,  d0,  #4
959        vshll.u8        q1,  d2,  #4
960        vst1.16         {d1, d2}, [r0, :64]!
961        bgt             4b
962        pop             {r4-r11,pc}
9638:
964        vld1.8          {d0}, [r1], r2
965        vld1.8          {d2}, [r1], r2
966        subs            r4,  r4,  #2
967        vshll.u8        q0,  d0,  #4
968        vshll.u8        q1,  d2,  #4
969        vst1.16         {q0, q1}, [r0, :128]!
970        bgt             8b
971        pop             {r4-r11,pc}
972160:
973        add             r9,  r1,  r2
974        lsl             r2,  r2,  #1
975        add             r8,  r0,  r7
976        lsl             r7,  r7,  #1
97716:
978        vld1.8          {q2}, [r1], r2
979        vld1.8          {q3}, [r9], r2
980        subs            r4,  r4,  #2
981        vshll.u8        q0,  d4,  #4
982        vshll.u8        q1,  d5,  #4
983        vshll.u8        q2,  d6,  #4
984        vshll.u8        q3,  d7,  #4
985        vst1.16         {q0, q1}, [r0, :128], r7
986        vst1.16         {q2, q3}, [r8, :128], r7
987        bgt             16b
988        pop             {r4-r11,pc}
989320:
990        add             r8,  r0,  r3
99132:
992        vld1.8          {q0,  q1},  [r1], r2
993        subs            r4,  r4,  #2
994        vshll.u8        q8,  d0,  #4
995        vshll.u8        q9,  d1,  #4
996        vld1.8          {q2,  q3},  [r1], r2
997        vshll.u8        q10, d2,  #4
998        vshll.u8        q11, d3,  #4
999        vshll.u8        q12, d4,  #4
1000        vst1.16         {q8,  q9},  [r0, :128], r7
1001        vshll.u8        q13, d5,  #4
1002        vst1.16         {q10, q11}, [r8, :128], r7
1003        vshll.u8        q14, d6,  #4
1004        vst1.16         {q12, q13}, [r0, :128], r7
1005        vshll.u8        q15, d7,  #4
1006        vst1.16         {q14, q15}, [r8, :128], r7
1007        bgt             32b
1008        pop             {r4-r11,pc}
1009640:
1010        sub             r2,  r2,  #32
1011        add             r8,  r0,  #32
1012        mov             r6,  #64
101364:
1014        vld1.8          {q0,  q1},  [r1]!
1015        subs            r4,  r4,  #1
1016        vshll.u8        q8,  d0,  #4
1017        vshll.u8        q9,  d1,  #4
1018        vld1.8          {q2,  q3},  [r1], r2
1019        vshll.u8        q10, d2,  #4
1020        vshll.u8        q11, d3,  #4
1021        vshll.u8        q12, d4,  #4
1022        vst1.16         {q8,  q9},  [r0, :128], r6
1023        vshll.u8        q13, d5,  #4
1024        vshll.u8        q14, d6,  #4
1025        vst1.16         {q10, q11}, [r8, :128], r6
1026        vshll.u8        q15, d7,  #4
1027        vst1.16         {q12, q13}, [r0, :128], r6
1028        vst1.16         {q14, q15}, [r8, :128], r6
1029        bgt             64b
1030        pop             {r4-r11,pc}
10311280:
1032        sub             r2,  r2,  #96
1033        add             r8,  r0,  #32
1034        mov             r6,  #64
1035128:
1036        vld1.8          {q0,  q1},  [r1]!
1037        vld1.8          {q2,  q3},  [r1]!
1038        vshll.u8        q10, d0,  #4
1039        vshll.u8        q11, d1,  #4
1040        vshll.u8        q12, d2,  #4
1041        vshll.u8        q13, d3,  #4
1042        vshll.u8        q14, d4,  #4
1043        vshll.u8        q15, d5,  #4
1044        vld1.8          {q8,  q9},  [r1]!
1045        vst1.16         {q10, q11}, [r0, :128], r6
1046        vst1.16         {q12, q13}, [r8, :128], r6
1047        vshll.u8        q0,  d6,  #4
1048        vshll.u8        q1,  d7,  #4
1049        vshll.u8        q2,  d16, #4
1050        vshll.u8        q3,  d17, #4
1051        vshll.u8        q8,  d18, #4
1052        vshll.u8        q9,  d19, #4
1053        vld1.8          {q10, q11}, [r1], r2
1054        vst1.16         {q14, q15}, [r0, :128], r6
1055        vst1.16         {q0,  q1},  [r8, :128], r6
1056        vshll.u8        q12, d20, #4
1057        vshll.u8        q13, d21, #4
1058        vshll.u8        q14, d22, #4
1059        vshll.u8        q15, d23, #4
1060        subs            r4,  r4,  #1
1061        vst1.16         {q2,  q3},  [r0, :128], r6
1062        vst1.16         {q8,  q9},  [r8, :128], r6
1063        vst1.16         {q12, q13}, [r0, :128], r6
1064        vst1.16         {q14, q15}, [r8, :128], r6
1065        bgt             128b
1066        pop             {r4-r11,pc}
1067endfunc
1068
1069
1070.macro load_slice s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6
1071        vld1.\wd        {\d0[]}, [\s0], \strd
1072        vld1.\wd        {\d1[]}, [\s1], \strd
1073.ifnb \d2
1074        vld1.\wd        {\d2[]}, [\s0], \strd
1075        vld1.\wd        {\d3[]}, [\s1], \strd
1076.endif
1077.ifnb \d4
1078        vld1.\wd        {\d4[]}, [\s0], \strd
1079.endif
1080.ifnb \d5
1081        vld1.\wd        {\d5[]}, [\s1], \strd
1082.endif
1083.ifnb \d6
1084        vld1.\wd        {\d6[]}, [\s0], \strd
1085.endif
1086.endm
1087.macro load_reg s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
1088        vld1.8          {\d0}, [\s0], \strd
1089        vld1.8          {\d1}, [\s1], \strd
1090.ifnb \d2
1091        vld1.8          {\d2}, [\s0], \strd
1092        vld1.8          {\d3}, [\s1], \strd
1093.endif
1094.ifnb \d4
1095        vld1.8          {\d4}, [\s0], \strd
1096.endif
1097.ifnb \d5
1098        vld1.8          {\d5}, [\s1], \strd
1099.endif
1100.ifnb \d6
1101        vld1.8          {\d6}, [\s0], \strd
1102.endif
1103.endm
1104.macro load_16 s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
1105        load_slice      \s0, \s1, \strd, 16, \d0, \d1, \d2, \d3, \d4, \d5, \d6
1106.endm
1107.macro load_32 s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
1108        load_slice      \s0, \s1, \strd, 32, \d0, \d1, \d2, \d3, \d4, \d5, \d6
1109.endm
1110.macro interleave_1_16 r0, r1, r2, r3, r4
1111        vext.8          \r0, \r0, \r1, #6
1112        vext.8          \r1, \r1, \r2, #6
1113.ifnb \r3
1114        vext.8          \r2, \r2, \r3, #6
1115        vext.8          \r3, \r3, \r4, #6
1116.endif
1117.endm
1118.macro interleave_1_32 r0, r1, r2, r3, r4
1119        vext.8          \r0, \r0, \r1, #4
1120        vext.8          \r1, \r1, \r2, #4
1121.ifnb \r3
1122        vext.8          \r2, \r2, \r3, #4
1123        vext.8          \r3, \r3, \r4, #4
1124.endif
1125.endm
1126.macro vmovl_u8 q0, d0, q1, d1, q2, d2, q3, d3, q4, d4, q5, d5, q6, d6
1127        vmovl.u8        \q0, \d0
1128        vmovl.u8        \q1, \d1
1129.ifnb \q2
1130        vmovl.u8        \q2, \d2
1131        vmovl.u8        \q3, \d3
1132.endif
1133.ifnb \q4
1134        vmovl.u8        \q4, \d4
1135.endif
1136.ifnb \q5
1137        vmovl.u8        \q5, \d5
1138.endif
1139.ifnb \q6
1140        vmovl.u8        \q6, \d6
1141.endif
1142.endm
1143.macro mul_mla_4 d, s0, s1, s2, s3
1144        vmul.s16        \d,  \s0,  d0[0]
1145        vmla.s16        \d,  \s1,  d0[1]
1146        vmla.s16        \d,  \s2,  d0[2]
1147        vmla.s16        \d,  \s3,  d0[3]
1148.endm
1149.macro mul_mla_8_1 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8
1150        vmul.s16        \d0, \s0, d0[0]
1151        vmla.s16        \d0, \s1, d0[1]
1152        vmla.s16        \d0, \s2, d0[2]
1153        vmla.s16        \d0, \s3, d0[3]
1154        vmla.s16        \d0, \s4, d1[0]
1155        vmla.s16        \d0, \s5, d1[1]
1156        vmla.s16        \d0, \s6, d1[2]
1157        vmla.s16        \d0, \s7, d1[3]
1158        vmul.s16        \d1, \s1, d0[0]
1159        vmla.s16        \d1, \s2, d0[1]
1160        vmla.s16        \d1, \s3, d0[2]
1161        vmla.s16        \d1, \s4, d0[3]
1162        vmla.s16        \d1, \s5, d1[0]
1163        vmla.s16        \d1, \s6, d1[1]
1164        vmla.s16        \d1, \s7, d1[2]
1165        vmla.s16        \d1, \s8, d1[3]
1166.endm
1167.macro mul_mla_8_2 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9
1168        vmul.s16        \d0, \s0, d0[0]
1169        vmla.s16        \d0, \s1, d0[1]
1170        vmla.s16        \d0, \s2, d0[2]
1171        vmla.s16        \d0, \s3, d0[3]
1172        vmla.s16        \d0, \s4, d1[0]
1173        vmla.s16        \d0, \s5, d1[1]
1174        vmla.s16        \d0, \s6, d1[2]
1175        vmla.s16        \d0, \s7, d1[3]
1176        vmul.s16        \d1, \s2, d0[0]
1177        vmla.s16        \d1, \s3, d0[1]
1178        vmla.s16        \d1, \s4, d0[2]
1179        vmla.s16        \d1, \s5, d0[3]
1180        vmla.s16        \d1, \s6, d1[0]
1181        vmla.s16        \d1, \s7, d1[1]
1182        vmla.s16        \d1, \s8, d1[2]
1183        vmla.s16        \d1, \s9, d1[3]
1184.endm
1185.macro mul_mla_8_4 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11
1186        vmul.s16        \d0, \s0,  d0[0]
1187        vmla.s16        \d0, \s1,  d0[1]
1188        vmla.s16        \d0, \s2,  d0[2]
1189        vmla.s16        \d0, \s3,  d0[3]
1190        vmla.s16        \d0, \s4,  d1[0]
1191        vmla.s16        \d0, \s5,  d1[1]
1192        vmla.s16        \d0, \s6,  d1[2]
1193        vmla.s16        \d0, \s7,  d1[3]
1194        vmul.s16        \d1, \s4,  d0[0]
1195        vmla.s16        \d1, \s5,  d0[1]
1196        vmla.s16        \d1, \s6,  d0[2]
1197        vmla.s16        \d1, \s7,  d0[3]
1198        vmla.s16        \d1, \s8,  d1[0]
1199        vmla.s16        \d1, \s9,  d1[1]
1200        vmla.s16        \d1, \s10, d1[2]
1201        vmla.s16        \d1, \s11, d1[3]
1202.endm
1203.macro vqrshrun_s16 shift, q0, d0, q1, d1, q2, d2, q3, d3
1204        vqrshrun.s16    \d0, \q0, #\shift
1205.ifnb \q1
1206        vqrshrun.s16    \d1, \q1, #\shift
1207.endif
1208.ifnb \q2
1209        vqrshrun.s16    \d2, \q2, #\shift
1210        vqrshrun.s16    \d3, \q3, #\shift
1211.endif
1212.endm
1213.macro vrshr_s16 shift, r0, r1, r2, r3
1214        vrshr.s16       \r0, \r0, #\shift
1215.ifnb \r1
1216        vrshr.s16       \r1, \r1, #\shift
1217.endif
1218.ifnb \r2
1219        vrshr.s16       \r2, \r2, #\shift
1220        vrshr.s16       \r3, \r3, #\shift
1221.endif
1222.endm
1223.macro st_16 strd, reg, lanes
1224        vst1.16         {\reg[0]}, [r0, :16], \strd
1225        vst1.16         {\reg[1]}, [r8, :16], \strd
1226.if \lanes > 2
1227        vst1.16         {\reg[2]}, [r0, :16], \strd
1228        vst1.16         {\reg[3]}, [r8, :16], \strd
1229.endif
1230.endm
1231.macro st_32 strd, r0, r1
1232        vst1.32         {\r0[0]}, [r0, :32], \strd
1233        vst1.32         {\r0[1]}, [r8, :32], \strd
1234.ifnb \r1
1235        vst1.32         {\r1[0]}, [r0, :32], \strd
1236        vst1.32         {\r1[1]}, [r8, :32], \strd
1237.endif
1238.endm
1239.macro st_reg strd, align, r0, r1, r2, r3, r4, r5, r6, r7
1240        vst1.8          {\r0}, [r0, \align], \strd
1241        vst1.8          {\r1}, [r8, \align], \strd
1242.ifnb \r2
1243        vst1.8          {\r2}, [r0, \align], \strd
1244        vst1.8          {\r3}, [r8, \align], \strd
1245.endif
1246.ifnb \r4
1247        vst1.8          {\r4}, [r0, \align], \strd
1248        vst1.8          {\r5}, [r8, \align], \strd
1249        vst1.8          {\r6}, [r0, \align], \strd
1250        vst1.8          {\r7}, [r8, \align], \strd
1251.endif
1252.endm
1253.macro shift_store_4 type, strd, q0, d0, d1, q1, d2, d3
1254.ifc \type, put
1255        vqrshrun_s16    6,     \q0, \d0, \q1, \d2
1256        st_32           \strd, \d0, \d2
1257.else
1258        vrshr_s16       2,          \q0, \q1
1259        st_reg          \strd, :64, \d0, \d1, \d2, \d3
1260.endif
1261.endm
1262.macro shift_store_8 type, strd, q0, d0, q1, d1, q2, d2, q3, d3
1263.ifc \type, put
1264        vqrshrun_s16    6,          \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3
1265        st_reg          \strd, :64, \d0, \d1, \d2, \d3
1266.else
1267        vrshr_s16       2,          \q0, \q1, \q2, \q3
1268        st_reg          \strd, :128,\q0, \q1, \q2, \q3
1269.endif
1270.endm
1271.macro shift_store_16 type, strd, q0, d0, d1, q1, q2, d4, d5, q3
1272.ifc \type, put
1273        vqrshrun.s16    \d0,   \q0, #6
1274        vqrshrun.s16    \d1,   \q1, #6
1275        vqrshrun.s16    \d4,   \q2, #6
1276        vqrshrun.s16    \d5,   \q3, #6
1277        st_reg          \strd, :128, \q0, \q2
1278.else
1279        vrshr_s16       2,     \q0, \q1, \q2, \q3
1280        vst1.16         {\q0, \q1}, [r0, :128], \strd
1281        vst1.16         {\q2, \q3}, [r8, :128], \strd
1282.endif
1283.endm
1284
1285.macro make_8tap_fn op, type, type_h, type_v
1286function \op\()_8tap_\type\()_8bpc_neon, export=1
1287        push            {r4-r11,lr}
1288        movw            r8,  \type_h
1289        movw            r9,  \type_v
1290        b               \op\()_8tap_neon
1291endfunc
1292.endm
1293
1294// No spaces in these expressions, due to gas-preprocessor.
1295#define REGULAR ((0*15<<7)|3*15)
1296#define SMOOTH  ((1*15<<7)|4*15)
1297#define SHARP   ((2*15<<7)|3*15)
1298
1299.macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, my, ds2, sr2, shift_hv
1300make_8tap_fn \type, regular,        REGULAR, REGULAR
1301make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH
1302make_8tap_fn \type, regular_sharp,  REGULAR, SHARP
1303make_8tap_fn \type, smooth,         SMOOTH,  SMOOTH
1304make_8tap_fn \type, smooth_regular, SMOOTH,  REGULAR
1305make_8tap_fn \type, smooth_sharp,   SMOOTH,  SHARP
1306make_8tap_fn \type, sharp,          SHARP,   SHARP
1307make_8tap_fn \type, sharp_regular,  SHARP,   REGULAR
1308make_8tap_fn \type, sharp_smooth,   SHARP,   SMOOTH
1309
1310function \type\()_8tap_neon
1311        ldrd            r4,  r5,  [sp, #36]
1312        ldrd            r6,  r7,  [sp, #44]
1313        movw            r10,  #0x4081  // (1 << 14) | (1 << 7) | (1 << 0)
1314        mul             \mx,  \mx, r10
1315        mul             \my,  \my, r10
1316        add             \mx,  \mx, r8 // mx, 8tap_h, 4tap_h
1317        add             \my,  \my, r9 // my, 8tap_v, 4tap_v
1318.ifc \type, prep
1319        lsl             \d_strd, \w, #1
1320.endif
1321
1322        clz             r8,  \w
1323        tst             \mx, #(0x7f << 14)
1324        sub             r8,  r8,  #24
1325        movrel          r10, X(mc_subpel_filters), -8
1326        bne             L(\type\()_8tap_h)
1327        tst             \my, #(0x7f << 14)
1328        bne             L(\type\()_8tap_v)
1329        b               \type\()_neon
1330
1331L(\type\()_8tap_h):
1332        cmp             \w,  #4
1333        ubfx            r9,  \mx, #7, #7
1334        and             \mx, \mx, #0x7f
1335        it              gt
1336        movgt           \mx,  r9
1337        tst             \my,  #(0x7f << 14)
1338        add             \mx, r10, \mx, lsl #3
1339        bne             L(\type\()_8tap_hv)
1340
1341        adr             r9,  L(\type\()_8tap_h_tbl)
1342        ldr             r8,  [r9, r8, lsl #2]
1343        add             r9,  r9,  r8
1344        bx              r9
1345
1346        .align 2
1347L(\type\()_8tap_h_tbl):
1348        .word 1280f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1349        .word 640f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1350        .word 320f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1351        .word 160f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1352        .word 80f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1353        .word 40f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1354        .word 20f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1355
135620:     // 2xN h
1357.ifc \type, put
1358        add             \mx,  \mx,  #2
1359        vld1.32         {d0[]}, [\mx]
1360        sub             \src,  \src,  #1
1361        add             \ds2,  \dst,  \d_strd
1362        add             \sr2,  \src,  \s_strd
1363        lsl             \d_strd,  \d_strd,  #1
1364        lsl             \s_strd,  \s_strd,  #1
1365        vmovl.s8        q0,  d0
13662:
1367        vld1.8          {d4},  [\src], \s_strd
1368        vld1.8          {d6},  [\sr2], \s_strd
1369        vmovl.u8        q2,  d4
1370        vmovl.u8        q3,  d6
1371        vext.8          d5,  d4,  d5,  #2
1372        vext.8          d7,  d6,  d7,  #2
1373        subs            \h,  \h,  #2
1374        vtrn.32         d4,  d6
1375        vtrn.32         d5,  d7
1376        vmul.s16        d2,  d4,  d0[0]
1377        vmla.s16        d2,  d5,  d0[1]
1378        vmla.s16        d2,  d6,  d0[2]
1379        vmla.s16        d2,  d7,  d0[3]
1380        vrshr.s16       d2,  d2,  #2
1381        vqrshrun.s16    d2,  q1,  #4
1382        vst1.16         {d2[0]}, [\dst, :16], \d_strd
1383        vst1.16         {d2[1]}, [\ds2, :16], \d_strd
1384        bgt             2b
1385        pop             {r4-r11,pc}
1386.endif
1387
138840:     // 4xN h
1389        add             \mx,  \mx,  #2
1390        vld1.32         {d0[]}, [\mx]
1391        sub             \src,  \src,  #1
1392        add             \ds2,  \dst,  \d_strd
1393        add             \sr2,  \src,  \s_strd
1394        lsl             \d_strd,  \d_strd,  #1
1395        lsl             \s_strd,  \s_strd,  #1
1396        vmovl.s8        q0,  d0
13974:
1398        vld1.8          {d16}, [\src], \s_strd
1399        vld1.8          {d24}, [\sr2], \s_strd
1400        vmovl.u8        q8,  d16
1401        vmovl.u8        q12, d24
1402        vext.8          d18, d16, d17, #2
1403        vext.8          d20, d16, d17, #4
1404        vext.8          d22, d16, d17, #6
1405        vext.8          d26, d24, d25, #2
1406        vext.8          d28, d24, d25, #4
1407        vext.8          d30, d24, d25, #6
1408        subs            \h,  \h,  #2
1409        vmul.s16        d4,  d16, d0[0]
1410        vmla.s16        d4,  d18, d0[1]
1411        vmla.s16        d4,  d20, d0[2]
1412        vmla.s16        d4,  d22, d0[3]
1413        vmul.s16        d5,  d24, d0[0]
1414        vmla.s16        d5,  d26, d0[1]
1415        vmla.s16        d5,  d28, d0[2]
1416        vmla.s16        d5,  d30, d0[3]
1417        vrshr.s16       q2,  q2,  #2
1418.ifc \type, put
1419        vqrshrun.s16    d4,  q2,  #4
1420        vst1.32         {d4[0]}, [\dst, :32], \d_strd
1421        vst1.32         {d4[1]}, [\ds2, :32], \d_strd
1422.else
1423        vst1.16         {d4}, [\dst, :64], \d_strd
1424        vst1.16         {d5}, [\ds2, :64], \d_strd
1425.endif
1426        bgt             4b
1427        pop             {r4-r11,pc}
1428
142980:     // 8xN h
1430        vld1.8          {d0}, [\mx, :64]
1431        sub             \src,  \src,  #3
1432        add             \ds2,  \dst,  \d_strd
1433        add             \sr2,  \src,  \s_strd
1434        lsl             \d_strd,  \d_strd,  #1
1435        lsl             \s_strd,  \s_strd,  #1
1436        vmovl.s8        q0,  d0
14378:
1438        vld1.8          {q8},  [\src], \s_strd
1439        vld1.8          {q12}, [\sr2], \s_strd
1440        vmovl.u8        q9,  d17
1441        vmovl.u8        q8,  d16
1442        vmovl.u8        q13, d25
1443        vmovl.u8        q12, d24
1444
1445        vmul.s16        q10, q8,  d0[0]
1446        vmul.s16        q14, q12, d0[0]
1447.irpc i, 1234567
1448        vext.8          q11, q8,  q9,  #(2*\i)
1449        vext.8          q15, q12, q13, #(2*\i)
1450.if \i < 4
1451        vmla.s16        q10, q11, d0[\i]
1452        vmla.s16        q14, q15, d0[\i]
1453.else
1454        vmla.s16        q10, q11, d1[\i-4]
1455        vmla.s16        q14, q15, d1[\i-4]
1456.endif
1457.endr
1458        subs            \h,  \h,  #2
1459        vrshr.s16       q10, q10, #2
1460        vrshr.s16       q14, q14, #2
1461.ifc \type, put
1462        vqrshrun.s16    d20, q10, #4
1463        vqrshrun.s16    d28, q14, #4
1464        vst1.8          {d20}, [\dst, :64], \d_strd
1465        vst1.8          {d28}, [\ds2, :64], \d_strd
1466.else
1467        vst1.16         {q10}, [\dst, :128], \d_strd
1468        vst1.16         {q14}, [\ds2, :128], \d_strd
1469.endif
1470        bgt             8b
1471        pop             {r4-r11,pc}
1472
1473160:
1474320:
1475640:
14761280:   // 16xN, 32xN, ... h
1477        // This could be done without touching q4-q6, by using only
1478        // one temporary for vext in the loop. That's slower on A7 and A53,
1479        // (but surprisingly, marginally faster on A8 and A73).
1480        vpush           {q4-q6}
1481        vld1.8          {d0}, [\mx, :64]
1482        sub             \src,  \src,  #3
1483        add             \ds2,  \dst,  \d_strd
1484        add             \sr2,  \src,  \s_strd
1485        lsl             \s_strd,  \s_strd,  #1
1486        vmovl.s8        q0,  d0
1487
1488        sub             \s_strd,  \s_strd,  \w
1489        sub             \s_strd,  \s_strd,  #8
1490.ifc \type, put
1491        lsl             \d_strd,  \d_strd,  #1
1492        sub             \d_strd,  \d_strd,  \w
1493.endif
1494161:
1495        vld1.8          {d16, d17, d18},  [\src]!
1496        vld1.8          {d24, d25, d26},  [\sr2]!
1497        mov             \mx, \w
1498        vmovl.u8        q10, d18
1499        vmovl.u8        q9,  d17
1500        vmovl.u8        q8,  d16
1501        vmovl.u8        q14, d26
1502        vmovl.u8        q13, d25
1503        vmovl.u8        q12, d24
1504
150516:
1506        vmul.s16        q1,  q8,  d0[0]
1507        vmul.s16        q2,  q9,  d0[0]
1508        vmul.s16        q3,  q12, d0[0]
1509        vmul.s16        q4,  q13, d0[0]
1510.irpc i, 1234567
1511        vext.8          q5,  q8,  q9,  #(2*\i)
1512        vext.8          q6,  q9,  q10, #(2*\i)
1513        vext.8          q11, q12, q13, #(2*\i)
1514        vext.8          q15, q13, q14, #(2*\i)
1515.if \i < 4
1516        vmla.s16        q1,  q5,  d0[\i]
1517        vmla.s16        q2,  q6,  d0[\i]
1518        vmla.s16        q3,  q11, d0[\i]
1519        vmla.s16        q4,  q15, d0[\i]
1520.else
1521        vmla.s16        q1,  q5,  d1[\i-4]
1522        vmla.s16        q2,  q6,  d1[\i-4]
1523        vmla.s16        q3,  q11, d1[\i-4]
1524        vmla.s16        q4,  q15, d1[\i-4]
1525.endif
1526.endr
1527        vrshr.s16       q1,  q1,  #2
1528        vrshr.s16       q2,  q2,  #2
1529        vrshr.s16       q3,  q3,  #2
1530        vrshr.s16       q4,  q4,  #2
1531        subs            \mx, \mx, #16
1532.ifc \type, put
1533        vqrshrun.s16    d2,  q1,  #4
1534        vqrshrun.s16    d3,  q2,  #4
1535        vqrshrun.s16    d4,  q3,  #4
1536        vqrshrun.s16    d5,  q4,  #4
1537        vst1.8          {q1}, [\dst, :128]!
1538        vst1.8          {q2}, [\ds2, :128]!
1539.else
1540        vst1.16         {q1, q2}, [\dst, :128]!
1541        vst1.16         {q3, q4}, [\ds2, :128]!
1542.endif
1543        ble             9f
1544
1545        vmov            q8,  q10
1546        vmov            q12, q14
1547        vld1.8          {d18, d19}, [\src]!
1548        vld1.8          {d26, d27}, [\sr2]!
1549        vmovl.u8        q10, d19
1550        vmovl.u8        q9,  d18
1551        vmovl.u8        q14, d27
1552        vmovl.u8        q13, d26
1553        b               16b
1554
15559:
1556        add             \dst,  \dst,  \d_strd
1557        add             \ds2,  \ds2,  \d_strd
1558        add             \src,  \src,  \s_strd
1559        add             \sr2,  \sr2,  \s_strd
1560
1561        subs            \h,  \h,  #2
1562        bgt             161b
1563        vpop            {q4-q6}
1564        pop             {r4-r11,pc}
1565
1566L(\type\()_8tap_v):
1567        cmp             \h,  #4
1568        ubfx            r9,  \my, #7, #7
1569        and             \my, \my, #0x7f
1570        it              gt
1571        movgt           \my, r9
1572        add             \my, r10, \my, lsl #3
1573
1574        adr             r9,  L(\type\()_8tap_v_tbl)
1575        ldr             r8,  [r9, r8, lsl #2]
1576        add             r9,  r9,  r8
1577        bx              r9
1578
1579        .align 2
1580L(\type\()_8tap_v_tbl):
1581        .word 1280f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1582        .word 640f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1583        .word 320f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1584        .word 160f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1585        .word 80f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1586        .word 40f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1587        .word 20f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1588
158920:     // 2xN v
1590.ifc \type, put
1591        bgt             28f
1592
1593        cmp             \h,  #2
1594        add             \my, \my, #2
1595        vld1.32         {d0[]}, [\my]
1596        sub             \src,  \src,  \s_strd
1597        add             \ds2,  \dst,  \d_strd
1598        add             \sr2,  \src,  \s_strd
1599        lsl             \s_strd,  \s_strd,  #1
1600        lsl             \d_strd,  \d_strd,  #1
1601        vmovl.s8        q0,  d0
1602
1603        // 2x2 v
1604        load_16         \src, \sr2, \s_strd, d1, d2, d3, d4, d5
1605        interleave_1_16 d1, d2, d3, d4, d5
1606        bgt             24f
1607        vmovl_u8        q8, d1, q9, d2, q10, d3, q11, d4
1608        mul_mla_4       d6, d16, d18, d20, d22
1609        vqrshrun_s16    6,   q3,  d6
1610        st_16           \d_strd, d6, 2
1611        pop             {r4-r11,pc}
1612
161324:     // 2x4 v
1614        load_16         \sr2, \src, \s_strd, d6, d7
1615        interleave_1_16 d5, d6, d7
1616        vmovl_u8        q8, d1, q9, d2, q10, d3, q11, d4, q12, d5, q13, d6
1617        vmov            d17, d20
1618        vmov            d19, d22
1619        vmov            d21, d24
1620        vmov            d23, d26
1621        mul_mla_4       q3, q8, q9, q10, q11
1622        vqrshrun_s16    6,   q3,  d6
1623        st_16           \d_strd, d6, 4
1624        pop             {r4-r11,pc}
1625
162628:     // 2x8, 2x16 v
1627        vpush           {q4-q7}
1628        vld1.8          {d0}, [\my, :64]
1629        sub             \sr2,  \src,  \s_strd, lsl #1
1630        add             \ds2,  \dst,  \d_strd
1631        sub             \src,  \sr2,  \s_strd
1632        lsl             \d_strd,  \d_strd,  #1
1633        lsl             \s_strd,  \s_strd,  #1
1634        vmovl.s8        q0,  d0
1635
1636        load_16         \src, \sr2, \s_strd, d2,  d4,  d6,  d8,  d10, d12, d14
1637        interleave_1_16 d2,  d4,  d6,  d8,  d10
1638        interleave_1_16 d10, d12, d14
1639        vmovl_u8        q1,  d2,  q2,  d4,  q3,  d6,  q4,  d8,  q5,  d10, q6,  d12
1640        vmov            d3,  d6
1641        vmov            d5,  d8
1642        vmov            d7,  d10
1643        vmov            d9,  d12
1644216:
1645        subs            \h,  \h,  #8
1646        load_16         \sr2, \src, \s_strd, d16, d18, d20, d22
1647        load_16         \sr2, \src, \s_strd, d24, d26, d28, d30
1648        interleave_1_16 d14, d16, d18, d20, d22
1649        interleave_1_16 d22, d24, d26, d28, d30
1650        vmovl_u8        q7,  d14, q8,  d16, q9,  d18, q10, d20
1651        vmovl_u8        q11, d22, q12, d24, q13, d26, q14, d28
1652        vmov            d11, d14
1653        vmov            d13, d16
1654        vmov            d15, d18
1655        vmov            d17, d20
1656        vmov            d19, d22
1657        vmov            d21, d24
1658        vmov            d23, d26
1659        vmov            d25, d28
1660        mul_mla_8_4     q1,  q2,  q1,  q2,  q3,  q4,  q5,  q6,  q7,  q8,  q9,  q10, q11, q12
1661        vqrshrun_s16    6,   q1,  d2,  q2,  d4
1662        st_16           \d_strd, d2, 4
1663        st_16           \d_strd, d4, 4
1664        ble             0f
1665        vmov            q1,  q9
1666        vmov            q2,  q10
1667        vmov            q3,  q11
1668        vmov            q4,  q12
1669        vmov            q5,  q13
1670        vmov            q6,  q14
1671        vmov            d14, d30
1672        b               216b
16730:
1674        vpop            {q4-q7}
1675        pop             {r4-r11,pc}
1676.endif
1677
167840:
1679        bgt            480f
1680
1681        // 4x2, 4x4 v
1682        cmp             \h,  #2
1683        add             \my, \my, #2
1684        vld1.32         {d0[]}, [\my]
1685        sub             \src, \src, \s_strd
1686        add             \ds2, \dst, \d_strd
1687        add             \sr2, \src, \s_strd
1688        lsl             \s_strd, \s_strd, #1
1689        lsl             \d_strd, \d_strd, #1
1690        vmovl.s8        q0,  d0
1691
1692        load_32         \src, \sr2, \s_strd, d1, d2, d3, d4, d5
1693        interleave_1_32 d1,  d2,  d3,  d4,  d5
1694        vmovl_u8        q8,  d1,  q9,  d2,  q10, d3,  q11, d4
1695        mul_mla_4       q3,  q8,  q9,  q10, q11
1696        shift_store_4   \type, \d_strd, q3, d6, d7
1697        ble             0f
1698        load_32         \sr2, \src, \s_strd, d6, d7
1699        interleave_1_32 d5,  d6,  d7
1700        vmovl_u8        q12, d5,  q13, d6
1701        mul_mla_4       q3,  q10, q11, q12, q13
1702        shift_store_4   \type, \d_strd, q3, d6, d7
17030:
1704        pop             {r4-r11,pc}
1705
1706480:    // 4x8, 4x16 v
1707        vpush           {q4}
1708        vld1.8          {d0}, [\my, :64]
1709        sub             \sr2, \src, \s_strd, lsl #1
1710        add             \ds2, \dst, \d_strd
1711        sub             \src, \sr2, \s_strd
1712        lsl             \s_strd, \s_strd, #1
1713        lsl             \d_strd, \d_strd, #1
1714        vmovl.s8        q0,  d0
1715
1716        load_32         \src, \sr2, \s_strd, d2,  d4,  d6,  d8,  d16, d18, d20
1717        interleave_1_32 d2,  d4,  d6
1718        interleave_1_32 d6,  d8,  d16, d18, d20
1719        vmovl_u8        q1,  d2,  q2,  d4,  q3,  d6,  q4,  d8,  q8,  d16, q9,  d18
1720
172148:
1722        subs            \h,  \h,  #4
1723        load_32         \sr2, \src, \s_strd, d22, d24, d26, d28
1724        interleave_1_32 d20, d22, d24, d26, d28
1725        vmovl_u8        q10, d20, q11, d22, q12, d24, q13, d26
1726        mul_mla_8_2     q1,  q2,  q1,  q2,  q3,  q4,  q8,  q9,  q10, q11, q12, q13
1727        shift_store_4   \type, \d_strd, q1,  d2,  d3,  q2,  d4,  d5
1728        ble             0f
1729        subs            \h,  \h,  #4
1730        load_32         \sr2,  \src, \s_strd, d30, d2,  d4,  d6
1731        interleave_1_32 d28, d30, d2,  d4,  d6
1732        vmovl_u8        q14, d28, q15, d30, q1,  d2,  q2,  d4
1733        mul_mla_8_2     q8,  q9,  q8,  q9,  q10, q11, q12, q13, q14, q15, q1,  q2
1734        shift_store_4   \type, \d_strd, q8,  d16, d17, q9,  d18, d19
1735        ble             0f
1736        subs            \h,  \h,  #4
1737        load_32         \sr2, \src, \s_strd, d8,  d16, d18, d20
1738        interleave_1_32 d6,  d8,  d16, d18, d20
1739        vmovl_u8        q3,  d6,  q4,  d8,  q8,  d16, q9, d18
1740        mul_mla_8_2     q12, q13, q12, q13, q14, q15, q1,  q2,  q3,  q4,  q8,  q9
1741        shift_store_4   \type, \d_strd, q12, d24, d25, q13, d26, d27
1742        bgt             48b
17430:
1744        vpop            {q4}
1745        pop             {r4-r11,pc}
1746
174780:
1748        bgt             880f
1749
1750        // 8x2, 8x4 v
1751        cmp             \h,  #2
1752        add             \my, \my, #2
1753        vld1.32         {d0[]}, [\my]
1754        sub             \src, \src, \s_strd
1755        add             \ds2, \dst, \d_strd
1756        add             \sr2, \src, \s_strd
1757        lsl             \s_strd, \s_strd, #1
1758        lsl             \d_strd, \d_strd, #1
1759        vmovl.s8        q0,  d0
1760
1761        load_reg        \src, \sr2, \s_strd, d1, d2, d3, d4, d5
1762        vmovl_u8        q8,  d1,  q9,  d2,  q10, d3,  q11, d4,  q12, d5
1763        mul_mla_4       q1,  q8,  q9,  q10, q11
1764        mul_mla_4       q2,  q9,  q10, q11, q12
1765        shift_store_8   \type, \d_strd, q1, d2, q2, d4
1766        ble             0f
1767        load_reg        \sr2, \src, \s_strd, d6, d7
1768        vmovl_u8        q13, d6,  q14, d7
1769        mul_mla_4       q1,  q10, q11, q12, q13
1770        mul_mla_4       q2,  q11, q12, q13, q14
1771        shift_store_8   \type, \d_strd, q1, d2, q2, d4
17720:
1773        pop             {r4-r11,pc}
1774
1775880:    // 8x6, 8x8, 8x16, 8x32 v
17761680:   // 16x8, 16x16, ...
1777320:    // 32x8, 32x16, ...
1778640:
17791280:
1780        vpush           {q4}
1781        vld1.8          {d0}, [\my, :64]
1782        sub             \src, \src, \s_strd
1783        sub             \src, \src, \s_strd, lsl #1
1784        vmovl.s8        q0,  d0
1785        mov             \my, \h
1786168:
1787        add             \ds2, \dst, \d_strd
1788        add             \sr2, \src, \s_strd
1789        lsl             \s_strd, \s_strd, #1
1790        lsl             \d_strd, \d_strd, #1
1791
1792        load_reg        \src, \sr2, \s_strd, d2,  d4,  d6,  d8,  d16, d18, d20
1793        vmovl_u8        q1,  d2,  q2,  d4,  q3,  d6,  q4,  d8,  q8,  d16, q9,  d18, q10, d20
1794
179588:
1796        subs            \h,  \h,  #2
1797        load_reg        \sr2, \src, \s_strd, d22, d24
1798        vmovl_u8        q11, d22, q12, d24
1799        mul_mla_8_1     q1,  q2,  q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12
1800        shift_store_8   \type, \d_strd, q1,  d2,  q2,  d4
1801        ble             9f
1802        subs            \h,  \h,  #2
1803        load_reg        \sr2, \src, \s_strd, d26, d28
1804        vmovl_u8        q13, d26, q14, d28
1805        mul_mla_8_1     q3,  q4,  q3,  q4,  q8,  q9,  q10, q11, q12, q13, q14
1806        shift_store_8   \type, \d_strd, q3,  d6,  q4,  d8
1807        ble             9f
1808        subs            \h,  \h,  #2
1809        load_reg        \sr2, \src, \s_strd, d30, d2
1810        vmovl_u8        q15, d30, q1,  d2
1811        mul_mla_8_1     q8,  q9,  q8,  q9,  q10, q11, q12, q13, q14, q15, q1
1812        shift_store_8   \type, \d_strd, q8,  d16, q9,  d18
1813        ble             9f
1814        subs            \h,  \h,  #2
1815        load_reg        \sr2, \src, \s_strd, d4,  d6
1816        vmovl_u8        q2,  d4,  q3,  d6
1817        mul_mla_8_1     q10, q11, q10, q11, q12, q13, q14, q15, q1,  q2,  q3
1818        shift_store_8   \type, \d_strd, q10, d20, q11, d22
1819        ble             9f
1820        subs            \h,  \h,  #4
1821        load_reg        \sr2, \src, \s_strd, d8,  d16, d18, d20
1822        vmovl_u8        q4,  d8,  q8,  d16, q9,  d18, q10, d20
1823        mul_mla_8_1     q12, q13, q12, q13, q14, q15, q1,  q2,  q3,  q4,  q8
1824        mul_mla_8_1     q14, q15, q14, q15, q1,  q2,  q3,  q4,  q8,  q9,  q10
1825        shift_store_8   \type, \d_strd, q12, d24, q13, d26, q14, d28, q15, d30
1826        bgt             88b
18279:
1828        subs            \w,  \w,  #8
1829        ble             0f
1830        asr             \s_strd, \s_strd, #1
1831        asr             \d_strd, \d_strd, #1
1832        mls             \src, \s_strd, \my, \src
1833        mls             \dst, \d_strd, \my, \dst
1834        sub             \src, \src, \s_strd, lsl #3
1835        mov             \h,  \my
1836        add             \src, \src, #8
1837.ifc \type, put
1838        add             \dst, \dst, #8
1839.else
1840        add             \dst, \dst, #16
1841.endif
1842        b               168b
18430:
1844        vpop            {q4}
1845        pop             {r4-r11,pc}
1846
1847160:
1848        bgt             1680b
1849
1850        // 16x2, 16x4 v
1851        add             \my, \my, #2
1852        vld1.32         {d0[]}, [\my]
1853        sub             \src, \src, \s_strd
1854        add             \ds2, \dst, \d_strd
1855        add             \sr2, \src, \s_strd
1856        lsl             \s_strd, \s_strd, #1
1857        lsl             \d_strd, \d_strd, #1
1858        vmovl.s8        q0,  d0
1859
1860        cmp             \h,  #2
1861        load_reg        \src, \sr2, \s_strd, q11, q12, q13, q14, q15
1862        vmovl.u8        q1,  d22
1863        vmovl.u8        q2,  d24
1864        vmovl.u8        q3,  d26
1865        vmovl.u8        q8,  d28
1866        vmovl.u8        q9,  d30
1867        vmovl.u8        q11, d23
1868        vmovl.u8        q12, d25
1869        vmovl.u8        q13, d27
1870        vmovl.u8        q14, d29
1871        vmovl.u8        q15, d31
1872        mul_mla_4       q1,  q1,  q2,  q3,  q8
1873        mul_mla_4       q10, q2,  q3,  q8,  q9
1874        mul_mla_4       q2,  q11, q12, q13, q14
1875        mul_mla_4       q11, q12, q13, q14, q15
1876        shift_store_16  \type, \d_strd, q1, d2, d3, q2, q10, d20, d21, q11
1877        ble             0f
1878        load_reg        \sr2, \src, \s_strd, q10, q11
1879        vmovl.u8        q1,  d20
1880        vmovl.u8        q10, d21
1881        vmovl.u8        q12, d22
1882        vmovl.u8        q11, d23
1883        mul_mla_4       q2,  q3,  q8,  q9,  q1
1884        mul_mla_4       q3,  q13, q14, q15, q10
1885        mul_mla_4       q13, q8,  q9,  q1,  q12
1886        mul_mla_4       q14, q14, q15, q10, q11
1887        shift_store_16  \type, \d_strd, q2, d4, d5, q3, q13, d26, d27, q14
18880:
1889        pop             {r4-r11,pc}
1890
1891L(\type\()_8tap_hv):
1892        cmp             \h,  #4
1893        ubfx            r9,  \my, #7, #7
1894        and             \my, \my, #0x7f
1895        it              gt
1896        movgt           \my, r9
1897        add             \my,  r10, \my, lsl #3
1898
1899        adr             r9,  L(\type\()_8tap_hv_tbl)
1900        ldr             r8,  [r9, r8, lsl #2]
1901        add             r9,  r9,  r8
1902        bx              r9
1903
1904        .align 2
1905L(\type\()_8tap_hv_tbl):
1906        .word 1280f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1907        .word 640f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1908        .word 320f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1909        .word 160f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1910        .word 80f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1911        .word 40f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1912        .word 20f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1913
191420:
1915.ifc \type, put
1916        add             \mx,  \mx,  #2
1917        vld1.32         {d0[]},  [\mx]
1918        bgt             280f
1919        add             \my,  \my,  #2
1920        vld1.32         {d2[]},  [\my]
1921
1922        // 2x2, 2x4 hv
1923        sub             \sr2, \src, #1
1924        sub             \src, \sr2, \s_strd
1925        add             \ds2, \dst, \d_strd
1926        lsl             \s_strd, \s_strd, #1
1927        lsl             \d_strd, \d_strd, #1
1928        vmovl.s8        q0,  d0
1929        vmovl.s8        q1,  d2
1930
1931
1932        vld1.8          {d26}, [\src], \s_strd
1933        vmovl.u8        q13, d26
1934        vext.8          q14, q13, q13, #2
1935        vmul.s16        d26, d26, d0
1936        vmul.s16        d28, d28, d0
1937        vpadd.s16       d26, d26, d28
1938        vpadd.s16       d26, d26, d26
1939        vrshr.s16       d16, d26, #2
1940        bl              L(\type\()_8tap_filter_2)
1941
1942        vext.8          d16, d16, d16, #4
1943        vmov            d17, d26
1944        vext.8          d16, d16, d26, #4
1945
19462:
1947        bl              L(\type\()_8tap_filter_2)
1948
1949        vext.8          d18, d17, d26, #4
1950        vmull.s16       q2,  d16, d2[0]
1951        vmlal.s16       q2,  d17, d2[1]
1952        vmlal.s16       q2,  d18, d2[2]
1953        vmlal.s16       q2,  d26, d2[3]
1954
1955        vqrshrn.s32     d4,  q2,  #\shift_hv
1956        vqmovun.s16     d4,  q2
1957        subs            \h,  \h,  #2
1958        vst1.16         {d4[0]}, [\dst, :16], \d_strd
1959        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
1960        ble             0f
1961        vmov            d16, d18
1962        vmov            d17, d26
1963        b               2b
1964
1965280:    // 2x8, 2x16, 2x32 hv
1966        vld1.8          {d2},  [\my, :64]
1967        sub             \src, \src, #1
1968        sub             \sr2, \src, \s_strd, lsl #1
1969        sub             \src, \sr2, \s_strd
1970        add             \ds2, \dst, \d_strd
1971        lsl             \s_strd, \s_strd, #1
1972        lsl             \d_strd, \d_strd, #1
1973        vmovl.s8        q0,  d0
1974        vmovl.s8        q1,  d2
1975
1976        vld1.8          {d26}, [\src], \s_strd
1977        vmovl.u8        q13, d26
1978        vext.8          q14, q13, q13, #2
1979        vmul.s16        d26, d26, d0
1980        vmul.s16        d28, d28, d0
1981        vpadd.s16       d26, d26, d28
1982        vpadd.s16       d26, d26, d26
1983        vrshr.s16       d16, d26, #2
1984
1985        bl              L(\type\()_8tap_filter_2)
1986        vext.8          d16, d16, d16, #4
1987        vmov            d17, d26
1988        vext.8          d16, d16, d26, #4
1989        bl              L(\type\()_8tap_filter_2)
1990        vext.8          d18, d17, d26, #4
1991        vmov            d19, d26
1992        bl              L(\type\()_8tap_filter_2)
1993        vext.8          d20, d19, d26, #4
1994        vmov            d21, d26
1995
199628:
1997        bl              L(\type\()_8tap_filter_2)
1998        vext.8          d22, d21, d26, #4
1999        vmull.s16       q2,  d16, d2[0]
2000        vmlal.s16       q2,  d17, d2[1]
2001        vmlal.s16       q2,  d18, d2[2]
2002        vmlal.s16       q2,  d19, d2[3]
2003        vmlal.s16       q2,  d20, d3[0]
2004        vmlal.s16       q2,  d21, d3[1]
2005        vmlal.s16       q2,  d22, d3[2]
2006        vmlal.s16       q2,  d26, d3[3]
2007
2008        vqrshrn.s32     d4,  q2,  #\shift_hv
2009        vqmovun.s16     d4,  q2
2010        subs            \h,  \h,  #2
2011        vst1.16         {d4[0]}, [\dst, :16], \d_strd
2012        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
2013        ble             0f
2014        vmov            d16, d18
2015        vmov            d17, d19
2016        vmov            d18, d20
2017        vmov            d19, d21
2018        vmov            d20, d22
2019        vmov            d21, d26
2020        b               28b
2021
20220:
2023        pop             {r4-r11,pc}
2024
2025L(\type\()_8tap_filter_2):
2026        vld1.8          {d28},  [\sr2], \s_strd
2027        vld1.8          {d30},  [\src], \s_strd
2028        vext.8          d29, d28, d28, #1
2029        vext.8          d31, d30, d30, #1
2030        vmovl.u8        q13, d28
2031        vmovl.u8        q14, d29
2032        vmov            d27, d28
2033        vmovl.u8        q14, d30
2034        vmovl.u8        q15, d31
2035        vtrn.32         d26, d28
2036        vtrn.32         d27, d30
2037        vmul.s16        d26, d26, d0[0]
2038        vmla.s16        d26, d27, d0[1]
2039        vmla.s16        d26, d28, d0[2]
2040        vmla.s16        d26, d30, d0[3]
2041        vrshr.s16       d26, d26, #2
2042        vext.8          d27, d26, d26, #4
2043        bx              lr
2044.endif
2045
204640:
2047        add             \mx, \mx, #2
2048        vld1.32         {d0[]},  [\mx]
2049        bgt             480f
2050        add             \my, \my,  #2
2051        vld1.32         {d2[]},  [\my]
2052        sub             \sr2, \src, #1
2053        sub             \src, \sr2, \s_strd
2054        add             \ds2, \dst, \d_strd
2055        lsl             \s_strd, \s_strd, #1
2056        lsl             \d_strd, \d_strd, #1
2057        vmovl.s8        q0,  d0
2058        vmovl.s8        q1,  d2
2059
2060        // 4x2, 4x4 hv
2061        vld1.8          {d30}, [\src], \s_strd
2062        vmovl.u8        q14, d30
2063        vext.8          d27, d28, d29, #2
2064        vext.8          d30, d28, d29, #4
2065        vext.8          d31, d28, d29, #6
2066        vmul.s16        d26, d28, d0[0]
2067        vmla.s16        d26, d27, d0[1]
2068        vmla.s16        d26, d30, d0[2]
2069        vmla.s16        d26, d31, d0[3]
2070        vrshr.s16       d16, d26, #2
2071
2072        bl              L(\type\()_8tap_filter_4)
2073        vmov            d17, d26
2074        vmov            d18, d27
2075
20764:
2077        bl              L(\type\()_8tap_filter_4)
2078        vmull.s16       q2,  d16, d2[0]
2079        vmlal.s16       q2,  d17, d2[1]
2080        vmlal.s16       q2,  d18, d2[2]
2081        vmlal.s16       q2,  d26, d2[3]
2082        vmull.s16       q3,  d17, d2[0]
2083        vmlal.s16       q3,  d18, d2[1]
2084        vmlal.s16       q3,  d26, d2[2]
2085        vmlal.s16       q3,  d27, d2[3]
2086        vqrshrn.s32     d4,  q2,  #\shift_hv
2087        vqrshrn.s32     d6,  q3,  #\shift_hv
2088        subs            \h,  \h,  #2
2089.ifc \type, put
2090        vqmovun.s16     d4,  q2
2091        vqmovun.s16     d6,  q3
2092        vst1.32         {d4[0]}, [\dst, :32], \d_strd
2093        vst1.32         {d6[0]}, [\ds2, :32], \d_strd
2094.else
2095        vst1.16         {d4}, [\dst, :64], \d_strd
2096        vst1.16         {d6}, [\ds2, :64], \d_strd
2097.endif
2098        ble             0f
2099        vmov            d16, d18
2100        vmov            d17, d26
2101        vmov            d18, d27
2102        b               4b
2103
2104480:    // 4x8, 4x16, 4x32 hv
2105        vld1.8          {d2},  [\my, :64]
2106        sub             \src, \src, #1
2107        sub             \sr2, \src, \s_strd, lsl #1
2108        sub             \src, \sr2, \s_strd
2109        add             \ds2, \dst, \d_strd
2110        lsl             \s_strd, \s_strd, #1
2111        lsl             \d_strd, \d_strd, #1
2112        vmovl.s8        q0,  d0
2113        vmovl.s8        q1,  d2
2114
2115        vld1.8          {d30}, [\src], \s_strd
2116        vmovl.u8        q14, d30
2117        vext.8          d27, d28, d29, #2
2118        vext.8          d30, d28, d29, #4
2119        vext.8          d31, d28, d29, #6
2120        vmul.s16        d26, d28, d0[0]
2121        vmla.s16        d26, d27, d0[1]
2122        vmla.s16        d26, d30, d0[2]
2123        vmla.s16        d26, d31, d0[3]
2124        vrshr.s16       d16, d26, #2
2125
2126        bl              L(\type\()_8tap_filter_4)
2127        vmov            d17, d26
2128        vmov            d18, d27
2129        bl              L(\type\()_8tap_filter_4)
2130        vmov            d19, d26
2131        vmov            d20, d27
2132        bl              L(\type\()_8tap_filter_4)
2133        vmov            d21, d26
2134        vmov            d22, d27
2135
213648:
2137        bl              L(\type\()_8tap_filter_4)
2138        vmull.s16       q2,  d16, d2[0]
2139        vmlal.s16       q2,  d17, d2[1]
2140        vmlal.s16       q2,  d18, d2[2]
2141        vmlal.s16       q2,  d19, d2[3]
2142        vmlal.s16       q2,  d20, d3[0]
2143        vmlal.s16       q2,  d21, d3[1]
2144        vmlal.s16       q2,  d22, d3[2]
2145        vmlal.s16       q2,  d26, d3[3]
2146        vmull.s16       q3,  d17, d2[0]
2147        vmlal.s16       q3,  d18, d2[1]
2148        vmlal.s16       q3,  d19, d2[2]
2149        vmlal.s16       q3,  d20, d2[3]
2150        vmlal.s16       q3,  d21, d3[0]
2151        vmlal.s16       q3,  d22, d3[1]
2152        vmlal.s16       q3,  d26, d3[2]
2153        vmlal.s16       q3,  d27, d3[3]
2154        vqrshrn.s32     d4,  q2,  #\shift_hv
2155        vqrshrn.s32     d6,  q3,  #\shift_hv
2156        subs            \h,  \h,  #2
2157.ifc \type, put
2158        vqmovun.s16     d4,  q2
2159        vqmovun.s16     d6,  q3
2160        vst1.32         {d4[0]}, [\dst, :32], \d_strd
2161        vst1.32         {d6[0]}, [\ds2, :32], \d_strd
2162.else
2163        vst1.16         {d4}, [\dst, :64], \d_strd
2164        vst1.16         {d6}, [\ds2, :64], \d_strd
2165.endif
2166        ble             0f
2167        vmov            d16, d18
2168        vmov            d17, d19
2169        vmov            d18, d20
2170        vmov            d19, d21
2171        vmov            d20, d22
2172        vmov            d21, d26
2173        vmov            d22, d27
2174        b               48b
21750:
2176        pop             {r4-r11,pc}
2177
2178L(\type\()_8tap_filter_4):
2179        vld1.8          {d30}, [\sr2], \s_strd
2180        vld1.8          {d31}, [\src], \s_strd
2181        vmovl.u8        q14, d30
2182        vext.8          d27, d28, d29, #2
2183        vext.8          d30, d28, d29, #4
2184        vext.8          d1,  d28, d29, #6
2185        vmul.s16        d26, d28, d0[0]
2186        vmla.s16        d26, d27, d0[1]
2187        vmla.s16        d26, d30, d0[2]
2188        vmla.s16        d26, d1,  d0[3]
2189
2190        vmovl.u8        q14, d31
2191        vext.8          d30, d28, d29, #2
2192        vext.8          d31, d28, d29, #4
2193        vext.8          d1,  d28, d29, #6
2194        vmul.s16        d27, d28, d0[0]
2195        vmla.s16        d27, d30, d0[1]
2196        vmla.s16        d27, d31, d0[2]
2197        vmla.s16        d27, d1,  d0[3]
2198        vrshr.s16       d26, d26, #2
2199        vrshr.s16       d27, d27, #2
2200        bx              lr
2201
220280:
2203160:
2204320:
2205        bgt             880f
2206        vpush           {q4-q7}
2207        add             \my,  \my,  #2
2208        vld1.8          {d0},  [\mx, :64]
2209        vld1.32         {d2[]},  [\my]
2210        sub             \src,  \src,  #3
2211        sub             \src,  \src,  \s_strd
2212        vmovl.s8        q0,  d0
2213        vmovl.s8        q1,  d2
2214        mov             \my, \h
2215
2216164:    // 8x2, 8x4, 16x2, 16x4, 32x2, 32x4 hv
2217        add             \ds2,  \dst,  \d_strd
2218        add             \sr2,  \src,  \s_strd
2219        lsl             \d_strd, \d_strd, #1
2220        lsl             \s_strd, \s_strd, #1
2221
2222        vld1.8          {q14},  [\src], \s_strd
2223        vmovl.u8        q12, d28
2224        vmovl.u8        q13, d29
2225        vmul.s16        q10, q12, d0[0]
2226.irpc i, 123
2227        vext.8          q14, q12, q13, #(2*\i)
2228        vmla.s16        q10, q14, d0[\i]
2229.endr
2230.irpc i, 4567
2231        vext.8          q14, q12, q13, #(2*\i)
2232        vmla.s16        q10, q14, d1[\i-4]
2233.endr
2234        vrshr.s16       q3,  q10, #2
2235
2236        bl              L(\type\()_8tap_filter_8)
2237        vmov            q4,  q10
2238        vmov            q5,  q11
2239
22408:
2241        bl              L(\type\()_8tap_filter_8)
2242        vmull.s16       q12, d6,  d2[0]
2243        vmull.s16       q13, d7,  d2[0]
2244        vmull.s16       q14, d8,  d2[0]
2245        vmull.s16       q15, d9,  d2[0]
2246        vmlal.s16       q12, d8,  d2[1]
2247        vmlal.s16       q13, d9,  d2[1]
2248        vmlal.s16       q14, d10, d2[1]
2249        vmlal.s16       q15, d11, d2[1]
2250        vmlal.s16       q12, d10, d2[2]
2251        vmlal.s16       q13, d11, d2[2]
2252        vmlal.s16       q14, d20, d2[2]
2253        vmlal.s16       q15, d21, d2[2]
2254        vmlal.s16       q12, d20, d2[3]
2255        vmlal.s16       q13, d21, d2[3]
2256        vmlal.s16       q14, d22, d2[3]
2257        vmlal.s16       q15, d23, d2[3]
2258        vqrshrn.s32     d24, q12, #\shift_hv
2259        vqrshrn.s32     d25, q13, #\shift_hv
2260        vqrshrn.s32     d28, q14, #\shift_hv
2261        vqrshrn.s32     d29, q15, #\shift_hv
2262        subs            \h,  \h,  #2
2263.ifc \type, put
2264        vqmovun.s16     d24, q12
2265        vqmovun.s16     d28, q14
2266        vst1.8          {d24}, [\dst, :64], \d_strd
2267        vst1.8          {d28}, [\ds2, :64], \d_strd
2268.else
2269        vst1.16         {q12}, [\dst, :128], \d_strd
2270        vst1.16         {q14}, [\ds2, :128], \d_strd
2271.endif
2272        ble             9f
2273        vmov            q3,  q5
2274        vmov            q4,  q10
2275        vmov            q5,  q11
2276        b               8b
22779:
2278        subs            \w,  \w,  #8
2279        ble             0f
2280        asr             \s_strd,  \s_strd,  #1
2281        asr             \d_strd,  \d_strd,  #1
2282        mls             \src,  \s_strd,  \my,  \src
2283        mls             \dst,  \d_strd,  \my,  \dst
2284        sub             \src,  \src,  \s_strd,  lsl #2
2285        mov             \h,  \my
2286        add             \src,  \src,  #8
2287.ifc \type, put
2288        add             \dst,  \dst,  #8
2289.else
2290        add             \dst,  \dst,  #16
2291.endif
2292        b               164b
2293
2294880:    // 8x8, 8x16, ..., 16x8, ..., 32x8, ... hv
2295640:
22961280:
2297        vpush           {q4-q7}
2298        vld1.8          {d0},  [\mx, :64]
2299        vld1.8          {d2},  [\my, :64]
2300        sub             \src,  \src,  #3
2301        sub             \src,  \src,  \s_strd
2302        sub             \src,  \src,  \s_strd, lsl #1
2303        vmovl.s8        q0,  d0
2304        vmovl.s8        q1,  d2
2305        mov             \my, \h
2306
2307168:
2308        add             \ds2,  \dst,  \d_strd
2309        add             \sr2,  \src,  \s_strd
2310        lsl             \d_strd, \d_strd, #1
2311        lsl             \s_strd, \s_strd, #1
2312
2313        vld1.8          {q14},  [\src], \s_strd
2314        vmovl.u8        q12, d28
2315        vmovl.u8        q13, d29
2316        vmul.s16        q10, q12, d0[0]
2317.irpc i, 123
2318        vext.8          q14, q12, q13, #(2*\i)
2319        vmla.s16        q10, q14, d0[\i]
2320.endr
2321.irpc i, 4567
2322        vext.8          q14, q12, q13, #(2*\i)
2323        vmla.s16        q10, q14, d1[\i-4]
2324.endr
2325        vrshr.s16       q3,  q10, #2
2326
2327        bl              L(\type\()_8tap_filter_8)
2328        vmov            q4,  q10
2329        vmov            q5,  q11
2330        bl              L(\type\()_8tap_filter_8)
2331        vmov            q6,  q10
2332        vmov            q7,  q11
2333        bl              L(\type\()_8tap_filter_8)
2334        vmov            q8,  q10
2335        vmov            q9,  q11
2336
233788:
2338        bl              L(\type\()_8tap_filter_8)
2339        vmull.s16       q12, d6,  d2[0]
2340        vmull.s16       q13, d7,  d2[0]
2341        vmull.s16       q14, d8,  d2[0]
2342        vmull.s16       q15, d9,  d2[0]
2343        vmlal.s16       q12, d8,  d2[1]
2344        vmlal.s16       q13, d9,  d2[1]
2345        vmlal.s16       q14, d10, d2[1]
2346        vmlal.s16       q15, d11, d2[1]
2347        vmlal.s16       q12, d10, d2[2]
2348        vmlal.s16       q13, d11, d2[2]
2349        vmlal.s16       q14, d12, d2[2]
2350        vmlal.s16       q15, d13, d2[2]
2351        vmlal.s16       q12, d12, d2[3]
2352        vmlal.s16       q13, d13, d2[3]
2353        vmlal.s16       q14, d14, d2[3]
2354        vmlal.s16       q15, d15, d2[3]
2355        vmlal.s16       q12, d14, d3[0]
2356        vmlal.s16       q13, d15, d3[0]
2357        vmlal.s16       q14, d16, d3[0]
2358        vmlal.s16       q15, d17, d3[0]
2359        vmlal.s16       q12, d16, d3[1]
2360        vmlal.s16       q13, d17, d3[1]
2361        vmlal.s16       q14, d18, d3[1]
2362        vmlal.s16       q15, d19, d3[1]
2363        vmlal.s16       q12, d18, d3[2]
2364        vmlal.s16       q13, d19, d3[2]
2365        vmlal.s16       q14, d20, d3[2]
2366        vmlal.s16       q15, d21, d3[2]
2367        vmlal.s16       q12, d20, d3[3]
2368        vmlal.s16       q13, d21, d3[3]
2369        vmlal.s16       q14, d22, d3[3]
2370        vmlal.s16       q15, d23, d3[3]
2371        vqrshrn.s32     d24, q12, #\shift_hv
2372        vqrshrn.s32     d25, q13, #\shift_hv
2373        vqrshrn.s32     d28, q14, #\shift_hv
2374        vqrshrn.s32     d29, q15, #\shift_hv
2375        subs            \h,  \h,  #2
2376.ifc \type, put
2377        vqmovun.s16     d24, q12
2378        vqmovun.s16     d28, q14
2379        vst1.8          {d24}, [\dst, :64], \d_strd
2380        vst1.8          {d28}, [\ds2, :64], \d_strd
2381.else
2382        vst1.16         {q12}, [\dst, :128], \d_strd
2383        vst1.16         {q14}, [\ds2, :128], \d_strd
2384.endif
2385        ble             9f
2386        vmov            q3,  q5
2387        vmov            q4,  q6
2388        vmov            q5,  q7
2389        vmov            q6,  q8
2390        vmov            q7,  q9
2391        vmov            q8,  q10
2392        vmov            q9,  q11
2393        b               88b
23949:
2395        subs            \w,  \w,  #8
2396        ble             0f
2397        asr             \s_strd,  \s_strd,  #1
2398        asr             \d_strd,  \d_strd,  #1
2399        mls             \src,  \s_strd,  \my,  \src
2400        mls             \dst,  \d_strd,  \my,  \dst
2401        sub             \src,  \src,  \s_strd,  lsl #3
2402        mov             \h,  \my
2403        add             \src,  \src,  #8
2404.ifc \type, put
2405        add             \dst,  \dst,  #8
2406.else
2407        add             \dst,  \dst,  #16
2408.endif
2409        b               168b
24100:
2411        vpop            {q4-q7}
2412        pop             {r4-r11,pc}
2413
2414L(\type\()_8tap_filter_8):
2415        vld1.8          {q14},  [\sr2], \s_strd
2416        vld1.8          {q15},  [\src], \s_strd
2417        vmovl.u8        q12, d28
2418        vmovl.u8        q13, d29
2419        vmul.s16        q10, q12, d0[0]
2420.irpc i, 123
2421        vext.8          q14, q12, q13, #(2*\i)
2422        vmla.s16        q10, q14, d0[\i]
2423.endr
2424.irpc i, 4567
2425        vext.8          q14, q12, q13, #(2*\i)
2426        vmla.s16        q10, q14, d1[\i-4]
2427.endr
2428        vmovl.u8        q12, d30
2429        vmovl.u8        q13, d31
2430        vmul.s16        q11, q12, d0[0]
2431.irpc i, 123
2432        vext.8          q14, q12, q13, #(2*\i)
2433        vmla.s16        q11, q14, d0[\i]
2434.endr
2435.irpc i, 4567
2436        vext.8          q14, q12, q13, #(2*\i)
2437        vmla.s16        q11, q14, d1[\i-4]
2438.endr
2439        vrshr.s16       q10, q10, #2
2440        vrshr.s16       q11, q11, #2
2441        bx              lr
2442endfunc
2443
2444
2445function \type\()_bilin_8bpc_neon, export=1
2446        push            {r4-r11,lr}
2447        ldrd            r4,  r5,  [sp, #36]
2448        ldrd            r6,  r7,  [sp, #44]
2449        vdup.8          d1,  \mx
2450        vdup.8          d3,  \my
2451        rsb             r8,  \mx, #16
2452        rsb             r9,  \my, #16
2453        vdup.8          d0,  r8
2454        vdup.8          d2,  r9
2455.ifc \type, prep
2456        lsl             \d_strd, \w, #1
2457.endif
2458        clz             r8,  \w
2459        cmp             \mx, #0
2460        sub             r8,  r8,  #24
2461        bne             L(\type\()_bilin_h)
2462        cmp             \my, #0
2463        bne             L(\type\()_bilin_v)
2464        b               \type\()_neon
2465
2466L(\type\()_bilin_h):
2467        cmp             \my, #0
2468        bne             L(\type\()_bilin_hv)
2469
2470        adr             r9,  L(\type\()_bilin_h_tbl)
2471        ldr             r8,  [r9, r8, lsl #2]
2472        add             r9,  r9,  r8
2473        bx              r9
2474
2475        .align 2
2476L(\type\()_bilin_h_tbl):
2477        .word 1280f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2478        .word 640f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2479        .word 320f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2480        .word 160f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2481        .word 80f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2482        .word 40f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2483        .word 20f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2484
248520:     // 2xN h
2486.ifc \type, put
2487        add             \ds2,  \dst,  \d_strd
2488        add             \sr2,  \src,  \s_strd
2489        lsl             \d_strd,  \d_strd,  #1
2490        lsl             \s_strd,  \s_strd,  #1
24912:
2492        vld1.32         {d4[]},  [\src], \s_strd
2493        vld1.32         {d6[]},  [\sr2], \s_strd
2494        vext.8          d5,  d4,  d4, #1
2495        vext.8          d7,  d6,  d6, #1
2496        vtrn.16         q2,  q3
2497        subs            \h,  \h,  #2
2498        vmull.u8        q3,  d4,  d0
2499        vmlal.u8        q3,  d5,  d1
2500        vqrshrn.u16     d4,  q3,  #4
2501        vst1.16         {d4[0]}, [\dst, :16], \d_strd
2502        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
2503        bgt             2b
2504        pop             {r4-r11,pc}
2505.endif
2506
250740:     // 4xN h
2508        add             \ds2,  \dst,  \d_strd
2509        add             \sr2,  \src,  \s_strd
2510        lsl             \d_strd,  \d_strd,  #1
2511        lsl             \s_strd,  \s_strd,  #1
25124:
2513        vld1.8          {d4}, [\src], \s_strd
2514        vld1.8          {d6}, [\sr2], \s_strd
2515        vext.8          d5,  d4,  d4, #1
2516        vext.8          d7,  d6,  d6, #1
2517        vtrn.32         q2,  q3
2518        subs            \h,  \h,  #2
2519        vmull.u8        q3,  d4,  d0
2520        vmlal.u8        q3,  d5,  d1
2521.ifc \type, put
2522        vqrshrn.u16     d4,  q3,  #4
2523        vst1.32         {d4[0]}, [\dst, :32], \d_strd
2524        vst1.32         {d4[1]}, [\ds2, :32], \d_strd
2525.else
2526        vst1.16         {d6}, [\dst, :64], \d_strd
2527        vst1.16         {d7}, [\ds2, :64], \d_strd
2528.endif
2529        bgt             4b
2530        pop             {r4-r11,pc}
2531
253280:     // 8xN h
2533        add             \ds2,  \dst,  \d_strd
2534        add             \sr2,  \src,  \s_strd
2535        lsl             \d_strd,  \d_strd,  #1
2536        lsl             \s_strd,  \s_strd,  #1
25378:
2538        vld1.8          {q8},  [\src], \s_strd
2539        vld1.8          {q10}, [\sr2], \s_strd
2540        vext.8          q9,  q8,  q8,  #1
2541        vext.8          q11, q10, q10, #1
2542        subs            \h,  \h,  #2
2543        vmull.u8        q8,  d16, d0
2544        vmull.u8        q10, d20, d0
2545        vmlal.u8        q8,  d18, d1
2546        vmlal.u8        q10, d22, d1
2547.ifc \type, put
2548        vqrshrn.u16     d16,  q8,  #4
2549        vqrshrn.u16     d18,  q10, #4
2550        vst1.8          {d16}, [\dst, :64], \d_strd
2551        vst1.8          {d18}, [\ds2, :64], \d_strd
2552.else
2553        vst1.16         {q8},  [\dst, :128], \d_strd
2554        vst1.16         {q10}, [\ds2, :128], \d_strd
2555.endif
2556        bgt             8b
2557        pop             {r4-r11,pc}
2558160:
2559320:
2560640:
25611280:   // 16xN, 32xN, ... h
2562        add             \ds2,  \dst,  \d_strd
2563        add             \sr2,  \src,  \s_strd
2564        lsl             \s_strd,  \s_strd,  #1
2565
2566        sub             \s_strd,  \s_strd,  \w
2567        sub             \s_strd,  \s_strd,  #8
2568.ifc \type, put
2569        lsl             \d_strd,  \d_strd,  #1
2570        sub             \d_strd,  \d_strd,  \w
2571.endif
2572161:
2573        vld1.8          {d16},  [\src]!
2574        vld1.8          {d22},  [\sr2]!
2575        mov             \mx, \w
2576
257716:
2578        vld1.8          {d17,d18},  [\src]!
2579        vld1.8          {d23,d24},  [\sr2]!
2580        vext.8          q10, q8,  q9,  #1
2581        vext.8          q13, q11, q12, #1
2582        vmull.u8        q2,  d16, d0
2583        vmull.u8        q3,  d17, d0
2584        vmull.u8        q14, d22, d0
2585        vmull.u8        q15, d23, d0
2586        vmlal.u8        q2,  d20, d1
2587        vmlal.u8        q3,  d21, d1
2588        vmlal.u8        q14, d26, d1
2589        vmlal.u8        q15, d27, d1
2590        subs            \mx, \mx, #16
2591.ifc \type, put
2592        vqrshrn.u16     d4,  q2,  #4
2593        vqrshrn.u16     d5,  q3,  #4
2594        vqrshrn.u16     d28, q14, #4
2595        vqrshrn.u16     d29, q15, #4
2596        vst1.8          {q2},  [\dst, :128]!
2597        vst1.8          {q14}, [\ds2, :128]!
2598.else
2599        vst1.16         {q2,  q3},  [\dst, :128]!
2600        vst1.16         {q14, q15}, [\ds2, :128]!
2601.endif
2602        ble             9f
2603
2604        vmov            d16, d18
2605        vmov            d22, d24
2606        b               16b
2607
26089:
2609        add             \dst,  \dst,  \d_strd
2610        add             \ds2,  \ds2,  \d_strd
2611        add             \src,  \src,  \s_strd
2612        add             \sr2,  \sr2,  \s_strd
2613
2614        subs            \h,  \h,  #2
2615        bgt             161b
2616        pop             {r4-r11,pc}
2617
2618L(\type\()_bilin_v):
2619        cmp             \h,  #4
2620        adr             r9,  L(\type\()_bilin_v_tbl)
2621        ldr             r8,  [r9, r8, lsl #2]
2622        add             r9,  r9,  r8
2623        bx              r9
2624
2625        .align 2
2626L(\type\()_bilin_v_tbl):
2627        .word 1280f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2628        .word 640f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2629        .word 320f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2630        .word 160f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2631        .word 80f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2632        .word 40f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2633        .word 20f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2634
263520:     // 2xN v
2636.ifc \type, put
2637        cmp             \h,  #2
2638        add             \ds2,  \dst,  \d_strd
2639        add             \sr2,  \src,  \s_strd
2640        lsl             \s_strd,  \s_strd,  #1
2641        lsl             \d_strd,  \d_strd,  #1
2642
2643        // 2x2 v
2644        vld1.16         {d16[]}, [\src], \s_strd
2645        bgt             24f
2646        vld1.16         {d17[]}, [\sr2], \s_strd
2647        vld1.16         {d18[]}, [\src], \s_strd
2648        vext.8          d16, d16, d17, #6
2649        vext.8          d17, d17, d18, #6
2650        vmull.u8        q2,  d16, d2
2651        vmlal.u8        q2,  d17, d3
2652        vqrshrn.u16     d4,  q2,  #4
2653        vst1.16         {d4[0]}, [\dst, :16]
2654        vst1.16         {d4[1]}, [\ds2, :16]
2655        pop             {r4-r11,pc}
265624:     // 2x4, 2x8, ... v
2657        vld1.16         {d17[]}, [\sr2], \s_strd
2658        vld1.16         {d18[]}, [\src], \s_strd
2659        vld1.16         {d19[]}, [\sr2], \s_strd
2660        vld1.16         {d20[]}, [\src], \s_strd
2661        vext.8          d16, d16, d17, #6
2662        vext.8          d17, d17, d18, #6
2663        vext.8          d18, d18, d19, #6
2664        vext.8          d19, d19, d20, #6
2665        vtrn.32         d16, d18
2666        vtrn.32         d17, d19
2667        vmull.u8        q2,  d16, d2
2668        vmlal.u8        q2,  d17, d3
2669        subs            \h,  \h,  #4
2670        vqrshrn.u16     d4,  q2,  #4
2671        vst1.16         {d4[0]}, [\dst, :16], \d_strd
2672        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
2673        vst1.16         {d4[2]}, [\dst, :16], \d_strd
2674        vst1.16         {d4[3]}, [\ds2, :16], \d_strd
2675        ble             0f
2676        vmov            d16, d20
2677        b               24b
26780:
2679        pop             {r4-r11,pc}
2680.endif
2681
268240:     // 4xN v
2683        add             \ds2,  \dst,  \d_strd
2684        add             \sr2,  \src,  \s_strd
2685        lsl             \s_strd,  \s_strd,  #1
2686        lsl             \d_strd,  \d_strd,  #1
2687        vld1.32         {d16[]}, [\src], \s_strd
26884:
2689        vld1.32         {d17[]}, [\sr2], \s_strd
2690        vld1.32         {d18[]}, [\src], \s_strd
2691        vext.8          d16, d16, d17, #4
2692        vext.8          d17, d17, d18, #4
2693        vmull.u8        q2,  d16, d2
2694        vmlal.u8        q2,  d17, d3
2695        subs            \h,  \h,  #2
2696.ifc \type, put
2697        vqrshrn.u16     d4,  q2,  #4
2698        vst1.32         {d4[0]}, [\dst, :32], \d_strd
2699        vst1.32         {d4[1]}, [\ds2, :32], \d_strd
2700.else
2701        vst1.16         {d4}, [\dst, :64], \d_strd
2702        vst1.16         {d5}, [\ds2, :64], \d_strd
2703.endif
2704        ble             0f
2705        vmov            d16,  d18
2706        b               4b
27070:
2708        pop             {r4-r11,pc}
2709
271080:     // 8xN v
2711        add             \ds2,  \dst,  \d_strd
2712        add             \sr2,  \src,  \s_strd
2713        lsl             \s_strd,  \s_strd,  #1
2714        lsl             \d_strd,  \d_strd,  #1
2715        vld1.8          {d16}, [\src], \s_strd
27168:
2717        vld1.8          {d17}, [\sr2], \s_strd
2718        vld1.8          {d18}, [\src], \s_strd
2719        vmull.u8        q2,  d16, d2
2720        vmull.u8        q3,  d17, d2
2721        vmlal.u8        q2,  d17, d3
2722        vmlal.u8        q3,  d18, d3
2723        subs            \h,  \h,  #2
2724.ifc \type, put
2725        vqrshrn.u16     d4,  q2,  #4
2726        vqrshrn.u16     d6,  q3,  #4
2727        vst1.8          {d4}, [\dst, :64], \d_strd
2728        vst1.8          {d6}, [\ds2, :64], \d_strd
2729.else
2730        vst1.16         {q2}, [\dst, :128], \d_strd
2731        vst1.16         {q3}, [\ds2, :128], \d_strd
2732.endif
2733        ble             0f
2734        vmov            d16, d18
2735        b               8b
27360:
2737        pop             {r4-r11,pc}
2738
2739160:    // 16xN, 32xN, ...
2740320:
2741640:
27421280:
2743        mov             \my, \h
27441:
2745        add             \ds2, \dst, \d_strd
2746        add             \sr2, \src, \s_strd
2747        lsl             \s_strd, \s_strd, #1
2748        lsl             \d_strd, \d_strd, #1
2749
2750        vld1.8          {q8},  [\src], \s_strd
27512:
2752        vld1.8          {q9},  [\sr2], \s_strd
2753        vld1.8          {q10}, [\src], \s_strd
2754        vmull.u8        q12, d16, d2
2755        vmull.u8        q13, d17, d2
2756        vmull.u8        q14, d18, d2
2757        vmull.u8        q15, d19, d2
2758        vmlal.u8        q12, d18, d3
2759        vmlal.u8        q13, d19, d3
2760        vmlal.u8        q14, d20, d3
2761        vmlal.u8        q15, d21, d3
2762        subs            \h,  \h,  #2
2763.ifc \type, put
2764        vqrshrn.u16     d24, q12, #4
2765        vqrshrn.u16     d25, q13, #4
2766        vqrshrn.u16     d28, q14, #4
2767        vqrshrn.u16     d29, q15, #4
2768        vst1.8          {q12}, [\dst, :128], \d_strd
2769        vst1.8          {q14}, [\ds2, :128], \d_strd
2770.else
2771        vst1.16         {q12, q13}, [\dst, :128], \d_strd
2772        vst1.16         {q14, q15}, [\ds2, :128], \d_strd
2773.endif
2774        ble             9f
2775        vmov            q8,  q10
2776        b               2b
27779:
2778        subs            \w,  \w,  #16
2779        ble             0f
2780        asr             \s_strd, \s_strd, #1
2781        asr             \d_strd, \d_strd, #1
2782        mls             \src, \s_strd, \my, \src
2783        mls             \dst, \d_strd, \my, \dst
2784        sub             \src, \src, \s_strd, lsl #1
2785        mov             \h,  \my
2786        add             \src, \src, #16
2787.ifc \type, put
2788        add             \dst, \dst, #16
2789.else
2790        add             \dst, \dst, #32
2791.endif
2792        b               1b
27930:
2794        pop             {r4-r11,pc}
2795
2796L(\type\()_bilin_hv):
2797        vmovl.u8        q2,  d2
2798        vmovl.u8        q3,  d3
2799        adr             r9,  L(\type\()_bilin_hv_tbl)
2800        ldr             r8,  [r9, r8, lsl #2]
2801        add             r9,  r9,  r8
2802        bx              r9
2803
2804        .align 2
2805L(\type\()_bilin_hv_tbl):
2806        .word 1280f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2807        .word 640f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2808        .word 320f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2809        .word 160f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2810        .word 80f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2811        .word 40f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2812        .word 20f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2813
281420:     // 2xN hv
2815.ifc \type, put
2816        add             \sr2, \src, \s_strd
2817        add             \ds2, \dst, \d_strd
2818        lsl             \s_strd, \s_strd, #1
2819        lsl             \d_strd, \d_strd, #1
2820
2821        vld1.32         {d28[]},  [\src], \s_strd
2822        vext.8          d29, d28, d28, #1
2823        vmull.u8        q8,  d28, d0
2824        vmlal.u8        q8,  d29, d1
2825
28262:
2827        vld1.32         {d28[]},  [\sr2], \s_strd
2828        vld1.32         {d30[]},  [\src], \s_strd
2829        vext.8          d29, d28, d28, #1
2830        vext.8          d31, d30, d30, #1
2831        vtrn.16         d28, d30
2832        vtrn.16         d29, d31
2833        vmull.u8        q9,  d28, d0
2834        vmlal.u8        q9,  d29, d1
2835
2836        vtrn.32         d16, d18
2837
2838        vmul.u16        d20, d16, d4
2839        vmla.u16        d20, d19, d6
2840        vqrshrn.u16     d20, q10, #8
2841        subs            \h,  \h,  #2
2842        vst1.16         {d20[0]}, [\dst, :16], \d_strd
2843        vst1.16         {d20[1]}, [\ds2, :16], \d_strd
2844        ble             0f
2845        vtrn.32         d19, d16
2846        b               2b
28470:
2848        pop             {r4-r11,pc}
2849.endif
2850
285140:     // 4xN hv
2852        add             \sr2, \src, \s_strd
2853        add             \ds2, \dst, \d_strd
2854        lsl             \s_strd, \s_strd, #1
2855        lsl             \d_strd, \d_strd, #1
2856
2857        vld1.8          {d28},  [\src], \s_strd
2858        vext.8          d29, d28, d28, #1
2859        vmull.u8        q8,  d28, d0
2860        vmlal.u8        q8,  d29, d1
2861
28624:
2863        vld1.8          {d28},  [\sr2], \s_strd
2864        vld1.8          {d30},  [\src], \s_strd
2865        vext.8          d29, d28, d28, #1
2866        vext.8          d31, d30, d30, #1
2867        vtrn.32         d28, d30
2868        vtrn.32         d29, d31
2869        vmull.u8        q9,  d28, d0
2870        vmlal.u8        q9,  d29, d1
2871
2872        vmov            d17, d18
2873
2874        vmul.u16        q10, q8, q2
2875        vmla.u16        q10, q9, q3
2876        subs            \h,  \h,  #2
2877.ifc \type, put
2878        vqrshrn.u16     d20, q10, #8
2879        vst1.32         {d20[0]}, [\dst, :32], \d_strd
2880        vst1.32         {d20[1]}, [\ds2, :32], \d_strd
2881.else
2882        vrshr.u16       q10, q10, #4
2883        vst1.16         {d20}, [\dst, :64], \d_strd
2884        vst1.16         {d21}, [\ds2, :64], \d_strd
2885.endif
2886        ble             0f
2887        vmov            d16, d19
2888        b               4b
28890:
2890        pop             {r4-r11,pc}
2891
289280:     // 8xN, 16xN, ... hv
2893160:
2894320:
2895640:
28961280:
2897        mov             \my, \h
2898
28991:
2900        add             \sr2, \src, \s_strd
2901        add             \ds2, \dst, \d_strd
2902        lsl             \s_strd, \s_strd, #1
2903        lsl             \d_strd, \d_strd, #1
2904
2905        vld1.8          {q12},  [\src], \s_strd
2906        vext.8          q13, q12, q12, #1
2907        vmull.u8        q8,  d24, d0
2908        vmlal.u8        q8,  d26, d1
2909
29102:
2911        vld1.8          {q12},  [\sr2], \s_strd
2912        vld1.8          {q14},  [\src], \s_strd
2913        vext.8          q13, q12, q12, #1
2914        vext.8          q15, q14, q14, #1
2915        vmull.u8        q9,  d24, d0
2916        vmlal.u8        q9,  d26, d1
2917        vmull.u8        q10, d28, d0
2918        vmlal.u8        q10, d30, d1
2919
2920        vmul.u16        q8,  q8,  q2
2921        vmla.u16        q8,  q9,  q3
2922        vmul.u16        q9,  q9,  q2
2923        vmla.u16        q9,  q10, q3
2924        subs            \h,  \h,  #2
2925.ifc \type, put
2926        vqrshrn.u16     d16, q8,  #8
2927        vqrshrn.u16     d18, q9,  #8
2928        vst1.8          {d16}, [\dst, :64], \d_strd
2929        vst1.8          {d18}, [\ds2, :64], \d_strd
2930.else
2931        vrshr.u16       q8,  q8,  #4
2932        vrshr.u16       q9,  q9,  #4
2933        vst1.16         {q8}, [\dst, :128], \d_strd
2934        vst1.16         {q9}, [\ds2, :128], \d_strd
2935.endif
2936        ble             9f
2937        vmov            q8,  q10
2938        b               2b
29399:
2940        subs            \w,  \w,  #8
2941        ble             0f
2942        asr             \s_strd,  \s_strd,  #1
2943        asr             \d_strd,  \d_strd,  #1
2944        mls             \src,  \s_strd,  \my,  \src
2945        mls             \dst,  \d_strd,  \my,  \dst
2946        sub             \src,  \src,  \s_strd,  lsl #1
2947        mov             \h,  \my
2948        add             \src,  \src,  #8
2949.ifc \type, put
2950        add             \dst,  \dst,  #8
2951.else
2952        add             \dst,  \dst,  #16
2953.endif
2954        b               1b
29550:
2956        pop             {r4-r11,pc}
2957endfunc
2958.endm
2959
2960filter_fn put,  r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, 10
2961filter_fn prep, r0, r7, r1, r2, r3, r4, r5, r6, r8, r9, 6
2962
2963.macro load_filter_ptr src
2964        asr             r12, \src, #10
2965        add             r12, r11, r12, lsl #3
2966.endm
2967
2968.macro load_filter_coef dst, src, inc
2969        add             \src, \src, \inc
2970        vld1.8          {\dst}, [r12, :64]
2971.endm
2972
2973.macro load_filter_row dst, src, inc
2974        load_filter_ptr \src
2975        load_filter_coef \dst, \src, \inc
2976.endm
2977
2978function warp_filter_horz_neon
2979        load_filter_ptr r5                  // filter 0
2980        vld1.16         {q7}, [r2], r3
2981        vmov.i8         q6,  #128
2982
2983        load_filter_coef d0, r5,  r7        // filter 0
2984        load_filter_row d1,  r5,  r7        // filter 1
2985        load_filter_row d2,  r5,  r7        // filter 2
2986        load_filter_ptr r5                  // filter 3
2987        veor            q7,  q7,  q6        // subtract by 128 to allow using vmull
2988        load_filter_coef d3, r5,  r7        // filter 3
2989        vext.8          d12, d14, d15, #1   // filter 1 pixels
2990        vext.8          d13, d14, d15, #2   // filter 2 pixels
2991        load_filter_ptr r5                  // filter 4
2992        vmull.s8        q2,  d14, d0        // filter 0 output
2993        vmull.s8        q3,  d12, d1        // filter 1 output
2994        load_filter_coef d0, r5,  r7        // filter 4
2995        load_filter_ptr r5                  // filter 5
2996        vext.8          d12, d14, d15, #3   // filter 3 pixels
2997        vmull.s8        q4,  d13, d2        // filter 2 output
2998        vext.8          d13, d14, d15, #4   // filter 4 pixels
2999        vpadd.i16       d4,  d4,  d5        // pixel 0 (4x16)
3000        vpadd.i16       d5,  d6,  d7        // pixel 1 (4x16)
3001        load_filter_coef d1, r5,  r7        // filter 5
3002        load_filter_ptr r5                  // filter 6
3003        vmull.s8        q5,  d12, d3        // filter 3 output
3004        vext.8          d12, d14, d15, #5   // filter 5 pixels
3005        vmull.s8        q3,  d13, d0        // filter 4 output
3006        load_filter_coef d0, r5,  r7        // filter 6
3007        vext.8          d13, d14, d15, #6   // filter 6 pixels
3008        load_filter_ptr r5                  // filter 7
3009        vpadd.i16       d8,  d8,  d9        // pixel 2 (4x16)
3010        vpadd.i16       d9,  d10, d11       // pixel 3 (4x16)
3011        vmull.s8        q5,  d12, d1        // filter 5 output
3012        load_filter_coef d1, r5,  r7        // filter 7
3013        vext.8          d14, d14, d15, #7   // filter 7 pixels
3014        vpadd.i16       d6,  d6,  d7        // pixel 4 (4x16)
3015        vpadd.i16       d10, d10, d11       // pixel 5 (4x16)
3016        vmull.s8        q6,  d13, d0        // filter 6 output
3017        vmull.s8        q7,  d14, d1        // filter 7 output
3018
3019        sub             r5,  r5,  r7, lsl #3
3020
3021        vpadd.i16       d4,  d4,  d5        // pixel 0,1 (2x16)
3022        vpadd.i16       d5,  d8,  d9        // pixel 2,3 (2x16)
3023        vpadd.i16       d12, d12, d13       // pixel 6 (4x16)
3024        vpadd.i16       d14, d14, d15       // pixel 7 (4x16)
3025        vpadd.i16       d6,  d6,  d10       // pixel 4,5 (2x16)
3026        vpadd.i16       d10, d12, d14       // pixel 6,7 (2x16)
3027        vpadd.i16       d4,  d4,  d5        // pixel 0-3
3028        vpadd.i16       d5,  d6,  d10       // pixel 4-7
3029
3030        add             r5,  r5,  r8
3031
3032        bx              lr
3033endfunc
3034
3035// void dav1d_warp_affine_8x8_8bpc_neon(
3036//         pixel *dst, const ptrdiff_t dst_stride,
3037//         const pixel *src, const ptrdiff_t src_stride,
3038//         const int16_t *const abcd, int mx, int my)
3039.macro warp t, shift
3040function warp_affine_8x8\t\()_8bpc_neon, export=1
3041        push            {r4-r11,lr}
3042        vpush           {q4-q7}
3043        ldrd            r4,  r5,  [sp, #100]
3044        ldr             r6,  [sp, #108]
3045        ldrd            r8,  r9,  [r4]
3046        sxth            r7,  r8
3047        asr             r8,  r8, #16
3048        asr             r4,  r9, #16
3049        sxth            r9,  r9
3050        mov             r10, #8
3051        sub             r2,  r2,  r3, lsl #1
3052        sub             r2,  r2,  r3
3053        sub             r2,  r2,  #3
3054        movrel          r11, X(mc_warp_filter), 64*8
3055.ifnb \t
3056        lsl             r1,  r1,  #1
3057.endif
3058        add             r5,  r5,  #512
3059        add             r6,  r6,  #512
3060
3061        bl              warp_filter_horz_neon
3062        vrshr.s16       q8,  q2,  #3
3063        bl              warp_filter_horz_neon
3064        vrshr.s16       q9,  q2,  #3
3065        bl              warp_filter_horz_neon
3066        vrshr.s16       q10, q2,  #3
3067        bl              warp_filter_horz_neon
3068        vrshr.s16       q11, q2,  #3
3069        bl              warp_filter_horz_neon
3070        vrshr.s16       q12, q2,  #3
3071        bl              warp_filter_horz_neon
3072        vrshr.s16       q13, q2,  #3
3073        bl              warp_filter_horz_neon
3074        vrshr.s16       q14, q2,  #3
3075
30761:
3077        bl              warp_filter_horz_neon
3078        vrshr.s16       q15, q2,  #3
3079
3080        load_filter_row d8,  r6,  r9
3081        load_filter_row d9,  r6,  r9
3082        load_filter_row d10, r6,  r9
3083        load_filter_row d11, r6,  r9
3084        load_filter_row d12, r6,  r9
3085        load_filter_row d13, r6,  r9
3086        load_filter_row d14, r6,  r9
3087        load_filter_row d15, r6,  r9
3088        transpose_8x8b  q4,  q5,  q6,  q7,  d8,  d9,  d10, d11, d12, d13, d14, d15
3089        vmovl.s8        q1,  d8
3090        vmovl.s8        q2,  d9
3091        vmovl.s8        q3,  d10
3092        vmovl.s8        q4,  d11
3093        vmovl.s8        q5,  d12
3094        vmovl.s8        q6,  d13
3095
3096        sub             r6,  r6,  r9, lsl #3
3097
3098        // This ordering of vmull/vmlal is highly beneficial for
3099        // Cortex A8/A9/A53 here, but harmful for Cortex A7.
3100        vmull.s16       q0,  d16,  d2
3101        vmlal.s16       q0,  d18,  d4
3102        vmlal.s16       q0,  d20,  d6
3103        vmlal.s16       q0,  d22,  d8
3104        vmlal.s16       q0,  d24,  d10
3105        vmlal.s16       q0,  d26,  d12
3106        vmull.s16       q1,  d17,  d3
3107        vmlal.s16       q1,  d19,  d5
3108        vmlal.s16       q1,  d21,  d7
3109        vmlal.s16       q1,  d23,  d9
3110        vmlal.s16       q1,  d25,  d11
3111        vmlal.s16       q1,  d27,  d13
3112
3113        vmovl.s8        q2,  d14
3114        vmovl.s8        q3,  d15
3115
3116        vmlal.s16       q0,  d28,  d4
3117        vmlal.s16       q0,  d30,  d6
3118        vmlal.s16       q1,  d29,  d5
3119        vmlal.s16       q1,  d31,  d7
3120
3121.ifb \t
3122        vmov.i16        q7,  #128
3123.else
3124        vmov.i16        q7,  #0x800
3125.endif
3126
3127        vmov            q8,  q9
3128        vmov            q9,  q10
3129        vqrshrn.s32     d0,  q0,  #\shift
3130        vmov            q10, q11
3131        vqrshrn.s32     d1,  q1,  #\shift
3132        vmov            q11, q12
3133        vadd.i16        q0,  q0,  q7
3134        vmov            q12, q13
3135.ifb \t
3136        vqmovun.s16     d0,  q0
3137.endif
3138        vmov            q13, q14
3139        vmov            q14, q15
3140        subs            r10, r10, #1
3141.ifnb \t
3142        vst1.16         {q0}, [r0, :128], r1
3143.else
3144        vst1.8          {d0}, [r0, :64], r1
3145.endif
3146
3147        add             r6,  r6,  r4
3148        bgt             1b
3149
3150        vpop            {q4-q7}
3151        pop             {r4-r11,pc}
3152endfunc
3153.endm
3154
3155warp  , 11
3156warp t, 7
3157
3158// void dav1d_emu_edge_8bpc_neon(
3159//         const intptr_t bw, const intptr_t bh,
3160//         const intptr_t iw, const intptr_t ih,
3161//         const intptr_t x, const intptr_t y,
3162//         pixel *dst, const ptrdiff_t dst_stride,
3163//         const pixel *ref, const ptrdiff_t ref_stride)
3164function emu_edge_8bpc_neon, export=1
3165        push            {r4-r11,lr}
3166        ldrd            r4,  r5,  [sp, #36]
3167        ldrd            r6,  r7,  [sp, #44]
3168        ldrd            r8,  r9,  [sp, #52]
3169
3170        // ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride)
3171        // ref += iclip(x, 0, iw - 1)
3172        sub             r12, r3,  #1           // ih - 1
3173        cmp             r5,  r3
3174        sub             lr,  r2,  #1           // iw - 1
3175        it              lt
3176        movlt           r12, r5                // min(y, ih - 1)
3177        cmp             r4,  r2
3178        bic             r12, r12, r12, asr #31 // max(min(y, ih - 1), 0)
3179        it              lt
3180        movlt           lr,  r4                // min(x, iw - 1)
3181        bic             lr,  lr,  lr,  asr #31 // max(min(x, iw - 1), 0)
3182        mla             r8,  r12, r9,  r8      // ref += iclip() * stride
3183        add             r8,  r8,  lr           // ref += iclip()
3184
3185        // bottom_ext = iclip(y + bh - ih, 0, bh - 1)
3186        // top_ext = iclip(-y, 0, bh - 1)
3187        add             r10, r5,  r1           // y + bh
3188        neg             r5,  r5                // -y
3189        sub             r10, r10, r3           // y + bh - ih
3190        sub             r12, r1,  #1           // bh - 1
3191        cmp             r10, r1
3192        bic             r5,  r5,  r5,  asr #31 // max(-y, 0)
3193        it              ge
3194        movge           r10, r12               // min(y + bh - ih, bh-1)
3195        cmp             r5,  r1
3196        bic             r10, r10, r10, asr #31 // max(min(y + bh - ih, bh-1), 0)
3197        it              ge
3198        movge           r5,  r12               // min(max(-y, 0), bh-1)
3199
3200        // right_ext = iclip(x + bw - iw, 0, bw - 1)
3201        // left_ext = iclip(-x, 0, bw - 1)
3202        add             r11, r4,  r0           // x + bw
3203        neg             r4,  r4                // -x
3204        sub             r11, r11, r2           // x + bw - iw
3205        sub             lr,  r0,  #1           // bw - 1
3206        cmp             r11, r0
3207        bic             r4,  r4,  r4,  asr #31 // max(-x, 0)
3208        it              ge
3209        movge           r11, lr                // min(x + bw - iw, bw-1)
3210        cmp             r4,  r0
3211        bic             r11, r11, r11, asr #31 // max(min(x + bw - iw, bw-1), 0)
3212        it              ge
3213        movge           r4,  lr                // min(max(-x, 0), bw - 1)
3214
3215        // center_h = bh - top_ext - bottom_ext
3216        // dst += top_ext * PXSTRIDE(dst_stride)
3217        // center_w = bw - left_ext - right_ext
3218        sub             r1,  r1,  r5           // bh - top_ext
3219        mla             r6,  r5,  r7,  r6
3220        sub             r2,  r0,  r4           // bw - left_ext
3221        sub             r1,  r1,  r10          // center_h = bh - top_ext - bottom_ext
3222        sub             r2,  r2,  r11          // center_w = bw - left_ext - right_ext
3223
3224        mov             r0,  r6                // backup of dst
3225
3226.macro v_loop need_left, need_right
32270:
3228.if \need_left
3229        vld1.8          {d0[], d1[]}, [r8]
3230        mov             r12, r6                // out = dst
3231        mov             r3,  r4
32321:
3233        subs            r3,  r3,  #16
3234        vst1.8          {q0}, [r12, :128]!
3235        bgt             1b
3236.endif
3237        mov             lr,  r8
3238        add             r12, r6,  r4           // out = dst + left_ext
3239        mov             r3,  r2
32401:
3241        vld1.8          {q0, q1}, [lr]!
3242        subs            r3,  r3,  #32
3243.if \need_left
3244        vst1.8          {q0, q1}, [r12]!
3245.else
3246        vst1.8          {q0, q1}, [r12, :128]!
3247.endif
3248        bgt             1b
3249.if \need_right
3250        add             r3,  r8,  r2           // in + center_w
3251        sub             r3,  r3,  #1           // in + center_w - 1
3252        add             r12, r6,  r4           // dst + left_ext
3253        vld1.8          {d0[], d1[]}, [r3]
3254        add             r12, r12, r2           // out = dst + left_ext + center_w
3255        mov             r3,  r11
32561:
3257        subs            r3,  r3,  #16
3258        vst1.8          {q0}, [r12]!
3259        bgt             1b
3260.endif
3261
3262        subs            r1,  r1,  #1           // center_h--
3263        add             r6,  r6,  r7
3264        add             r8,  r8,  r9
3265        bgt             0b
3266.endm
3267
3268        cmp             r4,  #0
3269        beq             2f
3270        // need_left
3271        cmp             r11, #0
3272        beq             3f
3273        // need_left + need_right
3274        v_loop          1,   1
3275        b               5f
3276
32772:
3278        // !need_left
3279        cmp             r11, #0
3280        beq             4f
3281        // !need_left + need_right
3282        v_loop          0,   1
3283        b               5f
3284
32853:
3286        // need_left + !need_right
3287        v_loop          1,   0
3288        b               5f
3289
32904:
3291        // !need_left + !need_right
3292        v_loop          0,   0
3293
32945:
3295        cmp             r10, #0
3296        // Storing the original dst in r0 overwrote bw, recalculate it here
3297        add             r2,  r2,  r4           // center_w + left_ext
3298        add             r2,  r2,  r11          // bw = center_w + left_ext + right_ext
3299
3300        beq             3f
3301        // need_bottom
3302        sub             r8,  r6,  r7           // ref = dst - stride
3303        mov             r4,  r2
33041:
3305        vld1.8          {q0, q1}, [r8, :128]!
3306        mov             r3,  r10
33072:
3308        subs            r3,  r3,  #1
3309        vst1.8          {q0, q1}, [r6, :128], r7
3310        bgt             2b
3311        mls             r6,  r7,  r10,  r6     // dst -= bottom_ext * stride
3312        subs            r4,  r4,  #32          // bw -= 32
3313        add             r6,  r6,  #32          // dst += 32
3314        bgt             1b
3315
33163:
3317        cmp             r5,  #0
3318        beq             3f
3319        // need_top
3320        mls             r6,  r7,  r5,  r0      // dst = stored_dst - top_ext * stride
33211:
3322        vld1.8          {q0, q1}, [r0, :128]!
3323        mov             r3,  r5
33242:
3325        subs            r3,  r3,  #1
3326        vst1.8          {q0, q1}, [r6, :128], r7
3327        bgt             2b
3328        mls             r6,  r7,  r5,  r6      // dst -= top_ext * stride
3329        subs            r2,  r2,  #32          // bw -= 32
3330        add             r6,  r6,  #32          // dst += 32
3331        bgt             1b
3332
33333:
3334        pop             {r4-r11,pc}
3335endfunc
3336