arm: Don't assume alignment in mbtree_propagate_list_internal where it isn't provided
[x264/x264-sandbox.git] / common / arm / mc-a.S
1 /*****************************************************************************
2  * mc.S: arm motion compensation
3  *****************************************************************************
4  * Copyright (C) 2009-2015 x264 project
5  *
6  * Authors: David Conrad <lessen42@gmail.com>
7  *          Mans Rullgard <mans@mansr.com>
8  *          Stefan Groenroos <stefan.gronroos@gmail.com>
9  *          Janne Grunau <janne-x264@jannau.net>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
24  *
25  * This program is also available under a commercial proprietary license.
26  * For more information, contact us at licensing@x264.com.
27  *****************************************************************************/
28
29 #include "asm.S"
30
31 .section .rodata
32 .align 4
33 pw_0to15:
34 .short 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
35
36 .text
37
38 // note: prefetch stuff assumes 64-byte cacheline, true for the Cortex-A8
39 // They also use nothing above armv5te, but we don't care about pre-armv6
40
41 // void prefetch_ref( uint8_t *pix, intptr_t stride, int parity )
42 function x264_prefetch_ref_arm
43     sub         r2, r2, #1
44     add         r0, r0, #64
45     and         r2, r2, r1
46     add         r0, r0, r2, lsl #3
47     add         r2, r1, r1, lsl #1
48     pld         [r0]
49     pld         [r0, r1]
50     pld         [r0, r1, lsl #1]
51     add         r3, r0, r1, lsl #2
52     pld         [r0, r2]
53     pld         [r3]
54     pld         [r3, r1]
55     pld         [r3, r1, lsl #1]
56     pld         [r3, r2]
57     bx          lr
58 endfunc
59
60 // void prefetch_fenc( uint8_t *pix_y,  intptr_t stride_y,
61 //                     uint8_t *pix_uv, intptr_t stride_uv, int mb_x )
62 function x264_prefetch_fenc_arm
63     ldr         ip, [sp]
64     push        {lr}
65     and         lr, ip, #3
66     smulbb      lr, lr, r1      // note: this assumes stride_y is <= 16 bits signed
67     and         ip, ip, #6
68     smulbb      ip, ip, r3
69     add         r0, r0, #64
70     add         r2, r2, #64
71     add         r0, r0, lr, lsl #2
72     pld         [r0]
73     add         lr, r0, r1, lsl #1
74     pld         [r0, r1]
75     pld         [lr]
76     add         r2, r2, ip, lsl #2
77     pld         [lr, r1]
78     pld         [r2]
79     add         ip, r2, r3, lsl #1
80     pld         [r2, r3]
81     pld         [ip]
82     pld         [ip, r3]
83     pop         {pc}
84 endfunc
85
86
87 // void *x264_memcpy_aligned( void *dst, const void *src, size_t n )
88 function x264_memcpy_aligned_neon
89     orr         r3,  r0,  r1,  lsr #1
90     movrel      ip,  memcpy_table
91     and         r3,  r3,  #0xc
92     ldr         pc,  [ip, r3]
93 endfunc
94
95 .macro MEMCPY_ALIGNED srcalign dstalign
96 function memcpy_aligned_\dstalign\()_\srcalign\()_neon, export=0
97     mov         r3, r0
98 .if \srcalign == 8 && \dstalign == 8
99     sub         r2, #16
100     vld1.64     {d0}, [r1,:64]!
101     vst1.64     {d0}, [r3,:64]!
102     .set r1align, 128
103     .set r3align, 128
104 .else
105     .set r1align, \srcalign * 8
106     .set r3align, \dstalign * 8
107 .endif
108     tst         r2, #16
109     beq         32f
110     sub         r2, #16
111     vld1.64     {d0-d1}, [r1,:r1align]!
112     vst1.64     {d0-d1}, [r3,:r3align]!
113 32: // n is a multiple of 32
114     tst         r2, #32
115     beq         640f
116     sub         r2, #32
117     vld1.64     {d0-d3}, [r1,:r1align]!
118     vst1.64     {d0-d3}, [r3,:r3align]!
119 640: // n is a multiple of 64
120     cmp         r2, #0
121     beq         1f
122 64:
123     subs        r2, #64
124     vld1.64     {d0-d3}, [r1,:r1align]!
125     vld1.64     {d4-d7}, [r1,:r1align]!
126     vst1.64     {d0-d3}, [r3,:r3align]!
127     vst1.64     {d4-d7}, [r3,:r3align]!
128     bgt         64b
129 1:   // end
130 .if \srcalign == 8 && \dstalign == 8
131     vld1.64     {d0}, [r1,:64]!
132     vst1.64     {d0}, [r3,:64]!
133 .endif
134     bx          lr
135 endfunc
136 .endm
137
138 MEMCPY_ALIGNED 16, 16
139 MEMCPY_ALIGNED 16, 8
140 MEMCPY_ALIGNED  8, 16
141 MEMCPY_ALIGNED  8, 8
142
143 .section .rodata
144 memcpy_table:
145 .word memcpy_aligned_16_16_neon
146 .word memcpy_aligned_16_8_neon
147 .word memcpy_aligned_8_16_neon
148 .word memcpy_aligned_8_8_neon
149 .text
150
151 .ltorg
152
153 // void x264_memzero_aligned( void *dst, size_t n )
154 function x264_memzero_aligned_neon
155     vmov.i8     q0, #0
156     vmov.i8     q1, #0
157 memzero_loop:
158     subs        r1, #128
159 .rept 4
160     vst1.64     {d0-d3}, [r0,:128]!
161 .endr
162     bgt         memzero_loop
163     bx          lr
164 endfunc
165
166
167 // void pixel_avg( uint8_t *dst,  intptr_t dst_stride,
168 //                 uint8_t *src1, intptr_t src1_stride,
169 //                 uint8_t *src2, intptr_t src2_stride, int weight );
170 .macro AVGH w h
171 function x264_pixel_avg_\w\()x\h\()_neon
172     ldr         ip, [sp, #8]
173     push        {r4-r6,lr}
174     cmp         ip, #32
175     ldrd        r4, r5, [sp, #16]
176     mov         lr, #\h
177     beq         x264_pixel_avg_w\w\()_neon
178     rsbs        r6,  ip,  #64
179     blt         x264_pixel_avg_weight_w\w\()_add_sub_neon     // weight > 64
180     cmp         ip,  #0
181     bge         x264_pixel_avg_weight_w\w\()_add_add_neon
182     b           x264_pixel_avg_weight_w\w\()_sub_add_neon     // weight < 0
183 endfunc
184 .endm
185
186 AVGH  4, 2
187 AVGH  4, 4
188 AVGH  4, 8
189 AVGH  4, 16
190 AVGH  8, 4
191 AVGH  8, 8
192 AVGH  8, 16
193 AVGH 16, 8
194 AVGH 16, 16
195
196 // 0 < weight < 64
197 .macro load_weights_add_add
198     vdup.8      d30, ip
199     vdup.8      d31, r6
200 .endm
201
202 .macro load_add_add d1 d2
203     vld1.32     {\d1}, [r2], r3
204     vld1.32     {\d2}, [r4], r5
205 .endm
206
207 .macro weight_add_add dst s1 s2
208     vmull.u8    \dst, \s1, d30
209     vmlal.u8    \dst, \s2, d31
210 .endm
211
212 // weight > 64
213 .macro load_weights_add_sub
214     rsb         r6,  #0
215     vdup.8      d30, ip
216     vdup.8      d31, r6
217 .endm
218
219 .macro load_add_sub d1 d2
220     vld1.32     {\d1}, [r2], r3
221     vld1.32     {\d2}, [r4], r5
222 .endm
223
224 .macro weight_add_sub dst s1 s2
225     vmull.u8    \dst, \s1, d30
226     vmlsl.u8    \dst, \s2, d31
227 .endm
228
229 // weight < 0
230 .macro load_weights_sub_add
231     rsb         ip,  #0
232     vdup.8      d31, r6
233     vdup.8      d30, ip
234 .endm
235
236 .macro load_sub_add d1 d2
237     vld1.32     {\d2}, [r4], r5
238     vld1.32     {\d1}, [r2], r3
239 .endm
240
241 .macro weight_sub_add dst s1 s2
242     vmull.u8    \dst, \s2, d31
243     vmlsl.u8    \dst, \s1, d30
244 .endm
245
246 .macro AVG_WEIGHT ext
247 function x264_pixel_avg_weight_w4_\ext\()_neon, export=0
248     load_weights_\ext
249 1:  // height loop
250     subs            lr,  lr,  #2
251     load_\ext       d0[], d1[]
252     weight_\ext     q8,  d0,  d1
253     load_\ext       d2[], d3[]
254     vqrshrun.s16    d0,  q8,  #6
255     weight_\ext     q9,  d2,  d3
256     vst1.32         {d0[0]}, [r0,:32], r1
257     vqrshrun.s16    d1,  q9,  #6
258     vst1.32         {d1[0]}, [r0,:32], r1
259     bgt             1b
260     pop             {r4-r6,pc}
261 endfunc
262
263 function x264_pixel_avg_weight_w8_\ext\()_neon, export=0
264     load_weights_\ext
265 1:  // height loop
266     subs            lr,  lr,  #4
267     load_\ext       d0,  d1
268     weight_\ext     q8,  d0,  d1
269     load_\ext       d2,  d3
270     weight_\ext     q9,  d2,  d3
271     load_\ext       d4,  d5
272     weight_\ext     q10, d4,  d5
273     load_\ext       d6,  d7
274     weight_\ext     q11, d6,  d7
275     vqrshrun.s16    d0,  q8,  #6
276     vqrshrun.s16    d1,  q9,  #6
277     vqrshrun.s16    d2,  q10, #6
278     vqrshrun.s16    d3,  q11, #6
279     vst1.64         {d0}, [r0,:64], r1
280     vst1.64         {d1}, [r0,:64], r1
281     vst1.64         {d2}, [r0,:64], r1
282     vst1.64         {d3}, [r0,:64], r1
283     bgt             1b
284     pop             {r4-r6,pc}
285 endfunc
286
287 function x264_pixel_avg_weight_w16_\ext\()_neon, export=0
288     load_weights_\ext
289 1:  // height loop
290     subs            lr,  lr,  #2
291     load_\ext       d0-d1, d2-d3
292     weight_\ext     q8,  d0,  d2
293     weight_\ext     q9,  d1,  d3
294     load_\ext       d4-d5, d6-d7
295     weight_\ext     q10, d4,  d6
296     weight_\ext     q11, d5,  d7
297     vqrshrun.s16    d0,  q8,  #6
298     vqrshrun.s16    d1,  q9,  #6
299     vqrshrun.s16    d2,  q10, #6
300     vqrshrun.s16    d3,  q11, #6
301     vst1.64         {d0-d1}, [r0,:128], r1
302     vst1.64         {d2-d3}, [r0,:128], r1
303     bgt             1b
304     pop             {r4-r6,pc}
305 endfunc
306 .endm
307
308 AVG_WEIGHT add_add
309 AVG_WEIGHT add_sub
310 AVG_WEIGHT sub_add
311
312 function x264_pixel_avg_w4_neon, export=0
313     subs        lr,  lr,  #2
314     vld1.32     {d0[]}, [r2], r3
315     vld1.32     {d2[]}, [r4], r5
316     vrhadd.u8   d0,  d0,  d2
317     vld1.32     {d1[]}, [r2], r3
318     vld1.32     {d3[]}, [r4], r5
319     vrhadd.u8   d1,  d1,  d3
320     vst1.32     {d0[0]}, [r0,:32], r1
321     vst1.32     {d1[0]}, [r0,:32], r1
322     bgt         x264_pixel_avg_w4_neon
323     pop         {r4-r6,pc}
324 endfunc
325
326 function x264_pixel_avg_w8_neon, export=0
327     subs        lr,  lr,  #4
328     vld1.64     {d0}, [r2], r3
329     vld1.64     {d2}, [r4], r5
330     vrhadd.u8   d0,  d0,  d2
331     vld1.64     {d1}, [r2], r3
332     vld1.64     {d3}, [r4], r5
333     vrhadd.u8   d1,  d1,  d3
334     vst1.64     {d0}, [r0,:64], r1
335     vld1.64     {d2}, [r2], r3
336     vld1.64     {d4}, [r4], r5
337     vrhadd.u8   d2,  d2,  d4
338     vst1.64     {d1}, [r0,:64], r1
339     vld1.64     {d3}, [r2], r3
340     vld1.64     {d5}, [r4], r5
341     vrhadd.u8   d3,  d3,  d5
342     vst1.64     {d2}, [r0,:64], r1
343     vst1.64     {d3}, [r0,:64], r1
344     bgt         x264_pixel_avg_w8_neon
345     pop         {r4-r6,pc}
346 endfunc
347
348 function x264_pixel_avg_w16_neon, export=0
349     subs        lr,  lr,  #4
350     vld1.64     {d0-d1}, [r2], r3
351     vld1.64     {d2-d3}, [r4], r5
352     vrhadd.u8   q0,  q0,  q1
353     vld1.64     {d2-d3}, [r2], r3
354     vld1.64     {d4-d5}, [r4], r5
355     vrhadd.u8   q1,  q1,  q2
356     vst1.64     {d0-d1}, [r0,:128], r1
357     vld1.64     {d4-d5}, [r2], r3
358     vld1.64     {d6-d7}, [r4], r5
359     vrhadd.u8   q2,  q2,  q3
360     vst1.64     {d2-d3}, [r0,:128], r1
361     vld1.64     {d6-d7}, [r2], r3
362     vld1.64     {d0-d1}, [r4], r5
363     vrhadd.u8   q3,  q3,  q0
364     vst1.64     {d4-d5}, [r0,:128], r1
365     vst1.64     {d6-d7}, [r0,:128], r1
366     bgt         x264_pixel_avg_w16_neon
367     pop         {r4-r6,pc}
368 endfunc
369
370
371 function x264_pixel_avg2_w4_neon
372     ldr         ip,  [sp, #4]
373     push        {lr}
374     ldr         lr,  [sp, #4]
375 avg2_w4_loop:
376     subs        ip,  ip,  #2
377     vld1.32     {d0[]},  [r2], r3
378     vld1.32     {d2[]},  [lr], r3
379     vrhadd.u8   d0,  d0,  d2
380     vld1.32     {d1[]},  [r2], r3
381     vld1.32     {d3[]},  [lr], r3
382     vrhadd.u8   d1,  d1,  d3
383     vst1.32     {d0[0]}, [r0,:32], r1
384     vst1.32     {d1[0]}, [r0,:32], r1
385     bgt         avg2_w4_loop
386     pop         {pc}
387 endfunc
388
389 function x264_pixel_avg2_w8_neon
390     ldr         ip,  [sp, #4]
391     push        {lr}
392     ldr         lr,  [sp, #4]
393 avg2_w8_loop:
394     subs        ip,  ip,  #2
395     vld1.64     {d0}, [r2], r3
396     vld1.64     {d2}, [lr], r3
397     vrhadd.u8   d0,  d0,  d2
398     vld1.64     {d1}, [r2], r3
399     vld1.64     {d3}, [lr], r3
400     vrhadd.u8   d1,  d1,  d3
401     vst1.64     {d0}, [r0,:64], r1
402     vst1.64     {d1}, [r0,:64], r1
403     bgt         avg2_w8_loop
404     pop         {pc}
405 endfunc
406
407 function x264_pixel_avg2_w16_neon
408     ldr         ip,  [sp, #4]
409     push        {lr}
410     ldr         lr,  [sp, #4]
411 avg2_w16_loop:
412     subs        ip,  ip,  #2
413     vld1.64     {d0-d1}, [r2], r3
414     vld1.64     {d2-d3}, [lr], r3
415     vrhadd.u8   q0,  q0,  q1
416     vld1.64     {d4-d5}, [r2], r3
417     vld1.64     {d6-d7}, [lr], r3
418     vrhadd.u8   q2,  q2,  q3
419     vst1.64     {d0-d1}, [r0,:128], r1
420     vst1.64     {d4-d5}, [r0,:128], r1
421     bgt         avg2_w16_loop
422     pop         {pc}
423 endfunc
424
425 function x264_pixel_avg2_w20_neon
426     ldr         ip,  [sp, #4]
427     push        {lr}
428     sub         r1,  r1,  #16
429     ldr         lr,  [sp, #4]
430 avg2_w20_loop:
431     subs        ip,  ip,  #2
432     vld1.64     {d0-d2},  [r2], r3
433     vld1.64     {d4-d6},  [lr], r3
434     vrhadd.u8   q0,  q0,  q2
435     vrhadd.u8   d2,  d2,  d6
436     vld1.64     {d4-d6},  [r2], r3
437     vld1.64     {d16-d18},[lr], r3
438     vrhadd.u8   q2,  q2,  q8
439     vst1.64     {d0-d1},  [r0,:128]!
440     vrhadd.u8   d6,  d6,  d18
441     vst1.32     {d2[0]},  [r0,:32], r1
442     vst1.64     {d4-d5},  [r0,:128]!
443     vst1.32     {d6[0]},  [r0,:32], r1
444     bgt         avg2_w20_loop
445     pop         {pc}
446 endfunc
447
448
449 .macro weight_prologue type
450     push        {r4-r5,lr}
451     ldr         r4,  [sp, #4*3]     // weight_t
452     ldr         ip,  [sp, #4*3+4]   // h
453 .ifc \type, full
454     ldr         lr,  [r4, #32]      // denom
455 .endif
456     ldrd        r4,  r5,  [r4, #32+4]    // scale, offset
457     vdup.8      d0,  r4
458     vdup.16     q1,  r5
459 .ifc \type, full
460     rsb         lr,  lr,  #0
461     vdup.16     q2,  lr
462 .endif
463 .endm
464
465 // void mc_weight( uint8_t *src, intptr_t src_stride, uint8_t *dst, intptr_t dst_stride,
466 //                 const x264_weight_t *weight, int height )
467 function x264_mc_weight_w20_neon
468     weight_prologue full
469     sub         r1, #16
470 weight20_loop:
471     subs        ip,  #2
472     vld1.8      {d17-d19}, [r2], r3
473     vmull.u8    q10, d17, d0
474     vmull.u8    q11, d18, d0
475     vld1.8      {d16-d18}, [r2], r3
476     vmull.u8    q12, d16, d0
477     vmull.u8    q13, d17, d0
478     vtrn.32     d19, d18
479     vmull.u8    q14, d19, d0
480     vrshl.s16   q10, q10, q2
481     vrshl.s16   q11, q11, q2
482     vrshl.s16   q12, q12, q2
483     vrshl.s16   q13, q13, q2
484     vrshl.s16   q14, q14, q2
485     vadd.s16    q10, q10, q1
486     vadd.s16    q11, q11, q1
487     vadd.s16    q12, q12, q1
488     vadd.s16    q13, q13, q1
489     vadd.s16    q14, q14, q1
490     vqmovun.s16 d16, q10
491     vqmovun.s16 d17, q11
492     vqmovun.s16 d18, q12
493     vqmovun.s16 d19, q13
494     vqmovun.s16 d20, q14
495     vst1.8      {d16-d17}, [r0,:128]!
496     vst1.32     {d20[0]},  [r0,:32], r1
497     vst1.8      {d18-d19}, [r0,:128]!
498     vst1.32     {d20[1]},  [r0,:32], r1
499     bgt         weight20_loop
500     pop         {r4-r5,pc}
501 endfunc
502
503 function x264_mc_weight_w16_neon
504     weight_prologue full
505 weight16_loop:
506     subs        ip,  #2
507     vld1.8      {d16-d17}, [r2], r3
508     vld1.8      {d18-d19}, [r2], r3
509     vmull.u8    q10, d16, d0
510     vmull.u8    q11, d17, d0
511     vmull.u8    q12, d18, d0
512     vmull.u8    q13, d19, d0
513     vrshl.s16   q10, q10, q2
514     vrshl.s16   q11, q11, q2
515     vrshl.s16   q12, q12, q2
516     vrshl.s16   q13, q13, q2
517     vadd.s16    q10, q10, q1
518     vadd.s16    q11, q11, q1
519     vadd.s16    q12, q12, q1
520     vadd.s16    q13, q13, q1
521     vqmovun.s16 d16, q10
522     vqmovun.s16 d17, q11
523     vqmovun.s16 d18, q12
524     vqmovun.s16 d19, q13
525     vst1.8      {d16-d17}, [r0,:128], r1
526     vst1.8      {d18-d19}, [r0,:128], r1
527     bgt         weight16_loop
528     pop         {r4-r5,pc}
529 endfunc
530
531 function x264_mc_weight_w8_neon
532     weight_prologue full
533 weight8_loop:
534     subs        ip,  #2
535     vld1.8      {d16}, [r2], r3
536     vld1.8      {d18}, [r2], r3
537     vmull.u8    q8,  d16, d0
538     vmull.u8    q9,  d18, d0
539     vrshl.s16   q8,  q8,  q2
540     vrshl.s16   q9,  q9,  q2
541     vadd.s16    q8,  q8,  q1
542     vadd.s16    q9,  q9,  q1
543     vqmovun.s16 d16, q8
544     vqmovun.s16 d18, q9
545     vst1.8      {d16}, [r0,:64], r1
546     vst1.8      {d18}, [r0,:64], r1
547     bgt         weight8_loop
548     pop         {r4-r5,pc}
549 endfunc
550
551 function x264_mc_weight_w4_neon
552     weight_prologue full
553 weight4_loop:
554     subs        ip,  #2
555     vld1.32     {d16[0]}, [r2], r3
556     vld1.32     {d16[1]}, [r2], r3
557     vmull.u8    q8,  d16, d0
558     vrshl.s16   q8,  q8,  q2
559     vadd.s16    q8,  q8,  q1
560     vqmovun.s16 d16, q8
561     vst1.32     {d16[0]}, [r0], r1
562     vst1.32     {d16[1]}, [r0], r1
563     bgt         weight4_loop
564     pop         {r4-r5,pc}
565 endfunc
566
567 function x264_mc_weight_w20_nodenom_neon
568     weight_prologue nodenom
569     sub         r1, #16
570 weight20_nodenom_loop:
571     subs        ip,  #2
572     vld1.8      {d26-d28}, [r2], r3
573     vmov        q8,  q1
574     vmov        q9,  q1
575     vld1.8      {d29-d31}, [r2], r3
576     vmov        q10, q1
577     vmov        q11, q1
578     vmov        q12, q1
579     vtrn.32     d28, d31
580     vmlal.u8    q8,  d26, d0
581     vmlal.u8    q9,  d27, d0
582     vmlal.u8    q10, d29, d0
583     vmlal.u8    q11, d30, d0
584     vmlal.u8    q12, d28, d0
585     vqmovun.s16 d16, q8
586     vqmovun.s16 d17, q9
587     vqmovun.s16 d18, q10
588     vqmovun.s16 d19, q11
589     vqmovun.s16 d20, q12
590     vst1.8      {d16-d17}, [r0,:128]!
591     vst1.32     {d20[0]},  [r0,:32], r1
592     vst1.8      {d18-d19}, [r0,:128]!
593     vst1.32     {d20[1]},  [r0,:32], r1
594     bgt         weight20_nodenom_loop
595     pop         {r4-r5,pc}
596 endfunc
597
598 function x264_mc_weight_w16_nodenom_neon
599     weight_prologue nodenom
600 weight16_nodenom_loop:
601     subs        ip,  #2
602     vld1.8      {d16-d17}, [r2], r3
603     vld1.8      {d18-d19}, [r2], r3
604     vmov        q12, q1
605     vmov        q13, q1
606     vmov        q14, q1
607     vmov        q15, q1
608     vmlal.u8    q12, d16, d0
609     vmlal.u8    q13, d17, d0
610     vmlal.u8    q14, d18, d0
611     vmlal.u8    q15, d19, d0
612     vqmovun.s16 d16, q12
613     vqmovun.s16 d17, q13
614     vqmovun.s16 d18, q14
615     vqmovun.s16 d19, q15
616     vst1.8      {d16-d17}, [r0,:128], r1
617     vst1.8      {d18-d19}, [r0,:128], r1
618     bgt         weight16_nodenom_loop
619     pop         {r4-r5,pc}
620 endfunc
621
622 function x264_mc_weight_w8_nodenom_neon
623     weight_prologue nodenom
624 weight8_nodenom_loop:
625     subs        ip,  #2
626     vld1.8      {d16}, [r2], r3
627     vld1.8      {d18}, [r2], r3
628     vmov        q10, q1
629     vmov        q11, q1
630     vmlal.u8    q10, d16, d0
631     vmlal.u8    q11, d18, d0
632     vqmovun.s16 d16, q10
633     vqmovun.s16 d17, q11
634     vst1.8      {d16}, [r0,:64], r1
635     vst1.8      {d17}, [r0,:64], r1
636     bgt         weight8_nodenom_loop
637     pop         {r4-r5,pc}
638 endfunc
639
640 function x264_mc_weight_w4_nodenom_neon
641     weight_prologue nodenom
642 weight4_nodenom_loop:
643     subs        ip,  #2
644     vld1.32     {d16[0]}, [r2], r3
645     vld1.32     {d16[1]}, [r2], r3
646     vmov        q10, q1
647     vmlal.u8    q10, d16, d0
648     vqmovun.s16 d16, q10
649     vst1.32     {d16[0]}, [r0], r1
650     vst1.32     {d16[1]}, [r0], r1
651     bgt         weight4_nodenom_loop
652     pop         {r4-r5,pc}
653 endfunc
654
655 .macro weight_simple_prologue
656     push        {lr}
657     ldr         lr,  [sp, #4]       // weight_t
658     ldr         ip,  [sp, #8]       // h
659     ldr         lr,  [lr]           // offset
660     vdup.8      q1,  lr
661 .endm
662
663 .macro weight_simple name op
664 function x264_mc_weight_w20_\name\()_neon
665     weight_simple_prologue
666 weight20_\name\()_loop:
667     subs        ip,  #2
668     vld1.8      {d16-d18}, [r2], r3
669     vld1.8      {d19-d21}, [r2], r3
670     \op         q8,  q8,  q1
671     \op         q9,  q9,  q1
672     \op         q10, q10, q1
673     vst1.8      {d16-d18}, [r0,:64], r1
674     vst1.8      {d19-d21}, [r0,:64], r1
675     bgt         weight20_\name\()_loop
676     pop         {pc}
677 endfunc
678
679 function x264_mc_weight_w16_\name\()_neon
680     weight_simple_prologue
681 weight16_\name\()_loop:
682     subs        ip,  #2
683     vld1.8      {d16-d17}, [r2], r3
684     vld1.8      {d18-d19}, [r2], r3
685     \op         q8,  q8,  q1
686     \op         q9,  q9,  q1
687     vst1.8      {d16-d17}, [r0,:128], r1
688     vst1.8      {d18-d19}, [r0,:128], r1
689     bgt         weight16_\name\()_loop
690     pop         {pc}
691 endfunc
692
693 function x264_mc_weight_w8_\name\()_neon
694     weight_simple_prologue
695 weight8_\name\()_loop:
696     subs        ip,  #2
697     vld1.8      {d16}, [r2], r3
698     vld1.8      {d17}, [r2], r3
699     \op         q8,  q8,  q1
700     vst1.8      {d16}, [r0,:64], r1
701     vst1.8      {d17}, [r0,:64], r1
702     bgt         weight8_\name\()_loop
703     pop         {pc}
704 endfunc
705
706 function x264_mc_weight_w4_\name\()_neon
707     weight_simple_prologue
708 weight4_\name\()_loop:
709     subs        ip,  #2
710     vld1.32     {d16[]}, [r2], r3
711     vld1.32     {d17[]}, [r2], r3
712     \op         q8,  q8,  q1
713     vst1.32     {d16[0]}, [r0], r1
714     vst1.32     {d17[0]}, [r0], r1
715     bgt         weight4_\name\()_loop
716     pop         {pc}
717 endfunc
718 .endm
719
720 weight_simple offsetadd, vqadd.u8
721 weight_simple offsetsub, vqsub.u8
722
723
724 // void mc_copy( uint8_t *dst, intptr_t dst_stride, uint8_t *src, intptr_t src_stride, int height )
725 function x264_mc_copy_w4_neon
726     ldr         ip,  [sp]
727 copy_w4_loop:
728     subs        ip,  ip,  #4
729     vld1.32     {d0[]},  [r2], r3
730     vld1.32     {d1[]},  [r2], r3
731     vld1.32     {d2[]},  [r2], r3
732     vld1.32     {d3[]},  [r2], r3
733     vst1.32     {d0[0]}, [r0,:32], r1
734     vst1.32     {d1[0]}, [r0,:32], r1
735     vst1.32     {d2[0]}, [r0,:32], r1
736     vst1.32     {d3[0]}, [r0,:32], r1
737     bgt         copy_w4_loop
738     bx          lr
739 endfunc
740
741 function x264_mc_copy_w8_neon
742     ldr         ip,  [sp]
743 copy_w8_loop:
744     subs        ip,  ip,  #4
745     vld1.32     {d0}, [r2], r3
746     vld1.32     {d1}, [r2], r3
747     vld1.32     {d2}, [r2], r3
748     vld1.32     {d3}, [r2], r3
749     vst1.32     {d0}, [r0,:64], r1
750     vst1.32     {d1}, [r0,:64], r1
751     vst1.32     {d2}, [r0,:64], r1
752     vst1.32     {d3}, [r0,:64], r1
753     bgt         copy_w8_loop
754     bx          lr
755 endfunc
756
757 function x264_mc_copy_w16_neon
758     ldr         ip,  [sp]
759 copy_w16_loop:
760     subs        ip,  ip,  #4
761     vld1.32     {d0-d1}, [r2], r3
762     vld1.32     {d2-d3}, [r2], r3
763     vld1.32     {d4-d5}, [r2], r3
764     vld1.32     {d6-d7}, [r2], r3
765     vst1.32     {d0-d1}, [r0,:128], r1
766     vst1.32     {d2-d3}, [r0,:128], r1
767     vst1.32     {d4-d5}, [r0,:128], r1
768     vst1.32     {d6-d7}, [r0,:128], r1
769     bgt         copy_w16_loop
770     bx          lr
771 endfunc
772
773 function x264_mc_copy_w16_aligned_neon
774     ldr         ip,  [sp]
775 copy_w16_aligned_loop:
776     subs        ip,  ip,  #4
777     vld1.32     {d0-d1}, [r2,:128], r3
778     vld1.32     {d2-d3}, [r2,:128], r3
779     vld1.32     {d4-d5}, [r2,:128], r3
780     vld1.32     {d6-d7}, [r2,:128], r3
781     vst1.32     {d0-d1}, [r0,:128], r1
782     vst1.32     {d2-d3}, [r0,:128], r1
783     vst1.32     {d4-d5}, [r0,:128], r1
784     vst1.32     {d6-d7}, [r0,:128], r1
785     bgt         copy_w16_aligned_loop
786     bx          lr
787 endfunc
788
789
790 // void x264_mc_chroma_neon( uint8_t *dst, intptr_t i_dst_stride,
791 //                           uint8_t *src, intptr_t i_src_stride,
792 //                           int dx, int dy, int i_width, int i_height );
793
794 function x264_mc_chroma_neon
795     push            {r4-r8, lr}
796     vpush           {d8-d11}
797     ldrd            r4, r5, [sp, #56]
798     ldrd            r6, r7, [sp, #64]
799
800     asr             lr, r6, #3
801     mul             lr, r4, lr
802     add             r3, r3, r5, asr #2
803     cmp             r7, #4
804
805     and             r5, r5, #7
806     and             r6, r6, #7
807
808     add             r3, r3, lr
809     bic             r3, r3, #0x1
810
811     pld             [r3]
812     pld             [r3, r4]
813
814     bgt             mc_chroma_w8
815     beq             mc_chroma_w4
816
817 .macro CHROMA_MC_START r00, r01, r10, r11
818     muls            lr, r5, r6
819     rsb             r7, lr, r6, lsl #3
820     rsb             ip, lr, r5, lsl #3
821     sub             r5, lr, r5, lsl #3
822     sub             r5, r5, r6, lsl #3
823     add             r5, r5, #64
824
825     beq             2f
826     vld2.8          {\r00-\r01}, [r3], r4
827
828     vdup.8          d0,    r5
829     vdup.8          d1,    ip
830
831     vdup.8          d2,    r7
832     vld2.8          {\r10-\r11}, [r3], r4
833     vdup.8          d3,    lr
834     ldr             r5,    [sp, #72]
835 .endm
836
837 .macro CHROMA_MC width, align
838 mc_chroma_w\width:
839     CHROMA_MC_START d4, d5,  d8, d9
840     vext.8          d6,  d4,  d6,  #1
841     vext.8          d7,  d5,  d7,  #1
842     vext.8          d10, d8,  d10, #1
843     vext.8          d11, d9,  d11, #1
844 // since the element size varies, there's a different index for the 2nd store
845 .if \width == 4
846     .set st2, 1
847 .else
848     .set st2, 2
849 .endif
850
851     vtrn.32         d4, d6
852     vtrn.32         d5, d7
853     vtrn.32         d8, d10
854     vtrn.32         d9, d11
855
856     vtrn.32         d0, d1
857     vtrn.32         d2, d3
858
859 1:  // height loop, interpolate xy
860
861     vmull.u8        q8,  d4,  d0
862     vmlal.u8        q8,  d8,  d2
863     vmull.u8        q9,  d5,  d0
864     vmlal.u8        q9,  d9,  d2
865
866     vld2.8          {d4-d5},  [r3], r4
867
868     vext.8          d6,  d4,  d6,  #1
869     vext.8          d7,  d5,  d7,  #1
870
871     vadd.i16        d16, d16, d17
872     vadd.i16        d17, d18, d19
873
874     vtrn.32         d4,  d6
875     vtrn.32         d5,  d7
876
877     vmull.u8        q10, d8,  d0
878     vmlal.u8        q10, d4,  d2
879     vmull.u8        q11, d9,  d0
880     vmlal.u8        q11, d5,  d2
881
882     vld2.8          {d8-d9},  [r3], r4
883
884     vrshrn.u16      d16, q8,  #6
885
886     vext.8          d10, d8,  d10,  #1
887     vext.8          d11, d9,  d11,  #1
888
889     vadd.i16        d18, d20, d21
890     vadd.i16        d19, d22, d23
891
892     vtrn.32         d8, d10
893     vtrn.32         d9, d11
894
895     vrshrn.u16      d18, q9,  #6
896
897     subs            r5,  r5,  #2
898
899     pld             [r3]
900     pld             [r3, r4]
901
902     vst1.\align     {d16[0]},   [r0,:\align], r2
903     vst1.\align     {d16[st2]}, [r1,:\align], r2
904     vst1.\align     {d18[0]},   [r0,:\align], r2
905     vst1.\align     {d18[st2]}, [r1,:\align], r2
906     bgt             1b
907
908     vpop            {d8-d11}
909     pop             {r4-r8, pc}
910
911 2:  // dx or dy are 0
912     tst             r7,  r7
913     add             ip,  ip,  r7
914     vdup.8          d0,  r5
915     ldr             r5,  [sp, #72]
916     vdup.8          d1,  ip
917
918     beq             4f
919
920     vld1.64          {d4}, [r3], r4
921     vld1.64          {d6}, [r3], r4
922
923 3:  // vertical interpolation loop
924
925     vmull.u8        q8,  d4,  d0
926     vmlal.u8        q8,  d6,  d1
927     vmull.u8        q9,  d6,  d0
928     vld1.64         {d4}, [r3], r4
929     vmlal.u8        q9,  d4,  d1
930     vld1.64         {d6}, [r3], r4
931
932     vrshrn.u16      d16, q8,  #6 // uvuvuvuv
933     vrshrn.u16      d17, q9,  #6 // uvuvuvuv
934     subs            r5,  r5,  #2
935     vuzp.8          d16, d17 // d16=uuuu|uuuu, d17=vvvv|vvvv
936
937     pld             [r3]
938     pld             [r3, r4]
939
940     vst1.\align     {d16[0]},   [r0,:\align], r2
941     vst1.\align     {d16[st2]}, [r0,:\align], r2
942     vst1.\align     {d17[0]},   [r1,:\align], r2
943     vst1.\align     {d17[st2]}, [r1,:\align], r2
944     bgt             3b
945
946     vpop            {d8-d11}
947     pop             {r4-r8, pc}
948
949 4:  // dy is 0
950
951     vld1.64         {d4-d5},  [r3], r4
952     vld1.64         {d6-d7},  [r3], r4
953
954     vext.8          d5,  d4,  d5,  #2
955     vext.8          d7,  d6,  d7,  #2
956
957 5:  // horizontal interpolation loop
958
959     vmull.u8        q8,  d4,  d0
960     vmlal.u8        q8,  d5,  d1
961     vmull.u8        q9,  d6,  d0
962     vmlal.u8        q9,  d7,  d1
963
964     subs            r5,  r5,  #2
965     vld1.64         {d4-d5},  [r3], r4
966     vld1.64         {d6-d7},  [r3], r4
967     vext.8          d5,  d4,  d5,  #2
968     vrshrn.u16      d16, q8,  #6
969     vrshrn.u16      d17, q9,  #6
970     vext.8          d7,  d6,  d7,  #2
971     vuzp.8          d16, d17
972
973     pld             [r3]
974     pld             [r3, r4]
975
976     vst1.\align     {d16[0]},   [r0,:\align], r2
977     vst1.\align     {d16[st2]}, [r0,:\align], r2
978     vst1.\align     {d17[0]},   [r1,:\align], r2
979     vst1.\align     {d17[st2]}, [r1,:\align], r2
980     bgt             5b
981
982     vpop            {d8-d11}
983     pop             {r4-r8, pc}
984 .endm
985
986    CHROMA_MC 2, 16
987    CHROMA_MC 4, 32
988
989 mc_chroma_w8:
990     CHROMA_MC_START d4, d7, d8, d11
991     vext.8          d5,  d4,  d5,  #1
992     vext.8          d9,  d8,  d9,  #1
993     vext.8          d7,  d6,  d7,  #1
994     vext.8          d11, d10, d11,  #1
995
996 1:  // height loop, interpolate xy
997     vmull.u8        q8,  d4,  d0
998     vmlal.u8        q8,  d5,  d1
999     vmlal.u8        q8,  d8,  d2
1000     vmlal.u8        q8,  d9,  d3
1001
1002     vmull.u8        q9,  d6,  d0
1003     vmlal.u8        q9,  d7,  d1
1004     vmlal.u8        q9,  d10,  d2
1005     vmlal.u8        q9,  d11,  d3
1006
1007     vld2.8          {d4-d7}, [r3], r4
1008
1009     vext.8          d5,  d4,  d5,  #1
1010     vext.8          d7,  d6,  d7,  #1
1011
1012     vmull.u8        q10, d8,   d0
1013     vmlal.u8        q10, d9,   d1
1014     vmlal.u8        q10, d4,   d2
1015     vmlal.u8        q10, d5,   d3
1016
1017     vmull.u8        q11, d10,  d0
1018     vmlal.u8        q11, d11,  d1
1019     vmlal.u8        q11, d6,   d2
1020     vmlal.u8        q11, d7,   d3
1021
1022     subs            r5,  r5,   #2
1023     vld2.8          {d8-d11}, [r3], r4
1024
1025     vrshrn.u16      d16, q8,  #6
1026     vrshrn.u16      d17, q9,  #6
1027     vrshrn.u16      d18, q10, #6
1028     vext.8          d9,  d8,  d9,  #1
1029     vrshrn.u16      d19, q11, #6
1030     vext.8          d11, d10, d11,  #1
1031
1032     pld             [r3]
1033     pld             [r3, r4]
1034
1035     vst1.64         {d16}, [r0,:64], r2
1036     vst1.64         {d17}, [r1,:64], r2
1037     vst1.64         {d18}, [r0,:64], r2
1038     vst1.64         {d19}, [r1,:64], r2
1039
1040     bgt             1b
1041
1042     vpop            {d8-d11}
1043     pop             {r4-r8, pc}
1044
1045 2:  // dx or dy are 0
1046     tst             r7,  r7
1047     add             ip,  ip,  r7
1048     vdup.8          d0,  r5
1049     ldr             r5,  [sp, #72]
1050     vdup.8          d1,  ip
1051
1052     beq             4f
1053
1054     vld2.8          {d4-d5}, [r3], r4
1055     vld2.8          {d6-d7}, [r3], r4
1056
1057 3:  // vertical interpolation loop
1058     vmull.u8        q8,  d4,  d0 //U
1059     vmlal.u8        q8,  d6,  d1
1060     vmull.u8        q9,  d5,  d0 //V
1061     vmlal.u8        q9,  d7,  d1
1062
1063     vld2.8          {d4-d5}, [r3], r4
1064
1065     vmull.u8        q10, d6,  d0
1066     vmlal.u8        q10, d4,  d1
1067     vmull.u8        q11, d7,  d0
1068     vmlal.u8        q11, d5,  d1
1069
1070     vld2.8          {d6-d7}, [r3], r4
1071
1072     vrshrn.u16      d16, q8,  #6
1073     vrshrn.u16      d17, q9,  #6
1074     vrshrn.u16      d18, q10, #6
1075     vrshrn.u16      d19, q11, #6
1076     subs            r5,  r5,  #2
1077
1078     pld             [r3]
1079     pld             [r3, r4]
1080
1081     vst1.64         {d16}, [r0,:64], r2
1082     vst1.64         {d17}, [r1,:64], r2
1083     vst1.64         {d18}, [r0,:64], r2
1084     vst1.64         {d19}, [r1,:64], r2
1085
1086     bgt             3b
1087
1088     vpop            {d8-d11}
1089     pop             {r4-r8, pc}
1090
1091 4:  // dy is 0
1092
1093     vld2.8          {d4-d7},  [r3], r4
1094     vld2.8          {d8-d11}, [r3], r4
1095     vext.8          d5,  d4,  d5,  #1
1096     vext.8          d7,  d6,  d7,  #1
1097     vext.8          d9,  d8,  d9,  #1
1098     vext.8          d11, d10, d11, #1
1099
1100 5:  // horizontal interpolation loop
1101     subs            r5,  r5,  #2
1102     vmull.u8        q8,  d4,  d0 //U
1103     vmlal.u8        q8,  d5,  d1
1104     vmull.u8        q9,  d6,  d0 //V
1105     vmlal.u8        q9,  d7,  d1
1106
1107     vld2.8          {d4-d7}, [r3], r4
1108
1109     vmull.u8        q10, d8,  d0
1110     vmlal.u8        q10, d9,  d1
1111     vmull.u8        q11, d10, d0
1112     vmlal.u8        q11, d11, d1
1113
1114     vld2.8          {d8-d11}, [r3], r4
1115
1116     vext.8          d5,  d4,  d5,  #1
1117     vrshrn.u16      d16, q8,  #6
1118     vext.8          d7,  d6,  d7,  #1
1119     vrshrn.u16      d17, q9,  #6
1120     vext.8          d9,  d8,  d9,  #1
1121     vrshrn.u16      d18, q10, #6
1122     vext.8          d11, d10, d11, #1
1123     vrshrn.u16      d19, q11, #6
1124
1125     pld             [r3]
1126     pld             [r3, r4]
1127
1128     vst1.64         {d16}, [r0,:64], r2
1129     vst1.64         {d17}, [r1,:64], r2
1130     vst1.64         {d18}, [r0,:64], r2
1131     vst1.64         {d19}, [r1,:64], r2
1132     bgt             5b
1133
1134     vpop            {d8-d11}
1135     pop             {r4-r8, pc}
1136
1137 endfunc
1138
1139
1140 // hpel_filter_v( uint8_t *dst, uint8_t *src, int16_t *buf, intptr_t stride, int width )
1141 function x264_hpel_filter_v_neon
1142     ldr             ip,  [sp]
1143     sub             r1,  r1,  r3,  lsl #1
1144     push            {lr}
1145     add             lr,  r1,  ip
1146     vmov.u8         d30, #5
1147     vmov.u8         d31, #20
1148
1149 filter_v_loop:
1150     subs            ip,  ip,  #16
1151     vld1.64         {d0-d1},   [r1,:128], r3
1152     vld1.64         {d2-d3},   [r1,:128], r3
1153     vld1.64         {d4-d5},   [r1,:128], r3
1154     vld1.64         {d6-d7},   [r1,:128], r3
1155     vld1.64         {d16-d17}, [r1,:128], r3
1156     vld1.64         {d18-d19}, [r1,:128], r3
1157     sub             r1,  lr,  ip
1158
1159     vaddl.u8        q10, d0,  d18
1160     vmlsl.u8        q10, d2,  d30
1161     vmlal.u8        q10, d4,  d31
1162     vmlal.u8        q10, d6,  d31
1163     vmlsl.u8        q10, d16, d30
1164
1165     vaddl.u8        q11, d1,  d19
1166     vmlsl.u8        q11, d3,  d30
1167     vmlal.u8        q11, d5,  d31
1168     vmlal.u8        q11, d7,  d31
1169     vmlsl.u8        q11, d17, d30
1170
1171     vqrshrun.s16    d0,  q10, #5
1172     vst1.64         {d20-d21}, [r2,:128]!
1173     vqrshrun.s16    d1,  q11, #5
1174     vst1.64         {d22-d23}, [r2,:128]!
1175     vst1.64         {d0-d1},   [r0,:128]!
1176     bgt             filter_v_loop
1177     pop             {pc}
1178 endfunc
1179
1180 // hpel_filter_c( uint8_t *dst, int16_t *buf, int width );
1181 function x264_hpel_filter_c_neon
1182     sub             r1,  #16
1183     vld1.64         {d0-d3}, [r1,:128]!
1184
1185     // unrolled 2x: 4% faster
1186 filter_c_loop:
1187     subs            r2,  r2,  #16
1188     vld1.64         {d4-d7}, [r1,:128]!
1189     vext.16         q8,  q0,  q1,  #6
1190     vext.16         q12, q1,  q2,  #3
1191     vadd.s16        q8,  q8,  q12
1192     vext.16         q9,  q0,  q1,  #7
1193     vext.16         q11, q1,  q2,  #2
1194     vadd.s16        q9,  q9,  q11
1195     vext.16         q10, q1,  q2,  #1
1196     vext.16         q11, q1,  q2,  #6
1197     vadd.s16        q10, q1,  q10
1198     vsub.s16        q8,  q8,  q9    // a-b
1199     vext.16         q15, q2,  q3,  #3
1200     vsub.s16        q9,  q9,  q10   // b-c
1201
1202     vext.16         q12, q1,  q2,  #7
1203     vshr.s16        q8,  q8,  #2    // (a-b)/4
1204     vadd.s16        q11, q11, q15
1205     vext.16         q14, q2,  q3,  #2
1206     vsub.s16        q8,  q8,  q9    // (a-b)/4-b+c
1207     vadd.s16        q12, q12, q14
1208     vext.16         q13, q2,  q3,  #1
1209
1210     vshr.s16        q8,  q8,  #2    // ((a-b)/4-b+c)/4
1211     vadd.s16        q13, q2,  q13
1212     vadd.s16        q8,  q8,  q10   // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1213     vsub.s16        q11, q11, q12   // a-b
1214     vsub.s16        q12, q12, q13   // b-c
1215     vshr.s16        q11, q11, #2    // (a-b)/4
1216     vqrshrun.s16    d30, q8,  #6
1217     vsub.s16        q11, q11, q12   // (a-b)/4-b+c
1218     vshr.s16        q11, q11, #2    // ((a-b)/4-b+c)/4
1219     vld1.64         {d0-d3}, [r1,:128]!
1220     vadd.s16        q11, q11, q13   // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1221
1222     vext.16         q8,  q2,  q3,  #6
1223     vqrshrun.s16    d31, q11,  #6
1224     vext.16         q12, q3,  q0,  #3
1225     vadd.s16        q8,  q8,  q12
1226     vext.16         q9,  q2,  q3,  #7
1227     vst1.64         {d30-d31}, [r0,:128]!
1228     bxle            lr
1229     subs            r2,  r2,  #16
1230
1231     vext.16         q11, q3,  q0,  #2
1232     vadd.s16        q9,  q9,  q11
1233     vext.16         q10, q3,  q0,  #1
1234     vext.16         q11, q3,  q0,  #6
1235     vadd.s16        q10, q3,  q10
1236     vsub.s16        q8,  q8,  q9    // a-b
1237     vext.16         q15, q0,  q1,  #3
1238     vsub.s16        q9,  q9,  q10   // b-c
1239
1240     vext.16         q12, q3,  q0,  #7
1241     vshr.s16        q8,  q8,  #2    // (a-b)/4
1242     vadd.s16        q11, q11, q15
1243     vext.16         q14, q0,  q1,  #2
1244     vsub.s16        q8,  q8,  q9    // (a-b)/4-b+c
1245     vadd.s16        q12, q12, q14
1246     vext.16         q13, q0,  q1,  #1
1247
1248     vshr.s16        q8,  q8,  #2    // ((a-b)/4-b+c)/4
1249     vadd.s16        q13, q0,  q13
1250     vadd.s16        q8,  q8,  q10   // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1251     vsub.s16        q11, q11, q12   // a-b
1252     vsub.s16        q12, q12, q13   // b-c
1253     vshr.s16        q11, q11, #2    // (a-b)/4
1254     vqrshrun.s16    d30, q8,  #6
1255     vsub.s16        q11, q11, q12   // (a-b)/4-b+c
1256     vshr.s16        q11, q11, #2    // ((a-b)/4-b+c)/4
1257     vadd.s16        q11, q11, q13   // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1258
1259     vqrshrun.s16    d31, q11,  #6
1260     vst1.64         {d30-d31}, [r0,:128]!
1261     bgt             filter_c_loop
1262     bx              lr
1263 endfunc
1264
1265 // hpel_filter_h( uint8_t *dst, uint8_t *src, int width );
1266 function x264_hpel_filter_h_neon
1267     sub             r1,  #16
1268     vmov.u8         d30, #5
1269     vld1.64         {d0-d3}, [r1,:128]!
1270     vmov.u8         d31, #20
1271
1272     // unrolled 3x because it's 5% faster, due to mitigating
1273     // the high latency of multiplication and vqrshrun
1274 filter_h_loop:
1275     subs            r2,  r2,  #16
1276     vld1.64         {d4-d5}, [r1,:128]!
1277     vext.8          q8,  q0,  q1,  #14
1278     vext.8          q12, q1,  q2,  #3
1279     vaddl.u8        q13, d16, d24
1280     vext.8          q9,  q0,  q1,  #15
1281     vaddl.u8        q14, d17, d25
1282
1283     vext.8          q10, q1,  q2,  #1
1284     vmlal.u8        q13, d2,  d31
1285     vmlsl.u8        q13, d18, d30
1286     vext.8          q11, q1,  q2,  #2
1287     vmlal.u8        q13, d20, d31
1288     vmlsl.u8        q13, d22, d30
1289
1290     vmlsl.u8        q14, d19, d30
1291     vmlal.u8        q14, d3,  d31
1292     vmlal.u8        q14, d21, d31
1293     vmlsl.u8        q14, d23, d30
1294     vqrshrun.s16    d6,  q13, #5
1295
1296     vld1.64         {d0-d1}, [r1,:128]!
1297     vext.8          q8,  q1,  q2,  #14
1298     vext.8          q12, q2,  q0,  #3
1299     vaddl.u8        q13, d16, d24
1300     vqrshrun.s16    d7,  q14, #5
1301     vext.8          q9,  q1,  q2,  #15
1302     vaddl.u8        q14, d17, d25
1303
1304     vst1.64         {d6-d7}, [r0,:128]!
1305     bxle            lr
1306     subs            r2,  r2,  #16
1307
1308     vext.8          q10, q2,  q0,  #1
1309     vmlal.u8        q13, d4,  d31
1310     vmlsl.u8        q13, d18, d30
1311     vext.8          q11, q2,  q0,  #2
1312     vmlal.u8        q13, d20, d31
1313     vmlsl.u8        q13, d22, d30
1314
1315     vmlsl.u8        q14, d19, d30
1316     vmlal.u8        q14, d5,  d31
1317     vmlal.u8        q14, d21, d31
1318     vmlsl.u8        q14, d23, d30
1319     vqrshrun.s16    d6,  q13, #5
1320
1321     vld1.64         {d2-d3}, [r1,:128]!
1322     vext.8          q8,  q2,  q0,  #14
1323     vext.8          q12, q0,  q1,  #3
1324     vaddl.u8        q13, d16, d24
1325     vqrshrun.s16    d7,  q14, #5
1326     vext.8          q9,  q2,  q0,  #15
1327     vaddl.u8        q14, d17, d25
1328
1329     vst1.64         {d6-d7}, [r0,:128]!
1330     bxle            lr
1331     subs            r2,  r2,  #16
1332
1333     vext.8          q10, q0,  q1,  #1
1334     vmlal.u8        q13, d0,  d31
1335     vmlsl.u8        q13, d18, d30
1336     vext.8          q11, q0,  q1,  #2
1337     vmlal.u8        q13, d20, d31
1338     vmlsl.u8        q13, d22, d30
1339
1340     vmlsl.u8        q14, d19, d30
1341     vmlal.u8        q14, d1,  d31
1342     vmlal.u8        q14, d21, d31
1343     vmlsl.u8        q14, d23, d30
1344
1345     vqrshrun.s16    d6, q13, #5
1346     vqrshrun.s16    d7, q14, #5
1347     vst1.64         {d6-d7}, [r0,:128]!
1348     bgt             filter_h_loop
1349     bx              lr
1350 endfunc
1351
1352
1353 // frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv,
1354 //                         uint8_t *dstc, intptr_t src_stride, intptr_t dst_stride, int width,
1355 //                         int height )
1356 function x264_frame_init_lowres_core_neon
1357     push            {r4-r10,lr}
1358     vpush           {d8-d15}
1359     ldrd            r4,  r5,  [sp, #96]
1360     ldrd            r6,  r7,  [sp, #104]
1361     ldr             lr,  [sp, #112]
1362     sub             r10, r6,  r7            // dst_stride - width
1363     and             r10, r10, #~15
1364
1365 lowres_yloop:
1366     mov             ip,  r7                 // width
1367     mov             r6,  r0                 // src0
1368     add             r8,  r0,  r5            // src1 = src0 + src_stride
1369     add             r9,  r0,  r5,  lsl #1   // src2 = src1 + src_stride
1370
1371     vld2.8          {d8, d10}, [r6,:128]!
1372     vld2.8          {d12,d14}, [r8,:128]!
1373     vld2.8          {d16,d18}, [r9,:128]!
1374
1375 lowres_xloop:
1376     subs            ip,  ip,  #16
1377
1378     vld2.8          {d9, d11}, [r6,:128]!
1379     vld2.8          {d13,d15}, [r8,:128]!
1380     vrhadd.u8       q0,  q4,  q6
1381     vld2.8          {d17,d19}, [r9,:128]!
1382     vrhadd.u8       q5,  q5,  q7
1383     vld2.8          {d20,d22}, [r6,:128]!
1384     vrhadd.u8       q1,  q6,  q8
1385     vld2.8          {d24,d26}, [r8,:128]!
1386     vrhadd.u8       q7,  q7,  q9
1387     vext.8          q4,  q4,  q10, #1
1388     vrhadd.u8       q0,  q0,  q5
1389     vext.8          q6,  q6,  q12, #1
1390     vrhadd.u8       q1,  q1,  q7
1391     vld2.8          {d28,d30}, [r9,:128]!
1392     vrhadd.u8       q4,  q4,  q6
1393     vext.8          q8,  q8,  q14, #1
1394     vrhadd.u8       q6,  q6,  q8
1395     vst1.64         {d0-d1},   [r1,:128]!
1396     vrhadd.u8       q2,  q4,  q5
1397     vst1.64         {d2-d3},   [r3,:128]!
1398     vrhadd.u8       q3,  q6,  q7
1399     vst1.64         {d4-d5},   [r2,:128]!
1400     vst1.64         {d6-d7},   [r4,:128]!
1401
1402     ble             lowres_xloop_end
1403     subs            ip,  ip,  #16
1404
1405     vld2.8          {d21,d23}, [r6,:128]!
1406     vld2.8          {d25,d27}, [r8,:128]!
1407     vrhadd.u8       q0,  q10, q12
1408     vld2.8          {d29,d31}, [r9,:128]!
1409     vrhadd.u8       q11, q11, q13
1410     vld2.8          {d8, d10}, [r6,:128]!
1411     vrhadd.u8       q1,  q12, q14
1412     vld2.8          {d12,d14}, [r8,:128]!
1413     vrhadd.u8       q13, q13, q15
1414     vext.8          q10, q10, q4,  #1
1415     vrhadd.u8       q0,  q0,  q11
1416     vext.8          q12, q12, q6,  #1
1417     vrhadd.u8       q1,  q1,  q13
1418     vld2.8          {d16,d18}, [r9,:128]!
1419     vrhadd.u8       q10, q10, q12
1420     vext.8          q14, q14, q8,  #1
1421     vrhadd.u8       q12, q12, q14
1422     vst1.64         {d0-d1},   [r1,:128]!
1423     vrhadd.u8       q2,  q10, q11
1424     vst1.64         {d2-d3},   [r3,:128]!
1425     vrhadd.u8       q3,  q12, q13
1426     vst1.64         {d4-d5},   [r2,:128]!
1427     vst1.64         {d6-d7},   [r4,:128]!
1428
1429     bgt             lowres_xloop
1430
1431 lowres_xloop_end:
1432     subs            lr,  lr,  #1
1433     add             r0,  r0,  r5,  lsl #1
1434     add             r1,  r1,  r10
1435     add             r2,  r2,  r10
1436     add             r3,  r3,  r10
1437     add             r4,  r4,  r10
1438     bgt             lowres_yloop
1439
1440     vpop            {d8-d15}
1441     pop             {r4-r10,pc}
1442 endfunc
1443
1444 function x264_load_deinterleave_chroma_fdec_neon
1445     mov             ip,  #FDEC_STRIDE/2
1446 1:
1447     vld2.8          {d0-d1}, [r1,:128], r2
1448     subs            r3,  r3,  #1
1449     pld             [r1]
1450     vst1.8          {d0},    [r0,:64], ip
1451     vst1.8          {d1},    [r0,:64], ip
1452     bgt             1b
1453
1454     bx              lr
1455 endfunc
1456
1457 function x264_load_deinterleave_chroma_fenc_neon
1458     mov             ip,  #FENC_STRIDE/2
1459 1:
1460     vld2.8          {d0-d1}, [r1,:128], r2
1461     subs            r3,  r3,  #1
1462     pld             [r1]
1463     vst1.8          {d0},    [r0,:64], ip
1464     vst1.8          {d1},    [r0,:64], ip
1465     bgt             1b
1466
1467     bx              lr
1468 endfunc
1469
1470 function x264_plane_copy_neon
1471     push            {r4,lr}
1472     ldr             r4,  [sp, #8]
1473     ldr             lr,  [sp, #12]
1474     add             r12, r4,  #15
1475     bic             r4,  r12, #15
1476     sub             r1,  r1,  r4
1477     sub             r3,  r3,  r4
1478 1:
1479     mov             r12, r4
1480 16:
1481     tst             r12, #16
1482     beq             32f
1483     subs            r12, r12, #16
1484     vld1.8          {q0}, [r2]!
1485     vst1.8          {q0}, [r0]!
1486     beq             0f
1487 32:
1488     subs            r12, r12, #32
1489     vld1.8          {q0, q1}, [r2]!
1490     vst1.8          {q0, q1}, [r0]!
1491     bgt             32b
1492 0:
1493     subs            lr,  lr,  #1
1494     add             r2,  r2,  r3
1495     add             r0,  r0,  r1
1496     bgt             1b
1497
1498     pop             {r4,pc}
1499 endfunc
1500
1501 function x264_plane_copy_deinterleave_neon
1502     push            {r4-r7, lr}
1503     ldrd            r6, r7, [sp, #28]
1504     ldrd            r4, r5, [sp, #20]
1505     add             lr,  r6,  #15
1506     bic             lr,  lr,  #15
1507     sub             r1,  r1,  lr
1508     sub             r3,  r3,  lr
1509     sub             r5,  r5,  lr, lsl #1
1510 block:
1511     vld2.8          {d0-d3}, [r4,:128]!
1512     subs            lr,  lr,  #16
1513     vst1.8          {q0},    [r0]!
1514     vst1.8          {q1},    [r2]!
1515     bgt             block
1516
1517     add             r4,  r4,  r5
1518     subs            r7,  r7,  #1
1519     add             r0,  r0,  r1
1520     add             r2,  r2,  r3
1521     mov             lr,  r6
1522     bgt             block
1523
1524     pop             {r4-r7, pc}
1525 endfunc
1526
1527 function x264_plane_copy_deinterleave_rgb_neon
1528     push            {r4-r8, r10, r11, lr}
1529     ldrd            r4,  r5,  [sp, #32]
1530     ldrd            r6,  r7,  [sp, #40]
1531     ldr             r8,  [sp, #48]
1532     ldrd            r10, r11, [sp, #52]
1533     add             lr,  r10, #7
1534     subs            r8,  r8,  #3
1535     bic             lr,  lr,  #7
1536     sub             r7,  r7,  lr, lsl #1
1537     sub             r1,  r1,  lr
1538     sub             r3,  r3,  lr
1539     sub             r5,  r5,  lr
1540     subne           r7,  r7,  lr, lsl #1
1541     subeq           r7,  r7,  lr
1542     bne             block4
1543 block3:
1544     vld3.8          {d0,d1,d2}, [r6]!
1545     subs            lr,  lr,  #8
1546     vst1.8          {d0},    [r0]!
1547     vst1.8          {d1},    [r2]!
1548     vst1.8          {d2},    [r4]!
1549     bgt             block3
1550
1551     subs            r11, r11, #1
1552     add             r0,  r0,  r1
1553     add             r2,  r2,  r3
1554     add             r4,  r4,  r5
1555     add             r6,  r6,  r7
1556     mov             lr,  r10
1557     bgt             block3
1558
1559     pop             {r4-r8, r10, r11, pc}
1560 block4:
1561     vld4.8          {d0,d1,d2,d3}, [r6]!
1562     subs            lr,  lr,  #8
1563     vst1.8          {d0},    [r0]!
1564     vst1.8          {d1},    [r2]!
1565     vst1.8          {d2},    [r4]!
1566     bgt             block4
1567
1568     subs            r11, r11, #1
1569     add             r0,  r0,  r1
1570     add             r2,  r2,  r3
1571     add             r4,  r4,  r5
1572     add             r6,  r6,  r7
1573     mov             lr,  r10
1574     bgt             block4
1575
1576     pop             {r4-r8, r10, r11, pc}
1577 endfunc
1578
1579 function x264_plane_copy_interleave_neon
1580     push            {r4-r7, lr}
1581     ldrd            r6, r7, [sp, #28]
1582     ldrd            r4, r5, [sp, #20]
1583     add             lr,  r6,  #15
1584     bic             lr,  lr,  #15
1585     sub             r1,  r1,  lr, lsl #1
1586     sub             r3,  r3,  lr
1587     sub             r5,  r5,  lr
1588 blocki:
1589     vld1.8          {q0}, [r2]!
1590     vld1.8          {q1}, [r4]!
1591     subs            lr,  lr,  #16
1592     vst2.8          {d0,d2}, [r0]!
1593     vst2.8          {d1,d3}, [r0]!
1594     bgt             blocki
1595
1596     subs            r7,  r7,  #1
1597     add             r0,  r0,  r1
1598     add             r2,  r2,  r3
1599     add             r4,  r4,  r5
1600     mov             lr,  r6
1601     bgt             blocki
1602
1603     pop             {r4-r7, pc}
1604 endfunc
1605
1606 function x264_plane_copy_swap_neon
1607     push            {r4-r5, lr}
1608     ldrd            r4, r5, [sp, #12]
1609     add             lr,  r4,  #15
1610     bic             lr,  lr,  #15
1611     sub             r1,  r1,  lr, lsl #1
1612     sub             r3,  r3,  lr, lsl #1
1613 1:
1614     vld1.8          {q0, q1}, [r2]!
1615     subs            lr,  lr,  #16
1616     vrev16.8        q0,  q0
1617     vrev16.8        q1,  q1
1618     vst1.8          {q0, q1}, [r0]!
1619     bgt             1b
1620
1621     subs            r5,  r5,  #1
1622     add             r0,  r0,  r1
1623     add             r2,  r2,  r3
1624     mov             lr,  r4
1625     bgt             1b
1626
1627     pop             {r4-r5, pc}
1628 endfunc
1629
1630 function x264_store_interleave_chroma_neon
1631     push            {lr}
1632     ldr             lr,  [sp, #4]
1633     mov             ip,  #FDEC_STRIDE
1634 1:
1635     vld1.8          {d0}, [r2], ip
1636     vld1.8          {d1}, [r3], ip
1637     subs            lr,  lr,  #1
1638     vst2.8          {d0,d1}, [r0,:128], r1
1639     bgt             1b
1640
1641     pop             {pc}
1642 endfunc
1643
1644 .macro integral4h p1, p2
1645     vext.8          d1,  \p1, \p2,  #1
1646     vext.8          d2,  \p1, \p2,  #2
1647     vext.8          d3,  \p1, \p2,  #3
1648     vaddl.u8        q0,  \p1, d1
1649     vaddl.u8        q1,  d2,  d3
1650     vadd.u16        q0,  q0,  q1
1651     vadd.u16        q0,  q0,  q2
1652 .endm
1653
1654 function integral_init4h_neon
1655     sub             r3,  r0,  r2, lsl #1
1656     vld1.8          {d6, d7}, [r1, :128]!
1657 1:
1658     subs            r2,  r2,  #16
1659     vld1.16         {q2},  [r3, :128]!
1660     integral4h      d6, d7
1661     vld1.8          {d6},  [r1, :64]!
1662     vld1.16         {q2},  [r3, :128]!
1663     vst1.16         {q0},  [r0, :128]!
1664     integral4h      d7, d6
1665     vld1.8          {d7},  [r1, :64]!
1666     vst1.16         {q0},  [r0, :128]!
1667     bgt             1b
1668     bx              lr
1669 endfunc
1670
1671 .macro integral8h p1, p2, s
1672     vext.8          d1,  \p1,  \p2,  #1
1673     vext.8          d2,  \p1,  \p2,  #2
1674     vext.8          d3,  \p1,  \p2,  #3
1675     vext.8          d4,  \p1,  \p2,  #4
1676     vext.8          d5,  \p1,  \p2,  #5
1677     vext.8          d6,  \p1,  \p2,  #6
1678     vext.8          d7,  \p1,  \p2,  #7
1679     vaddl.u8        q0,  \p1,  d1
1680     vaddl.u8        q1,  d2,   d3
1681     vaddl.u8        q2,  d4,   d5
1682     vaddl.u8        q3,  d6,   d7
1683     vadd.u16        q0,  q0,   q1
1684     vadd.u16        q2,  q2,   q3
1685     vadd.u16        q0,  q0,   q2
1686     vadd.u16        q0,  q0,   \s
1687 .endm
1688
1689 function integral_init8h_neon
1690     sub             r3,  r0,  r2, lsl #1
1691     vld1.8          {d16, d17}, [r1, :128]!
1692 1:
1693     subs            r2,  r2,  #16
1694     vld1.16         {q9},  [r3, :128]!
1695     integral8h      d16, d17, q9
1696     vld1.8          {d16}, [r1, :64]!
1697     vld1.16         {q9},  [r3, :128]!
1698     vst1.16         {q0},  [r0, :128]!
1699     integral8h      d17, d16, q9
1700     vld1.8          {d17}, [r1, :64]!
1701     vst1.16         {q0},  [r0, :128]!
1702     bgt             1b
1703     bx              lr
1704 endfunc
1705
1706 function integral_init4v_neon
1707     push            {r4-r5}
1708     mov             r3,   r0
1709     add             r4,   r0,   r2,  lsl #3
1710     add             r5,   r0,   r2,  lsl #4
1711     sub             r2,   r2,   #8
1712     vld1.16         {q11, q12}, [r3]!
1713     vld1.16         {q8,  q9},  [r5]!
1714     vld1.16         {q13}, [r3]!
1715     vld1.16         {q10}, [r5]!
1716 1:
1717     subs            r2,   r2,   #16
1718     vld1.16         {q14, q15}, [r4]!
1719     vext.8          q0,   q11,  q12, #8
1720     vext.8          q1,   q12,  q13, #8
1721     vext.8          q2,   q8,   q9,  #8
1722     vext.8          q3,   q9,   q10, #8
1723     vsub.u16        q14,  q14,  q11
1724     vsub.u16        q15,  q15,  q12
1725     vadd.u16        q0,   q0,   q11
1726     vadd.u16        q1,   q1,   q12
1727     vadd.u16        q2,   q2,   q8
1728     vadd.u16        q3,   q3,   q9
1729     vst1.16         {q14},  [r1]!
1730     vst1.16         {q15},  [r1]!
1731     vmov            q11,  q13
1732     vmov            q8,   q10
1733     vsub.u16        q0,   q2,   q0
1734     vsub.u16        q1,   q3,   q1
1735     vld1.16         {q12, q13}, [r3]!
1736     vld1.16         {q9,  q10}, [r5]!
1737     vst1.16         {q0}, [r0]!
1738     vst1.16         {q1}, [r0]!
1739     bgt             1b
1740 2:
1741     pop             {r4-r5}
1742     bx              lr
1743 endfunc
1744
1745 function integral_init8v_neon
1746     add             r2,  r0,  r1,  lsl #4
1747     sub             r1,  r1,  #8
1748     ands            r3,  r1,  #16 - 1
1749     beq             1f
1750     subs            r1,  r1,  #8
1751     vld1.16         {q0}, [r0]
1752     vld1.16         {q2}, [r2]!
1753     vsub.u16        q8,  q2,  q0
1754     vst1.16         {q8}, [r0]!
1755     ble             2f
1756 1:
1757     subs            r1,  r1,  #16
1758     vld1.16         {q0, q1}, [r0]
1759     vld1.16         {q2, q3}, [r2]!
1760     vsub.u16        q8,  q2,  q0
1761     vsub.u16        q9,  q3,  q1
1762     vst1.16         {q8},  [r0]!
1763     vst1.16         {q9},  [r0]!
1764     bgt             1b
1765 2:
1766     bx              lr
1767 endfunc
1768
1769 function x264_mbtree_propagate_cost_neon
1770     push            {r4-r5,lr}
1771     ldrd            r4, r5, [sp, #12]
1772     ldr             lr, [sp, #20]
1773     vld1.32         {d6[], d7[]},  [r5]
1774 8:
1775     subs            lr,  lr,  #8
1776     vld1.16         {q8},  [r1]!
1777     vld1.16         {q9},  [r2]!
1778     vld1.16         {q10}, [r3]!
1779     vld1.16         {q11}, [r4]!
1780     vbic.u16        q10, #0xc000
1781     vmin.u16        q10, q9,  q10
1782     vmull.u16       q12, d18, d22           @ propagate_intra
1783     vmull.u16       q13, d19, d23           @ propagate_intra
1784     vsubl.u16       q14, d18, d20           @ propagate_num
1785     vsubl.u16       q15, d19, d21           @ propagate_num
1786     vmovl.u16       q10, d18                @ propagate_denom
1787     vmovl.u16       q11, d19                @ propagate_denom
1788     vmovl.u16       q9,  d17
1789     vmovl.u16       q8,  d16
1790     vcvt.f32.s32    q12, q12
1791     vcvt.f32.s32    q13, q13
1792     vcvt.f32.s32    q14, q14
1793     vcvt.f32.s32    q15, q15
1794     vcvt.f32.s32    q10, q10
1795     vcvt.f32.s32    q11, q11
1796     vrecpe.f32      q0,  q10
1797     vrecpe.f32      q1,  q11
1798     vcvt.f32.s32    q8,  q8
1799     vcvt.f32.s32    q9,  q9
1800     vrecps.f32      q10, q0,  q10
1801     vrecps.f32      q11, q1,  q11
1802     vmla.f32        q8,  q12, q3            @ propagate_amount
1803     vmla.f32        q9,  q13, q3            @ propagate_amount
1804     vmul.f32        q0,  q0,  q10
1805     vmul.f32        q1,  q1,  q11
1806     vmul.f32        q8,  q8,  q14
1807     vmul.f32        q9,  q9,  q15
1808     vmul.f32        q0,  q8,  q0
1809     vmul.f32        q1,  q9,  q1
1810     vcvt.s32.f32    q0,  q0
1811     vcvt.s32.f32    q1,  q1
1812     vqmovn.s32      d0,  q0
1813     vqmovn.s32      d1,  q1
1814     vst1.16         {q0},  [r0]!
1815     bgt             8b
1816     pop             {r4-r5,pc}
1817 endfunc
1818
1819 function x264_mbtree_propagate_list_internal_neon
1820     vld2.16         {d4[], d5[]}, [sp]      @ bipred_weight, mb_y
1821     movrel          r12, pw_0to15
1822     vmov.u16        q10, #0xc000
1823     vld1.16         {q0},  [r12, :128]      @h->mb.i_mb_x,h->mb.i_mb_y
1824     vmov.u32        q11, #4
1825     vmov.u8         q3,  #32
1826     vdup.u16        q8,  d5[0]              @ mb_y
1827     vzip.u16        q0,  q8
1828     ldr             r12, [sp, #8]
1829 8:
1830     subs            r12, r12,  #8
1831     vld1.16         {q14},  [r1, :128]!      @ propagate_amount
1832     vld1.16         {q15},  [r2]!            @ lowres_cost
1833     vld1.16         {q8, q9},  [r0]!
1834     vand            q15, q15, q10
1835     vceq.u16        q1,  q15, q10
1836     vmull.u16       q12, d28, d4
1837     vmull.u16       q13, d29, d4
1838     vrshrn.u32      d30, q12, #6
1839     vrshrn.u32      d31, q13, #6
1840     vbsl            q1,  q15, q14           @ if( lists_used == 3 )
1841     @ propagate_amount = (propagate_amount * bipred_weight + 32) >> 6
1842     vshr.s16        q12, q8,  #5
1843     vshr.s16        q13, q9,  #5
1844     vuzp.16         q8,  q9                 @ x & 31, y & 31
1845     vadd.s16        q12, q12, q0
1846     vadd.s16        q0,  q0,  q11
1847     vmovn.i16       d16, q8
1848     vmovn.i16       d17, q9
1849     vadd.s16        q13, q13, q0
1850     vbic.i16        q8,  #128+64+32
1851     vadd.s16        q0,  q0,  q11
1852     vbic.i16        q8,  #(128+64+32)<<8
1853     vst1.16         {q12, q13},  [r3, :128]!
1854     vsub.i8         q9,  q3,  q8
1855     vmull.u8        q12, d17, d16           @ idx3weight = y*x
1856     vmull.u8        q14, d19, d16           @ idx1weight = (32-y)*x
1857     vmull.u8        q15, d19, d18           @ idx0weight = (32-y)*(32-x)
1858     vmull.u8        q13, d17, d18           @ idx2weight = y*(32-x)
1859     vmull.u16       q9,  d28, d2            @ idx1weight
1860     vmull.u16       q8,  d29, d3
1861     vmull.u16       q14, d30, d2            @ idx0weight
1862     vmull.u16       q15, d31, d3
1863     vrshrn.u32      d18, q9,  #10           @ idx1weight
1864     vrshrn.u32      d19, q8,  #10
1865     vrshrn.u32      d16, q14, #10           @ idx0weight
1866     vrshrn.u32      d17, q15, #10
1867     vmull.u16       q14, d24, d2            @ idx3weight
1868     vmull.u16       q15, d25, d3
1869     vzip.16         q8,  q9
1870     vmull.u16       q12, d26, d2            @ idx2weight
1871     vmull.u16       q13, d27, d3
1872     vst1.16         {q8, q9},   [r3, :128]!
1873     vrshrn.u32      d19, q15, #10           @ idx3weight
1874     vrshrn.u32      d18, q14, #10
1875     vrshrn.u32      d16, q12, #10           @ idx2weight
1876     vrshrn.u32      d17, q13, #10
1877     vzip.16         q8,  q9
1878     vst1.16         {q8, q9},   [r3, :128]!
1879     bge             8b
1880     bx              lr
1881 endfunc