mc-a.S
上传用户:lctgjx
上传日期:2022-06-04
资源大小:8887k
文件大小:30k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  * mc.S: h264 encoder
  3.  *****************************************************************************
  4.  * Copyright (C) 2009 x264 project
  5.  *
  6.  * Authors: David Conrad <lessen42@gmail.com>
  7.  *          Mans Rullgard <mans@mansr.com>
  8.  *
  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.
  13.  *
  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.
  18.  *
  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.  *****************************************************************************/
  23. #include "asm.S"
  24. .fpu neon
  25. .text
  26. // note: prefetch stuff assumes 64-byte cacheline, true for the Cortex-A8
  27. // They also use nothing above armv5te, but we don't care about pre-armv6
  28. // void prefetch_ref( uint8_t *pix, int stride, int parity )
  29. function x264_prefetch_ref_arm, export=1
  30.     sub         r2, r2, #1
  31.     add         r0, r0, #64
  32.     and         r2, r2, r1
  33.     add         r0, r0, r2, lsl #3
  34.     add         r2, r1, r1, lsl #1
  35.     pld         [r0]
  36.     pld         [r0, r1]
  37.     pld         [r0, r1, lsl #1]
  38.     add         r3, r0, r1, lsl #2
  39.     pld         [r0, r2]
  40.     pld         [r3]
  41.     pld         [r3, r1]
  42.     pld         [r3, r1, lsl #1]
  43.     pld         [r3, r2]
  44.     bx          lr
  45. .endfunc
  46. // void prefetch_fenc( uint8_t *pix_y, int stride_y,
  47. //                     uint8_t *pix_uv, int stride_uv, int mb_x )
  48. function x264_prefetch_fenc_arm, export=1
  49.     ldr         ip, [sp]
  50.     push        {lr}
  51.     and         lr, ip, #3
  52.     smulbb      lr, lr, r1      // note: this assumes stride_y is <= 16 bits signed
  53.     and         ip, ip, #6
  54.     smulbb      ip, ip, r3
  55.     add         r0, r0, #64
  56.     add         r2, r2, #64
  57.     add         r0, r0, lr, lsl #2
  58.     pld         [r0]
  59.     add         lr, r0, r1, lsl #1
  60.     pld         [r0, r1]
  61.     pld         [lr]
  62.     add         r2, r2, ip, lsl #2
  63.     pld         [lr, r1]
  64.     pld         [r2]
  65.     add         ip, r2, r3, lsl #1
  66.     pld         [r2, r3]
  67.     pld         [ip]
  68.     pld         [ip, r3]
  69.     pop         {pc}
  70. .endfunc
  71. // void *x264_memcpy_aligned( void * dst, const void * src, size_t n )
  72. function x264_memcpy_aligned_neon, export=1
  73.     orr         r3,  r0,  r1,  lsr #1
  74.     movrel      ip,  memcpy_table
  75.     and         r3,  r3,  #0xc
  76.     ldr         pc,  [ip, r3]
  77. .endfunc
  78. .macro MEMCPY_ALIGNED srcalign dstalign
  79. function memcpy_aligned_dstalign()_srcalign()_neon
  80.     mov         r3, r0
  81. .if srcalign == 8 && dstalign == 8
  82.     sub         r2, #16
  83.     vld1.64     {d0}, [r1,:64]!
  84.     vst1.64     {d0}, [r3,:64]!
  85.     .set r1align, 128
  86.     .set r3align, 128
  87. .else
  88.     .set r1align, srcalign * 8
  89.     .set r3align, dstalign * 8
  90. .endif
  91.     tst         r2, #16
  92.     beq         32f
  93.     sub         r2, #16
  94.     vld1.64     {d0-d1}, [r1,:r1align]!
  95.     vst1.64     {d0-d1}, [r3,:r3align]!
  96. 32: // n is a multiple of 32
  97.     tst         r2, #32
  98.     beq         64f
  99.     sub         r2, #32
  100.     vld1.64     {d0-d3}, [r1,:r1align]!
  101.     vst1.64     {d0-d3}, [r3,:r3align]!
  102. 64: // n is a multiple of 64
  103.     subs        r2, #64
  104.     vld1.64     {d0-d3}, [r1,:r1align]!
  105.     vld1.64     {d4-d7}, [r1,:r1align]!
  106.     vst1.64     {d0-d3}, [r3,:r3align]!
  107.     vst1.64     {d4-d7}, [r3,:r3align]!
  108.     bgt         64b
  109. .if srcalign == 8 && dstalign == 8
  110.     vld1.64     {d0}, [r1,:64]!
  111.     vst1.64     {d0}, [r3,:64]!
  112. .endif
  113.     bx          lr
  114. .endfunc
  115. .endm
  116. MEMCPY_ALIGNED 16, 16
  117. MEMCPY_ALIGNED 16, 8
  118. MEMCPY_ALIGNED  8, 16
  119. MEMCPY_ALIGNED  8, 8
  120. .section .rodata
  121. memcpy_table:
  122. .word memcpy_aligned_16_16_neon
  123. .word memcpy_aligned_16_8_neon
  124. .word memcpy_aligned_8_16_neon
  125. .word memcpy_aligned_8_8_neon
  126. .text
  127. .ltorg
  128. // void x264_memzero_aligned( void *dst, size_t n )
  129. function x264_memzero_aligned_neon, export=1
  130.     vmov.i8     q0, #0
  131.     vmov.i8     q1, #0
  132. memzero_loop:
  133.     subs        r1, #128
  134. .rept 4
  135.     vst1.64     {d0-d3}, [r0,:128]!
  136. .endr
  137.     bgt         memzero_loop
  138.     bx          lr
  139. .endfunc
  140. // void pixel_avg( uint8_t *dst, int dst_stride,
  141. //                 uint8_t *src1, int src1_stride,
  142. //                 uint8_t *src2, int src2_stride, int weight );
  143. .macro AVGH w h
  144. function x264_pixel_avg_w()xh()_neon, export=1
  145.     ldr         ip, [sp, #8]
  146.     push        {r4-r6,lr}
  147.     cmp         ip, #32
  148.     ldrd        r4, [sp, #16]
  149.     mov         lr, #h
  150.     beq         x264_pixel_avg_ww()_neon
  151.     rsbs        r6,  ip,  #64
  152.     blt         x264_pixel_avg_weight_ww()_add_sub_neon     // weight > 64
  153.     cmp         ip,  #0
  154.     bge         x264_pixel_avg_weight_ww()_add_add_neon
  155.     b           x264_pixel_avg_weight_ww()_sub_add_neon     // weight < 0
  156. .endfunc
  157. .endm
  158. AVGH  4, 2
  159. AVGH  4, 4
  160. AVGH  4, 8
  161. AVGH  8, 4
  162. AVGH  8, 8
  163. AVGH  8, 16
  164. AVGH 16, 8
  165. AVGH 16, 16
  166. // 0 < weight < 64
  167. .macro load_weights_add_add
  168.     vdup.8      d30, ip
  169.     vdup.8      d31, r6
  170. .endm
  171. .macro load_add_add d1 d2
  172.     vld1.32     {d1}, [r2], r3
  173.     vld1.32     {d2}, [r4], r5
  174. .endm
  175. .macro weight_add_add dst s1 s2
  176.     vmull.u8    dst, s1, d30
  177.     vmlal.u8    dst, s2, d31
  178. .endm
  179. // weight > 64
  180. .macro load_weights_add_sub
  181.     rsb         r6,  #0
  182.     vdup.8      d30, ip
  183.     vdup.8      d31, r6
  184. .endm
  185. .macro load_add_sub d1 d2
  186.     vld1.32     {d1}, [r2], r3
  187.     vld1.32     {d2}, [r4], r5
  188. .endm
  189. .macro weight_add_sub dst s1 s2
  190.     vmull.u8    dst, s1, d30
  191.     vmlsl.u8    dst, s2, d31
  192. .endm
  193. // weight < 0
  194. .macro load_weights_sub_add
  195.     rsb         ip,  #0
  196.     vdup.8      d31, r6
  197.     vdup.8      d30, ip
  198. .endm
  199. .macro load_sub_add d1 d2
  200.     vld1.32     {d2}, [r4], r5
  201.     vld1.32     {d1}, [r2], r3
  202. .endm
  203. .macro weight_sub_add dst s1 s2
  204.     vmull.u8    dst, s2, d31
  205.     vmlsl.u8    dst, s1, d30
  206. .endm
  207. .macro AVG_WEIGHT ext
  208. function x264_pixel_avg_weight_w4_ext()_neon, export=1
  209.     load_weights_ext
  210. 1:  // height loop
  211.     subs            lr,  lr,  #2
  212.     load_ext       d0[], d1[]
  213.     weight_ext     q8,  d0,  d1
  214.     load_ext       d2[], d3[]
  215.     vqrshrun.s16    d0,  q8,  #6
  216.     weight_ext     q9,  d2,  d3
  217.     vst1.32         {d0[0]}, [r0,:32], r1
  218.     vqrshrun.s16    d1,  q9,  #6
  219.     vst1.32         {d1[0]}, [r0,:32], r1
  220.     bgt             1b
  221.     pop             {r4-r6,pc}
  222. .endfunc
  223. function x264_pixel_avg_weight_w8_ext()_neon, export=1
  224.     load_weights_ext
  225. 1:  // height loop
  226.     subs            lr,  lr,  #4
  227.     load_ext       d0,  d1
  228.     weight_ext     q8,  d0,  d1
  229.     load_ext       d2,  d3
  230.     weight_ext     q9,  d2,  d3
  231.     load_ext       d4,  d5
  232.     weight_ext     q10, d4,  d5
  233.     load_ext       d6,  d7
  234.     weight_ext     q11, d6,  d7
  235.     vqrshrun.s16    d0,  q8,  #6
  236.     vqrshrun.s16    d1,  q9,  #6
  237.     vqrshrun.s16    d2,  q10, #6
  238.     vqrshrun.s16    d3,  q11, #6
  239.     vst1.64         {d0}, [r0,:64], r1
  240.     vst1.64         {d1}, [r0,:64], r1
  241.     vst1.64         {d2}, [r0,:64], r1
  242.     vst1.64         {d3}, [r0,:64], r1
  243.     bgt             1b
  244.     pop             {r4-r6,pc}
  245. .endfunc
  246. function x264_pixel_avg_weight_w16_ext()_neon, export=1
  247.     load_weights_ext
  248. 1:  // height loop
  249.     subs            lr,  lr,  #2
  250.     load_ext       d0-d1, d2-d3
  251.     weight_ext     q8,  d0,  d2
  252.     weight_ext     q9,  d1,  d3
  253.     load_ext       d4-d5, d6-d7
  254.     weight_ext     q10, d4,  d6
  255.     weight_ext     q11, d5,  d7
  256.     vqrshrun.s16    d0,  q8,  #6
  257.     vqrshrun.s16    d1,  q9,  #6
  258.     vqrshrun.s16    d2,  q10, #6
  259.     vqrshrun.s16    d3,  q11, #6
  260.     vst1.64         {d0-d1}, [r0,:128], r1
  261.     vst1.64         {d2-d3}, [r0,:128], r1
  262.     bgt             1b
  263.     pop             {r4-r6,pc}
  264. .endfunc
  265. .endm
  266. AVG_WEIGHT add_add
  267. AVG_WEIGHT add_sub
  268. AVG_WEIGHT sub_add
  269. function x264_pixel_avg_w4_neon, export=1
  270.     subs        lr,  lr,  #2
  271.     vld1.32     {d0[]}, [r2], r3
  272.     vld1.32     {d2[]}, [r4], r5
  273.     vrhadd.u8   d0,  d0,  d2
  274.     vld1.32     {d1[]}, [r2], r3
  275.     vld1.32     {d3[]}, [r4], r5
  276.     vrhadd.u8   d1,  d1,  d3
  277.     vst1.32     {d0[0]}, [r0,:32], r1
  278.     vst1.32     {d1[0]}, [r0,:32], r1
  279.     bgt         x264_pixel_avg_w4_neon
  280.     pop         {r4-r6,pc}
  281. .endfunc
  282. function x264_pixel_avg_w8_neon, export=1
  283.     subs        lr,  lr,  #4
  284.     vld1.64     {d0}, [r2], r3
  285.     vld1.64     {d2}, [r4], r5
  286.     vrhadd.u8   d0,  d0,  d2
  287.     vld1.64     {d1}, [r2], r3
  288.     vld1.64     {d3}, [r4], r5
  289.     vrhadd.u8   d1,  d1,  d3
  290.     vst1.64     {d0}, [r0,:64], r1
  291.     vld1.64     {d2}, [r2], r3
  292.     vld1.64     {d4}, [r4], r5
  293.     vrhadd.u8   d2,  d2,  d4
  294.     vst1.64     {d1}, [r0,:64], r1
  295.     vld1.64     {d3}, [r2], r3
  296.     vld1.64     {d5}, [r4], r5
  297.     vrhadd.u8   d3,  d3,  d5
  298.     vst1.64     {d2}, [r0,:64], r1
  299.     vst1.64     {d3}, [r0,:64], r1
  300.     bgt         x264_pixel_avg_w8_neon
  301.     pop         {r4-r6,pc}
  302. .endfunc
  303. function x264_pixel_avg_w16_neon, export=1
  304.     subs        lr,  lr,  #4
  305.     vld1.64     {d0-d1}, [r2], r3
  306.     vld1.64     {d2-d3}, [r4], r5
  307.     vrhadd.u8   q0,  q0,  q1
  308.     vld1.64     {d2-d3}, [r2], r3
  309.     vld1.64     {d4-d5}, [r4], r5
  310.     vrhadd.u8   q1,  q1,  q2
  311.     vst1.64     {d0-d1}, [r0,:128], r1
  312.     vld1.64     {d4-d5}, [r2], r3
  313.     vld1.64     {d6-d7}, [r4], r5
  314.     vrhadd.u8   q2,  q2,  q3
  315.     vst1.64     {d2-d3}, [r0,:128], r1
  316.     vld1.64     {d6-d7}, [r2], r3
  317.     vld1.64     {d0-d1}, [r4], r5
  318.     vrhadd.u8   q3,  q3,  q0
  319.     vst1.64     {d4-d5}, [r0,:128], r1
  320.     vst1.64     {d6-d7}, [r0,:128], r1
  321.     bgt         x264_pixel_avg_w16_neon
  322.     pop         {r4-r6,pc}
  323. .endfunc
  324. function x264_pixel_avg2_w4_neon, export=1
  325.     ldr         ip,  [sp, #4]
  326.     push        {lr}
  327.     ldr         lr,  [sp, #4]
  328. avg2_w4_loop:
  329.     subs        ip,  ip,  #2
  330.     vld1.32     {d0[]},  [r2], r3
  331.     vld1.32     {d2[]},  [lr], r3
  332.     vrhadd.u8   d0,  d0,  d2
  333.     vld1.32     {d1[]},  [r2], r3
  334.     vld1.32     {d3[]},  [lr], r3
  335.     vrhadd.u8   d1,  d1,  d3
  336.     vst1.32     {d0[0]}, [r0,:32], r1
  337.     vst1.32     {d1[0]}, [r0,:32], r1
  338.     bgt         avg2_w4_loop
  339.     pop         {pc}
  340. .endfunc
  341. function x264_pixel_avg2_w8_neon, export=1
  342.     ldr         ip,  [sp, #4]
  343.     push        {lr}
  344.     ldr         lr,  [sp, #4]
  345. avg2_w8_loop:
  346.     subs        ip,  ip,  #2
  347.     vld1.64     {d0}, [r2], r3
  348.     vld1.64     {d2}, [lr], r3
  349.     vrhadd.u8   d0,  d0,  d2
  350.     vld1.64     {d1}, [r2], r3
  351.     vld1.64     {d3}, [lr], r3
  352.     vrhadd.u8   d1,  d1,  d3
  353.     vst1.64     {d0}, [r0,:64], r1
  354.     vst1.64     {d1}, [r0,:64], r1
  355.     bgt         avg2_w8_loop
  356.     pop         {pc}
  357. .endfunc
  358. function x264_pixel_avg2_w16_neon, export=1
  359.     ldr         ip,  [sp, #4]
  360.     push        {lr}
  361.     ldr         lr,  [sp, #4]
  362. avg2_w16_loop:
  363.     subs        ip,  ip,  #2
  364.     vld1.64     {d0-d1}, [r2], r3
  365.     vld1.64     {d2-d3}, [lr], r3
  366.     vrhadd.u8   q0,  q0,  q1
  367.     vld1.64     {d4-d5}, [r2], r3
  368.     vld1.64     {d6-d7}, [lr], r3
  369.     vrhadd.u8   q2,  q2,  q3
  370.     vst1.64     {d0-d1}, [r0,:128], r1
  371.     vst1.64     {d4-d5}, [r0,:128], r1
  372.     bgt         avg2_w16_loop
  373.     pop         {pc}
  374. .endfunc
  375. function x264_pixel_avg2_w20_neon, export=1
  376.     ldr         ip,  [sp, #4]
  377.     push        {lr}
  378.     sub         r1,  r1,  #16
  379.     ldr         lr,  [sp, #4]
  380. avg2_w20_loop:
  381.     subs        ip,  ip,  #2
  382.     vld1.64     {d0-d2},  [r2], r3
  383.     vld1.64     {d4-d6},  [lr], r3
  384.     vrhadd.u8   q0,  q0,  q2
  385.     vrhadd.u8   d2,  d2,  d6
  386.     vld1.64     {d4-d6},  [r2], r3
  387.     vld1.64     {d16-d18},[lr], r3
  388.     vrhadd.u8   q2,  q2,  q8
  389.     vst1.64     {d0-d1},  [r0,:128]!
  390.     vrhadd.u8   d6,  d6,  d18
  391.     vst1.32     {d2[0]},  [r0,:32], r1
  392.     vst1.64     {d4-d5},  [r0,:128]!
  393.     vst1.32     {d6[0]},  [r0,:32], r1
  394.     bgt         avg2_w20_loop
  395.     pop         {pc}
  396. .endfunc
  397. // void mc_copy( uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int height )
  398. function x264_mc_copy_w4_neon, export=1
  399.     ldr         ip,  [sp]
  400. copy_w4_loop:
  401.     subs        ip,  ip,  #4
  402.     vld1.32     {d0[]},  [r2], r3
  403.     vld1.32     {d1[]},  [r2], r3
  404.     vld1.32     {d2[]},  [r2], r3
  405.     vld1.32     {d3[]},  [r2], r3
  406.     vst1.32     {d0[0]}, [r0,:32], r1
  407.     vst1.32     {d1[0]}, [r0,:32], r1
  408.     vst1.32     {d2[0]}, [r0,:32], r1
  409.     vst1.32     {d3[0]}, [r0,:32], r1
  410.     bgt         copy_w4_loop
  411.     bx          lr
  412. .endfunc
  413. function x264_mc_copy_w8_neon, export=1
  414.     ldr         ip,  [sp]
  415. copy_w8_loop:
  416.     subs        ip,  ip,  #4
  417.     vld1.32     {d0}, [r2], r3
  418.     vld1.32     {d1}, [r2], r3
  419.     vld1.32     {d2}, [r2], r3
  420.     vld1.32     {d3}, [r2], r3
  421.     vst1.32     {d0}, [r0,:64], r1
  422.     vst1.32     {d1}, [r0,:64], r1
  423.     vst1.32     {d2}, [r0,:64], r1
  424.     vst1.32     {d3}, [r0,:64], r1
  425.     bgt         copy_w8_loop
  426.     bx          lr
  427. .endfunc
  428. function x264_mc_copy_w16_neon, export=1
  429.     ldr         ip,  [sp]
  430. copy_w16_loop:
  431.     subs        ip,  ip,  #4
  432.     vld1.32     {d0-d1}, [r2], r3
  433.     vld1.32     {d2-d3}, [r2], r3
  434.     vld1.32     {d4-d5}, [r2], r3
  435.     vld1.32     {d6-d7}, [r2], r3
  436.     vst1.32     {d0-d1}, [r0,:128], r1
  437.     vst1.32     {d2-d3}, [r0,:128], r1
  438.     vst1.32     {d4-d5}, [r0,:128], r1
  439.     vst1.32     {d6-d7}, [r0,:128], r1
  440.     bgt         copy_w16_loop
  441.     bx          lr
  442. .endfunc
  443. function x264_mc_copy_w16_aligned_neon, export=1
  444.     ldr         ip,  [sp]
  445. copy_w16_aligned_loop:
  446.     subs        ip,  ip,  #4
  447.     vld1.32     {d0-d1}, [r2,:128], r3
  448.     vld1.32     {d2-d3}, [r2,:128], r3
  449.     vld1.32     {d4-d5}, [r2,:128], r3
  450.     vld1.32     {d6-d7}, [r2,:128], r3
  451.     vst1.32     {d0-d1}, [r0,:128], r1
  452.     vst1.32     {d2-d3}, [r0,:128], r1
  453.     vst1.32     {d4-d5}, [r0,:128], r1
  454.     vst1.32     {d6-d7}, [r0,:128], r1
  455.     bgt         copy_w16_aligned_loop
  456.     bx          lr
  457. .endfunc
  458. // void x264_mc_chroma_neon( uint8_t *dst, int i_dst_stride,
  459. //                           uint8_t *src, int i_src_stride,
  460. //                           int dx, int dy, int i_width, int i_height );
  461. function x264_mc_chroma_neon, export=1
  462.     push            {r4-r6, lr}
  463.     ldrd            r4,  [sp, #16]
  464.     ldr             r6,  [sp, #24]
  465.     asr             lr,  r5,  #3
  466.     mul             lr,  r3,  lr
  467.     add             r2,  r2,  r4,  asr #3
  468.     cmp             r6, #4
  469.     add             r2,  r2,  lr
  470.     and             r4, r4, #7
  471.     and             r5, r5, #7
  472.     pld             [r2]
  473.     pld             [r2, r3]
  474.     bgt             mc_chroma_w8
  475.     beq             mc_chroma_w4
  476. // calculate cA cB cC cD
  477. .macro CHROMA_MC_START r0 r1
  478.     muls            lr,  r4,  r5
  479.     rsb             r6,  lr,  r5,  lsl #3
  480.     rsb             ip,  lr,  r4,  lsl #3
  481.     sub             r4,  lr,  r4,  lsl #3
  482.     sub             r4,  r4,  r5,  lsl #3
  483.     add             r4,  r4,  #64
  484.     beq             2f
  485.     add             r5,  r2,  r3
  486.     vdup.8          d0,  r4
  487.     lsl             r3,  r3,  #1
  488.     vdup.8          d1,  ip
  489.     vld1.64         {r0}, [r2], r3
  490.     vdup.8          d2,  r6
  491.     vld1.64         {r1}, [r5], r3
  492.     vdup.8          d3,  lr
  493.     ldr             r4,  [sp, #28]
  494.     vext.8          d5,  d4,  d5,  #1
  495.     vext.8          d7,  d6,  d7,  #1
  496. .endm
  497. .macro CHROMA_MC width, align
  498. mc_chroma_wwidth:
  499.     CHROMA_MC_START d4,  d6
  500. // since the element size varies, there's a different index for the 2nd store
  501. .if width == 4
  502.     .set st2, 1
  503. .else
  504.     .set st2, 2
  505. .endif
  506.     vtrn.32         d4,  d5
  507.     vtrn.32         d6,  d7
  508.     vtrn.32         d0,  d1
  509.     vtrn.32         d2,  d3
  510. 1:  // height loop, interpolate xy
  511.     pld             [r5]
  512.     vmull.u8        q8,  d4,  d0
  513.     vmlal.u8        q8,  d6,  d2
  514.     vld1.64         {d4},     [r2], r3
  515.     vext.8          d5,  d4,  d5,  #1
  516.     vtrn.32         d4,  d5
  517.     vmull.u8        q9,  d6,  d0
  518.     vmlal.u8        q9,  d4,  d2
  519.     vld1.64         {d6},     [r5], r3
  520.     vadd.i16        d16, d16, d17
  521.     vadd.i16        d17, d18, d19
  522.     vrshrn.u16      d16, q8,  #6
  523.     subs            r4,  r4,  #2
  524.     pld             [r2]
  525.     vext.8          d7,  d6,  d7,  #1
  526.     vtrn.32         d6,  d7
  527.     vst1.align     {d16[0]},   [r0,:align], r1
  528.     vst1.align     {d16[st2]}, [r0,:align], r1
  529.     bgt             1b
  530.     pop             {r4-r6, pc}
  531. 2:  // dx or dy are 0
  532.     tst             r6,  r6
  533.     add             ip,  ip,  r6
  534.     vdup.8          d0,  r4
  535.     vdup.8          d1,  ip
  536.     vtrn.32         d0,  d1
  537.     ldr             r4,  [sp, #28]
  538.     beq             4f
  539.     vext.32         d1,  d0,  d1,  #1
  540.     add             r5,  r2,  r3
  541.     lsl             r3,  r3,  #1
  542.     vld1.32         {d4[0]},  [r2], r3
  543.     vld1.32         {d4[1]},  [r5], r3
  544. 3:  // vertical interpolation loop
  545.     pld             [r5]
  546.     vmull.u8        q8,  d4,  d0
  547.     vld1.32         {d4[0]},  [r2], r3
  548.     vmull.u8        q9,  d4,  d1
  549.     vld1.32         {d4[1]},  [r5], r3
  550.     vadd.i16        d16, d16, d17
  551.     vadd.i16        d17, d18, d19
  552.     vrshrn.u16      d16, q8,  #6
  553.     subs            r4,  r4,  #2
  554.     pld             [r2]
  555.     vst1.align     {d16[0]},   [r0,:align], r1
  556.     vst1.align     {d16[st2]}, [r0,:align], r1
  557.     bgt             3b
  558.     pop             {r4-r6, pc}
  559. 4:  // dy is 0
  560.     vld1.64         {d4},     [r2], r3
  561.     vld1.64         {d6},     [r2], r3
  562.     vext.8          d5,  d4,  d5,  #1
  563.     vext.8          d7,  d6,  d7,  #1
  564.     vtrn.32         d4,  d5
  565.     vtrn.32         d6,  d7
  566. 5:  // horizontal interpolation loop
  567.     vmull.u8        q8,  d4,  d0
  568.     vmull.u8        q9,  d6,  d0
  569.     subs            r4,  r4,  #2
  570.     vld1.64         {d4},     [r2], r3
  571.     vext.8          d5,  d4,  d5,  #1
  572.     vtrn.32         d4,  d5
  573.     vadd.i16        d16, d16, d17
  574.     vadd.i16        d17, d18, d19
  575.     pld             [r2]
  576.     vrshrn.u16      d16, q8,  #6
  577.     vld1.64         {d6},     [r2], r3
  578.     vext.8          d7,  d6,  d7,  #1
  579.     vtrn.32         d6,  d7
  580.     pld             [r2]
  581.     vst1.align     {d16[0]},   [r0,:align], r1
  582.     vst1.align     {d16[st2]}, [r0,:align], r1
  583.     bgt             5b
  584.     pop             {r4-r6, pc}
  585. .endm
  586.     CHROMA_MC 2, 16
  587.     CHROMA_MC 4, 32
  588. // the optimial timing for width 8 is different enough that it's not
  589. // readable to put it in the same macro as width 2/4
  590. mc_chroma_w8:
  591.     CHROMA_MC_START d4-d5, d6-d7
  592. 1:  // height loop, interpolate xy
  593.     pld             [r5]
  594.     vmull.u8        q8,  d4,  d0
  595.     vmlal.u8        q8,  d5,  d1
  596.     vld1.64         {d4, d5}, [r2], r3
  597.     vmlal.u8        q8,  d6,  d2
  598.     vext.8          d5,  d4,  d5,  #1
  599.     vmlal.u8        q8,  d7,  d3
  600.     vmull.u8        q9,  d6,  d0
  601.     subs            r4,  r4,  #2
  602.     vmlal.u8        q9,  d7,  d1
  603.     vmlal.u8        q9,  d4,  d2
  604.     vmlal.u8        q9,  d5,  d3
  605.     vrshrn.u16      d16, q8,  #6
  606.     vld1.64         {d6, d7}, [r5], r3
  607.     pld             [r2]
  608.     vrshrn.u16      d17, q9,  #6
  609.     vext.8          d7,  d6,  d7,  #1
  610.     vst1.64         {d16}, [r0,:64], r1
  611.     vst1.64         {d17}, [r0,:64], r1
  612.     bgt             1b
  613.     pop             {r4-r6, pc}
  614. 2:  // dx or dy are 0
  615.     tst             r6,  r6
  616.     add             ip,  ip,  r6
  617.     vdup.8          d0,  r4
  618.     vdup.8          d1,  ip
  619.     ldr             r4,  [sp, #28]
  620.     beq             4f
  621.     add             r5,  r2,  r3
  622.     lsl             r3,  r3,  #1
  623.     vld1.64         {d4}, [r2], r3
  624.     vld1.64         {d6}, [r5], r3
  625. 3:  // vertical interpolation loop
  626.     pld             [r5]
  627.     vmull.u8        q8,  d4,  d0
  628.     vmlal.u8        q8,  d6,  d1
  629.     vld1.64         {d4}, [r2], r3
  630.     vmull.u8        q9,  d6,  d0
  631.     vmlal.u8        q9,  d4,  d1
  632.     vld1.64         {d6}, [r5], r3
  633.     vrshrn.u16      d16, q8,  #6
  634.     vrshrn.u16      d17, q9,  #6
  635.     subs            r4,  r4,  #2
  636.     pld             [r2]
  637.     vst1.64         {d16}, [r0,:64], r1
  638.     vst1.64         {d17}, [r0,:64], r1
  639.     bgt             3b
  640.     pop             {r4-r6, pc}
  641. 4:  // dy is 0
  642.     vld1.64         {d4, d5}, [r2], r3
  643.     vld1.64         {d6, d7}, [r2], r3
  644.     vext.8          d5,  d4,  d5,  #1
  645.     vext.8          d7,  d6,  d7,  #1
  646. 5:  // horizontal interpolation loop
  647.     pld             [r2]
  648.     subs            r4,  r4,  #2
  649.     vmull.u8        q8,  d4,  d0
  650.     vmlal.u8        q8,  d5,  d1
  651.     vld1.64         {d4,  d5}, [r2], r3
  652.     vmull.u8        q9,  d6,  d0
  653.     vmlal.u8        q9,  d7,  d1
  654.     pld             [r2]
  655.     vext.8          d5,  d4,  d5,  #1
  656.     vrshrn.u16      d16, q8,  #6
  657.     vrshrn.u16      d17, q9,  #6
  658.     vld1.64         {d6, d7}, [r2], r3
  659.     vext.8          d7,  d6,  d7,  #1
  660.     vst1.64         {d16}, [r0,:64], r1
  661.     vst1.64         {d17}, [r0,:64], r1
  662.     bgt             5b
  663.     pop             {r4-r6, pc}
  664. .endfunc
  665. // hpel_filter_v( uint8_t *dst, uint8_t *src, int16_t *buf, int stride, int width)
  666. function x264_hpel_filter_v_neon, export=1
  667.     ldr             ip,  [sp]
  668.     sub             r1,  r1,  r3,  lsl #1
  669.     push            {lr}
  670.     add             lr,  r1,  ip
  671.     vmov.u8         d30, #5
  672.     vmov.u8         d31, #20
  673. filter_v_loop:
  674.     subs            ip,  ip,  #16
  675.     vld1.64         {d0-d1},   [r1,:128], r3
  676.     vld1.64         {d2-d3},   [r1,:128], r3
  677.     vld1.64         {d4-d5},   [r1,:128], r3
  678.     vld1.64         {d6-d7},   [r1,:128], r3
  679.     vld1.64         {d16-d17}, [r1,:128], r3
  680.     vld1.64         {d18-d19}, [r1,:128], r3
  681.     sub             r1,  lr,  ip
  682.     vaddl.u8        q10, d0,  d18
  683.     vmlsl.u8        q10, d2,  d30
  684.     vmlal.u8        q10, d4,  d31
  685.     vmlal.u8        q10, d6,  d31
  686.     vmlsl.u8        q10, d16, d30
  687.     vaddl.u8        q11, d1,  d19
  688.     vmlsl.u8        q11, d3,  d30
  689.     vmlal.u8        q11, d5,  d31
  690.     vmlal.u8        q11, d7,  d31
  691.     vmlsl.u8        q11, d17, d30
  692.     vqrshrun.s16    d0,  q10, #5
  693.     vst1.64         {d20-d21}, [r2,:128]!
  694.     vqrshrun.s16    d1,  q11, #5
  695.     vst1.64         {d22-d23}, [r2,:128]!
  696.     vst1.64         {d0-d1},   [r0,:128]!
  697.     bgt             filter_v_loop
  698.     pop             {pc}
  699. .endfunc
  700. // hpel_filter_c( uint8_t *dst, int16_t *buf, int width );
  701. function x264_hpel_filter_c_neon, export=1
  702.     sub             r1,  #16
  703.     vld1.64         {d0-d3}, [r1,:128]!
  704.     // unrolled 2x: 4% faster
  705. filter_c_loop:
  706.     subs            r2,  r2,  #16
  707.     vld1.64         {d4-d7}, [r1,:128]!
  708.     vext.16         q8,  q0,  q1,  #6
  709.     vext.16         q12, q1,  q2,  #3
  710.     vadd.s16        q8,  q8,  q12
  711.     vext.16         q9,  q0,  q1,  #7
  712.     vext.16         q11, q1,  q2,  #2
  713.     vadd.s16        q9,  q9,  q11
  714.     vext.16         q10, q1,  q2,  #1
  715.     vext.16         q11, q1,  q2,  #6
  716.     vadd.s16        q10, q1,  q10
  717.     vsub.s16        q8,  q8,  q9    // a-b
  718.     vext.16         q15, q2,  q3,  #3
  719.     vsub.s16        q9,  q9,  q10   // b-c
  720.     vext.16         q12, q1,  q2,  #7
  721.     vshr.s16        q8,  q8,  #2    // (a-b)/4
  722.     vadd.s16        q11, q11, q15
  723.     vext.16         q14, q2,  q3,  #2
  724.     vsub.s16        q8,  q8,  q9    // (a-b)/4-b+c
  725.     vadd.s16        q12, q12, q14
  726.     vext.16         q13, q2,  q3,  #1
  727.     vshr.s16        q8,  q8,  #2    // ((a-b)/4-b+c)/4
  728.     vadd.s16        q13, q2,  q13
  729.     vadd.s16        q8,  q8,  q10   // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
  730.     vsub.s16        q11, q11, q12   // a-b
  731.     vsub.s16        q12, q12, q13   // b-c
  732.     vshr.s16        q11, q11, #2    // (a-b)/4
  733.     vqrshrun.s16    d30, q8,  #6
  734.     vsub.s16        q11, q11, q12   // (a-b)/4-b+c
  735.     vshr.s16        q11, q11, #2    // ((a-b)/4-b+c)/4
  736.     vld1.64         {d0-d3}, [r1,:128]!
  737.     vadd.s16        q11, q11, q13   // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
  738.     vext.16         q8,  q2,  q3,  #6
  739.     vqrshrun.s16    d31, q11,  #6
  740.     vext.16         q12, q3,  q0,  #3
  741.     vadd.s16        q8,  q8,  q12
  742.     vext.16         q9,  q2,  q3,  #7
  743.     vst1.64         {d30-d31}, [r0,:128]!
  744.     bxle            lr
  745.     subs            r2,  r2,  #16
  746.     vext.16         q11, q3,  q0,  #2
  747.     vadd.s16        q9,  q9,  q11
  748.     vext.16         q10, q3,  q0,  #1
  749.     vext.16         q11, q3,  q0,  #6
  750.     vadd.s16        q10, q3,  q10
  751.     vsub.s16        q8,  q8,  q9    // a-b
  752.     vext.16         q15, q0,  q1,  #3
  753.     vsub.s16        q9,  q9,  q10   // b-c
  754.     vext.16         q12, q3,  q0,  #7
  755.     vshr.s16        q8,  q8,  #2    // (a-b)/4
  756.     vadd.s16        q11, q11, q15
  757.     vext.16         q14, q0,  q1,  #2
  758.     vsub.s16        q8,  q8,  q9    // (a-b)/4-b+c
  759.     vadd.s16        q12, q12, q14
  760.     vext.16         q13, q0,  q1,  #1
  761.     vshr.s16        q8,  q8,  #2    // ((a-b)/4-b+c)/4
  762.     vadd.s16        q13, q0,  q13
  763.     vadd.s16        q8,  q8,  q10   // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
  764.     vsub.s16        q11, q11, q12   // a-b
  765.     vsub.s16        q12, q12, q13   // b-c
  766.     vshr.s16        q11, q11, #2    // (a-b)/4
  767.     vqrshrun.s16    d30, q8,  #6
  768.     vsub.s16        q11, q11, q12   // (a-b)/4-b+c
  769.     vshr.s16        q11, q11, #2    // ((a-b)/4-b+c)/4
  770.     vadd.s16        q11, q11, q13   // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
  771.     vqrshrun.s16    d31, q11,  #6
  772.     vst1.64         {d30-d31}, [r0,:128]!
  773.     bgt             filter_c_loop
  774.     bx              lr
  775. .endfunc
  776. // hpel_filter_h( uint8_t *dst, uint8_t *src, int width );
  777. function x264_hpel_filter_h_neon, export=1
  778.     sub             r1,  #16
  779.     vmov.u8         d30, #5
  780.     vld1.64         {d0-d3}, [r1,:128]!
  781.     vmov.u8         d31, #20
  782.     // unrolled 3x because it's 5% faster, due to mitigating
  783.     // the high latency of multiplication and vqrshrun
  784. filter_h_loop:
  785.     subs            r2,  r2,  #16
  786.     vld1.64         {d4-d5}, [r1,:128]!
  787.     vext.8          q8,  q0,  q1,  #14
  788.     vext.8          q12, q1,  q2,  #3
  789.     vaddl.u8        q13, d16, d24
  790.     vext.8          q9,  q0,  q1,  #15
  791.     vaddl.u8        q14, d17, d25
  792.     vext.8          q10, q1,  q2,  #1
  793.     vmlal.u8        q13, d2,  d31
  794.     vmlsl.u8        q13, d18, d30
  795.     vext.8          q11, q1,  q2,  #2
  796.     vmlal.u8        q13, d20, d31
  797.     vmlsl.u8        q13, d22, d30
  798.     vmlsl.u8        q14, d19, d30
  799.     vmlal.u8        q14, d3,  d31
  800.     vmlal.u8        q14, d21, d31
  801.     vmlsl.u8        q14, d23, d30
  802.     vqrshrun.s16    d6,  q13, #5
  803.     vld1.64         {d0-d1}, [r1,:128]!
  804.     vext.8          q8,  q1,  q2,  #14
  805.     vext.8          q12, q2,  q0,  #3
  806.     vaddl.u8        q13, d16, d24
  807.     vqrshrun.s16    d7,  q14, #5
  808.     vext.8          q9,  q1,  q2,  #15
  809.     vaddl.u8        q14, d17, d25
  810.     vst1.64         {d6-d7}, [r0,:128]!
  811.     bxle            lr
  812.     subs            r2,  r2,  #16
  813.     vext.8          q10, q2,  q0,  #1
  814.     vmlal.u8        q13, d4,  d31
  815.     vmlsl.u8        q13, d18, d30
  816.     vext.8          q11, q2,  q0,  #2
  817.     vmlal.u8        q13, d20, d31
  818.     vmlsl.u8        q13, d22, d30
  819.     vmlsl.u8        q14, d19, d30
  820.     vmlal.u8        q14, d5,  d31
  821.     vmlal.u8        q14, d21, d31
  822.     vmlsl.u8        q14, d23, d30
  823.     vqrshrun.s16    d6,  q13, #5
  824.     vld1.64         {d2-d3}, [r1,:128]!
  825.     vext.8          q8,  q2,  q0,  #14
  826.     vext.8          q12, q0,  q1,  #3
  827.     vaddl.u8        q13, d16, d24
  828.     vqrshrun.s16    d7,  q14, #5
  829.     vext.8          q9,  q2,  q0,  #15
  830.     vaddl.u8        q14, d17, d25
  831.     vst1.64         {d6-d7}, [r0,:128]!
  832.     bxle            lr
  833.     subs            r2,  r2,  #16
  834.     vext.8          q10, q0,  q1,  #1
  835.     vmlal.u8        q13, d0,  d31
  836.     vmlsl.u8        q13, d18, d30
  837.     vext.8          q11, q0,  q1,  #2
  838.     vmlal.u8        q13, d20, d31
  839.     vmlsl.u8        q13, d22, d30
  840.     vmlsl.u8        q14, d19, d30
  841.     vmlal.u8        q14, d1,  d31
  842.     vmlal.u8        q14, d21, d31
  843.     vmlsl.u8        q14, d23, d30
  844.     vqrshrun.s16    d6, q13, #5
  845.     vqrshrun.s16    d7, q14, #5
  846.     vst1.64         {d6-d7}, [r0,:128]!
  847.     bgt             filter_h_loop
  848.     bx              lr
  849. .endfunc
  850. // frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv,
  851. //                         uint8_t *dstc, int src_stride, int dst_stride, int width,
  852. //                         int height )
  853. function x264_frame_init_lowres_core_neon, export=1
  854.     push            {r4-r10,lr}
  855.     vpush           {d8-d15}
  856.     ldrd            r4,  [sp, #96]
  857.     ldrd            r6,  [sp, #104]
  858.     ldr             lr,  [sp, #112]
  859.     sub             r10, r6,  r7            // dst_stride - width
  860.     and             r10, r10, #~15
  861. lowres_yloop:
  862.     mov             ip,  r7                 // width
  863.     mov             r6,  r0                 // src0
  864.     add             r8,  r0,  r5            // src1 = src0 + src_stride
  865.     add             r9,  r0,  r5,  lsl #1   // src2 = src1 + src_stride
  866.     vld2.8          {d8, d10}, [r6,:128]!
  867.     vld2.8          {d12,d14}, [r8,:128]!
  868.     vld2.8          {d16,d18}, [r9,:128]!
  869. lowres_xloop:
  870.     subs            ip,  ip,  #16
  871.     vld2.8          {d9, d11}, [r6,:128]!
  872.     vld2.8          {d13,d15}, [r8,:128]!
  873.     vrhadd.u8       q0,  q4,  q6
  874.     vld2.8          {d17,d19}, [r9,:128]!
  875.     vrhadd.u8       q5,  q5,  q7
  876.     vld2.8          {d20,d22}, [r6,:128]!
  877.     vrhadd.u8       q1,  q6,  q8
  878.     vld2.8          {d24,d26}, [r8,:128]!
  879.     vrhadd.u8       q7,  q7,  q9
  880.     vext.8          q4,  q4,  q10, #1
  881.     vrhadd.u8       q0,  q0,  q5
  882.     vext.8          q6,  q6,  q12, #1
  883.     vrhadd.u8       q1,  q1,  q7
  884.     vld2.8          {d28,d30}, [r9,:128]!
  885.     vrhadd.u8       q4,  q4,  q6
  886.     vext.8          q8,  q8,  q14, #1
  887.     vrhadd.u8       q6,  q6,  q8
  888.     vst1.64         {d0-d1},   [r1,:128]!
  889.     vrhadd.u8       q2,  q4,  q5
  890.     vst1.64         {d2-d3},   [r3,:128]!
  891.     vrhadd.u8       q3,  q6,  q7
  892.     vst1.64         {d4-d5},   [r2,:128]!
  893.     vst1.64         {d6-d7},   [r4,:128]!
  894.     ble             lowres_xloop_end
  895.     subs            ip,  ip,  #16
  896.     vld2.8          {d21,d23}, [r6,:128]!
  897.     vld2.8          {d25,d27}, [r8,:128]!
  898.     vrhadd.u8       q0,  q10, q12
  899.     vld2.8          {d29,d31}, [r9,:128]!
  900.     vrhadd.u8       q11, q11, q13
  901.     vld2.8          {d8, d10}, [r6,:128]!
  902.     vrhadd.u8       q1,  q12, q14
  903.     vld2.8          {d12,d14}, [r8,:128]!
  904.     vrhadd.u8       q13, q13, q15
  905.     vext.8          q10, q10, q4,  #1
  906.     vrhadd.u8       q0,  q0,  q11
  907.     vext.8          q12, q12, q6,  #1
  908.     vrhadd.u8       q1,  q1,  q13
  909.     vld2.8          {d16,d18}, [r9,:128]!
  910.     vrhadd.u8       q10, q10, q12
  911.     vext.8          q14, q14, q8,  #1
  912.     vrhadd.u8       q12, q12, q14
  913.     vst1.64         {d0-d1},   [r1,:128]!
  914.     vrhadd.u8       q2,  q10, q11
  915.     vst1.64         {d2-d3},   [r3,:128]!
  916.     vrhadd.u8       q3,  q12, q13
  917.     vst1.64         {d4-d5},   [r2,:128]!
  918.     vst1.64         {d6-d7},   [r4,:128]!
  919.     bgt             lowres_xloop
  920. lowres_xloop_end:
  921.     subs            lr,  lr,  #1
  922.     add             r0,  r0,  r5,  lsl #1
  923.     add             r1,  r1,  r10
  924.     add             r2,  r2,  r10
  925.     add             r3,  r3,  r10
  926.     add             r4,  r4,  r10
  927.     bgt             lowres_yloop
  928.     vpop            {d8-d15}
  929.     pop             {r4-r10,pc}
  930. .endfunc