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