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