1 /*****************************************************************************
2 * mc.S: arm motion compensation
3 *****************************************************************************
4 * Copyright (C) 2009-2010 x264 project
6 * Authors: David Conrad <lessen42@gmail.com>
7 * Mans Rullgard <mans@mansr.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
23 * This program is also available under a commercial proprietary license.
24 * For more information, contact us at licensing@x264.com.
25 *****************************************************************************/
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
35 // void prefetch_ref( uint8_t *pix, int stride, int parity )
36 function x264_prefetch_ref_arm
40 add r0, r0, r2, lsl #3
41 add r2, r1, r1, lsl #1
45 add r3, r0, r1, lsl #2
54 // void prefetch_fenc( uint8_t *pix_y, int stride_y,
55 // uint8_t *pix_uv, int stride_uv, int mb_x )
56 function x264_prefetch_fenc_arm
60 smulbb lr, lr, r1 // note: this assumes stride_y is <= 16 bits signed
65 add r0, r0, lr, lsl #2
67 add lr, r0, r1, lsl #1
70 add r2, r2, ip, lsl #2
73 add ip, r2, r3, lsl #1
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
89 .macro MEMCPY_ALIGNED srcalign dstalign
90 function memcpy_aligned_\dstalign\()_\srcalign\()_neon
92 .if \srcalign == 8 && \dstalign == 8
94 vld1.64 {d0}, [r1,:64]!
95 vst1.64 {d0}, [r3,:64]!
99 .set r1align, \srcalign * 8
100 .set r3align, \dstalign * 8
105 vld1.64 {d0-d1}, [r1,:r1align]!
106 vst1.64 {d0-d1}, [r3,:r3align]!
107 32: // n is a multiple of 32
111 vld1.64 {d0-d3}, [r1,:r1align]!
112 vst1.64 {d0-d3}, [r3,:r3align]!
113 64: // n is a multiple of 64
115 vld1.64 {d0-d3}, [r1,:r1align]!
116 vld1.64 {d4-d7}, [r1,:r1align]!
117 vst1.64 {d0-d3}, [r3,:r3align]!
118 vst1.64 {d4-d7}, [r3,:r3align]!
120 .if \srcalign == 8 && \dstalign == 8
121 vld1.64 {d0}, [r1,:64]!
122 vst1.64 {d0}, [r3,:64]!
128 MEMCPY_ALIGNED 16, 16
135 .word memcpy_aligned_16_16_neon
136 .word memcpy_aligned_16_8_neon
137 .word memcpy_aligned_8_16_neon
138 .word memcpy_aligned_8_8_neon
143 // void x264_memzero_aligned( void *dst, size_t n )
144 function x264_memzero_aligned_neon
150 vst1.64 {d0-d3}, [r0,:128]!
157 // void pixel_avg( uint8_t *dst, int dst_stride,
158 // uint8_t *src1, int src1_stride,
159 // uint8_t *src2, int src2_stride, int weight );
161 function x264_pixel_avg_\w\()x\h\()_neon
167 beq x264_pixel_avg_w\w\()_neon
169 blt x264_pixel_avg_weight_w\w\()_add_sub_neon // weight > 64
171 bge x264_pixel_avg_weight_w\w\()_add_add_neon
172 b x264_pixel_avg_weight_w\w\()_sub_add_neon // weight < 0
186 .macro load_weights_add_add
191 .macro load_add_add d1 d2
192 vld1.32 {\d1}, [r2], r3
193 vld1.32 {\d2}, [r4], r5
196 .macro weight_add_add dst s1 s2
197 vmull.u8 \dst, \s1, d30
198 vmlal.u8 \dst, \s2, d31
202 .macro load_weights_add_sub
208 .macro load_add_sub d1 d2
209 vld1.32 {\d1}, [r2], r3
210 vld1.32 {\d2}, [r4], r5
213 .macro weight_add_sub dst s1 s2
214 vmull.u8 \dst, \s1, d30
215 vmlsl.u8 \dst, \s2, d31
219 .macro load_weights_sub_add
225 .macro load_sub_add d1 d2
226 vld1.32 {\d2}, [r4], r5
227 vld1.32 {\d1}, [r2], r3
230 .macro weight_sub_add dst s1 s2
231 vmull.u8 \dst, \s2, d31
232 vmlsl.u8 \dst, \s1, d30
235 .macro AVG_WEIGHT ext
236 function x264_pixel_avg_weight_w4_\ext\()_neon
241 weight_\ext q8, d0, d1
243 vqrshrun.s16 d0, q8, #6
244 weight_\ext q9, d2, d3
245 vst1.32 {d0[0]}, [r0,:32], r1
246 vqrshrun.s16 d1, q9, #6
247 vst1.32 {d1[0]}, [r0,:32], r1
252 function x264_pixel_avg_weight_w8_\ext\()_neon
257 weight_\ext q8, d0, d1
259 weight_\ext q9, d2, d3
261 weight_\ext q10, d4, d5
263 weight_\ext q11, d6, d7
264 vqrshrun.s16 d0, q8, #6
265 vqrshrun.s16 d1, q9, #6
266 vqrshrun.s16 d2, q10, #6
267 vqrshrun.s16 d3, q11, #6
268 vst1.64 {d0}, [r0,:64], r1
269 vst1.64 {d1}, [r0,:64], r1
270 vst1.64 {d2}, [r0,:64], r1
271 vst1.64 {d3}, [r0,:64], r1
276 function x264_pixel_avg_weight_w16_\ext\()_neon
280 load_\ext d0-d1, d2-d3
281 weight_\ext q8, d0, d2
282 weight_\ext q9, d1, d3
283 load_\ext d4-d5, d6-d7
284 weight_\ext q10, d4, d6
285 weight_\ext q11, d5, d7
286 vqrshrun.s16 d0, q8, #6
287 vqrshrun.s16 d1, q9, #6
288 vqrshrun.s16 d2, q10, #6
289 vqrshrun.s16 d3, q11, #6
290 vst1.64 {d0-d1}, [r0,:128], r1
291 vst1.64 {d2-d3}, [r0,:128], r1
301 function x264_pixel_avg_w4_neon
303 vld1.32 {d0[]}, [r2], r3
304 vld1.32 {d2[]}, [r4], r5
306 vld1.32 {d1[]}, [r2], r3
307 vld1.32 {d3[]}, [r4], r5
309 vst1.32 {d0[0]}, [r0,:32], r1
310 vst1.32 {d1[0]}, [r0,:32], r1
311 bgt x264_pixel_avg_w4_neon
315 function x264_pixel_avg_w8_neon
317 vld1.64 {d0}, [r2], r3
318 vld1.64 {d2}, [r4], r5
320 vld1.64 {d1}, [r2], r3
321 vld1.64 {d3}, [r4], r5
323 vst1.64 {d0}, [r0,:64], r1
324 vld1.64 {d2}, [r2], r3
325 vld1.64 {d4}, [r4], r5
327 vst1.64 {d1}, [r0,:64], r1
328 vld1.64 {d3}, [r2], r3
329 vld1.64 {d5}, [r4], r5
331 vst1.64 {d2}, [r0,:64], r1
332 vst1.64 {d3}, [r0,:64], r1
333 bgt x264_pixel_avg_w8_neon
337 function x264_pixel_avg_w16_neon
339 vld1.64 {d0-d1}, [r2], r3
340 vld1.64 {d2-d3}, [r4], r5
342 vld1.64 {d2-d3}, [r2], r3
343 vld1.64 {d4-d5}, [r4], r5
345 vst1.64 {d0-d1}, [r0,:128], r1
346 vld1.64 {d4-d5}, [r2], r3
347 vld1.64 {d6-d7}, [r4], r5
349 vst1.64 {d2-d3}, [r0,:128], r1
350 vld1.64 {d6-d7}, [r2], r3
351 vld1.64 {d0-d1}, [r4], r5
353 vst1.64 {d4-d5}, [r0,:128], r1
354 vst1.64 {d6-d7}, [r0,:128], r1
355 bgt x264_pixel_avg_w16_neon
360 function x264_pixel_avg2_w4_neon
366 vld1.32 {d0[]}, [r2], r3
367 vld1.32 {d2[]}, [lr], r3
369 vld1.32 {d1[]}, [r2], r3
370 vld1.32 {d3[]}, [lr], r3
372 vst1.32 {d0[0]}, [r0,:32], r1
373 vst1.32 {d1[0]}, [r0,:32], r1
378 function x264_pixel_avg2_w8_neon
384 vld1.64 {d0}, [r2], r3
385 vld1.64 {d2}, [lr], r3
387 vld1.64 {d1}, [r2], r3
388 vld1.64 {d3}, [lr], r3
390 vst1.64 {d0}, [r0,:64], r1
391 vst1.64 {d1}, [r0,:64], r1
396 function x264_pixel_avg2_w16_neon
402 vld1.64 {d0-d1}, [r2], r3
403 vld1.64 {d2-d3}, [lr], r3
405 vld1.64 {d4-d5}, [r2], r3
406 vld1.64 {d6-d7}, [lr], r3
408 vst1.64 {d0-d1}, [r0,:128], r1
409 vst1.64 {d4-d5}, [r0,:128], r1
414 function x264_pixel_avg2_w20_neon
421 vld1.64 {d0-d2}, [r2], r3
422 vld1.64 {d4-d6}, [lr], r3
425 vld1.64 {d4-d6}, [r2], r3
426 vld1.64 {d16-d18},[lr], r3
428 vst1.64 {d0-d1}, [r0,:128]!
429 vrhadd.u8 d6, d6, d18
430 vst1.32 {d2[0]}, [r0,:32], r1
431 vst1.64 {d4-d5}, [r0,:128]!
432 vst1.32 {d6[0]}, [r0,:32], r1
438 .macro weight_prologue type
440 ldr r4, [sp, #4*3] // weight_t
441 ldr ip, [sp, #4*3+4] // h
443 ldr lr, [r4, #32] // denom
445 ldrd r4, [r4, #32+4] // scale, offset
454 // void mc_weight( uint8_t *src, int src_stride, uint8_t *dst, int dst_stride,
455 // const x264_weight_t *weight, int height )
456 function x264_mc_weight_w20_neon
461 vld1.8 {d17-d19}, [r2], r3
465 vld1.8 {d16-d18}, [r2], r3
469 vmul.s16 q10, q10, q0
470 vmul.s16 q11, q11, q0
471 vmul.s16 q12, q12, q0
472 vmul.s16 q13, q13, q0
473 vmul.s16 d28, d28, d0
474 vmul.s16 d29, d30, 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
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
498 function x264_mc_weight_w16_neon
502 vld1.8 {d16-d17}, [r2], r3
503 vld1.8 {d18-d19}, [r2], r3
508 vmul.s16 q10, q10, q0
509 vmul.s16 q11, q11, q0
510 vmul.s16 q12, q12, q0
511 vmul.s16 q13, q13, q0
512 vrshl.s16 q10, q10, q2
513 vrshl.s16 q11, q11, q2
514 vrshl.s16 q12, q12, q2
515 vrshl.s16 q13, q13, q2
516 vadd.s16 q10, q10, q1
517 vadd.s16 q11, q11, q1
518 vadd.s16 q12, q12, q1
519 vadd.s16 q13, q13, q1
524 vst1.8 {d16-d17}, [r0,:128], r1
525 vst1.8 {d18-d19}, [r0,:128], r1
530 function x264_mc_weight_w8_neon
534 vld1.8 {d16}, [r2], r3
535 vld1.8 {d18}, [r2], r3
546 vst1.8 {d16}, [r0,:64], r1
547 vst1.8 {d18}, [r0,:64], r1
552 function x264_mc_weight_w4_neon
556 vld1.32 {d16[]}, [r2], r3
557 vld1.32 {d18[]}, [r2], r3
560 vmul.s16 d16, d16, d0
561 vmul.s16 d17, d18, d0
565 vst1.32 {d16[0]}, [r0,:32], r1
566 vst1.32 {d16[1]}, [r0,:32], r1
571 function x264_mc_weight_w20_nodenom_neon
572 weight_prologue nodenom
574 weight20_nodenom_loop:
576 vld1.8 {d17-d19}, [r2], r3
580 vld1.8 {d16-d18}, [r2], r3
590 vmla.s16 q10, q12, q0
591 vmla.s16 q11, q13, q0
593 vmla.s16 d24, d28, d0
594 vmla.s16 d25, d30, d0
600 vst1.8 {d16-d17}, [r0,:128]!
601 vst1.32 {d20[0]}, [r0,:32], r1
602 vst1.8 {d18-d19}, [r0,:128]!
603 vst1.32 {d20[1]}, [r0,:32], r1
604 bgt weight20_nodenom_loop
608 function x264_mc_weight_w16_nodenom_neon
609 weight_prologue nodenom
610 weight16_nodenom_loop:
612 vld1.8 {d16-d17}, [r2], r3
613 vld1.8 {d18-d19}, [r2], r3
624 vmla.s16 q10, q14, q0
625 vmla.s16 q11, q15, q0
630 vst1.8 {d16-d17}, [r0,:128], r1
631 vst1.8 {d18-d19}, [r0,:128], r1
632 bgt weight16_nodenom_loop
636 function x264_mc_weight_w8_nodenom_neon
637 weight_prologue nodenom
638 weight8_nodenom_loop:
640 vld1.8 {d16}, [r2], r3
641 vld1.8 {d18}, [r2], r3
650 vst1.8 {d16}, [r0,:64], r1
651 vst1.8 {d17}, [r0,:64], r1
652 bgt weight8_nodenom_loop
656 function x264_mc_weight_w4_nodenom_neon
657 weight_prologue nodenom
658 weight4_nodenom_loop:
660 vld1.32 {d16[]}, [r2], r3
661 vld1.32 {d18[]}, [r2], r3
665 vmla.s16 d20, d16, d0
666 vmla.s16 d21, d18, d0
668 vst1.32 {d16[0]}, [r0,:32], r1
669 vst1.32 {d16[1]}, [r0,:32], r1
670 bgt weight4_nodenom_loop
674 .macro weight_simple_prologue
676 ldr lr, [sp, #4] // weight_t
677 ldr ip, [sp, #8] // h
678 ldr lr, [lr] // offset
682 .macro weight_simple name op
683 function x264_mc_weight_w20_\name\()_neon
684 weight_simple_prologue
685 weight20_\name\()_loop:
687 vld1.8 {d16-d18}, [r2], r3
688 vld1.8 {d19-d21}, [r2], r3
692 vst1.8 {d16-d18}, [r0,:64], r1
693 vst1.8 {d19-d21}, [r0,:64], r1
694 bgt weight20_\name\()_loop
698 function x264_mc_weight_w16_\name\()_neon
699 weight_simple_prologue
700 weight16_\name\()_loop:
702 vld1.8 {d16-d17}, [r2], r3
703 vld1.8 {d18-d19}, [r2], r3
706 vst1.8 {d16-d17}, [r0,:128], r1
707 vst1.8 {d18-d19}, [r0,:128], r1
708 bgt weight16_\name\()_loop
712 function x264_mc_weight_w8_\name\()_neon
713 weight_simple_prologue
714 weight8_\name\()_loop:
716 vld1.8 {d16}, [r2], r3
717 vld1.8 {d17}, [r2], r3
719 vst1.8 {d16}, [r0,:64], r1
720 vst1.8 {d17}, [r0,:64], r1
721 bgt weight8_\name\()_loop
725 function x264_mc_weight_w4_\name\()_neon
726 weight_simple_prologue
727 weight4_\name\()_loop:
729 vld1.32 {d16[]}, [r2], r3
730 vld1.32 {d17[]}, [r2], r3
732 vst1.32 {d16[0]}, [r0,:32], r1
733 vst1.32 {d17[0]}, [r0,:32], r1
734 bgt weight4_\name\()_loop
739 weight_simple offsetadd, vqadd.u8
740 weight_simple offsetsub, vqsub.u8
743 // void mc_copy( uint8_t *dst, int dst_stride, uint8_t *src, int src_stride, int height )
744 function x264_mc_copy_w4_neon
748 vld1.32 {d0[]}, [r2], r3
749 vld1.32 {d1[]}, [r2], r3
750 vld1.32 {d2[]}, [r2], r3
751 vld1.32 {d3[]}, [r2], r3
752 vst1.32 {d0[0]}, [r0,:32], r1
753 vst1.32 {d1[0]}, [r0,:32], r1
754 vst1.32 {d2[0]}, [r0,:32], r1
755 vst1.32 {d3[0]}, [r0,:32], r1
760 function x264_mc_copy_w8_neon
764 vld1.32 {d0}, [r2], r3
765 vld1.32 {d1}, [r2], r3
766 vld1.32 {d2}, [r2], r3
767 vld1.32 {d3}, [r2], r3
768 vst1.32 {d0}, [r0,:64], r1
769 vst1.32 {d1}, [r0,:64], r1
770 vst1.32 {d2}, [r0,:64], r1
771 vst1.32 {d3}, [r0,:64], r1
776 function x264_mc_copy_w16_neon
780 vld1.32 {d0-d1}, [r2], r3
781 vld1.32 {d2-d3}, [r2], r3
782 vld1.32 {d4-d5}, [r2], r3
783 vld1.32 {d6-d7}, [r2], r3
784 vst1.32 {d0-d1}, [r0,:128], r1
785 vst1.32 {d2-d3}, [r0,:128], r1
786 vst1.32 {d4-d5}, [r0,:128], r1
787 vst1.32 {d6-d7}, [r0,:128], r1
792 function x264_mc_copy_w16_aligned_neon
794 copy_w16_aligned_loop:
796 vld1.32 {d0-d1}, [r2,:128], r3
797 vld1.32 {d2-d3}, [r2,:128], r3
798 vld1.32 {d4-d5}, [r2,:128], r3
799 vld1.32 {d6-d7}, [r2,:128], r3
800 vst1.32 {d0-d1}, [r0,:128], r1
801 vst1.32 {d2-d3}, [r0,:128], r1
802 vst1.32 {d4-d5}, [r0,:128], r1
803 vst1.32 {d6-d7}, [r0,:128], r1
804 bgt copy_w16_aligned_loop
809 // void x264_mc_chroma_neon( uint8_t *dst, int i_dst_stride,
810 // uint8_t *src, int i_src_stride,
811 // int dx, int dy, int i_width, int i_height );
812 function x264_mc_chroma_neon
819 add r2, r2, r4, asr #3
831 // calculate cA cB cC cD
832 .macro CHROMA_MC_START r0 r1
834 rsb r6, lr, r5, lsl #3
835 rsb ip, lr, r4, lsl #3
836 sub r4, lr, r4, lsl #3
837 sub r4, r4, r5, lsl #3
847 vld1.64 {\r0}, [r2], r3
849 vld1.64 {\r1}, [r5], r3
853 vext.8 d5, d4, d5, #1
854 vext.8 d7, d6, d7, #1
857 .macro CHROMA_MC width, align
859 CHROMA_MC_START d4, d6
860 // since the element size varies, there's a different index for the 2nd store
873 1: // height loop, interpolate xy
877 vld1.64 {d4}, [r2], r3
878 vext.8 d5, d4, d5, #1
882 vld1.64 {d6}, [r5], r3
883 vadd.i16 d16, d16, d17
884 vadd.i16 d17, d18, d19
885 vrshrn.u16 d16, q8, #6
888 vext.8 d7, d6, d7, #1
890 vst1.\align {d16[0]}, [r0,:\align], r1
891 vst1.\align {d16[st2]}, [r0,:\align], r1
906 vext.32 d1, d0, d1, #1
909 vld1.32 {d4[0]}, [r2], r3
910 vld1.32 {d4[1]}, [r5], r3
912 3: // vertical interpolation loop
915 vld1.32 {d4[0]}, [r2], r3
917 vld1.32 {d4[1]}, [r5], r3
918 vadd.i16 d16, d16, d17
919 vadd.i16 d17, d18, d19
920 vrshrn.u16 d16, q8, #6
923 vst1.\align {d16[0]}, [r0,:\align], r1
924 vst1.\align {d16[st2]}, [r0,:\align], r1
930 vld1.64 {d4}, [r2], r3
931 vld1.64 {d6}, [r2], r3
932 vext.8 d5, d4, d5, #1
933 vext.8 d7, d6, d7, #1
937 5: // horizontal interpolation loop
941 vld1.64 {d4}, [r2], r3
942 vext.8 d5, d4, d5, #1
944 vadd.i16 d16, d16, d17
945 vadd.i16 d17, d18, d19
947 vrshrn.u16 d16, q8, #6
948 vld1.64 {d6}, [r2], r3
949 vext.8 d7, d6, d7, #1
952 vst1.\align {d16[0]}, [r0,:\align], r1
953 vst1.\align {d16[st2]}, [r0,:\align], r1
962 // the optimial timing for width 8 is different enough that it's not
963 // readable to put it in the same macro as width 2/4
965 CHROMA_MC_START d4-d5, d6-d7
967 1: // height loop, interpolate xy
971 vld1.64 {d4, d5}, [r2], r3
973 vext.8 d5, d4, d5, #1
980 vrshrn.u16 d16, q8, #6
981 vld1.64 {d6, d7}, [r5], r3
983 vrshrn.u16 d17, q9, #6
984 vext.8 d7, d6, d7, #1
985 vst1.64 {d16}, [r0,:64], r1
986 vst1.64 {d17}, [r0,:64], r1
1002 vld1.64 {d4}, [r2], r3
1003 vld1.64 {d6}, [r5], r3
1005 3: // vertical interpolation loop
1009 vld1.64 {d4}, [r2], r3
1012 vld1.64 {d6}, [r5], r3
1013 vrshrn.u16 d16, q8, #6
1014 vrshrn.u16 d17, q9, #6
1017 vst1.64 {d16}, [r0,:64], r1
1018 vst1.64 {d17}, [r0,:64], r1
1024 vld1.64 {d4, d5}, [r2], r3
1025 vld1.64 {d6, d7}, [r2], r3
1026 vext.8 d5, d4, d5, #1
1027 vext.8 d7, d6, d7, #1
1029 5: // horizontal interpolation loop
1034 vld1.64 {d4, d5}, [r2], r3
1038 vext.8 d5, d4, d5, #1
1039 vrshrn.u16 d16, q8, #6
1040 vrshrn.u16 d17, q9, #6
1041 vld1.64 {d6, d7}, [r2], r3
1042 vext.8 d7, d6, d7, #1
1043 vst1.64 {d16}, [r0,:64], r1
1044 vst1.64 {d17}, [r0,:64], r1
1051 // hpel_filter_v( uint8_t *dst, uint8_t *src, int16_t *buf, int stride, int width)
1052 function x264_hpel_filter_v_neon
1054 sub r1, r1, r3, lsl #1
1062 vld1.64 {d0-d1}, [r1,:128], r3
1063 vld1.64 {d2-d3}, [r1,:128], r3
1064 vld1.64 {d4-d5}, [r1,:128], r3
1065 vld1.64 {d6-d7}, [r1,:128], r3
1066 vld1.64 {d16-d17}, [r1,:128], r3
1067 vld1.64 {d18-d19}, [r1,:128], r3
1070 vaddl.u8 q10, d0, d18
1071 vmlsl.u8 q10, d2, d30
1072 vmlal.u8 q10, d4, d31
1073 vmlal.u8 q10, d6, d31
1074 vmlsl.u8 q10, d16, d30
1076 vaddl.u8 q11, d1, d19
1077 vmlsl.u8 q11, d3, d30
1078 vmlal.u8 q11, d5, d31
1079 vmlal.u8 q11, d7, d31
1080 vmlsl.u8 q11, d17, d30
1082 vqrshrun.s16 d0, q10, #5
1083 vst1.64 {d20-d21}, [r2,:128]!
1084 vqrshrun.s16 d1, q11, #5
1085 vst1.64 {d22-d23}, [r2,:128]!
1086 vst1.64 {d0-d1}, [r0,:128]!
1091 // hpel_filter_c( uint8_t *dst, int16_t *buf, int width );
1092 function x264_hpel_filter_c_neon
1094 vld1.64 {d0-d3}, [r1,:128]!
1096 // unrolled 2x: 4% faster
1099 vld1.64 {d4-d7}, [r1,:128]!
1100 vext.16 q8, q0, q1, #6
1101 vext.16 q12, q1, q2, #3
1102 vadd.s16 q8, q8, q12
1103 vext.16 q9, q0, q1, #7
1104 vext.16 q11, q1, q2, #2
1105 vadd.s16 q9, q9, q11
1106 vext.16 q10, q1, q2, #1
1107 vext.16 q11, q1, q2, #6
1108 vadd.s16 q10, q1, q10
1109 vsub.s16 q8, q8, q9 // a-b
1110 vext.16 q15, q2, q3, #3
1111 vsub.s16 q9, q9, q10 // b-c
1113 vext.16 q12, q1, q2, #7
1114 vshr.s16 q8, q8, #2 // (a-b)/4
1115 vadd.s16 q11, q11, q15
1116 vext.16 q14, q2, q3, #2
1117 vsub.s16 q8, q8, q9 // (a-b)/4-b+c
1118 vadd.s16 q12, q12, q14
1119 vext.16 q13, q2, q3, #1
1121 vshr.s16 q8, q8, #2 // ((a-b)/4-b+c)/4
1122 vadd.s16 q13, q2, q13
1123 vadd.s16 q8, q8, q10 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1124 vsub.s16 q11, q11, q12 // a-b
1125 vsub.s16 q12, q12, q13 // b-c
1126 vshr.s16 q11, q11, #2 // (a-b)/4
1127 vqrshrun.s16 d30, q8, #6
1128 vsub.s16 q11, q11, q12 // (a-b)/4-b+c
1129 vshr.s16 q11, q11, #2 // ((a-b)/4-b+c)/4
1130 vld1.64 {d0-d3}, [r1,:128]!
1131 vadd.s16 q11, q11, q13 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1133 vext.16 q8, q2, q3, #6
1134 vqrshrun.s16 d31, q11, #6
1135 vext.16 q12, q3, q0, #3
1136 vadd.s16 q8, q8, q12
1137 vext.16 q9, q2, q3, #7
1138 vst1.64 {d30-d31}, [r0,:128]!
1142 vext.16 q11, q3, q0, #2
1143 vadd.s16 q9, q9, q11
1144 vext.16 q10, q3, q0, #1
1145 vext.16 q11, q3, q0, #6
1146 vadd.s16 q10, q3, q10
1147 vsub.s16 q8, q8, q9 // a-b
1148 vext.16 q15, q0, q1, #3
1149 vsub.s16 q9, q9, q10 // b-c
1151 vext.16 q12, q3, q0, #7
1152 vshr.s16 q8, q8, #2 // (a-b)/4
1153 vadd.s16 q11, q11, q15
1154 vext.16 q14, q0, q1, #2
1155 vsub.s16 q8, q8, q9 // (a-b)/4-b+c
1156 vadd.s16 q12, q12, q14
1157 vext.16 q13, q0, q1, #1
1159 vshr.s16 q8, q8, #2 // ((a-b)/4-b+c)/4
1160 vadd.s16 q13, q0, q13
1161 vadd.s16 q8, q8, q10 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1162 vsub.s16 q11, q11, q12 // a-b
1163 vsub.s16 q12, q12, q13 // b-c
1164 vshr.s16 q11, q11, #2 // (a-b)/4
1165 vqrshrun.s16 d30, q8, #6
1166 vsub.s16 q11, q11, q12 // (a-b)/4-b+c
1167 vshr.s16 q11, q11, #2 // ((a-b)/4-b+c)/4
1168 vadd.s16 q11, q11, q13 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1170 vqrshrun.s16 d31, q11, #6
1171 vst1.64 {d30-d31}, [r0,:128]!
1176 // hpel_filter_h( uint8_t *dst, uint8_t *src, int width );
1177 function x264_hpel_filter_h_neon
1180 vld1.64 {d0-d3}, [r1,:128]!
1183 // unrolled 3x because it's 5% faster, due to mitigating
1184 // the high latency of multiplication and vqrshrun
1187 vld1.64 {d4-d5}, [r1,:128]!
1188 vext.8 q8, q0, q1, #14
1189 vext.8 q12, q1, q2, #3
1190 vaddl.u8 q13, d16, d24
1191 vext.8 q9, q0, q1, #15
1192 vaddl.u8 q14, d17, d25
1194 vext.8 q10, q1, q2, #1
1195 vmlal.u8 q13, d2, d31
1196 vmlsl.u8 q13, d18, d30
1197 vext.8 q11, q1, q2, #2
1198 vmlal.u8 q13, d20, d31
1199 vmlsl.u8 q13, d22, d30
1201 vmlsl.u8 q14, d19, d30
1202 vmlal.u8 q14, d3, d31
1203 vmlal.u8 q14, d21, d31
1204 vmlsl.u8 q14, d23, d30
1205 vqrshrun.s16 d6, q13, #5
1207 vld1.64 {d0-d1}, [r1,:128]!
1208 vext.8 q8, q1, q2, #14
1209 vext.8 q12, q2, q0, #3
1210 vaddl.u8 q13, d16, d24
1211 vqrshrun.s16 d7, q14, #5
1212 vext.8 q9, q1, q2, #15
1213 vaddl.u8 q14, d17, d25
1215 vst1.64 {d6-d7}, [r0,:128]!
1219 vext.8 q10, q2, q0, #1
1220 vmlal.u8 q13, d4, d31
1221 vmlsl.u8 q13, d18, d30
1222 vext.8 q11, q2, q0, #2
1223 vmlal.u8 q13, d20, d31
1224 vmlsl.u8 q13, d22, d30
1226 vmlsl.u8 q14, d19, d30
1227 vmlal.u8 q14, d5, d31
1228 vmlal.u8 q14, d21, d31
1229 vmlsl.u8 q14, d23, d30
1230 vqrshrun.s16 d6, q13, #5
1232 vld1.64 {d2-d3}, [r1,:128]!
1233 vext.8 q8, q2, q0, #14
1234 vext.8 q12, q0, q1, #3
1235 vaddl.u8 q13, d16, d24
1236 vqrshrun.s16 d7, q14, #5
1237 vext.8 q9, q2, q0, #15
1238 vaddl.u8 q14, d17, d25
1240 vst1.64 {d6-d7}, [r0,:128]!
1244 vext.8 q10, q0, q1, #1
1245 vmlal.u8 q13, d0, d31
1246 vmlsl.u8 q13, d18, d30
1247 vext.8 q11, q0, q1, #2
1248 vmlal.u8 q13, d20, d31
1249 vmlsl.u8 q13, d22, d30
1251 vmlsl.u8 q14, d19, d30
1252 vmlal.u8 q14, d1, d31
1253 vmlal.u8 q14, d21, d31
1254 vmlsl.u8 q14, d23, d30
1256 vqrshrun.s16 d6, q13, #5
1257 vqrshrun.s16 d7, q14, #5
1258 vst1.64 {d6-d7}, [r0,:128]!
1264 // frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv,
1265 // uint8_t *dstc, int src_stride, int dst_stride, int width,
1267 function x264_frame_init_lowres_core_neon
1273 sub r10, r6, r7 // dst_stride - width
1279 add r8, r0, r5 // src1 = src0 + src_stride
1280 add r9, r0, r5, lsl #1 // src2 = src1 + src_stride
1282 vld2.8 {d8, d10}, [r6,:128]!
1283 vld2.8 {d12,d14}, [r8,:128]!
1284 vld2.8 {d16,d18}, [r9,:128]!
1289 vld2.8 {d9, d11}, [r6,:128]!
1290 vld2.8 {d13,d15}, [r8,:128]!
1291 vrhadd.u8 q0, q4, q6
1292 vld2.8 {d17,d19}, [r9,:128]!
1293 vrhadd.u8 q5, q5, q7
1294 vld2.8 {d20,d22}, [r6,:128]!
1295 vrhadd.u8 q1, q6, q8
1296 vld2.8 {d24,d26}, [r8,:128]!
1297 vrhadd.u8 q7, q7, q9
1298 vext.8 q4, q4, q10, #1
1299 vrhadd.u8 q0, q0, q5
1300 vext.8 q6, q6, q12, #1
1301 vrhadd.u8 q1, q1, q7
1302 vld2.8 {d28,d30}, [r9,:128]!
1303 vrhadd.u8 q4, q4, q6
1304 vext.8 q8, q8, q14, #1
1305 vrhadd.u8 q6, q6, q8
1306 vst1.64 {d0-d1}, [r1,:128]!
1307 vrhadd.u8 q2, q4, q5
1308 vst1.64 {d2-d3}, [r3,:128]!
1309 vrhadd.u8 q3, q6, q7
1310 vst1.64 {d4-d5}, [r2,:128]!
1311 vst1.64 {d6-d7}, [r4,:128]!
1313 ble lowres_xloop_end
1316 vld2.8 {d21,d23}, [r6,:128]!
1317 vld2.8 {d25,d27}, [r8,:128]!
1318 vrhadd.u8 q0, q10, q12
1319 vld2.8 {d29,d31}, [r9,:128]!
1320 vrhadd.u8 q11, q11, q13
1321 vld2.8 {d8, d10}, [r6,:128]!
1322 vrhadd.u8 q1, q12, q14
1323 vld2.8 {d12,d14}, [r8,:128]!
1324 vrhadd.u8 q13, q13, q15
1325 vext.8 q10, q10, q4, #1
1326 vrhadd.u8 q0, q0, q11
1327 vext.8 q12, q12, q6, #1
1328 vrhadd.u8 q1, q1, q13
1329 vld2.8 {d16,d18}, [r9,:128]!
1330 vrhadd.u8 q10, q10, q12
1331 vext.8 q14, q14, q8, #1
1332 vrhadd.u8 q12, q12, q14
1333 vst1.64 {d0-d1}, [r1,:128]!
1334 vrhadd.u8 q2, q10, q11
1335 vst1.64 {d2-d3}, [r3,:128]!
1336 vrhadd.u8 q3, q12, q13
1337 vst1.64 {d4-d5}, [r2,:128]!
1338 vst1.64 {d6-d7}, [r4,:128]!
1344 add r0, r0, r5, lsl #1