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