xref: /aosp_15_r20/external/libdav1d/src/arm/32/ipred.S (revision c09093415860a1c2373dacd84c4fde00c507cdfd)
1/*
2 * Copyright © 2018, VideoLAN and dav1d authors
3 * Copyright © 2020, Martin Storsjo
4 * Copyright © 2019, B Krishnan Iyer
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_8bpc_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);
36function ipred_dc_128_8bpc_neon, export=1
37        push            {r4, lr}
38        ldr             r4,  [sp, #8]
39        clz             r3,  r3
40        adr             r2,  L(ipred_dc_128_tbl)
41        sub             r3,  r3,  #25
42        ldr             r3,  [r2,  r3,  lsl #2]
43        vmov.i8         q0,  #128
44        add             r2,  r2,  r3
45        add             r12, r0,  r1
46        lsl             r1,  r1,  #1
47        bx              r2
48
49        .align 2
50L(ipred_dc_128_tbl):
51        .word 640f - L(ipred_dc_128_tbl) + CONFIG_THUMB
52        .word 320f - L(ipred_dc_128_tbl) + CONFIG_THUMB
53        .word 16f  - L(ipred_dc_128_tbl) + CONFIG_THUMB
54        .word 8f   - L(ipred_dc_128_tbl) + CONFIG_THUMB
55        .word 4f   - L(ipred_dc_128_tbl) + CONFIG_THUMB
564:
57        vst1.32         {d0[0]},  [r0,  :32], r1
58        vst1.32         {d0[0]},  [r12, :32], r1
59        subs            r4,  r4,  #4
60        vst1.32         {d0[0]},  [r0,  :32], r1
61        vst1.32         {d0[0]},  [r12, :32], r1
62        bgt             4b
63        pop             {r4, pc}
648:
65        vst1.8          {d0},  [r0,  :64], r1
66        vst1.8          {d0},  [r12, :64], r1
67        subs            r4,  r4,  #4
68        vst1.8          {d0},  [r0,  :64], r1
69        vst1.8          {d0},  [r12, :64], r1
70        bgt             8b
71        pop             {r4, pc}
7216:
73        vst1.8          {d0,  d1}, [r0,  :128], r1
74        vst1.8          {d0,  d1}, [r12, :128], r1
75        subs            r4,  r4,  #4
76        vst1.8          {d0,  d1}, [r0,  :128], r1
77        vst1.8          {d0,  d1}, [r12, :128], r1
78        bgt             16b
79        pop             {r4, pc}
80320:
81        vmov.i8         q1,  #128
8232:
83        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
84        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
85        subs            r4,  r4,  #4
86        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
87        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
88        bgt             32b
89        pop             {r4, pc}
90640:
91        vmov.i8         q1,  #128
92        sub             r1,  r1,  #32
9364:
94        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
95        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
96        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
97        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
98        subs            r4,  r4,  #4
99        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
100        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
101        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
102        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
103        bgt             64b
104        pop             {r4, pc}
105endfunc
106
107// void ipred_v_8bpc_neon(pixel *dst, const ptrdiff_t stride,
108//                        const pixel *const topleft,
109//                        const int width, const int height, const int a,
110//                        const int max_width, const int max_height);
111function ipred_v_8bpc_neon, export=1
112        push            {r4, lr}
113        ldr             lr,  [sp, #8]
114        clz             r3,  r3
115        adr             r4,  L(ipred_v_tbl)
116        sub             r3,  r3,  #25
117        ldr             r3,  [r4,  r3,  lsl #2]
118        add             r2,  r2,  #1
119        add             r4,  r4,  r3
120        add             r12, r0,  r1
121        lsl             r1,  r1,  #1
122        bx              r4
123
124        .align 2
125L(ipred_v_tbl):
126        .word 640f - L(ipred_v_tbl) + CONFIG_THUMB
127        .word 320f - L(ipred_v_tbl) + CONFIG_THUMB
128        .word 160f - L(ipred_v_tbl) + CONFIG_THUMB
129        .word 80f  - L(ipred_v_tbl) + CONFIG_THUMB
130        .word 40f  - L(ipred_v_tbl) + CONFIG_THUMB
13140:
132        vld1.32         {d0[]},   [r2]
1334:
134        vst1.32         {d0[0]},  [r0,  :32], r1
135        vst1.32         {d0[0]},  [r12, :32], r1
136        subs            lr,  lr,  #4
137        vst1.32         {d0[0]},  [r0,  :32], r1
138        vst1.32         {d0[0]},  [r12, :32], r1
139        bgt             4b
140        pop             {r4, pc}
14180:
142        vld1.8          {d0}, [r2]
1438:
144        vst1.8          {d0},  [r0,  :64], r1
145        vst1.8          {d0},  [r12, :64], r1
146        subs            lr,  lr,  #4
147        vst1.8          {d0},  [r0,  :64], r1
148        vst1.8          {d0},  [r12, :64], r1
149        bgt             8b
150        pop             {r4, pc}
151160:
152        vld1.8          {q0},  [r2]
15316:
154        vst1.8          {d0,  d1},  [r0,  :128], r1
155        vst1.8          {d0,  d1},  [r12, :128], r1
156        subs            lr,  lr,  #4
157        vst1.8          {d0,  d1},  [r0,  :128], r1
158        vst1.8          {d0,  d1},  [r12, :128], r1
159        bgt             16b
160        pop             {r4, pc}
161320:
162        vld1.8          {q0,  q1},  [r2]
16332:
164        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
165        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
166        subs            lr,  lr,  #4
167        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
168        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
169        bgt             32b
170        pop             {r4, pc}
171640:
172        vld1.8          {q0,  q1},  [r2]!
173        sub             r1,  r1,  #32
174        vld1.8          {q2,  q3},  [r2]
17564:
176        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
177        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
178        vst1.8          {d4,  d5,  d6,  d7},  [r0,  :128], r1
179        vst1.8          {d4,  d5,  d6,  d7},  [r12, :128], r1
180        subs            lr,  lr,  #4
181        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
182        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
183        vst1.8          {d4,  d5,  d6,  d7},  [r0,  :128], r1
184        vst1.8          {d4,  d5,  d6,  d7},  [r12, :128], r1
185        bgt             64b
186        pop             {r4, pc}
187endfunc
188
189// void ipred_h_8bpc_neon(pixel *dst, const ptrdiff_t stride,
190//                        const pixel *const topleft,
191//                        const int width, const int height, const int a,
192//                        const int max_width, const int max_height);
193function ipred_h_8bpc_neon, export=1
194        push            {r4-r5, lr}
195        ldr             r4,  [sp, #12]
196        clz             r3,  r3
197        adr             r5,  L(ipred_h_tbl)
198        sub             r3,  r3,  #25
199        ldr             r3,  [r5,  r3,  lsl #2]
200        sub             r2,  r2,  #4
201        mov             lr,  #-4
202        add             r5,  r5,  r3
203        add             r12, r0,  r1
204        lsl             r1,  r1,  #1
205        bx              r5
206
207        .align 2
208L(ipred_h_tbl):
209        .word 640f - L(ipred_h_tbl) + CONFIG_THUMB
210        .word 320f - L(ipred_h_tbl) + CONFIG_THUMB
211        .word 160f - L(ipred_h_tbl) + CONFIG_THUMB
212        .word 8f   - L(ipred_h_tbl) + CONFIG_THUMB
213        .word 4f   - L(ipred_h_tbl) + CONFIG_THUMB
2144:
215        vld4.8          {d0[],  d1[],  d2[],  d3[]},  [r2, :32],  lr
216        vst1.32         {d3[0]},  [r0,  :32], r1
217        vst1.32         {d2[0]},  [r12, :32], r1
218        subs            r4,  r4,  #4
219        vst1.32         {d1[0]},  [r0,  :32], r1
220        vst1.32         {d0[0]},  [r12, :32], r1
221        bgt             4b
222        pop             {r4-r5, pc}
2238:
224        vld4.8          {d0[],  d1[],  d2[],  d3[]},  [r2, :32],  lr
225        vst1.8          {d3},  [r0,  :64], r1
226        vst1.8          {d2},  [r12, :64], r1
227        subs            r4,  r4,  #4
228        vst1.8          {d1},  [r0,  :64], r1
229        vst1.8          {d0},  [r12, :64], r1
230        bgt             8b
231        pop             {r4-r5, pc}
232160:
233        add             r2,  r2,  #3
234        mov             lr,  #-1
23516:
236        vld1.8          {d0[],  d1[]},  [r2],  lr
237        subs            r4,  r4,  #4
238        vld1.8          {d2[],  d3[]},  [r2],  lr
239        vst1.8          {q0},  [r0,    :128],  r1
240        vld1.8          {d4[],  d5[]},  [r2],  lr
241        vst1.8          {q1},  [r12,   :128],  r1
242        vld1.8          {d6[],  d7[]},  [r2],  lr
243        vst1.8          {q2},  [r0,    :128],  r1
244        vst1.8          {q3},  [r12,   :128],  r1
245        bgt             16b
246        pop             {r4-r5, pc}
247320:
248        add             r2,  r2,  #3
249        mov             lr,  #-1
250        sub             r1,  r1,  #16
25132:
252        vld1.8          {d0[],  d1[]}, [r2],  lr
253        subs            r4,  r4,  #4
254        vld1.8          {d2[],  d3[]}, [r2],  lr
255        vst1.8          {q0},  [r0,   :128]!
256        vld1.8          {d4[],  d5[]}, [r2],  lr
257        vst1.8          {q1},  [r12,  :128]!
258        vld1.8          {d6[],  d7[]}, [r2],  lr
259        vst1.8          {q0},  [r0,   :128],  r1
260        vst1.8          {q1},  [r12,  :128],  r1
261        vst1.8          {q2},  [r0,   :128]!
262        vst1.8          {q3},  [r12,  :128]!
263        vst1.8          {q2},  [r0,   :128],  r1
264        vst1.8          {q3},  [r12,  :128],  r1
265        bgt             32b
266        pop             {r4-r5, pc}
267640:
268        add             r2,  r2,  #3
269        mov             lr,  #-1
270        sub             r1,  r1,  #48
27164:
272        vld1.8          {d0[],  d1[]},  [r2],  lr
273        subs            r4,  r4,  #4
274        vld1.8          {d2[],  d3[]},  [r2],  lr
275        vst1.8          {q0},  [r0,    :128]!
276        vld1.8          {d4[],  d5[]},  [r2],  lr
277        vst1.8          {q1},  [r12,   :128]!
278        vld1.8          {d6[],  d7[]},  [r2],  lr
279        vst1.8          {q0},  [r0,    :128]!
280        vst1.8          {q1},  [r12,   :128]!
281        vst1.8          {q0},  [r0,    :128]!
282        vst1.8          {q1},  [r12,   :128]!
283        vst1.8          {q0},  [r0,    :128],  r1
284        vst1.8          {q1},  [r12,   :128],  r1
285        vst1.8          {q2},  [r0,    :128]!
286        vst1.8          {q3},  [r12,   :128]!
287        vst1.8          {q2},  [r0,    :128]!
288        vst1.8          {q3},  [r12,   :128]!
289        vst1.8          {q2},  [r0,    :128]!
290        vst1.8          {q3},  [r12,   :128]!
291        vst1.8          {q2},  [r0,    :128],  r1
292        vst1.8          {q3},  [r12,   :128],  r1
293        bgt             64b
294        pop             {r4-r5, pc}
295endfunc
296
297// void ipred_dc_top_8bpc_neon(pixel *dst, const ptrdiff_t stride,
298//                             const pixel *const topleft,
299//                             const int width, const int height, const int a,
300//                             const int max_width, const int max_height);
301function ipred_dc_top_8bpc_neon, export=1
302        push            {r4-r5, lr}
303        ldr             r4,  [sp, #12]
304        clz             r3,  r3
305        adr             r5,  L(ipred_dc_top_tbl)
306        sub             r3,  r3,  #25
307        ldr             r3,  [r5,  r3,  lsl #2]
308        add             r2,  r2,  #1
309        add             r5,  r5,  r3
310        add             r12, r0,  r1
311        lsl             r1,  r1,  #1
312        bx              r5
313
314        .align 2
315L(ipred_dc_top_tbl):
316        .word 640f - L(ipred_dc_top_tbl) + CONFIG_THUMB
317        .word 320f - L(ipred_dc_top_tbl) + CONFIG_THUMB
318        .word 160f - L(ipred_dc_top_tbl) + CONFIG_THUMB
319        .word 80f  - L(ipred_dc_top_tbl) + CONFIG_THUMB
320        .word 40f  - L(ipred_dc_top_tbl) + CONFIG_THUMB
32140:
322        vld1.32         {d0[]},  [r2]
323        vpaddl.u8       d0,  d0
324        vpadd.u16       d0,  d0
325        vrshrn.u16      d0,  q0,  #2
326        vdup.8          d0,  d0[0]
3274:
328        vst1.32         {d0[0]},  [r0,  :32], r1
329        vst1.32         {d0[0]},  [r12, :32], r1
330        subs            r4,  r4,  #4
331        vst1.32         {d0[0]},  [r0,  :32], r1
332        vst1.32         {d0[0]},  [r12, :32], r1
333        bgt             4b
334        pop             {r4-r5, pc}
33580:
336        vld1.8          {d0},  [r2]
337        vpaddl.u8       d0,  d0
338        vpadd.u16       d0,  d0
339        vpadd.u16       d0,  d0
340        vrshrn.u16      d0,  q0,  #3
341        vdup.8          d0,  d0[0]
3428:
343        vst1.8          {d0},  [r0,  :64], r1
344        vst1.8          {d0},  [r12, :64], r1
345        subs            r4,  r4,  #4
346        vst1.8          {d0},  [r0,  :64], r1
347        vst1.8          {d0},  [r12, :64], r1
348        bgt             8b
349        pop             {r4-r5, pc}
350160:
351        vld1.8          {d0,  d1},  [r2]
352        vaddl.u8        q0,  d0,  d1
353        vadd.u16        d0,  d0,  d1
354        vpadd.u16       d0,  d0
355        vpadd.u16       d0,  d0
356        vrshrn.u16      d0,  q0,  #4
357        vdup.8          q0,  d0[0]
35816:
359        vst1.8          {d0,  d1},  [r0,  :128], r1
360        vst1.8          {d0,  d1},  [r12, :128], r1
361        subs            r4,  r4,  #4
362        vst1.8          {d0,  d1},  [r0,  :128], r1
363        vst1.8          {d0,  d1},  [r12, :128], r1
364        bgt             16b
365        pop             {r4-r5, pc}
366320:
367        vld1.8          {d0,  d1,  d2,  d3},  [r2]
368        vaddl.u8        q0,  d0,  d1
369        vaddl.u8        q1,  d2,  d3
370        vadd.u16        q0,  q0,  q1
371        vadd.u16        d0,  d0,  d1
372        vpadd.u16       d0,  d0
373        vpadd.u16       d0,  d0
374        vrshrn.u16      d4,  q0,  #5
375        vdup.8          q0,  d4[0]
376        vdup.8          q1,  d4[0]
37732:
378        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
379        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
380        subs            r4,  r4,  #4
381        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
382        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
383        bgt             32b
384        pop             {r4-r5, pc}
385640:
386        vld1.8          {d0,  d1,  d2,  d3},  [r2]!
387        vaddl.u8        q0,  d0,  d1
388        vld1.8          {d4,  d5,  d6,  d7},  [r2]
389        vaddl.u8        q1,  d2,  d3
390        vaddl.u8        q2,  d4,  d5
391        vaddl.u8        q3,  d6,  d7
392        vadd.u16        q0,  q0,  q1
393        vadd.u16        q1,  q2,  q3
394        vadd.u16        q0,  q0,  q1
395        vadd.u16        d0,  d0,  d1
396        vpadd.u16       d0,  d0
397        vpadd.u16       d0,  d0
398        vrshrn.u16      d18, q0,  #6
399        vdup.8          q0,  d18[0]
400        vdup.8          q1,  d18[0]
401        sub             r1,  r1,  #32
40264:
403        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
404        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
405        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
406        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
407        subs            r4,  r4,  #4
408        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
409        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
410        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
411        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
412        bgt             64b
413        pop             {r4-r5, pc}
414endfunc
415
416// void ipred_dc_left_8bpc_neon(pixel *dst, const ptrdiff_t stride,
417//                              const pixel *const topleft,
418//                              const int width, const int height, const int a,
419//                              const int max_width, const int max_height);
420function ipred_dc_left_8bpc_neon, export=1
421        push            {r4-r5, lr}
422        ldr             r4,  [sp, #12]
423        sub             r2,  r2,  r4
424        clz             r3,  r3
425        clz             lr,  r4
426        sub             lr,  lr,  #25
427        adr             r5,  L(ipred_dc_left_tbl)
428        sub             r3,  r3,  #20
429        ldr             r3,  [r5,  r3,  lsl #2]
430        ldr             lr,  [r5,  lr,  lsl #2]
431        add             r3,  r5,  r3
432        add             r5,  r5,  lr
433        add             r12, r0,  r1
434        lsl             r1,  r1,  #1
435        bx              r5
436
437        .align 2
438L(ipred_dc_left_tbl):
439        .word L(ipred_dc_left_h64) - L(ipred_dc_left_tbl) + CONFIG_THUMB
440        .word L(ipred_dc_left_h32) - L(ipred_dc_left_tbl) + CONFIG_THUMB
441        .word L(ipred_dc_left_h16) - L(ipred_dc_left_tbl) + CONFIG_THUMB
442        .word L(ipred_dc_left_h8)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
443        .word L(ipred_dc_left_h4)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
444        .word L(ipred_dc_left_w64) - L(ipred_dc_left_tbl) + CONFIG_THUMB
445        .word L(ipred_dc_left_w32) - L(ipred_dc_left_tbl) + CONFIG_THUMB
446        .word L(ipred_dc_left_w16) - L(ipred_dc_left_tbl) + CONFIG_THUMB
447        .word L(ipred_dc_left_w8)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
448        .word L(ipred_dc_left_w4)  - L(ipred_dc_left_tbl) + CONFIG_THUMB
449
450L(ipred_dc_left_h4):
451        vld1.32         {d0[]},  [r2, :32]
452        vpaddl.u8       d0,  d0
453        vpadd.u16       d0,  d0
454        vrshrn.u16      d0,  q0,  #2
455        vdup.8          q0,  d0[0]
456        bx              r3
457L(ipred_dc_left_w4):
458        vst1.32         {d0[0]},  [r0,  :32], r1
459        vst1.32         {d0[0]},  [r12, :32], r1
460        subs            r4,  r4,  #4
461        vst1.32         {d0[0]},  [r0,  :32], r1
462        vst1.32         {d0[0]},  [r12, :32], r1
463        bgt             L(ipred_dc_left_w4)
464        pop             {r4-r5, pc}
465L(ipred_dc_left_h8):
466        vld1.8          {d0},  [r2, :64]
467        vpaddl.u8       d0,  d0
468        vpadd.u16       d0,  d0
469        vpadd.u16       d0,  d0
470        vrshrn.u16      d0,  q0,  #3
471        vdup.8          q0,  d0[0]
472        bx              r3
473L(ipred_dc_left_w8):
474        vst1.8          {d0},  [r0,  :64], r1
475        vst1.8          {d0},  [r12, :64], r1
476        subs            r4,  r4,  #4
477        vst1.8          {d0},  [r0,  :64], r1
478        vst1.8          {d0},  [r12, :64], r1
479        bgt             L(ipred_dc_left_w8)
480        pop             {r4-r5, pc}
481L(ipred_dc_left_h16):
482        vld1.8          {d0,  d1},  [r2, :128]
483        vaddl.u8        q0,  d0,  d1
484        vadd.u16        d0,  d0,  d1
485        vpadd.u16       d0,  d0
486        vpadd.u16       d0,  d0
487        vrshrn.u16      d0,  q0,  #4
488        vdup.8          q0,  d0[0]
489        bx              r3
490L(ipred_dc_left_w16):
491        vst1.8          {d0,  d1},  [r0,  :128], r1
492        vst1.8          {d0,  d1},  [r12, :128], r1
493        subs            r4,  r4,  #4
494        vst1.8          {d0,  d1},  [r0,  :128], r1
495        vst1.8          {d0,  d1},  [r12, :128], r1
496        bgt             L(ipred_dc_left_w16)
497        pop             {r4-r5, pc}
498L(ipred_dc_left_h32):
499        vld1.8          {d0,  d1,  d2,  d3},  [r2, :128]
500        vaddl.u8        q0,  d0,  d1
501        vaddl.u8        q1,  d2,  d3
502        vadd.u16        q0,  q0,  q1
503        vadd.u16        d0,  d0,  d1
504        vpadd.u16       d0,  d0
505        vpadd.u16       d0,  d0
506        vrshrn.u16      d0,  q0,  #5
507        vdup.8          q0,  d0[0]
508        bx              r3
509L(ipred_dc_left_w32):
510        vmov.8          q1,  q0
5111:
512        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
513        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
514        subs            r4,  r4,  #4
515        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
516        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
517        bgt             1b
518        pop             {r4-r5, pc}
519L(ipred_dc_left_h64):
520        vld1.8          {d0,  d1,  d2,  d3},  [r2, :128]!
521        vld1.8          {d4,  d5,  d6,  d7},  [r2, :128]
522        vaddl.u8        q0,  d0,  d1
523        vaddl.u8        q1,  d2,  d3
524        vaddl.u8        q2,  d4,  d5
525        vaddl.u8        q3,  d6,  d7
526        vadd.u16        q0,  q0,  q1
527        vadd.u16        q1,  q2,  q3
528        vadd.u16        q0,  q0,  q1
529        vadd.u16        d0,  d0,  d1
530        vpadd.u16       d0,  d0
531        vpadd.u16       d0,  d0
532        vrshrn.u16      d0,  q0,  #6
533        vdup.8          q0,  d0[0]
534        bx              r3
535L(ipred_dc_left_w64):
536        vmov.8          q1,  q0
537        sub             r1,  r1,  #32
5381:
539        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
540        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
541        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
542        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
543        subs            r4,  r4, #4
544        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
545        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
546        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
547        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
548        bgt             1b
549        pop             {r4-r5, pc}
550endfunc
551
552// void ipred_dc_8bpc_neon(pixel *dst, const ptrdiff_t stride,
553//                         const pixel *const topleft,
554//                         const int width, const int height, const int a,
555//                         const int max_width, const int max_height);
556function ipred_dc_8bpc_neon, export=1
557        push            {r4-r6, lr}
558        ldr             r4,  [sp, #16]
559        sub             r2,  r2,  r4
560        add             lr,  r3,  r4        // width + height
561        clz             r3,  r3
562        clz             r12, r4
563        vdup.16         q15, lr             // width + height
564        adr             r5,  L(ipred_dc_tbl)
565        rbit            lr,  lr             // rbit(width + height)
566        sub             r3,  r3,  #20       // 25 leading bits, minus table offset 5
567        sub             r12, r12, #25
568        clz             lr,  lr             // ctz(width + height)
569        ldr             r3,  [r5,  r3,  lsl #2]
570        ldr             r12, [r5,  r12, lsl #2]
571        neg             lr,  lr             // -ctz(width + height)
572        add             r3,  r5,  r3
573        add             r5,  r5,  r12
574        vshr.u16        q15, q15, #1        // (width + height) >> 1
575        vdup.16         q14, lr             // -ctz(width + height)
576        add             r12, r0,  r1
577        lsl             r1,  r1,  #1
578        bx              r5
579
580        .align 2
581L(ipred_dc_tbl):
582        .word L(ipred_dc_h64) - L(ipred_dc_tbl) + CONFIG_THUMB
583        .word L(ipred_dc_h32) - L(ipred_dc_tbl) + CONFIG_THUMB
584        .word L(ipred_dc_h16) - L(ipred_dc_tbl) + CONFIG_THUMB
585        .word L(ipred_dc_h8)  - L(ipred_dc_tbl) + CONFIG_THUMB
586        .word L(ipred_dc_h4)  - L(ipred_dc_tbl) + CONFIG_THUMB
587        .word L(ipred_dc_w64) - L(ipred_dc_tbl) + CONFIG_THUMB
588        .word L(ipred_dc_w32) - L(ipred_dc_tbl) + CONFIG_THUMB
589        .word L(ipred_dc_w16) - L(ipred_dc_tbl) + CONFIG_THUMB
590        .word L(ipred_dc_w8)  - L(ipred_dc_tbl) + CONFIG_THUMB
591        .word L(ipred_dc_w4)  - L(ipred_dc_tbl) + CONFIG_THUMB
592
593L(ipred_dc_h4):
594        vld1.32         {d0[]},  [r2, :32]!
595        vpaddl.u8       d0,  d0
596        add             r2,  r2,  #1
597        vpadd.u16       d0,  d0
598        bx              r3
599L(ipred_dc_w4):
600        vld1.32         {d1[]},  [r2]
601        vadd.s16        d0,  d0,  d30
602        vpaddl.u8       d1,  d1
603        vpadd.u16       d1,  d1
604        cmp             r4,  #4
605        vadd.s16        d0,  d0,  d1
606        vshl.u16        d0,  d0,  d28
607        beq             1f
608        // h = 8/16
609        movw            lr,  #(0x3334/2)
610        movw            r5,  #(0x5556/2)
611        cmp             r4,  #16
612        it              ne
613        movne           lr,  r5
614        vdup.16         d30, lr
615        vqdmulh.s16     d0,  d0,  d30
6161:
617        vdup.8          d0,  d0[0]
6182:
619        vst1.32         {d0[0]},  [r0,  :32], r1
620        vst1.32         {d0[0]},  [r12, :32], r1
621        subs            r4,  r4,  #4
622        vst1.32         {d0[0]},  [r0,  :32], r1
623        vst1.32         {d0[0]},  [r12, :32], r1
624        bgt             2b
625        pop             {r4-r6, pc}
626
627L(ipred_dc_h8):
628        vld1.8          {d0},  [r2, :64]!
629        vpaddl.u8       d0,  d0
630        vpadd.u16       d0,  d0
631        add             r2,  r2,  #1
632        vpadd.u16       d0,  d0
633        bx              r3
634L(ipred_dc_w8):
635        vld1.8          {d2},  [r2]
636        vadd.s16        d0,  d0,  d30
637        vpaddl.u8       d2,  d2
638        vpadd.u16       d2,  d2
639        vpadd.u16       d2,  d2
640        cmp             r4,  #8
641        vadd.s16        d0,  d0,  d2
642        vshl.u16        d0,  d0,  d28
643        beq             1f
644        // h = 4/16/32
645        cmp             r4,  #32
646        movw            lr,  #(0x3334/2)
647        movw            r5,  #(0x5556/2)
648        it              ne
649        movne           lr,  r5
650        vdup.16         d24, lr
651        vqdmulh.s16     d0,  d0,  d24
6521:
653        vdup.8          d0,  d0[0]
6542:
655        vst1.8          {d0},  [r0,  :64], r1
656        vst1.8          {d0},  [r12, :64], r1
657        subs            r4,  r4,  #4
658        vst1.8          {d0},  [r0,  :64], r1
659        vst1.8          {d0},  [r12, :64], r1
660        bgt             2b
661        pop             {r4-r6, pc}
662
663L(ipred_dc_h16):
664        vld1.8          {d0,  d1},  [r2, :128]!
665        vaddl.u8        q0,  d0,  d1
666        vadd.u16        d0,  d0,  d1
667        vpadd.u16       d0,  d0
668        add             r2,  r2,  #1
669        vpadd.u16       d0,  d0
670        bx              r3
671L(ipred_dc_w16):
672        vld1.8          {d2,  d3},  [r2]
673        vadd.s16        d0,  d0,  d30
674        vaddl.u8        q1,  d2,  d3
675        vadd.u16        d2,  d2,  d3
676        vpadd.u16       d2,  d2
677        vpadd.u16       d2,  d2
678        cmp             r4,  #16
679        vadd.s16        d0,  d0,  d2
680        vshl.u16        d0,  d0,  d28
681        beq             1f
682        // h = 4/8/32/64
683        tst             r4,  #(32+16+8)     // 16 added to make a consecutive bitmask
684        movw            lr,  #(0x3334/2)
685        movw            r5,  #(0x5556/2)
686        it              ne
687        movne           lr,  r5
688        vdup.16         d24, lr
689        vqdmulh.s16     d0,  d0,  d24
6901:
691        vdup.8          q0,  d0[0]
6922:
693        vst1.8          {d0,  d1},  [r0,  :128], r1
694        vst1.8          {d0,  d1},  [r12, :128], r1
695        subs            r4,  r4, #4
696        vst1.8          {d0,  d1},  [r0,  :128], r1
697        vst1.8          {d0,  d1},  [r12, :128], r1
698        bgt             2b
699        pop             {r4-r6, pc}
700
701L(ipred_dc_h32):
702        vld1.8          {d0,  d1,  d2,  d3},  [r2, :128]!
703        vaddl.u8        q0,  d0,  d1
704        vaddl.u8        q1,  d2,  d3
705        vadd.u16        q0,  q0,  q1
706        vadd.u16        d0,  d0,  d1
707        vpadd.u16       d0,  d0
708        add             r2,  r2,  #1
709        vpadd.u16       d0,  d0
710        bx              r3
711L(ipred_dc_w32):
712        vld1.8          {d2,  d3,  d4,  d5},  [r2]
713        vadd.s16        d0,  d0,  d30
714        vaddl.u8        q1,  d2,  d3
715        vaddl.u8        q2,  d4,  d5
716        vadd.u16        q1,  q1,  q2
717        vadd.u16        d2,  d2,  d3
718        vpadd.u16       d2,  d2
719        vpadd.u16       d2,  d2
720        cmp             r4,  #32
721        vadd.s16        d0,  d0,  d2
722        vshl.u16        d4,  d0,  d28
723        beq             1f
724        // h = 8/16/64
725        cmp             r4,  #8
726        movw            lr,  #(0x3334/2)
727        movw            r5,  #(0x5556/2)
728        it              ne
729        movne           lr,  r5
730        vdup.16         d24, lr
731        vqdmulh.s16     d4,  d4,  d24
7321:
733        vdup.8          q0,  d4[0]
734        vdup.8          q1,  d4[0]
7352:
736        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
737        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
738        subs            r4,  r4,  #4
739        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
740        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
741        bgt             2b
742        pop             {r4-r6, pc}
743
744L(ipred_dc_h64):
745        vld1.8          {d0,  d1,  d2,  d3},  [r2, :128]!
746        vaddl.u8        q0,  d0,  d1
747        vld1.8          {d4,  d5,  d6,  d7},  [r2, :128]!
748        vaddl.u8        q1,  d2,  d3
749        vaddl.u8        q2,  d4,  d5
750        vaddl.u8        q3,  d6,  d7
751        vadd.u16        q0,  q0,  q1
752        vadd.u16        q1,  q2,  q3
753        vadd.u16        q0,  q0,  q1
754        vadd.u16        d0,  d0,  d1
755        vpadd.u16       d0,  d0
756        add             r2,  r2,  #1
757        vpadd.u16       d0,  d0
758        bx              r3
759L(ipred_dc_w64):
760        vld1.8          {d2,  d3,  d4,  d5},  [r2]!
761        vadd.s16        d0,  d0,  d30
762        vaddl.u8        q2,  d4,  d5
763        vaddl.u8        q1,  d2,  d3
764        vadd.u16        d4,  d4,  d5
765        vadd.u16        d2,  d2,  d3
766        vld1.8          {d16, d17, d18, d19}, [r2]
767        vpadd.u16       d4,  d4
768        vpadd.u16       d2,  d2
769        vpadd.u16       d4,  d4
770        vpadd.u16       d2,  d2
771        vaddl.u8        q8,  d16, d17
772        vaddl.u8        q9,  d18, d19
773        vadd.u16        d16, d16, d17
774        vadd.u16        d18, d18, d19
775        vpadd.u16       d16, d16
776        vpadd.u16       d18, d18
777        vpadd.u16       d16, d16
778        vpadd.u16       d18, d18
779        vadd.u16        d2,  d2,  d4
780        vadd.u16        d3,  d16, d18
781        cmp             r4,  #64
782        vadd.s16        d0,  d0,  d2
783        vadd.s16        d0,  d0,  d3
784        vshl.u16        d18, d0,  d28
785        beq             1f
786        // h = 16/32
787        movw            lr,  #(0x5556/2)
788        movt            lr,  #(0x3334/2)
789        and             r5,  r4,  #31
790        lsr             lr,  lr,  r5
791        vdup.16         d30, lr
792        vqdmulh.s16     d18, d18, d30
7931:
794        sub             r1,  r1,  #32
795        vdup.8          q0,  d18[0]
796        vdup.8          q1,  d18[0]
7972:
798        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
799        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
800        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
801        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
802        subs            r4,  r4,  #4
803        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128]!
804        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128]!
805        vst1.8          {d0,  d1,  d2,  d3},  [r0,  :128], r1
806        vst1.8          {d0,  d1,  d2,  d3},  [r12, :128], r1
807        bgt             2b
808        pop             {r4-r6, pc}
809endfunc
810
811// void ipred_paeth_8bpc_neon(pixel *dst, const ptrdiff_t stride,
812//                            const pixel *const topleft,
813//                            const int width, const int height, const int a,
814//                            const int max_width, const int max_height);
815function ipred_paeth_8bpc_neon, export=1
816        push            {r4-r8, lr}
817        ldr             r4,  [sp, #24]
818        clz             lr,  r3
819        adr             r5,  L(ipred_paeth_tbl)
820        sub             lr,  lr,  #25
821        ldr             lr,  [r5, lr, lsl #2]
822        vld1.8          {d4[], d5[]},  [r2]
823        add             r8,  r2,  #1
824        sub             r2,  r2,  #4
825        add             r5,  r5,  lr
826        mov             r7,  #-4
827        add             r6,  r0,  r1
828        lsl             r1,  r1,  #1
829        bx              r5
830
831        .align 2
832L(ipred_paeth_tbl):
833        .word 640f - L(ipred_paeth_tbl) + CONFIG_THUMB
834        .word 320f - L(ipred_paeth_tbl) + CONFIG_THUMB
835        .word 160f - L(ipred_paeth_tbl) + CONFIG_THUMB
836        .word 80f  - L(ipred_paeth_tbl) + CONFIG_THUMB
837        .word 40f  - L(ipred_paeth_tbl) + CONFIG_THUMB
838
83940:
840        vld1.32         {d6[], d7[]},  [r8]
841        vsubl.u8        q8,  d6,  d4  // top - topleft
8424:
843        vld4.8          {d0[], d1[], d2[], d3[]},  [r2, :32], r7
844        vzip.32         d0,  d1
845        vzip.32         d2,  d3
846        vaddw.u8        q9,  q8,  d0
847        vaddw.u8        q10, q8,  d2
848        vqmovun.s16     d18, q9       // base
849        vqmovun.s16     d19, q10
850        vmov            d1,  d2
851        vabd.u8         q10, q3,  q9  // tdiff
852        vabd.u8         q11, q2,  q9  // tldiff
853        vabd.u8         q9,  q0,  q9  // ldiff
854        vmin.u8         q12, q10, q11 // min(tdiff, tldiff)
855        vcge.u8         q10, q11, q10 // tldiff >= tdiff
856        vcge.u8         q9,  q12, q9  // min(tdiff, tldiff) >= ldiff
857        vbsl            q10, q3,  q2  // tdiff <= tldiff ? top : topleft
858        vbit            q10, q0,  q9  // ldiff <= min ? left : ...
859        vst1.32         {d21[1]}, [r0, :32], r1
860        vst1.32         {d21[0]}, [r6, :32], r1
861        subs            r4,  r4,  #4
862        vst1.32         {d20[1]}, [r0, :32], r1
863        vst1.32         {d20[0]}, [r6, :32], r1
864        bgt             4b
865        pop             {r4-r8, pc}
86680:
867        vld1.8          {d6},  [r8]
868        vsubl.u8        q8,  d6,  d4  // top - topleft
869        vmov            d7,  d6
8708:
871        vld4.8          {d0[], d1[], d2[], d3[]},  [r2, :32], r7
872        vaddw.u8        q9,  q8,  d0
873        vaddw.u8        q10, q8,  d1
874        vaddw.u8        q11, q8,  d2
875        vaddw.u8        q12, q8,  d3
876        vqmovun.s16     d18, q9       // base
877        vqmovun.s16     d19, q10
878        vqmovun.s16     d20, q11
879        vqmovun.s16     d21, q12
880        vabd.u8         q11, q3,  q9  // tdiff
881        vabd.u8         q12, q3,  q10
882        vabd.u8         q13, q2,  q9  // tldiff
883        vabd.u8         q14, q2,  q10
884        vabd.u8         q10, q1,  q10 // ldiff
885        vabd.u8         q9,  q0,  q9
886        vmin.u8         q15, q12, q14 // min(tdiff, tldiff)
887        vcge.u8         q12, q14, q12 // tldiff >= tdiff
888        vmin.u8         q14, q11, q13 // min(tdiff, tldiff)
889        vcge.u8         q11, q13, q11 // tldiff >= tdiff
890        vcge.u8         q10, q15, q10 // min(tdiff, tldiff) >= ldiff
891        vcge.u8         q9,  q14, q9
892        vbsl            q12, q3,  q2  // tdiff <= tldiff ? top : topleft
893        vbsl            q11, q3,  q2
894        vbit            q12, q1,  q10 // ldiff <= min ? left : ...
895        vbit            q11, q0,  q9
896        vst1.8          {d25}, [r0, :64], r1
897        vst1.8          {d24}, [r6, :64], r1
898        subs            r4,  r4,  #4
899        vst1.8          {d23}, [r0, :64], r1
900        vst1.8          {d22}, [r6, :64], r1
901        bgt             8b
902        pop             {r4-r8, pc}
903160:
904320:
905640:
906        vld1.8          {d6},  [r8]!
907        mov             r12, r3
908        // Set up pointers for four rows in parallel; r0, r6, r5, lr
909        add             r5,  r0,  r1
910        add             lr,  r6,  r1
911        lsl             r1,  r1,  #1
912        sub             r1,  r1,  r3
9131:
914        vld4.8          {d0[], d1[], d2[], d3[]},  [r2, :32], r7
9152:
916        vsubl.u8        q8,  d6,  d4  // top - topleft
917        vmov            d7,  d6
918        vaddw.u8        q9,  q8,  d0
919        vaddw.u8        q10, q8,  d1
920        vaddw.u8        q11, q8,  d2
921        vaddw.u8        q12, q8,  d3
922        vqmovun.s16     d18, q9       // base
923        vqmovun.s16     d19, q10
924        vqmovun.s16     d20, q11
925        vqmovun.s16     d21, q12
926        vabd.u8         q11, q3,  q9  // tdiff
927        vabd.u8         q12, q3,  q10
928        vabd.u8         q13, q2,  q9  // tldiff
929        vabd.u8         q14, q2,  q10
930        vabd.u8         q10, q1,  q10 // ldiff
931        vabd.u8         q9,  q0,  q9
932        vmin.u8         q15, q12, q14 // min(tdiff, tldiff)
933        vcge.u8         q12, q14, q12 // tldiff >= tdiff
934        vmin.u8         q14, q11, q13 // min(tdiff, tldiff)
935        vcge.u8         q11, q13, q11 // tldiff >= tdiff
936        vcge.u8         q10, q15, q10 // min(tdiff, tldiff) >= ldiff
937        vcge.u8         q9,  q14, q9
938        vbsl            q12, q3,  q2  // tdiff <= tldiff ? top : topleft
939        vbsl            q11, q3,  q2
940        vbit            q12, q1,  q10 // ldiff <= min ? left : ...
941        vbit            q11, q0,  q9
942        subs            r3,  r3,  #8
943        vst1.8          {d25}, [r0, :64]!
944        vst1.8          {d24}, [r6, :64]!
945        vst1.8          {d23}, [r5, :64]!
946        vst1.8          {d22}, [lr, :64]!
947        ble             8f
948        vld1.8          {d6},  [r8]!
949        b               2b
9508:
951        subs            r4,  r4,  #4
952        ble             9f
953        // End of horizontal loop, move pointers to next four rows
954        sub             r8,  r8,  r12
955        add             r0,  r0,  r1
956        add             r6,  r6,  r1
957        vld1.8          {d6},  [r8]!
958        add             r5,  r5,  r1
959        add             lr,  lr,  r1
960        mov             r3,  r12
961        b               1b
9629:
963        pop             {r4-r8, pc}
964endfunc
965
966// void ipred_smooth_8bpc_neon(pixel *dst, const ptrdiff_t stride,
967//                             const pixel *const topleft,
968//                             const int width, const int height, const int a,
969//                             const int max_width, const int max_height);
970function ipred_smooth_8bpc_neon, export=1
971        push            {r4-r10, lr}
972        ldr             r4,  [sp, #32]
973        movrel          r10, X(sm_weights)
974        add             r12, r10, r4
975        add             r10, r10, r3
976        clz             r9,  r3
977        adr             r5,  L(ipred_smooth_tbl)
978        sub             lr,  r2,  r4
979        sub             r9,  r9,  #25
980        ldr             r9,  [r5, r9, lsl #2]
981        vld1.8          {d4[]},  [lr] // bottom
982        add             r8,  r2,  #1
983        add             r5,  r5,  r9
984        add             r6,  r0,  r1
985        lsl             r1,  r1,  #1
986        bx              r5
987
988        .align 2
989L(ipred_smooth_tbl):
990        .word 640f - L(ipred_smooth_tbl) + CONFIG_THUMB
991        .word 320f - L(ipred_smooth_tbl) + CONFIG_THUMB
992        .word 160f - L(ipred_smooth_tbl) + CONFIG_THUMB
993        .word 80f  - L(ipred_smooth_tbl) + CONFIG_THUMB
994        .word 40f  - L(ipred_smooth_tbl) + CONFIG_THUMB
995
99640:
997        vld1.32         {d16[]}, [r8]       // top
998        vld1.32         {d18[]}, [r10, :32] // weights_hor
999        sub             r2,  r2,  #4
1000        mov             r7,  #-4
1001        vdup.8          q3,  d16[3]   // right
1002        vsubl.u8        q8,  d16, d4  // top-bottom
1003        vmovl.u8        q9,  d18      // weights_hor
10044:
1005        vld4.8          {d0[],  d1[],  d2[],  d3[]},  [r2,  :32], r7 // left
1006        vld4.8          {d20[], d21[], d22[], d23[]}, [r12, :32]!    // weights_ver
1007        vshll.i8        q12, d6,  #8  // right*256
1008        vshll.i8        q13, d6,  #8
1009        vzip.32         d1,  d0       // left, flipped
1010        vzip.32         d3,  d2
1011        vzip.32         d20, d21      // weights_ver
1012        vzip.32         d22, d23
1013        vshll.i8        q14, d4,  #8  // bottom*256
1014        vshll.i8        q15, d4,  #8
1015        vsubl.u8        q0,  d1,  d6  // left-right
1016        vsubl.u8        q1,  d3,  d6
1017        vmovl.u8        q10, d20      // weights_ver
1018        vmovl.u8        q11, d22
1019        vmla.i16        q12, q1,  q9  // right*256  + (left-right)*weights_hor
1020        vmla.i16        q13, q0,  q9  // (left flipped)
1021        vmla.i16        q14, q8,  q10 // bottom*256 + (top-bottom)*weights_ver
1022        vmla.i16        q15, q8,  q11
1023        vhadd.u16       q12, q12, q14
1024        vhadd.u16       q13, q13, q15
1025        vrshrn.i16      d24, q12, #8
1026        vrshrn.i16      d25, q13, #8
1027        vst1.32         {d24[0]}, [r0, :32], r1
1028        vst1.32         {d24[1]}, [r6, :32], r1
1029        subs            r4,  r4,  #4
1030        vst1.32         {d25[0]}, [r0, :32], r1
1031        vst1.32         {d25[1]}, [r6, :32], r1
1032        bgt             4b
1033        pop             {r4-r10, pc}
103480:
1035        vld1.8          {d16}, [r8]       // top
1036        vld1.8          {d18}, [r10, :64] // weights_hor
1037        sub             r2,  r2,  #2
1038        mov             r7,  #-2
1039        vdup.8          q3,  d16[7]   // right
1040        vsubl.u8        q8,  d16, d4  // top-bottom
1041        vmovl.u8        q9,  d18      // weights_hor
10428:
1043        vld2.8          {d0[],  d1[]},  [r2,  :16], r7 // left
1044        vld2.8          {d20[], d22[]}, [r12, :16]!    // weights_ver
1045        vshll.i8        q12, d6,  #8  // right*256
1046        vshll.i8        q13, d6,  #8
1047        vshll.i8        q14, d4,  #8  // bottom*256
1048        vshll.i8        q15, d4,  #8
1049        vsubl.u8        q1,  d0,  d6  // left-right (left flipped)
1050        vsubl.u8        q0,  d1,  d6
1051        vmovl.u8        q10, d20      // weights_ver
1052        vmovl.u8        q11, d22
1053        vmla.i16        q12, q0,  q9  // right*256  + (left-right)*weights_hor
1054        vmla.i16        q13, q1,  q9
1055        vmla.i16        q14, q8,  q10 // bottom*256 + (top-bottom)*weights_ver
1056        vmla.i16        q15, q8,  q11
1057        vhadd.u16       q12, q12, q14
1058        vhadd.u16       q13, q13, q15
1059        vrshrn.i16      d24, q12, #8
1060        vrshrn.i16      d25, q13, #8
1061        subs            r4,  r4,  #2
1062        vst1.8          {d24}, [r0, :64], r1
1063        vst1.8          {d25}, [r6, :64], r1
1064        bgt             8b
1065        pop             {r4-r10, pc}
1066160:
1067320:
1068640:
1069        add             lr,  r2,  r3
1070        sub             r2,  r2,  #2
1071        mov             r7,  #-2
1072        vld1.8          {d6[], d7[]}, [lr] // right
1073        sub             r1,  r1,  r3
1074        mov             r9,  r3
1075
10761:
1077        vld2.8          {d0[],  d1[]},  [r2,  :16], r7 // left
1078        vld2.8          {d20[], d22[]}, [r12, :16]!    // weights_ver
1079        vsubl.u8        q1,  d0,  d6  // left-right (left flipped)
1080        vsubl.u8        q0,  d1,  d6
1081        vmovl.u8        q10, d20      // weights_ver
1082        vmovl.u8        q11, d22
10832:
1084        vld1.8          {d16}, [r8]!       // top
1085        vld1.8          {d18}, [r10, :64]! // weights_hor
1086        vshll.i8        q12, d6,  #8  // right*256
1087        vshll.i8        q13, d6,  #8
1088        vmovl.u8        q9,  d18      // weights_hor
1089        vshll.i8        q14, d4,  #8  // bottom*256
1090        vshll.i8        q15, d4,  #8
1091        vsubl.u8        q8,  d16, d4  // top-bottom
1092        vmla.i16        q12, q0,  q9  // right*256  + (left-right)*weights_hor
1093        vmla.i16        q13, q1,  q9
1094        vmla.i16        q14, q8,  q10 // bottom*256 + (top-bottom)*weights_ver
1095        vmla.i16        q15, q8,  q11
1096        vhadd.u16       q12, q12, q14
1097        vhadd.u16       q13, q13, q15
1098        vrshrn.i16      d24, q12, #8
1099        vrshrn.i16      d25, q13, #8
1100        subs            r3,  r3,  #8
1101        vst1.8          {d24}, [r0, :64]!
1102        vst1.8          {d25}, [r6, :64]!
1103        bgt             2b
1104        subs            r4,  r4,  #2
1105        ble             9f
1106        sub             r8,  r8,  r9
1107        sub             r10, r10, r9
1108        add             r0,  r0,  r1
1109        add             r6,  r6,  r1
1110        mov             r3,  r9
1111        b               1b
11129:
1113        pop             {r4-r10, pc}
1114endfunc
1115
1116// void ipred_smooth_v_8bpc_neon(pixel *dst, const ptrdiff_t stride,
1117//                               const pixel *const topleft,
1118//                               const int width, const int height, const int a,
1119//                               const int max_width, const int max_height);
1120function ipred_smooth_v_8bpc_neon, export=1
1121        push            {r4-r7, lr}
1122        ldr             r4,  [sp, #20]
1123        movrel          r7,  X(sm_weights)
1124        add             r7,  r7,  r4
1125        clz             lr,  r3
1126        adr             r5,  L(ipred_smooth_v_tbl)
1127        sub             r12, r2,  r4
1128        sub             lr,  lr,  #25
1129        ldr             lr,  [r5, lr, lsl #2]
1130        vld1.8          {d4[]},  [r12] // bottom
1131        add             r2,  r2,  #1
1132        add             r5,  r5,  lr
1133        add             r6,  r0,  r1
1134        lsl             r1,  r1,  #1
1135        bx              r5
1136
1137        .align 2
1138L(ipred_smooth_v_tbl):
1139        .word 640f - L(ipred_smooth_v_tbl) + CONFIG_THUMB
1140        .word 320f - L(ipred_smooth_v_tbl) + CONFIG_THUMB
1141        .word 160f - L(ipred_smooth_v_tbl) + CONFIG_THUMB
1142        .word 80f  - L(ipred_smooth_v_tbl) + CONFIG_THUMB
1143        .word 40f  - L(ipred_smooth_v_tbl) + CONFIG_THUMB
1144
114540:
1146        vld1.32         {d6[]}, [r2]  // top
1147        vsubl.u8        q3,  d6,  d4  // top-bottom
11484:
1149        vld4.8          {d16[], d17[], d18[], d19[]}, [r7, :32]! // weights_ver
1150        vshll.i8        q10, d4,  #8  // bottom*256
1151        vshll.i8        q11, d4,  #8
1152        vzip.32         d16, d17      // weights_ver
1153        vzip.32         d18, d19
1154        vmovl.u8        q8,  d16      // weights_ver
1155        vmovl.u8        q9,  d18
1156        subs            r4,  r4,  #4
1157        vmla.i16        q10, q3,  q8  // bottom*256 + (top-bottom)*weights_ver
1158        vmla.i16        q11, q3,  q9
1159        vrshrn.i16      d20, q10, #8
1160        vrshrn.i16      d21, q11, #8
1161        vst1.32         {d20[0]}, [r0, :32], r1
1162        vst1.32         {d20[1]}, [r6, :32], r1
1163        vst1.32         {d21[0]}, [r0, :32], r1
1164        vst1.32         {d21[1]}, [r6, :32], r1
1165        bgt             4b
1166        pop             {r4-r7, pc}
116780:
1168        vld1.8          {d6}, [r2]    // top
1169        vsubl.u8        q3,  d6,  d4  // top-bottom
11708:
1171        vld4.8          {d16[], d18[], d20[], d22[]}, [r7, :32]! // weights_ver
1172        vshll.i8        q12, d4,  #8  // bottom*256
1173        vshll.i8        q13, d4,  #8
1174        vshll.i8        q14, d4,  #8
1175        vshll.i8        q15, d4,  #8
1176        vmovl.u8        q8,  d16      // weights_ver
1177        vmovl.u8        q9,  d18
1178        vmovl.u8        q10, d20
1179        vmovl.u8        q11, d22
1180        vmla.i16        q12, q3,  q8  // bottom*256 + (top-bottom)*weights_ver
1181        vmla.i16        q13, q3,  q9
1182        vmla.i16        q14, q3,  q10
1183        vmla.i16        q15, q3,  q11
1184        vrshrn.i16      d24, q12, #8
1185        vrshrn.i16      d25, q13, #8
1186        vrshrn.i16      d26, q14, #8
1187        vrshrn.i16      d27, q15, #8
1188        vst1.8          {d24}, [r0, :64], r1
1189        vst1.8          {d25}, [r6, :64], r1
1190        subs            r4,  r4,  #4
1191        vst1.8          {d26}, [r0, :64], r1
1192        vst1.8          {d27}, [r6, :64], r1
1193        bgt             8b
1194        pop             {r4-r7, pc}
1195160:
1196320:
1197640:
1198        vpush           {q4-q7}
1199        // Set up pointers for four rows in parallel; r0, r6, r5, lr
1200        add             r5,  r0,  r1
1201        add             lr,  r6,  r1
1202        lsl             r1,  r1,  #1
1203        sub             r1,  r1,  r3
1204        mov             r12, r3
1205
12061:
1207        vld4.8          {d8[], d10[], d12[], d14[]}, [r7, :32]! // weights_ver
1208        vmovl.u8        q4,  d8       // weights_ver
1209        vmovl.u8        q5,  d10
1210        vmovl.u8        q6,  d12
1211        vmovl.u8        q7,  d14
12122:
1213        vld1.8          {q3}, [r2]!   // top
1214        vshll.i8        q8,  d4,  #8  // bottom*256
1215        vshll.i8        q9,  d4,  #8
1216        vshll.i8        q10, d4,  #8
1217        vshll.i8        q11, d4,  #8
1218        vsubl.u8        q0,  d6,  d4  // top-bottom
1219        vsubl.u8        q1,  d7,  d4
1220        vshll.i8        q12, d4,  #8
1221        vshll.i8        q13, d4,  #8
1222        vshll.i8        q14, d4,  #8
1223        vshll.i8        q15, d4,  #8
1224        vmla.i16        q8,  q0,  q4  // bottom*256 + (top-bottom)*weights_ver
1225        vmla.i16        q9,  q1,  q4
1226        vmla.i16        q10, q0,  q5
1227        vmla.i16        q11, q1,  q5
1228        vmla.i16        q12, q0,  q6  // bottom*256 + (top-bottom)*weights_ver
1229        vmla.i16        q13, q1,  q6
1230        vmla.i16        q14, q0,  q7
1231        vmla.i16        q15, q1,  q7
1232        vrshrn.i16      d16, q8,  #8
1233        vrshrn.i16      d17, q9,  #8
1234        vrshrn.i16      d18, q10, #8
1235        vrshrn.i16      d19, q11, #8
1236        vrshrn.i16      d20, q12, #8
1237        vrshrn.i16      d21, q13, #8
1238        vrshrn.i16      d22, q14, #8
1239        vrshrn.i16      d23, q15, #8
1240        subs            r3,  r3,  #16
1241        vst1.8          {q8},  [r0, :128]!
1242        vst1.8          {q9},  [r6, :128]!
1243        vst1.8          {q10}, [r5, :128]!
1244        vst1.8          {q11}, [lr, :128]!
1245        bgt             2b
1246        subs            r4,  r4,  #4
1247        ble             9f
1248        sub             r2,  r2,  r12
1249        add             r0,  r0,  r1
1250        add             r6,  r6,  r1
1251        add             r5,  r5,  r1
1252        add             lr,  lr,  r1
1253        mov             r3,  r12
1254        b               1b
12559:
1256        vpop            {q4-q7}
1257        pop             {r4-r7, pc}
1258endfunc
1259
1260// void ipred_smooth_h_8bpc_neon(pixel *dst, const ptrdiff_t stride,
1261//                               const pixel *const topleft,
1262//                               const int width, const int height, const int a,
1263//                               const int max_width, const int max_height);
1264function ipred_smooth_h_8bpc_neon, export=1
1265        push            {r4-r8, lr}
1266        ldr             r4,  [sp, #24]
1267        movrel          r8,  X(sm_weights)
1268        add             r8,  r8,  r3
1269        clz             lr,  r3
1270        adr             r5,  L(ipred_smooth_h_tbl)
1271        add             r12, r2,  r3
1272        sub             lr,  lr,  #25
1273        ldr             lr,  [r5, lr, lsl #2]
1274        vld1.8          {d4[]},  [r12] // right
1275        add             r5,  r5,  lr
1276        add             r6,  r0,  r1
1277        lsl             r1,  r1,  #1
1278        bx              r5
1279
1280        .align 2
1281L(ipred_smooth_h_tbl):
1282        .word 640f - L(ipred_smooth_h_tbl) + CONFIG_THUMB
1283        .word 320f - L(ipred_smooth_h_tbl) + CONFIG_THUMB
1284        .word 160f - L(ipred_smooth_h_tbl) + CONFIG_THUMB
1285        .word 80f  - L(ipred_smooth_h_tbl) + CONFIG_THUMB
1286        .word 40f  - L(ipred_smooth_h_tbl) + CONFIG_THUMB
1287
128840:
1289        vld1.32         {d6[]}, [r8, :32] // weights_hor
1290        sub             r2,  r2,  #4
1291        mov             r7,  #-4
1292        vmovl.u8        q3,  d6       // weights_hor
12934:
1294        vld4.8          {d0[], d1[], d2[], d3[]},  [r2, :32], r7 // left
1295        vshll.i8        q8,  d4,  #8  // right*256
1296        vshll.i8        q9,  d4,  #8
1297        vzip.32         d3,  d2       // left, flipped
1298        vzip.32         d1,  d0
1299        vsubl.u8        q1,  d3,  d4  // left-right
1300        vsubl.u8        q0,  d1,  d4
1301        subs            r4,  r4,  #4
1302        vmla.i16        q8,  q1,  q3  // right*256  + (left-right)*weights_hor
1303        vmla.i16        q9,  q0,  q3
1304        vrshrn.i16      d16, q8,  #8
1305        vrshrn.i16      d17, q9,  #8
1306        vst1.32         {d16[0]}, [r0, :32], r1
1307        vst1.32         {d16[1]}, [r6, :32], r1
1308        vst1.32         {d17[0]}, [r0, :32], r1
1309        vst1.32         {d17[1]}, [r6, :32], r1
1310        bgt             4b
1311        pop             {r4-r8, pc}
131280:
1313        vld1.8          {d6}, [r8, :64] // weights_hor
1314        sub             r2,  r2,  #4
1315        mov             r7,  #-4
1316        vmovl.u8        q3,  d6       // weights_hor
13178:
1318        vld4.8          {d16[], d18[], d20[], d22[]},  [r2, :32], r7 // left
1319        vshll.i8        q12, d4,  #8  // right*256
1320        vshll.i8        q13, d4,  #8
1321        vshll.i8        q14, d4,  #8
1322        vshll.i8        q15, d4,  #8
1323        vsubl.u8        q11, d22, d4  // left-right
1324        vsubl.u8        q10, d20, d4
1325        vsubl.u8        q9,  d18, d4
1326        vsubl.u8        q8,  d16, d4
1327        vmla.i16        q12, q11, q3  // right*256  + (left-right)*weights_hor
1328        vmla.i16        q13, q10, q3  // (left flipped)
1329        vmla.i16        q14, q9,  q3
1330        vmla.i16        q15, q8,  q3
1331        vrshrn.i16      d24, q12, #8
1332        vrshrn.i16      d25, q13, #8
1333        vrshrn.i16      d26, q14, #8
1334        vrshrn.i16      d27, q15, #8
1335        vst1.8          {d24}, [r0, :64], r1
1336        vst1.8          {d25}, [r6, :64], r1
1337        subs            r4,  r4,  #4
1338        vst1.8          {d26}, [r0, :64], r1
1339        vst1.8          {d27}, [r6, :64], r1
1340        bgt             8b
1341        pop             {r4-r8, pc}
1342160:
1343320:
1344640:
1345        vpush           {q4-q7}
1346        sub             r2,  r2,  #4
1347        mov             r7,  #-4
1348        // Set up pointers for four rows in parallel; r0, r6, r5, lr
1349        add             r5,  r0,  r1
1350        add             lr,  r6,  r1
1351        lsl             r1,  r1,  #1
1352        sub             r1,  r1,  r3
1353        mov             r12, r3
1354
13551:
1356        vld4.8          {d8[], d10[], d12[], d14[]},  [r2, :32], r7 // left
1357        vsubl.u8        q4,  d8,  d4  // left-right
1358        vsubl.u8        q5,  d10, d4
1359        vsubl.u8        q6,  d12, d4
1360        vsubl.u8        q7,  d14, d4
13612:
1362        vld1.8          {q1}, [r8, :128]! // weights_hor
1363        vshll.i8        q8,  d4,  #8  // right*256
1364        vshll.i8        q9,  d4,  #8
1365        vshll.i8        q10, d4,  #8
1366        vshll.i8        q11, d4,  #8
1367        vmovl.u8        q0,  d2       // weights_hor
1368        vmovl.u8        q1,  d3
1369        vshll.i8        q12, d4,  #8
1370        vshll.i8        q13, d4,  #8
1371        vshll.i8        q14, d4,  #8
1372        vshll.i8        q15, d4,  #8
1373        vmla.i16        q8,  q7,  q0  // right*256  + (left-right)*weights_hor
1374        vmla.i16        q9,  q7,  q1  // (left flipped)
1375        vmla.i16        q10, q6,  q0
1376        vmla.i16        q11, q6,  q1
1377        vmla.i16        q12, q5,  q0
1378        vmla.i16        q13, q5,  q1
1379        vmla.i16        q14, q4,  q0
1380        vmla.i16        q15, q4,  q1
1381        vrshrn.i16      d16, q8,  #8
1382        vrshrn.i16      d17, q9,  #8
1383        vrshrn.i16      d18, q10, #8
1384        vrshrn.i16      d19, q11, #8
1385        vrshrn.i16      d20, q12, #8
1386        vrshrn.i16      d21, q13, #8
1387        vrshrn.i16      d22, q14, #8
1388        vrshrn.i16      d23, q15, #8
1389        subs            r3,  r3,  #16
1390        vst1.8          {q8},  [r0, :128]!
1391        vst1.8          {q9},  [r6, :128]!
1392        vst1.8          {q10}, [r5, :128]!
1393        vst1.8          {q11}, [lr, :128]!
1394        bgt             2b
1395        subs            r4,  r4,  #4
1396        ble             9f
1397        sub             r8,  r8,  r12
1398        add             r0,  r0,  r1
1399        add             r6,  r6,  r1
1400        add             r5,  r5,  r1
1401        add             lr,  lr,  r1
1402        mov             r3,  r12
1403        b               1b
14049:
1405        vpop            {q4-q7}
1406        pop             {r4-r8, pc}
1407endfunc
1408
1409// void ipred_filter_8bpc_neon(pixel *dst, const ptrdiff_t stride,
1410//                             const pixel *const topleft,
1411//                             const int width, const int height, const int filt_idx,
1412//                             const int max_width, const int max_height);
1413function ipred_filter_8bpc_neon, export=1
1414        push            {r4-r8, lr}
1415        movw            r12, #511
1416        ldrd            r4,  r5,  [sp, #24]
1417        and             r5,  r5,  r12 // 511
1418        movrel          r6,  X(filter_intra_taps)
1419        lsl             r5,  r5,  #6
1420        add             r6,  r6,  r5
1421        vld1.8          {d20, d21, d22, d23}, [r6, :128]!
1422        clz             lr,  r3
1423        adr             r5,  L(ipred_filter_tbl)
1424        vld1.8          {d27, d28, d29}, [r6, :64]
1425        sub             lr,  lr,  #26
1426        ldr             lr,  [r5, lr, lsl #2]
1427        vmovl.s8        q8,  d20
1428        vmovl.s8        q9,  d21
1429        add             r5,  r5,  lr
1430        vmovl.s8        q10, d22
1431        vmovl.s8        q11, d23
1432        add             r6,  r0,  r1
1433        lsl             r1,  r1,  #1
1434        vmovl.s8        q12, d27
1435        vmovl.s8        q13, d28
1436        vmovl.s8        q14, d29
1437        add             r8,  r2,  #1
1438        sub             r2,  r2,  #2
1439        mov             r7,  #-2
1440        bx              r5
1441
1442        .align 2
1443L(ipred_filter_tbl):
1444        .word 320f - L(ipred_filter_tbl) + CONFIG_THUMB
1445        .word 160f - L(ipred_filter_tbl) + CONFIG_THUMB
1446        .word 80f  - L(ipred_filter_tbl) + CONFIG_THUMB
1447        .word 40f  - L(ipred_filter_tbl) + CONFIG_THUMB
1448
144940:
1450        vld1.32         {d0[]}, [r8]     // top (0-3)
1451        vmovl.u8        q0,  d0          // top (0-3)
14524:
1453        vld1.32         {d2[]}, [r2], r7 // left (0-1) + topleft (2)
1454        vmul.i16        q2,  q9,  d0[0]  // p1(top[0]) * filter(1)
1455        vmla.i16        q2,  q10, d0[1]  // p2(top[1]) * filter(2)
1456        vmla.i16        q2,  q11, d0[2]  // p3(top[2]) * filter(3)
1457        vmovl.u8        q1,  d2          // left (0-1) + topleft (2)
1458        vmla.i16        q2,  q12, d0[3]  // p4(top[3]) * filter(4)
1459        vmla.i16        q2,  q8,  d2[2]  // p0(topleft) * filter(0)
1460        vmla.i16        q2,  q13, d2[1]  // p5(left[0]) * filter(5)
1461        vmla.i16        q2,  q14, d2[0]  // p6(left[1]) * filter(6)
1462        vqrshrun.s16    d4,  q2,  #4
1463        subs            r4,  r4,  #2
1464        vst1.32         {d4[0]}, [r0, :32], r1
1465        vmovl.u8        q0,  d4
1466        vst1.32         {d4[1]}, [r6, :32], r1
1467        vmov            d0,  d1          // move top from [4-7] to [0-3]
1468        bgt             4b
1469        pop             {r4-r8, pc}
147080:
1471        vld1.8          {d0},  [r8]      // top (0-7)
1472        vmovl.u8        q0,  d0          // top (0-7)
14738:
1474        vld1.32         {d2[]}, [r2], r7 // left (0-1) + topleft (2)
1475        vmul.i16        q2,  q9,  d0[0]  // p1(top[0]) * filter(1)
1476        vmla.i16        q2,  q10, d0[1]  // p2(top[1]) * filter(2)
1477        vmla.i16        q2,  q11, d0[2]  // p3(top[2]) * filter(3)
1478        vmovl.u8        q1,  d2          // left (0-1) + topleft (2)
1479        vmla.i16        q2,  q12, d0[3]  // p4(top[3]) * filter(4)
1480        vmla.i16        q2,  q8,  d2[2]  // p0(topleft) * filter(0)
1481        vmla.i16        q2,  q13, d2[1]  // p5(left[0]) * filter(5)
1482        vmla.i16        q2,  q14, d2[0]  // p6(left[1]) * filter(6)
1483        vmul.i16        q3,  q9,  d1[0]  // p1(top[0]) * filter(1)
1484        vmla.i16        q3,  q10, d1[1]  // p2(top[1]) * filter(2)
1485        vmla.i16        q3,  q11, d1[2]  // p3(top[2]) * filter(3)
1486        vqrshrun.s16    d4,  q2,  #4
1487        vmovl.u8        q1,  d4          // first block, in 16 bit
1488        vmla.i16        q3,  q12, d1[3]  // p4(top[3]) * filter(4)
1489        vmla.i16        q3,  q8,  d0[3]  // p0(topleft) * filter(0)
1490        vmla.i16        q3,  q13, d2[3]  // p5(left[0]) * filter(5)
1491        vmla.i16        q3,  q14, d3[3]  // p6(left[1]) * filter(6)
1492        vqrshrun.s16    d5,  q3,  #4
1493        vzip.32         d4,  d5
1494        subs            r4,  r4,  #2
1495        vst1.8          {d4}, [r0, :64], r1
1496        vmovl.u8        q0,  d5
1497        vst1.8          {d5}, [r6, :64], r1
1498        bgt             8b
1499        pop             {r4-r8, pc}
1500160:
1501320:
1502        vpush           {q4-q5}
1503        sub             r1,  r1,  r3
1504        mov             lr,  r3
1505
15061:
1507        vld1.32         {d0[]}, [r2], r7 // left (0-1) + topleft (2)
1508        vmovl.u8        q0,  d0          // left (0-1) + topleft (2)
15092:
1510        vld1.8          {q2}, [r8]!      // top(0-15)
1511        vmul.i16        q3,  q8,  d0[2]  // p0(topleft) * filter(0)
1512        vmla.i16        q3,  q13, d0[1]  // p5(left[0]) * filter(5)
1513        vmovl.u8        q1,  d4          // top(0-7)
1514        vmovl.u8        q2,  d5          // top(8-15)
1515        vmla.i16        q3,  q14, d0[0]  // p6(left[1]) * filter(6)
1516        vmla.i16        q3,  q9,  d2[0]  // p1(top[0]) * filter(1)
1517        vmla.i16        q3,  q10, d2[1]  // p2(top[1]) * filter(2)
1518        vmla.i16        q3,  q11, d2[2]  // p3(top[2]) * filter(3)
1519        vmla.i16        q3,  q12, d2[3]  // p4(top[3]) * filter(4)
1520
1521        vmul.i16        q4,  q9,  d3[0]  // p1(top[0]) * filter(1)
1522        vmla.i16        q4,  q10, d3[1]  // p2(top[1]) * filter(2)
1523        vmla.i16        q4,  q11, d3[2]  // p3(top[2]) * filter(3)
1524        vqrshrun.s16    d6,  q3,  #4
1525        vmovl.u8        q0,  d6          // first block, in 16 bit
1526        vmla.i16        q4,  q12, d3[3]  // p4(top[3]) * filter(4)
1527        vmla.i16        q4,  q8,  d2[3]  // p0(topleft) * filter(0)
1528        vmla.i16        q4,  q13, d0[3]  // p5(left[0]) * filter(5)
1529        vmla.i16        q4,  q14, d1[3]  // p6(left[1]) * filter(6)
1530
1531        vmul.i16        q5,  q9,  d4[0]  // p1(top[0]) * filter(1)
1532        vmla.i16        q5,  q10, d4[1]  // p2(top[1]) * filter(2)
1533        vmla.i16        q5,  q11, d4[2]  // p3(top[2]) * filter(3)
1534        vqrshrun.s16    d7,  q4,  #4
1535        vmovl.u8        q0,  d7          // second block, in 16 bit
1536        vmla.i16        q5,  q12, d4[3]  // p4(top[3]) * filter(4)
1537        vmla.i16        q5,  q8,  d3[3]  // p0(topleft) * filter(0)
1538        vmla.i16        q5,  q13, d0[3]  // p5(left[0]) * filter(5)
1539        vmla.i16        q5,  q14, d1[3]  // p6(left[1]) * filter(6)
1540
1541        vmul.i16        q15, q9,  d5[0]  // p1(top[0]) * filter(1)
1542        vmla.i16        q15, q10, d5[1]  // p2(top[1]) * filter(2)
1543        vmla.i16        q15, q11, d5[2]  // p3(top[2]) * filter(3)
1544        vqrshrun.s16    d8,  q5,  #4
1545        vmovl.u8        q0,  d8          // third block, in 16 bit
1546        vmov.u8         r12, d5[6]
1547        vmla.i16        q15, q12, d5[3]  // p4(top[3]) * filter(4)
1548        vmla.i16        q15, q8,  d4[3]  // p0(topleft) * filter(0)
1549        vmla.i16        q15, q13, d0[3]  // p5(left[0]) * filter(5)
1550        vmla.i16        q15, q14, d1[3]  // p6(left[1]) * filter(6)
1551        vmov.8          d0[4], r12
1552
1553        subs            r3,  r3,  #16
1554        vqrshrun.s16    d9,  q15, #4
1555
1556        vst4.32         {d6[0], d7[0], d8[0], d9[0]}, [r0, :128]!
1557        vst4.32         {d6[1], d7[1], d8[1], d9[1]}, [r6, :128]!
1558        ble             8f
1559        vmov.u8         r12, d9[7]
1560        vmov.8          d0[0], r12
1561        vmov.u8         r12, d9[3]
1562        vmov.8          d0[2], r12
1563        b               2b
15648:
1565        subs            r4,  r4,  #2
1566
1567        ble             9f
1568        sub             r8,  r6,  lr
1569        add             r0,  r0,  r1
1570        add             r6,  r6,  r1
1571        mov             r3,  lr
1572        b               1b
15739:
1574        vpop            {q4-q5}
1575        pop             {r4-r8, pc}
1576endfunc
1577
1578// void pal_pred_8bpc_neon(pixel *dst, const ptrdiff_t stride,
1579//                         const pixel *const pal, const uint8_t *idx,
1580//                         const int w, const int h);
1581function pal_pred_8bpc_neon, export=1
1582        push            {r4-r5, lr}
1583        ldrd            r4,  r5,  [sp, #12]
1584        vld1.8          {d0}, [r2, :64]
1585        clz             lr,  r4
1586        adr             r12, L(pal_pred_tbl)
1587        sub             lr,  lr,  #25
1588        vmov.i8         q15, #7
1589        ldr             lr,  [r12, lr, lsl #2]
1590        add             r12, r12, lr
1591        add             r2,  r0,  r1
1592        bx              r12
1593
1594        .align 2
1595L(pal_pred_tbl):
1596        .word 640f - L(pal_pred_tbl) + CONFIG_THUMB
1597        .word 320f - L(pal_pred_tbl) + CONFIG_THUMB
1598        .word 160f - L(pal_pred_tbl) + CONFIG_THUMB
1599        .word 80f  - L(pal_pred_tbl) + CONFIG_THUMB
1600        .word 40f  - L(pal_pred_tbl) + CONFIG_THUMB
1601
160240:
1603        lsl             r1,  r1,  #1
16044:
1605        vld1.8          {d2}, [r3, :64]!
1606        subs            r5,  r5,  #4
1607        vshr.u8         d3,  d2,  #4
1608        vand.u8         d2,  d2,  d30
1609        vzip.8          d2,  d3
1610        vtbl.8          d2, {d0}, d2
1611        vtbl.8          d3, {d0}, d3
1612        vst1.32         {d2[0]}, [r0, :32], r1
1613        vst1.32         {d2[1]}, [r2, :32], r1
1614        vst1.32         {d3[0]}, [r0, :32], r1
1615        vst1.32         {d3[1]}, [r2, :32], r1
1616        bgt             4b
1617        pop             {r4-r5, pc}
161880:
1619        lsl             r1,  r1,  #1
16208:
1621        vld1.8          {q1}, [r3, :64]!
1622        subs            r5,  r5,  #4
1623        vshr.u8         q2,  q1,  #4
1624        vand.u8         q1,  q1,  q15
1625        vzip.8          q1,  q2
1626        vtbl.8          d2, {d0}, d2
1627        vtbl.8          d3, {d0}, d3
1628        vst1.8          {d2}, [r0, :64], r1
1629        vtbl.8          d4, {d0}, d4
1630        vst1.8          {d3}, [r2, :64], r1
1631        vtbl.8          d5, {d0}, d5
1632        vst1.8          {d4}, [r0, :64], r1
1633        vst1.8          {d5}, [r2, :64], r1
1634        bgt             8b
1635        pop             {r4-r5, pc}
1636160:
1637        lsl             r1,  r1,  #1
163816:
1639        vld1.8          {q10, q11}, [r3, :64]!
1640        subs            r5,  r5,  #4
1641        vand.u8         q8,  q10, q15
1642        vshr.u8         q9,  q10, #4
1643        vand.u8         q10, q11, q15
1644        vshr.u8         q11, q11, #4
1645        vzip.8          q8,  q9
1646        vzip.8          q10, q11
1647        vtbl.8          d16, {d0}, d16
1648        vtbl.8          d17, {d0}, d17
1649        vtbl.8          d18, {d0}, d18
1650        vtbl.8          d19, {d0}, d19
1651        vtbl.8          d20, {d0}, d20
1652        vtbl.8          d21, {d0}, d21
1653        vst1.8          {q8},  [r0, :128], r1
1654        vtbl.8          d22, {d0}, d22
1655        vst1.8          {q9},  [r2, :128], r1
1656        vtbl.8          d23, {d0}, d23
1657        vst1.8          {q10}, [r0, :128], r1
1658        vst1.8          {q11}, [r2, :128], r1
1659        bgt             16b
1660        pop             {r4-r5, pc}
1661320:
1662        lsl             r1,  r1,  #1
166332:
1664        vld1.8          {q10, q11}, [r3, :64]!
1665        subs            r5,  r5,  #2
1666        vand.u8         q8,  q10, q15
1667        vshr.u8         q9,  q10, #4
1668        vand.u8         q10, q11, q15
1669        vshr.u8         q11, q11, #4
1670        vzip.8          q8,  q9
1671        vzip.8          q10, q11
1672        vtbl.8          d16, {d0}, d16
1673        vtbl.8          d17, {d0}, d17
1674        vtbl.8          d18, {d0}, d18
1675        vtbl.8          d19, {d0}, d19
1676        vtbl.8          d20, {d0}, d20
1677        vtbl.8          d21, {d0}, d21
1678        vst1.8          {q8,  q9},  [r0, :128], r1
1679        vtbl.8          d22, {d0}, d22
1680        vtbl.8          d23, {d0}, d23
1681        vst1.8          {q10, q11}, [r2, :128], r1
1682        bgt             32b
1683        pop             {r4-r5, pc}
1684640:
1685        sub             r1,  r1,  #32
168664:
1687        vld1.8          {q10, q11}, [r3, :64]!
1688        subs            r5,  r5,  #1
1689        vand.u8         q8,  q10, q15
1690        vshr.u8         q9,  q10, #4
1691        vand.u8         q10, q11, q15
1692        vshr.u8         q11, q11, #4
1693        vzip.8          q8,  q9
1694        vzip.8          q10, q11
1695        vtbl.8          d16, {d0}, d16
1696        vtbl.8          d17, {d0}, d17
1697        vtbl.8          d18, {d0}, d18
1698        vtbl.8          d19, {d0}, d19
1699        vtbl.8          d20, {d0}, d20
1700        vtbl.8          d21, {d0}, d21
1701        vst1.8          {q8,  q9},  [r0, :128]!
1702        vtbl.8          d22, {d0}, d22
1703        vtbl.8          d23, {d0}, d23
1704        vst1.8          {q10, q11}, [r0, :128], r1
1705        bgt             64b
1706        pop             {r4-r5, pc}
1707endfunc
1708
1709// void ipred_cfl_128_8bpc_neon(pixel *dst, const ptrdiff_t stride,
1710//                              const pixel *const topleft,
1711//                              const int width, const int height,
1712//                              const int16_t *ac, const int alpha);
1713function ipred_cfl_128_8bpc_neon, export=1
1714        push            {r4-r8, lr}
1715        ldrd            r4,  r5,  [sp, #24]
1716        ldr             r6,  [sp, #32]
1717        clz             lr,  r3
1718        adr             r12, L(ipred_cfl_128_tbl)
1719        sub             lr,  lr,  #26
1720        ldr             lr,  [r12, lr, lsl #2]
1721        vmov.i16        q0,  #128     // dc
1722        vdup.i16        q1,  r6       // alpha
1723        add             r12, r12, lr
1724        add             r6,  r0,  r1
1725        lsl             r1,  r1,  #1
1726        bx              r12
1727
1728        .align 2
1729L(ipred_cfl_128_tbl):
1730L(ipred_cfl_splat_tbl):
1731        .word L(ipred_cfl_splat_w16) - L(ipred_cfl_128_tbl) + CONFIG_THUMB
1732        .word L(ipred_cfl_splat_w16) - L(ipred_cfl_128_tbl) + CONFIG_THUMB
1733        .word L(ipred_cfl_splat_w8)  - L(ipred_cfl_128_tbl) + CONFIG_THUMB
1734        .word L(ipred_cfl_splat_w4)  - L(ipred_cfl_128_tbl) + CONFIG_THUMB
1735
1736L(ipred_cfl_splat_w4):
1737        vld1.16         {q2, q3}, [r5, :128]!
1738        vmul.i16        q2,  q2,  q1  // diff = ac * alpha
1739        vmul.i16        q3,  q3,  q1
1740        vshr.s16        q8,  q2,  #15 // sign = diff >> 15
1741        vshr.s16        q9,  q3,  #15
1742        vadd.i16        q2,  q2,  q8  // diff + sign
1743        vadd.i16        q3,  q3,  q9
1744        vrshr.s16       q2,  q2,  #6  // (diff + sign + 32) >> 6 = apply_sign()
1745        vrshr.s16       q3,  q3,  #6
1746        vadd.i16        q2,  q2,  q0  // dc + apply_sign()
1747        vadd.i16        q3,  q3,  q0
1748        vqmovun.s16     d4,  q2       // iclip_pixel(dc + apply_sign())
1749        vqmovun.s16     d5,  q3
1750        vst1.32         {d4[0]}, [r0, :32], r1
1751        vst1.32         {d4[1]}, [r6, :32], r1
1752        subs            r4,  r4,  #4
1753        vst1.32         {d5[0]}, [r0, :32], r1
1754        vst1.32         {d5[1]}, [r6, :32], r1
1755        bgt             L(ipred_cfl_splat_w4)
1756        pop             {r4-r8, pc}
1757L(ipred_cfl_splat_w8):
1758        vld1.16         {q8, q9},   [r5, :128]!
1759        vld1.16         {q10, q11}, [r5, :128]!
1760        vmul.i16        q8,  q8,  q1  // diff = ac * alpha
1761        vmul.i16        q9,  q9,  q1
1762        vmul.i16        q10, q10, q1
1763        vmul.i16        q11, q11, q1
1764        vshr.s16        q12, q8,  #15 // sign = diff >> 15
1765        vshr.s16        q13, q9,  #15
1766        vshr.s16        q14, q10, #15
1767        vshr.s16        q15, q11, #15
1768        vadd.i16        q8,  q8,  q12 // diff + sign
1769        vadd.i16        q9,  q9,  q13
1770        vadd.i16        q10, q10, q14
1771        vadd.i16        q11, q11, q15
1772        vrshr.s16       q8,  q8,  #6  // (diff + sign + 32) >> 6 = apply_sign()
1773        vrshr.s16       q9,  q9,  #6
1774        vrshr.s16       q10, q10, #6
1775        vrshr.s16       q11, q11, #6
1776        vadd.i16        q8,  q8,  q0  // dc + apply_sign()
1777        vadd.i16        q9,  q9,  q0
1778        vadd.i16        q10, q10, q0
1779        vadd.i16        q11, q11, q0
1780        vqmovun.s16     d16, q8       // iclip_pixel(dc + apply_sign())
1781        vqmovun.s16     d17, q9
1782        vqmovun.s16     d18, q10
1783        vqmovun.s16     d19, q11
1784        vst1.8          {d16}, [r0, :64], r1
1785        vst1.8          {d17}, [r6, :64], r1
1786        subs            r4,  r4,  #4
1787        vst1.8          {d18}, [r0, :64], r1
1788        vst1.8          {d19}, [r6, :64], r1
1789        bgt             L(ipred_cfl_splat_w8)
1790        pop             {r4-r8, pc}
1791L(ipred_cfl_splat_w16):
1792        add             r12, r5,  r3, lsl #1
1793        sub             r1,  r1,  r3
1794        mov             lr,  r3
17951:
1796        vld1.16         {q8, q9},   [r5, :128]!
1797        vmul.i16        q8,  q8,  q1  // diff = ac * alpha
1798        vld1.16         {q10, q11}, [r12, :128]!
1799        vmul.i16        q9,  q9,  q1
1800        vmul.i16        q10, q10, q1
1801        vmul.i16        q11, q11, q1
1802        vshr.s16        q12, q8,  #15 // sign = diff >> 15
1803        vshr.s16        q13, q9,  #15
1804        vshr.s16        q14, q10, #15
1805        vshr.s16        q15, q11, #15
1806        vadd.i16        q8,  q8,  q12 // diff + sign
1807        vadd.i16        q9,  q9,  q13
1808        vadd.i16        q10, q10, q14
1809        vadd.i16        q11, q11, q15
1810        vrshr.s16       q8,  q8,  #6  // (diff + sign + 32) >> 6 = apply_sign()
1811        vrshr.s16       q9,  q9,  #6
1812        vrshr.s16       q10, q10, #6
1813        vrshr.s16       q11, q11, #6
1814        vadd.i16        q8,  q8,  q0  // dc + apply_sign()
1815        vadd.i16        q9,  q9,  q0
1816        vadd.i16        q10, q10, q0
1817        vadd.i16        q11, q11, q0
1818        vqmovun.s16     d16, q8       // iclip_pixel(dc + apply_sign())
1819        vqmovun.s16     d17, q9
1820        vqmovun.s16     d18, q10
1821        vqmovun.s16     d19, q11
1822        subs            r3,  r3,  #16
1823        vst1.16         {q8}, [r0, :128]!
1824        vst1.16         {q9}, [r6, :128]!
1825        bgt             1b
1826        subs            r4,  r4,  #2
1827        add             r5,  r5,  lr, lsl #1
1828        add             r12, r12, lr, lsl #1
1829        add             r0,  r0,  r1
1830        add             r6,  r6,  r1
1831        mov             r3,  lr
1832        bgt             1b
1833        pop             {r4-r8, pc}
1834endfunc
1835
1836// void ipred_cfl_top_8bpc_neon(pixel *dst, const ptrdiff_t stride,
1837//                              const pixel *const topleft,
1838//                              const int width, const int height,
1839//                              const int16_t *ac, const int alpha);
1840function ipred_cfl_top_8bpc_neon, export=1
1841        push            {r4-r8, lr}
1842        ldrd            r4,  r5,  [sp, #24]
1843        ldr             r6,  [sp, #32]
1844        clz             lr,  r3
1845        adr             r12, L(ipred_cfl_top_tbl)
1846        sub             lr,  lr,  #26
1847        ldr             lr,  [r12, lr, lsl #2]
1848        vdup.16         q1,  r6   // alpha
1849        add             r2,  r2,  #1
1850        add             r12, r12, lr
1851        add             r6,  r0,  r1
1852        lsl             r1,  r1,  #1
1853        bx              r12
1854
1855        .align 2
1856L(ipred_cfl_top_tbl):
1857        .word 32f - L(ipred_cfl_top_tbl) + CONFIG_THUMB
1858        .word 16f - L(ipred_cfl_top_tbl) + CONFIG_THUMB
1859        .word 8f  - L(ipred_cfl_top_tbl) + CONFIG_THUMB
1860        .word 4f  - L(ipred_cfl_top_tbl) + CONFIG_THUMB
1861
18624:
1863        vld1.32         {d0[]}, [r2]
1864        vpaddl.u8       d0,  d0
1865        vpadd.u16       d0,  d0
1866        vrshr.u16       d0,  d0,  #2
1867        vdup.16         q0,  d0[0]
1868        b               L(ipred_cfl_splat_w4)
18698:
1870        vld1.8          {d0}, [r2]
1871        vpaddl.u8       d0,  d0
1872        vpadd.u16       d0,  d0
1873        vpadd.u16       d0,  d0
1874        vrshr.u16       d0,  d0,  #3
1875        vdup.16         q0,  d0[0]
1876        b               L(ipred_cfl_splat_w8)
187716:
1878        vld1.8          {q0}, [r2]
1879        vaddl.u8        q0,  d0,  d1
1880        vadd.u16        d0,  d0,  d1
1881        vpadd.u16       d0,  d0
1882        vpadd.u16       d0,  d0
1883        vrshr.u16       d0,  d0,  #4
1884        vdup.16         q0,  d0[0]
1885        b               L(ipred_cfl_splat_w16)
188632:
1887        vld1.8          {q2, q3}, [r2]
1888        vaddl.u8        q2,  d4,  d5
1889        vaddl.u8        q3,  d6,  d7
1890        vadd.u16        q0,  q2,  q3
1891        vadd.u16        d0,  d0,  d1
1892        vpadd.u16       d0,  d0
1893        vpadd.u16       d0,  d0
1894        vrshr.u16       d0,  d0,  #5
1895        vdup.16         q0,  d0[0]
1896        b               L(ipred_cfl_splat_w16)
1897endfunc
1898
1899// void ipred_cfl_left_8bpc_neon(pixel *dst, const ptrdiff_t stride,
1900//                               const pixel *const topleft,
1901//                               const int width, const int height,
1902//                               const int16_t *ac, const int alpha);
1903function ipred_cfl_left_8bpc_neon, export=1
1904        push            {r4-r8, lr}
1905        ldrd            r4,  r5,  [sp, #24]
1906        ldr             r6,  [sp, #32]
1907        sub             r2,  r2,  r4
1908        clz             lr,  r3
1909        clz             r8,  r4
1910        adr             r12, L(ipred_cfl_splat_tbl)
1911        adr             r7,  L(ipred_cfl_left_tbl)
1912        sub             lr,  lr,  #26
1913        sub             r8,  r8,  #26
1914        ldr             lr,  [r12, lr, lsl #2]
1915        ldr             r8,  [r7,  r8, lsl #2]
1916        vdup.16         q1,  r6   // alpha
1917        add             r12, r12, lr
1918        add             r7,  r7,  r8
1919        add             r6,  r0,  r1
1920        lsl             r1,  r1,  #1
1921        bx              r7
1922
1923        .align 2
1924L(ipred_cfl_left_tbl):
1925        .word L(ipred_cfl_left_h32) - L(ipred_cfl_left_tbl) + CONFIG_THUMB
1926        .word L(ipred_cfl_left_h16) - L(ipred_cfl_left_tbl) + CONFIG_THUMB
1927        .word L(ipred_cfl_left_h8)  - L(ipred_cfl_left_tbl) + CONFIG_THUMB
1928        .word L(ipred_cfl_left_h4)  - L(ipred_cfl_left_tbl) + CONFIG_THUMB
1929
1930L(ipred_cfl_left_h4):
1931        vld1.32         {d0[]}, [r2, :32]
1932        vpaddl.u8       d0,  d0
1933        vpadd.u16       d0,  d0
1934        vrshr.u16       d0,  d0,  #2
1935        vdup.16         q0,  d0[0]
1936        bx              r12
1937
1938L(ipred_cfl_left_h8):
1939        vld1.8          {d0}, [r2, :64]
1940        vpaddl.u8       d0,  d0
1941        vpadd.u16       d0,  d0
1942        vpadd.u16       d0,  d0
1943        vrshr.u16       d0,  d0,  #3
1944        vdup.16         q0,  d0[0]
1945        bx              r12
1946
1947L(ipred_cfl_left_h16):
1948        vld1.8          {q0}, [r2, :128]
1949        vaddl.u8        q0,  d0,  d1
1950        vadd.u16        d0,  d0,  d1
1951        vpadd.u16       d0,  d0
1952        vpadd.u16       d0,  d0
1953        vrshr.u16       d0,  d0,  #4
1954        vdup.16         q0,  d0[0]
1955        bx              r12
1956
1957L(ipred_cfl_left_h32):
1958        vld1.8          {q2, q3}, [r2, :128]
1959        vaddl.u8        q2,  d4,  d5
1960        vaddl.u8        q3,  d6,  d7
1961        vadd.u16        q0,  q2,  q3
1962        vadd.u16        d0,  d0,  d1
1963        vpadd.u16       d0,  d0
1964        vpadd.u16       d0,  d0
1965        vrshr.u16       d0,  d0,  #5
1966        vdup.16         q0,  d0[0]
1967        bx              r12
1968endfunc
1969
1970// void ipred_cfl_8bpc_neon(pixel *dst, const ptrdiff_t stride,
1971//                          const pixel *const topleft,
1972//                          const int width, const int height,
1973//                          const int16_t *ac, const int alpha);
1974function ipred_cfl_8bpc_neon, export=1
1975        push            {r4-r8, lr}
1976        ldrd            r4,  r5,  [sp, #24]
1977        ldr             r6,  [sp, #32]
1978        sub             r2,  r2,  r4
1979        add             r8,  r3,  r4  // width + height
1980        vdup.16         q1,  r6       // alpha
1981        clz             lr,  r3
1982        clz             r6,  r4
1983        vdup.16         d16, r8       // width + height
1984        adr             r7,  L(ipred_cfl_tbl)
1985        rbit            r8,  r8       // rbit(width + height)
1986        sub             lr,  lr,  #22 // 26 leading bits, minus table offset 4
1987        sub             r6,  r6,  #26
1988        clz             r8,  r8       // ctz(width + height)
1989        ldr             lr,  [r7, lr, lsl #2]
1990        ldr             r6,  [r7, r6, lsl #2]
1991        neg             r8,  r8       // -ctz(width + height)
1992        add             r12, r7,  lr
1993        add             r7,  r7,  r6
1994        vshr.u16        d16, d16, #1  // (width + height) >> 1
1995        vdup.16         d17, r8       // -ctz(width + height)
1996        add             r6,  r0,  r1
1997        lsl             r1,  r1,  #1
1998        bx              r7
1999
2000        .align 2
2001L(ipred_cfl_tbl):
2002        .word L(ipred_cfl_h32) - L(ipred_cfl_tbl) + CONFIG_THUMB
2003        .word L(ipred_cfl_h16) - L(ipred_cfl_tbl) + CONFIG_THUMB
2004        .word L(ipred_cfl_h8)  - L(ipred_cfl_tbl) + CONFIG_THUMB
2005        .word L(ipred_cfl_h4)  - L(ipred_cfl_tbl) + CONFIG_THUMB
2006        .word L(ipred_cfl_w32) - L(ipred_cfl_tbl) + CONFIG_THUMB
2007        .word L(ipred_cfl_w16) - L(ipred_cfl_tbl) + CONFIG_THUMB
2008        .word L(ipred_cfl_w8)  - L(ipred_cfl_tbl) + CONFIG_THUMB
2009        .word L(ipred_cfl_w4)  - L(ipred_cfl_tbl) + CONFIG_THUMB
2010
2011L(ipred_cfl_h4):
2012        vld1.32         {d0[]}, [r2, :32]!
2013        vpaddl.u8       d0,  d0
2014        add             r2,  r2,  #1
2015        vpadd.i16       d0,  d0
2016        bx              r12
2017L(ipred_cfl_w4):
2018        vld1.32         {d1[]},  [r2]
2019        vadd.i16        d0,  d0,  d16
2020        vpaddl.u8       d1,  d1
2021        vpadd.u16       d1,  d1
2022        cmp             r4,  #4
2023        vadd.i16        d0,  d0,  d1
2024        vshl.u16        d0,  d0,  d17
2025        beq             1f
2026        // h = 8/16
2027        movw            lr,  #(0x3334/2)
2028        movw            r8,  #(0x5556/2)
2029        cmp             r4,  #16
2030        it              ne
2031        movne           lr,  r8
2032        vdup.16         d18, lr
2033        vqdmulh.s16     d0,  d0,  d18
20341:
2035        vdup.16         q0,  d0[0]
2036        b               L(ipred_cfl_splat_w4)
2037
2038L(ipred_cfl_h8):
2039        vld1.8          {d0}, [r2, :64]!
2040        vpaddl.u8       d0,  d0
2041        vpadd.i16       d0,  d0
2042        add             r2,  r2,  #1
2043        vpadd.i16       d0,  d0
2044        bx              r12
2045L(ipred_cfl_w8):
2046        vld1.8          {d1}, [r2]
2047        vadd.i16        d0,  d0,  d16
2048        vpaddl.u8       d1,  d1
2049        vpadd.i16       d1,  d1
2050        vpadd.i16       d1,  d1
2051        cmp             r4,  #8
2052        vadd.i16        d0,  d0,  d1
2053        vshl.u16        d0,  d0,  d17
2054        beq             1f
2055        // h = 4/16/32
2056        cmp             r4,  #32
2057        movw            lr,  #(0x3334/2)
2058        movw            r8,  #(0x5556/2)
2059        it              ne
2060        movne           lr,  r8
2061        vdup.16         d18, lr
2062        vqdmulh.s16     d0,  d0,  d18
20631:
2064        vdup.16         q0,  d0[0]
2065        b               L(ipred_cfl_splat_w8)
2066
2067L(ipred_cfl_h16):
2068        vld1.8          {q0}, [r2, :128]!
2069        vaddl.u8        q0,  d0,  d1
2070        vadd.i16        d0,  d0,  d1
2071        vpadd.i16       d0,  d0
2072        add             r2,  r2,  #1
2073        vpadd.i16       d0,  d0
2074        bx              r12
2075L(ipred_cfl_w16):
2076        vld1.8          {q2}, [r2]
2077        vadd.i16        d0,  d0,  d16
2078        vaddl.u8        q2,  d4,  d5
2079        vadd.i16        d4,  d4,  d5
2080        vpadd.i16       d4,  d4
2081        vpadd.i16       d4,  d4
2082        cmp             r4,  #16
2083        vadd.i16        d0,  d0,  d4
2084        vshl.u16        d0,  d0,  d17
2085        beq             1f
2086        // h = 4/8/32/64
2087        tst             r4,  #(32+16+8)  // 16 added to make a consecutive bitmask
2088        movw            lr,  #(0x3334/2)
2089        movw            r8,  #(0x5556/2)
2090        it              ne
2091        movne           lr,  r8
2092        vdup.16         d18, lr
2093        vqdmulh.s16     d0,  d0,  d18
20941:
2095        vdup.16         q0,  d0[0]
2096        b               L(ipred_cfl_splat_w16)
2097
2098L(ipred_cfl_h32):
2099        vld1.8          {q2, q3}, [r2, :128]!
2100        vaddl.u8        q2,  d4,  d5
2101        vaddl.u8        q3,  d6,  d7
2102        vadd.i16        q0,  q2,  q3
2103        vadd.i16        d0,  d0,  d1
2104        vpadd.i16       d0,  d0
2105        add             r2,  r2,  #1
2106        vpadd.i16       d0,  d0
2107        bx              r12
2108L(ipred_cfl_w32):
2109        vld1.8          {q2, q3},  [r2]
2110        vadd.i16        d0,  d0,  d16
2111        vaddl.u8        q2,  d4,  d5
2112        vaddl.u8        q3,  d6,  d7
2113        vadd.i16        q2,  q2,  q3
2114        vadd.i16        d4,  d4,  d5
2115        vpadd.i16       d4,  d4
2116        vpadd.i16       d4,  d4
2117        cmp             r4,  #32
2118        vadd.i16        d0,  d0,  d4
2119        vshl.u16        d0,  d0,  d17
2120        beq             1f
2121        // h = 8/16/64
2122        cmp             r4,  #8
2123        movw            lr,  #(0x3334/2)
2124        movw            r8,  #(0x5556/2)
2125        it              ne
2126        movne           lr,  r8
2127        vdup.16         d18, lr
2128        vqdmulh.s16     d0,  d0,  d18
21291:
2130        vdup.16         q0,  d0[0]
2131        b               L(ipred_cfl_splat_w16)
2132endfunc
2133
2134// void cfl_ac_420_8bpc_neon(int16_t *const ac, const pixel *const ypx,
2135//                           const ptrdiff_t stride, const int w_pad,
2136//                           const int h_pad, const int cw, const int ch);
2137function ipred_cfl_ac_420_8bpc_neon, export=1
2138        push            {r4-r8,lr}
2139        ldrd            r4,  r5,  [sp, #24]
2140        ldr             r6,  [sp, #32]
2141        clz             r8,  r5
2142        lsl             r4,  r4,  #2
2143        adr             r7,  L(ipred_cfl_ac_420_tbl)
2144        sub             r8,  r8,  #27
2145        ldr             r8,  [r7, r8, lsl #2]
2146        vmov.i16        q8,  #0
2147        vmov.i16        q9,  #0
2148        vmov.i16        q10, #0
2149        vmov.i16        q11, #0
2150        add             r7,  r7,  r8
2151        sub             r8,  r6,  r4  // height - h_pad
2152        rbit            lr,  r5       // rbit(width)
2153        rbit            r12, r6       // rbit(height)
2154        clz             lr,  lr       // ctz(width)
2155        clz             r12, r12      // ctz(height)
2156        add             lr,  lr,  r12 // log2sz
2157        add             r12, r1,  r2
2158        vdup.32         d31, lr
2159        lsl             r2,  r2,  #1
2160        vneg.s32        d31, d31      // -log2sz
2161        bx              r7
2162
2163        .align 2
2164L(ipred_cfl_ac_420_tbl):
2165        .word L(ipred_cfl_ac_420_w16) - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB
2166        .word L(ipred_cfl_ac_420_w8)  - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB
2167        .word L(ipred_cfl_ac_420_w4)  - L(ipred_cfl_ac_420_tbl) + CONFIG_THUMB
2168
2169L(ipred_cfl_ac_420_w4):
21701:      // Copy and subsample input
2171        vld1.8          {d0}, [r1,  :64], r2
2172        vld1.8          {d2}, [r12, :64], r2
2173        vld1.8          {d1}, [r1,  :64], r2
2174        vld1.8          {d3}, [r12, :64], r2
2175        vpaddl.u8       q0,  q0
2176        vpaddl.u8       q1,  q1
2177        vadd.i16        q0,  q0,  q1
2178        vshl.i16        q0,  q0,  #1
2179        subs            r8,  r8,  #2
2180        vst1.16         {q0}, [r0, :128]!
2181        vadd.i16        q8,  q8,  q0
2182        bgt             1b
2183        cmp             r4,  #0
2184        vmov            d0,  d1
2185        vmov            d2,  d1
2186        vmov            d3,  d1
2187L(ipred_cfl_ac_420_w4_hpad):
2188        beq             3f // This assumes that all callers already did "cmp r4, #0"
21892:      // Vertical padding (h_pad > 0)
2190        subs            r4,  r4,  #4
2191        vst1.16         {q0, q1}, [r0, :128]!
2192        vadd.i16        q8,  q8,  q0
2193        vadd.i16        q8,  q8,  q1
2194        bgt             2b
21953:
2196L(ipred_cfl_ac_420_w4_calc_subtract_dc):
2197        // Aggregate the sums
2198        vadd.i16        q0,  q8,  q9
2199        vadd.i16        q1,  q10, q11
2200        vpaddl.u16      q0,  q0
2201        vpaddl.u16      q1,  q1
2202        vadd.i32        q0,  q1
2203        vadd.i32        d0,  d0,  d1
2204        vpadd.i32       d0,  d0,  d0  // sum
2205        sub             r0,  r0,  r6, lsl #3
2206        vrshl.u32       d16, d0,  d31 // (sum + (1 << (log2sz - 1))) >>= log2sz
2207        vdup.16         q8,  d16[0]
2208L(ipred_cfl_ac_420_w4_subtract_dc):
22096:      // Subtract dc from ac
2210        vld1.16         {q0, q1}, [r0, :128]
2211        subs            r6,  r6,  #4
2212        vsub.i16        q0,  q0,  q8
2213        vsub.i16        q1,  q1,  q8
2214        vst1.16         {q0, q1}, [r0, :128]!
2215        bgt             6b
2216        pop             {r4-r8, pc}
2217
2218L(ipred_cfl_ac_420_w8):
2219        cmp             r3,  #0
2220        bne             L(ipred_cfl_ac_420_w8_wpad)
22211:      // Copy and subsample input, without padding
2222        vld1.8          {q0}, [r1,  :128], r2
2223        vld1.8          {q1}, [r12, :128], r2
2224        vld1.8          {q2}, [r1,  :128], r2
2225        vpaddl.u8       q0,  q0
2226        vld1.8          {q3}, [r12, :128], r2
2227        vpaddl.u8       q1,  q1
2228        vpaddl.u8       q2,  q2
2229        vpaddl.u8       q3,  q3
2230        vadd.i16        q0,  q0,  q1
2231        vadd.i16        q2,  q2,  q3
2232        vshl.i16        q0,  q0,  #1
2233        vshl.i16        q1,  q2,  #1
2234        subs            r8,  r8,  #2
2235        vst1.16         {q0, q1}, [r0, :128]!
2236        vadd.i16        q8,  q8,  q0
2237        vadd.i16        q9,  q9,  q1
2238        bgt             1b
2239        cmp             r4,  #0
2240        vmov            q0,  q1
2241        b               L(ipred_cfl_ac_420_w8_hpad)
2242
2243L(ipred_cfl_ac_420_w8_wpad):
22441:      // Copy and subsample input, padding 4
2245        vld1.16         {d0}, [r1,  :64], r2
2246        vld1.16         {d2}, [r12, :64], r2
2247        vld1.16         {d1}, [r1,  :64], r2
2248        vld1.16         {d3}, [r12, :64], r2
2249        vpaddl.u8       q0,  q0
2250        vpaddl.u8       q1,  q1
2251        vadd.i16        q0,  q0,  q1
2252        vshl.i16        q0,  q0,  #1
2253        vdup.16         d3,  d1[3]
2254        vmov            d2,  d1
2255        vdup.16         d1,  d0[3]
2256        subs            r8,  r8,  #2
2257        vst1.16         {q0, q1}, [r0, :128]!
2258        vadd.i16        q8,  q8,  q0
2259        vadd.i16        q9,  q9,  q1
2260        bgt             1b
2261        cmp             r4,  #0
2262        vmov            q0,  q1
2263
2264L(ipred_cfl_ac_420_w8_hpad):
2265        beq             3f // This assumes that all callers already did "cmp r4, #0"
22662:      // Vertical padding (h_pad > 0)
2267        subs            r4,  r4,  #4
2268        vst1.16         {q0, q1}, [r0, :128]!
2269        vadd.i16        q8,  q8,  q0
2270        vadd.i16        q9,  q9,  q1
2271        vst1.16         {q0, q1}, [r0, :128]!
2272        vadd.i16        q10, q10, q0
2273        vadd.i16        q11, q11, q1
2274        bgt             2b
22753:
2276
2277        // Double the height and reuse the w4 summing/subtracting
2278        lsl             r6,  r6,  #1
2279        b               L(ipred_cfl_ac_420_w4_calc_subtract_dc)
2280
2281L(ipred_cfl_ac_420_w16):
2282        adr             r7,  L(ipred_cfl_ac_420_w16_tbl)
2283        ldr             r3,  [r7, r3, lsl #2]
2284        add             r7,  r7,  r3
2285        bx              r7
2286
2287        .align 2
2288L(ipred_cfl_ac_420_w16_tbl):
2289        .word L(ipred_cfl_ac_420_w16_wpad0) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
2290        .word L(ipred_cfl_ac_420_w16_wpad1) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
2291        .word L(ipred_cfl_ac_420_w16_wpad2) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
2292        .word L(ipred_cfl_ac_420_w16_wpad3) - L(ipred_cfl_ac_420_w16_tbl) + CONFIG_THUMB
2293
2294L(ipred_cfl_ac_420_w16_wpad0):
22951:      // Copy and subsample input, without padding
2296        vld1.8          {q0, q1},   [r1,  :128], r2
2297        vld1.8          {q2, q3},   [r12, :128], r2
2298        vpaddl.u8       q0,  q0
2299        vld1.8          {q12, q13}, [r1,  :128], r2
2300        vpaddl.u8       q1,  q1
2301        vpaddl.u8       q2,  q2
2302        vpaddl.u8       q3,  q3
2303        vadd.i16        q0,  q0,  q2
2304        vadd.i16        q1,  q1,  q3
2305        vld1.8          {q2, q3},   [r12, :128], r2
2306        vpaddl.u8       q12, q12
2307        vpaddl.u8       q13, q13
2308        vpaddl.u8       q2,  q2
2309        vpaddl.u8       q3,  q3
2310        vadd.i16        q12, q12, q2
2311        vadd.i16        q13, q13, q3
2312        vshl.i16        q0,  q0,  #1
2313        vshl.i16        q1,  q1,  #1
2314        vshl.i16        q2,  q12, #1
2315        vshl.i16        q3,  q13, #1
2316        subs            r8,  r8,  #2
2317        vst1.16         {q0, q1}, [r0, :128]!
2318        vadd.i16        q8,  q8,  q0
2319        vadd.i16        q9,  q9,  q1
2320        vst1.16         {q2, q3}, [r0, :128]!
2321        vadd.i16        q10, q10, q2
2322        vadd.i16        q11, q11, q3
2323        bgt             1b
2324        cmp             r4,  #0
2325        vmov            q0,  q2
2326        vmov            q1,  q3
2327        b               L(ipred_cfl_ac_420_w16_hpad)
2328
2329L(ipred_cfl_ac_420_w16_wpad1):
23301:      // Copy and subsample input, padding 4
2331        vldr            d2,    [r1,  #16]
2332        vld1.8          {q0},  [r1,  :128], r2
2333        vldr            d6,    [r12, #16]
2334        vld1.8          {q2},  [r12, :128], r2
2335        vpaddl.u8       d2,  d2
2336        vldr            d26,   [r1,  #16]
2337        vpaddl.u8       q0,  q0
2338        vld1.8          {q12}, [r1,  :128], r2
2339        vpaddl.u8       d6,  d6
2340        vldr            d30,   [r12, #16]
2341        vpaddl.u8       q2,  q2
2342        vld1.8          {q14}, [r12, :128], r2
2343        vpaddl.u8       d26, d26
2344        vpaddl.u8       q12, q12
2345        vpaddl.u8       d30, d30
2346        vpaddl.u8       q14, q14
2347        vadd.i16        d2,  d2,  d6
2348        vadd.i16        q0,  q0,  q2
2349        vadd.i16        d26, d26, d30
2350        vadd.i16        q12, q12, q14
2351        vshl.i16        d2,  d2,  #1
2352        vshl.i16        q0,  q0,  #1
2353        vshl.i16        d6,  d26, #1
2354        vshl.i16        q2,  q12, #1
2355        vdup.16         d3,  d2[3]
2356        vdup.16         d7,  d6[3]
2357        subs            r8,  r8,  #2
2358        vst1.16         {q0, q1}, [r0, :128]!
2359        vadd.i16        q8,  q8,  q0
2360        vadd.i16        q9,  q9,  q1
2361        vst1.16         {q2, q3}, [r0, :128]!
2362        vadd.i16        q10, q10, q2
2363        vadd.i16        q11, q11, q3
2364        bgt             1b
2365        cmp             r4,  #0
2366        vmov            q0,  q2
2367        vmov            q1,  q3
2368        b               L(ipred_cfl_ac_420_w16_hpad)
2369
2370L(ipred_cfl_ac_420_w16_wpad2):
23711:      // Copy and subsample input, padding 8
2372        vld1.8          {q0}, [r1,  :128], r2
2373        vld1.8          {q1}, [r12, :128], r2
2374        vld1.8          {q2}, [r1,  :128], r2
2375        vpaddl.u8       q0,  q0
2376        vld1.8          {q3}, [r12, :128], r2
2377        vpaddl.u8       q1,  q1
2378        vpaddl.u8       q2,  q2
2379        vpaddl.u8       q3,  q3
2380        vadd.i16        q0,  q0,  q1
2381        vadd.i16        q2,  q2,  q3
2382        vshl.i16        q0,  q0,  #1
2383        vshl.i16        q2,  q2,  #1
2384        vdup.16         q1,  d1[3]
2385        vdup.16         q3,  d5[3]
2386        subs            r8,  r8,  #2
2387        vst1.16         {q0, q1}, [r0, :128]!
2388        vadd.i16        q8,  q8,  q0
2389        vadd.i16        q9,  q9,  q1
2390        vst1.16         {q2, q3}, [r0, :128]!
2391        vadd.i16        q10, q10, q2
2392        vadd.i16        q11, q11, q3
2393        bgt             1b
2394        cmp             r4,  #0
2395        vmov            q0,  q2
2396        vmov            q1,  q3
2397        b               L(ipred_cfl_ac_420_w16_hpad)
2398
2399L(ipred_cfl_ac_420_w16_wpad3):
24001:      // Copy and subsample input, padding 12
2401        vld1.8          {d0}, [r1,  :64], r2
2402        vld1.8          {d1}, [r12, :64], r2
2403        vld1.8          {d4}, [r1,  :64], r2
2404        vpaddl.u8       q0,  q0
2405        vld1.8          {d5}, [r12, :64], r2
2406        vpaddl.u8       q2,  q2
2407        vadd.i16        d0,  d0,  d1
2408        vadd.i16        d4,  d4,  d5
2409        vshl.i16        d0,  d0,  #1
2410        vshl.i16        d4,  d4,  #1
2411        vdup.16         q1,  d0[3]
2412        vdup.16         q3,  d4[3]
2413        vdup.16         d1,  d0[3]
2414        vdup.16         d5,  d4[3]
2415        subs            r8,  r8,  #2
2416        vst1.16         {q0, q1}, [r0, :128]!
2417        vadd.i16        q8,  q8,  q0
2418        vadd.i16        q9,  q9,  q1
2419        vst1.16         {q2, q3}, [r0, :128]!
2420        vadd.i16        q10, q10, q2
2421        vadd.i16        q11, q11, q3
2422        bgt             1b
2423        cmp             r4,  #0
2424        vmov            q0,  q2
2425        vmov            q1,  q3
2426        b               L(ipred_cfl_ac_420_w16_hpad)
2427
2428L(ipred_cfl_ac_420_w16_hpad):
2429        beq             3f // This assumes that all callers already did "cmp r4, #0"
24302:      // Vertical padding (h_pad > 0)
2431        subs            r4,  r4,  #2
2432        vst1.16         {q0, q1}, [r0, :128]!
2433        vadd.i16        q8,  q8,  q0
2434        vadd.i16        q9,  q9,  q1
2435        vst1.16         {q2, q3}, [r0, :128]!
2436        vadd.i16        q10, q10, q2
2437        vadd.i16        q11, q11, q3
2438        bgt             2b
24393:
2440
2441        // Quadruple the height and reuse the w4 summing/subtracting
2442        lsl             r6,  r6,  #2
2443        b               L(ipred_cfl_ac_420_w4_calc_subtract_dc)
2444endfunc
2445
2446// void cfl_ac_422_8bpc_neon(int16_t *const ac, const pixel *const ypx,
2447//                           const ptrdiff_t stride, const int w_pad,
2448//                           const int h_pad, const int cw, const int ch);
2449function ipred_cfl_ac_422_8bpc_neon, export=1
2450        push            {r4-r8,lr}
2451        ldrd            r4,  r5,  [sp, #24]
2452        ldr             r6,  [sp, #32]
2453        clz             r8,  r5
2454        lsl             r4,  r4,  #2
2455        adr             r7,  L(ipred_cfl_ac_422_tbl)
2456        sub             r8,  r8,  #27
2457        ldr             r8,  [r7, r8, lsl #2]
2458        vmov.i16        q8,  #0
2459        vmov.i16        q9,  #0
2460        vmov.i16        q10, #0
2461        vmov.i16        q11, #0
2462        add             r7,  r7,  r8
2463        sub             r8,  r6,  r4  // height - h_pad
2464        rbit            lr,  r5       // rbit(width)
2465        rbit            r12, r6       // rbit(height)
2466        clz             lr,  lr       // ctz(width)
2467        clz             r12, r12      // ctz(height)
2468        add             lr,  lr,  r12 // log2sz
2469        add             r12, r1,  r2
2470        vdup.32         d31, lr
2471        lsl             r2,  r2,  #1
2472        vneg.s32        d31, d31      // -log2sz
2473        bx              r7
2474
2475        .align 2
2476L(ipred_cfl_ac_422_tbl):
2477        .word L(ipred_cfl_ac_422_w16) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB
2478        .word L(ipred_cfl_ac_422_w8) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB
2479        .word L(ipred_cfl_ac_422_w4) - L(ipred_cfl_ac_422_tbl) + CONFIG_THUMB
2480
2481L(ipred_cfl_ac_422_w4):
24821:      // Copy and subsample input
2483        vld1.8          {d0}, [r1,  :64], r2
2484        vld1.8          {d1}, [r12, :64], r2
2485        vld1.8          {d2}, [r1,  :64], r2
2486        vld1.8          {d3}, [r12, :64], r2
2487        vpaddl.u8       q0,  q0
2488        vpaddl.u8       q1,  q1
2489        vshl.i16        q0,  q0,  #2
2490        vshl.i16        q1,  q1,  #2
2491        subs            r8,  r8,  #4
2492        vst1.16         {q0, q1}, [r0, :128]!
2493        vadd.i16        q8,  q8,  q0
2494        vadd.i16        q9,  q9,  q1
2495        bgt             1b
2496        cmp             r4,  #0
2497        vmov            d0,  d3
2498        vmov            d1,  d3
2499        vmov            d2,  d3
2500        b               L(ipred_cfl_ac_420_w4_hpad)
2501
2502L(ipred_cfl_ac_422_w8):
2503        cmp             r3,  #0
2504        bne             L(ipred_cfl_ac_422_w8_wpad)
25051:      // Copy and subsample input, without padding
2506        vld1.8          {q0}, [r1,  :128], r2
2507        vld1.8          {q1}, [r12, :128], r2
2508        vld1.8          {q2}, [r1,  :128], r2
2509        vpaddl.u8       q0,  q0
2510        vld1.8          {q3}, [r12, :128], r2
2511        vpaddl.u8       q1,  q1
2512        vpaddl.u8       q2,  q2
2513        vpaddl.u8       q3,  q3
2514        vshl.i16        q0,  q0,  #2
2515        vshl.i16        q1,  q1,  #2
2516        vshl.i16        q2,  q2,  #2
2517        vshl.i16        q3,  q3,  #2
2518        subs            r8,  r8,  #4
2519        vst1.16         {q0, q1}, [r0, :128]!
2520        vadd.i16        q8,  q8,  q0
2521        vadd.i16        q9,  q9,  q1
2522        vst1.16         {q2, q3}, [r0, :128]!
2523        vadd.i16        q10, q10, q2
2524        vadd.i16        q11, q11, q3
2525        bgt             1b
2526        cmp             r4,  #0
2527        vmov            q0,  q3
2528        vmov            q1,  q3
2529        b               L(ipred_cfl_ac_420_w8_hpad)
2530
2531L(ipred_cfl_ac_422_w8_wpad):
25321:      // Copy and subsample input, padding 4
2533        vld1.8          {d0}, [r1,  :64], r2
2534        vld1.8          {d1}, [r12, :64], r2
2535        vld1.8          {d2}, [r1,  :64], r2
2536        vld1.8          {d3}, [r12, :64], r2
2537        vpaddl.u8       q0,  q0
2538        vpaddl.u8       q1,  q1
2539        vshl.i16        q0,  q0,  #2
2540        vshl.i16        q1,  q1,  #2
2541        vdup.16         d7,  d3[3]
2542        vmov            d6,  d3
2543        vdup.16         d5,  d2[3]
2544        vmov            d4,  d2
2545        vdup.16         d3,  d1[3]
2546        vmov            d2,  d1
2547        vdup.16         d1,  d0[3]
2548        subs            r8,  r8,  #4
2549        vst1.16         {q0, q1}, [r0, :128]!
2550        vadd.i16        q8,  q8,  q0
2551        vadd.i16        q9,  q9,  q1
2552        vst1.16         {q2, q3}, [r0, :128]!
2553        vadd.i16        q10, q10, q2
2554        vadd.i16        q11, q11, q3
2555        bgt             1b
2556        cmp             r4,  #0
2557        vmov            q0,  q3
2558        vmov            q1,  q3
2559        b               L(ipred_cfl_ac_420_w8_hpad)
2560
2561L(ipred_cfl_ac_422_w16):
2562        adr             r7,  L(ipred_cfl_ac_422_w16_tbl)
2563        ldr             r3,  [r7, r3, lsl #2]
2564        add             r7,  r7,  r3
2565        bx              r7
2566
2567        .align 2
2568L(ipred_cfl_ac_422_w16_tbl):
2569        .word L(ipred_cfl_ac_422_w16_wpad0) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
2570        .word L(ipred_cfl_ac_422_w16_wpad1) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
2571        .word L(ipred_cfl_ac_422_w16_wpad2) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
2572        .word L(ipred_cfl_ac_422_w16_wpad3) - L(ipred_cfl_ac_422_w16_tbl) + CONFIG_THUMB
2573
2574L(ipred_cfl_ac_422_w16_wpad0):
25751:      // Copy and subsample input, without padding
2576        vld1.8          {q0, q1}, [r1,  :128], r2
2577        vld1.8          {q2, q3}, [r12, :128], r2
2578        vpaddl.u8       q0,  q0
2579        vpaddl.u8       q1,  q1
2580        vpaddl.u8       q2,  q2
2581        vpaddl.u8       q3,  q3
2582        vshl.i16        q0,  q0,  #2
2583        vshl.i16        q1,  q1,  #2
2584        vshl.i16        q2,  q2,  #2
2585        vshl.i16        q3,  q3,  #2
2586        subs            r8,  r8,  #2
2587        vst1.16         {q0, q1}, [r0, :128]!
2588        vadd.i16        q8,  q8,  q0
2589        vadd.i16        q9,  q9,  q1
2590        vst1.16         {q2, q3}, [r0, :128]!
2591        vadd.i16        q10, q10, q2
2592        vadd.i16        q11, q11, q3
2593        bgt             1b
2594        cmp             r4,  #0
2595        vmov            q0,  q2
2596        vmov            q1,  q3
2597        b               L(ipred_cfl_ac_420_w16_hpad)
2598
2599L(ipred_cfl_ac_422_w16_wpad1):
26001:      // Copy and subsample input, padding 4
2601        vldr            d2,   [r1,  #16]
2602        vld1.8          {q0}, [r1,  :128], r2
2603        vldr            d6,   [r12, #16]
2604        vld1.8          {q2}, [r12, :128], r2
2605        vpaddl.u8       d2,  d2
2606        vpaddl.u8       q0,  q0
2607        vpaddl.u8       d6,  d6
2608        vpaddl.u8       q2,  q2
2609        vshl.i16        d2,  d2,  #2
2610        vshl.i16        q0,  q0,  #2
2611        vshl.i16        d6,  d6,  #2
2612        vshl.i16        q2,  q2,  #2
2613        vdup.16         d3,  d2[3]
2614        vdup.16         d7,  d6[3]
2615        subs            r8,  r8,  #2
2616        vst1.16         {q0, q1}, [r0, :128]!
2617        vadd.i16        q8,  q8,  q0
2618        vadd.i16        q9,  q9,  q1
2619        vst1.16         {q2, q3}, [r0, :128]!
2620        vadd.i16        q10, q10, q2
2621        vadd.i16        q11, q11, q3
2622        bgt             1b
2623        cmp             r4,  #0
2624        vmov            q0,  q2
2625        vmov            q1,  q3
2626        b               L(ipred_cfl_ac_420_w16_hpad)
2627
2628L(ipred_cfl_ac_422_w16_wpad2):
26291:      // Copy and subsample input, padding 8
2630        vld1.8          {q0}, [r1,  :128], r2
2631        vld1.8          {q2}, [r12, :128], r2
2632        vpaddl.u8       q0,  q0
2633        vpaddl.u8       q2,  q2
2634        vshl.i16        q0,  q0,  #2
2635        vshl.i16        q2,  q2,  #2
2636        vdup.16         q1,  d1[3]
2637        vdup.16         q3,  d5[3]
2638        subs            r8,  r8,  #2
2639        vst1.16         {q0, q1}, [r0, :128]!
2640        vadd.i16        q8,  q8,  q0
2641        vadd.i16        q9,  q9,  q1
2642        vst1.16         {q2, q3}, [r0, :128]!
2643        vadd.i16        q10, q10, q2
2644        vadd.i16        q11, q11, q3
2645        bgt             1b
2646        cmp             r4,  #0
2647        vmov            q0,  q2
2648        vmov            q1,  q3
2649        b               L(ipred_cfl_ac_420_w16_hpad)
2650
2651L(ipred_cfl_ac_422_w16_wpad3):
26521:      // Copy and subsample input, padding 12
2653        vld1.8          {d0}, [r1,  :64], r2
2654        vld1.8          {d1}, [r12, :64], r2
2655        vpaddl.u8       q0,  q0
2656        vshl.i16        q0,  q0,  #2
2657        vdup.16         q3,  d1[3]
2658        vdup.16         q1,  d0[3]
2659        vdup.16         d5,  d1[3]
2660        vmov            d4,  d1
2661        vdup.16         d1,  d0[3]
2662        subs            r8,  r8,  #2
2663        vst1.16         {q0, q1}, [r0, :128]!
2664        vadd.i16        q8,  q8,  q0
2665        vadd.i16        q9,  q9,  q1
2666        vst1.16         {q2, q3}, [r0, :128]!
2667        vadd.i16        q10, q10, q2
2668        vadd.i16        q11, q11, q3
2669        bgt             1b
2670        cmp             r4,  #0
2671        vmov            q0,  q2
2672        vmov            q1,  q3
2673        b               L(ipred_cfl_ac_420_w16_hpad)
2674endfunc
2675
2676// void cfl_ac_444_8bpc_neon(int16_t *const ac, const pixel *const ypx,
2677//                           const ptrdiff_t stride, const int w_pad,
2678//                           const int h_pad, const int cw, const int ch);
2679function ipred_cfl_ac_444_8bpc_neon, export=1
2680        push            {r4-r8,lr}
2681        ldrd            r4,  r5,  [sp, #24]
2682        ldr             r6,  [sp, #32]
2683        clz             r8,  r5
2684        lsl             r4,  r4,  #2
2685        adr             r7,  L(ipred_cfl_ac_444_tbl)
2686        sub             r8,  r8,  #26
2687        ldr             r8,  [r7, r8, lsl #2]
2688        vmov.i16        q8,  #0
2689        vmov.i16        q9,  #0
2690        vmov.i16        q10, #0
2691        vmov.i16        q11, #0
2692        add             r7,  r7,  r8
2693        sub             r8,  r6,  r4  // height - h_pad
2694        rbit            lr,  r5       // rbit(width)
2695        rbit            r12, r6       // rbit(height)
2696        clz             lr,  lr       // ctz(width)
2697        clz             r12, r12      // ctz(height)
2698        add             lr,  lr,  r12 // log2sz
2699        add             r12, r1,  r2
2700        vdup.32         d31, lr
2701        lsl             r2,  r2,  #1
2702        vneg.s32        d31, d31      // -log2sz
2703        bx              r7
2704
2705        .align 2
2706L(ipred_cfl_ac_444_tbl):
2707        .word L(ipred_cfl_ac_444_w32) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
2708        .word L(ipred_cfl_ac_444_w16) - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
2709        .word L(ipred_cfl_ac_444_w8)  - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
2710        .word L(ipred_cfl_ac_444_w4)  - L(ipred_cfl_ac_444_tbl) + CONFIG_THUMB
2711
2712L(ipred_cfl_ac_444_w4):
27131:      // Copy and expand input
2714        vld1.32         {d0[]},  [r1,  :32], r2
2715        vld1.32         {d0[1]}, [r12, :32], r2
2716        vld1.32         {d2[]},  [r1,  :32], r2
2717        vld1.32         {d2[1]}, [r12, :32], r2
2718        vshll.u8        q0,  d0,  #3
2719        vshll.u8        q1,  d2,  #3
2720        subs            r8,  r8,  #4
2721        vst1.16         {q0, q1}, [r0, :128]!
2722        vadd.i16        q8,  q8,  q0
2723        vadd.i16        q9,  q9,  q1
2724        bgt             1b
2725        cmp             r4,  #0
2726        vmov            d0,  d3
2727        vmov            d1,  d3
2728        vmov            d2,  d3
2729        b               L(ipred_cfl_ac_420_w4_hpad)
2730
2731L(ipred_cfl_ac_444_w8):
27321:      // Copy and expand input
2733        vld1.16         {d0}, [r1,  :64], r2
2734        vld1.16         {d2}, [r12, :64], r2
2735        vld1.16         {d4}, [r1,  :64], r2
2736        vshll.u8        q0,  d0,  #3
2737        vld1.16         {d6}, [r12, :64], r2
2738        vshll.u8        q1,  d2,  #3
2739        vshll.u8        q2,  d4,  #3
2740        vshll.u8        q3,  d6,  #3
2741        subs            r8,  r8,  #4
2742        vst1.16         {q0, q1}, [r0, :128]!
2743        vadd.i16        q8,  q8,  q0
2744        vadd.i16        q9,  q9,  q1
2745        vst1.16         {q2, q3}, [r0, :128]!
2746        vadd.i16        q10, q10, q2
2747        vadd.i16        q11, q11, q3
2748        bgt             1b
2749        cmp             r4,  #0
2750        vmov            q0,  q3
2751        vmov            q1,  q3
2752        b               L(ipred_cfl_ac_420_w8_hpad)
2753
2754L(ipred_cfl_ac_444_w16):
2755        cmp             r3,  #0
2756        bne             L(ipred_cfl_ac_444_w16_wpad)
27571:      // Copy and expand input, without padding
2758        vld1.8          {q1}, [r1,  :128], r2
2759        vld1.8          {q3}, [r12, :128], r2
2760        vshll.u8        q0,  d2,  #3
2761        vshll.u8        q1,  d3,  #3
2762        vshll.u8        q2,  d6,  #3
2763        vshll.u8        q3,  d7,  #3
2764        subs            r8,  r8,  #2
2765        vst1.16         {q0, q1}, [r0, :128]!
2766        vadd.i16        q8,  q8,  q0
2767        vadd.i16        q9,  q9,  q1
2768        vst1.16         {q2, q3}, [r0, :128]!
2769        vadd.i16        q10, q10, q2
2770        vadd.i16        q11, q11, q3
2771        bgt             1b
2772        cmp             r4,  #0
2773        vmov            q0,  q2
2774        vmov            q1,  q3
2775        b               L(ipred_cfl_ac_420_w16_hpad)
2776
2777L(ipred_cfl_ac_444_w16_wpad):
27781:      // Copy and expand input, padding 8
2779        vld1.8          {d0}, [r1,  :64], r2
2780        vld1.8          {d4}, [r12, :64], r2
2781        vshll.u8        q0,  d0,  #3
2782        vshll.u8        q2,  d4,  #3
2783        vdup.16         q1,  d1[3]
2784        vdup.16         q3,  d5[3]
2785        subs            r8,  r8,  #2
2786        vst1.16         {q0, q1}, [r0, :128]!
2787        vadd.i16        q8,  q8,  q0
2788        vadd.i16        q9,  q9,  q1
2789        vst1.16         {q2, q3}, [r0, :128]!
2790        vadd.i16        q10, q10, q2
2791        vadd.i16        q11, q11, q3
2792        bgt             1b
2793        cmp             r4,  #0
2794        vmov            q0,  q2
2795        vmov            q1,  q3
2796        b               L(ipred_cfl_ac_420_w16_hpad)
2797
2798L(ipred_cfl_ac_444_w32):
2799        adr             r7,  L(ipred_cfl_ac_444_w32_tbl)
2800        ldr             r3,  [r7, r3, lsl #1] // (w3>>1) << 2
2801        add             r7,  r7,  r3
2802        bx              r7
2803
2804        .align 2
2805L(ipred_cfl_ac_444_w32_tbl):
2806        .word L(ipred_cfl_ac_444_w32_wpad0) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
2807        .word L(ipred_cfl_ac_444_w32_wpad2) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
2808        .word L(ipred_cfl_ac_444_w32_wpad4) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
2809        .word L(ipred_cfl_ac_444_w32_wpad6) - L(ipred_cfl_ac_444_w32_tbl) + CONFIG_THUMB
2810
2811L(ipred_cfl_ac_444_w32_wpad0):
28121:      // Copy and expand input, without padding
2813        vld1.8          {q2, q3},   [r1,  :128], r2
2814        vld1.8          {q13, q14}, [r12, :128], r2
2815        vshll.u8        q0,  d4,  #3
2816        vshll.u8        q1,  d5,  #3
2817        vshll.u8        q2,  d6,  #3
2818        vshll.u8        q3,  d7,  #3
2819        vshll.u8        q12, d26, #3
2820        vshll.u8        q13, d27, #3
2821        subs            r8,  r8,  #2
2822        vst1.16         {q0, q1},   [r0, :128]!
2823        vadd.i16        q8,  q8,  q0
2824        vadd.i16        q9,  q9,  q1
2825        vshll.u8        q0,  d28, #3
2826        vshll.u8        q1,  d29, #3
2827        vst1.16         {q2, q3},   [r0, :128]!
2828        vadd.i16        q10, q10, q2
2829        vadd.i16        q11, q11, q3
2830        vst1.16         {q12, q13}, [r0, :128]!
2831        vadd.i16        q8,  q8,  q12
2832        vadd.i16        q9,  q9,  q13
2833        vst1.16         {q0, q1},   [r0, :128]!
2834        vadd.i16        q10, q10, q0
2835        vadd.i16        q11, q11, q1
2836        bgt             1b
2837        cmp             r4,  #0
2838        b               L(ipred_cfl_ac_444_w32_hpad)
2839
2840L(ipred_cfl_ac_444_w32_wpad2):
28411:      // Copy and expand input, padding 8
2842        vldr            d4,    [r1,  #16]
2843        vld1.8          {q1},  [r1,  :128], r2
2844        vldr            d28,   [r12, #16]
2845        vld1.8          {q13}, [r12, :128], r2
2846        vshll.u8        q2,  d4,  #3
2847        vshll.u8        q0,  d2,  #3
2848        vshll.u8        q1,  d3,  #3
2849        vshll.u8        q12, d26, #3
2850        vshll.u8        q13, d27, #3
2851        vdup.16         q3,  d5[3]
2852        subs            r8,  r8,  #2
2853        vst1.16         {q0, q1},   [r0, :128]!
2854        vadd.i16        q8,  q8,  q0
2855        vadd.i16        q9,  q9,  q1
2856        vshll.u8        q0,  d28, #3
2857        vst1.16         {q2, q3},   [r0, :128]!
2858        vadd.i16        q10, q10, q2
2859        vadd.i16        q11, q11, q3
2860        vdup.16         q1,  d1[3]
2861        vst1.16         {q12, q13}, [r0, :128]!
2862        vadd.i16        q8,  q8,  q12
2863        vadd.i16        q9,  q9,  q13
2864        vst1.16         {q0, q1},   [r0, :128]!
2865        vadd.i16        q10, q10, q0
2866        vadd.i16        q11, q11, q1
2867        bgt             1b
2868        cmp             r4,  #0
2869        b               L(ipred_cfl_ac_444_w32_hpad)
2870
2871L(ipred_cfl_ac_444_w32_wpad4):
28721:      // Copy and expand input, padding 16
2873        vld1.8          {q1},  [r1,  :128], r2
2874        vld1.8          {q13}, [r12, :128], r2
2875        vshll.u8        q0,  d2,  #3
2876        vshll.u8        q1,  d3,  #3
2877        vshll.u8        q12, d26, #3
2878        vshll.u8        q13, d27, #3
2879        vdup.16         q2,  d3[3]
2880        vdup.16         q3,  d3[3]
2881        subs            r8,  r8,  #2
2882        vst1.16         {q0, q1},   [r0, :128]!
2883        vadd.i16        q8,  q8,  q0
2884        vadd.i16        q9,  q9,  q1
2885        vdup.16         q0,  d27[3]
2886        vdup.16         q1,  d27[3]
2887        vst1.16         {q2, q3},   [r0, :128]!
2888        vadd.i16        q10, q10, q2
2889        vadd.i16        q11, q11, q3
2890        vst1.16         {q12, q13}, [r0, :128]!
2891        vadd.i16        q8,  q8,  q12
2892        vadd.i16        q9,  q9,  q13
2893        vst1.16         {q0, q1},   [r0, :128]!
2894        vadd.i16        q10, q10, q0
2895        vadd.i16        q11, q11, q1
2896        bgt             1b
2897        cmp             r4,  #0
2898        b               L(ipred_cfl_ac_444_w32_hpad)
2899
2900L(ipred_cfl_ac_444_w32_wpad6):
29011:      // Copy and expand input, padding 24
2902        vld1.8          {d0},  [r1,  :64], r2
2903        vld1.8          {d24}, [r12, :64], r2
2904        vshll.u8        q0,  d0,  #3
2905        vshll.u8        q12, d24, #3
2906        subs            r8,  r8,  #2
2907        vdup.16         q1,  d1[3]
2908        vdup.16         q2,  d1[3]
2909        vdup.16         q3,  d1[3]
2910        vst1.16         {q0, q1},   [r0, :128]!
2911        vadd.i16        q8,  q8,  q0
2912        vadd.i16        q9,  q9,  q1
2913        vdup.16         q13, d25[3]
2914        vdup.16         q0,  d25[3]
2915        vdup.16         q1,  d25[3]
2916        vst1.16         {q2, q3},   [r0, :128]!
2917        vadd.i16        q10, q10, q2
2918        vadd.i16        q11, q11, q3
2919        vst1.16         {q12, q13}, [r0, :128]!
2920        vadd.i16        q8,  q8,  q12
2921        vadd.i16        q9,  q9,  q13
2922        vst1.16         {q0, q1},   [r0, :128]!
2923        vadd.i16        q10, q10, q0
2924        vadd.i16        q11, q11, q1
2925        bgt             1b
2926        cmp             r4,  #0
2927
2928L(ipred_cfl_ac_444_w32_hpad):
2929        beq             3f // This assumes that all callers already did "cmp r4, #0"
29302:      // Vertical padding (h_pad > 0)
2931        subs            r4,  r4,  #1
2932        vst1.16         {q12, q13}, [r0, :128]!
2933        vadd.i16        q8,  q8,  q12
2934        vadd.i16        q9,  q9,  q13
2935        vst1.16         {q0, q1},   [r0, :128]!
2936        vadd.i16        q10, q10, q0
2937        vadd.i16        q11, q11, q1
2938        bgt             2b
29393:
2940
2941        //  Multiply the height by eight and reuse the w4 subtracting
2942        lsl             r6,  r6,  #3
2943        // Aggregate the sums, with wider intermediates earlier than in
2944        // ipred_cfl_ac_420_w8_calc_subtract_dc.
2945        vpaddl.u16      q0,  q8
2946        vpaddl.u16      q1,  q9
2947        vpaddl.u16      q2,  q10
2948        vpaddl.u16      q3,  q11
2949        vadd.i32        q0,  q0,  q1
2950        vadd.i32        q2,  q2,  q3
2951        vadd.i32        q0,  q0,  q2
2952        vadd.i32        d0,  d0,  d1
2953        vpadd.i32       d0,  d0,  d0  // sum
2954        sub             r0,  r0,  r6, lsl #3
2955        vrshl.u32       d16, d0,  d31 // (sum + (1 << (log2sz - 1))) >>= log2sz
2956        vdup.16         q8,  d16[0]
2957        b               L(ipred_cfl_ac_420_w4_subtract_dc)
2958endfunc
2959