2 ; Copyright (c) 2013 The WebM project authors. All Rights Reserved.
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.
11 EXPORT |vp9_lpf_horizontal_16_neon|
12 EXPORT |vp9_lpf_vertical_16_neon|
15 AREA ||.text||, CODE, READONLY, ALIGN=2
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
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
30 ldr r4, [sp, #88] ; load thresh
31 ldr r12, [sp, #92] ; load count
34 vld1.8 {d16[]}, [r2] ; load *blimit
35 vld1.8 {d17[]}, [r3] ; load *limit
36 vld1.8 {d18[]}, [r4] ; load *thresh
38 sub r8, r0, r1, lsl #3 ; move src pointer down by 8 lines
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
57 bl vp9_wide_mbfilter_neon
62 ; flat && mask were not set for any of the channels. Just store the values
64 sub r8, r0, r1, lsl #1
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
77 ; flat2 was not set for any of the channels. Just store the values from
79 sub r8, r0, r1, lsl #1
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
92 sub r8, r0, r1, lsl #3
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
118 ENDP ; |vp9_lpf_horizontal_16_neon|
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)
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
132 ldr r4, [sp, #88] ; load thresh
134 vld1.8 {d16[]}, [r2] ; load *blimit
135 vld1.8 {d17[]}, [r3] ; load *limit
136 vld1.8 {d18[]}, [r4] ; load *thresh
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
157 sub r0, r0, r1, lsl #3
179 bl vp9_wide_mbfilter_neon
184 ; flat && mask were not set for any of the channels. Just store the values
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
205 ; flat2 was not set for any of the channels. Just store the values from
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
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
282 ENDP ; |vp9_lpf_vertical_16_neon|
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.
308 |vp9_wide_mbfilter_neon| PROC
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)
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
325 vabd.u8 d24, d7, d8 ; abs(p0 - q0)
327 vmax.u8 d19, d19, d23
329 vabd.u8 d23, d6, d9 ; a = abs(p1 - q1)
330 vqadd.u8 d24, d24, d24 ; b = abs(p0 - q0) * 2
333 vcge.u8 d19, d17, d19
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)
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
347 vshr.u8 d23, d23, #1 ; a = a / 2
348 vqadd.u8 d24, d24, d23 ; a = b + a
351 vcge.u8 d24, d16, d24 ; (a > blimit * 2 + limit) * -1
353 vcge.u8 d20, d30, d20 ; flat
355 vand d19, d19, d24 ; mask
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
362 vand d16, d20, d19 ; flat && mask
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)
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))
381 vmax.u8 d26, d22, d23
382 vmax.u8 d27, d24, d25
383 vmax.u8 d23, d26, d27
385 vcge.u8 d18, d30, d23 ; flat2
389 orrs r5, r5, r6 ; Check for 0
390 orreq r7, r7, #1 ; Only do filter branch
392 vand d17, d18, d16 ; flat2 && flat && mask
395 ; mbfilter() function
399 veor d23, d8, d22 ; qs0
400 veor d24, d7, d22 ; ps0
401 veor d25, d6, d22 ; ps1
402 veor d26, d9, d22 ; qs1
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)
413 ; filter = clamp(filter + 3 * ( qs0 - ps0))
416 vand d28, d28, d19 ; filter &= mask
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
424 vqadd.s8 d24, d24, d30 ; op0 = clamp(ps0 + filter2)
425 vqsub.s8 d23, d23, d29 ; oq0 = clamp(qs0 - filter1)
427 ; outer tap adjustments: ++filter1 >> 1
428 vrshr.s8 d29, d29, #1
429 vbic d29, d29, d21 ; filter &= ~hev
431 vqadd.s8 d25, d25, d29 ; op1 = clamp(ps1 + filter)
432 vqsub.s8 d26, d26, d29 ; oq1 = clamp(qs1 - filter)
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
442 orrs r5, r5, r6 ; Check for 0
443 orreq r7, r7, #2 ; Only do mbfilter branch
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?
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
453 vaddw.u8 q15, d6 ; op2=p1 + p0 + q0 + p3 * 3 + p2 *2
455 vqrshrn.u16 d18, q15, #3 ; r_op2
460 vaddl.u8 q14, d7, d10
461 vqrshrn.u16 d19, q15, #3 ; r_op1
465 vaddl.u8 q14, d8, d11
466 vqrshrn.u16 d20, q15, #3 ; r_op0
468 vsubw.u8 q15, d4 ; oq0 = op0 - p3
469 vsubw.u8 q15, d7 ; oq0 -= p0
471 vaddl.u8 q14, d9, d11
472 vqrshrn.u16 d21, q15, #3 ; r_oq0
474 vsubw.u8 q15, d5 ; oq1 = oq0 - p2
475 vsubw.u8 q15, d8 ; oq1 -= q0
477 vaddl.u8 q14, d10, d11
478 vqrshrn.u16 d22, q15, #3 ; r_oq1
480 vsubw.u8 q15, d6 ; oq2 = oq0 - p1
481 vsubw.u8 q15, d9 ; oq2 -= q1
483 vqrshrn.u16 d27, q15, #3 ; r_oq2
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)
492 vbit d23, d27, d16 ; t_oq2 |= r_oq2 & (flat & mask)
493 vbif d23, d10, d16 ; t_oq2 |= q2 & ~(flat & mask)
498 ; wide_mbfilter flat2 && flat && mask branch
500 vaddl.u8 q15, d7, d8 ; op6 = p0 + q0
504 vmlal.u8 q15, d0, d16 ; op6 += p7 * 3
512 vadd.i16 q14, q15, q14
513 vqrshrn.u16 d16, q15, #4 ; w_op6
515 vsub.i16 q15, q14, q12
516 vaddl.u8 q14, d3, d10
517 vqrshrn.u16 d24, q15, #4 ; w_op5
522 vaddl.u8 q14, d4, d11
523 vqrshrn.u16 d25, q15, #4 ; w_op4
528 vsub.i16 q14, q15, q14
529 vqrshrn.u16 d26, q15, #4 ; w_op3
531 vaddw.u8 q15, q14, d5 ; op2 += p2
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
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
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
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
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
567 vaddl.u8 q14, d3, d10
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
574 vaddl.u8 q14, d4, d11
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
581 vaddl.u8 q14, d5, d12
583 vaddl.u8 q4, d13, d15
584 vbif d16, d1, d17 ; op6 |= p6 & ~(f2 & f & m)
585 vqrshrn.u16 d1, q15, #4 ; w_oq4
588 vaddl.u8 q14, d6, d13
590 vaddl.u8 q4, d14, d15
591 vbif d24, d2, d17 ; op5 |= p5 & ~(f2 & f & m)
592 vqrshrn.u16 d2, q15, #4 ; w_oq5
595 vbif d25, d3, d17 ; op4 |= p4 & ~(f2 & f & m)
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)
604 ENDP ; |vp9_wide_mbfilter_neon|