1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2009 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.
22 *****************************************************************************/
29 // note: prefetch stuff assumes 64-byte cacheline, true for the Cortex-A8
30 // They also use nothing above armv5te, but we don't care about pre-armv6
32 // void prefetch_ref( uint8_t *pix, int stride, int parity )
33 function x264_prefetch_ref_arm
37 add r0, r0, r2, lsl #3
38 add r2, r1, r1, lsl #1
42 add r3, r0, r1, lsl #2
51 // void prefetch_fenc( uint8_t *pix_y, int stride_y,
52 // uint8_t *pix_uv, int stride_uv, int mb_x )
53 function x264_prefetch_fenc_arm
57 smulbb lr, lr, r1 // note: this assumes stride_y is <= 16 bits signed
62 add r0, r0, lr, lsl #2
64 add lr, r0, r1, lsl #1
67 add r2, r2, ip, lsl #2
70 add ip, r2, r3, lsl #1
78 // void *x264_memcpy_aligned( void * dst, const void * src, size_t n )
79 function x264_memcpy_aligned_neon
80 orr r3, r0, r1, lsr #1
81 movrel ip, memcpy_table
86 .macro MEMCPY_ALIGNED srcalign dstalign
87 function memcpy_aligned_\dstalign\()_\srcalign\()_neon
89 .if \srcalign == 8 && \dstalign == 8
91 vld1.64 {d0}, [r1,:64]!
92 vst1.64 {d0}, [r3,:64]!
96 .set r1align, \srcalign * 8
97 .set r3align, \dstalign * 8
102 vld1.64 {d0-d1}, [r1,:r1align]!
103 vst1.64 {d0-d1}, [r3,:r3align]!
104 32: // n is a multiple of 32
108 vld1.64 {d0-d3}, [r1,:r1align]!
109 vst1.64 {d0-d3}, [r3,:r3align]!
110 64: // n is a multiple of 64
112 vld1.64 {d0-d3}, [r1,:r1align]!
113 vld1.64 {d4-d7}, [r1,:r1align]!
114 vst1.64 {d0-d3}, [r3,:r3align]!
115 vst1.64 {d4-d7}, [r3,:r3align]!
117 .if \srcalign == 8 && \dstalign == 8
118 vld1.64 {d0}, [r1,:64]!
119 vst1.64 {d0}, [r3,:64]!
125 MEMCPY_ALIGNED 16, 16
132 .word memcpy_aligned_16_16_neon
133 .word memcpy_aligned_16_8_neon
134 .word memcpy_aligned_8_16_neon
135 .word memcpy_aligned_8_8_neon
140 // void x264_memzero_aligned( void *dst, size_t n )
141 function x264_memzero_aligned_neon
147 vst1.64 {d0-d3}, [r0,:128]!
154 // void pixel_avg( uint8_t *dst, int dst_stride,
155 // uint8_t *src1, int src1_stride,
156 // uint8_t *src2, int src2_stride, int weight );
158 function x264_pixel_avg_\w\()x\h\()_neon
164 beq x264_pixel_avg_w\w\()_neon
166 blt x264_pixel_avg_weight_w\w\()_add_sub_neon // weight > 64
168 bge x264_pixel_avg_weight_w\w\()_add_add_neon
169 b x264_pixel_avg_weight_w\w\()_sub_add_neon // weight < 0
183 .macro load_weights_add_add
188 .macro load_add_add d1 d2
189 vld1.32 {\d1}, [r2], r3
190 vld1.32 {\d2}, [r4], r5
193 .macro weight_add_add dst s1 s2
194 vmull.u8 \dst, \s1, d30
195 vmlal.u8 \dst, \s2, d31
199 .macro load_weights_add_sub
205 .macro load_add_sub d1 d2
206 vld1.32 {\d1}, [r2], r3
207 vld1.32 {\d2}, [r4], r5
210 .macro weight_add_sub dst s1 s2
211 vmull.u8 \dst, \s1, d30
212 vmlsl.u8 \dst, \s2, d31
216 .macro load_weights_sub_add
222 .macro load_sub_add d1 d2
223 vld1.32 {\d2}, [r4], r5
224 vld1.32 {\d1}, [r2], r3
227 .macro weight_sub_add dst s1 s2
228 vmull.u8 \dst, \s2, d31
229 vmlsl.u8 \dst, \s1, d30
232 .macro AVG_WEIGHT ext
233 function x264_pixel_avg_weight_w4_\ext\()_neon
238 weight_\ext q8, d0, d1
240 vqrshrun.s16 d0, q8, #6
241 weight_\ext q9, d2, d3
242 vst1.32 {d0[0]}, [r0,:32], r1
243 vqrshrun.s16 d1, q9, #6
244 vst1.32 {d1[0]}, [r0,:32], r1
249 function x264_pixel_avg_weight_w8_\ext\()_neon
254 weight_\ext q8, d0, d1
256 weight_\ext q9, d2, d3
258 weight_\ext q10, d4, d5
260 weight_\ext q11, d6, d7
261 vqrshrun.s16 d0, q8, #6
262 vqrshrun.s16 d1, q9, #6
263 vqrshrun.s16 d2, q10, #6
264 vqrshrun.s16 d3, q11, #6
265 vst1.64 {d0}, [r0,:64], r1
266 vst1.64 {d1}, [r0,:64], r1
267 vst1.64 {d2}, [r0,:64], r1
268 vst1.64 {d3}, [r0,:64], r1
273 function x264_pixel_avg_weight_w16_\ext\()_neon
277 load_\ext d0-d1, d2-d3
278 weight_\ext q8, d0, d2
279 weight_\ext q9, d1, d3
280 load_\ext d4-d5, d6-d7
281 weight_\ext q10, d4, d6
282 weight_\ext q11, d5, d7
283 vqrshrun.s16 d0, q8, #6
284 vqrshrun.s16 d1, q9, #6
285 vqrshrun.s16 d2, q10, #6
286 vqrshrun.s16 d3, q11, #6
287 vst1.64 {d0-d1}, [r0,:128], r1
288 vst1.64 {d2-d3}, [r0,:128], r1
298 function x264_pixel_avg_w4_neon
300 vld1.32 {d0[]}, [r2], r3
301 vld1.32 {d2[]}, [r4], r5
303 vld1.32 {d1[]}, [r2], r3
304 vld1.32 {d3[]}, [r4], r5
306 vst1.32 {d0[0]}, [r0,:32], r1
307 vst1.32 {d1[0]}, [r0,:32], r1
308 bgt x264_pixel_avg_w4_neon
312 function x264_pixel_avg_w8_neon
314 vld1.64 {d0}, [r2], r3
315 vld1.64 {d2}, [r4], r5
317 vld1.64 {d1}, [r2], r3
318 vld1.64 {d3}, [r4], r5
320 vst1.64 {d0}, [r0,:64], r1
321 vld1.64 {d2}, [r2], r3
322 vld1.64 {d4}, [r4], r5
324 vst1.64 {d1}, [r0,:64], r1
325 vld1.64 {d3}, [r2], r3
326 vld1.64 {d5}, [r4], r5
328 vst1.64 {d2}, [r0,:64], r1
329 vst1.64 {d3}, [r0,:64], r1
330 bgt x264_pixel_avg_w8_neon
334 function x264_pixel_avg_w16_neon
336 vld1.64 {d0-d1}, [r2], r3
337 vld1.64 {d2-d3}, [r4], r5
339 vld1.64 {d2-d3}, [r2], r3
340 vld1.64 {d4-d5}, [r4], r5
342 vst1.64 {d0-d1}, [r0,:128], r1
343 vld1.64 {d4-d5}, [r2], r3
344 vld1.64 {d6-d7}, [r4], r5
346 vst1.64 {d2-d3}, [r0,:128], r1
347 vld1.64 {d6-d7}, [r2], r3
348 vld1.64 {d0-d1}, [r4], r5
350 vst1.64 {d4-d5}, [r0,:128], r1
351 vst1.64 {d6-d7}, [r0,:128], r1
352 bgt x264_pixel_avg_w16_neon
357 function x264_pixel_avg2_w4_neon
363 vld1.32 {d0[]}, [r2], r3
364 vld1.32 {d2[]}, [lr], r3
366 vld1.32 {d1[]}, [r2], r3
367 vld1.32 {d3[]}, [lr], r3
369 vst1.32 {d0[0]}, [r0,:32], r1
370 vst1.32 {d1[0]}, [r0,:32], r1
375 function x264_pixel_avg2_w8_neon
381 vld1.64 {d0}, [r2], r3
382 vld1.64 {d2}, [lr], r3
384 vld1.64 {d1}, [r2], r3
385 vld1.64 {d3}, [lr], r3
387 vst1.64 {d0}, [r0,:64], r1
388 vst1.64 {d1}, [r0,:64], r1
393 function x264_pixel_avg2_w16_neon
399 vld1.64 {d0-d1}, [r2], r3
400 vld1.64 {d2-d3}, [lr], r3
402 vld1.64 {d4-d5}, [r2], r3
403 vld1.64 {d6-d7}, [lr], r3
405 vst1.64 {d0-d1}, [r0,:128], r1
406 vst1.64 {d4-d5}, [r0,:128], r1
411 function x264_pixel_avg2_w20_neon
418 vld1.64 {d0-d2}, [r2], r3
419 vld1.64 {d4-d6}, [lr], r3
422 vld1.64 {d4-d6}, [r2], r3
423 vld1.64 {d16-d18},[lr], r3
425 vst1.64 {d0-d1}, [r0,:128]!
426 vrhadd.u8 d6, d6, d18
427 vst1.32 {d2[0]}, [r0,:32], r1
428 vst1.64 {d4-d5}, [r0,:128]!
429 vst1.32 {d6[0]}, [r0,:32], r1
435 // void mc_copy( uint8_t *dst, int dst_stride, uint8_t *src, int src_stride, int height )
436 function x264_mc_copy_w4_neon
440 vld1.32 {d0[]}, [r2], r3
441 vld1.32 {d1[]}, [r2], r3
442 vld1.32 {d2[]}, [r2], r3
443 vld1.32 {d3[]}, [r2], r3
444 vst1.32 {d0[0]}, [r0,:32], r1
445 vst1.32 {d1[0]}, [r0,:32], r1
446 vst1.32 {d2[0]}, [r0,:32], r1
447 vst1.32 {d3[0]}, [r0,:32], r1
452 function x264_mc_copy_w8_neon
456 vld1.32 {d0}, [r2], r3
457 vld1.32 {d1}, [r2], r3
458 vld1.32 {d2}, [r2], r3
459 vld1.32 {d3}, [r2], r3
460 vst1.32 {d0}, [r0,:64], r1
461 vst1.32 {d1}, [r0,:64], r1
462 vst1.32 {d2}, [r0,:64], r1
463 vst1.32 {d3}, [r0,:64], r1
468 function x264_mc_copy_w16_neon
472 vld1.32 {d0-d1}, [r2], r3
473 vld1.32 {d2-d3}, [r2], r3
474 vld1.32 {d4-d5}, [r2], r3
475 vld1.32 {d6-d7}, [r2], r3
476 vst1.32 {d0-d1}, [r0,:128], r1
477 vst1.32 {d2-d3}, [r0,:128], r1
478 vst1.32 {d4-d5}, [r0,:128], r1
479 vst1.32 {d6-d7}, [r0,:128], r1
484 function x264_mc_copy_w16_aligned_neon
486 copy_w16_aligned_loop:
488 vld1.32 {d0-d1}, [r2,:128], r3
489 vld1.32 {d2-d3}, [r2,:128], r3
490 vld1.32 {d4-d5}, [r2,:128], r3
491 vld1.32 {d6-d7}, [r2,:128], r3
492 vst1.32 {d0-d1}, [r0,:128], r1
493 vst1.32 {d2-d3}, [r0,:128], r1
494 vst1.32 {d4-d5}, [r0,:128], r1
495 vst1.32 {d6-d7}, [r0,:128], r1
496 bgt copy_w16_aligned_loop
501 // void x264_mc_chroma_neon( uint8_t *dst, int i_dst_stride,
502 // uint8_t *src, int i_src_stride,
503 // int dx, int dy, int i_width, int i_height );
504 function x264_mc_chroma_neon
511 add r2, r2, r4, asr #3
523 // calculate cA cB cC cD
524 .macro CHROMA_MC_START r0 r1
526 rsb r6, lr, r5, lsl #3
527 rsb ip, lr, r4, lsl #3
528 sub r4, lr, r4, lsl #3
529 sub r4, r4, r5, lsl #3
539 vld1.64 {\r0}, [r2], r3
541 vld1.64 {\r1}, [r5], r3
545 vext.8 d5, d4, d5, #1
546 vext.8 d7, d6, d7, #1
549 .macro CHROMA_MC width, align
551 CHROMA_MC_START d4, d6
552 // since the element size varies, there's a different index for the 2nd store
565 1: // height loop, interpolate xy
569 vld1.64 {d4}, [r2], r3
570 vext.8 d5, d4, d5, #1
574 vld1.64 {d6}, [r5], r3
575 vadd.i16 d16, d16, d17
576 vadd.i16 d17, d18, d19
577 vrshrn.u16 d16, q8, #6
580 vext.8 d7, d6, d7, #1
582 vst1.\align {d16[0]}, [r0,:\align], r1
583 vst1.\align {d16[st2]}, [r0,:\align], r1
598 vext.32 d1, d0, d1, #1
601 vld1.32 {d4[0]}, [r2], r3
602 vld1.32 {d4[1]}, [r5], r3
604 3: // vertical interpolation loop
607 vld1.32 {d4[0]}, [r2], r3
609 vld1.32 {d4[1]}, [r5], r3
610 vadd.i16 d16, d16, d17
611 vadd.i16 d17, d18, d19
612 vrshrn.u16 d16, q8, #6
615 vst1.\align {d16[0]}, [r0,:\align], r1
616 vst1.\align {d16[st2]}, [r0,:\align], r1
622 vld1.64 {d4}, [r2], r3
623 vld1.64 {d6}, [r2], r3
624 vext.8 d5, d4, d5, #1
625 vext.8 d7, d6, d7, #1
629 5: // horizontal interpolation loop
633 vld1.64 {d4}, [r2], r3
634 vext.8 d5, d4, d5, #1
636 vadd.i16 d16, d16, d17
637 vadd.i16 d17, d18, d19
639 vrshrn.u16 d16, q8, #6
640 vld1.64 {d6}, [r2], r3
641 vext.8 d7, d6, d7, #1
644 vst1.\align {d16[0]}, [r0,:\align], r1
645 vst1.\align {d16[st2]}, [r0,:\align], r1
654 // the optimial timing for width 8 is different enough that it's not
655 // readable to put it in the same macro as width 2/4
657 CHROMA_MC_START d4-d5, d6-d7
659 1: // height loop, interpolate xy
663 vld1.64 {d4, d5}, [r2], r3
665 vext.8 d5, d4, d5, #1
672 vrshrn.u16 d16, q8, #6
673 vld1.64 {d6, d7}, [r5], r3
675 vrshrn.u16 d17, q9, #6
676 vext.8 d7, d6, d7, #1
677 vst1.64 {d16}, [r0,:64], r1
678 vst1.64 {d17}, [r0,:64], r1
694 vld1.64 {d4}, [r2], r3
695 vld1.64 {d6}, [r5], r3
697 3: // vertical interpolation loop
701 vld1.64 {d4}, [r2], r3
704 vld1.64 {d6}, [r5], r3
705 vrshrn.u16 d16, q8, #6
706 vrshrn.u16 d17, q9, #6
709 vst1.64 {d16}, [r0,:64], r1
710 vst1.64 {d17}, [r0,:64], r1
716 vld1.64 {d4, d5}, [r2], r3
717 vld1.64 {d6, d7}, [r2], r3
718 vext.8 d5, d4, d5, #1
719 vext.8 d7, d6, d7, #1
721 5: // horizontal interpolation loop
726 vld1.64 {d4, d5}, [r2], r3
730 vext.8 d5, d4, d5, #1
731 vrshrn.u16 d16, q8, #6
732 vrshrn.u16 d17, q9, #6
733 vld1.64 {d6, d7}, [r2], r3
734 vext.8 d7, d6, d7, #1
735 vst1.64 {d16}, [r0,:64], r1
736 vst1.64 {d17}, [r0,:64], r1
743 // hpel_filter_v( uint8_t *dst, uint8_t *src, int16_t *buf, int stride, int width)
744 function x264_hpel_filter_v_neon
746 sub r1, r1, r3, lsl #1
754 vld1.64 {d0-d1}, [r1,:128], r3
755 vld1.64 {d2-d3}, [r1,:128], r3
756 vld1.64 {d4-d5}, [r1,:128], r3
757 vld1.64 {d6-d7}, [r1,:128], r3
758 vld1.64 {d16-d17}, [r1,:128], r3
759 vld1.64 {d18-d19}, [r1,:128], r3
762 vaddl.u8 q10, d0, d18
763 vmlsl.u8 q10, d2, d30
764 vmlal.u8 q10, d4, d31
765 vmlal.u8 q10, d6, d31
766 vmlsl.u8 q10, d16, d30
768 vaddl.u8 q11, d1, d19
769 vmlsl.u8 q11, d3, d30
770 vmlal.u8 q11, d5, d31
771 vmlal.u8 q11, d7, d31
772 vmlsl.u8 q11, d17, d30
774 vqrshrun.s16 d0, q10, #5
775 vst1.64 {d20-d21}, [r2,:128]!
776 vqrshrun.s16 d1, q11, #5
777 vst1.64 {d22-d23}, [r2,:128]!
778 vst1.64 {d0-d1}, [r0,:128]!
783 // hpel_filter_c( uint8_t *dst, int16_t *buf, int width );
784 function x264_hpel_filter_c_neon
786 vld1.64 {d0-d3}, [r1,:128]!
788 // unrolled 2x: 4% faster
791 vld1.64 {d4-d7}, [r1,:128]!
792 vext.16 q8, q0, q1, #6
793 vext.16 q12, q1, q2, #3
795 vext.16 q9, q0, q1, #7
796 vext.16 q11, q1, q2, #2
798 vext.16 q10, q1, q2, #1
799 vext.16 q11, q1, q2, #6
800 vadd.s16 q10, q1, q10
801 vsub.s16 q8, q8, q9 // a-b
802 vext.16 q15, q2, q3, #3
803 vsub.s16 q9, q9, q10 // b-c
805 vext.16 q12, q1, q2, #7
806 vshr.s16 q8, q8, #2 // (a-b)/4
807 vadd.s16 q11, q11, q15
808 vext.16 q14, q2, q3, #2
809 vsub.s16 q8, q8, q9 // (a-b)/4-b+c
810 vadd.s16 q12, q12, q14
811 vext.16 q13, q2, q3, #1
813 vshr.s16 q8, q8, #2 // ((a-b)/4-b+c)/4
814 vadd.s16 q13, q2, q13
815 vadd.s16 q8, q8, q10 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
816 vsub.s16 q11, q11, q12 // a-b
817 vsub.s16 q12, q12, q13 // b-c
818 vshr.s16 q11, q11, #2 // (a-b)/4
819 vqrshrun.s16 d30, q8, #6
820 vsub.s16 q11, q11, q12 // (a-b)/4-b+c
821 vshr.s16 q11, q11, #2 // ((a-b)/4-b+c)/4
822 vld1.64 {d0-d3}, [r1,:128]!
823 vadd.s16 q11, q11, q13 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
825 vext.16 q8, q2, q3, #6
826 vqrshrun.s16 d31, q11, #6
827 vext.16 q12, q3, q0, #3
829 vext.16 q9, q2, q3, #7
830 vst1.64 {d30-d31}, [r0,:128]!
834 vext.16 q11, q3, q0, #2
836 vext.16 q10, q3, q0, #1
837 vext.16 q11, q3, q0, #6
838 vadd.s16 q10, q3, q10
839 vsub.s16 q8, q8, q9 // a-b
840 vext.16 q15, q0, q1, #3
841 vsub.s16 q9, q9, q10 // b-c
843 vext.16 q12, q3, q0, #7
844 vshr.s16 q8, q8, #2 // (a-b)/4
845 vadd.s16 q11, q11, q15
846 vext.16 q14, q0, q1, #2
847 vsub.s16 q8, q8, q9 // (a-b)/4-b+c
848 vadd.s16 q12, q12, q14
849 vext.16 q13, q0, q1, #1
851 vshr.s16 q8, q8, #2 // ((a-b)/4-b+c)/4
852 vadd.s16 q13, q0, q13
853 vadd.s16 q8, q8, q10 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
854 vsub.s16 q11, q11, q12 // a-b
855 vsub.s16 q12, q12, q13 // b-c
856 vshr.s16 q11, q11, #2 // (a-b)/4
857 vqrshrun.s16 d30, q8, #6
858 vsub.s16 q11, q11, q12 // (a-b)/4-b+c
859 vshr.s16 q11, q11, #2 // ((a-b)/4-b+c)/4
860 vadd.s16 q11, q11, q13 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
862 vqrshrun.s16 d31, q11, #6
863 vst1.64 {d30-d31}, [r0,:128]!
868 // hpel_filter_h( uint8_t *dst, uint8_t *src, int width );
869 function x264_hpel_filter_h_neon
872 vld1.64 {d0-d3}, [r1,:128]!
875 // unrolled 3x because it's 5% faster, due to mitigating
876 // the high latency of multiplication and vqrshrun
879 vld1.64 {d4-d5}, [r1,:128]!
880 vext.8 q8, q0, q1, #14
881 vext.8 q12, q1, q2, #3
882 vaddl.u8 q13, d16, d24
883 vext.8 q9, q0, q1, #15
884 vaddl.u8 q14, d17, d25
886 vext.8 q10, q1, q2, #1
887 vmlal.u8 q13, d2, d31
888 vmlsl.u8 q13, d18, d30
889 vext.8 q11, q1, q2, #2
890 vmlal.u8 q13, d20, d31
891 vmlsl.u8 q13, d22, d30
893 vmlsl.u8 q14, d19, d30
894 vmlal.u8 q14, d3, d31
895 vmlal.u8 q14, d21, d31
896 vmlsl.u8 q14, d23, d30
897 vqrshrun.s16 d6, q13, #5
899 vld1.64 {d0-d1}, [r1,:128]!
900 vext.8 q8, q1, q2, #14
901 vext.8 q12, q2, q0, #3
902 vaddl.u8 q13, d16, d24
903 vqrshrun.s16 d7, q14, #5
904 vext.8 q9, q1, q2, #15
905 vaddl.u8 q14, d17, d25
907 vst1.64 {d6-d7}, [r0,:128]!
911 vext.8 q10, q2, q0, #1
912 vmlal.u8 q13, d4, d31
913 vmlsl.u8 q13, d18, d30
914 vext.8 q11, q2, q0, #2
915 vmlal.u8 q13, d20, d31
916 vmlsl.u8 q13, d22, d30
918 vmlsl.u8 q14, d19, d30
919 vmlal.u8 q14, d5, d31
920 vmlal.u8 q14, d21, d31
921 vmlsl.u8 q14, d23, d30
922 vqrshrun.s16 d6, q13, #5
924 vld1.64 {d2-d3}, [r1,:128]!
925 vext.8 q8, q2, q0, #14
926 vext.8 q12, q0, q1, #3
927 vaddl.u8 q13, d16, d24
928 vqrshrun.s16 d7, q14, #5
929 vext.8 q9, q2, q0, #15
930 vaddl.u8 q14, d17, d25
932 vst1.64 {d6-d7}, [r0,:128]!
936 vext.8 q10, q0, q1, #1
937 vmlal.u8 q13, d0, d31
938 vmlsl.u8 q13, d18, d30
939 vext.8 q11, q0, q1, #2
940 vmlal.u8 q13, d20, d31
941 vmlsl.u8 q13, d22, d30
943 vmlsl.u8 q14, d19, d30
944 vmlal.u8 q14, d1, d31
945 vmlal.u8 q14, d21, d31
946 vmlsl.u8 q14, d23, d30
948 vqrshrun.s16 d6, q13, #5
949 vqrshrun.s16 d7, q14, #5
950 vst1.64 {d6-d7}, [r0,:128]!
956 // frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv,
957 // uint8_t *dstc, int src_stride, int dst_stride, int width,
959 function x264_frame_init_lowres_core_neon
965 sub r10, r6, r7 // dst_stride - width
971 add r8, r0, r5 // src1 = src0 + src_stride
972 add r9, r0, r5, lsl #1 // src2 = src1 + src_stride
974 vld2.8 {d8, d10}, [r6,:128]!
975 vld2.8 {d12,d14}, [r8,:128]!
976 vld2.8 {d16,d18}, [r9,:128]!
981 vld2.8 {d9, d11}, [r6,:128]!
982 vld2.8 {d13,d15}, [r8,:128]!
984 vld2.8 {d17,d19}, [r9,:128]!
986 vld2.8 {d20,d22}, [r6,:128]!
988 vld2.8 {d24,d26}, [r8,:128]!
990 vext.8 q4, q4, q10, #1
992 vext.8 q6, q6, q12, #1
994 vld2.8 {d28,d30}, [r9,:128]!
996 vext.8 q8, q8, q14, #1
998 vst1.64 {d0-d1}, [r1,:128]!
1000 vst1.64 {d2-d3}, [r3,:128]!
1001 vrhadd.u8 q3, q6, q7
1002 vst1.64 {d4-d5}, [r2,:128]!
1003 vst1.64 {d6-d7}, [r4,:128]!
1005 ble lowres_xloop_end
1008 vld2.8 {d21,d23}, [r6,:128]!
1009 vld2.8 {d25,d27}, [r8,:128]!
1010 vrhadd.u8 q0, q10, q12
1011 vld2.8 {d29,d31}, [r9,:128]!
1012 vrhadd.u8 q11, q11, q13
1013 vld2.8 {d8, d10}, [r6,:128]!
1014 vrhadd.u8 q1, q12, q14
1015 vld2.8 {d12,d14}, [r8,:128]!
1016 vrhadd.u8 q13, q13, q15
1017 vext.8 q10, q10, q4, #1
1018 vrhadd.u8 q0, q0, q11
1019 vext.8 q12, q12, q6, #1
1020 vrhadd.u8 q1, q1, q13
1021 vld2.8 {d16,d18}, [r9,:128]!
1022 vrhadd.u8 q10, q10, q12
1023 vext.8 q14, q14, q8, #1
1024 vrhadd.u8 q12, q12, q14
1025 vst1.64 {d0-d1}, [r1,:128]!
1026 vrhadd.u8 q2, q10, q11
1027 vst1.64 {d2-d3}, [r3,:128]!
1028 vrhadd.u8 q3, q12, q13
1029 vst1.64 {d4-d5}, [r2,:128]!
1030 vst1.64 {d6-d7}, [r4,:128]!
1036 add r0, r0, r5, lsl #1