1;
2;  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3;
4;  Use of this source code is governed by a BSD-style license
5;  that can be found in the LICENSE file in the root of the source
6;  tree. An additional intellectual property rights grant can be found
7;  in the file PATENTS.  All contributing project authors may
8;  be found in the AUTHORS file in the root of the source tree.
9;
10
11    EXPORT  |vp9_lpf_horizontal_16_neon|
12    EXPORT  |vp9_lpf_vertical_16_neon|
13    ARM
14
15    AREA ||.text||, CODE, READONLY, ALIGN=2
16
17; void vp9_lpf_horizontal_16_neon(uint8_t *s, int p,
18;                                 const uint8_t *blimit,
19;                                 const uint8_t *limit,
20;                                 const uint8_t *thresh
21;                                 int count)
22; r0    uint8_t *s,
23; r1    int p, /* pitch */
24; r2    const uint8_t *blimit,
25; r3    const uint8_t *limit,
26; sp    const uint8_t *thresh,
27|vp9_lpf_horizontal_16_neon| PROC
28    push        {r4-r8, lr}
29    vpush       {d8-d15}
30    ldr         r4, [sp, #88]              ; load thresh
31    ldr         r12, [sp, #92]             ; load count
32
33h_count
34    vld1.8      {d16[]}, [r2]              ; load *blimit
35    vld1.8      {d17[]}, [r3]              ; load *limit
36    vld1.8      {d18[]}, [r4]              ; load *thresh
37
38    sub         r8, r0, r1, lsl #3         ; move src pointer down by 8 lines
39
40    vld1.u8     {d0}, [r8@64], r1          ; p7
41    vld1.u8     {d1}, [r8@64], r1          ; p6
42    vld1.u8     {d2}, [r8@64], r1          ; p5
43    vld1.u8     {d3}, [r8@64], r1          ; p4
44    vld1.u8     {d4}, [r8@64], r1          ; p3
45    vld1.u8     {d5}, [r8@64], r1          ; p2
46    vld1.u8     {d6}, [r8@64], r1          ; p1
47    vld1.u8     {d7}, [r8@64], r1          ; p0
48    vld1.u8     {d8}, [r8@64], r1          ; q0
49    vld1.u8     {d9}, [r8@64], r1          ; q1
50    vld1.u8     {d10}, [r8@64], r1         ; q2
51    vld1.u8     {d11}, [r8@64], r1         ; q3
52    vld1.u8     {d12}, [r8@64], r1         ; q4
53    vld1.u8     {d13}, [r8@64], r1         ; q5
54    vld1.u8     {d14}, [r8@64], r1         ; q6
55    vld1.u8     {d15}, [r8@64], r1         ; q7
56
57    bl          vp9_wide_mbfilter_neon
58
59    tst         r7, #1
60    beq         h_mbfilter
61
62    ; flat && mask were not set for any of the channels. Just store the values
63    ; from filter.
64    sub         r8, r0, r1, lsl #1
65
66    vst1.u8     {d25}, [r8@64], r1         ; store op1
67    vst1.u8     {d24}, [r8@64], r1         ; store op0
68    vst1.u8     {d23}, [r8@64], r1         ; store oq0
69    vst1.u8     {d26}, [r8@64], r1         ; store oq1
70
71    b           h_next
72
73h_mbfilter
74    tst         r7, #2
75    beq         h_wide_mbfilter
76
77    ; flat2 was not set for any of the channels. Just store the values from
78    ; mbfilter.
79    sub         r8, r0, r1, lsl #1
80    sub         r8, r8, r1
81
82    vst1.u8     {d18}, [r8@64], r1         ; store op2
83    vst1.u8     {d19}, [r8@64], r1         ; store op1
84    vst1.u8     {d20}, [r8@64], r1         ; store op0
85    vst1.u8     {d21}, [r8@64], r1         ; store oq0
86    vst1.u8     {d22}, [r8@64], r1         ; store oq1
87    vst1.u8     {d23}, [r8@64], r1         ; store oq2
88
89    b           h_next
90
91h_wide_mbfilter
92    sub         r8, r0, r1, lsl #3
93    add         r8, r8, r1
94
95    vst1.u8     {d16}, [r8@64], r1         ; store op6
96    vst1.u8     {d24}, [r8@64], r1         ; store op5
97    vst1.u8     {d25}, [r8@64], r1         ; store op4
98    vst1.u8     {d26}, [r8@64], r1         ; store op3
99    vst1.u8     {d27}, [r8@64], r1         ; store op2
100    vst1.u8     {d18}, [r8@64], r1         ; store op1
101    vst1.u8     {d19}, [r8@64], r1         ; store op0
102    vst1.u8     {d20}, [r8@64], r1         ; store oq0
103    vst1.u8     {d21}, [r8@64], r1         ; store oq1
104    vst1.u8     {d22}, [r8@64], r1         ; store oq2
105    vst1.u8     {d23}, [r8@64], r1         ; store oq3
106    vst1.u8     {d1}, [r8@64], r1          ; store oq4
107    vst1.u8     {d2}, [r8@64], r1          ; store oq5
108    vst1.u8     {d3}, [r8@64], r1          ; store oq6
109
110h_next
111    add         r0, r0, #8
112    subs        r12, r12, #1
113    bne         h_count
114
115    vpop        {d8-d15}
116    pop         {r4-r8, pc}
117
118    ENDP        ; |vp9_lpf_horizontal_16_neon|
119
120; void vp9_lpf_vertical_16_neon(uint8_t *s, int p,
121;                               const uint8_t *blimit,
122;                               const uint8_t *limit,
123;                               const uint8_t *thresh)
124; r0    uint8_t *s,
125; r1    int p, /* pitch */
126; r2    const uint8_t *blimit,
127; r3    const uint8_t *limit,
128; sp    const uint8_t *thresh,
129|vp9_lpf_vertical_16_neon| PROC
130    push        {r4-r8, lr}
131    vpush       {d8-d15}
132    ldr         r4, [sp, #88]              ; load thresh
133
134    vld1.8      {d16[]}, [r2]              ; load *blimit
135    vld1.8      {d17[]}, [r3]              ; load *limit
136    vld1.8      {d18[]}, [r4]              ; load *thresh
137
138    sub         r8, r0, #8
139
140    vld1.8      {d0}, [r8@64], r1
141    vld1.8      {d8}, [r0@64], r1
142    vld1.8      {d1}, [r8@64], r1
143    vld1.8      {d9}, [r0@64], r1
144    vld1.8      {d2}, [r8@64], r1
145    vld1.8      {d10}, [r0@64], r1
146    vld1.8      {d3}, [r8@64], r1
147    vld1.8      {d11}, [r0@64], r1
148    vld1.8      {d4}, [r8@64], r1
149    vld1.8      {d12}, [r0@64], r1
150    vld1.8      {d5}, [r8@64], r1
151    vld1.8      {d13}, [r0@64], r1
152    vld1.8      {d6}, [r8@64], r1
153    vld1.8      {d14}, [r0@64], r1
154    vld1.8      {d7}, [r8@64], r1
155    vld1.8      {d15}, [r0@64], r1
156
157    sub         r0, r0, r1, lsl #3
158
159    vtrn.32     q0, q2
160    vtrn.32     q1, q3
161    vtrn.32     q4, q6
162    vtrn.32     q5, q7
163
164    vtrn.16     q0, q1
165    vtrn.16     q2, q3
166    vtrn.16     q4, q5
167    vtrn.16     q6, q7
168
169    vtrn.8      d0, d1
170    vtrn.8      d2, d3
171    vtrn.8      d4, d5
172    vtrn.8      d6, d7
173
174    vtrn.8      d8, d9
175    vtrn.8      d10, d11
176    vtrn.8      d12, d13
177    vtrn.8      d14, d15
178
179    bl          vp9_wide_mbfilter_neon
180
181    tst         r7, #1
182    beq         v_mbfilter
183
184    ; flat && mask were not set for any of the channels. Just store the values
185    ; from filter.
186    sub         r8, r0, #2
187
188    vswp        d23, d25
189
190    vst4.8      {d23[0], d24[0], d25[0], d26[0]}, [r8], r1
191    vst4.8      {d23[1], d24[1], d25[1], d26[1]}, [r8], r1
192    vst4.8      {d23[2], d24[2], d25[2], d26[2]}, [r8], r1
193    vst4.8      {d23[3], d24[3], d25[3], d26[3]}, [r8], r1
194    vst4.8      {d23[4], d24[4], d25[4], d26[4]}, [r8], r1
195    vst4.8      {d23[5], d24[5], d25[5], d26[5]}, [r8], r1
196    vst4.8      {d23[6], d24[6], d25[6], d26[6]}, [r8], r1
197    vst4.8      {d23[7], d24[7], d25[7], d26[7]}, [r8], r1
198
199    b           v_end
200
201v_mbfilter
202    tst         r7, #2
203    beq         v_wide_mbfilter
204
205    ; flat2 was not set for any of the channels. Just store the values from
206    ; mbfilter.
207    sub         r8, r0, #3
208
209    vst3.8      {d18[0], d19[0], d20[0]}, [r8], r1
210    vst3.8      {d21[0], d22[0], d23[0]}, [r0], r1
211    vst3.8      {d18[1], d19[1], d20[1]}, [r8], r1
212    vst3.8      {d21[1], d22[1], d23[1]}, [r0], r1
213    vst3.8      {d18[2], d19[2], d20[2]}, [r8], r1
214    vst3.8      {d21[2], d22[2], d23[2]}, [r0], r1
215    vst3.8      {d18[3], d19[3], d20[3]}, [r8], r1
216    vst3.8      {d21[3], d22[3], d23[3]}, [r0], r1
217    vst3.8      {d18[4], d19[4], d20[4]}, [r8], r1
218    vst3.8      {d21[4], d22[4], d23[4]}, [r0], r1
219    vst3.8      {d18[5], d19[5], d20[5]}, [r8], r1
220    vst3.8      {d21[5], d22[5], d23[5]}, [r0], r1
221    vst3.8      {d18[6], d19[6], d20[6]}, [r8], r1
222    vst3.8      {d21[6], d22[6], d23[6]}, [r0], r1
223    vst3.8      {d18[7], d19[7], d20[7]}, [r8], r1
224    vst3.8      {d21[7], d22[7], d23[7]}, [r0], r1
225
226    b           v_end
227
228v_wide_mbfilter
229    sub         r8, r0, #8
230
231    vtrn.32     d0,  d26
232    vtrn.32     d16, d27
233    vtrn.32     d24, d18
234    vtrn.32     d25, d19
235
236    vtrn.16     d0,  d24
237    vtrn.16     d16, d25
238    vtrn.16     d26, d18
239    vtrn.16     d27, d19
240
241    vtrn.8      d0,  d16
242    vtrn.8      d24, d25
243    vtrn.8      d26, d27
244    vtrn.8      d18, d19
245
246    vtrn.32     d20, d1
247    vtrn.32     d21, d2
248    vtrn.32     d22, d3
249    vtrn.32     d23, d15
250
251    vtrn.16     d20, d22
252    vtrn.16     d21, d23
253    vtrn.16     d1,  d3
254    vtrn.16     d2,  d15
255
256    vtrn.8      d20, d21
257    vtrn.8      d22, d23
258    vtrn.8      d1,  d2
259    vtrn.8      d3,  d15
260
261    vst1.8      {d0}, [r8@64], r1
262    vst1.8      {d20}, [r0@64], r1
263    vst1.8      {d16}, [r8@64], r1
264    vst1.8      {d21}, [r0@64], r1
265    vst1.8      {d24}, [r8@64], r1
266    vst1.8      {d22}, [r0@64], r1
267    vst1.8      {d25}, [r8@64], r1
268    vst1.8      {d23}, [r0@64], r1
269    vst1.8      {d26}, [r8@64], r1
270    vst1.8      {d1}, [r0@64], r1
271    vst1.8      {d27}, [r8@64], r1
272    vst1.8      {d2}, [r0@64], r1
273    vst1.8      {d18}, [r8@64], r1
274    vst1.8      {d3}, [r0@64], r1
275    vst1.8      {d19}, [r8@64], r1
276    vst1.8      {d15}, [r0@64], r1
277
278v_end
279    vpop        {d8-d15}
280    pop         {r4-r8, pc}
281
282    ENDP        ; |vp9_lpf_vertical_16_neon|
283
284; void vp9_wide_mbfilter_neon();
285; This is a helper function for the loopfilters. The invidual functions do the
286; necessary load, transpose (if necessary) and store.
287;
288; r0-r3 PRESERVE
289; d16    blimit
290; d17    limit
291; d18    thresh
292; d0    p7
293; d1    p6
294; d2    p5
295; d3    p4
296; d4    p3
297; d5    p2
298; d6    p1
299; d7    p0
300; d8    q0
301; d9    q1
302; d10   q2
303; d11   q3
304; d12   q4
305; d13   q5
306; d14   q6
307; d15   q7
308|vp9_wide_mbfilter_neon| PROC
309    mov         r7, #0
310
311    ; filter_mask
312    vabd.u8     d19, d4, d5                ; abs(p3 - p2)
313    vabd.u8     d20, d5, d6                ; abs(p2 - p1)
314    vabd.u8     d21, d6, d7                ; abs(p1 - p0)
315    vabd.u8     d22, d9, d8                ; abs(q1 - q0)
316    vabd.u8     d23, d10, d9               ; abs(q2 - q1)
317    vabd.u8     d24, d11, d10              ; abs(q3 - q2)
318
319    ; only compare the largest value to limit
320    vmax.u8     d19, d19, d20              ; max(abs(p3 - p2), abs(p2 - p1))
321    vmax.u8     d20, d21, d22              ; max(abs(p1 - p0), abs(q1 - q0))
322    vmax.u8     d23, d23, d24              ; max(abs(q2 - q1), abs(q3 - q2))
323    vmax.u8     d19, d19, d20
324
325    vabd.u8     d24, d7, d8                ; abs(p0 - q0)
326
327    vmax.u8     d19, d19, d23
328
329    vabd.u8     d23, d6, d9                ; a = abs(p1 - q1)
330    vqadd.u8    d24, d24, d24              ; b = abs(p0 - q0) * 2
331
332    ; abs () > limit
333    vcge.u8     d19, d17, d19
334
335    ; flatmask4
336    vabd.u8     d25, d7, d5                ; abs(p0 - p2)
337    vabd.u8     d26, d8, d10               ; abs(q0 - q2)
338    vabd.u8     d27, d4, d7                ; abs(p3 - p0)
339    vabd.u8     d28, d11, d8               ; abs(q3 - q0)
340
341    ; only compare the largest value to thresh
342    vmax.u8     d25, d25, d26              ; max(abs(p0 - p2), abs(q0 - q2))
343    vmax.u8     d26, d27, d28              ; max(abs(p3 - p0), abs(q3 - q0))
344    vmax.u8     d25, d25, d26
345    vmax.u8     d20, d20, d25
346
347    vshr.u8     d23, d23, #1               ; a = a / 2
348    vqadd.u8    d24, d24, d23              ; a = b + a
349
350    vmov.u8     d30, #1
351    vcge.u8     d24, d16, d24              ; (a > blimit * 2 + limit) * -1
352
353    vcge.u8     d20, d30, d20              ; flat
354
355    vand        d19, d19, d24              ; mask
356
357    ; hevmask
358    vcgt.u8     d21, d21, d18              ; (abs(p1 - p0) > thresh)*-1
359    vcgt.u8     d22, d22, d18              ; (abs(q1 - q0) > thresh)*-1
360    vorr        d21, d21, d22              ; hev
361
362    vand        d16, d20, d19              ; flat && mask
363    vmov        r5, r6, d16
364
365    ; flatmask5(1, p7, p6, p5, p4, p0, q0, q4, q5, q6, q7)
366    vabd.u8     d22, d3, d7                ; abs(p4 - p0)
367    vabd.u8     d23, d12, d8               ; abs(q4 - q0)
368    vabd.u8     d24, d7, d2                ; abs(p0 - p5)
369    vabd.u8     d25, d8, d13               ; abs(q0 - q5)
370    vabd.u8     d26, d1, d7                ; abs(p6 - p0)
371    vabd.u8     d27, d14, d8               ; abs(q6 - q0)
372    vabd.u8     d28, d0, d7                ; abs(p7 - p0)
373    vabd.u8     d29, d15, d8               ; abs(q7 - q0)
374
375    ; only compare the largest value to thresh
376    vmax.u8     d22, d22, d23              ; max(abs(p4 - p0), abs(q4 - q0))
377    vmax.u8     d23, d24, d25              ; max(abs(p0 - p5), abs(q0 - q5))
378    vmax.u8     d24, d26, d27              ; max(abs(p6 - p0), abs(q6 - q0))
379    vmax.u8     d25, d28, d29              ; max(abs(p7 - p0), abs(q7 - q0))
380
381    vmax.u8     d26, d22, d23
382    vmax.u8     d27, d24, d25
383    vmax.u8     d23, d26, d27
384
385    vcge.u8     d18, d30, d23              ; flat2
386
387    vmov.u8     d22, #0x80
388
389    orrs        r5, r5, r6                 ; Check for 0
390    orreq       r7, r7, #1                 ; Only do filter branch
391
392    vand        d17, d18, d16              ; flat2 && flat && mask
393    vmov        r5, r6, d17
394
395    ; mbfilter() function
396
397    ; filter() function
398    ; convert to signed
399    veor        d23, d8, d22               ; qs0
400    veor        d24, d7, d22               ; ps0
401    veor        d25, d6, d22               ; ps1
402    veor        d26, d9, d22               ; qs1
403
404    vmov.u8     d27, #3
405
406    vsub.s8     d28, d23, d24              ; ( qs0 - ps0)
407    vqsub.s8    d29, d25, d26              ; filter = clamp(ps1-qs1)
408    vmull.s8    q15, d28, d27              ; 3 * ( qs0 - ps0)
409    vand        d29, d29, d21              ; filter &= hev
410    vaddw.s8    q15, q15, d29              ; filter + 3 * (qs0 - ps0)
411    vmov.u8     d29, #4
412
413    ; filter = clamp(filter + 3 * ( qs0 - ps0))
414    vqmovn.s16  d28, q15
415
416    vand        d28, d28, d19              ; filter &= mask
417
418    vqadd.s8    d30, d28, d27              ; filter2 = clamp(filter+3)
419    vqadd.s8    d29, d28, d29              ; filter1 = clamp(filter+4)
420    vshr.s8     d30, d30, #3               ; filter2 >>= 3
421    vshr.s8     d29, d29, #3               ; filter1 >>= 3
422
423
424    vqadd.s8    d24, d24, d30              ; op0 = clamp(ps0 + filter2)
425    vqsub.s8    d23, d23, d29              ; oq0 = clamp(qs0 - filter1)
426
427    ; outer tap adjustments: ++filter1 >> 1
428    vrshr.s8    d29, d29, #1
429    vbic        d29, d29, d21              ; filter &= ~hev
430
431    vqadd.s8    d25, d25, d29              ; op1 = clamp(ps1 + filter)
432    vqsub.s8    d26, d26, d29              ; oq1 = clamp(qs1 - filter)
433
434    veor        d24, d24, d22              ; *f_op0 = u^0x80
435    veor        d23, d23, d22              ; *f_oq0 = u^0x80
436    veor        d25, d25, d22              ; *f_op1 = u^0x80
437    veor        d26, d26, d22              ; *f_oq1 = u^0x80
438
439    tst         r7, #1
440    bxne        lr
441
442    orrs        r5, r5, r6                 ; Check for 0
443    orreq       r7, r7, #2                 ; Only do mbfilter branch
444
445    ; mbfilter flat && mask branch
446    ; TODO(fgalligan): Can I decrease the cycles shifting to consective d's
447    ; and using vibt on the q's?
448    vmov.u8     d29, #2
449    vaddl.u8    q15, d7, d8                ; op2 = p0 + q0
450    vmlal.u8    q15, d4, d27               ; op2 = p0 + q0 + p3 * 3
451    vmlal.u8    q15, d5, d29               ; op2 = p0 + q0 + p3 * 3 + p2 * 2
452    vaddl.u8    q10, d4, d5
453    vaddw.u8    q15, d6                    ; op2=p1 + p0 + q0 + p3 * 3 + p2 *2
454    vaddl.u8    q14, d6, d9
455    vqrshrn.u16 d18, q15, #3               ; r_op2
456
457    vsub.i16    q15, q10
458    vaddl.u8    q10, d4, d6
459    vadd.i16    q15, q14
460    vaddl.u8    q14, d7, d10
461    vqrshrn.u16 d19, q15, #3               ; r_op1
462
463    vsub.i16    q15, q10
464    vadd.i16    q15, q14
465    vaddl.u8    q14, d8, d11
466    vqrshrn.u16 d20, q15, #3               ; r_op0
467
468    vsubw.u8    q15, d4                    ; oq0 = op0 - p3
469    vsubw.u8    q15, d7                    ; oq0 -= p0
470    vadd.i16    q15, q14
471    vaddl.u8    q14, d9, d11
472    vqrshrn.u16 d21, q15, #3               ; r_oq0
473
474    vsubw.u8    q15, d5                    ; oq1 = oq0 - p2
475    vsubw.u8    q15, d8                    ; oq1 -= q0
476    vadd.i16    q15, q14
477    vaddl.u8    q14, d10, d11
478    vqrshrn.u16 d22, q15, #3               ; r_oq1
479
480    vsubw.u8    q15, d6                    ; oq2 = oq0 - p1
481    vsubw.u8    q15, d9                    ; oq2 -= q1
482    vadd.i16    q15, q14
483    vqrshrn.u16 d27, q15, #3               ; r_oq2
484
485    ; Filter does not set op2 or oq2, so use p2 and q2.
486    vbif        d18, d5, d16               ; t_op2 |= p2 & ~(flat & mask)
487    vbif        d19, d25, d16              ; t_op1 |= f_op1 & ~(flat & mask)
488    vbif        d20, d24, d16              ; t_op0 |= f_op0 & ~(flat & mask)
489    vbif        d21, d23, d16              ; t_oq0 |= f_oq0 & ~(flat & mask)
490    vbif        d22, d26, d16              ; t_oq1 |= f_oq1 & ~(flat & mask)
491
492    vbit        d23, d27, d16              ; t_oq2 |= r_oq2 & (flat & mask)
493    vbif        d23, d10, d16              ; t_oq2 |= q2 & ~(flat & mask)
494
495    tst         r7, #2
496    bxne        lr
497
498    ; wide_mbfilter flat2 && flat && mask branch
499    vmov.u8     d16, #7
500    vaddl.u8    q15, d7, d8                ; op6 = p0 + q0
501    vaddl.u8    q12, d2, d3
502    vaddl.u8    q13, d4, d5
503    vaddl.u8    q14, d1, d6
504    vmlal.u8    q15, d0, d16               ; op6 += p7 * 3
505    vadd.i16    q12, q13
506    vadd.i16    q15, q14
507    vaddl.u8    q14, d2, d9
508    vadd.i16    q15, q12
509    vaddl.u8    q12, d0, d1
510    vaddw.u8    q15, d1
511    vaddl.u8    q13, d0, d2
512    vadd.i16    q14, q15, q14
513    vqrshrn.u16 d16, q15, #4               ; w_op6
514
515    vsub.i16    q15, q14, q12
516    vaddl.u8    q14, d3, d10
517    vqrshrn.u16 d24, q15, #4               ; w_op5
518
519    vsub.i16    q15, q13
520    vaddl.u8    q13, d0, d3
521    vadd.i16    q15, q14
522    vaddl.u8    q14, d4, d11
523    vqrshrn.u16 d25, q15, #4               ; w_op4
524
525    vadd.i16    q15, q14
526    vaddl.u8    q14, d0, d4
527    vsub.i16    q15, q13
528    vsub.i16    q14, q15, q14
529    vqrshrn.u16 d26, q15, #4               ; w_op3
530
531    vaddw.u8    q15, q14, d5               ; op2 += p2
532    vaddl.u8    q14, d0, d5
533    vaddw.u8    q15, d12                   ; op2 += q4
534    vbif        d26, d4, d17               ; op3 |= p3 & ~(f2 & f & m)
535    vqrshrn.u16 d27, q15, #4               ; w_op2
536
537    vsub.i16    q15, q14
538    vaddl.u8    q14, d0, d6
539    vaddw.u8    q15, d6                    ; op1 += p1
540    vaddw.u8    q15, d13                   ; op1 += q5
541    vbif        d27, d18, d17              ; op2 |= t_op2 & ~(f2 & f & m)
542    vqrshrn.u16 d18, q15, #4               ; w_op1
543
544    vsub.i16    q15, q14
545    vaddl.u8    q14, d0, d7
546    vaddw.u8    q15, d7                    ; op0 += p0
547    vaddw.u8    q15, d14                   ; op0 += q6
548    vbif        d18, d19, d17              ; op1 |= t_op1 & ~(f2 & f & m)
549    vqrshrn.u16 d19, q15, #4               ; w_op0
550
551    vsub.i16    q15, q14
552    vaddl.u8    q14, d1, d8
553    vaddw.u8    q15, d8                    ; oq0 += q0
554    vaddw.u8    q15, d15                   ; oq0 += q7
555    vbif        d19, d20, d17              ; op0 |= t_op0 & ~(f2 & f & m)
556    vqrshrn.u16 d20, q15, #4               ; w_oq0
557
558    vsub.i16    q15, q14
559    vaddl.u8    q14, d2, d9
560    vaddw.u8    q15, d9                    ; oq1 += q1
561    vaddl.u8    q4, d10, d15
562    vaddw.u8    q15, d15                   ; oq1 += q7
563    vbif        d20, d21, d17              ; oq0 |= t_oq0 & ~(f2 & f & m)
564    vqrshrn.u16 d21, q15, #4               ; w_oq1
565
566    vsub.i16    q15, q14
567    vaddl.u8    q14, d3, d10
568    vadd.i16    q15, q4
569    vaddl.u8    q4, d11, d15
570    vbif        d21, d22, d17              ; oq1 |= t_oq1 & ~(f2 & f & m)
571    vqrshrn.u16 d22, q15, #4               ; w_oq2
572
573    vsub.i16    q15, q14
574    vaddl.u8    q14, d4, d11
575    vadd.i16    q15, q4
576    vaddl.u8    q4, d12, d15
577    vbif        d22, d23, d17              ; oq2 |= t_oq2 & ~(f2 & f & m)
578    vqrshrn.u16 d23, q15, #4               ; w_oq3
579
580    vsub.i16    q15, q14
581    vaddl.u8    q14, d5, d12
582    vadd.i16    q15, q4
583    vaddl.u8    q4, d13, d15
584    vbif        d16, d1, d17               ; op6 |= p6 & ~(f2 & f & m)
585    vqrshrn.u16 d1, q15, #4                ; w_oq4
586
587    vsub.i16    q15, q14
588    vaddl.u8    q14, d6, d13
589    vadd.i16    q15, q4
590    vaddl.u8    q4, d14, d15
591    vbif        d24, d2, d17               ; op5 |= p5 & ~(f2 & f & m)
592    vqrshrn.u16 d2, q15, #4                ; w_oq5
593
594    vsub.i16    q15, q14
595    vbif        d25, d3, d17               ; op4 |= p4 & ~(f2 & f & m)
596    vadd.i16    q15, q4
597    vbif        d23, d11, d17              ; oq3 |= q3 & ~(f2 & f & m)
598    vqrshrn.u16 d3, q15, #4                ; w_oq6
599    vbif        d1, d12, d17               ; oq4 |= q4 & ~(f2 & f & m)
600    vbif        d2, d13, d17               ; oq5 |= q5 & ~(f2 & f & m)
601    vbif        d3, d14, d17               ; oq6 |= q6 & ~(f2 & f & m)
602
603    bx          lr
604    ENDP        ; |vp9_wide_mbfilter_neon|
605
606    END
607