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_0 d0, s0, s1, s2, s3, s4, s5, s6, s7
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.endm
1159.macro mul_mla_8_1 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8
1160        vmul.s16        \d0, \s0, d0[0]
1161        vmla.s16        \d0, \s1, d0[1]
1162        vmla.s16        \d0, \s2, d0[2]
1163        vmla.s16        \d0, \s3, d0[3]
1164        vmla.s16        \d0, \s4, d1[0]
1165        vmla.s16        \d0, \s5, d1[1]
1166        vmla.s16        \d0, \s6, d1[2]
1167        vmla.s16        \d0, \s7, d1[3]
1168        vmul.s16        \d1, \s1, d0[0]
1169        vmla.s16        \d1, \s2, d0[1]
1170        vmla.s16        \d1, \s3, d0[2]
1171        vmla.s16        \d1, \s4, d0[3]
1172        vmla.s16        \d1, \s5, d1[0]
1173        vmla.s16        \d1, \s6, d1[1]
1174        vmla.s16        \d1, \s7, d1[2]
1175        vmla.s16        \d1, \s8, d1[3]
1176.endm
1177.macro mul_mla_8_2 d0, d1, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9
1178        vmul.s16        \d0, \s0, d0[0]
1179        vmla.s16        \d0, \s1, d0[1]
1180        vmla.s16        \d0, \s2, d0[2]
1181        vmla.s16        \d0, \s3, d0[3]
1182        vmla.s16        \d0, \s4, d1[0]
1183        vmla.s16        \d0, \s5, d1[1]
1184        vmla.s16        \d0, \s6, d1[2]
1185        vmla.s16        \d0, \s7, d1[3]
1186        vmul.s16        \d1, \s2, d0[0]
1187        vmla.s16        \d1, \s3, d0[1]
1188        vmla.s16        \d1, \s4, d0[2]
1189        vmla.s16        \d1, \s5, d0[3]
1190        vmla.s16        \d1, \s6, d1[0]
1191        vmla.s16        \d1, \s7, d1[1]
1192        vmla.s16        \d1, \s8, d1[2]
1193        vmla.s16        \d1, \s9, d1[3]
1194.endm
1195.macro vqrshrun_s16 shift, q0, d0, q1, d1, q2, d2, q3, d3
1196        vqrshrun.s16    \d0, \q0, #\shift
1197.ifnb \q1
1198        vqrshrun.s16    \d1, \q1, #\shift
1199.endif
1200.ifnb \q2
1201        vqrshrun.s16    \d2, \q2, #\shift
1202        vqrshrun.s16    \d3, \q3, #\shift
1203.endif
1204.endm
1205.macro vrshr_s16 shift, r0, r1, r2, r3
1206        vrshr.s16       \r0, \r0, #\shift
1207.ifnb \r1
1208        vrshr.s16       \r1, \r1, #\shift
1209.endif
1210.ifnb \r2
1211        vrshr.s16       \r2, \r2, #\shift
1212        vrshr.s16       \r3, \r3, #\shift
1213.endif
1214.endm
1215.macro st_16 strd, reg, lanes
1216        vst1.16         {\reg[0]}, [r0, :16], \strd
1217        vst1.16         {\reg[1]}, [r8, :16], \strd
1218.if \lanes > 2
1219        vst1.16         {\reg[2]}, [r0, :16], \strd
1220        vst1.16         {\reg[3]}, [r8, :16], \strd
1221.endif
1222.endm
1223.macro st_32 strd, r0, r1
1224        vst1.32         {\r0[0]}, [r0, :32], \strd
1225        vst1.32         {\r0[1]}, [r8, :32], \strd
1226.ifnb \r1
1227        vst1.32         {\r1[0]}, [r0, :32], \strd
1228        vst1.32         {\r1[1]}, [r8, :32], \strd
1229.endif
1230.endm
1231.macro st_reg strd, align, r0, r1, r2, r3, r4, r5, r6, r7
1232        vst1.8          {\r0}, [r0, \align], \strd
1233        vst1.8          {\r1}, [r8, \align], \strd
1234.ifnb \r2
1235        vst1.8          {\r2}, [r0, \align], \strd
1236        vst1.8          {\r3}, [r8, \align], \strd
1237.endif
1238.ifnb \r4
1239        vst1.8          {\r4}, [r0, \align], \strd
1240        vst1.8          {\r5}, [r8, \align], \strd
1241        vst1.8          {\r6}, [r0, \align], \strd
1242        vst1.8          {\r7}, [r8, \align], \strd
1243.endif
1244.endm
1245.macro shift_store_4 type, strd, q0, d0, d1, q1, d2, d3
1246.ifc \type, put
1247        vqrshrun_s16    6,     \q0, \d0, \q1, \d2
1248        st_32           \strd, \d0, \d2
1249.else
1250        vrshr_s16       2,          \q0, \q1
1251        st_reg          \strd, :64, \d0, \d1, \d2, \d3
1252.endif
1253.endm
1254.macro shift_store_8 type, strd, q0, d0, q1, d1, q2, d2, q3, d3
1255.ifc \type, put
1256        vqrshrun_s16    6,          \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3
1257        st_reg          \strd, :64, \d0, \d1, \d2, \d3
1258.else
1259        vrshr_s16       2,          \q0, \q1, \q2, \q3
1260        st_reg          \strd, :128,\q0, \q1, \q2, \q3
1261.endif
1262.endm
1263.macro shift_store_16 type, strd, q0, d0, d1, q1, q2, d4, d5, q3
1264.ifc \type, put
1265        vqrshrun.s16    \d0,   \q0, #6
1266        vqrshrun.s16    \d1,   \q1, #6
1267        vqrshrun.s16    \d4,   \q2, #6
1268        vqrshrun.s16    \d5,   \q3, #6
1269        st_reg          \strd, :128, \q0, \q2
1270.else
1271        vrshr_s16       2,     \q0, \q1, \q2, \q3
1272        vst1.16         {\q0, \q1}, [r0, :128], \strd
1273        vst1.16         {\q2, \q3}, [r8, :128], \strd
1274.endif
1275.endm
1276
1277.macro make_8tap_fn op, type, type_h, type_v
1278function \op\()_8tap_\type\()_8bpc_neon, export=1
1279        push            {r4-r11,lr}
1280        movw            r8,  \type_h
1281        movw            r9,  \type_v
1282        b               \op\()_8tap_neon
1283endfunc
1284.endm
1285
1286// No spaces in these expressions, due to gas-preprocessor.
1287#define REGULAR ((0*15<<7)|3*15)
1288#define SMOOTH  ((1*15<<7)|4*15)
1289#define SHARP   ((2*15<<7)|3*15)
1290
1291.macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, my, ds2, sr2, shift_hv
1292make_8tap_fn \type, regular,        REGULAR, REGULAR
1293make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH
1294make_8tap_fn \type, regular_sharp,  REGULAR, SHARP
1295make_8tap_fn \type, smooth,         SMOOTH,  SMOOTH
1296make_8tap_fn \type, smooth_regular, SMOOTH,  REGULAR
1297make_8tap_fn \type, smooth_sharp,   SMOOTH,  SHARP
1298make_8tap_fn \type, sharp,          SHARP,   SHARP
1299make_8tap_fn \type, sharp_regular,  SHARP,   REGULAR
1300make_8tap_fn \type, sharp_smooth,   SHARP,   SMOOTH
1301
1302function \type\()_8tap_neon
1303        ldrd            r4,  r5,  [sp, #36]
1304        ldrd            r6,  r7,  [sp, #44]
1305        movw            r10,  #0x4081  // (1 << 14) | (1 << 7) | (1 << 0)
1306        mul             \mx,  \mx, r10
1307        mul             \my,  \my, r10
1308        add             \mx,  \mx, r8 // mx, 8tap_h, 4tap_h
1309        add             \my,  \my, r9 // my, 8tap_v, 4tap_v
1310.ifc \type, prep
1311        lsl             \d_strd, \w, #1
1312.endif
1313
1314        clz             r8,  \w
1315        tst             \mx, #(0x7f << 14)
1316        sub             r8,  r8,  #24
1317        movrel          r10, X(mc_subpel_filters), -8
1318        bne             L(\type\()_8tap_h)
1319        tst             \my, #(0x7f << 14)
1320        bne             L(\type\()_8tap_v)
1321        b               \type\()_neon
1322
1323L(\type\()_8tap_h):
1324        cmp             \w,  #4
1325        ubfx            r9,  \mx, #7, #7
1326        and             \mx, \mx, #0x7f
1327        it              gt
1328        movgt           \mx,  r9
1329        tst             \my,  #(0x7f << 14)
1330        add             \mx, r10, \mx, lsl #3
1331        bne             L(\type\()_8tap_hv)
1332
1333        adr             r9,  L(\type\()_8tap_h_tbl)
1334        ldr             r8,  [r9, r8, lsl #2]
1335        add             r9,  r9,  r8
1336        bx              r9
1337
1338        .align 2
1339L(\type\()_8tap_h_tbl):
1340        .word 1280f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1341        .word 640f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1342        .word 320f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1343        .word 160f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1344        .word 80f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1345        .word 40f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1346        .word 20f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
1347
134820:     // 2xN h
1349.ifc \type, put
1350        add             \mx,  \mx,  #2
1351        vld1.32         {d0[]}, [\mx]
1352        sub             \src,  \src,  #1
1353        add             \ds2,  \dst,  \d_strd
1354        add             \sr2,  \src,  \s_strd
1355        lsl             \d_strd,  \d_strd,  #1
1356        lsl             \s_strd,  \s_strd,  #1
1357        vmovl.s8        q0,  d0
13582:
1359        vld1.8          {d4},  [\src], \s_strd
1360        vld1.8          {d6},  [\sr2], \s_strd
1361        vmovl.u8        q2,  d4
1362        vmovl.u8        q3,  d6
1363        vext.8          d5,  d4,  d5,  #2
1364        vext.8          d7,  d6,  d7,  #2
1365        subs            \h,  \h,  #2
1366        vtrn.32         d4,  d6
1367        vtrn.32         d5,  d7
1368        vmul.s16        d2,  d4,  d0[0]
1369        vmla.s16        d2,  d5,  d0[1]
1370        vmla.s16        d2,  d6,  d0[2]
1371        vmla.s16        d2,  d7,  d0[3]
1372        vrshr.s16       d2,  d2,  #2
1373        vqrshrun.s16    d2,  q1,  #4
1374        vst1.16         {d2[0]}, [\dst, :16], \d_strd
1375        vst1.16         {d2[1]}, [\ds2, :16], \d_strd
1376        bgt             2b
1377        pop             {r4-r11,pc}
1378.endif
1379
138040:     // 4xN h
1381        add             \mx,  \mx,  #2
1382        vld1.32         {d0[]}, [\mx]
1383        sub             \src,  \src,  #1
1384        add             \ds2,  \dst,  \d_strd
1385        add             \sr2,  \src,  \s_strd
1386        lsl             \d_strd,  \d_strd,  #1
1387        lsl             \s_strd,  \s_strd,  #1
1388        vmovl.s8        q0,  d0
13894:
1390        vld1.8          {d16}, [\src], \s_strd
1391        vld1.8          {d24}, [\sr2], \s_strd
1392        vmovl.u8        q8,  d16
1393        vmovl.u8        q12, d24
1394        vext.8          d18, d16, d17, #2
1395        vext.8          d20, d16, d17, #4
1396        vext.8          d22, d16, d17, #6
1397        vext.8          d26, d24, d25, #2
1398        vext.8          d28, d24, d25, #4
1399        vext.8          d30, d24, d25, #6
1400        subs            \h,  \h,  #2
1401        vmul.s16        d4,  d16, d0[0]
1402        vmla.s16        d4,  d18, d0[1]
1403        vmla.s16        d4,  d20, d0[2]
1404        vmla.s16        d4,  d22, d0[3]
1405        vmul.s16        d5,  d24, d0[0]
1406        vmla.s16        d5,  d26, d0[1]
1407        vmla.s16        d5,  d28, d0[2]
1408        vmla.s16        d5,  d30, d0[3]
1409        vrshr.s16       q2,  q2,  #2
1410.ifc \type, put
1411        vqrshrun.s16    d4,  q2,  #4
1412        vst1.32         {d4[0]}, [\dst, :32], \d_strd
1413        vst1.32         {d4[1]}, [\ds2, :32], \d_strd
1414.else
1415        vst1.16         {d4}, [\dst, :64], \d_strd
1416        vst1.16         {d5}, [\ds2, :64], \d_strd
1417.endif
1418        bgt             4b
1419        pop             {r4-r11,pc}
1420
142180:     // 8xN h
1422        vld1.8          {d0}, [\mx, :64]
1423        sub             \src,  \src,  #3
1424        add             \ds2,  \dst,  \d_strd
1425        add             \sr2,  \src,  \s_strd
1426        lsl             \d_strd,  \d_strd,  #1
1427        lsl             \s_strd,  \s_strd,  #1
1428        vmovl.s8        q0,  d0
14298:
1430        vld1.8          {q8},  [\src], \s_strd
1431        vld1.8          {q12}, [\sr2], \s_strd
1432        vmovl.u8        q9,  d17
1433        vmovl.u8        q8,  d16
1434        vmovl.u8        q13, d25
1435        vmovl.u8        q12, d24
1436
1437        vmul.s16        q10, q8,  d0[0]
1438        vmul.s16        q14, q12, d0[0]
1439.irpc i, 1234567
1440        vext.8          q11, q8,  q9,  #(2*\i)
1441        vext.8          q15, q12, q13, #(2*\i)
1442.if \i < 4
1443        vmla.s16        q10, q11, d0[\i]
1444        vmla.s16        q14, q15, d0[\i]
1445.else
1446        vmla.s16        q10, q11, d1[\i-4]
1447        vmla.s16        q14, q15, d1[\i-4]
1448.endif
1449.endr
1450        subs            \h,  \h,  #2
1451        vrshr.s16       q10, q10, #2
1452        vrshr.s16       q14, q14, #2
1453.ifc \type, put
1454        vqrshrun.s16    d20, q10, #4
1455        vqrshrun.s16    d28, q14, #4
1456        vst1.8          {d20}, [\dst, :64], \d_strd
1457        vst1.8          {d28}, [\ds2, :64], \d_strd
1458.else
1459        vst1.16         {q10}, [\dst, :128], \d_strd
1460        vst1.16         {q14}, [\ds2, :128], \d_strd
1461.endif
1462        bgt             8b
1463        pop             {r4-r11,pc}
1464
1465160:
1466320:
1467640:
14681280:   // 16xN, 32xN, ... h
1469        // This could be done without touching q4-q6, by using only
1470        // one temporary for vext in the loop. That's slower on A7 and A53,
1471        // (but surprisingly, marginally faster on A8 and A73).
1472        vpush           {q4-q6}
1473        vld1.8          {d0}, [\mx, :64]
1474        sub             \src,  \src,  #3
1475        add             \ds2,  \dst,  \d_strd
1476        add             \sr2,  \src,  \s_strd
1477        lsl             \s_strd,  \s_strd,  #1
1478        vmovl.s8        q0,  d0
1479
1480        sub             \s_strd,  \s_strd,  \w
1481        sub             \s_strd,  \s_strd,  #8
1482.ifc \type, put
1483        lsl             \d_strd,  \d_strd,  #1
1484        sub             \d_strd,  \d_strd,  \w
1485.endif
1486161:
1487        vld1.8          {d16, d17, d18},  [\src]!
1488        vld1.8          {d24, d25, d26},  [\sr2]!
1489        mov             \mx, \w
1490        vmovl.u8        q10, d18
1491        vmovl.u8        q9,  d17
1492        vmovl.u8        q8,  d16
1493        vmovl.u8        q14, d26
1494        vmovl.u8        q13, d25
1495        vmovl.u8        q12, d24
1496
149716:
1498        vmul.s16        q1,  q8,  d0[0]
1499        vmul.s16        q2,  q9,  d0[0]
1500        vmul.s16        q3,  q12, d0[0]
1501        vmul.s16        q4,  q13, d0[0]
1502.irpc i, 1234567
1503        vext.8          q5,  q8,  q9,  #(2*\i)
1504        vext.8          q6,  q9,  q10, #(2*\i)
1505        vext.8          q11, q12, q13, #(2*\i)
1506        vext.8          q15, q13, q14, #(2*\i)
1507.if \i < 4
1508        vmla.s16        q1,  q5,  d0[\i]
1509        vmla.s16        q2,  q6,  d0[\i]
1510        vmla.s16        q3,  q11, d0[\i]
1511        vmla.s16        q4,  q15, d0[\i]
1512.else
1513        vmla.s16        q1,  q5,  d1[\i-4]
1514        vmla.s16        q2,  q6,  d1[\i-4]
1515        vmla.s16        q3,  q11, d1[\i-4]
1516        vmla.s16        q4,  q15, d1[\i-4]
1517.endif
1518.endr
1519        vrshr.s16       q1,  q1,  #2
1520        vrshr.s16       q2,  q2,  #2
1521        vrshr.s16       q3,  q3,  #2
1522        vrshr.s16       q4,  q4,  #2
1523        subs            \mx, \mx, #16
1524.ifc \type, put
1525        vqrshrun.s16    d2,  q1,  #4
1526        vqrshrun.s16    d3,  q2,  #4
1527        vqrshrun.s16    d4,  q3,  #4
1528        vqrshrun.s16    d5,  q4,  #4
1529        vst1.8          {q1}, [\dst, :128]!
1530        vst1.8          {q2}, [\ds2, :128]!
1531.else
1532        vst1.16         {q1, q2}, [\dst, :128]!
1533        vst1.16         {q3, q4}, [\ds2, :128]!
1534.endif
1535        ble             9f
1536
1537        vmov            q8,  q10
1538        vmov            q12, q14
1539        vld1.8          {d18, d19}, [\src]!
1540        vld1.8          {d26, d27}, [\sr2]!
1541        vmovl.u8        q10, d19
1542        vmovl.u8        q9,  d18
1543        vmovl.u8        q14, d27
1544        vmovl.u8        q13, d26
1545        b               16b
1546
15479:
1548        add             \dst,  \dst,  \d_strd
1549        add             \ds2,  \ds2,  \d_strd
1550        add             \src,  \src,  \s_strd
1551        add             \sr2,  \sr2,  \s_strd
1552
1553        subs            \h,  \h,  #2
1554        bgt             161b
1555        vpop            {q4-q6}
1556        pop             {r4-r11,pc}
1557
1558L(\type\()_8tap_v):
1559        cmp             \h,  #4
1560        ubfx            r9,  \my, #7, #7
1561        and             \my, \my, #0x7f
1562        it              gt
1563        movgt           \my, r9
1564        add             \my, r10, \my, lsl #3
1565
1566        adr             r9,  L(\type\()_8tap_v_tbl)
1567        ldr             r8,  [r9, r8, lsl #2]
1568        add             r9,  r9,  r8
1569        bx              r9
1570
1571        .align 2
1572L(\type\()_8tap_v_tbl):
1573        .word 1280f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1574        .word 640f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1575        .word 320f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1576        .word 160f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1577        .word 80f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1578        .word 40f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1579        .word 20f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
1580
158120:     // 2xN v
1582.ifc \type, put
1583        bgt             28f
1584
1585        cmp             \h,  #2
1586        add             \my, \my, #2
1587        vld1.32         {d0[]}, [\my]
1588        sub             \src,  \src,  \s_strd
1589        add             \ds2,  \dst,  \d_strd
1590        add             \sr2,  \src,  \s_strd
1591        lsl             \s_strd,  \s_strd,  #1
1592        lsl             \d_strd,  \d_strd,  #1
1593        vmovl.s8        q0,  d0
1594
1595        // 2x2 v
1596        load_16         \src, \sr2, \s_strd, d1, d2, d3, d4, d5
1597        interleave_1_16 d1, d2, d3, d4, d5
1598        bgt             24f
1599        vmovl_u8        q8, d1, q9, d2, q10, d3, q11, d4
1600        mul_mla_4       d6, d16, d18, d20, d22
1601        vqrshrun_s16    6,   q3,  d6
1602        st_16           \d_strd, d6, 2
1603        pop             {r4-r11,pc}
1604
160524:     // 2x4 v
1606        load_16         \sr2, \src, \s_strd, d6, d7
1607        interleave_1_16 d5, d6, d7
1608        vmovl_u8        q8, d1, q9, d2, q10, d3, q11, d4, q12, d5, q13, d6
1609        vmov            d17, d20
1610        vmov            d19, d22
1611        vmov            d21, d24
1612        vmov            d23, d26
1613        mul_mla_4       q3, q8, q9, q10, q11
1614        vqrshrun_s16    6,   q3,  d6
1615        st_16           \d_strd, d6, 4
1616        pop             {r4-r11,pc}
1617
161828:     // 2x6, 2x8, 2x12, 2x16 v
1619        vpush           {q4-q7}
1620        vld1.8          {d0}, [\my, :64]
1621        sub             \sr2,  \src,  \s_strd, lsl #1
1622        add             \ds2,  \dst,  \d_strd
1623        sub             \src,  \sr2,  \s_strd
1624        lsl             \d_strd,  \d_strd,  #1
1625        lsl             \s_strd,  \s_strd,  #1
1626        vmovl.s8        q0,  d0
1627
1628        load_16         \src, \sr2, \s_strd, d2,  d4,  d6,  d8,  d10, d12, d14
1629        interleave_1_16 d2,  d4,  d6,  d8,  d10
1630        interleave_1_16 d10, d12, d14
1631        vmovl_u8        q1,  d2,  q2,  d4,  q3,  d6,  q4,  d8,  q5,  d10, q6,  d12
1632        vmov            d3,  d6
1633        vmov            d5,  d8
1634        vmov            d7,  d10
1635        vmov            d9,  d12
1636216:
1637        subs            \h,  \h,  #4
1638        load_16         \sr2, \src, \s_strd, d16, d18, d20, d22
1639        interleave_1_16 d14, d16, d18, d20, d22
1640        vmovl_u8        q7,  d14, q8,  d16, q9,  d18, q10, d20
1641        vmov            d11, d14
1642        vmov            d13, d16
1643        vmov            d15, d18
1644        vmov            d17, d20
1645        mul_mla_8_0     q1,  q1,  q2,  q3,  q4,  q5,  q6,  q7, q8
1646        vqrshrun_s16    6,   q1,  d2
1647        st_16           \d_strd, d2, 4
1648        ble             0f
1649        cmp             \h,  #2
1650        vmov            q1,  q5
1651        vmov            q2,  q6
1652        vmov            q3,  q7
1653        vmov            q4,  q8
1654        vmov            q5,  q9
1655        vmov            q6,  q10
1656        vmov            d14, d22
1657        beq             26f
1658        b               216b
165926:
1660        load_16         \sr2, \src, \s_strd, d16, d18
1661        interleave_1_16 d14, d16, d18
1662        vmovl_u8        q7,  d14, q8,  d16
1663        vmov            d11, d14
1664        vmov            d13, d16
1665        mul_mla_8_0     d2,  d2,  d4,  d6,  d8,  d10, d12, d14, d16
1666        vqrshrun_s16    6,   q1,  d2
1667        st_16           \d_strd, d2, 2
16680:
1669        vpop            {q4-q7}
1670        pop             {r4-r11,pc}
1671.endif
1672
167340:
1674        bgt            480f
1675
1676        // 4x2, 4x4 v
1677        cmp             \h,  #2
1678        add             \my, \my, #2
1679        vld1.32         {d0[]}, [\my]
1680        sub             \src, \src, \s_strd
1681        add             \ds2, \dst, \d_strd
1682        add             \sr2, \src, \s_strd
1683        lsl             \s_strd, \s_strd, #1
1684        lsl             \d_strd, \d_strd, #1
1685        vmovl.s8        q0,  d0
1686
1687        load_32         \src, \sr2, \s_strd, d1, d2, d3, d4, d5
1688        interleave_1_32 d1,  d2,  d3,  d4,  d5
1689        vmovl_u8        q8,  d1,  q9,  d2,  q10, d3,  q11, d4
1690        mul_mla_4       q3,  q8,  q9,  q10, q11
1691        shift_store_4   \type, \d_strd, q3, d6, d7
1692        ble             0f
1693        load_32         \sr2, \src, \s_strd, d6, d7
1694        interleave_1_32 d5,  d6,  d7
1695        vmovl_u8        q12, d5,  q13, d6
1696        mul_mla_4       q3,  q10, q11, q12, q13
1697        shift_store_4   \type, \d_strd, q3, d6, d7
16980:
1699        pop             {r4-r11,pc}
1700
1701480:    // 4x6, 4x8, 4x12, 4x16 v
1702        vpush           {q4}
1703        vld1.8          {d0}, [\my, :64]
1704        sub             \sr2, \src, \s_strd, lsl #1
1705        add             \ds2, \dst, \d_strd
1706        sub             \src, \sr2, \s_strd
1707        lsl             \s_strd, \s_strd, #1
1708        lsl             \d_strd, \d_strd, #1
1709        vmovl.s8        q0,  d0
1710
1711        load_32         \src, \sr2, \s_strd, d2,  d4,  d6,  d8,  d16, d18, d20
1712        interleave_1_32 d2,  d4,  d6
1713        interleave_1_32 d6,  d8,  d16, d18, d20
1714        vmovl_u8        q1,  d2,  q2,  d4,  q3,  d6,  q4,  d8,  q8,  d16, q9,  d18
1715
171648:
1717        subs            \h,  \h,  #4
1718        load_32         \sr2, \src, \s_strd, d22, d24, d26, d28
1719        interleave_1_32 d20, d22, d24, d26, d28
1720        vmovl_u8        q10, d20, q11, d22, q12, d24, q13, d26
1721        mul_mla_8_2     q1,  q2,  q1,  q2,  q3,  q4,  q8,  q9,  q10, q11, q12, q13
1722        shift_store_4   \type, \d_strd, q1,  d2,  d3,  q2,  d4,  d5
1723        ble             0f
1724        load_32         \sr2,  \src, \s_strd, d30, d2
1725        subs            \h,  \h,  #2
1726        interleave_1_32 d28, d30, d2
1727        vmovl_u8        q14, d28, q15, d30
1728        mul_mla_8_0     q8,  q8,  q9,  q10, q11, q12, q13, q14, q15
1729        shift_store_4   \type, \d_strd, q8,  d16, d17
1730        ble             0f
1731        load_32         \sr2,  \src, \s_strd, d4,  d6
1732        subs            \h,  \h,  #2
1733        interleave_1_32 d2,  d4,  d6
1734        vmovl_u8        q1,  d2,  q2,  d4
1735        mul_mla_8_0     q9,  q10, q11, q12, q13, q14, q15, q1,  q2
1736        shift_store_4   \type, \d_strd, q9,  d18, d19
1737        ble             0f
1738        subs            \h,  \h,  #4
1739        load_32         \sr2, \src, \s_strd, d8,  d16, d18, d20
1740        interleave_1_32 d6,  d8,  d16, d18, d20
1741        vmovl_u8        q3,  d6,  q4,  d8,  q8,  d16, q9, d18
1742        mul_mla_8_2     q12, q13, q12, q13, q14, q15, q1,  q2,  q3,  q4,  q8,  q9
1743        shift_store_4   \type, \d_strd, q12, d24, d25, q13, d26, d27
1744        bgt             48b
17450:
1746        vpop            {q4}
1747        pop             {r4-r11,pc}
1748
174980:
1750        bgt             880f
1751
1752        // 8x2, 8x4 v
1753        cmp             \h,  #2
1754        add             \my, \my, #2
1755        vld1.32         {d0[]}, [\my]
1756        sub             \src, \src, \s_strd
1757        add             \ds2, \dst, \d_strd
1758        add             \sr2, \src, \s_strd
1759        lsl             \s_strd, \s_strd, #1
1760        lsl             \d_strd, \d_strd, #1
1761        vmovl.s8        q0,  d0
1762
1763        load_reg        \src, \sr2, \s_strd, d1, d2, d3, d4, d5
1764        vmovl_u8        q8,  d1,  q9,  d2,  q10, d3,  q11, d4,  q12, d5
1765        mul_mla_4       q1,  q8,  q9,  q10, q11
1766        mul_mla_4       q2,  q9,  q10, q11, q12
1767        shift_store_8   \type, \d_strd, q1, d2, q2, d4
1768        ble             0f
1769        load_reg        \sr2, \src, \s_strd, d6, d7
1770        vmovl_u8        q13, d6,  q14, d7
1771        mul_mla_4       q1,  q10, q11, q12, q13
1772        mul_mla_4       q2,  q11, q12, q13, q14
1773        shift_store_8   \type, \d_strd, q1, d2, q2, d4
17740:
1775        pop             {r4-r11,pc}
1776
1777880:    // 8x6, 8x8, 8x16, 8x32 v
17781680:   // 16x8, 16x16, ...
1779320:    // 32x8, 32x16, ...
1780640:
17811280:
1782        vpush           {q4}
1783        vld1.8          {d0}, [\my, :64]
1784        sub             \src, \src, \s_strd
1785        sub             \src, \src, \s_strd, lsl #1
1786        vmovl.s8        q0,  d0
1787        mov             \my, \h
1788168:
1789        add             \ds2, \dst, \d_strd
1790        add             \sr2, \src, \s_strd
1791        lsl             \s_strd, \s_strd, #1
1792        lsl             \d_strd, \d_strd, #1
1793
1794        load_reg        \src, \sr2, \s_strd, d2,  d4,  d6,  d8,  d16, d18, d20
1795        vmovl_u8        q1,  d2,  q2,  d4,  q3,  d6,  q4,  d8,  q8,  d16, q9,  d18, q10, d20
1796
179788:
1798        subs            \h,  \h,  #2
1799        load_reg        \sr2, \src, \s_strd, d22, d24
1800        vmovl_u8        q11, d22, q12, d24
1801        mul_mla_8_1     q1,  q2,  q1,  q2,  q3,  q4,  q8,  q9,  q10,  q11, q12
1802        shift_store_8   \type, \d_strd, q1,  d2,  q2,  d4
1803        ble             9f
1804        subs            \h,  \h,  #2
1805        load_reg        \sr2, \src, \s_strd, d26, d28
1806        vmovl_u8        q13, d26, q14, d28
1807        mul_mla_8_1     q3,  q4,  q3,  q4,  q8,  q9,  q10, q11, q12, q13, q14
1808        shift_store_8   \type, \d_strd, q3,  d6,  q4,  d8
1809        ble             9f
1810        subs            \h,  \h,  #2
1811        load_reg        \sr2, \src, \s_strd, d30, d2
1812        vmovl_u8        q15, d30, q1,  d2
1813        mul_mla_8_1     q8,  q9,  q8,  q9,  q10, q11, q12, q13, q14, q15, q1
1814        shift_store_8   \type, \d_strd, q8,  d16, q9,  d18
1815        ble             9f
1816        subs            \h,  \h,  #2
1817        load_reg        \sr2, \src, \s_strd, d4,  d6
1818        vmovl_u8        q2,  d4,  q3,  d6
1819        mul_mla_8_1     q10, q11, q10, q11, q12, q13, q14, q15, q1,  q2,  q3
1820        shift_store_8   \type, \d_strd, q10, d20, q11, d22
1821        ble             9f
1822        subs            \h,  \h,  #4
1823        load_reg        \sr2, \src, \s_strd, d8,  d16, d18, d20
1824        vmovl_u8        q4,  d8,  q8,  d16, q9,  d18, q10, d20
1825        mul_mla_8_1     q12, q13, q12, q13, q14, q15, q1,  q2,  q3,  q4,  q8
1826        mul_mla_8_1     q14, q15, q14, q15, q1,  q2,  q3,  q4,  q8,  q9,  q10
1827        shift_store_8   \type, \d_strd, q12, d24, q13, d26, q14, d28, q15, d30
1828        bgt             88b
18299:
1830        subs            \w,  \w,  #8
1831        ble             0f
1832        asr             \s_strd, \s_strd, #1
1833        asr             \d_strd, \d_strd, #1
1834        mls             \src, \s_strd, \my, \src
1835        mls             \dst, \d_strd, \my, \dst
1836        sub             \src, \src, \s_strd, lsl #3
1837        mov             \h,  \my
1838        add             \src, \src, #8
1839.ifc \type, put
1840        add             \dst, \dst, #8
1841.else
1842        add             \dst, \dst, #16
1843.endif
1844        b               168b
18450:
1846        vpop            {q4}
1847        pop             {r4-r11,pc}
1848
1849160:
1850        bgt             1680b
1851
1852        // 16x2, 16x4 v
1853        add             \my, \my, #2
1854        vld1.32         {d0[]}, [\my]
1855        sub             \src, \src, \s_strd
1856        add             \ds2, \dst, \d_strd
1857        add             \sr2, \src, \s_strd
1858        lsl             \s_strd, \s_strd, #1
1859        lsl             \d_strd, \d_strd, #1
1860        vmovl.s8        q0,  d0
1861
1862        cmp             \h,  #2
1863        load_reg        \src, \sr2, \s_strd, q11, q12, q13, q14, q15
1864        vmovl.u8        q1,  d22
1865        vmovl.u8        q2,  d24
1866        vmovl.u8        q3,  d26
1867        vmovl.u8        q8,  d28
1868        vmovl.u8        q9,  d30
1869        vmovl.u8        q11, d23
1870        vmovl.u8        q12, d25
1871        vmovl.u8        q13, d27
1872        vmovl.u8        q14, d29
1873        vmovl.u8        q15, d31
1874        mul_mla_4       q1,  q1,  q2,  q3,  q8
1875        mul_mla_4       q10, q2,  q3,  q8,  q9
1876        mul_mla_4       q2,  q11, q12, q13, q14
1877        mul_mla_4       q11, q12, q13, q14, q15
1878        shift_store_16  \type, \d_strd, q1, d2, d3, q2, q10, d20, d21, q11
1879        ble             0f
1880        load_reg        \sr2, \src, \s_strd, q10, q11
1881        vmovl.u8        q1,  d20
1882        vmovl.u8        q10, d21
1883        vmovl.u8        q12, d22
1884        vmovl.u8        q11, d23
1885        mul_mla_4       q2,  q3,  q8,  q9,  q1
1886        mul_mla_4       q3,  q13, q14, q15, q10
1887        mul_mla_4       q13, q8,  q9,  q1,  q12
1888        mul_mla_4       q14, q14, q15, q10, q11
1889        shift_store_16  \type, \d_strd, q2, d4, d5, q3, q13, d26, d27, q14
18900:
1891        pop             {r4-r11,pc}
1892
1893L(\type\()_8tap_hv):
1894        cmp             \h,  #4
1895        ubfx            r9,  \my, #7, #7
1896        and             \my, \my, #0x7f
1897        it              gt
1898        movgt           \my, r9
1899        add             \my,  r10, \my, lsl #3
1900
1901        adr             r9,  L(\type\()_8tap_hv_tbl)
1902        ldr             r8,  [r9, r8, lsl #2]
1903        add             r9,  r9,  r8
1904        bx              r9
1905
1906        .align 2
1907L(\type\()_8tap_hv_tbl):
1908        .word 1280f - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1909        .word 640f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1910        .word 320f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1911        .word 160f  - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1912        .word 80f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1913        .word 40f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1914        .word 20f   - L(\type\()_8tap_hv_tbl) + CONFIG_THUMB
1915
191620:
1917.ifc \type, put
1918        add             \mx,  \mx,  #2
1919        vld1.32         {d0[]},  [\mx]
1920        bgt             280f
1921        add             \my,  \my,  #2
1922        vld1.32         {d2[]},  [\my]
1923
1924        // 2x2, 2x4 hv
1925        sub             \sr2, \src, #1
1926        sub             \src, \sr2, \s_strd
1927        add             \ds2, \dst, \d_strd
1928        lsl             \s_strd, \s_strd, #1
1929        lsl             \d_strd, \d_strd, #1
1930        vmovl.s8        q0,  d0
1931        vmovl.s8        q1,  d2
1932
1933
1934        vld1.8          {d26}, [\src], \s_strd
1935        vmovl.u8        q13, d26
1936        vext.8          q14, q13, q13, #2
1937        vmul.s16        d26, d26, d0
1938        vmul.s16        d28, d28, d0
1939        vpadd.s16       d26, d26, d28
1940        vpadd.s16       d26, d26, d26
1941        vrshr.s16       d16, d26, #2
1942        bl              L(\type\()_8tap_filter_2)
1943
1944        vext.8          d16, d16, d16, #4
1945        vmov            d17, d26
1946        vext.8          d16, d16, d26, #4
1947
19482:
1949        bl              L(\type\()_8tap_filter_2)
1950
1951        vext.8          d18, d17, d26, #4
1952        vmull.s16       q2,  d16, d2[0]
1953        vmlal.s16       q2,  d17, d2[1]
1954        vmlal.s16       q2,  d18, d2[2]
1955        vmlal.s16       q2,  d26, d2[3]
1956
1957        vqrshrn.s32     d4,  q2,  #\shift_hv
1958        vqmovun.s16     d4,  q2
1959        subs            \h,  \h,  #2
1960        vst1.16         {d4[0]}, [\dst, :16], \d_strd
1961        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
1962        ble             0f
1963        vmov            d16, d18
1964        vmov            d17, d26
1965        b               2b
1966
1967280:    // 2x8, 2x16, 2x32 hv
1968        vld1.8          {d2},  [\my, :64]
1969        sub             \src, \src, #1
1970        sub             \sr2, \src, \s_strd, lsl #1
1971        sub             \src, \sr2, \s_strd
1972        add             \ds2, \dst, \d_strd
1973        lsl             \s_strd, \s_strd, #1
1974        lsl             \d_strd, \d_strd, #1
1975        vmovl.s8        q0,  d0
1976        vmovl.s8        q1,  d2
1977
1978        vld1.8          {d26}, [\src], \s_strd
1979        vmovl.u8        q13, d26
1980        vext.8          q14, q13, q13, #2
1981        vmul.s16        d26, d26, d0
1982        vmul.s16        d28, d28, d0
1983        vpadd.s16       d26, d26, d28
1984        vpadd.s16       d26, d26, d26
1985        vrshr.s16       d16, d26, #2
1986
1987        bl              L(\type\()_8tap_filter_2)
1988        vext.8          d16, d16, d16, #4
1989        vmov            d17, d26
1990        vext.8          d16, d16, d26, #4
1991        bl              L(\type\()_8tap_filter_2)
1992        vext.8          d18, d17, d26, #4
1993        vmov            d19, d26
1994        bl              L(\type\()_8tap_filter_2)
1995        vext.8          d20, d19, d26, #4
1996        vmov            d21, d26
1997
199828:
1999        bl              L(\type\()_8tap_filter_2)
2000        vext.8          d22, d21, d26, #4
2001        vmull.s16       q2,  d16, d2[0]
2002        vmlal.s16       q2,  d17, d2[1]
2003        vmlal.s16       q2,  d18, d2[2]
2004        vmlal.s16       q2,  d19, d2[3]
2005        vmlal.s16       q2,  d20, d3[0]
2006        vmlal.s16       q2,  d21, d3[1]
2007        vmlal.s16       q2,  d22, d3[2]
2008        vmlal.s16       q2,  d26, d3[3]
2009
2010        vqrshrn.s32     d4,  q2,  #\shift_hv
2011        vqmovun.s16     d4,  q2
2012        subs            \h,  \h,  #2
2013        vst1.16         {d4[0]}, [\dst, :16], \d_strd
2014        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
2015        ble             0f
2016        vmov            d16, d18
2017        vmov            d17, d19
2018        vmov            d18, d20
2019        vmov            d19, d21
2020        vmov            d20, d22
2021        vmov            d21, d26
2022        b               28b
2023
20240:
2025        pop             {r4-r11,pc}
2026
2027L(\type\()_8tap_filter_2):
2028        vld1.8          {d28},  [\sr2], \s_strd
2029        vld1.8          {d30},  [\src], \s_strd
2030        vext.8          d29, d28, d28, #1
2031        vext.8          d31, d30, d30, #1
2032        vmovl.u8        q13, d28
2033        vmovl.u8        q14, d29
2034        vmov            d27, d28
2035        vmovl.u8        q14, d30
2036        vmovl.u8        q15, d31
2037        vtrn.32         d26, d28
2038        vtrn.32         d27, d30
2039        vmul.s16        d26, d26, d0[0]
2040        vmla.s16        d26, d27, d0[1]
2041        vmla.s16        d26, d28, d0[2]
2042        vmla.s16        d26, d30, d0[3]
2043        vrshr.s16       d26, d26, #2
2044        vext.8          d27, d26, d26, #4
2045        bx              lr
2046.endif
2047
204840:
2049        add             \mx, \mx, #2
2050        vld1.32         {d0[]},  [\mx]
2051        bgt             480f
2052        add             \my, \my,  #2
2053        vld1.32         {d2[]},  [\my]
2054        sub             \sr2, \src, #1
2055        sub             \src, \sr2, \s_strd
2056        add             \ds2, \dst, \d_strd
2057        lsl             \s_strd, \s_strd, #1
2058        lsl             \d_strd, \d_strd, #1
2059        vmovl.s8        q0,  d0
2060        vmovl.s8        q1,  d2
2061
2062        // 4x2, 4x4 hv
2063        vld1.8          {d30}, [\src], \s_strd
2064        vmovl.u8        q14, d30
2065        vext.8          d27, d28, d29, #2
2066        vext.8          d30, d28, d29, #4
2067        vext.8          d31, d28, d29, #6
2068        vmul.s16        d26, d28, d0[0]
2069        vmla.s16        d26, d27, d0[1]
2070        vmla.s16        d26, d30, d0[2]
2071        vmla.s16        d26, d31, d0[3]
2072        vrshr.s16       d16, d26, #2
2073
2074        bl              L(\type\()_8tap_filter_4)
2075        vmov            d17, d26
2076        vmov            d18, d27
2077
20784:
2079        bl              L(\type\()_8tap_filter_4)
2080        vmull.s16       q2,  d16, d2[0]
2081        vmlal.s16       q2,  d17, d2[1]
2082        vmlal.s16       q2,  d18, d2[2]
2083        vmlal.s16       q2,  d26, d2[3]
2084        vmull.s16       q3,  d17, d2[0]
2085        vmlal.s16       q3,  d18, d2[1]
2086        vmlal.s16       q3,  d26, d2[2]
2087        vmlal.s16       q3,  d27, d2[3]
2088        vqrshrn.s32     d4,  q2,  #\shift_hv
2089        vqrshrn.s32     d6,  q3,  #\shift_hv
2090        subs            \h,  \h,  #2
2091.ifc \type, put
2092        vqmovun.s16     d4,  q2
2093        vqmovun.s16     d6,  q3
2094        vst1.32         {d4[0]}, [\dst, :32], \d_strd
2095        vst1.32         {d6[0]}, [\ds2, :32], \d_strd
2096.else
2097        vst1.16         {d4}, [\dst, :64], \d_strd
2098        vst1.16         {d6}, [\ds2, :64], \d_strd
2099.endif
2100        ble             0f
2101        vmov            d16, d18
2102        vmov            d17, d26
2103        vmov            d18, d27
2104        b               4b
2105
2106480:    // 4x8, 4x16, 4x32 hv
2107        vld1.8          {d2},  [\my, :64]
2108        sub             \src, \src, #1
2109        sub             \sr2, \src, \s_strd, lsl #1
2110        sub             \src, \sr2, \s_strd
2111        add             \ds2, \dst, \d_strd
2112        lsl             \s_strd, \s_strd, #1
2113        lsl             \d_strd, \d_strd, #1
2114        vmovl.s8        q0,  d0
2115        vmovl.s8        q1,  d2
2116
2117        vld1.8          {d30}, [\src], \s_strd
2118        vmovl.u8        q14, d30
2119        vext.8          d27, d28, d29, #2
2120        vext.8          d30, d28, d29, #4
2121        vext.8          d31, d28, d29, #6
2122        vmul.s16        d26, d28, d0[0]
2123        vmla.s16        d26, d27, d0[1]
2124        vmla.s16        d26, d30, d0[2]
2125        vmla.s16        d26, d31, d0[3]
2126        vrshr.s16       d16, d26, #2
2127
2128        bl              L(\type\()_8tap_filter_4)
2129        vmov            d17, d26
2130        vmov            d18, d27
2131        bl              L(\type\()_8tap_filter_4)
2132        vmov            d19, d26
2133        vmov            d20, d27
2134        bl              L(\type\()_8tap_filter_4)
2135        vmov            d21, d26
2136        vmov            d22, d27
2137
213848:
2139        bl              L(\type\()_8tap_filter_4)
2140        vmull.s16       q2,  d16, d2[0]
2141        vmlal.s16       q2,  d17, d2[1]
2142        vmlal.s16       q2,  d18, d2[2]
2143        vmlal.s16       q2,  d19, d2[3]
2144        vmlal.s16       q2,  d20, d3[0]
2145        vmlal.s16       q2,  d21, d3[1]
2146        vmlal.s16       q2,  d22, d3[2]
2147        vmlal.s16       q2,  d26, d3[3]
2148        vmull.s16       q3,  d17, d2[0]
2149        vmlal.s16       q3,  d18, d2[1]
2150        vmlal.s16       q3,  d19, d2[2]
2151        vmlal.s16       q3,  d20, d2[3]
2152        vmlal.s16       q3,  d21, d3[0]
2153        vmlal.s16       q3,  d22, d3[1]
2154        vmlal.s16       q3,  d26, d3[2]
2155        vmlal.s16       q3,  d27, d3[3]
2156        vqrshrn.s32     d4,  q2,  #\shift_hv
2157        vqrshrn.s32     d6,  q3,  #\shift_hv
2158        subs            \h,  \h,  #2
2159.ifc \type, put
2160        vqmovun.s16     d4,  q2
2161        vqmovun.s16     d6,  q3
2162        vst1.32         {d4[0]}, [\dst, :32], \d_strd
2163        vst1.32         {d6[0]}, [\ds2, :32], \d_strd
2164.else
2165        vst1.16         {d4}, [\dst, :64], \d_strd
2166        vst1.16         {d6}, [\ds2, :64], \d_strd
2167.endif
2168        ble             0f
2169        vmov            d16, d18
2170        vmov            d17, d19
2171        vmov            d18, d20
2172        vmov            d19, d21
2173        vmov            d20, d22
2174        vmov            d21, d26
2175        vmov            d22, d27
2176        b               48b
21770:
2178        pop             {r4-r11,pc}
2179
2180L(\type\()_8tap_filter_4):
2181        vld1.8          {d30}, [\sr2], \s_strd
2182        vld1.8          {d31}, [\src], \s_strd
2183        vmovl.u8        q14, d30
2184        vext.8          d27, d28, d29, #2
2185        vext.8          d30, d28, d29, #4
2186        vext.8          d1,  d28, d29, #6
2187        vmul.s16        d26, d28, d0[0]
2188        vmla.s16        d26, d27, d0[1]
2189        vmla.s16        d26, d30, d0[2]
2190        vmla.s16        d26, d1,  d0[3]
2191
2192        vmovl.u8        q14, d31
2193        vext.8          d30, d28, d29, #2
2194        vext.8          d31, d28, d29, #4
2195        vext.8          d1,  d28, d29, #6
2196        vmul.s16        d27, d28, d0[0]
2197        vmla.s16        d27, d30, d0[1]
2198        vmla.s16        d27, d31, d0[2]
2199        vmla.s16        d27, d1,  d0[3]
2200        vrshr.s16       d26, d26, #2
2201        vrshr.s16       d27, d27, #2
2202        bx              lr
2203
220480:
2205160:
2206320:
2207        bgt             880f
2208        vpush           {q4-q7}
2209        add             \my,  \my,  #2
2210        vld1.8          {d0},  [\mx, :64]
2211        vld1.32         {d2[]},  [\my]
2212        sub             \src,  \src,  #3
2213        sub             \src,  \src,  \s_strd
2214        vmovl.s8        q0,  d0
2215        vmovl.s8        q1,  d2
2216        mov             \my, \h
2217
2218164:    // 8x2, 8x4, 16x2, 16x4, 32x2, 32x4 hv
2219        add             \ds2,  \dst,  \d_strd
2220        add             \sr2,  \src,  \s_strd
2221        lsl             \d_strd, \d_strd, #1
2222        lsl             \s_strd, \s_strd, #1
2223
2224        vld1.8          {q14},  [\src], \s_strd
2225        vmovl.u8        q12, d28
2226        vmovl.u8        q13, d29
2227        vmul.s16        q10, q12, d0[0]
2228.irpc i, 123
2229        vext.8          q14, q12, q13, #(2*\i)
2230        vmla.s16        q10, q14, d0[\i]
2231.endr
2232.irpc i, 4567
2233        vext.8          q14, q12, q13, #(2*\i)
2234        vmla.s16        q10, q14, d1[\i-4]
2235.endr
2236        vrshr.s16       q3,  q10, #2
2237
2238        bl              L(\type\()_8tap_filter_8)
2239        vmov            q4,  q10
2240        vmov            q5,  q11
2241
22428:
2243        bl              L(\type\()_8tap_filter_8)
2244        vmull.s16       q12, d6,  d2[0]
2245        vmull.s16       q13, d7,  d2[0]
2246        vmull.s16       q14, d8,  d2[0]
2247        vmull.s16       q15, d9,  d2[0]
2248        vmlal.s16       q12, d8,  d2[1]
2249        vmlal.s16       q13, d9,  d2[1]
2250        vmlal.s16       q14, d10, d2[1]
2251        vmlal.s16       q15, d11, d2[1]
2252        vmlal.s16       q12, d10, d2[2]
2253        vmlal.s16       q13, d11, d2[2]
2254        vmlal.s16       q14, d20, d2[2]
2255        vmlal.s16       q15, d21, d2[2]
2256        vmlal.s16       q12, d20, d2[3]
2257        vmlal.s16       q13, d21, d2[3]
2258        vmlal.s16       q14, d22, d2[3]
2259        vmlal.s16       q15, d23, d2[3]
2260        vqrshrn.s32     d24, q12, #\shift_hv
2261        vqrshrn.s32     d25, q13, #\shift_hv
2262        vqrshrn.s32     d28, q14, #\shift_hv
2263        vqrshrn.s32     d29, q15, #\shift_hv
2264        subs            \h,  \h,  #2
2265.ifc \type, put
2266        vqmovun.s16     d24, q12
2267        vqmovun.s16     d28, q14
2268        vst1.8          {d24}, [\dst, :64], \d_strd
2269        vst1.8          {d28}, [\ds2, :64], \d_strd
2270.else
2271        vst1.16         {q12}, [\dst, :128], \d_strd
2272        vst1.16         {q14}, [\ds2, :128], \d_strd
2273.endif
2274        ble             9f
2275        vmov            q3,  q5
2276        vmov            q4,  q10
2277        vmov            q5,  q11
2278        b               8b
22799:
2280        subs            \w,  \w,  #8
2281        ble             0f
2282        asr             \s_strd,  \s_strd,  #1
2283        asr             \d_strd,  \d_strd,  #1
2284        mls             \src,  \s_strd,  \my,  \src
2285        mls             \dst,  \d_strd,  \my,  \dst
2286        sub             \src,  \src,  \s_strd,  lsl #2
2287        mov             \h,  \my
2288        add             \src,  \src,  #8
2289.ifc \type, put
2290        add             \dst,  \dst,  #8
2291.else
2292        add             \dst,  \dst,  #16
2293.endif
2294        b               164b
2295
2296880:    // 8x8, 8x16, ..., 16x8, ..., 32x8, ... hv
2297640:
22981280:
2299        vpush           {q4-q7}
2300        vld1.8          {d0},  [\mx, :64]
2301        vld1.8          {d2},  [\my, :64]
2302        sub             \src,  \src,  #3
2303        sub             \src,  \src,  \s_strd
2304        sub             \src,  \src,  \s_strd, lsl #1
2305        vmovl.s8        q0,  d0
2306        vmovl.s8        q1,  d2
2307        mov             \my, \h
2308
2309168:
2310        add             \ds2,  \dst,  \d_strd
2311        add             \sr2,  \src,  \s_strd
2312        lsl             \d_strd, \d_strd, #1
2313        lsl             \s_strd, \s_strd, #1
2314
2315        vld1.8          {q14},  [\src], \s_strd
2316        vmovl.u8        q12, d28
2317        vmovl.u8        q13, d29
2318        vmul.s16        q10, q12, d0[0]
2319.irpc i, 123
2320        vext.8          q14, q12, q13, #(2*\i)
2321        vmla.s16        q10, q14, d0[\i]
2322.endr
2323.irpc i, 4567
2324        vext.8          q14, q12, q13, #(2*\i)
2325        vmla.s16        q10, q14, d1[\i-4]
2326.endr
2327        vrshr.s16       q3,  q10, #2
2328
2329        bl              L(\type\()_8tap_filter_8)
2330        vmov            q4,  q10
2331        vmov            q5,  q11
2332        bl              L(\type\()_8tap_filter_8)
2333        vmov            q6,  q10
2334        vmov            q7,  q11
2335        bl              L(\type\()_8tap_filter_8)
2336        vmov            q8,  q10
2337        vmov            q9,  q11
2338
233988:
2340        bl              L(\type\()_8tap_filter_8)
2341        vmull.s16       q12, d6,  d2[0]
2342        vmull.s16       q13, d7,  d2[0]
2343        vmull.s16       q14, d8,  d2[0]
2344        vmull.s16       q15, d9,  d2[0]
2345        vmlal.s16       q12, d8,  d2[1]
2346        vmlal.s16       q13, d9,  d2[1]
2347        vmlal.s16       q14, d10, d2[1]
2348        vmlal.s16       q15, d11, d2[1]
2349        vmlal.s16       q12, d10, d2[2]
2350        vmlal.s16       q13, d11, d2[2]
2351        vmlal.s16       q14, d12, d2[2]
2352        vmlal.s16       q15, d13, d2[2]
2353        vmlal.s16       q12, d12, d2[3]
2354        vmlal.s16       q13, d13, d2[3]
2355        vmlal.s16       q14, d14, d2[3]
2356        vmlal.s16       q15, d15, d2[3]
2357        vmlal.s16       q12, d14, d3[0]
2358        vmlal.s16       q13, d15, d3[0]
2359        vmlal.s16       q14, d16, d3[0]
2360        vmlal.s16       q15, d17, d3[0]
2361        vmlal.s16       q12, d16, d3[1]
2362        vmlal.s16       q13, d17, d3[1]
2363        vmlal.s16       q14, d18, d3[1]
2364        vmlal.s16       q15, d19, d3[1]
2365        vmlal.s16       q12, d18, d3[2]
2366        vmlal.s16       q13, d19, d3[2]
2367        vmlal.s16       q14, d20, d3[2]
2368        vmlal.s16       q15, d21, d3[2]
2369        vmlal.s16       q12, d20, d3[3]
2370        vmlal.s16       q13, d21, d3[3]
2371        vmlal.s16       q14, d22, d3[3]
2372        vmlal.s16       q15, d23, d3[3]
2373        vqrshrn.s32     d24, q12, #\shift_hv
2374        vqrshrn.s32     d25, q13, #\shift_hv
2375        vqrshrn.s32     d28, q14, #\shift_hv
2376        vqrshrn.s32     d29, q15, #\shift_hv
2377        subs            \h,  \h,  #2
2378.ifc \type, put
2379        vqmovun.s16     d24, q12
2380        vqmovun.s16     d28, q14
2381        vst1.8          {d24}, [\dst, :64], \d_strd
2382        vst1.8          {d28}, [\ds2, :64], \d_strd
2383.else
2384        vst1.16         {q12}, [\dst, :128], \d_strd
2385        vst1.16         {q14}, [\ds2, :128], \d_strd
2386.endif
2387        ble             9f
2388        vmov            q3,  q5
2389        vmov            q4,  q6
2390        vmov            q5,  q7
2391        vmov            q6,  q8
2392        vmov            q7,  q9
2393        vmov            q8,  q10
2394        vmov            q9,  q11
2395        b               88b
23969:
2397        subs            \w,  \w,  #8
2398        ble             0f
2399        asr             \s_strd,  \s_strd,  #1
2400        asr             \d_strd,  \d_strd,  #1
2401        mls             \src,  \s_strd,  \my,  \src
2402        mls             \dst,  \d_strd,  \my,  \dst
2403        sub             \src,  \src,  \s_strd,  lsl #3
2404        mov             \h,  \my
2405        add             \src,  \src,  #8
2406.ifc \type, put
2407        add             \dst,  \dst,  #8
2408.else
2409        add             \dst,  \dst,  #16
2410.endif
2411        b               168b
24120:
2413        vpop            {q4-q7}
2414        pop             {r4-r11,pc}
2415
2416L(\type\()_8tap_filter_8):
2417        vld1.8          {q14},  [\sr2], \s_strd
2418        vld1.8          {q15},  [\src], \s_strd
2419        vmovl.u8        q12, d28
2420        vmovl.u8        q13, d29
2421        vmul.s16        q10, q12, d0[0]
2422.irpc i, 123
2423        vext.8          q14, q12, q13, #(2*\i)
2424        vmla.s16        q10, q14, d0[\i]
2425.endr
2426.irpc i, 4567
2427        vext.8          q14, q12, q13, #(2*\i)
2428        vmla.s16        q10, q14, d1[\i-4]
2429.endr
2430        vmovl.u8        q12, d30
2431        vmovl.u8        q13, d31
2432        vmul.s16        q11, q12, d0[0]
2433.irpc i, 123
2434        vext.8          q14, q12, q13, #(2*\i)
2435        vmla.s16        q11, q14, d0[\i]
2436.endr
2437.irpc i, 4567
2438        vext.8          q14, q12, q13, #(2*\i)
2439        vmla.s16        q11, q14, d1[\i-4]
2440.endr
2441        vrshr.s16       q10, q10, #2
2442        vrshr.s16       q11, q11, #2
2443        bx              lr
2444endfunc
2445
2446
2447function \type\()_bilin_8bpc_neon, export=1
2448        push            {r4-r11,lr}
2449        ldrd            r4,  r5,  [sp, #36]
2450        ldrd            r6,  r7,  [sp, #44]
2451        vdup.8          d1,  \mx
2452        vdup.8          d3,  \my
2453        rsb             r8,  \mx, #16
2454        rsb             r9,  \my, #16
2455        vdup.8          d0,  r8
2456        vdup.8          d2,  r9
2457.ifc \type, prep
2458        lsl             \d_strd, \w, #1
2459.endif
2460        clz             r8,  \w
2461        cmp             \mx, #0
2462        sub             r8,  r8,  #24
2463        bne             L(\type\()_bilin_h)
2464        cmp             \my, #0
2465        bne             L(\type\()_bilin_v)
2466        b               \type\()_neon
2467
2468L(\type\()_bilin_h):
2469        cmp             \my, #0
2470        bne             L(\type\()_bilin_hv)
2471
2472        adr             r9,  L(\type\()_bilin_h_tbl)
2473        ldr             r8,  [r9, r8, lsl #2]
2474        add             r9,  r9,  r8
2475        bx              r9
2476
2477        .align 2
2478L(\type\()_bilin_h_tbl):
2479        .word 1280f - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2480        .word 640f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2481        .word 320f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2482        .word 160f  - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2483        .word 80f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2484        .word 40f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2485        .word 20f   - L(\type\()_bilin_h_tbl) + CONFIG_THUMB
2486
248720:     // 2xN h
2488.ifc \type, put
2489        add             \ds2,  \dst,  \d_strd
2490        add             \sr2,  \src,  \s_strd
2491        lsl             \d_strd,  \d_strd,  #1
2492        lsl             \s_strd,  \s_strd,  #1
24932:
2494        vld1.32         {d4[]},  [\src], \s_strd
2495        vld1.32         {d6[]},  [\sr2], \s_strd
2496        vext.8          d5,  d4,  d4, #1
2497        vext.8          d7,  d6,  d6, #1
2498        vtrn.16         q2,  q3
2499        subs            \h,  \h,  #2
2500        vmull.u8        q3,  d4,  d0
2501        vmlal.u8        q3,  d5,  d1
2502        vqrshrn.u16     d4,  q3,  #4
2503        vst1.16         {d4[0]}, [\dst, :16], \d_strd
2504        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
2505        bgt             2b
2506        pop             {r4-r11,pc}
2507.endif
2508
250940:     // 4xN h
2510        add             \ds2,  \dst,  \d_strd
2511        add             \sr2,  \src,  \s_strd
2512        lsl             \d_strd,  \d_strd,  #1
2513        lsl             \s_strd,  \s_strd,  #1
25144:
2515        vld1.8          {d4}, [\src], \s_strd
2516        vld1.8          {d6}, [\sr2], \s_strd
2517        vext.8          d5,  d4,  d4, #1
2518        vext.8          d7,  d6,  d6, #1
2519        vtrn.32         q2,  q3
2520        subs            \h,  \h,  #2
2521        vmull.u8        q3,  d4,  d0
2522        vmlal.u8        q3,  d5,  d1
2523.ifc \type, put
2524        vqrshrn.u16     d4,  q3,  #4
2525        vst1.32         {d4[0]}, [\dst, :32], \d_strd
2526        vst1.32         {d4[1]}, [\ds2, :32], \d_strd
2527.else
2528        vst1.16         {d6}, [\dst, :64], \d_strd
2529        vst1.16         {d7}, [\ds2, :64], \d_strd
2530.endif
2531        bgt             4b
2532        pop             {r4-r11,pc}
2533
253480:     // 8xN h
2535        add             \ds2,  \dst,  \d_strd
2536        add             \sr2,  \src,  \s_strd
2537        lsl             \d_strd,  \d_strd,  #1
2538        lsl             \s_strd,  \s_strd,  #1
25398:
2540        vld1.8          {q8},  [\src], \s_strd
2541        vld1.8          {q10}, [\sr2], \s_strd
2542        vext.8          q9,  q8,  q8,  #1
2543        vext.8          q11, q10, q10, #1
2544        subs            \h,  \h,  #2
2545        vmull.u8        q8,  d16, d0
2546        vmull.u8        q10, d20, d0
2547        vmlal.u8        q8,  d18, d1
2548        vmlal.u8        q10, d22, d1
2549.ifc \type, put
2550        vqrshrn.u16     d16,  q8,  #4
2551        vqrshrn.u16     d18,  q10, #4
2552        vst1.8          {d16}, [\dst, :64], \d_strd
2553        vst1.8          {d18}, [\ds2, :64], \d_strd
2554.else
2555        vst1.16         {q8},  [\dst, :128], \d_strd
2556        vst1.16         {q10}, [\ds2, :128], \d_strd
2557.endif
2558        bgt             8b
2559        pop             {r4-r11,pc}
2560160:
2561320:
2562640:
25631280:   // 16xN, 32xN, ... h
2564        add             \ds2,  \dst,  \d_strd
2565        add             \sr2,  \src,  \s_strd
2566        lsl             \s_strd,  \s_strd,  #1
2567
2568        sub             \s_strd,  \s_strd,  \w
2569        sub             \s_strd,  \s_strd,  #8
2570.ifc \type, put
2571        lsl             \d_strd,  \d_strd,  #1
2572        sub             \d_strd,  \d_strd,  \w
2573.endif
2574161:
2575        vld1.8          {d16},  [\src]!
2576        vld1.8          {d22},  [\sr2]!
2577        mov             \mx, \w
2578
257916:
2580        vld1.8          {d17,d18},  [\src]!
2581        vld1.8          {d23,d24},  [\sr2]!
2582        vext.8          q10, q8,  q9,  #1
2583        vext.8          q13, q11, q12, #1
2584        vmull.u8        q2,  d16, d0
2585        vmull.u8        q3,  d17, d0
2586        vmull.u8        q14, d22, d0
2587        vmull.u8        q15, d23, d0
2588        vmlal.u8        q2,  d20, d1
2589        vmlal.u8        q3,  d21, d1
2590        vmlal.u8        q14, d26, d1
2591        vmlal.u8        q15, d27, d1
2592        subs            \mx, \mx, #16
2593.ifc \type, put
2594        vqrshrn.u16     d4,  q2,  #4
2595        vqrshrn.u16     d5,  q3,  #4
2596        vqrshrn.u16     d28, q14, #4
2597        vqrshrn.u16     d29, q15, #4
2598        vst1.8          {q2},  [\dst, :128]!
2599        vst1.8          {q14}, [\ds2, :128]!
2600.else
2601        vst1.16         {q2,  q3},  [\dst, :128]!
2602        vst1.16         {q14, q15}, [\ds2, :128]!
2603.endif
2604        ble             9f
2605
2606        vmov            d16, d18
2607        vmov            d22, d24
2608        b               16b
2609
26109:
2611        add             \dst,  \dst,  \d_strd
2612        add             \ds2,  \ds2,  \d_strd
2613        add             \src,  \src,  \s_strd
2614        add             \sr2,  \sr2,  \s_strd
2615
2616        subs            \h,  \h,  #2
2617        bgt             161b
2618        pop             {r4-r11,pc}
2619
2620L(\type\()_bilin_v):
2621        cmp             \h,  #4
2622        adr             r9,  L(\type\()_bilin_v_tbl)
2623        ldr             r8,  [r9, r8, lsl #2]
2624        add             r9,  r9,  r8
2625        bx              r9
2626
2627        .align 2
2628L(\type\()_bilin_v_tbl):
2629        .word 1280f - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2630        .word 640f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2631        .word 320f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2632        .word 160f  - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2633        .word 80f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2634        .word 40f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2635        .word 20f   - L(\type\()_bilin_v_tbl) + CONFIG_THUMB
2636
263720:     // 2xN v
2638.ifc \type, put
2639        cmp             \h,  #2
2640        add             \ds2,  \dst,  \d_strd
2641        add             \sr2,  \src,  \s_strd
2642        lsl             \s_strd,  \s_strd,  #1
2643        lsl             \d_strd,  \d_strd,  #1
2644
2645        // 2x2 v
2646        vld1.16         {d16[]}, [\src], \s_strd
2647        bgt             24f
264822:
2649        vld1.16         {d17[]}, [\sr2], \s_strd
2650        vld1.16         {d18[]}, [\src], \s_strd
2651        vext.8          d16, d16, d17, #6
2652        vext.8          d17, d17, d18, #6
2653        vmull.u8        q2,  d16, d2
2654        vmlal.u8        q2,  d17, d3
2655        vqrshrn.u16     d4,  q2,  #4
2656        vst1.16         {d4[0]}, [\dst, :16]
2657        vst1.16         {d4[1]}, [\ds2, :16]
2658        pop             {r4-r11,pc}
265924:     // 2x4, 2x6, 2x8, ... v
2660        vld1.16         {d17[]}, [\sr2], \s_strd
2661        vld1.16         {d18[]}, [\src], \s_strd
2662        vld1.16         {d19[]}, [\sr2], \s_strd
2663        vld1.16         {d20[]}, [\src], \s_strd
2664        sub             \h,  \h,  #4
2665        vext.8          d16, d16, d17, #6
2666        vext.8          d17, d17, d18, #6
2667        vext.8          d18, d18, d19, #6
2668        vext.8          d19, d19, d20, #6
2669        vtrn.32         d16, d18
2670        vtrn.32         d17, d19
2671        vmull.u8        q2,  d16, d2
2672        vmlal.u8        q2,  d17, d3
2673        cmp             \h,  #2
2674        vqrshrn.u16     d4,  q2,  #4
2675        vst1.16         {d4[0]}, [\dst, :16], \d_strd
2676        vst1.16         {d4[1]}, [\ds2, :16], \d_strd
2677        vst1.16         {d4[2]}, [\dst, :16], \d_strd
2678        vst1.16         {d4[3]}, [\ds2, :16], \d_strd
2679        blt             0f
2680        vmov            d16, d20
2681        beq             22b
2682        b               24b
26830:
2684        pop             {r4-r11,pc}
2685.endif
2686
268740:     // 4xN v
2688        add             \ds2,  \dst,  \d_strd
2689        add             \sr2,  \src,  \s_strd
2690        lsl             \s_strd,  \s_strd,  #1
2691        lsl             \d_strd,  \d_strd,  #1
2692        vld1.32         {d16[]}, [\src], \s_strd
26934:
2694        vld1.32         {d17[]}, [\sr2], \s_strd
2695        vld1.32         {d18[]}, [\src], \s_strd
2696        vext.8          d16, d16, d17, #4
2697        vext.8          d17, d17, d18, #4
2698        vmull.u8        q2,  d16, d2
2699        vmlal.u8        q2,  d17, d3
2700        subs            \h,  \h,  #2
2701.ifc \type, put
2702        vqrshrn.u16     d4,  q2,  #4
2703        vst1.32         {d4[0]}, [\dst, :32], \d_strd
2704        vst1.32         {d4[1]}, [\ds2, :32], \d_strd
2705.else
2706        vst1.16         {d4}, [\dst, :64], \d_strd
2707        vst1.16         {d5}, [\ds2, :64], \d_strd
2708.endif
2709        ble             0f
2710        vmov            d16,  d18
2711        b               4b
27120:
2713        pop             {r4-r11,pc}
2714
271580:     // 8xN v
2716        add             \ds2,  \dst,  \d_strd
2717        add             \sr2,  \src,  \s_strd
2718        lsl             \s_strd,  \s_strd,  #1
2719        lsl             \d_strd,  \d_strd,  #1
2720        vld1.8          {d16}, [\src], \s_strd
27218:
2722        vld1.8          {d17}, [\sr2], \s_strd
2723        vld1.8          {d18}, [\src], \s_strd
2724        vmull.u8        q2,  d16, d2
2725        vmull.u8        q3,  d17, d2
2726        vmlal.u8        q2,  d17, d3
2727        vmlal.u8        q3,  d18, d3
2728        subs            \h,  \h,  #2
2729.ifc \type, put
2730        vqrshrn.u16     d4,  q2,  #4
2731        vqrshrn.u16     d6,  q3,  #4
2732        vst1.8          {d4}, [\dst, :64], \d_strd
2733        vst1.8          {d6}, [\ds2, :64], \d_strd
2734.else
2735        vst1.16         {q2}, [\dst, :128], \d_strd
2736        vst1.16         {q3}, [\ds2, :128], \d_strd
2737.endif
2738        ble             0f
2739        vmov            d16, d18
2740        b               8b
27410:
2742        pop             {r4-r11,pc}
2743
2744160:    // 16xN, 32xN, ...
2745320:
2746640:
27471280:
2748        mov             \my, \h
27491:
2750        add             \ds2, \dst, \d_strd
2751        add             \sr2, \src, \s_strd
2752        lsl             \s_strd, \s_strd, #1
2753        lsl             \d_strd, \d_strd, #1
2754
2755        vld1.8          {q8},  [\src], \s_strd
27562:
2757        vld1.8          {q9},  [\sr2], \s_strd
2758        vld1.8          {q10}, [\src], \s_strd
2759        vmull.u8        q12, d16, d2
2760        vmull.u8        q13, d17, d2
2761        vmull.u8        q14, d18, d2
2762        vmull.u8        q15, d19, d2
2763        vmlal.u8        q12, d18, d3
2764        vmlal.u8        q13, d19, d3
2765        vmlal.u8        q14, d20, d3
2766        vmlal.u8        q15, d21, d3
2767        subs            \h,  \h,  #2
2768.ifc \type, put
2769        vqrshrn.u16     d24, q12, #4
2770        vqrshrn.u16     d25, q13, #4
2771        vqrshrn.u16     d28, q14, #4
2772        vqrshrn.u16     d29, q15, #4
2773        vst1.8          {q12}, [\dst, :128], \d_strd
2774        vst1.8          {q14}, [\ds2, :128], \d_strd
2775.else
2776        vst1.16         {q12, q13}, [\dst, :128], \d_strd
2777        vst1.16         {q14, q15}, [\ds2, :128], \d_strd
2778.endif
2779        ble             9f
2780        vmov            q8,  q10
2781        b               2b
27829:
2783        subs            \w,  \w,  #16
2784        ble             0f
2785        asr             \s_strd, \s_strd, #1
2786        asr             \d_strd, \d_strd, #1
2787        mls             \src, \s_strd, \my, \src
2788        mls             \dst, \d_strd, \my, \dst
2789        sub             \src, \src, \s_strd, lsl #1
2790        mov             \h,  \my
2791        add             \src, \src, #16
2792.ifc \type, put
2793        add             \dst, \dst, #16
2794.else
2795        add             \dst, \dst, #32
2796.endif
2797        b               1b
27980:
2799        pop             {r4-r11,pc}
2800
2801L(\type\()_bilin_hv):
2802        vmovl.u8        q2,  d2
2803        vmovl.u8        q3,  d3
2804        adr             r9,  L(\type\()_bilin_hv_tbl)
2805        ldr             r8,  [r9, r8, lsl #2]
2806        add             r9,  r9,  r8
2807        bx              r9
2808
2809        .align 2
2810L(\type\()_bilin_hv_tbl):
2811        .word 1280f - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2812        .word 640f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2813        .word 320f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2814        .word 160f  - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2815        .word 80f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2816        .word 40f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2817        .word 20f   - L(\type\()_bilin_hv_tbl) + CONFIG_THUMB
2818
281920:     // 2xN hv
2820.ifc \type, put
2821        add             \sr2, \src, \s_strd
2822        add             \ds2, \dst, \d_strd
2823        lsl             \s_strd, \s_strd, #1
2824        lsl             \d_strd, \d_strd, #1
2825
2826        vld1.32         {d28[]},  [\src], \s_strd
2827        vext.8          d29, d28, d28, #1
2828        vmull.u8        q8,  d28, d0
2829        vmlal.u8        q8,  d29, d1
2830
28312:
2832        vld1.32         {d28[]},  [\sr2], \s_strd
2833        vld1.32         {d30[]},  [\src], \s_strd
2834        vext.8          d29, d28, d28, #1
2835        vext.8          d31, d30, d30, #1
2836        vtrn.16         d28, d30
2837        vtrn.16         d29, d31
2838        vmull.u8        q9,  d28, d0
2839        vmlal.u8        q9,  d29, d1
2840
2841        vtrn.32         d16, d18
2842
2843        vmul.u16        d20, d16, d4
2844        vmla.u16        d20, d19, d6
2845        vqrshrn.u16     d20, q10, #8
2846        subs            \h,  \h,  #2
2847        vst1.16         {d20[0]}, [\dst, :16], \d_strd
2848        vst1.16         {d20[1]}, [\ds2, :16], \d_strd
2849        ble             0f
2850        vtrn.32         d19, d16
2851        b               2b
28520:
2853        pop             {r4-r11,pc}
2854.endif
2855
285640:     // 4xN hv
2857        add             \sr2, \src, \s_strd
2858        add             \ds2, \dst, \d_strd
2859        lsl             \s_strd, \s_strd, #1
2860        lsl             \d_strd, \d_strd, #1
2861
2862        vld1.8          {d28},  [\src], \s_strd
2863        vext.8          d29, d28, d28, #1
2864        vmull.u8        q8,  d28, d0
2865        vmlal.u8        q8,  d29, d1
2866
28674:
2868        vld1.8          {d28},  [\sr2], \s_strd
2869        vld1.8          {d30},  [\src], \s_strd
2870        vext.8          d29, d28, d28, #1
2871        vext.8          d31, d30, d30, #1
2872        vtrn.32         d28, d30
2873        vtrn.32         d29, d31
2874        vmull.u8        q9,  d28, d0
2875        vmlal.u8        q9,  d29, d1
2876
2877        vmov            d17, d18
2878
2879        vmul.u16        q10, q8, q2
2880        vmla.u16        q10, q9, q3
2881        subs            \h,  \h,  #2
2882.ifc \type, put
2883        vqrshrn.u16     d20, q10, #8
2884        vst1.32         {d20[0]}, [\dst, :32], \d_strd
2885        vst1.32         {d20[1]}, [\ds2, :32], \d_strd
2886.else
2887        vrshr.u16       q10, q10, #4
2888        vst1.16         {d20}, [\dst, :64], \d_strd
2889        vst1.16         {d21}, [\ds2, :64], \d_strd
2890.endif
2891        ble             0f
2892        vmov            d16, d19
2893        b               4b
28940:
2895        pop             {r4-r11,pc}
2896
289780:     // 8xN, 16xN, ... hv
2898160:
2899320:
2900640:
29011280:
2902        mov             \my, \h
2903
29041:
2905        add             \sr2, \src, \s_strd
2906        add             \ds2, \dst, \d_strd
2907        lsl             \s_strd, \s_strd, #1
2908        lsl             \d_strd, \d_strd, #1
2909
2910        vld1.8          {q12},  [\src], \s_strd
2911        vext.8          q13, q12, q12, #1
2912        vmull.u8        q8,  d24, d0
2913        vmlal.u8        q8,  d26, d1
2914
29152:
2916        vld1.8          {q12},  [\sr2], \s_strd
2917        vld1.8          {q14},  [\src], \s_strd
2918        vext.8          q13, q12, q12, #1
2919        vext.8          q15, q14, q14, #1
2920        vmull.u8        q9,  d24, d0
2921        vmlal.u8        q9,  d26, d1
2922        vmull.u8        q10, d28, d0
2923        vmlal.u8        q10, d30, d1
2924
2925        vmul.u16        q8,  q8,  q2
2926        vmla.u16        q8,  q9,  q3
2927        vmul.u16        q9,  q9,  q2
2928        vmla.u16        q9,  q10, q3
2929        subs            \h,  \h,  #2
2930.ifc \type, put
2931        vqrshrn.u16     d16, q8,  #8
2932        vqrshrn.u16     d18, q9,  #8
2933        vst1.8          {d16}, [\dst, :64], \d_strd
2934        vst1.8          {d18}, [\ds2, :64], \d_strd
2935.else
2936        vrshr.u16       q8,  q8,  #4
2937        vrshr.u16       q9,  q9,  #4
2938        vst1.16         {q8}, [\dst, :128], \d_strd
2939        vst1.16         {q9}, [\ds2, :128], \d_strd
2940.endif
2941        ble             9f
2942        vmov            q8,  q10
2943        b               2b
29449:
2945        subs            \w,  \w,  #8
2946        ble             0f
2947        asr             \s_strd,  \s_strd,  #1
2948        asr             \d_strd,  \d_strd,  #1
2949        mls             \src,  \s_strd,  \my,  \src
2950        mls             \dst,  \d_strd,  \my,  \dst
2951        sub             \src,  \src,  \s_strd,  lsl #1
2952        mov             \h,  \my
2953        add             \src,  \src,  #8
2954.ifc \type, put
2955        add             \dst,  \dst,  #8
2956.else
2957        add             \dst,  \dst,  #16
2958.endif
2959        b               1b
29600:
2961        pop             {r4-r11,pc}
2962endfunc
2963.endm
2964
2965filter_fn put,  r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, 10
2966filter_fn prep, r0, r7, r1, r2, r3, r4, r5, r6, r8, r9, 6
2967
2968.macro load_filter_ptr src
2969        asr             r12, \src, #10
2970        add             r12, r11, r12, lsl #3
2971.endm
2972
2973.macro load_filter_coef dst, src, inc
2974        add             \src, \src, \inc
2975        vld1.8          {\dst}, [r12, :64]
2976.endm
2977
2978.macro load_filter_row dst, src, inc
2979        load_filter_ptr \src
2980        load_filter_coef \dst, \src, \inc
2981.endm
2982
2983function warp_filter_horz_neon
2984        load_filter_ptr r5                  // filter 0
2985        vld1.16         {q7}, [r2], r3
2986        vmov.i8         q6,  #128
2987
2988        load_filter_coef d0, r5,  r7        // filter 0
2989        load_filter_row d1,  r5,  r7        // filter 1
2990        load_filter_row d2,  r5,  r7        // filter 2
2991        load_filter_ptr r5                  // filter 3
2992        veor            q7,  q7,  q6        // subtract by 128 to allow using vmull
2993        load_filter_coef d3, r5,  r7        // filter 3
2994        vext.8          d12, d14, d15, #1   // filter 1 pixels
2995        vext.8          d13, d14, d15, #2   // filter 2 pixels
2996        load_filter_ptr r5                  // filter 4
2997        vmull.s8        q2,  d14, d0        // filter 0 output
2998        vmull.s8        q3,  d12, d1        // filter 1 output
2999        load_filter_coef d0, r5,  r7        // filter 4
3000        load_filter_ptr r5                  // filter 5
3001        vext.8          d12, d14, d15, #3   // filter 3 pixels
3002        vmull.s8        q4,  d13, d2        // filter 2 output
3003        vext.8          d13, d14, d15, #4   // filter 4 pixels
3004        vpadd.i16       d4,  d4,  d5        // pixel 0 (4x16)
3005        vpadd.i16       d5,  d6,  d7        // pixel 1 (4x16)
3006        load_filter_coef d1, r5,  r7        // filter 5
3007        load_filter_ptr r5                  // filter 6
3008        vmull.s8        q5,  d12, d3        // filter 3 output
3009        vext.8          d12, d14, d15, #5   // filter 5 pixels
3010        vmull.s8        q3,  d13, d0        // filter 4 output
3011        load_filter_coef d0, r5,  r7        // filter 6
3012        vext.8          d13, d14, d15, #6   // filter 6 pixels
3013        load_filter_ptr r5                  // filter 7
3014        vpadd.i16       d8,  d8,  d9        // pixel 2 (4x16)
3015        vpadd.i16       d9,  d10, d11       // pixel 3 (4x16)
3016        vmull.s8        q5,  d12, d1        // filter 5 output
3017        load_filter_coef d1, r5,  r7        // filter 7
3018        vext.8          d14, d14, d15, #7   // filter 7 pixels
3019        vpadd.i16       d6,  d6,  d7        // pixel 4 (4x16)
3020        vpadd.i16       d10, d10, d11       // pixel 5 (4x16)
3021        vmull.s8        q6,  d13, d0        // filter 6 output
3022        vmull.s8        q7,  d14, d1        // filter 7 output
3023
3024        sub             r5,  r5,  r7, lsl #3
3025
3026        vpadd.i16       d4,  d4,  d5        // pixel 0,1 (2x16)
3027        vpadd.i16       d5,  d8,  d9        // pixel 2,3 (2x16)
3028        vpadd.i16       d12, d12, d13       // pixel 6 (4x16)
3029        vpadd.i16       d14, d14, d15       // pixel 7 (4x16)
3030        vpadd.i16       d6,  d6,  d10       // pixel 4,5 (2x16)
3031        vpadd.i16       d10, d12, d14       // pixel 6,7 (2x16)
3032        vpadd.i16       d4,  d4,  d5        // pixel 0-3
3033        vpadd.i16       d5,  d6,  d10       // pixel 4-7
3034
3035        add             r5,  r5,  r8
3036
3037        bx              lr
3038endfunc
3039
3040// void dav1d_warp_affine_8x8_8bpc_neon(
3041//         pixel *dst, const ptrdiff_t dst_stride,
3042//         const pixel *src, const ptrdiff_t src_stride,
3043//         const int16_t *const abcd, int mx, int my)
3044.macro warp t, shift
3045function warp_affine_8x8\t\()_8bpc_neon, export=1
3046        push            {r4-r11,lr}
3047        vpush           {q4-q7}
3048        ldrd            r4,  r5,  [sp, #100]
3049        ldr             r6,  [sp, #108]
3050        ldrd            r8,  r9,  [r4]
3051        sxth            r7,  r8
3052        asr             r8,  r8, #16
3053        asr             r4,  r9, #16
3054        sxth            r9,  r9
3055        mov             r10, #8
3056        sub             r2,  r2,  r3, lsl #1
3057        sub             r2,  r2,  r3
3058        sub             r2,  r2,  #3
3059        movrel          r11, X(mc_warp_filter), 64*8
3060.ifnb \t
3061        lsl             r1,  r1,  #1
3062.endif
3063        add             r5,  r5,  #512
3064        add             r6,  r6,  #512
3065
3066        bl              warp_filter_horz_neon
3067        vrshr.s16       q8,  q2,  #3
3068        bl              warp_filter_horz_neon
3069        vrshr.s16       q9,  q2,  #3
3070        bl              warp_filter_horz_neon
3071        vrshr.s16       q10, q2,  #3
3072        bl              warp_filter_horz_neon
3073        vrshr.s16       q11, q2,  #3
3074        bl              warp_filter_horz_neon
3075        vrshr.s16       q12, q2,  #3
3076        bl              warp_filter_horz_neon
3077        vrshr.s16       q13, q2,  #3
3078        bl              warp_filter_horz_neon
3079        vrshr.s16       q14, q2,  #3
3080
30811:
3082        bl              warp_filter_horz_neon
3083        vrshr.s16       q15, q2,  #3
3084
3085        load_filter_row d8,  r6,  r9
3086        load_filter_row d9,  r6,  r9
3087        load_filter_row d10, r6,  r9
3088        load_filter_row d11, r6,  r9
3089        load_filter_row d12, r6,  r9
3090        load_filter_row d13, r6,  r9
3091        load_filter_row d14, r6,  r9
3092        load_filter_row d15, r6,  r9
3093        transpose_8x8b  q4,  q5,  q6,  q7,  d8,  d9,  d10, d11, d12, d13, d14, d15
3094        vmovl.s8        q1,  d8
3095        vmovl.s8        q2,  d9
3096        vmovl.s8        q3,  d10
3097        vmovl.s8        q4,  d11
3098        vmovl.s8        q5,  d12
3099        vmovl.s8        q6,  d13
3100
3101        sub             r6,  r6,  r9, lsl #3
3102
3103        // This ordering of vmull/vmlal is highly beneficial for
3104        // Cortex A8/A9/A53 here, but harmful for Cortex A7.
3105        vmull.s16       q0,  d16,  d2
3106        vmlal.s16       q0,  d18,  d4
3107        vmlal.s16       q0,  d20,  d6
3108        vmlal.s16       q0,  d22,  d8
3109        vmlal.s16       q0,  d24,  d10
3110        vmlal.s16       q0,  d26,  d12
3111        vmull.s16       q1,  d17,  d3
3112        vmlal.s16       q1,  d19,  d5
3113        vmlal.s16       q1,  d21,  d7
3114        vmlal.s16       q1,  d23,  d9
3115        vmlal.s16       q1,  d25,  d11
3116        vmlal.s16       q1,  d27,  d13
3117
3118        vmovl.s8        q2,  d14
3119        vmovl.s8        q3,  d15
3120
3121        vmlal.s16       q0,  d28,  d4
3122        vmlal.s16       q0,  d30,  d6
3123        vmlal.s16       q1,  d29,  d5
3124        vmlal.s16       q1,  d31,  d7
3125
3126.ifb \t
3127        vmov.i16        q7,  #128
3128.else
3129        vmov.i16        q7,  #0x800
3130.endif
3131
3132        vmov            q8,  q9
3133        vmov            q9,  q10
3134        vqrshrn.s32     d0,  q0,  #\shift
3135        vmov            q10, q11
3136        vqrshrn.s32     d1,  q1,  #\shift
3137        vmov            q11, q12
3138        vadd.i16        q0,  q0,  q7
3139        vmov            q12, q13
3140.ifb \t
3141        vqmovun.s16     d0,  q0
3142.endif
3143        vmov            q13, q14
3144        vmov            q14, q15
3145        subs            r10, r10, #1
3146.ifnb \t
3147        vst1.16         {q0}, [r0, :128], r1
3148.else
3149        vst1.8          {d0}, [r0, :64], r1
3150.endif
3151
3152        add             r6,  r6,  r4
3153        bgt             1b
3154
3155        vpop            {q4-q7}
3156        pop             {r4-r11,pc}
3157endfunc
3158.endm
3159
3160warp  , 11
3161warp t, 7
3162
3163// void dav1d_emu_edge_8bpc_neon(
3164//         const intptr_t bw, const intptr_t bh,
3165//         const intptr_t iw, const intptr_t ih,
3166//         const intptr_t x, const intptr_t y,
3167//         pixel *dst, const ptrdiff_t dst_stride,
3168//         const pixel *ref, const ptrdiff_t ref_stride)
3169function emu_edge_8bpc_neon, export=1
3170        push            {r4-r11,lr}
3171        ldrd            r4,  r5,  [sp, #36]
3172        ldrd            r6,  r7,  [sp, #44]
3173        ldrd            r8,  r9,  [sp, #52]
3174
3175        // ref += iclip(y, 0, ih - 1) * PXSTRIDE(ref_stride)
3176        // ref += iclip(x, 0, iw - 1)
3177        sub             r12, r3,  #1           // ih - 1
3178        cmp             r5,  r3
3179        sub             lr,  r2,  #1           // iw - 1
3180        it              lt
3181        movlt           r12, r5                // min(y, ih - 1)
3182        cmp             r4,  r2
3183        bic             r12, r12, r12, asr #31 // max(min(y, ih - 1), 0)
3184        it              lt
3185        movlt           lr,  r4                // min(x, iw - 1)
3186        bic             lr,  lr,  lr,  asr #31 // max(min(x, iw - 1), 0)
3187        mla             r8,  r12, r9,  r8      // ref += iclip() * stride
3188        add             r8,  r8,  lr           // ref += iclip()
3189
3190        // bottom_ext = iclip(y + bh - ih, 0, bh - 1)
3191        // top_ext = iclip(-y, 0, bh - 1)
3192        add             r10, r5,  r1           // y + bh
3193        neg             r5,  r5                // -y
3194        sub             r10, r10, r3           // y + bh - ih
3195        sub             r12, r1,  #1           // bh - 1
3196        cmp             r10, r1
3197        bic             r5,  r5,  r5,  asr #31 // max(-y, 0)
3198        it              ge
3199        movge           r10, r12               // min(y + bh - ih, bh-1)
3200        cmp             r5,  r1
3201        bic             r10, r10, r10, asr #31 // max(min(y + bh - ih, bh-1), 0)
3202        it              ge
3203        movge           r5,  r12               // min(max(-y, 0), bh-1)
3204
3205        // right_ext = iclip(x + bw - iw, 0, bw - 1)
3206        // left_ext = iclip(-x, 0, bw - 1)
3207        add             r11, r4,  r0           // x + bw
3208        neg             r4,  r4                // -x
3209        sub             r11, r11, r2           // x + bw - iw
3210        sub             lr,  r0,  #1           // bw - 1
3211        cmp             r11, r0
3212        bic             r4,  r4,  r4,  asr #31 // max(-x, 0)
3213        it              ge
3214        movge           r11, lr                // min(x + bw - iw, bw-1)
3215        cmp             r4,  r0
3216        bic             r11, r11, r11, asr #31 // max(min(x + bw - iw, bw-1), 0)
3217        it              ge
3218        movge           r4,  lr                // min(max(-x, 0), bw - 1)
3219
3220        // center_h = bh - top_ext - bottom_ext
3221        // dst += top_ext * PXSTRIDE(dst_stride)
3222        // center_w = bw - left_ext - right_ext
3223        sub             r1,  r1,  r5           // bh - top_ext
3224        mla             r6,  r5,  r7,  r6
3225        sub             r2,  r0,  r4           // bw - left_ext
3226        sub             r1,  r1,  r10          // center_h = bh - top_ext - bottom_ext
3227        sub             r2,  r2,  r11          // center_w = bw - left_ext - right_ext
3228
3229        mov             r0,  r6                // backup of dst
3230
3231.macro v_loop need_left, need_right
32320:
3233.if \need_left
3234        vld1.8          {d0[], d1[]}, [r8]
3235        mov             r12, r6                // out = dst
3236        mov             r3,  r4
32371:
3238        subs            r3,  r3,  #16
3239        vst1.8          {q0}, [r12, :128]!
3240        bgt             1b
3241.endif
3242        mov             lr,  r8
3243        add             r12, r6,  r4           // out = dst + left_ext
3244        mov             r3,  r2
32451:
3246        vld1.8          {q0, q1}, [lr]!
3247        subs            r3,  r3,  #32
3248.if \need_left
3249        vst1.8          {q0, q1}, [r12]!
3250.else
3251        vst1.8          {q0, q1}, [r12, :128]!
3252.endif
3253        bgt             1b
3254.if \need_right
3255        add             r3,  r8,  r2           // in + center_w
3256        sub             r3,  r3,  #1           // in + center_w - 1
3257        add             r12, r6,  r4           // dst + left_ext
3258        vld1.8          {d0[], d1[]}, [r3]
3259        add             r12, r12, r2           // out = dst + left_ext + center_w
3260        mov             r3,  r11
32611:
3262        subs            r3,  r3,  #16
3263        vst1.8          {q0}, [r12]!
3264        bgt             1b
3265.endif
3266
3267        subs            r1,  r1,  #1           // center_h--
3268        add             r6,  r6,  r7
3269        add             r8,  r8,  r9
3270        bgt             0b
3271.endm
3272
3273        cmp             r4,  #0
3274        beq             2f
3275        // need_left
3276        cmp             r11, #0
3277        beq             3f
3278        // need_left + need_right
3279        v_loop          1,   1
3280        b               5f
3281
32822:
3283        // !need_left
3284        cmp             r11, #0
3285        beq             4f
3286        // !need_left + need_right
3287        v_loop          0,   1
3288        b               5f
3289
32903:
3291        // need_left + !need_right
3292        v_loop          1,   0
3293        b               5f
3294
32954:
3296        // !need_left + !need_right
3297        v_loop          0,   0
3298
32995:
3300        cmp             r10, #0
3301        // Storing the original dst in r0 overwrote bw, recalculate it here
3302        add             r2,  r2,  r4           // center_w + left_ext
3303        add             r2,  r2,  r11          // bw = center_w + left_ext + right_ext
3304
3305        beq             3f
3306        // need_bottom
3307        sub             r8,  r6,  r7           // ref = dst - stride
3308        mov             r4,  r2
33091:
3310        vld1.8          {q0, q1}, [r8, :128]!
3311        mov             r3,  r10
33122:
3313        subs            r3,  r3,  #1
3314        vst1.8          {q0, q1}, [r6, :128], r7
3315        bgt             2b
3316        mls             r6,  r7,  r10,  r6     // dst -= bottom_ext * stride
3317        subs            r4,  r4,  #32          // bw -= 32
3318        add             r6,  r6,  #32          // dst += 32
3319        bgt             1b
3320
33213:
3322        cmp             r5,  #0
3323        beq             3f
3324        // need_top
3325        mls             r6,  r7,  r5,  r0      // dst = stored_dst - top_ext * stride
33261:
3327        vld1.8          {q0, q1}, [r0, :128]!
3328        mov             r3,  r5
33292:
3330        subs            r3,  r3,  #1
3331        vst1.8          {q0, q1}, [r6, :128], r7
3332        bgt             2b
3333        mls             r6,  r7,  r5,  r6      // dst -= top_ext * stride
3334        subs            r2,  r2,  #32          // bw -= 32
3335        add             r6,  r6,  #32          // dst += 32
3336        bgt             1b
3337
33383:
3339        pop             {r4-r11,pc}
3340endfunc
3341