xref: /aosp_15_r20/external/libdav1d/src/arm/32/ipred16.S (revision c09093415860a1c2373dacd84c4fde00c507cdfd)
1/*
2 * Copyright © 2018, VideoLAN and dav1d authors
3 * Copyright © 2019, B Krishnan Iyer
4 * Copyright © 2020, Martin Storsjo
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 *    list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 *    this list of conditions and the following disclaimer in the documentation
15 *    and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "src/arm/asm.S"
30#include "util.S"
31
32// void ipred_dc_128_16bpc_neon(pixel *dst, const ptrdiff_t stride,
33//                              const pixel *const topleft,
34//                              const int width, const int height, const int a,
35//                              const int max_width, const int max_height,
36//                              const int bitdepth_max);
37function ipred_dc_128_16bpc_neon, export=1
38        push            {r4, lr}
39        ldr             r4,  [sp, #8]
40        ldr             r12, [sp, #24]
41        clz             r3,  r3
42        adr             r2,  L(ipred_dc_128_tbl)
43        sub             r3,  r3,  #25
44        vdup.16         q0,  r12
45        ldr             r3,  [r2,  r3,  lsl #2]
46        add             r12, r0,  r1
47        vrshr.u16       q0,  q0,  #1
48        add             r2,  r2,  r3
49        lsl             r1,  r1,  #1
50        bx              r2
51
52        .align 2
53L(ipred_dc_128_tbl):
54        .word 640f - L(ipred_dc_128_tbl) + CONFIG_THUMB
55        .word 320f - L(ipred_dc_128_tbl) + CONFIG_THUMB
56        .word 160f - L(ipred_dc_128_tbl) + CONFIG_THUMB
57        .word 8f   - L(ipred_dc_128_tbl) + CONFIG_THUMB
58        .word 4f   - L(ipred_dc_128_tbl) + CONFIG_THUMB
594:
60        vst1.16         {d0},  [r0,  :64], r1
61        vst1.16         {d0},  [r12, :64], r1
62        subs            r4,  r4,  #4
63        vst1.16         {d0},  [r0,  :64], r1
64        vst1.16         {d0},  [r12, :64], r1
65        bgt             4b
66        pop             {r4, pc}
678:
68        vst1.16         {d0,  d1}, [r0,  :128], r1
69        vst1.16         {d0,  d1}, [r12, :128], r1
70        subs            r4,  r4,  #4
71        vst1.16         {d0,  d1}, [r0,  :128], r1
72        vst1.16         {d0,  d1}, [r12, :128], r1
73        bgt             8b
74        pop             {r4, pc}
75160:
76        vmov            q1,  q0
7716:
78        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
79        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
80        subs            r4,  r4,  #4
81        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
82        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
83        bgt             16b
84        pop             {r4, pc}
85320:
86        vmov            q1,  q0
87        sub             r1,  r1,  #32
8832:
89        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
90        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
91        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
92        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
93        subs            r4,  r4,  #4
94        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
95        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
96        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
97        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
98        bgt             32b
99        pop             {r4, pc}
100640:
101        vmov            q1,  q0
102        sub             r1,  r1,  #96
10364:
104        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
105        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
106        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
107        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
108        subs            r4,  r4,  #2
109        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
110        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
111        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
112        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
113        bgt             64b
114        pop             {r4, pc}
115endfunc
116
117// void ipred_v_16bpc_neon(pixel *dst, const ptrdiff_t stride,
118//                         const pixel *const topleft,
119//                         const int width, const int height, const int a,
120//                         const int max_width, const int max_height);
121function ipred_v_16bpc_neon, export=1
122        push            {r4, lr}
123        ldr             lr,  [sp, #8]
124        clz             r3,  r3
125        adr             r4,  L(ipred_v_tbl)
126        sub             r3,  r3,  #25
127        ldr             r3,  [r4,  r3,  lsl #2]
128        add             r2,  r2,  #2
129        add             r4,  r4,  r3
130        add             r12, r0,  r1
131        lsl             r1,  r1,  #1
132        bx              r4
133
134        .align 2
135L(ipred_v_tbl):
136        .word 640f - L(ipred_v_tbl) + CONFIG_THUMB
137        .word 320f - L(ipred_v_tbl) + CONFIG_THUMB
138        .word 160f - L(ipred_v_tbl) + CONFIG_THUMB
139        .word 80f  - L(ipred_v_tbl) + CONFIG_THUMB
140        .word 40f  - L(ipred_v_tbl) + CONFIG_THUMB
141
14240:
143        vld1.16         {d0}, [r2]
1444:
145        vst1.16         {d0},  [r0,  :64], r1
146        vst1.16         {d0},  [r12, :64], r1
147        subs            lr,  lr,  #4
148        vst1.16         {d0},  [r0,  :64], r1
149        vst1.16         {d0},  [r12, :64], r1
150        bgt             4b
151        pop             {r4, pc}
15280:
153        vld1.16         {q0},  [r2]
1548:
155        vst1.16         {d0,  d1},  [r0,  :128], r1
156        vst1.16         {d0,  d1},  [r12, :128], r1
157        subs            lr,  lr,  #4
158        vst1.16         {d0,  d1},  [r0,  :128], r1
159        vst1.16         {d0,  d1},  [r12, :128], r1
160        bgt             8b
161        pop             {r4, pc}
162160:
163        vld1.16         {q0,  q1},  [r2]
16416:
165        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
166        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
167        subs            lr,  lr,  #4
168        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
169        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
170        bgt             16b
171        pop             {r4, pc}
172320:
173        vld1.16         {q0,  q1},  [r2]!
174        sub             r1,  r1,  #32
175        vld1.16         {q2,  q3},  [r2]
17632:
177        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
178        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
179        vst1.16         {d4,  d5,  d6,  d7},  [r0,  :128], r1
180        vst1.16         {d4,  d5,  d6,  d7},  [r12, :128], r1
181        subs            lr,  lr,  #4
182        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
183        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
184        vst1.16         {d4,  d5,  d6,  d7},  [r0,  :128], r1
185        vst1.16         {d4,  d5,  d6,  d7},  [r12, :128], r1
186        bgt             32b
187        pop             {r4, pc}
188640:
189        vld1.16         {q0,  q1},  [r2]!
190        sub             r1,  r1,  #96
191        vld1.16         {q2,  q3},  [r2]!
192        vld1.16         {q8,  q9},  [r2]!
193        vld1.16         {q10, q11}, [r2]!
19464:
195        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
196        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
197        vst1.16         {d4,  d5,  d6,  d7},  [r0,  :128]!
198        vst1.16         {d4,  d5,  d6,  d7},  [r12, :128]!
199        subs            lr,  lr,  #2
200        vst1.16         {d16, d17, d18, d19}, [r0,  :128]!
201        vst1.16         {d16, d17, d18, d19}, [r12, :128]!
202        vst1.16         {d20, d21, d22, d23}, [r0,  :128], r1
203        vst1.16         {d20, d21, d22, d23}, [r12, :128], r1
204        bgt             64b
205        pop             {r4, pc}
206endfunc
207
208// void ipred_h_16bpc_neon(pixel *dst, const ptrdiff_t stride,
209//                         const pixel *const topleft,
210//                         const int width, const int height, const int a,
211//                         const int max_width, const int max_height);
212function ipred_h_16bpc_neon, export=1
213        push            {r4-r5, lr}
214        ldr             r4,  [sp, #12]
215        clz             r3,  r3
216        adr             r5,  L(ipred_h_tbl)
217        sub             r3,  r3,  #25
218        ldr             r3,  [r5,  r3,  lsl #2]
219        sub             r2,  r2,  #2
220        mov             lr,  #-2
221        add             r5,  r5,  r3
222        add             r12, r0,  r1
223        lsl             r1,  r1,  #1
224        bx              r5
225
226        .align 2
227L(ipred_h_tbl):
228        .word 640f - L(ipred_h_tbl) + CONFIG_THUMB
229        .word 320f - L(ipred_h_tbl) + CONFIG_THUMB
230        .word 160f - L(ipred_h_tbl) + CONFIG_THUMB
231        .word 8f   - L(ipred_h_tbl) + CONFIG_THUMB
232        .word 40f  - L(ipred_h_tbl) + CONFIG_THUMB
23340:
234        sub             r2,  r2,  #6
235        mov             lr,  #-8
2364:
237        vld4.16         {d0[],  d1[],  d2[],  d3[]},  [r2],  lr
238        vst1.16         {d3},  [r0,  :64], r1
239        vst1.16         {d2},  [r12, :64], r1
240        subs            r4,  r4,  #4
241        vst1.16         {d1},  [r0,  :64], r1
242        vst1.16         {d0},  [r12, :64], r1
243        bgt             4b
244        pop             {r4-r5, pc}
2458:
246        vld1.16         {d0[],  d1[]},  [r2],  lr
247        subs            r4,  r4,  #4
248        vld1.16         {d2[],  d3[]},  [r2],  lr
249        vst1.16         {q0},  [r0,    :128],  r1
250        vld1.16         {d4[],  d5[]},  [r2],  lr
251        vst1.16         {q1},  [r12,   :128],  r1
252        vld1.16         {d6[],  d7[]},  [r2],  lr
253        vst1.16         {q2},  [r0,    :128],  r1
254        vst1.16         {q3},  [r12,   :128],  r1
255        bgt             8b
256        pop             {r4-r5, pc}
257160:
258        sub             r1,  r1,  #16
25916:
260        vld1.16         {d0[],  d1[]}, [r2],  lr
261        subs            r4,  r4,  #4
262        vld1.16         {d2[],  d3[]}, [r2],  lr
263        vst1.16         {q0},  [r0,   :128]!
264        vld1.16         {d4[],  d5[]}, [r2],  lr
265        vst1.16         {q1},  [r12,  :128]!
266        vld1.16         {d6[],  d7[]}, [r2],  lr
267        vst1.16         {q0},  [r0,   :128],  r1
268        vst1.16         {q1},  [r12,  :128],  r1
269        vst1.16         {q2},  [r0,   :128]!
270        vst1.16         {q3},  [r12,  :128]!
271        vst1.16         {q2},  [r0,   :128],  r1
272        vst1.16         {q3},  [r12,  :128],  r1
273        bgt             16b
274        pop             {r4-r5, pc}
275320:
276        sub             r1,  r1,  #48
27732:
278        vld1.16         {d0[],  d1[]},  [r2],  lr
279        subs            r4,  r4,  #4
280        vld1.16         {d2[],  d3[]},  [r2],  lr
281        vst1.16         {q0},  [r0,    :128]!
282        vld1.16         {d4[],  d5[]},  [r2],  lr
283        vst1.16         {q1},  [r12,   :128]!
284        vld1.16         {d6[],  d7[]},  [r2],  lr
285        vst1.16         {q0},  [r0,    :128]!
286        vst1.16         {q1},  [r12,   :128]!
287        vst1.16         {q0},  [r0,    :128]!
288        vst1.16         {q1},  [r12,   :128]!
289        vst1.16         {q0},  [r0,    :128],  r1
290        vst1.16         {q1},  [r12,   :128],  r1
291        vst1.16         {q2},  [r0,    :128]!
292        vst1.16         {q3},  [r12,   :128]!
293        vst1.16         {q2},  [r0,    :128]!
294        vst1.16         {q3},  [r12,   :128]!
295        vst1.16         {q2},  [r0,    :128]!
296        vst1.16         {q3},  [r12,   :128]!
297        vst1.16         {q2},  [r0,    :128],  r1
298        vst1.16         {q3},  [r12,   :128],  r1
299        bgt             32b
300        pop             {r4-r5, pc}
301640:
302        sub             r1,  r1,  #96
30364:
304        vld1.16         {d0[],  d1[]},  [r2],  lr
305        subs            r4,  r4,  #2
306        vld1.16         {d4[],  d5[]},  [r2],  lr
307        vmov            q1,  q0
308        vmov            q3,  q2
309        vst1.16         {q0, q1}, [r0,  :128]!
310        vst1.16         {q2, q3}, [r12, :128]!
311        vst1.16         {q0, q1}, [r0,  :128]!
312        vst1.16         {q2, q3}, [r12, :128]!
313        vst1.16         {q0, q1}, [r0,  :128]!
314        vst1.16         {q2, q3}, [r12, :128]!
315        vst1.16         {q0, q1}, [r0,  :128],  r1
316        vst1.16         {q2, q3}, [r12, :128],  r1
317        bgt             64b
318        pop             {r4-r5, pc}
319endfunc
320
321// void ipred_dc_top_16bpc_neon(pixel *dst, const ptrdiff_t stride,
322//                              const pixel *const topleft,
323//                              const int width, const int height, const int a,
324//                              const int max_width, const int max_height);
325function ipred_dc_top_16bpc_neon, export=1
326        push            {r4-r5, lr}
327        ldr             r4,  [sp, #12]
328        clz             r3,  r3
329        adr             r5,  L(ipred_dc_top_tbl)
330        sub             r3,  r3,  #25
331        ldr             r3,  [r5,  r3,  lsl #2]
332        add             r2,  r2,  #2
333        add             r5,  r5,  r3
334        add             r12, r0,  r1
335        lsl             r1,  r1,  #1
336        bx              r5
337
338        .align 2
339L(ipred_dc_top_tbl):
340        .word 640f - L(ipred_dc_top_tbl) + CONFIG_THUMB
341        .word 320f - L(ipred_dc_top_tbl) + CONFIG_THUMB
342        .word 160f - L(ipred_dc_top_tbl) + CONFIG_THUMB
343        .word 80f  - L(ipred_dc_top_tbl) + CONFIG_THUMB
344        .word 40f  - L(ipred_dc_top_tbl) + CONFIG_THUMB
345
34640:
347        vld1.16         {d0},  [r2]
348        vpadd.i16       d0,  d0,  d0
349        vpadd.i16       d0,  d0,  d0
350        vrshr.u16       d0,  d0,  #2
351        vdup.16         d0,  d0[0]
3524:
353        vst1.16         {d0},  [r0,  :64], r1
354        vst1.16         {d0},  [r12, :64], r1
355        subs            r4,  r4,  #4
356        vst1.16         {d0},  [r0,  :64], r1
357        vst1.16         {d0},  [r12, :64], r1
358        bgt             4b
359        pop             {r4-r5, pc}
36080:
361        vld1.16         {d0,  d1},  [r2]
362        vadd.i16        d0,  d0,  d1
363        vpadd.i16       d0,  d0,  d0
364        vpadd.i16       d0,  d0,  d0
365        vrshr.u16       d0,  d0,  #3
366        vdup.16         q0,  d0[0]
3678:
368        vst1.16         {d0,  d1},  [r0,  :128], r1
369        vst1.16         {d0,  d1},  [r12, :128], r1
370        subs            r4,  r4,  #4
371        vst1.16         {d0,  d1},  [r0,  :128], r1
372        vst1.16         {d0,  d1},  [r12, :128], r1
373        bgt             8b
374        pop             {r4-r5, pc}
375160:
376        vld1.16         {d0,  d1,  d2,  d3},  [r2]
377        vadd.i16        q0,  q0,  q1
378        vadd.i16        d0,  d0,  d1
379        vpadd.i16       d0,  d0,  d0
380        vpadd.i16       d0,  d0,  d0
381        vrshr.u16       d4,  d0,  #4
382        vdup.16         q0,  d4[0]
383        vdup.16         q1,  d4[0]
38416:
385        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
386        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
387        subs            r4,  r4,  #4
388        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
389        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
390        bgt             16b
391        pop             {r4-r5, pc}
392320:
393        vld1.16         {d0,  d1,  d2,  d3},  [r2]!
394        vld1.16         {d4,  d5,  d6,  d7},  [r2]
395        vadd.i16        q0,  q0,  q1
396        vadd.i16        q2,  q2,  q3
397        vadd.i16        q0,  q0,  q2
398        vadd.i16        d0,  d0,  d1
399        vpadd.i16       d0,  d0,  d0
400        vpaddl.u16      d0,  d0
401        vrshrn.i32      d18, q0,  #5
402        vdup.16         q0,  d18[0]
403        vdup.16         q1,  d18[0]
404        sub             r1,  r1,  #32
40532:
406        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
407        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
408        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
409        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
410        subs            r4,  r4,  #4
411        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
412        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
413        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
414        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
415        bgt             32b
416        pop             {r4-r5, pc}
417640:
418        vld1.16         {d0,  d1,  d2,  d3},  [r2]!
419        vld1.16         {d4,  d5,  d6,  d7},  [r2]!
420        vadd.i16        q0,  q0,  q1
421        vld1.16         {d16, d17, d18, d19}, [r2]!
422        vadd.i16        q2,  q2,  q3
423        vld1.16         {d20, d21, d22, d23}, [r2]
424        vadd.i16        q8,  q8,  q9
425        vadd.i16        q10, q10, q11
426        vadd.i16        q0,  q0,  q2
427        vadd.i16        q8,  q8,  q10
428        vadd.i16        q0,  q0,  q8
429        vadd.i16        d0,  d0,  d1
430        vpaddl.u16      d0,  d0
431        vpadd.i32       d0,  d0,  d0
432        vrshrn.i32      d18, q0,  #6
433        vdup.16         q0,  d18[0]
434        vdup.16         q1,  d18[0]
435        sub             r1,  r1,  #96
43664:
437        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
438        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
439        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
440        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
441        subs            r4,  r4,  #2
442        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
443        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
444        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
445        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
446        bgt             64b
447        pop             {r4-r5, pc}
448endfunc
449
450// void ipred_dc_left_16bpc_neon(pixel *dst, const ptrdiff_t stride,
451//                               const pixel *const topleft,
452//                               const int width, const int height, const int a,
453//                               const int max_width, const int max_height);
454function ipred_dc_left_16bpc_neon, export=1
455        push            {r4-r5, lr}
456        ldr             r4,  [sp, #12]
457        sub             r2,  r2,  r4,  lsl #1
458        clz             r3,  r3
459        clz             lr,  r4
460        sub             lr,  lr,  #25
461        adr             r5,  L(ipred_dc_left_tbl)
462        sub             r3,  r3,  #20
463        ldr             r3,  [r5,  r3,  lsl #2]
464        ldr             lr,  [r5,  lr,  lsl #2]
465        add             r3,  r5,  r3
466        add             r5,  r5,  lr
467        add             r12, r0,  r1
468        lsl             r1,  r1,  #1
469        bx              r5
470
471        .align 2
472L(ipred_dc_left_tbl):
473        .word L(ipred_dc_left_h64) - L(ipred_dc_left_tbl) + CONFIG_THUMB
474        .word L(ipred_dc_left_h32) - L(ipred_dc_left_tbl) + CONFIG_THUMB
475        .word L(ipred_dc_left_h16) - L(ipred_dc_left_tbl) + CONFIG_THUMB
476        .word L(ipred_dc_left_h8)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
477        .word L(ipred_dc_left_h4)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
478        .word L(ipred_dc_left_w64) - L(ipred_dc_left_tbl) + CONFIG_THUMB
479        .word L(ipred_dc_left_w32) - L(ipred_dc_left_tbl) + CONFIG_THUMB
480        .word L(ipred_dc_left_w16) - L(ipred_dc_left_tbl) + CONFIG_THUMB
481        .word L(ipred_dc_left_w8)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
482        .word L(ipred_dc_left_w4)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
483
484L(ipred_dc_left_h4):
485        vld1.16         {d0},  [r2, :64]
486        vpadd.i16       d0,  d0,  d0
487        vpadd.i16       d0,  d0,  d0
488        vrshr.u16       d0,  d0,  #2
489        vdup.16         q0,  d0[0]
490        bx              r3
491L(ipred_dc_left_w4):
492        vst1.16         {d0},  [r0,  :64], r1
493        vst1.16         {d0},  [r12, :64], r1
494        subs            r4,  r4,  #4
495        vst1.16         {d0},  [r0,  :64], r1
496        vst1.16         {d0},  [r12, :64], r1
497        bgt             L(ipred_dc_left_w4)
498        pop             {r4-r5, pc}
499L(ipred_dc_left_h8):
500        vld1.16         {d0,  d1},  [r2, :128]
501        vadd.i16        d0,  d0,  d1
502        vpadd.i16       d0,  d0,  d0
503        vpadd.i16       d0,  d0,  d0
504        vrshr.u16       d0,  d0,  #3
505        vdup.16         q0,  d0[0]
506        bx              r3
507L(ipred_dc_left_w8):
508        vst1.16         {d0,  d1},  [r0,  :128], r1
509        vst1.16         {d0,  d1},  [r12, :128], r1
510        subs            r4,  r4,  #4
511        vst1.16         {d0,  d1},  [r0,  :128], r1
512        vst1.16         {d0,  d1},  [r12, :128], r1
513        bgt             L(ipred_dc_left_w8)
514        pop             {r4-r5, pc}
515L(ipred_dc_left_h16):
516        vld1.16         {d0,  d1,  d2,  d3},  [r2, :128]
517        vadd.i16        q0,  q0,  q1
518        vadd.i16        d0,  d0,  d1
519        vpadd.i16       d0,  d0,  d0
520        vpadd.i16       d0,  d0,  d0
521        vrshr.u16       d0,  d0,  #4
522        vdup.16         q0,  d0[0]
523        bx              r3
524L(ipred_dc_left_w16):
525        vmov            q1,  q0
5261:
527        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
528        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
529        subs            r4,  r4,  #4
530        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
531        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
532        bgt             1b
533        pop             {r4-r5, pc}
534L(ipred_dc_left_h32):
535        vld1.16         {d0,  d1,  d2,  d3},  [r2, :128]!
536        vld1.16         {d4,  d5,  d6,  d7},  [r2, :128]
537        vadd.i16        q0,  q0,  q1
538        vadd.i16        q2,  q2,  q3
539        vadd.i16        q0,  q0,  q2
540        vadd.i16        d0,  d0,  d1
541        vpadd.i16       d0,  d0,  d0
542        vpaddl.u16      d0,  d0
543        vrshrn.i32      d0,  q0,  #5
544        vdup.16         q0,  d0[0]
545        bx              r3
546L(ipred_dc_left_w32):
547        sub             r1,  r1,  #32
548        vmov            q1,  q0
5491:
550        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
551        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
552        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
553        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
554        subs            r4,  r4,  #4
555        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
556        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
557        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
558        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
559        bgt             1b
560        pop             {r4-r5, pc}
561L(ipred_dc_left_h64):
562        vld1.16         {d0,  d1,  d2,  d3},  [r2, :128]!
563        vld1.16         {d4,  d5,  d6,  d7},  [r2, :128]!
564        vadd.i16        q0,  q0,  q1
565        vld1.16         {d16, d17, d18, d19}, [r2, :128]!
566        vadd.i16        q2,  q2,  q3
567        vld1.16         {d20, d21, d22, d23}, [r2, :128]
568        vadd.i16        q8,  q8,  q9
569        vadd.i16        q10, q10, q11
570        vadd.i16        q0,  q0,  q2
571        vadd.i16        q8,  q8,  q10
572        vadd.i16        q0,  q0,  q8
573        vadd.i16        d0,  d0,  d1
574        vpaddl.u16      d0,  d0
575        vpadd.i32       d0,  d0,  d0
576        vrshrn.i32      d0,  q0,  #6
577        vdup.16         q0,  d0[0]
578        bx              r3
579L(ipred_dc_left_w64):
580        sub             r1,  r1,  #96
581        vmov            q1,  q0
5821:
583        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
584        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
585        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
586        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
587        subs            r4,  r4,  #2
588        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
589        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
590        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
591        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
592        bgt             1b
593        pop             {r4-r5, pc}
594endfunc
595
596// void ipred_dc_16bpc_neon(pixel *dst, const ptrdiff_t stride,
597//                          const pixel *const topleft,
598//                          const int width, const int height, const int a,
599//                          const int max_width, const int max_height);
600function ipred_dc_16bpc_neon, export=1
601        push            {r4-r6, lr}
602        ldr             r4,  [sp, #16]
603        sub             r2,  r2,  r4,  lsl #1
604        add             lr,  r3,  r4        // width + height
605        clz             r3,  r3
606        clz             r12, r4
607        vdup.32         q15, lr             // width + height
608        adr             r5,  L(ipred_dc_tbl)
609        rbit            lr,  lr             // rbit(width + height)
610        sub             r3,  r3,  #20       // 25 leading bits, minus table offset 5
611        sub             r12, r12, #25
612        clz             lr,  lr             // ctz(width + height)
613        ldr             r3,  [r5,  r3,  lsl #2]
614        ldr             r12, [r5,  r12, lsl #2]
615        neg             lr,  lr             // -ctz(width + height)
616        add             r3,  r5,  r3
617        add             r5,  r5,  r12
618        vshr.u32        q15, q15, #1        // (width + height) >> 1
619        vdup.32         q14, lr             // -ctz(width + height)
620        add             r12, r0,  r1
621        lsl             r1,  r1,  #1
622        bx              r5
623
624        .align 2
625L(ipred_dc_tbl):
626        .word L(ipred_dc_h64) - L(ipred_dc_tbl) + CONFIG_THUMB
627        .word L(ipred_dc_h32) - L(ipred_dc_tbl) + CONFIG_THUMB
628        .word L(ipred_dc_h16) - L(ipred_dc_tbl) + CONFIG_THUMB
629        .word L(ipred_dc_h8)  - L(ipred_dc_tbl) + CONFIG_THUMB
630        .word L(ipred_dc_h4)  - L(ipred_dc_tbl) + CONFIG_THUMB
631        .word L(ipred_dc_w64) - L(ipred_dc_tbl) + CONFIG_THUMB
632        .word L(ipred_dc_w32) - L(ipred_dc_tbl) + CONFIG_THUMB
633        .word L(ipred_dc_w16) - L(ipred_dc_tbl) + CONFIG_THUMB
634        .word L(ipred_dc_w8)  - L(ipred_dc_tbl) + CONFIG_THUMB
635        .word L(ipred_dc_w4)  - L(ipred_dc_tbl) + CONFIG_THUMB
636
637L(ipred_dc_h4):
638        vld1.16         {d0},  [r2, :64]!
639        vpadd.i16       d0,  d0,  d0
640        add             r2,  r2,  #2
641        vpaddl.u16      d0,  d0
642        bx              r3
643L(ipred_dc_w4):
644        vld1.16         {d2},  [r2]
645        vadd.i32        d0,  d0,  d30
646        vpadd.i16       d2,  d2,  d2
647        vpaddl.u16      d2,  d2
648        cmp             r4,  #4
649        vadd.i32        d0,  d0,  d2
650        vshl.u32        d0,  d0,  d28
651        beq             1f
652        // h = 8/16
653        cmp             r4,  #16
654        movw            lr,  #0x6667
655        movw            r5,  #0xAAAB
656        it              ne
657        movne           lr,  r5
658        vdup.32         d24, lr
659        vmul.i32        d0,  d0,  d24
660        vshr.u32        d0,  d0,  #17
6611:
662        vdup.16         d0,  d0[0]
6632:
664        vst1.16         {d0},  [r0,  :64], r1
665        vst1.16         {d0},  [r12, :64], r1
666        subs            r4,  r4,  #4
667        vst1.16         {d0},  [r0,  :64], r1
668        vst1.16         {d0},  [r12, :64], r1
669        bgt             2b
670        pop             {r4-r6, pc}
671
672L(ipred_dc_h8):
673        vld1.16         {d0,  d1},  [r2, :128]!
674        vadd.i16        d0,  d0,  d1
675        vpadd.i16       d0,  d0,  d0
676        add             r2,  r2,  #2
677        vpaddl.u16      d0,  d0
678        bx              r3
679L(ipred_dc_w8):
680        vld1.16         {d2,  d3},  [r2]
681        vadd.i32        d0,  d0,  d30
682        vadd.i16        d2,  d2,  d3
683        vpadd.i16       d2,  d2,  d2
684        vpaddl.u16      d2,  d2
685        cmp             r4,  #8
686        vadd.i32        d0,  d0,  d2
687        vshl.u32        d0,  d0,  d28
688        beq             1f
689        // h = 4/16/32
690        cmp             r4,  #32
691        movw            lr,  #0x6667
692        movw            r5,  #0xAAAB
693        it              ne
694        movne           lr,  r5
695        vdup.32         d24, lr
696        vmul.i32        d0,  d0,  d24
697        vshr.u32        d0,  d0,  #17
6981:
699        vdup.16         q0,  d0[0]
7002:
701        vst1.16         {d0,  d1},  [r0,  :128], r1
702        vst1.16         {d0,  d1},  [r12, :128], r1
703        subs            r4,  r4,  #4
704        vst1.16         {d0,  d1},  [r0,  :128], r1
705        vst1.16         {d0,  d1},  [r12, :128], r1
706        bgt             2b
707        pop             {r4-r6, pc}
708
709L(ipred_dc_h16):
710        vld1.16         {d0,  d1,  d2,  d3},  [r2, :128]!
711        vadd.i16        q0,  q0,  q1
712        vadd.i16        d0,  d0,  d1
713        vpadd.i16       d0,  d0,  d0
714        add             r2,  r2,  #2
715        vpaddl.u16      d0,  d0
716        bx              r3
717L(ipred_dc_w16):
718        vld1.16         {d2,  d3,  d4,  d5},  [r2]
719        vadd.i32        d0,  d0,  d30
720        vadd.i16        q1,  q1,  q2
721        vadd.i16        d2,  d2,  d3
722        vpadd.i16       d2,  d2,  d1
723        vpaddl.u16      d2,  d2
724        cmp             r4,  #16
725        vadd.i32        d0,  d0,  d2
726        vshl.u32        d4,  d0,  d28
727        beq             1f
728        // h = 4/8/32/64
729        tst             r4,  #(32+16+8)     // 16 added to make a consecutive bitmask
730        movw            lr,  #0x6667
731        movw            r5,  #0xAAAB
732        it              ne
733        movne           lr,  r5
734        vdup.32         d24, lr
735        vmul.i32        d4,  d4,  d24
736        vshr.u32        d4,  d4,  #17
7371:
738        vdup.16         q0,  d4[0]
739        vdup.16         q1,  d4[0]
7402:
741        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
742        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
743        subs            r4,  r4,  #4
744        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
745        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
746        bgt             2b
747        pop             {r4-r6, pc}
748
749L(ipred_dc_h32):
750        vld1.16         {d0,  d1,  d2,  d3},  [r2, :128]!
751        vld1.16         {d4,  d5,  d6,  d7},  [r2, :128]!
752        vadd.i16        q0,  q0,  q1
753        vadd.i16        q2,  q2,  q3
754        vadd.i16        q0,  q0,  q2
755        vadd.i16        d0,  d0,  d1
756        vpadd.i16       d0,  d0,  d0
757        add             r2,  r2,  #2
758        vpaddl.u16      d0,  d0
759        bx              r3
760L(ipred_dc_w32):
761        vld1.16         {d2,  d3,  d4,  d5},  [r2]!
762        vadd.i32        d0,  d0,  d30
763        vld1.16         {d16, d17, d18, d19}, [r2]
764        vadd.i16        q1,  q1,  q2
765        vadd.i16        q8,  q8,  q9
766        vadd.i16        q1,  q1,  q8
767        vadd.i16        d2,  d2,  d3
768        vpadd.i16       d2,  d2,  d2
769        vpaddl.u16      d2,  d2
770        cmp             r4,  #32
771        vadd.i32        d0,  d0,  d2
772        vshl.u32        d4,  d0,  d28
773        beq             1f
774        // h = 8/16/64
775        cmp             r4,  #8
776        movw            lr,  #0x6667
777        movw            r5,  #0xAAAB
778        it              ne
779        movne           lr,  r5
780        vdup.32         d24, lr
781        vmul.i32        d4,  d4,  d24
782        vshr.u32        d4,  d4,  #17
7831:
784        sub             r1,  r1,  #32
785        vdup.16         q0,  d4[0]
786        vdup.16         q1,  d4[0]
7872:
788        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
789        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
790        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
791        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
792        subs            r4,  r4,  #4
793        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
794        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
795        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
796        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
797        bgt             2b
798        pop             {r4-r6, pc}
799L(ipred_dc_h64):
800        vld1.16         {d0,  d1,  d2,  d3},  [r2, :128]!
801        vld1.16         {d4,  d5,  d6,  d7},  [r2, :128]!
802        vadd.i16        q0,  q0,  q1
803        vld1.16         {d16, d17, d18, d19}, [r2, :128]!
804        vadd.i16        q2,  q2,  q3
805        vld1.16         {d20, d21, d22, d23}, [r2, :128]!
806        vadd.i16        q8,  q8,  q9
807        vadd.i16        q10, q10, q11
808        vadd.i16        q0,  q0,  q2
809        vadd.i16        q8,  q8,  q10
810        vadd.i16        q0,  q0,  q8
811        vadd.i16        d0,  d0,  d1
812        vpaddl.u16      d0,  d0
813        add             r2,  r2,  #2
814        vpadd.i32       d0,  d0,  d0
815        bx              r3
816L(ipred_dc_w64):
817        vld1.16         {d2,  d3,  d4,  d5},  [r2]!
818        vadd.i32        d0,  d0,  d30
819        vld1.16         {d16, d17, d18, d19}, [r2]!
820        vadd.i16        q1,  q1,  q2
821        vld1.16         {d20, d21, d22, d23}, [r2]!
822        vadd.i16        q8,  q8,  q9
823        vld1.16         {d24, d25, d26, d27}, [r2]!
824        vadd.i16        q10, q10, q11
825        vadd.i16        q12, q12, q13
826        vadd.i16        q1,  q1,  q8
827        vadd.i16        q10, q10, q12
828        vadd.i16        q1,  q1,  q10
829        vadd.i16        d2,  d2,  d3
830        vpaddl.u16      d2,  d2
831        vpadd.i32       d2,  d2,  d2
832        cmp             r4,  #64
833        vadd.i32        d0,  d0,  d2
834        vshl.u32        d4,  d0,  d28
835        beq             1f
836        // h = 16/32
837        cmp             r4,  #16
838        movw            lr,  #0x6667
839        movw            r5,  #0xAAAB
840        it              ne
841        movne           lr,  r5
842        vdup.32         d24, lr
843        vmul.i32        d4,  d4,  d24
844        vshr.u32        d4,  d4,  #17
8451:
846        sub             r1,  r1,  #96
847        vdup.16         q0,  d4[0]
848        vdup.16         q1,  d4[0]
8492:
850        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
851        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
852        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
853        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
854        subs            r4,  r4,  #2
855        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128]!
856        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128]!
857        vst1.16         {d0,  d1,  d2,  d3},  [r0,  :128], r1
858        vst1.16         {d0,  d1,  d2,  d3},  [r12, :128], r1
859        bgt             2b
860        pop             {r4-r6, pc}
861endfunc
862
863// void ipred_paeth_16bpc_neon(pixel *dst, const ptrdiff_t stride,
864//                             const pixel *const topleft,
865//                             const int width, const int height, const int a,
866//                             const int max_width, const int max_height);
867function ipred_paeth_16bpc_neon, export=1
868        push            {r4-r6, lr}
869        vpush           {q4}
870        ldr             r4,  [sp, #32]
871        clz             lr,  r3
872        adr             r12, L(ipred_paeth_tbl)
873        sub             lr,  lr,  #25
874        ldr             lr,  [r12, lr, lsl #2]
875        vld1.16         {d4[], d5[]},  [r2]
876        add             r6,  r2,  #2
877        sub             r2,  r2,  #4
878        add             r12, r12, lr
879        mov             r5,  #-4
880        add             lr,  r0,  r1
881        lsl             r1,  r1,  #1
882        bx              r12
883
884        .align 2
885L(ipred_paeth_tbl):
886        .word 640f - L(ipred_paeth_tbl) + CONFIG_THUMB
887        .word 320f - L(ipred_paeth_tbl) + CONFIG_THUMB
888        .word 160f - L(ipred_paeth_tbl) + CONFIG_THUMB
889        .word 80f  - L(ipred_paeth_tbl) + CONFIG_THUMB
890        .word 40f  - L(ipred_paeth_tbl) + CONFIG_THUMB
891
89240:
893        sub             r2,  r2,  #4
894        mov             r5,  #-8
895        vld1.16         {d6},  [r6]
896        vsub.i16        d16, d6,  d4  // top - topleft
897        vmov            d7,  d6
898        vmov            d17, d16
8994:
900        vld4.16         {d0[], d1[], d2[], d3[]},  [r2, :64], r5
901        vadd.i16        q9,  q8,  q0  // base
902        vadd.i16        q10, q8,  q1
903        vabd.s16        q11, q3,  q9  // tdiff
904        vabd.s16        q12, q3,  q10
905        vabd.s16        q13, q2,  q9  // tldiff
906        vabd.s16        q14, q2,  q10
907        vabd.s16        q9,  q0,  q9  // ldiff
908        vabd.s16        q10, q1,  q10
909        vmin.u16        q15, q11, q13 // min(tdiff, tldiff)
910        vmin.u16        q4,  q12, q14
911        vcge.u16        q11, q13, q11 // tldiff >= tdiff
912        vcge.u16        q12, q14, q12
913        vcge.u16        q9,  q15, q9  // min(tdiff, tldiff) >= ldiff
914        vcge.u16        q10, q4,  q10
915        vbsl            q12, q3,  q2  // tdiff <= tldiff ? top : topleft
916        vbsl            q11, q3,  q2
917        vbit            q12, q1,  q10 // ldiff <= min ? left : ...
918        vbit            q11, q0,  q9
919        vst1.16         {d25}, [r0, :64], r1
920        vst1.16         {d24}, [lr, :64], r1
921        subs            r4,  r4,  #4
922        vst1.16         {d23}, [r0, :64], r1
923        vst1.16         {d22}, [lr, :64], r1
924        bgt             4b
925        vpop            {q4}
926        pop             {r4-r6, pc}
92780:
928160:
929320:
930640:
931        vld1.16         {q3},  [r6]!
932        mov             r12, r3
933        sub             r1,  r1,  r3, lsl #1
9341:
935        vld2.16         {d0[], d2[]},  [r2, :32], r5
936        vmov            d1,  d0
937        vmov            d3,  d2
9382:
939        vsub.i16        q8,  q3,  q2  // top - topleft
940        vadd.i16        q9,  q8,  q0  // base
941        vadd.i16        q10, q8,  q1
942        vabd.s16        q11, q3,  q9  // tdiff
943        vabd.s16        q12, q3,  q10
944        vabd.s16        q13, q2,  q9  // tldiff
945        vabd.s16        q14, q2,  q10
946        vabd.s16        q9,  q0,  q9  // ldiff
947        vabd.s16        q10, q1,  q10
948        vmin.u16        q15, q11, q13 // min(tdiff, tldiff)
949        vmin.u16        q4,  q12, q14
950        vcge.u16        q11, q13, q11 // tldiff >= tdiff
951        vcge.u16        q12, q14, q12
952        vcge.u16        q9,  q15, q9  // min(tdiff, tldiff) >= ldiff
953        vcge.u16        q10, q4,  q10
954        vbsl            q12, q3,  q2  // tdiff <= tldiff ? top : topleft
955        vbsl            q11, q3,  q2
956        vbit            q12, q1,  q10 // ldiff <= min ? left : ...
957        vbit            q11, q0,  q9
958        subs            r3,  r3,  #8
959        vst1.16         {q12}, [r0, :128]!
960        vst1.16         {q11}, [lr, :128]!
961        ble             8f
962        vld1.16         {q3},  [r6]!
963        b               2b
9648:
965        subs            r4,  r4,  #2
966        ble             9f
967        // End of horizontal loop, move pointers to next two rows
968        sub             r6,  r6,  r12, lsl #1
969        add             r0,  r0,  r1
970        add             lr,  lr,  r1
971        vld1.16         {q3},  [r6]!
972        mov             r3,  r12
973        b               1b
9749:
975        vpop            {q4}
976        pop             {r4-r6, pc}
977endfunc
978
979// void ipred_smooth_16bpc_neon(pixel *dst, const ptrdiff_t stride,
980//                              const pixel *const topleft,
981//                              const int width, const int height, const int a,
982//                              const int max_width, const int max_height);
983function ipred_smooth_16bpc_neon, export=1
984        push            {r4-r10, lr}
985        ldr             r4,  [sp, #32]
986        movrel          r10, X(sm_weights)
987        add             r12, r10, r4
988        add             r10, r10, r3
989        clz             r9,  r3
990        adr             r5,  L(ipred_smooth_tbl)
991        sub             lr,  r2,  r4, lsl #1
992        sub             r9,  r9,  #25
993        ldr             r9,  [r5, r9, lsl #2]
994        vld1.16         {d4[], d5[]},  [lr] // bottom
995        add             r8,  r2,  #2
996        add             r5,  r5,  r9
997        add             r6,  r0,  r1
998        lsl             r1,  r1,  #1
999        bx              r5
1000
1001        .align 2
1002L(ipred_smooth_tbl):
1003        .word 640f - L(ipred_smooth_tbl) + CONFIG_THUMB
1004        .word 320f - L(ipred_smooth_tbl) + CONFIG_THUMB
1005        .word 160f - L(ipred_smooth_tbl) + CONFIG_THUMB
1006        .word 80f  - L(ipred_smooth_tbl) + CONFIG_THUMB
1007        .word 40f  - L(ipred_smooth_tbl) + CONFIG_THUMB
1008
100940:
1010        vld1.16         {d16},   [r8]       // top
1011        vld1.32         {d18[]}, [r10, :32] // weights_hor
1012        sub             r2,  r2,  #8
1013        mov             r7,  #-8
1014        vdup.16         q3,  d16[3]   // right
1015        vsub.i16        q8,  q8,  q2  // top-bottom
1016        vmovl.u8        q9,  d18      // weights_hor
1017        vadd.i16        d19, d4,  d6  // bottom+right
10184:
1019        vld4.16         {d0[],  d1[],  d2[],  d3[]},  [r2,  :64], r7 // left
1020        vld4.8          {d20[], d21[], d22[], d23[]}, [r12, :32]!    // weights_ver
1021        vshll.u16       q12, d19, #8  // (bottom+right)*256
1022        vshll.u16       q13, d19, #8
1023        vshll.u16       q14, d19, #8
1024        vshll.u16       q15, d19, #8
1025        vzip.32         d20, d21      // weights_ver
1026        vzip.32         d22, d23
1027        vsub.i16        q1,  q1,  q3  // left-right
1028        vsub.i16        q0,  q0,  q3
1029        vmovl.u8        q10, d20      // weights_ver
1030        vmovl.u8        q11, d22
1031        vmlal.s16       q12, d3,  d18 // += (left-right)*weights_hor
1032        vmlal.s16       q13, d2,  d18 // (left flipped)
1033        vmlal.s16       q14, d1,  d18
1034        vmlal.s16       q15, d0,  d18
1035        vmlal.s16       q12, d16, d20 // += (top-bottom)*weights_ver
1036        vmlal.s16       q13, d16, d21
1037        vmlal.s16       q14, d16, d22
1038        vmlal.s16       q15, d16, d23
1039        vrshrn.i32      d24, q12, #9
1040        vrshrn.i32      d25, q13, #9
1041        vrshrn.i32      d26, q14, #9
1042        vrshrn.i32      d27, q15, #9
1043        vst1.16         {d24}, [r0, :64], r1
1044        vst1.16         {d25}, [r6, :64], r1
1045        subs            r4,  r4,  #4
1046        vst1.16         {d26}, [r0, :64], r1
1047        vst1.16         {d27}, [r6, :64], r1
1048        bgt             4b
1049        pop             {r4-r10, pc}
105080:
1051        vld1.16         {q8},  [r8]       // top
1052        vld1.8          {d18}, [r10, :64] // weights_hor
1053        sub             r2,  r2,  #4
1054        mov             r7,  #-4
1055        vdup.16         q3,  d17[3]   // right
1056        vsub.i16        q8,  q8,  q2  // top-bottom
1057        vmovl.u8        q9,  d18      // weights_hor
1058        vadd.i16        d3,  d4,  d6  // bottom+right
10598:
1060        vld2.16         {d0[],  d1[]},  [r2,  :32], r7 // left
1061        vld2.8          {d20[], d22[]}, [r12, :16]!    // weights_ver
1062        vshll.u16       q12, d3,  #8  // (bottom+right)*256
1063        vshll.u16       q13, d3,  #8
1064        vshll.u16       q14, d3,  #8
1065        vshll.u16       q15, d3,  #8
1066        vsub.i16        q0,  q0,  q3  // left-right
1067        vmovl.u8        q10, d20      // weights_ver
1068        vmovl.u8        q11, d22
1069        vmlal.s16       q12, d1,  d18 // += (left-right)*weights_hor
1070        vmlal.s16       q13, d1,  d19 // (left flipped)
1071        vmlal.s16       q14, d0,  d18
1072        vmlal.s16       q15, d0,  d19
1073        vmlal.s16       q12, d16, d20 // += (top-bottom)*weights_ver
1074        vmlal.s16       q13, d17, d20
1075        vmlal.s16       q14, d16, d22
1076        vmlal.s16       q15, d17, d22
1077        vrshrn.i32      d24, q12, #9
1078        vrshrn.i32      d25, q13, #9
1079        vrshrn.i32      d26, q14, #9
1080        vrshrn.i32      d27, q15, #9
1081        subs            r4,  r4,  #2
1082        vst1.16         {q12}, [r0, :128], r1
1083        vst1.16         {q13}, [r6, :128], r1
1084        bgt             8b
1085        pop             {r4-r10, pc}
1086160:
1087320:
1088640:
1089        add             lr,  r2,  r3, lsl #1
1090        sub             r2,  r2,  #4
1091        mov             r7,  #-4
1092        vld1.16         {d6[], d7[]}, [lr] // right
1093        sub             r1,  r1,  r3, lsl #1
1094        mov             r9,  r3
1095        vadd.i16        d3,  d4,  d6  // bottom+right
1096
10971:
1098        vld2.16         {d0[],  d1[]},  [r2,  :32], r7 // left
1099        vld2.8          {d20[], d22[]}, [r12, :16]!    // weights_ver
1100        vsub.i16        q0,  q0,  q3  // left-right
1101        vmovl.u8        q10, d20      // weights_ver
1102        vmovl.u8        q11, d22
11032:
1104        vld1.8          {d18}, [r10, :64]! // weights_hor
1105        vld1.16         {q8},  [r8]!       // top
1106        vshll.u16       q12, d3,  #8  // (bottom+right)*256
1107        vshll.u16       q13, d3,  #8
1108        vmovl.u8        q9,  d18      // weights_hor
1109        vshll.u16       q14, d3,  #8
1110        vshll.u16       q15, d3,  #8
1111        vsub.i16        q8,  q8,  q2  // top-bottom
1112        vmlal.s16       q12, d1,  d18 // += (left-right)*weights_hor
1113        vmlal.s16       q13, d1,  d19 // (left flipped)
1114        vmlal.s16       q14, d0,  d18
1115        vmlal.s16       q15, d0,  d19
1116        vmlal.s16       q12, d16, d20 // += (top-bottom)*weights_ver
1117        vmlal.s16       q13, d17, d20
1118        vmlal.s16       q14, d16, d22
1119        vmlal.s16       q15, d17, d22
1120        vrshrn.i32      d24, q12, #9
1121        vrshrn.i32      d25, q13, #9
1122        vrshrn.i32      d26, q14, #9
1123        vrshrn.i32      d27, q15, #9
1124        subs            r3,  r3,  #8
1125        vst1.16         {q12}, [r0, :128]!
1126        vst1.16         {q13}, [r6, :128]!
1127        bgt             2b
1128        subs            r4,  r4,  #2
1129        ble             9f
1130        sub             r8,  r8,  r9, lsl #1
1131        sub             r10, r10, r9
1132        add             r0,  r0,  r1
1133        add             r6,  r6,  r1
1134        mov             r3,  r9
1135        b               1b
11369:
1137        pop             {r4-r10, pc}
1138endfunc
1139
1140// void ipred_smooth_v_16bpc_neon(pixel *dst, const ptrdiff_t stride,
1141//                                const pixel *const topleft,
1142//                                const int width, const int height, const int a,
1143//                                const int max_width, const int max_height);
1144function ipred_smooth_v_16bpc_neon, export=1
1145        push            {r4-r7, lr}
1146        ldr             r4,  [sp, #20]
1147        movrel          r7,  X(sm_weights)
1148        add             r7,  r7,  r4
1149        clz             lr,  r3
1150        adr             r5,  L(ipred_smooth_v_tbl)
1151        sub             r12, r2,  r4,  lsl #1
1152        sub             lr,  lr,  #25
1153        ldr             lr,  [r5, lr, lsl #2]
1154        vld1.16         {d4[], d5[]},  [r12] // bottom
1155        add             r2,  r2,  #2
1156        add             r5,  r5,  lr
1157        add             r6,  r0,  r1
1158        lsl             r1,  r1,  #1
1159        bx              r5
1160
1161        .align 2
1162L(ipred_smooth_v_tbl):
1163        .word 640f - L(ipred_smooth_v_tbl) + CONFIG_THUMB
1164        .word 320f - L(ipred_smooth_v_tbl) + CONFIG_THUMB
1165        .word 160f - L(ipred_smooth_v_tbl) + CONFIG_THUMB
1166        .word 80f  - L(ipred_smooth_v_tbl) + CONFIG_THUMB
1167        .word 40f  - L(ipred_smooth_v_tbl) + CONFIG_THUMB
1168
116940:
1170        vld1.16         {d6}, [r2]    // top
1171        vsub.i16        d6,  d6,  d4  // top-bottom
1172        vmov            d7,  d6
11734:
1174        vld4.8          {d16[], d17[], d18[], d19[]}, [r7, :32]! // weights_ver
1175        vzip.32         d16, d17      // weights_ver
1176        vzip.32         d18, d19
1177        vshll.u8        q8,  d16, #7  // weights_ver << 7
1178        vshll.u8        q9,  d18, #7
1179        vqrdmulh.s16    q10, q3,  q8  // ((top-bottom)*weights_ver + 128) >> 8
1180        vqrdmulh.s16    q11, q3,  q9
1181        vadd.i16        q10, q10, q2
1182        vadd.i16        q11, q11, q2
1183        vst1.16         {d20}, [r0, :64], r1
1184        vst1.16         {d21}, [r6, :64], r1
1185        subs            r4,  r4,  #4
1186        vst1.16         {d22}, [r0, :64], r1
1187        vst1.16         {d23}, [r6, :64], r1
1188        bgt             4b
1189        pop             {r4-r7, pc}
119080:
1191        vld1.16         {q3}, [r2]    // top
1192        vsub.i16        q3,  q3,  q2  // top-bottom
11938:
1194        vld4.8          {d16[], d18[], d20[], d22[]}, [r7, :32]! // weights_ver
1195        vshll.u8        q8,  d16, #7  // weights_ver << 7
1196        vshll.u8        q9,  d18, #7
1197        vshll.u8        q10, d20, #7
1198        vshll.u8        q11, d22, #7
1199        vqrdmulh.s16    q8,  q3,  q8  // ((top-bottom)*weights_ver + 128) >> 8
1200        vqrdmulh.s16    q9,  q3,  q9
1201        vqrdmulh.s16    q10, q3,  q10
1202        vqrdmulh.s16    q11, q3,  q11
1203        vadd.i16        q8,  q8,  q2
1204        vadd.i16        q9,  q9,  q2
1205        vadd.i16        q10, q10, q2
1206        vadd.i16        q11, q11, q2
1207        vst1.16         {q8},  [r0, :128], r1
1208        vst1.16         {q9},  [r6, :128], r1
1209        subs            r4,  r4,  #4
1210        vst1.16         {q10}, [r0, :128], r1
1211        vst1.16         {q11}, [r6, :128], r1
1212        bgt             8b
1213        pop             {r4-r7, pc}
1214160:
1215320:
1216640:
1217        vpush           {q4-q7}
1218        // Set up pointers for four rows in parallel; r0, r6, r5, lr
1219        add             r5,  r0,  r1
1220        add             lr,  r6,  r1
1221        lsl             r1,  r1,  #1
1222        sub             r1,  r1,  r3, lsl #1
1223        mov             r12, r3
1224
12251:
1226        vld4.8          {d8[], d10[], d12[], d14[]}, [r7, :32]! // weights_ver
1227        vshll.u8        q4,  d8,  #7  // weights_ver << 7
1228        vshll.u8        q5,  d10, #7
1229        vshll.u8        q6,  d12, #7
1230        vshll.u8        q7,  d14, #7
12312:
1232        vld1.16         {q0, q1}, [r2]!  // top
1233        vsub.i16        q0,  q0,  q2  // top-bottom
1234        vsub.i16        q1,  q1,  q2
1235        vqrdmulh.s16    q8,  q0,  q4  // ((top-bottom)*weights_ver + 128) >> 8
1236        vqrdmulh.s16    q9,  q1,  q4
1237        vqrdmulh.s16    q10, q0,  q5
1238        vqrdmulh.s16    q11, q1,  q5
1239        vqrdmulh.s16    q12, q0,  q6
1240        vqrdmulh.s16    q13, q1,  q6
1241        vqrdmulh.s16    q14, q0,  q7
1242        vqrdmulh.s16    q15, q1,  q7
1243        vadd.i16        q8,  q8,  q2
1244        vadd.i16        q9,  q9,  q2
1245        vadd.i16        q10, q10, q2
1246        vadd.i16        q11, q11, q2
1247        vadd.i16        q12, q12, q2
1248        vadd.i16        q13, q13, q2
1249        vadd.i16        q14, q14, q2
1250        vadd.i16        q15, q15, q2
1251        subs            r3,  r3,  #16
1252        vst1.16         {q8,  q9},  [r0, :128]!
1253        vst1.16         {q10, q11}, [r6, :128]!
1254        vst1.16         {q12, q13}, [r5, :128]!
1255        vst1.16         {q14, q15}, [lr, :128]!
1256        bgt             2b
1257        subs            r4,  r4,  #4
1258        ble             9f
1259        sub             r2,  r2,  r12, lsl #1
1260        add             r0,  r0,  r1
1261        add             r6,  r6,  r1
1262        add             r5,  r5,  r1
1263        add             lr,  lr,  r1
1264        mov             r3,  r12
1265        b               1b
12669:
1267        vpop            {q4-q7}
1268        pop             {r4-r7, pc}
1269endfunc
1270
1271// void ipred_smooth_h_16bpc_neon(pixel *dst, const ptrdiff_t stride,
1272//                                const pixel *const topleft,
1273//                                const int width, const int height, const int a,
1274//                                const int max_width, const int max_height);
1275function ipred_smooth_h_16bpc_neon, export=1
1276        push            {r4-r8, lr}
1277        ldr             r4,  [sp, #24]
1278        movrel          r8,  X(sm_weights)
1279        add             r8,  r8,  r3
1280        clz             lr,  r3
1281        adr             r5,  L(ipred_smooth_h_tbl)
1282        add             r12, r2,  r3, lsl #1
1283        sub             lr,  lr,  #25
1284        ldr             lr,  [r5, lr, lsl #2]
1285        vld1.16         {d4[], d5[]},  [r12] // right
1286        add             r5,  r5,  lr
1287        add             r6,  r0,  r1
1288        lsl             r1,  r1,  #1
1289        bx              r5
1290
1291        .align 2
1292L(ipred_smooth_h_tbl):
1293        .word 640f - L(ipred_smooth_h_tbl) + CONFIG_THUMB
1294        .word 320f - L(ipred_smooth_h_tbl) + CONFIG_THUMB
1295        .word 160f - L(ipred_smooth_h_tbl) + CONFIG_THUMB
1296        .word 80f  - L(ipred_smooth_h_tbl) + CONFIG_THUMB
1297        .word 40f  - L(ipred_smooth_h_tbl) + CONFIG_THUMB
1298
129940:
1300        vld1.32         {d6[]}, [r8, :32] // weights_hor
1301        sub             r2,  r2,  #8
1302        mov             r7,  #-8
1303        vshll.u8        q3,  d6,  #7  // weights_hor << 7
13044:
1305        vld4.16         {d0[], d1[], d2[], d3[]},  [r2, :64], r7 // left
1306        vsub.i16        q0,  q0,  q2  // left-right
1307        vsub.i16        q1,  q1,  q2
1308        subs            r4,  r4,  #4
1309        vqrdmulh.s16    q8,  q1,  q3  // ((left-right)*weights_hor + 128) >> 8
1310        vqrdmulh.s16    q9,  q0,  q3  // (left flipped)
1311        vadd.i16        q8,  q8,  q2
1312        vadd.i16        q9,  q9,  q2
1313        vst1.16         {d17}, [r0, :64], r1
1314        vst1.16         {d16}, [r6, :64], r1
1315        vst1.16         {d19}, [r0, :64], r1
1316        vst1.16         {d18}, [r6, :64], r1
1317        bgt             4b
1318        pop             {r4-r8, pc}
131980:
1320        vld1.8          {d6}, [r8, :64] // weights_hor
1321        sub             r2,  r2,  #8
1322        mov             r7,  #-8
1323        vshll.u8        q3,  d6,  #7  // weights_hor << 7
13248:
1325        vld1.16         {d23},  [r2, :64], r7 // left
1326        subs            r4,  r4,  #4
1327        vsub.i16        d23, d23, d4  // left-right
1328        vdup.16         q8,  d23[3]   // flip left
1329        vdup.16         q9,  d23[2]
1330        vdup.16         q10, d23[1]
1331        vdup.16         q11, d23[0]
1332        vqrdmulh.s16    q8,  q8,  q3  // ((left-right)*weights_hor + 128) >> 8
1333        vqrdmulh.s16    q9,  q9,  q3
1334        vqrdmulh.s16    q10, q10, q3
1335        vqrdmulh.s16    q11, q11, q3
1336        vadd.i16        q8,  q8,  q2
1337        vadd.i16        q9,  q9,  q2
1338        vadd.i16        q10, q10, q2
1339        vadd.i16        q11, q11, q2
1340        vst1.16         {q8},  [r0, :128], r1
1341        vst1.16         {q9},  [r6, :128], r1
1342        vst1.16         {q10}, [r0, :128], r1
1343        vst1.16         {q11}, [r6, :128], r1
1344        bgt             8b
1345        pop             {r4-r8, pc}
1346160:
1347320:
1348640:
1349        vpush           {q4-q7}
1350        sub             r2,  r2,  #8
1351        mov             r7,  #-8
1352        // Set up pointers for four rows in parallel; r0, r6, r5, lr
1353        add             r5,  r0,  r1
1354        add             lr,  r6,  r1
1355        lsl             r1,  r1,  #1
1356        sub             r1,  r1,  r3, lsl #1
1357        mov             r12, r3
1358
13591:
1360        vld1.16         {d15},  [r2, :64], r7 // left
1361        vsub.i16        d15, d15, d4  // left-right
1362        vdup.16         q4,  d15[3]   // flip left
1363        vdup.16         q5,  d15[2]
1364        vdup.16         q6,  d15[1]
1365        vdup.16         q7,  d15[0]
13662:
1367        vld1.8          {q1}, [r8, :128]! // weights_hor
1368        subs            r3,  r3,  #16
1369        vshll.u8        q0,  d2,  #7  // weights_hor << 7
1370        vshll.u8        q1,  d3,  #7
1371        vqrdmulh.s16    q8,  q0,  q4  // ((left-right)*weights_hor + 128) >> 8
1372        vqrdmulh.s16    q9,  q1,  q4
1373        vqrdmulh.s16    q10, q0,  q5
1374        vqrdmulh.s16    q11, q1,  q5
1375        vqrdmulh.s16    q12, q0,  q6
1376        vqrdmulh.s16    q13, q1,  q6
1377        vqrdmulh.s16    q14, q0,  q7
1378        vqrdmulh.s16    q15, q1,  q7
1379        vadd.i16        q8,  q8,  q2
1380        vadd.i16        q9,  q9,  q2
1381        vadd.i16        q10, q10, q2
1382        vadd.i16        q11, q11, q2
1383        vadd.i16        q12, q12, q2
1384        vadd.i16        q13, q13, q2
1385        vadd.i16        q14, q14, q2
1386        vadd.i16        q15, q15, q2
1387        vst1.16         {q8,  q9},  [r0, :128]!
1388        vst1.16         {q10, q11}, [r6, :128]!
1389        vst1.16         {q12, q13}, [r5, :128]!
1390        vst1.16         {q14, q15}, [lr, :128]!
1391        bgt             2b
1392        subs            r4,  r4,  #4
1393        ble             9f
1394        sub             r8,  r8,  r12
1395        add             r0,  r0,  r1
1396        add             r6,  r6,  r1
1397        add             r5,  r5,  r1
1398        add             lr,  lr,  r1
1399        mov             r3,  r12
1400        b               1b
14019:
1402        vpop            {q4-q7}
1403        pop             {r4-r8, pc}
1404endfunc
1405
1406// void ipred_filter_16bpc_neon(pixel *dst, const ptrdiff_t stride,
1407//                              const pixel *const topleft,
1408//                              const int width, const int height, const int filt_idx,
1409//                              const int max_width, const int max_height,
1410//                              const int bitdepth_max);
1411.macro filter_fn bpc
1412function ipred_filter_\bpc\()bpc_neon, export=1
1413        movw            r12, #511
1414        ldrd            r4,  r5,   [sp, #88]
1415        and             r5,  r5,  r12 // 511
1416        movrel          r6,  X(filter_intra_taps)
1417        lsl             r5,  r5,  #6
1418        add             r6,  r6,  r5
1419        vld1.8          {d20, d21, d22, d23}, [r6, :128]!
1420        clz             lr,  r3
1421        adr             r5,  L(ipred_filter\bpc\()_tbl)
1422        vld1.8          {d27, d28, d29}, [r6, :64]
1423        sub             lr,  lr,  #26
1424        ldr             lr,  [r5, lr, lsl #2]
1425        vmovl.s8        q8,  d20
1426        vmovl.s8        q9,  d21
1427        add             r5,  r5,  lr
1428        vmovl.s8        q10, d22
1429        vmovl.s8        q11, d23
1430        add             r6,  r0,  r1
1431        lsl             r1,  r1,  #1
1432        vmovl.s8        q12, d27
1433        vmovl.s8        q13, d28
1434        vmovl.s8        q14, d29
1435        mov             r7,  #-4
1436        vdup.16         q15, r8
1437        add             r8,  r2,  #2
1438        sub             r2,  r2,  #4
1439.if \bpc == 10
1440        vmov.i16        q7,  #0
1441.endif
1442        bx              r5
1443
1444        .align 2
1445L(ipred_filter\bpc\()_tbl):
1446        .word 320f - L(ipred_filter\bpc\()_tbl) + CONFIG_THUMB
1447        .word 160f - L(ipred_filter\bpc\()_tbl) + CONFIG_THUMB
1448        .word 80f  - L(ipred_filter\bpc\()_tbl) + CONFIG_THUMB
1449        .word 40f  - L(ipred_filter\bpc\()_tbl) + CONFIG_THUMB
1450
145140:
1452        vld1.16         {d0}, [r8]       // top (0-3)
14534:
1454        vld1.16         {d2}, [r2], r7   // left (0-1) + topleft (2)
1455.if \bpc == 10
1456        vmul.i16        q2,  q9,  d0[0]  // p1(top[0]) * filter(1)
1457        vmla.i16        q2,  q10, d0[1]  // p2(top[1]) * filter(2)
1458        vmla.i16        q2,  q11, d0[2]  // p3(top[2]) * filter(3)
1459        vmla.i16        q2,  q12, d0[3]  // p4(top[3]) * filter(4)
1460        vmla.i16        q2,  q8,  d2[2]  // p0(topleft) * filter(0)
1461        vmla.i16        q2,  q13, d2[1]  // p5(left[0]) * filter(5)
1462        vmla.i16        q2,  q14, d2[0]  // p6(left[1]) * filter(6)
1463        vrshr.s16       q2,  q2,  #4
1464        vmax.s16        q2,  q2,  q7
1465.else
1466        vmull.s16       q2,  d18, d0[0]  // p1(top[0]) * filter(1)
1467        vmlal.s16       q2,  d20, d0[1]  // p2(top[1]) * filter(2)
1468        vmlal.s16       q2,  d22, d0[2]  // p3(top[2]) * filter(3)
1469        vmlal.s16       q2,  d24, d0[3]  // p4(top[3]) * filter(4)
1470        vmlal.s16       q2,  d16, d2[2]  // p0(topleft) * filter(0)
1471        vmlal.s16       q2,  d26, d2[1]  // p5(left[0]) * filter(5)
1472        vmlal.s16       q2,  d28, d2[0]  // p6(left[1]) * filter(6)
1473        vmull.s16       q3,  d19, d0[0]  // p1(top[0]) * filter(1)
1474        vmlal.s16       q3,  d21, d0[1]  // p2(top[1]) * filter(2)
1475        vmlal.s16       q3,  d23, d0[2]  // p3(top[2]) * filter(3)
1476        vmlal.s16       q3,  d25, d0[3]  // p4(top[3]) * filter(4)
1477        vmlal.s16       q3,  d17, d2[2]  // p0(topleft) * filter(0)
1478        vmlal.s16       q3,  d27, d2[1]  // p5(left[0]) * filter(5)
1479        vmlal.s16       q3,  d29, d2[0]  // p6(left[1]) * filter(6)
1480        vqrshrun.s32    d4,  q2,  #4
1481        vqrshrun.s32    d5,  q3,  #4
1482.endif
1483        vmin.s16        q2,  q2,  q15
1484        subs            r4,  r4,  #2
1485        vst1.16         {d4}, [r0, :64], r1
1486        vst1.16         {d5}, [r6, :64], r1
1487        vmov            d0,  d5          // move top from [4-7] to [0-3]
1488        bgt             4b
1489        vpop            {q4-q7}
1490        pop             {r4-r8, pc}
149180:
1492        vld1.16         {q0},  [r8]      // top (0-7)
14938:
1494        vld1.16         {d2}, [r2], r7   // left (0-1) + topleft (2)
1495.if \bpc == 10
1496        vmul.i16        q2,  q9,  d0[0]  // p1(top[0]) * filter(1)
1497        vmla.i16        q2,  q10, d0[1]  // p2(top[1]) * filter(2)
1498        vmla.i16        q2,  q11, d0[2]  // p3(top[2]) * filter(3)
1499        vmla.i16        q2,  q12, d0[3]  // p4(top[3]) * filter(4)
1500        vmla.i16        q2,  q8,  d2[2]  // p0(topleft) * filter(0)
1501        vmla.i16        q2,  q13, d2[1]  // p5(left[0]) * filter(5)
1502        vmla.i16        q2,  q14, d2[0]  // p6(left[1]) * filter(6)
1503        vmul.i16        q3,  q9,  d1[0]  // p1(top[0]) * filter(1)
1504        vmla.i16        q3,  q10, d1[1]  // p2(top[1]) * filter(2)
1505        vmla.i16        q3,  q11, d1[2]  // p3(top[2]) * filter(3)
1506        vrshr.s16       q2,  q2,  #4
1507        vmax.s16        q2,  q2,  q7
1508        vmin.s16        q2,  q2,  q15
1509        vmla.i16        q3,  q12, d1[3]  // p4(top[3]) * filter(4)
1510        vmla.i16        q3,  q8,  d0[3]  // p0(topleft) * filter(0)
1511        vmla.i16        q3,  q13, d4[3]  // p5(left[0]) * filter(5)
1512        vmla.i16        q3,  q14, d5[3]  // p6(left[1]) * filter(6)
1513        vrshr.s16       q3,  q3,  #4
1514        vmax.s16        q3,  q3,  q7
1515.else
1516        vmull.s16       q2,  d18, d0[0]  // p1(top[0]) * filter(1)
1517        vmlal.s16       q2,  d20, d0[1]  // p2(top[1]) * filter(2)
1518        vmlal.s16       q2,  d22, d0[2]  // p3(top[2]) * filter(3)
1519        vmlal.s16       q2,  d24, d0[3]  // p4(top[3]) * filter(4)
1520        vmlal.s16       q2,  d16, d2[2]  // p0(topleft) * filter(0)
1521        vmlal.s16       q2,  d26, d2[1]  // p5(left[0]) * filter(5)
1522        vmlal.s16       q2,  d28, d2[0]  // p6(left[1]) * filter(6)
1523        vmull.s16       q3,  d19, d0[0]  // p1(top[0]) * filter(1)
1524        vmlal.s16       q3,  d21, d0[1]  // p2(top[1]) * filter(2)
1525        vmlal.s16       q3,  d23, d0[2]  // p3(top[2]) * filter(3)
1526        vmlal.s16       q3,  d25, d0[3]  // p4(top[3]) * filter(4)
1527        vmlal.s16       q3,  d17, d2[2]  // p0(topleft) * filter(0)
1528        vmlal.s16       q3,  d27, d2[1]  // p5(left[0]) * filter(5)
1529        vmlal.s16       q3,  d29, d2[0]  // p6(left[1]) * filter(6)
1530        vqrshrun.s32    d4,  q2,  #4
1531        vmull.s16       q4,  d18, d1[0]  // p1(top[0]) * filter(1)
1532        vmlal.s16       q4,  d20, d1[1]  // p2(top[1]) * filter(2)
1533        vmlal.s16       q4,  d22, d1[2]  // p3(top[2]) * filter(3)
1534        vqrshrun.s32    d5,  q3,  #4
1535        vmin.s16        q2,  q2,  q15
1536        vmlal.s16       q4,  d24, d1[3]  // p4(top[3]) * filter(4)
1537        vmlal.s16       q4,  d16, d0[3]  // p0(topleft) * filter(0)
1538        vmlal.s16       q4,  d26, d4[3]  // p5(left[0]) * filter(5)
1539        vmlal.s16       q4,  d28, d5[3]  // p6(left[1]) * filter(6)
1540        vmull.s16       q5,  d19, d1[0]  // p1(top[0]) * filter(1)
1541        vmlal.s16       q5,  d21, d1[1]  // p2(top[1]) * filter(2)
1542        vmlal.s16       q5,  d23, d1[2]  // p3(top[2]) * filter(3)
1543        vmlal.s16       q5,  d25, d1[3]  // p4(top[3]) * filter(4)
1544        vmlal.s16       q5,  d17, d0[3]  // p0(topleft) * filter(0)
1545        vmlal.s16       q5,  d27, d4[3]  // p5(left[0]) * filter(5)
1546        vmlal.s16       q5,  d29, d5[3]  // p6(left[1]) * filter(6)
1547        vqrshrun.s32    d6,  q4,  #4
1548        vqrshrun.s32    d7,  q5,  #4
1549.endif
1550        vmin.s16        q3,  q3,  q15
1551        vswp            d5,  d6
1552        subs            r4,  r4,  #2
1553        vst1.16         {q2}, [r0, :128], r1
1554        vmov            q0,  q3
1555        vst1.16         {q3}, [r6, :128], r1
1556        bgt             8b
1557        vpop            {q4-q7}
1558        pop             {r4-r8, pc}
1559160:
1560320:
1561        sub             r1,  r1,  r3, lsl #1
1562        mov             lr,  r3
1563
15641:
1565        vld1.16         {d0}, [r2], r7   // left (0-1) + topleft (2)
15662:
1567        vld1.16         {q1, q2}, [r8]!  // top(0-15)
1568.if \bpc == 10
1569        vmul.i16        q3,  q8,  d0[2]  // p0(topleft) * filter(0)
1570        vmla.i16        q3,  q13, d0[1]  // p5(left[0]) * filter(5)
1571        vmla.i16        q3,  q14, d0[0]  // p6(left[1]) * filter(6)
1572        vmla.i16        q3,  q9,  d2[0]  // p1(top[0]) * filter(1)
1573        vmla.i16        q3,  q10, d2[1]  // p2(top[1]) * filter(2)
1574        vmla.i16        q3,  q11, d2[2]  // p3(top[2]) * filter(3)
1575        vmla.i16        q3,  q12, d2[3]  // p4(top[3]) * filter(4)
1576
1577        vmul.i16        q4,  q9,  d3[0]  // p1(top[0]) * filter(1)
1578        vmla.i16        q4,  q10, d3[1]  // p2(top[1]) * filter(2)
1579        vmla.i16        q4,  q11, d3[2]  // p3(top[2]) * filter(3)
1580        vrshr.s16       q3,  q3,  #4
1581        vmax.s16        q3,  q3,  q7
1582        vmin.s16        q3,  q3,  q15
1583        vmla.i16        q4,  q12, d3[3]  // p4(top[3]) * filter(4)
1584        vmla.i16        q4,  q8,  d2[3]  // p0(topleft) * filter(0)
1585        vmla.i16        q4,  q13, d6[3]  // p5(left[0]) * filter(5)
1586        vmla.i16        q4,  q14, d7[3]  // p6(left[1]) * filter(6)
1587
1588        vmul.i16        q5,  q9,  d4[0]  // p1(top[0]) * filter(1)
1589        vmla.i16        q5,  q10, d4[1]  // p2(top[1]) * filter(2)
1590        vmla.i16        q5,  q11, d4[2]  // p3(top[2]) * filter(3)
1591        vrshr.s16       q4,  q4,  #4
1592        vmax.s16        q4,  q4,  q7
1593        vmin.s16        q4,  q4,  q15
1594        vmov            q0,  q4
1595        vmla.i16        q5,  q12, d4[3]  // p4(top[3]) * filter(4)
1596        vmla.i16        q5,  q8,  d3[3]  // p0(topleft) * filter(0)
1597        vmla.i16        q5,  q13, d0[3]  // p5(left[0]) * filter(5)
1598        vmla.i16        q5,  q14, d1[3]  // p6(left[1]) * filter(6)
1599
1600        vmul.i16        q6,  q9,  d5[0]  // p1(top[0]) * filter(1)
1601        vmla.i16        q6,  q10, d5[1]  // p2(top[1]) * filter(2)
1602        vmla.i16        q6,  q11, d5[2]  // p3(top[2]) * filter(3)
1603        vrshr.s16       q5,  q5,  #4
1604        vmax.s16        q5,  q5,  q7
1605        vmin.s16        q5,  q5,  q15
1606        vmov            q0,  q5
1607        vmov.u16        r12, d5[3]
1608        vmla.i16        q6,  q12, d5[3]  // p4(top[3]) * filter(4)
1609        vmla.i16        q6,  q8,  d4[3]  // p0(topleft) * filter(0)
1610        vmla.i16        q6,  q13, d0[3]  // p5(left[0]) * filter(5)
1611        vmla.i16        q6,  q14, d1[3]  // p6(left[1]) * filter(6)
1612        vmov.16         d0[2], r12
1613        subs            r3,  r3,  #16
1614        vrshr.s16       q6,  q6,  #4
1615.else
1616        vmull.s16       q3,  d16, d0[2]  // p0(topleft) * filter(0)
1617        vmlal.s16       q3,  d26, d0[1]  // p5(left[0]) * filter(5)
1618        vmlal.s16       q3,  d28, d0[0]  // p6(left[1]) * filter(6)
1619        vmlal.s16       q3,  d18, d2[0]  // p1(top[0]) * filter(1)
1620        vmlal.s16       q3,  d20, d2[1]  // p2(top[1]) * filter(2)
1621        vmlal.s16       q3,  d22, d2[2]  // p3(top[2]) * filter(3)
1622        vmlal.s16       q3,  d24, d2[3]  // p4(top[3]) * filter(4)
1623        vmull.s16       q4,  d17, d0[2]  // p0(topleft) * filter(0)
1624        vmlal.s16       q4,  d27, d0[1]  // p5(left[0]) * filter(5)
1625        vmlal.s16       q4,  d29, d0[0]  // p6(left[1]) * filter(6)
1626        vmlal.s16       q4,  d19, d2[0]  // p1(top[0]) * filter(1)
1627        vmlal.s16       q4,  d21, d2[1]  // p2(top[1]) * filter(2)
1628        vmlal.s16       q4,  d23, d2[2]  // p3(top[2]) * filter(3)
1629        vmlal.s16       q4,  d25, d2[3]  // p4(top[3]) * filter(4)
1630        vqrshrun.s32    d6,  q3,  #4
1631        vmull.s16       q5,  d18, d3[0]  // p1(top[0]) * filter(1)
1632        vmlal.s16       q5,  d20, d3[1]  // p2(top[1]) * filter(2)
1633        vqrshrun.s32    d7,  q4,  #4
1634        vmin.s16        q3,  q3,  q15
1635        vmlal.s16       q5,  d22, d3[2]  // p3(top[2]) * filter(3)
1636        vmlal.s16       q5,  d24, d3[3]  // p4(top[3]) * filter(4)
1637        vmlal.s16       q5,  d16, d2[3]  // p0(topleft) * filter(0)
1638        vmlal.s16       q5,  d26, d6[3]  // p5(left[0]) * filter(5)
1639        vmlal.s16       q5,  d28, d7[3]  // p6(left[1]) * filter(6)
1640        vmull.s16       q6,  d19, d3[0]  // p1(top[0]) * filter(1)
1641        vmlal.s16       q6,  d21, d3[1]  // p2(top[1]) * filter(2)
1642        vmlal.s16       q6,  d23, d3[2]  // p3(top[2]) * filter(3)
1643        vmlal.s16       q6,  d25, d3[3]  // p4(top[3]) * filter(4)
1644        vmlal.s16       q6,  d17, d2[3]  // p0(topleft) * filter(0)
1645        vmlal.s16       q6,  d27, d6[3]  // p5(left[0]) * filter(5)
1646        vmlal.s16       q6,  d29, d7[3]  // p6(left[1]) * filter(6)
1647        vqrshrun.s32    d8,  q5,  #4
1648        vmull.s16       q7,  d18, d4[0]  // p1(top[0]) * filter(1)
1649        vmlal.s16       q7,  d20, d4[1]  // p2(top[1]) * filter(2)
1650        vmlal.s16       q7,  d22, d4[2]  // p3(top[2]) * filter(3)
1651        vqrshrun.s32    d9,  q6,  #4
1652        vmin.s16        q0,  q4,  q15
1653        vmlal.s16       q7,  d24, d4[3]  // p4(top[3]) * filter(4)
1654        vmlal.s16       q7,  d16, d3[3]  // p0(topleft) * filter(0)
1655        vmlal.s16       q7,  d26, d0[3]  // p5(left[0]) * filter(5)
1656        vmlal.s16       q7,  d28, d1[3]  // p6(left[1]) * filter(6)
1657        vmin.s16        q4,  q4,  q15
1658        vmull.s16       q6,  d19, d4[0]  // p1(top[0]) * filter(1)
1659        vmlal.s16       q6,  d21, d4[1]  // p2(top[1]) * filter(2)
1660        vmlal.s16       q6,  d23, d4[2]  // p3(top[2]) * filter(3)
1661        vmlal.s16       q6,  d25, d4[3]  // p4(top[3]) * filter(4)
1662        vmlal.s16       q6,  d17, d3[3]  // p0(topleft) * filter(0)
1663        vmlal.s16       q6,  d27, d0[3]  // p5(left[0]) * filter(5)
1664        vmlal.s16       q6,  d29, d1[3]  // p6(left[1]) * filter(6)
1665        vqrshrun.s32    d10, q7,  #4
1666        vmull.s16       q1,  d18, d5[0]  // p1(top[0]) * filter(1)
1667        vmlal.s16       q1,  d20, d5[1]  // p2(top[1]) * filter(2)
1668        vmlal.s16       q1,  d22, d5[2]  // p3(top[2]) * filter(3)
1669        vqrshrun.s32    d11, q6,  #4
1670        vmin.s16        q0,  q5,  q15
1671        vmlal.s16       q1,  d24, d5[3]  // p4(top[3]) * filter(4)
1672        vmlal.s16       q1,  d16, d4[3]  // p0(topleft) * filter(0)
1673        vmlal.s16       q1,  d26, d0[3]  // p5(left[0]) * filter(5)
1674        vmlal.s16       q1,  d28, d1[3]  // p6(left[1]) * filter(6)
1675        vmin.s16        q5,  q5,  q15
1676        vmov.u16        r12, d5[3]
1677        vmull.s16       q7,  d19, d5[0]  // p1(top[0]) * filter(1)
1678        vmlal.s16       q7,  d21, d5[1]  // p2(top[1]) * filter(2)
1679        vmlal.s16       q7,  d23, d5[2]  // p3(top[2]) * filter(3)
1680        vmlal.s16       q7,  d25, d5[3]  // p4(top[3]) * filter(4)
1681        vmlal.s16       q7,  d17, d4[3]  // p0(topleft) * filter(0)
1682        vmlal.s16       q7,  d27, d0[3]  // p5(left[0]) * filter(5)
1683        vmlal.s16       q7,  d29, d1[3]  // p6(left[1]) * filter(6)
1684        vmov.16         d0[2], r12
1685        vqrshrun.s32    d12, q1,  #4
1686        subs            r3,  r3,  #16
1687        vqrshrun.s32    d13, q7,  #4
1688.endif
1689        vswp            q4,  q5
1690.if \bpc == 10
1691        vmax.s16        q6,  q6,  q7
1692.endif
1693        vswp            d7,  d10
1694        vmin.s16        q6,  q6,  q15
1695
1696        vswp            d9,  d12
1697
1698        vst1.16         {q3, q4}, [r0, :128]!
1699        vst1.16         {q5, q6}, [r6, :128]!
1700        ble             8f
1701        vmov.u16        r12, d13[3]
1702        vmov.16         d0[0], r12
1703        vmov.u16        r12, d9[3]
1704        vmov.16         d0[1], r12
1705        b               2b
17068:
1707        subs            r4,  r4,  #2
1708
1709        ble             9f
1710        sub             r8,  r6,  lr, lsl #1
1711        add             r0,  r0,  r1
1712        add             r6,  r6,  r1
1713        mov             r3,  lr
1714        b               1b
17159:
1716        vpop            {q4-q7}
1717        pop             {r4-r8, pc}
1718endfunc
1719.endm
1720
1721filter_fn 10
1722filter_fn 12
1723
1724function ipred_filter_16bpc_neon, export=1
1725        push            {r4-r8, lr}
1726        vpush           {q4-q7}
1727        movw            r12, 0x3ff
1728        ldr             r8, [sp, #104]
1729        cmp             r8,  r12
1730        ble             ipred_filter_10bpc_neon
1731        b               ipred_filter_12bpc_neon
1732endfunc
1733
1734// void pal_pred_16bpc_neon(pixel *dst, const ptrdiff_t stride,
1735//                          const pixel *const pal, const uint8_t *idx,
1736//                          const int w, const int h);
1737function pal_pred_16bpc_neon, export=1
1738        push            {r4-r5, lr}
1739        ldr             r4,  [sp, #12]
1740        ldr             r5,  [sp, #16]
1741        vld1.16         {q14}, [r2, :128]
1742        clz             lr,  r4
1743        adr             r12, L(pal_pred_tbl)
1744        sub             lr,  lr,  #25
1745        vmov.i8         q13, #7
1746        ldr             lr,  [r12, lr, lsl #2]
1747        vmov.i16        q15, #0x100
1748        add             r12, r12, lr
1749        add             r2,  r0,  r1
1750        bx              r12
1751
1752        .align 2
1753L(pal_pred_tbl):
1754        .word 640f - L(pal_pred_tbl) + CONFIG_THUMB
1755        .word 320f - L(pal_pred_tbl) + CONFIG_THUMB
1756        .word 160f - L(pal_pred_tbl) + CONFIG_THUMB
1757        .word 80f  - L(pal_pred_tbl) + CONFIG_THUMB
1758        .word 40f  - L(pal_pred_tbl) + CONFIG_THUMB
1759
176040:
1761        lsl             r1,  r1,  #1
17624:
1763        vld1.8          {d2}, [r3, :64]!
1764        subs            r5,  r5,  #4
1765        vshr.u8         d3,  d2,  #4
1766        vand.u8         d2,  d2,  d26
1767        vzip.8          d2,  d3
1768        // Restructure q1 from a, b, c, ... into 2*a, 2*a+1, 2*b, 2*b+1, 2*c, 2*c+1, ...
1769        vadd.i8         q0,  q1,  q1
1770        vadd.i8         q1,  q1,  q1
1771        vzip.8          q0,  q1
1772        vadd.i16        q0,  q0,  q15
1773        vadd.i16        q1,  q1,  q15
1774        vtbl.8          d0, {q14}, d0
1775        vtbl.8          d1, {q14}, d1
1776        vst1.16         {d0}, [r0, :64], r1
1777        vtbl.8          d2, {q14}, d2
1778        vst1.16         {d1}, [r2, :64], r1
1779        vtbl.8          d3, {q14}, d3
1780        vst1.16         {d2}, [r0, :64], r1
1781        vst1.16         {d3}, [r2, :64], r1
1782        bgt             4b
1783        pop             {r4-r5, pc}
178480:
1785        lsl             r1,  r1,  #1
17868:
1787        vld1.8          {q1}, [r3, :64]!
1788        subs            r5,  r5,  #4
1789        vshr.u8         q2,  q1,  #4
1790        vand.u8         q1,  q1,  q13
1791        vzip.8          q1,  q2
1792        // Prefer doing the adds twice, instead of chaining a vmov after
1793        // the add.
1794        vadd.i8         q0,  q1,  q1
1795        vadd.i8         q1,  q1,  q1
1796        vadd.i8         q3,  q2,  q2
1797        vadd.i8         q2,  q2,  q2
1798        vzip.8          q0,  q1
1799        vzip.8          q2,  q3
1800        vadd.i16        q0,  q0,  q15
1801        vadd.i16        q1,  q1,  q15
1802        vtbl.8          d0, {q14}, d0
1803        vadd.i16        q2,  q2,  q15
1804        vtbl.8          d1, {q14}, d1
1805        vadd.i16        q3,  q3,  q15
1806        vtbl.8          d2, {q14}, d2
1807        vtbl.8          d3, {q14}, d3
1808        vtbl.8          d4, {q14}, d4
1809        vtbl.8          d5, {q14}, d5
1810        vst1.16         {q0}, [r0, :128], r1
1811        vtbl.8          d6, {q14}, d6
1812        vst1.16         {q1}, [r2, :128], r1
1813        vtbl.8          d7, {q14}, d7
1814        vst1.16         {q2}, [r0, :128], r1
1815        vst1.16         {q3}, [r2, :128], r1
1816        bgt             8b
1817        pop             {r4-r5, pc}
1818160:
1819        lsl             r1,  r1,  #1
182016:
1821        vld1.8          {q10, q11}, [r3, :64]!
1822        subs            r5,  r5,  #4
1823        vand.u8         q2,  q10, q13
1824        vshr.u8         q3,  q10, #4
1825        vand.u8         q10, q11, q13
1826        vshr.u8         q11, q11, #4
1827        vzip.8          q2,  q3
1828        vzip.8          q10, q11
1829        vadd.i8         q0,  q2,  q2
1830        vadd.i8         q1,  q2,  q2
1831        vadd.i8         q2,  q3,  q3
1832        vadd.i8         q3,  q3,  q3
1833        vadd.i8         q8,  q10, q10
1834        vadd.i8         q9,  q10, q10
1835        vadd.i8         q10, q11, q11
1836        vzip.8          q0,  q1
1837        vadd.i8         q11, q11, q11
1838        vzip.8          q2,  q3
1839        vzip.8          q8,  q9
1840        vadd.i16        q0,  q0,  q15
1841        vzip.8          q10, q11
1842        vadd.i16        q1,  q1,  q15
1843        vadd.i16        q2,  q2,  q15
1844        vadd.i16        q3,  q3,  q15
1845        vadd.i16        q8,  q8,  q15
1846        vadd.i16        q9,  q9,  q15
1847        vadd.i16        q10, q10, q15
1848        vtbl.8          d0,  {q14}, d0
1849        vadd.i16        q11, q11, q15
1850        vtbl.8          d1,  {q14}, d1
1851        vtbl.8          d2,  {q14}, d2
1852        vtbl.8          d3,  {q14}, d3
1853        vtbl.8          d4,  {q14}, d4
1854        vtbl.8          d5,  {q14}, d5
1855        vtbl.8          d6,  {q14}, d6
1856        vtbl.8          d7,  {q14}, d7
1857        vtbl.8          d16, {q14}, d16
1858        vtbl.8          d17, {q14}, d17
1859        vtbl.8          d18, {q14}, d18
1860        vst1.16         {q0,  q1},  [r0, :128], r1
1861        vtbl.8          d19, {q14}, d19
1862        vtbl.8          d20, {q14}, d20
1863        vst1.16         {q2,  q3},  [r2, :128], r1
1864        vtbl.8          d21, {q14}, d21
1865        vtbl.8          d22, {q14}, d22
1866        vst1.16         {q8,  q9},  [r0, :128], r1
1867        vtbl.8          d23, {q14}, d23
1868        vst1.16         {q10, q11}, [r2, :128], r1
1869        bgt             16b
1870        pop             {r4-r5, pc}
1871320:
1872        lsl             r1,  r1,  #1
1873        sub             r1,  r1,  #32
187432:
1875        vld1.8          {q10, q11}, [r3, :64]!
1876        subs            r5,  r5,  #2
1877        vand.u8         q2,  q10, q13
1878        vshr.u8         q3,  q10, #4
1879        vand.u8         q10, q11, q13
1880        vshr.u8         q11, q11, #4
1881        vzip.8          q2,  q3
1882        vzip.8          q10, q11
1883        vadd.i8         q0,  q2,  q2
1884        vadd.i8         q1,  q2,  q2
1885        vadd.i8         q2,  q3,  q3
1886        vadd.i8         q3,  q3,  q3
1887        vadd.i8         q8,  q10, q10
1888        vadd.i8         q9,  q10, q10
1889        vadd.i8         q10, q11, q11
1890        vzip.8          q0,  q1
1891        vadd.i8         q11, q11, q11
1892        vzip.8          q2,  q3
1893        vzip.8          q8,  q9
1894        vadd.i16        q0,  q0,  q15
1895        vzip.8          q10, q11
1896        vadd.i16        q1,  q1,  q15
1897        vadd.i16        q2,  q2,  q15
1898        vadd.i16        q3,  q3,  q15
1899        vadd.i16        q8,  q8,  q15
1900        vadd.i16        q9,  q9,  q15
1901        vadd.i16        q10, q10, q15
1902        vtbl.8          d0,  {q14}, d0
1903        vadd.i16        q11, q11, q15
1904        vtbl.8          d1,  {q14}, d1
1905        vtbl.8          d2,  {q14}, d2
1906        vtbl.8          d3,  {q14}, d3
1907        vtbl.8          d4,  {q14}, d4
1908        vtbl.8          d5,  {q14}, d5
1909        vtbl.8          d6,  {q14}, d6
1910        vtbl.8          d7,  {q14}, d7
1911        vtbl.8          d16, {q14}, d16
1912        vtbl.8          d17, {q14}, d17
1913        vtbl.8          d18, {q14}, d18
1914        vst1.16         {q0,  q1},  [r0, :128]!
1915        vtbl.8          d19, {q14}, d19
1916        vtbl.8          d20, {q14}, d20
1917        vst1.16         {q2,  q3},  [r0, :128], r1
1918        vtbl.8          d21, {q14}, d21
1919        vtbl.8          d22, {q14}, d22
1920        vst1.16         {q8,  q9},  [r2, :128]!
1921        vtbl.8          d23, {q14}, d23
1922        vst1.16         {q10, q11}, [r2, :128], r1
1923        bgt             32b
1924        pop             {r4-r5, pc}
1925640:
1926        sub             r1,  r1,  #96
192764:
1928        vld1.8          {q10, q11}, [r3, :64]!
1929        subs            r5,  r5,  #1
1930        vand.u8         q2,  q10, q13
1931        vshr.u8         q3,  q10, #4
1932        vand.u8         q10, q11, q13
1933        vshr.u8         q11, q11, #4
1934        vzip.8          q2,  q3
1935        vzip.8          q10, q11
1936        vadd.i8         q0,  q2,  q2
1937        vadd.i8         q1,  q2,  q2
1938        vadd.i8         q2,  q3,  q3
1939        vadd.i8         q3,  q3,  q3
1940        vadd.i8         q8,  q10, q10
1941        vadd.i8         q9,  q10, q10
1942        vadd.i8         q10, q11, q11
1943        vzip.8          q0,  q1
1944        vadd.i8         q11, q11, q11
1945        vzip.8          q2,  q3
1946        vzip.8          q8,  q9
1947        vadd.i16        q0,  q0,  q15
1948        vzip.8          q10, q11
1949        vadd.i16        q1,  q1,  q15
1950        vadd.i16        q2,  q2,  q15
1951        vadd.i16        q3,  q3,  q15
1952        vadd.i16        q8,  q8,  q15
1953        vadd.i16        q9,  q9,  q15
1954        vadd.i16        q10, q10, q15
1955        vtbl.8          d0,  {q14}, d0
1956        vadd.i16        q11, q11, q15
1957        vtbl.8          d1,  {q14}, d1
1958        vtbl.8          d2,  {q14}, d2
1959        vtbl.8          d3,  {q14}, d3
1960        vtbl.8          d4,  {q14}, d4
1961        vtbl.8          d5,  {q14}, d5
1962        vtbl.8          d6,  {q14}, d6
1963        vtbl.8          d7,  {q14}, d7
1964        vtbl.8          d16, {q14}, d16
1965        vtbl.8          d17, {q14}, d17
1966        vtbl.8          d18, {q14}, d18
1967        vst1.16         {q0,  q1},  [r0, :128]!
1968        vtbl.8          d19, {q14}, d19
1969        vtbl.8          d20, {q14}, d20
1970        vst1.16         {q2,  q3},  [r0, :128]!
1971        vtbl.8          d21, {q14}, d21
1972        vtbl.8          d22, {q14}, d22
1973        vst1.16         {q8,  q9},  [r0, :128]!
1974        vtbl.8          d23, {q14}, d23
1975        vst1.16         {q10, q11}, [r0, :128], r1
1976        bgt             64b
1977        pop             {r4-r5, pc}
1978endfunc
1979
1980// void ipred_cfl_128_16bpc_neon(pixel *dst, const ptrdiff_t stride,
1981//                               const pixel *const topleft,
1982//                               const int width, const int height,
1983//                               const int16_t *ac, const int alpha,
1984//                               const int bitdepth_max);
1985function ipred_cfl_128_16bpc_neon, export=1
1986        push            {r4-r8, lr}
1987        ldrd            r4,  r5,  [sp, #24]
1988        ldrd            r6,  r7,  [sp, #32]
1989        clz             lr,  r3
1990        vdup.16         q15, r7       // bitdepth_max
1991        adr             r12, L(ipred_cfl_128_tbl)
1992        sub             lr,  lr,  #26
1993        ldr             lr,  [r12, lr, lsl #2]
1994        vrshr.u16       q0,  q15, #1
1995        vdup.16         q1,  r6       // alpha
1996        add             r12, r12, lr
1997        add             r6,  r0,  r1
1998        lsl             r1,  r1,  #1
1999        vmov.i16        q14, #0
2000        bx              r12
2001
2002        .align 2
2003L(ipred_cfl_128_tbl):
2004L(ipred_cfl_splat_tbl):
2005        .word L(ipred_cfl_splat_w16) - L(ipred_cfl_128_tbl) + CONFIG_THUMB
2006        .word L(ipred_cfl_splat_w16) - L(ipred_cfl_128_tbl) + CONFIG_THUMB
2007        .word L(ipred_cfl_splat_w8)  - L(ipred_cfl_128_tbl) + CONFIG_THUMB
2008        .word L(ipred_cfl_splat_w4)  - L(ipred_cfl_128_tbl) + CONFIG_THUMB
2009
2010L(ipred_cfl_splat_w4):
2011        vld1.16         {q8, q9}, [r5, :128]!
2012        vmull.s16       q2,  d16, d2  // diff = ac * alpha
2013        vmull.s16       q3,  d17, d3
2014        vmull.s16       q8,  d18, d2
2015        vmull.s16       q9,  d19, d3
2016        vshr.s32        q10, q2,  #31 // sign = diff >> 15
2017        vshr.s32        q11, q3,  #31
2018        vshr.s32        q12, q8,  #31
2019        vshr.s32        q13, q9,  #31
2020        vadd.i32        q2,  q2,  q10 // diff + sign
2021        vadd.i32        q3,  q3,  q11
2022        vadd.i32        q8,  q8,  q12
2023        vadd.i32        q9,  q9,  q13
2024        vrshrn.i32      d4,  q2,  #6  // (diff + sign + 32) >> 6 = apply_sign()
2025        vrshrn.i32      d5,  q3,  #6
2026        vrshrn.i32      d6,  q8,  #6
2027        vrshrn.i32      d7,  q9,  #6
2028        vadd.i16        q2,  q2,  q0  // dc + apply_sign()
2029        vadd.i16        q3,  q3,  q0
2030        vmax.s16        q2,  q2,  q14
2031        vmax.s16        q3,  q3,  q14
2032        vmin.s16        q2,  q2,  q15
2033        vmin.s16        q3,  q3,  q15
2034        vst1.16         {d4}, [r0, :64], r1
2035        vst1.16         {d5}, [r6, :64], r1
2036        subs            r4,  r4,  #4
2037        vst1.16         {d6}, [r0, :64], r1
2038        vst1.16         {d7}, [r6, :64], r1
2039        bgt             L(ipred_cfl_splat_w4)
2040        pop             {r4-r8, pc}
2041L(ipred_cfl_splat_w8):
2042        vld1.16         {q8, q9}, [r5, :128]!
2043        subs            r4,  r4,  #2
2044        vmull.s16       q2,  d16, d2  // diff = ac * alpha
2045        vmull.s16       q3,  d17, d3
2046        vmull.s16       q8,  d18, d2
2047        vmull.s16       q9,  d19, d3
2048        vshr.s32        q10, q2,  #31 // sign = diff >> 15
2049        vshr.s32        q11, q3,  #31
2050        vshr.s32        q12, q8,  #31
2051        vshr.s32        q13, q9,  #31
2052        vadd.i32        q2,  q2,  q10 // diff + sign
2053        vadd.i32        q3,  q3,  q11
2054        vadd.i32        q8,  q8,  q12
2055        vadd.i32        q9,  q9,  q13
2056        vrshrn.i32      d4,  q2,  #6  // (diff + sign + 32) >> 6 = apply_sign()
2057        vrshrn.i32      d5,  q3,  #6
2058        vrshrn.i32      d6,  q8,  #6
2059        vrshrn.i32      d7,  q9,  #6
2060        vadd.i16        q2,  q2,  q0  // dc + apply_sign()
2061        vadd.i16        q3,  q3,  q0
2062        vmax.s16        q2,  q2,  q14
2063        vmax.s16        q3,  q3,  q14
2064        vmin.s16        q2,  q2,  q15
2065        vmin.s16        q3,  q3,  q15
2066        vst1.16         {q2}, [r0, :128], r1
2067        vst1.16         {q3}, [r6, :128], r1
2068        bgt             L(ipred_cfl_splat_w8)
2069        pop             {r4-r8, pc}
2070L(ipred_cfl_splat_w16):
2071        vpush           {q4-q7}
2072        add             r12, r5,  r3, lsl #1
2073        sub             r1,  r1,  r3, lsl #1
2074        mov             lr,  r3
20751:
2076        vld1.16         {q6, q7}, [r5, :128]!
2077        vmull.s16       q2,  d12, d2  // diff = ac * alpha
2078        vld1.16         {q8, q9}, [r12, :128]!
2079        vmull.s16       q3,  d13, d3
2080        vmull.s16       q4,  d14, d2
2081        vmull.s16       q5,  d15, d3
2082        vmull.s16       q6,  d16, d2
2083        vmull.s16       q7,  d17, d3
2084        vmull.s16       q8,  d18, d2
2085        vmull.s16       q9,  d19, d3
2086        vshr.s32        q10, q2,  #31 // sign = diff >> 15
2087        vshr.s32        q11, q3,  #31
2088        vshr.s32        q12, q4,  #31
2089        vshr.s32        q13, q5,  #31
2090        vadd.i32        q2,  q2,  q10 // diff + sign
2091        vshr.s32        q10, q6,  #31
2092        vadd.i32        q3,  q3,  q11
2093        vshr.s32        q11, q7,  #31
2094        vadd.i32        q4,  q4,  q12
2095        vshr.s32        q12, q8,  #31
2096        vadd.i32        q5,  q5,  q13
2097        vshr.s32        q13, q9,  #31
2098        vadd.i32        q6,  q6,  q10
2099        vadd.i32        q7,  q7,  q11
2100        vadd.i32        q8,  q8,  q12
2101        vadd.i32        q9,  q9,  q13
2102        vrshrn.i32      d4,  q2,  #6  // (diff + sign + 32) >> 6 = apply_sign()
2103        vrshrn.i32      d5,  q3,  #6
2104        vrshrn.i32      d6,  q4,  #6
2105        vrshrn.i32      d7,  q5,  #6
2106        vadd.i16        q2,  q2,  q0  // dc + apply_sign()
2107        vrshrn.i32      d8,  q6,  #6
2108        vrshrn.i32      d9,  q7,  #6
2109        vadd.i16        q3,  q3,  q0
2110        vrshrn.i32      d10, q8,  #6
2111        vrshrn.i32      d11, q9,  #6
2112        vadd.i16        q4,  q4,  q0
2113        vadd.i16        q5,  q5,  q0
2114        vmax.s16        q2,  q2,  q14
2115        vmax.s16        q3,  q3,  q14
2116        vmax.s16        q4,  q4,  q14
2117        vmax.s16        q5,  q5,  q14
2118        vmin.s16        q2,  q2,  q15
2119        vmin.s16        q3,  q3,  q15
2120        vmin.s16        q4,  q4,  q15
2121        vmin.s16        q5,  q5,  q15
2122        subs            r3,  r3,  #16
2123        vst1.16         {q2, q3}, [r0, :128]!
2124        vst1.16         {q4, q5}, [r6, :128]!
2125        bgt             1b
2126        subs            r4,  r4,  #2
2127        add             r5,  r5,  lr, lsl #1
2128        add             r12, r12, lr, lsl #1
2129        add             r0,  r0,  r1
2130        add             r6,  r6,  r1
2131        mov             r3,  lr
2132        bgt             1b
2133        vpop            {q4-q7}
2134        pop             {r4-r8, pc}
2135endfunc
2136
2137// void ipred_cfl_top_16bpc_neon(pixel *dst, const ptrdiff_t stride,
2138//                               const pixel *const topleft,
2139//                               const int width, const int height,
2140//                               const int16_t *ac, const int alpha,
2141//                               const int bitdepth_max);
2142function ipred_cfl_top_16bpc_neon, export=1
2143        push            {r4-r8, lr}
2144        ldrd            r4,  r5,  [sp, #24]
2145        ldrd            r6,  r7,  [sp, #32]
2146        clz             lr,  r3
2147        vdup.16         q15, r7       // bitdepth_max
2148        adr             r12, L(ipred_cfl_top_tbl)
2149        sub             lr,  lr,  #26
2150        ldr             lr,  [r12, lr, lsl #2]
2151        vdup.16         q1,  r6   // alpha
2152        add             r2,  r2,  #2
2153        add             r12, r12, lr
2154        add             r6,  r0,  r1
2155        lsl             r1,  r1,  #1
2156        vmov.i16        q14, #0
2157        bx              r12
2158
2159        .align 2
2160L(ipred_cfl_top_tbl):
2161        .word 32f - L(ipred_cfl_top_tbl) + CONFIG_THUMB
2162        .word 16f - L(ipred_cfl_top_tbl) + CONFIG_THUMB
2163        .word 8f  - L(ipred_cfl_top_tbl) + CONFIG_THUMB
2164        .word 4f  - L(ipred_cfl_top_tbl) + CONFIG_THUMB
2165
21664:
2167        vld1.16         {d0}, [r2]
2168        vpadd.i16       d0,  d0,  d0
2169        vpadd.i16       d0,  d0,  d0
2170        vrshr.u16       d0,  d0,  #2
2171        vdup.16         q0,  d0[0]
2172        b               L(ipred_cfl_splat_w4)
21738:
2174        vld1.16         {q0}, [r2]
2175        vadd.i16        d0,  d0,  d1
2176        vpadd.i16       d0,  d0,  d0
2177        vpadd.i16       d0,  d0,  d0
2178        vrshr.u16       d0,  d0,  #3
2179        vdup.16         q0,  d0[0]
2180        b               L(ipred_cfl_splat_w8)
218116:
2182        vld1.16         {q2, q3}, [r2]
2183        vadd.i16        q0,  q2,  q3
2184        vadd.i16        d0,  d0,  d1
2185        vpadd.i16       d0,  d0,  d0
2186        vpadd.i16       d0,  d0,  d0
2187        vrshr.u16       d0,  d0,  #4
2188        vdup.16         q0,  d0[0]
2189        b               L(ipred_cfl_splat_w16)
219032:
2191        vld1.16         {q8,  q9},  [r2]!
2192        vld1.16         {q10, q11}, [r2]
2193        vadd.i16        q8,  q8,  q9
2194        vadd.i16        q10, q10, q11
2195        vadd.i16        q0,  q8,  q10
2196        vadd.i16        d0,  d0,  d1
2197        vpadd.i16       d0,  d0,  d0
2198        vpaddl.u16      d0,  d0
2199        vrshrn.i32      d0,  q0,  #5
2200        vdup.16         q0,  d0[0]
2201        b               L(ipred_cfl_splat_w16)
2202endfunc
2203
2204// void ipred_cfl_left_16bpc_neon(pixel *dst, const ptrdiff_t stride,
2205//                                const pixel *const topleft,
2206//                                const int width, const int height,
2207//                                const int16_t *ac, const int alpha,
2208//                                const int bitdepth_max);
2209function ipred_cfl_left_16bpc_neon, export=1
2210        push            {r4-r8, lr}
2211        ldrd            r4,  r5,  [sp, #24]
2212        ldrd            r6,  r7,  [sp, #32]
2213        sub             r2,  r2,  r4, lsl #1
2214        clz             lr,  r3
2215        clz             r8,  r4
2216        vdup.16         q15, r7       // bitdepth_max
2217        adr             r12, L(ipred_cfl_splat_tbl)
2218        adr             r7,  L(ipred_cfl_left_tbl)
2219        sub             lr,  lr,  #26
2220        sub             r8,  r8,  #26
2221        ldr             lr,  [r12, lr, lsl #2]
2222        ldr             r8,  [r7,  r8, lsl #2]
2223        vdup.16         q1,  r6   // alpha
2224        add             r12, r12, lr
2225        add             r7,  r7,  r8
2226        add             r6,  r0,  r1
2227        lsl             r1,  r1,  #1
2228        vmov.i16        q14, #0
2229        bx              r7
2230
2231        .align 2
2232L(ipred_cfl_left_tbl):
2233        .word L(ipred_cfl_left_h32) - L(ipred_cfl_left_tbl) + CONFIG_THUMB
2234        .word L(ipred_cfl_left_h16) - L(ipred_cfl_left_tbl) + CONFIG_THUMB
2235        .word L(ipred_cfl_left_h8)  - L(ipred_cfl_left_tbl) + CONFIG_THUMB
2236        .word L(ipred_cfl_left_h4)  - L(ipred_cfl_left_tbl) + CONFIG_THUMB
2237
2238L(ipred_cfl_left_h4):
2239        vld1.16         {d0}, [r2, :64]
2240        vpadd.i16       d0,  d0,  d0
2241        vpadd.i16       d0,  d0,  d0
2242        vrshr.u16       d0,  d0,  #2
2243        vdup.16         q0,  d0[0]
2244        bx              r12
2245
2246L(ipred_cfl_left_h8):
2247        vld1.16         {q0}, [r2, :128]
2248        vadd.i16        d0,  d0,  d1
2249        vpadd.i16       d0,  d0,  d0
2250        vpadd.i16       d0,  d0,  d0
2251        vrshr.u16       d0,  d0,  #3
2252        vdup.16         q0,  d0[0]
2253        bx              r12
2254
2255L(ipred_cfl_left_h16):
2256        vld1.16         {q2, q3}, [r2, :128]
2257        vadd.i16        q0,  q2,  q3
2258        vadd.i16        d0,  d0,  d1
2259        vpadd.i16       d0,  d0,  d0
2260        vpadd.i16       d0,  d0,  d0
2261        vrshr.u16       d0,  d0,  #4
2262        vdup.16         q0,  d0[0]
2263        bx              r12
2264
2265L(ipred_cfl_left_h32):
2266        vld1.16         {q8,  q9},  [r2, :128]!
2267        vld1.16         {q10, q11}, [r2, :128]
2268        vadd.i16        q8,  q8,  q9
2269        vadd.i16        q10, q10, q11
2270        vadd.i16        q0,  q8,  q10
2271        vadd.i16        d0,  d0,  d1
2272        vpadd.i16       d0,  d0,  d0
2273        vpaddl.u16      d0,  d0
2274        vrshrn.i32      d0,  q0,  #5
2275        vdup.16         q0,  d0[0]
2276        bx              r12
2277endfunc
2278
2279// void ipred_cfl_16bpc_neon(pixel *dst, const ptrdiff_t stride,
2280//                           const pixel *const topleft,
2281//                           const int width, const int height,
2282//                           const int16_t *ac, const int alpha,
2283//                           const int bitdepth_max);
2284function ipred_cfl_16bpc_neon, export=1
2285        push            {r4-r8, lr}
2286        ldrd            r4,  r5,  [sp, #24]
2287        ldrd            r6,  r7,  [sp, #32]
2288        sub             r2,  r2,  r4, lsl #1
2289        add             r8,  r3,  r4  // width + height
2290        vdup.16         q1,  r6       // alpha
2291        clz             lr,  r3
2292        clz             r6,  r4
2293        vdup.32         d16, r8       // width + height
2294        vdup.16         q15, r7       // bitdepth_max
2295        adr             r7,  L(ipred_cfl_tbl)
2296        rbit            r8,  r8       // rbit(width + height)
2297        sub             lr,  lr,  #22 // 26 leading bits, minus table offset 4
2298        sub             r6,  r6,  #26
2299        clz             r8,  r8       // ctz(width + height)
2300        ldr             lr,  [r7, lr, lsl #2]
2301        ldr             r6,  [r7, r6, lsl #2]
2302        neg             r8,  r8       // -ctz(width + height)
2303        add             r12, r7,  lr
2304        add             r7,  r7,  r6
2305        vshr.u32        d16, d16, #1  // (width + height) >> 1
2306        vdup.32         d17, r8       // -ctz(width + height)
2307        add             r6,  r0,  r1
2308        lsl             r1,  r1,  #1
2309        vmov.i16        q14, #0
2310        bx              r7
2311
2312        .align 2
2313L(ipred_cfl_tbl):
2314        .word L(ipred_cfl_h32) - L(ipred_cfl_tbl) + CONFIG_THUMB
2315        .word L(ipred_cfl_h16) - L(ipred_cfl_tbl) + CONFIG_THUMB
2316        .word L(ipred_cfl_h8)  - L(ipred_cfl_tbl) + CONFIG_THUMB
2317        .word L(ipred_cfl_h4)  - L(ipred_cfl_tbl) + CONFIG_THUMB
2318        .word L(ipred_cfl_w32) - L(ipred_cfl_tbl) + CONFIG_THUMB
2319        .word L(ipred_cfl_w16) - L(ipred_cfl_tbl) + CONFIG_THUMB
2320        .word L(ipred_cfl_w8)  - L(ipred_cfl_tbl) + CONFIG_THUMB
2321        .word L(ipred_cfl_w4)  - L(ipred_cfl_tbl) + CONFIG_THUMB
2322
2323L(ipred_cfl_h4):
2324        vld1.16         {d0}, [r2, :64]!
2325        vpadd.i16       d0,  d0,  d0
2326        add             r2,  r2,  #2
2327        vpaddl.u16      d0,  d0
2328        bx              r12
2329L(ipred_cfl_w4):
2330        vld1.16         {d1}, [r2]
2331        vadd.i32        d0,  d0,  d16
2332        vpadd.i16       d1,  d1,  d1
2333        vpaddl.u16      d1,  d1
2334        cmp             r4,  #4
2335        vadd.i32        d0,  d0,  d1
2336        vshl.u32        d0,  d0,  d17
2337        beq             1f
2338        // h = 8/16
2339        cmp             r4,  #16
2340        movw            lr,  #0x6667
2341        movw            r8,  #0xAAAB
2342        it              ne
2343        movne           lr,  r8
2344        vdup.32         d18, lr
2345        vmul.i32        d0,  d0,  d18
2346        vshr.u32        d0,  d0,  #17
23471:
2348        vdup.16         q0,  d0[0]
2349        b               L(ipred_cfl_splat_w4)
2350
2351L(ipred_cfl_h8):
2352        vld1.16         {q0}, [r2, :128]!
2353        vadd.i16        d0,  d0,  d1
2354        vpadd.i16       d0,  d0,  d0
2355        add             r2,  r2,  #2
2356        vpaddl.u16      d0,  d0
2357        bx              r12
2358L(ipred_cfl_w8):
2359        vld1.16         {q2}, [r2]
2360        vadd.i32        d0,  d0,  d16
2361        vadd.i16        d1,  d4,  d5
2362        vpadd.i16       d1,  d1,  d1
2363        vpaddl.u16      d1,  d1
2364        cmp             r4,  #8
2365        vadd.i32        d0,  d0,  d1
2366        vshl.u32        d0,  d0,  d17
2367        beq             1f
2368        // h = 4/16/32
2369        cmp             r4,  #32
2370        movw            lr,  #0x6667
2371        movw            r8,  #0xAAAB
2372        it              ne
2373        movne           lr,  r8
2374        vdup.32         d18, lr
2375        vmul.i32        d0,  d0,  d18
2376        vshr.u32        d0,  d0,  #17
23771:
2378        vdup.16         q0,  d0[0]
2379        b               L(ipred_cfl_splat_w8)
2380
2381L(ipred_cfl_h16):
2382        vld1.16         {q2, q3}, [r2, :128]!
2383        vadd.i16        q0,  q2,  q3
2384        vadd.i16        d0,  d0,  d1
2385        vpadd.i16       d0,  d0,  d0
2386        add             r2,  r2,  #2
2387        vpaddl.u16      d0,  d0
2388        bx              r12
2389L(ipred_cfl_w16):
2390        vld1.16         {q2, q3}, [r2]
2391        vadd.i32        d0,  d0,  d16
2392        vadd.i16        q2,  q2,  q3
2393        vadd.i16        d1,  d4,  d5
2394        vpadd.i16       d1,  d1,  d1
2395        vpaddl.u16      d1,  d1
2396        cmp             r4,  #16
2397        vadd.i32        d0,  d0,  d1
2398        vshl.u32        d0,  d0,  d17
2399        beq             1f
2400        // h = 4/8/32/64
2401        tst             r4,  #(32+16+8)  // 16 added to make a consecutive bitmask
2402        movw            lr,  #0x6667
2403        movw            r8,  #0xAAAB
2404        it              ne
2405        movne           lr,  r8
2406        vdup.32         d18, lr
2407        vmul.i32        d0,  d0,  d18
2408        vshr.u32        d0,  d0,  #17
24091:
2410        vdup.16         q0,  d0[0]
2411        b               L(ipred_cfl_splat_w16)
2412
2413L(ipred_cfl_h32):
2414        vld1.16         {q2, q3},   [r2, :128]!
2415        vld1.16         {q10, q11}, [r2, :128]!
2416        vadd.i16        q2,  q2,  q3
2417        vadd.i16        q10, q10, q11
2418        vadd.i16        q0,  q2,  q10
2419        vadd.i16        d0,  d0,  d1
2420        vpadd.i16       d0,  d0,  d0
2421        add             r2,  r2,  #2
2422        vpaddl.u16      d0,  d0
2423        bx              r12
2424L(ipred_cfl_w32):
2425        vld1.16         {q2, q3},   [r2]!
2426        vadd.i32        d0,  d0,  d16
2427        vld1.16         {q10, q11}, [r2]!
2428        vadd.i16        q2,  q2,  q3
2429        vadd.i16        q10, q10, q11
2430        vadd.i16        q2,  q2,  q10
2431        vadd.i16        d1,  d4,  d5
2432        vpadd.i16       d1,  d1,  d1
2433        vpaddl.u16      d1,  d1
2434        cmp             r4,  #32
2435        vadd.i32        d0,  d0,  d1
2436        vshl.u32        d0,  d0,  d17
2437        beq             1f
2438        // h = 8/16/64
2439        cmp             r4,  #8
2440        movw            lr,  #0x6667
2441        movw            r8,  #0xAAAB
2442        it              ne
2443        movne           lr,  r8
2444        vdup.32         d18, lr
2445        vmul.i32        d0,  d0,  d18
2446        vshr.u32        d0,  d0,  #17
24471:
2448        vdup.16         q0,  d0[0]
2449        b               L(ipred_cfl_splat_w16)
2450endfunc
2451
2452// void cfl_ac_420_16bpc_neon(int16_t *const ac, const pixel *const ypx,
2453//                            const ptrdiff_t stride, const int w_pad,
2454//                            const int h_pad, const int cw, const int ch);
2455function ipred_cfl_ac_420_16bpc_neon, export=1
2456        push            {r4-r8,lr}
2457        ldrd            r4,  r5,  [sp, #24]
2458        ldr             r6,  [sp, #32]
2459        clz             r8,  r5
2460        lsl             r4,  r4,  #2
2461        adr             r7,  L(ipred_cfl_ac_420_tbl)
2462        sub             r8,  r8,  #27
2463        ldr             r8,  [r7, r8, lsl #2]
2464        vmov.i32        q8,  #0
2465        vmov.i32        q9,  #0
2466        vmov.i32        q10, #0
2467        vmov.i32        q11, #0
2468        add             r7,  r7,  r8
2469        sub             r8,  r6,  r4  // height - h_pad
2470        rbit            lr,  r5       // rbit(width)
2471        rbit            r12, r6       // rbit(height)
2472        clz             lr,  lr       // ctz(width)
2473        clz             r12, r12      // ctz(height)
2474        add             lr,  lr,  r12 // log2sz
2475        add             r12, r1,  r2
2476        vdup.32         d31, lr
2477        lsl             r2,  r2,  #1
2478        vneg.s32        d31, d31      // -log2sz
2479        bx              r7
2480
2481        .align 2
2482L(ipred_cfl_ac_420_tbl):
2483        .word L(ipred_cfl_ac_420_w16) - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB
2484        .word L(ipred_cfl_ac_420_w8)  - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB
2485        .word L(ipred_cfl_ac_420_w4)  - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB
2486
2487L(ipred_cfl_ac_420_w4):
24881:      // Copy and subsample input
2489        vld1.16         {q0}, [r1,  :128], r2
2490        vld1.16         {q1}, [r12, :128], r2
2491        vld1.16         {q2}, [r1,  :128], r2
2492        vld1.16         {q3}, [r12, :128], r2
2493        vadd.i16        q0,  q0,  q1
2494        vadd.i16        q2,  q2,  q3
2495        vpadd.i16       d0,  d0,  d1
2496        vpadd.i16       d1,  d4,  d5
2497        vshl.i16        q0,  q0,  #1
2498        subs            r8,  r8,  #2
2499        vst1.16         {q0}, [r0, :128]!
2500        vaddw.u16       q8,  q8,  d0
2501        vaddw.u16       q9,  q9,  d1
2502        bgt             1b
2503        cmp             r4,  #0
2504        vmov            d0,  d1
2505        vmov            d2,  d1
2506        vmov            d3,  d1
2507L(ipred_cfl_ac_420_w4_hpad):
2508        beq             3f // This assumes that all callers already did "cmp r4, #0"
25092:      // Vertical padding (h_pad > 0)
2510        subs            r4,  r4,  #4
2511        vst1.16         {q0, q1}, [r0, :128]!
2512        vaddw.u16       q8,  q8,  d0
2513        vaddw.u16       q9,  q9,  d1
2514        vaddw.u16       q10, q10, d2
2515        vaddw.u16       q11, q11, d3
2516        bgt             2b
25173:
2518L(ipred_cfl_ac_420_w4_calc_subtract_dc):
2519        // Aggregate the sums
2520        vadd.i32        q8,  q8,  q9
2521        vadd.i32        q10, q10, q11
2522        vadd.i32        q0,  q8,  q10
2523        vadd.i32        d0,  d0,  d1
2524        vpadd.i32       d0,  d0,  d0  // sum
2525        sub             r0,  r0,  r6, lsl #3
2526        vrshl.u32       d16, d0,  d31 // (sum + (1 << (log2sz - 1))) >>= log2sz
2527        vdup.16         q8,  d16[0]
25286:      // Subtract dc from ac
2529        vld1.16         {q0, q1}, [r0, :128]
2530        subs            r6,  r6,  #4
2531        vsub.i16        q0,  q0,  q8
2532        vsub.i16        q1,  q1,  q8
2533        vst1.16         {q0, q1}, [r0, :128]!
2534        bgt             6b
2535        pop             {r4-r8, pc}
2536
2537L(ipred_cfl_ac_420_w8):
2538        cmp             r3,  #0
2539        bne             L(ipred_cfl_ac_420_w8_wpad)
25401:      // Copy and subsample input, without padding
2541        vld1.16         {q0,  q1},  [r1,  :128], r2
2542        vld1.16         {q2,  q3},  [r12, :128], r2
2543        vld1.16         {q12, q13}, [r1,  :128], r2
2544        vadd.i16        q0,  q0,  q2
2545        vadd.i16        q1,  q1,  q3
2546        vld1.16         {q2,  q3},  [r12, :128], r2
2547        vpadd.i16       d0,  d0,  d1
2548        vpadd.i16       d1,  d2,  d3
2549        vadd.i16        q12, q12, q2
2550        vadd.i16        q13, q13, q3
2551        vpadd.i16       d2,  d24, d25
2552        vpadd.i16       d3,  d26, d27
2553        vshl.i16        q0,  q0,  #1
2554        vshl.i16        q1,  q1,  #1
2555        subs            r8,  r8,  #2
2556        vst1.16         {q0, q1}, [r0, :128]!
2557        vaddw.u16       q8,  q8,  d0
2558        vaddw.u16       q9,  q9,  d1
2559        vaddw.u16       q10, q10, d2
2560        vaddw.u16       q11, q11, d3
2561        bgt             1b
2562        cmp             r4,  #0
2563        vmov            q0,  q1
2564        b               L(ipred_cfl_ac_420_w8_hpad)
2565
2566L(ipred_cfl_ac_420_w8_wpad):
25671:      // Copy and subsample input, padding 4
2568        vld1.16         {q0}, [r1,  :128], r2
2569        vld1.16         {q1}, [r12, :128], r2
2570        vld1.16         {q2}, [r1,  :128], r2
2571        vld1.16         {q3}, [r12, :128], r2
2572        vadd.i16        q0,  q0,  q1
2573        vadd.i16        q2,  q2,  q3
2574        vpadd.i16       d0,  d0,  d1
2575        vpadd.i16       d1,  d4,  d5
2576        vshl.i16        q0,  q0,  #1
2577        vdup.16         d3,  d1[3]
2578        vmov            d2,  d1
2579        vdup.16         d1,  d0[3]
2580        subs            r8,  r8,  #2
2581        vst1.16         {q0, q1}, [r0, :128]!
2582        vaddw.u16       q8,  q8,  d0
2583        vaddw.u16       q9,  q9,  d1
2584        vaddw.u16       q10, q10, d2
2585        vaddw.u16       q11, q11, d3
2586        bgt             1b
2587        cmp             r4,  #0
2588        vmov            q0,  q1
2589
2590L(ipred_cfl_ac_420_w8_hpad):
2591        beq             3f // This assumes that all callers already did "cmp r4, #0"
25922:      // Vertical padding (h_pad > 0)
2593        subs            r4,  r4,  #4
2594        vst1.16         {q0, q1}, [r0, :128]!
2595        vaddw.u16       q8,  q8,  d0
2596        vaddw.u16       q9,  q9,  d1
2597        vaddw.u16       q10, q10, d2
2598        vaddw.u16       q11, q11, d3
2599        vst1.16         {q0, q1}, [r0, :128]!
2600        vaddw.u16       q8,  q8,  d0
2601        vaddw.u16       q9,  q9,  d1
2602        vaddw.u16       q10, q10, d2
2603        vaddw.u16       q11, q11, d3
2604        bgt             2b
26053:
2606
2607        // Double the height and reuse the w4 summing/subtracting
2608        lsl             r6,  r6,  #1
2609        b               L(ipred_cfl_ac_420_w4_calc_subtract_dc)
2610
2611L(ipred_cfl_ac_420_w16):
2612        adr             r7,  L(ipred_cfl_ac_420_w16_tbl)
2613        ldr             r3,  [r7, r3, lsl #2]
2614        add             r7,  r7,  r3
2615        bx              r7
2616
2617        .align 2
2618L(ipred_cfl_ac_420_w16_tbl):
2619        .word L(ipred_cfl_ac_420_w16_wpad0) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
2620        .word L(ipred_cfl_ac_420_w16_wpad1) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
2621        .word L(ipred_cfl_ac_420_w16_wpad2) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
2622        .word L(ipred_cfl_ac_420_w16_wpad3) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
2623
2624L(ipred_cfl_ac_420_w16_wpad0):
2625        sub             r2,  r2,  #32
26261:      // Copy and subsample input, without padding
2627        vld1.16         {q0,  q1},  [r1,  :128]!
2628        vld1.16         {q12, q13}, [r12, :128]!
2629        vld1.16         {q2,  q3},  [r1,  :128], r2
2630        vadd.i16        q0,  q0,  q12
2631        vadd.i16        q1,  q1,  q13
2632        vld1.16         {q12, q13}, [r12, :128], r2
2633        vpadd.i16       d0,  d0,  d1
2634        vpadd.i16       d1,  d2,  d3
2635        vadd.i16        q2,  q2,  q12
2636        vadd.i16        q3,  q3,  q13
2637        vpadd.i16       d2,  d4,  d5
2638        vpadd.i16       d3,  d6,  d7
2639        vshl.i16        q0,  q0,  #1
2640        vshl.i16        q1,  q1,  #1
2641        subs            r8,  r8,  #1
2642        vst1.16         {q0, q1}, [r0, :128]!
2643        vaddw.u16       q8,  q8,  d0
2644        vaddw.u16       q9,  q9,  d1
2645        vaddw.u16       q10, q10, d2
2646        vaddw.u16       q11, q11, d3
2647        bgt             1b
2648        cmp             r4,  #0
2649        b               L(ipred_cfl_ac_420_w16_hpad)
2650
2651L(ipred_cfl_ac_420_w16_wpad1):
2652        sub             r2,  r2,  #32
26531:      // Copy and subsample input, padding 4
2654        vld1.16         {q0,  q1},  [r1,  :128]!
2655        vld1.16         {q12, q13}, [r12, :128]!
2656        vld1.16         {q2},       [r1,  :128], r2
2657        vadd.i16        q0,  q0,  q12
2658        vadd.i16        q1,  q1,  q13
2659        vld1.16         {q12},     [r12, :128], r2
2660        vpadd.i16       d0,  d0,  d1
2661        vadd.i16        q2,  q2,  q12
2662        vpadd.i16       d1,  d2,  d3
2663        vpadd.i16       d2,  d4,  d5
2664        vshl.i16        q0,  q0,  #1
2665        vshl.i16        d2,  d2,  #1
2666        subs            r8,  r8,  #1
2667        vdup.16         d3,  d2[3]
2668        vst1.16         {q0, q1}, [r0, :128]!
2669        vaddw.u16       q8,  q8,  d0
2670        vaddw.u16       q9,  q9,  d1
2671        vaddw.u16       q10, q10, d2
2672        vaddw.u16       q11, q11, d3
2673        bgt             1b
2674        cmp             r4,  #0
2675        b               L(ipred_cfl_ac_420_w16_hpad)
2676
2677L(ipred_cfl_ac_420_w16_wpad2):
26781:      // Copy and subsample input, padding 8
2679        vld1.16         {q0,  q1},  [r1,  :128], r2
2680        vld1.16         {q12, q13}, [r12, :128], r2
2681        vadd.i16        q0,  q0,  q12
2682        vadd.i16        q1,  q1,  q13
2683        vpadd.i16       d0,  d0,  d1
2684        vpadd.i16       d1,  d2,  d3
2685        vshl.i16        q0,  q0,  #1
2686        subs            r8,  r8,  #1
2687        vdup.16         q1,  d1[3]
2688        vst1.16         {q0, q1}, [r0, :128]!
2689        vaddw.u16       q8,  q8,  d0
2690        vaddw.u16       q9,  q9,  d1
2691        vaddw.u16       q10, q10, d2
2692        vaddw.u16       q11, q11, d3
2693        bgt             1b
2694        cmp             r4,  #0
2695        b               L(ipred_cfl_ac_420_w16_hpad)
2696
2697L(ipred_cfl_ac_420_w16_wpad3):
26981:      // Copy and subsample input, padding 12
2699        vld1.16         {q0},  [r1,  :128], r2
2700        vld1.16         {q12}, [r12, :128], r2
2701        vadd.i16        q0,  q0,  q12
2702        vpadd.i16       d0,  d0,  d1
2703        vshl.i16        d0,  d0,  #1
2704        subs            r8,  r8,  #1
2705        vdup.16         q1,  d0[3]
2706        vdup.16         d1,  d0[3]
2707        vst1.16         {q0, q1}, [r0, :128]!
2708        vaddw.u16       q8,  q8,  d0
2709        vaddw.u16       q9,  q9,  d1
2710        vaddw.u16       q10, q10, d2
2711        vaddw.u16       q11, q11, d3
2712        bgt             1b
2713        cmp             r4,  #0
2714        b               L(ipred_cfl_ac_420_w16_hpad)
2715
2716L(ipred_cfl_ac_420_w16_hpad):
2717        beq             3f // This assumes that all callers already did "cmp r4, #0"
27182:      // Vertical padding (h_pad > 0)
2719        subs            r4,  r4,  #2
2720        vst1.16         {q0, q1}, [r0, :128]!
2721        vaddw.u16       q8,  q8,  d0
2722        vaddw.u16       q9,  q9,  d1
2723        vaddw.u16       q10, q10, d2
2724        vaddw.u16       q11, q11, d3
2725        vst1.16         {q0, q1}, [r0, :128]!
2726        vaddw.u16       q8,  q8,  d0
2727        vaddw.u16       q9,  q9,  d1
2728        vaddw.u16       q10, q10, d2
2729        vaddw.u16       q11, q11, d3
2730        bgt             2b
27313:
2732
2733        // Quadruple the height and reuse the w4 summing/subtracting
2734        lsl             r6,  r6,  #2
2735        b               L(ipred_cfl_ac_420_w4_calc_subtract_dc)
2736endfunc
2737
2738// void cfl_ac_422_16bpc_neon(int16_t *const ac, const pixel *const ypx,
2739//                            const ptrdiff_t stride, const int w_pad,
2740//                            const int h_pad, const int cw, const int ch);
2741function ipred_cfl_ac_422_16bpc_neon, export=1
2742        push            {r4-r8,lr}
2743        ldrd            r4,  r5,  [sp, #24]
2744        ldr             r6,  [sp, #32]
2745        clz             r8,  r5
2746        lsl             r4,  r4,  #2
2747        adr             r7,  L(ipred_cfl_ac_422_tbl)
2748        sub             r8,  r8,  #27
2749        ldr             r8,  [r7, r8, lsl #2]
2750        vmov.i16        q8,  #0
2751        vmov.i16        q9,  #0
2752        vmov.i16        q10, #0
2753        vmov.i16        q11, #0
2754        add             r7,  r7,  r8
2755        sub             r8,  r6,  r4  // height - h_pad
2756        rbit            lr,  r5       // rbit(width)
2757        rbit            r12, r6       // rbit(height)
2758        clz             lr,  lr       // ctz(width)
2759        clz             r12, r12      // ctz(height)
2760        add             lr,  lr,  r12 // log2sz
2761        add             r12, r1,  r2
2762        vdup.32         d31, lr
2763        lsl             r2,  r2,  #1
2764        vneg.s32        d31, d31      // -log2sz
2765        bx              r7
2766
2767        .align 2
2768L(ipred_cfl_ac_422_tbl):
2769        .word L(ipred_cfl_ac_422_w16) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB
2770        .word L(ipred_cfl_ac_422_w8) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB
2771        .word L(ipred_cfl_ac_422_w4) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB
2772
2773L(ipred_cfl_ac_422_w4):
27741:      // Copy and subsample input
2775        vld1.16         {q0}, [r1,  :128], r2
2776        vld1.16         {q1}, [r12, :128], r2
2777        vld1.16         {q2}, [r1,  :128], r2
2778        vld1.16         {q3}, [r12, :128], r2
2779        vpadd.i16       d0,  d0,  d1
2780        vpadd.i16       d1,  d2,  d3
2781        vpadd.i16       d2,  d4,  d5
2782        vpadd.i16       d3,  d6,  d7
2783        vshl.i16        q0,  q0,  #2
2784        vshl.i16        q1,  q1,  #2
2785        subs            r8,  r8,  #4
2786        vst1.16         {q0, q1}, [r0, :128]!
2787        vaddw.u16       q8,  q8,  d0
2788        vaddw.u16       q9,  q9,  d1
2789        vaddw.u16       q10, q10, d2
2790        vaddw.u16       q11, q11, d3
2791        bgt             1b
2792        cmp             r4,  #0
2793        vmov            d0,  d3
2794        vmov            d1,  d3
2795        vmov            d2,  d3
2796        b               L(ipred_cfl_ac_420_w4_hpad)
2797
2798L(ipred_cfl_ac_422_w8):
2799        cmp             r3,  #0
2800        bne             L(ipred_cfl_ac_422_w8_wpad)
28011:      // Copy and subsample input, without padding
2802        vld1.16         {q0,  q1},  [r1,  :128], r2
2803        vld1.16         {q2,  q3},  [r12, :128], r2
2804        vld1.16         {q12, q13}, [r1,  :128], r2
2805        vpadd.i16       d0,  d0,  d1
2806        vpadd.i16       d1,  d2,  d3
2807        vpadd.i16       d2,  d4,  d5
2808        vpadd.i16       d3,  d6,  d7
2809        vld1.16         {q2, q3}, [r12, :128], r2
2810        vpadd.i16       d24, d24, d25
2811        vpadd.i16       d25, d26, d27
2812        vpadd.i16       d26, d4,  d5
2813        vpadd.i16       d27, d6,  d7
2814        vshl.i16        q0,  q0,  #2
2815        vshl.i16        q1,  q1,  #2
2816        vshl.i16        q2,  q12, #2
2817        vshl.i16        q3,  q13, #2
2818        subs            r8,  r8,  #4
2819        vst1.16         {q0, q1}, [r0, :128]!
2820        vaddw.u16       q8,  q8,  d0
2821        vaddw.u16       q9,  q9,  d1
2822        vaddw.u16       q10, q10, d2
2823        vaddw.u16       q11, q11, d3
2824        vst1.16         {q2, q3}, [r0, :128]!
2825        vaddw.u16       q8,  q8,  d4
2826        vaddw.u16       q9,  q9,  d5
2827        vaddw.u16       q10, q10, d6
2828        vaddw.u16       q11, q11, d7
2829        bgt             1b
2830        cmp             r4,  #0
2831        vmov            q0,  q3
2832        vmov            q1,  q3
2833        b               L(ipred_cfl_ac_420_w8_hpad)
2834
2835L(ipred_cfl_ac_422_w8_wpad):
28361:      // Copy and subsample input, padding 4
2837        vld1.16         {q0},  [r1,  :128], r2
2838        vld1.16         {q2},  [r12, :128], r2
2839        vld1.16         {q12}, [r1,  :128], r2
2840        vpadd.i16       d0,  d0,  d1
2841        vpadd.i16       d1,  d4,  d5
2842        vld1.16         {q2, q3}, [r12, :128], r2
2843        vpadd.i16       d24, d24, d25
2844        vpadd.i16       d25, d4,  d5
2845        vshl.i16        q0,  q0,  #2
2846        vshl.i16        q12, q12, #2
2847        vdup.16         d7,  d25[3]
2848        vmov            d6,  d25
2849        vdup.16         d5,  d24[3]
2850        vmov            d4,  d24
2851        vdup.16         d3,  d1[3]
2852        vmov            d2,  d1
2853        vdup.16         d1,  d0[3]
2854        subs            r8,  r8,  #4
2855        vst1.16         {q0, q1}, [r0, :128]!
2856        vaddw.u16       q8,  q8,  d0
2857        vaddw.u16       q9,  q9,  d1
2858        vaddw.u16       q10, q10, d2
2859        vaddw.u16       q11, q11, d3
2860        vst1.16         {q2, q3}, [r0, :128]!
2861        vaddw.u16       q8,  q8,  d4
2862        vaddw.u16       q9,  q9,  d5
2863        vaddw.u16       q10, q10, d6
2864        vaddw.u16       q11, q11, d7
2865        bgt             1b
2866        cmp             r4,  #0
2867        vmov            q0,  q3
2868        vmov            q1,  q3
2869        b               L(ipred_cfl_ac_420_w8_hpad)
2870
2871L(ipred_cfl_ac_422_w16):
2872        adr             r7,  L(ipred_cfl_ac_422_w16_tbl)
2873        ldr             r3,  [r7, r3, lsl #2]
2874        add             r7,  r7,  r3
2875        bx              r7
2876
2877        .align 2
2878L(ipred_cfl_ac_422_w16_tbl):
2879        .word L(ipred_cfl_ac_422_w16_wpad0) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
2880        .word L(ipred_cfl_ac_422_w16_wpad1) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
2881        .word L(ipred_cfl_ac_422_w16_wpad2) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
2882        .word L(ipred_cfl_ac_422_w16_wpad3) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
2883
2884L(ipred_cfl_ac_422_w16_wpad0):
2885        sub             r2,  r2,  #32
28861:      // Copy and subsample input, without padding
2887        vld1.16         {q0,  q1},  [r1,  :128]!
2888        vld1.16         {q2,  q3},  [r12, :128]!
2889        vld1.16         {q12, q13}, [r1,  :128], r2
2890        vpadd.i16       d0,  d0,  d1
2891        vpadd.i16       d1,  d2,  d3
2892        vpadd.i16       d2,  d24, d25
2893        vpadd.i16       d3,  d26, d27
2894        vld1.16         {q12, q13}, [r12, :128], r2
2895        vpadd.i16       d4,  d4,  d5
2896        vpadd.i16       d5,  d6,  d7
2897        vpadd.i16       d6,  d24, d25
2898        vpadd.i16       d7,  d26, d27
2899        vshl.i16        q0,  q0,  #2
2900        vshl.i16        q1,  q1,  #2
2901        vshl.i16        q2,  q2,  #2
2902        vshl.i16        q3,  q3,  #2
2903        subs            r8,  r8,  #2
2904        vst1.16         {q0, q1}, [r0, :128]!
2905        vaddw.u16       q8,  q8,  d0
2906        vaddw.u16       q9,  q9,  d1
2907        vaddw.u16       q10, q10, d2
2908        vaddw.u16       q11, q11, d3
2909        vst1.16         {q2, q3}, [r0, :128]!
2910        vaddw.u16       q8,  q8,  d4
2911        vaddw.u16       q9,  q9,  d5
2912        vaddw.u16       q10, q10, d6
2913        vaddw.u16       q11, q11, d7
2914        bgt             1b
2915        cmp             r4,  #0
2916        vmov            q0,  q2
2917        vmov            q1,  q3
2918        b               L(ipred_cfl_ac_420_w16_hpad)
2919
2920L(ipred_cfl_ac_422_w16_wpad1):
2921        sub             r2,  r2,  #32
29221:      // Copy and subsample input, padding 4
2923        vld1.16         {q0,  q1},  [r1,  :128]!
2924        vld1.16         {q2,  q3},  [r12, :128]!
2925        vld1.16         {q12},      [r1,  :128], r2
2926        vpadd.i16       d0,  d0,  d1
2927        vpadd.i16       d1,  d2,  d3
2928        vpadd.i16       d2,  d24, d25
2929        vld1.16         {q12},      [r12, :128], r2
2930        vpadd.i16       d4,  d4,  d5
2931        vpadd.i16       d5,  d6,  d7
2932        vpadd.i16       d6,  d24, d25
2933        vshl.i16        q0,  q0,  #2
2934        vshl.i16        d2,  d2,  #2
2935        vshl.i16        q2,  q2,  #2
2936        vshl.i16        d6,  d6,  #2
2937        vdup.16         d3,  d2[3]
2938        vdup.16         d7,  d6[3]
2939        subs            r8,  r8,  #2
2940        vst1.16         {q0, q1}, [r0, :128]!
2941        vaddw.u16       q8,  q8,  d0
2942        vaddw.u16       q9,  q9,  d1
2943        vaddw.u16       q10, q10, d2
2944        vaddw.u16       q11, q11, d3
2945        vst1.16         {q2, q3}, [r0, :128]!
2946        vaddw.u16       q8,  q8,  d4
2947        vaddw.u16       q9,  q9,  d5
2948        vaddw.u16       q10, q10, d6
2949        vaddw.u16       q11, q11, d7
2950        bgt             1b
2951        cmp             r4,  #0
2952        vmov            q0,  q2
2953        vmov            q1,  q3
2954        b               L(ipred_cfl_ac_420_w16_hpad)
2955
2956L(ipred_cfl_ac_422_w16_wpad2):
29571:      // Copy and subsample input, padding 8
2958        vld1.16         {q0,  q1},  [r1,  :128], r2
2959        vld1.16         {q2,  q3},  [r12, :128], r2
2960        vpadd.i16       d0,  d0,  d1
2961        vpadd.i16       d1,  d2,  d3
2962        vpadd.i16       d4,  d4,  d5
2963        vpadd.i16       d5,  d6,  d7
2964        vshl.i16        q0,  q0,  #2
2965        vshl.i16        q2,  q2,  #2
2966        vdup.16         q1,  d1[3]
2967        vdup.16         q3,  d5[3]
2968        subs            r8,  r8,  #2
2969        vst1.16         {q0, q1}, [r0, :128]!
2970        vaddw.u16       q8,  q8,  d0
2971        vaddw.u16       q9,  q9,  d1
2972        vaddw.u16       q10, q10, d2
2973        vaddw.u16       q11, q11, d3
2974        vst1.16         {q2, q3}, [r0, :128]!
2975        vaddw.u16       q8,  q8,  d4
2976        vaddw.u16       q9,  q9,  d5
2977        vaddw.u16       q10, q10, d6
2978        vaddw.u16       q11, q11, d7
2979        bgt             1b
2980        cmp             r4,  #0
2981        vmov            q0,  q2
2982        vmov            q1,  q3
2983        b               L(ipred_cfl_ac_420_w16_hpad)
2984
2985L(ipred_cfl_ac_422_w16_wpad3):
29861:      // Copy and subsample input, padding 12
2987        vld1.16         {q0}, [r1,  :128], r2
2988        vld1.16         {q2}, [r12, :128], r2
2989        vpadd.i16       d0,  d0,  d1
2990        vpadd.i16       d1,  d4,  d5
2991        vshl.i16        q0,  q0,  #2
2992        vdup.16         q3,  d1[3]
2993        vdup.16         q1,  d0[3]
2994        vdup.16         d5,  d1[3]
2995        vmov            d4,  d1
2996        vdup.16         d1,  d0[3]
2997        subs            r8,  r8,  #2
2998        vst1.16         {q0, q1}, [r0, :128]!
2999        vaddw.u16       q8,  q8,  d0
3000        vaddw.u16       q9,  q9,  d1
3001        vaddw.u16       q10, q10, d2
3002        vaddw.u16       q11, q11, d3
3003        vst1.16         {q2, q3}, [r0, :128]!
3004        vaddw.u16       q8,  q8,  d4
3005        vaddw.u16       q9,  q9,  d5
3006        vaddw.u16       q10, q10, d6
3007        vaddw.u16       q11, q11, d7
3008        bgt             1b
3009        cmp             r4,  #0
3010        vmov            q0,  q2
3011        vmov            q1,  q3
3012        b               L(ipred_cfl_ac_420_w16_hpad)
3013endfunc
3014
3015// void cfl_ac_444_16bpc_neon(int16_t *const ac, const pixel *const ypx,
3016//                            const ptrdiff_t stride, const int w_pad,
3017//                            const int h_pad, const int cw, const int ch);
3018function ipred_cfl_ac_444_16bpc_neon, export=1
3019        push            {r4-r8,lr}
3020        ldrd            r4,  r5,  [sp, #24]
3021        ldr             r6,  [sp, #32]
3022        clz             r8,  r5
3023        lsl             r4,  r4,  #2
3024        adr             r7,  L(ipred_cfl_ac_444_tbl)
3025        sub             r8,  r8,  #26
3026        ldr             r8,  [r7, r8, lsl #2]
3027        vmov.i16        q8,  #0
3028        vmov.i16        q9,  #0
3029        vmov.i16        q10, #0
3030        vmov.i16        q11, #0
3031        add             r7,  r7,  r8
3032        sub             r8,  r6,  r4  // height - h_pad
3033        rbit            lr,  r5       // rbit(width)
3034        rbit            r12, r6       // rbit(height)
3035        clz             lr,  lr       // ctz(width)
3036        clz             r12, r12      // ctz(height)
3037        add             lr,  lr,  r12 // log2sz
3038        add             r12, r1,  r2
3039        vdup.32         d31, lr
3040        lsl             r2,  r2,  #1
3041        vneg.s32        d31, d31      // -log2sz
3042        bx              r7
3043
3044        .align 2
3045L(ipred_cfl_ac_444_tbl):
3046        .word L(ipred_cfl_ac_444_w32) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
3047        .word L(ipred_cfl_ac_444_w16) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
3048        .word L(ipred_cfl_ac_444_w8)  - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
3049        .word L(ipred_cfl_ac_444_w4)  - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
3050
3051L(ipred_cfl_ac_444_w4):
30521:      // Copy and expand input
3053        vld1.16         {d0}, [r1,  :64], r2
3054        vld1.16         {d1}, [r12, :64], r2
3055        vld1.16         {d2}, [r1,  :64], r2
3056        vld1.16         {d3}, [r12, :64], r2
3057        vshl.i16        q0,  q0,  #3
3058        vshl.i16        q1,  q1,  #3
3059        subs            r8,  r8,  #4
3060        vst1.16         {q0, q1}, [r0, :128]!
3061        vaddw.u16       q8,  q8,  d0
3062        vaddw.u16       q9,  q9,  d1
3063        vaddw.u16       q10, q10, d2
3064        vaddw.u16       q11, q11, d3
3065        bgt             1b
3066        cmp             r4,  #0
3067        vmov            d0,  d3
3068        vmov            d1,  d3
3069        vmov            d2,  d3
3070        b               L(ipred_cfl_ac_420_w4_hpad)
3071
3072L(ipred_cfl_ac_444_w8):
30731:      // Copy and expand input
3074        vld1.16         {q0}, [r1,  :128], r2
3075        vld1.16         {q1}, [r12, :128], r2
3076        vld1.16         {q2}, [r1,  :128], r2
3077        vld1.16         {q3}, [r12, :128], r2
3078        vshl.i16        q0,  q0,  #3
3079        vshl.i16        q1,  q1,  #3
3080        vshl.i16        q2,  q2,  #3
3081        vshl.i16        q3,  q3,  #3
3082        subs            r8,  r8,  #4
3083        vst1.16         {q0, q1}, [r0, :128]!
3084        vaddw.u16       q8,  q8,  d0
3085        vaddw.u16       q9,  q9,  d1
3086        vaddw.u16       q10, q10, d2
3087        vaddw.u16       q11, q11, d3
3088        vst1.16         {q2, q3}, [r0, :128]!
3089        vaddw.u16       q8,  q8,  d4
3090        vaddw.u16       q9,  q9,  d5
3091        vaddw.u16       q10, q10, d6
3092        vaddw.u16       q11, q11, d7
3093        bgt             1b
3094        cmp             r4,  #0
3095        vmov            q0,  q3
3096        vmov            q1,  q3
3097        b               L(ipred_cfl_ac_420_w8_hpad)
3098
3099L(ipred_cfl_ac_444_w16):
3100        cmp             r3,  #0
3101        bne             L(ipred_cfl_ac_444_w16_wpad)
31021:      // Copy and expand input, without padding
3103        vld1.16         {q0, q1}, [r1,  :128], r2
3104        vld1.16         {q2, q3}, [r12, :128], r2
3105        vshl.i16        q0,  q0,  #3
3106        vshl.i16        q1,  q1,  #3
3107        vshl.i16        q2,  q2,  #3
3108        vshl.i16        q3,  q3,  #3
3109        subs            r8,  r8,  #2
3110        vst1.16         {q0, q1}, [r0, :128]!
3111        vaddw.u16       q8,  q8,  d0
3112        vaddw.u16       q9,  q9,  d1
3113        vaddw.u16       q10, q10, d2
3114        vaddw.u16       q11, q11, d3
3115        vst1.16         {q2, q3}, [r0, :128]!
3116        vaddw.u16       q8,  q8,  d4
3117        vaddw.u16       q9,  q9,  d5
3118        vaddw.u16       q10, q10, d6
3119        vaddw.u16       q11, q11, d7
3120        bgt             1b
3121        cmp             r4,  #0
3122        vmov            q0,  q2
3123        vmov            q1,  q3
3124        b               L(ipred_cfl_ac_420_w16_hpad)
3125
3126L(ipred_cfl_ac_444_w16_wpad):
31271:      // Copy and expand input, padding 8
3128        vld1.16         {q0}, [r1,  :128], r2
3129        vld1.16         {q2}, [r12, :128], r2
3130        vshl.i16        q0,  q0,  #3
3131        vshl.i16        q2,  q2,  #3
3132        vdup.16         q1,  d1[3]
3133        vdup.16         q3,  d5[3]
3134        subs            r8,  r8,  #2
3135        vst1.16         {q0, q1}, [r0, :128]!
3136        vaddw.u16       q8,  q8,  d0
3137        vaddw.u16       q9,  q9,  d1
3138        vaddw.u16       q10, q10, d2
3139        vaddw.u16       q11, q11, d3
3140        vst1.16         {q2, q3}, [r0, :128]!
3141        vaddw.u16       q8,  q8,  d4
3142        vaddw.u16       q9,  q9,  d5
3143        vaddw.u16       q10, q10, d6
3144        vaddw.u16       q11, q11, d7
3145        bgt             1b
3146        cmp             r4,  #0
3147        vmov            q0,  q2
3148        vmov            q1,  q3
3149        b               L(ipred_cfl_ac_420_w16_hpad)
3150
3151L(ipred_cfl_ac_444_w32):
3152        adr             r7,  L(ipred_cfl_ac_444_w32_tbl)
3153        ldr             r3,  [r7, r3, lsl #1] // (w3>>1) << 2
3154        asr             r2,  r2,  #1
3155        add             r7,  r7,  r3
3156        bx              r7
3157
3158        .align 2
3159L(ipred_cfl_ac_444_w32_tbl):
3160        .word L(ipred_cfl_ac_444_w32_wpad0) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
3161        .word L(ipred_cfl_ac_444_w32_wpad2) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
3162        .word L(ipred_cfl_ac_444_w32_wpad4) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
3163        .word L(ipred_cfl_ac_444_w32_wpad6) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
3164
3165L(ipred_cfl_ac_444_w32_wpad0):
3166        sub             r2,  r2,  #32
31671:      // Copy and expand input, without padding
3168        vld1.16         {q0, q1}, [r1, :128]!
3169        vld1.16         {q2, q3}, [r1, :128], r2
3170        vshl.i16        q0,  q0,  #3
3171        vshl.i16        q1,  q1,  #3
3172        vshl.i16        q2,  q2,  #3
3173        vshl.i16        q3,  q3,  #3
3174        subs            r8,  r8,  #1
3175        vst1.16         {q0, q1}, [r0, :128]!
3176        vaddw.u16       q8,  q8,  d0
3177        vaddw.u16       q9,  q9,  d1
3178        vaddw.u16       q10, q10, d2
3179        vaddw.u16       q11, q11, d3
3180        vst1.16         {q2, q3}, [r0, :128]!
3181        vaddw.u16       q8,  q8,  d4
3182        vaddw.u16       q9,  q9,  d5
3183        vaddw.u16       q10, q10, d6
3184        vaddw.u16       q11, q11, d7
3185        bgt             1b
3186        cmp             r4,  #0
3187        b               L(ipred_cfl_ac_444_w32_hpad)
3188
3189L(ipred_cfl_ac_444_w32_wpad2):
3190        sub             r2,  r2,  #32
31911:      // Copy and expand input, padding 8
3192        vld1.16         {q0, q1}, [r1, :128]!
3193        vld1.16         {q2},     [r1, :128], r2
3194        vshl.i16        q0,  q0,  #3
3195        vshl.i16        q1,  q1,  #3
3196        vshl.i16        q2,  q2,  #3
3197        subs            r8,  r8,  #1
3198        vst1.16         {q0, q1}, [r0, :128]!
3199        vdup.16         q3,  d5[3]
3200        vaddw.u16       q8,  q8,  d0
3201        vaddw.u16       q9,  q9,  d1
3202        vaddw.u16       q10, q10, d2
3203        vaddw.u16       q11, q11, d3
3204        vst1.16         {q2, q3}, [r0, :128]!
3205        vaddw.u16       q8,  q8,  d4
3206        vaddw.u16       q9,  q9,  d5
3207        vaddw.u16       q10, q10, d6
3208        vaddw.u16       q11, q11, d7
3209        bgt             1b
3210        cmp             r4,  #0
3211        b               L(ipred_cfl_ac_444_w32_hpad)
3212
3213L(ipred_cfl_ac_444_w32_wpad4):
32141:      // Copy and expand input, padding 16
3215        vld1.16         {q0, q1}, [r1, :128], r2
3216        vshl.i16        q0,  q0,  #3
3217        vshl.i16        q1,  q1,  #3
3218        subs            r8,  r8,  #1
3219        vst1.16         {q0, q1}, [r0, :128]!
3220        vdup.16         q2,  d3[3]
3221        vdup.16         q3,  d3[3]
3222        vaddw.u16       q8,  q8,  d0
3223        vaddw.u16       q9,  q9,  d1
3224        vaddw.u16       q10, q10, d2
3225        vaddw.u16       q11, q11, d3
3226        vst1.16         {q2, q3}, [r0, :128]!
3227        vaddw.u16       q8,  q8,  d4
3228        vaddw.u16       q9,  q9,  d5
3229        vaddw.u16       q10, q10, d6
3230        vaddw.u16       q11, q11, d7
3231        bgt             1b
3232        cmp             r4,  #0
3233        b               L(ipred_cfl_ac_444_w32_hpad)
3234
3235L(ipred_cfl_ac_444_w32_wpad6):
32361:      // Copy and expand input, padding 24
3237        vld1.16         {q0}, [r1, :128], r2
3238        vshl.i16        q0,  q0,  #3
3239        subs            r8,  r8,  #1
3240        vdup.16         q1,  d1[3]
3241        vst1.16         {q0, q1}, [r0, :128]!
3242        vdup.16         q2,  d1[3]
3243        vdup.16         q3,  d1[3]
3244        vaddw.u16       q8,  q8,  d0
3245        vaddw.u16       q9,  q9,  d1
3246        vaddw.u16       q10, q10, d2
3247        vaddw.u16       q11, q11, d3
3248        vst1.16         {q2, q3}, [r0, :128]!
3249        vaddw.u16       q8,  q8,  d4
3250        vaddw.u16       q9,  q9,  d5
3251        vaddw.u16       q10, q10, d6
3252        vaddw.u16       q11, q11, d7
3253        bgt             1b
3254        cmp             r4,  #0
3255
3256L(ipred_cfl_ac_444_w32_hpad):
3257        beq             3f // This assumes that all callers already did "cmp r4, #0"
32582:      // Vertical padding (h_pad > 0)
3259        subs            r4,  r4,  #1
3260        vst1.16         {q0, q1}, [r0, :128]!
3261        vaddw.u16       q8,  q8,  d0
3262        vaddw.u16       q9,  q9,  d1
3263        vaddw.u16       q10, q10, d2
3264        vaddw.u16       q11, q11, d3
3265        vst1.16         {q2, q3}, [r0, :128]!
3266        vaddw.u16       q8,  q8,  d4
3267        vaddw.u16       q9,  q9,  d5
3268        vaddw.u16       q10, q10, d6
3269        vaddw.u16       q11, q11, d7
3270        bgt             2b
32713:
3272
3273        //  Multiply the height by eight and reuse the w4 subtracting
3274        lsl             r6,  r6,  #3
3275        b               L(ipred_cfl_ac_420_w4_calc_subtract_dc)
3276endfunc
3277