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