2 ; Copyright (c) 2010 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.
12 EXPORT |vp8_mbloop_filter_horizontal_edge_y_neon|
13 EXPORT |vp8_mbloop_filter_horizontal_edge_uv_neon|
14 EXPORT |vp8_mbloop_filter_vertical_edge_y_neon|
15 EXPORT |vp8_mbloop_filter_vertical_edge_uv_neon|
18 AREA ||.text||, CODE, READONLY, ALIGN=2
20 ; void vp8_mbloop_filter_horizontal_edge_y_neon(unsigned char *src, int pitch,
21 ; const unsigned char *blimit,
22 ; const unsigned char *limit,
23 ; const unsigned char *thresh)
24 ; r0 unsigned char *src,
26 ; r2 unsigned char blimit
27 ; r3 unsigned char limit
28 ; sp unsigned char thresh,
29 |vp8_mbloop_filter_horizontal_edge_y_neon| PROC
31 add r1, r1, r1 ; double stride
32 ldr r12, [sp, #4] ; load thresh
33 sub r0, r0, r1, lsl #1 ; move src pointer down by 4 lines
34 vdup.u8 q2, r12 ; thresh
35 add r12, r0, r1, lsr #1 ; move src pointer up by 1 line
37 vld1.u8 {q3}, [r0@128], r1 ; p3
38 vld1.u8 {q4}, [r12@128], r1 ; p2
39 vld1.u8 {q5}, [r0@128], r1 ; p1
40 vld1.u8 {q6}, [r12@128], r1 ; p0
41 vld1.u8 {q7}, [r0@128], r1 ; q0
42 vld1.u8 {q8}, [r12@128], r1 ; q1
43 vld1.u8 {q9}, [r0@128], r1 ; q2
44 vld1.u8 {q10}, [r12@128], r1 ; q3
46 bl vp8_mbloop_filter_neon
48 sub r12, r12, r1, lsl #2
49 add r0, r12, r1, lsr #1
51 vst1.u8 {q4}, [r12@128],r1 ; store op2
52 vst1.u8 {q5}, [r0@128],r1 ; store op1
53 vst1.u8 {q6}, [r12@128], r1 ; store op0
54 vst1.u8 {q7}, [r0@128],r1 ; store oq0
55 vst1.u8 {q8}, [r12@128] ; store oq1
56 vst1.u8 {q9}, [r0@128] ; store oq2
59 ENDP ; |vp8_mbloop_filter_horizontal_edge_y_neon|
61 ; void vp8_mbloop_filter_horizontal_edge_uv_neon(unsigned char *u, int pitch,
62 ; const unsigned char *blimit,
63 ; const unsigned char *limit,
64 ; const unsigned char *thresh,
66 ; r0 unsigned char *u,
68 ; r2 unsigned char blimit
69 ; r3 unsigned char limit
70 ; sp unsigned char thresh,
71 ; sp+4 unsigned char *v
73 |vp8_mbloop_filter_horizontal_edge_uv_neon| PROC
75 ldr r12, [sp, #4] ; load thresh
76 sub r0, r0, r1, lsl #2 ; move u pointer down by 4 lines
77 vdup.u8 q2, r12 ; thresh
78 ldr r12, [sp, #8] ; load v ptr
79 sub r12, r12, r1, lsl #2 ; move v pointer down by 4 lines
81 vld1.u8 {d6}, [r0@64], r1 ; p3
82 vld1.u8 {d7}, [r12@64], r1 ; p3
83 vld1.u8 {d8}, [r0@64], r1 ; p2
84 vld1.u8 {d9}, [r12@64], r1 ; p2
85 vld1.u8 {d10}, [r0@64], r1 ; p1
86 vld1.u8 {d11}, [r12@64], r1 ; p1
87 vld1.u8 {d12}, [r0@64], r1 ; p0
88 vld1.u8 {d13}, [r12@64], r1 ; p0
89 vld1.u8 {d14}, [r0@64], r1 ; q0
90 vld1.u8 {d15}, [r12@64], r1 ; q0
91 vld1.u8 {d16}, [r0@64], r1 ; q1
92 vld1.u8 {d17}, [r12@64], r1 ; q1
93 vld1.u8 {d18}, [r0@64], r1 ; q2
94 vld1.u8 {d19}, [r12@64], r1 ; q2
95 vld1.u8 {d20}, [r0@64], r1 ; q3
96 vld1.u8 {d21}, [r12@64], r1 ; q3
98 bl vp8_mbloop_filter_neon
100 sub r0, r0, r1, lsl #3
101 sub r12, r12, r1, lsl #3
106 vst1.u8 {d8}, [r0@64], r1 ; store u op2
107 vst1.u8 {d9}, [r12@64], r1 ; store v op2
108 vst1.u8 {d10}, [r0@64], r1 ; store u op1
109 vst1.u8 {d11}, [r12@64], r1 ; store v op1
110 vst1.u8 {d12}, [r0@64], r1 ; store u op0
111 vst1.u8 {d13}, [r12@64], r1 ; store v op0
112 vst1.u8 {d14}, [r0@64], r1 ; store u oq0
113 vst1.u8 {d15}, [r12@64], r1 ; store v oq0
114 vst1.u8 {d16}, [r0@64], r1 ; store u oq1
115 vst1.u8 {d17}, [r12@64], r1 ; store v oq1
116 vst1.u8 {d18}, [r0@64], r1 ; store u oq2
117 vst1.u8 {d19}, [r12@64], r1 ; store v oq2
120 ENDP ; |vp8_mbloop_filter_horizontal_edge_uv_neon|
122 ; void vp8_mbloop_filter_vertical_edge_y_neon(unsigned char *src, int pitch,
123 ; const unsigned char *blimit,
124 ; const unsigned char *limit,
125 ; const unsigned char *thresh)
126 ; r0 unsigned char *src,
128 ; r2 unsigned char blimit
129 ; r3 unsigned char limit
130 ; sp unsigned char thresh,
131 |vp8_mbloop_filter_vertical_edge_y_neon| PROC
133 ldr r12, [sp, #4] ; load thresh
134 sub r0, r0, #4 ; move src pointer down by 4 columns
135 vdup.s8 q2, r12 ; thresh
136 add r12, r0, r1, lsl #3 ; move src pointer down by 8 lines
138 vld1.u8 {d6}, [r0], r1 ; load first 8-line src data
139 vld1.u8 {d7}, [r12], r1 ; load second 8-line src data
140 vld1.u8 {d8}, [r0], r1
141 vld1.u8 {d9}, [r12], r1
142 vld1.u8 {d10}, [r0], r1
143 vld1.u8 {d11}, [r12], r1
144 vld1.u8 {d12}, [r0], r1
145 vld1.u8 {d13}, [r12], r1
146 vld1.u8 {d14}, [r0], r1
147 vld1.u8 {d15}, [r12], r1
148 vld1.u8 {d16}, [r0], r1
149 vld1.u8 {d17}, [r12], r1
150 vld1.u8 {d18}, [r0], r1
151 vld1.u8 {d19}, [r12], r1
152 vld1.u8 {d20}, [r0], r1
153 vld1.u8 {d21}, [r12], r1
155 ;transpose to 8x16 matrix
171 sub r0, r0, r1, lsl #3
173 bl vp8_mbloop_filter_neon
175 sub r12, r12, r1, lsl #3
177 ;transpose to 16x8 matrix
193 ;store op2, op1, op0, oq0, oq1, oq2
194 vst1.8 {d6}, [r0], r1
195 vst1.8 {d7}, [r12], r1
196 vst1.8 {d8}, [r0], r1
197 vst1.8 {d9}, [r12], r1
198 vst1.8 {d10}, [r0], r1
199 vst1.8 {d11}, [r12], r1
200 vst1.8 {d12}, [r0], r1
201 vst1.8 {d13}, [r12], r1
202 vst1.8 {d14}, [r0], r1
203 vst1.8 {d15}, [r12], r1
204 vst1.8 {d16}, [r0], r1
205 vst1.8 {d17}, [r12], r1
206 vst1.8 {d18}, [r0], r1
207 vst1.8 {d19}, [r12], r1
212 ENDP ; |vp8_mbloop_filter_vertical_edge_y_neon|
214 ; void vp8_mbloop_filter_vertical_edge_uv_neon(unsigned char *u, int pitch,
215 ; const unsigned char *blimit,
216 ; const unsigned char *limit,
217 ; const unsigned char *thresh,
219 ; r0 unsigned char *u,
221 ; r2 const signed char *flimit,
222 ; r3 const signed char *limit,
223 ; sp const signed char *thresh,
224 ; sp+4 unsigned char *v
225 |vp8_mbloop_filter_vertical_edge_uv_neon| PROC
227 ldr r12, [sp, #4] ; load thresh
228 sub r0, r0, #4 ; move u pointer down by 4 columns
229 vdup.u8 q2, r12 ; thresh
230 ldr r12, [sp, #8] ; load v ptr
231 sub r12, r12, #4 ; move v pointer down by 4 columns
233 vld1.u8 {d6}, [r0], r1 ;load u data
234 vld1.u8 {d7}, [r12], r1 ;load v data
235 vld1.u8 {d8}, [r0], r1
236 vld1.u8 {d9}, [r12], r1
237 vld1.u8 {d10}, [r0], r1
238 vld1.u8 {d11}, [r12], r1
239 vld1.u8 {d12}, [r0], r1
240 vld1.u8 {d13}, [r12], r1
241 vld1.u8 {d14}, [r0], r1
242 vld1.u8 {d15}, [r12], r1
243 vld1.u8 {d16}, [r0], r1
244 vld1.u8 {d17}, [r12], r1
245 vld1.u8 {d18}, [r0], r1
246 vld1.u8 {d19}, [r12], r1
247 vld1.u8 {d20}, [r0], r1
248 vld1.u8 {d21}, [r12], r1
250 ;transpose to 8x16 matrix
266 sub r0, r0, r1, lsl #3
268 bl vp8_mbloop_filter_neon
270 sub r12, r12, r1, lsl #3
272 ;transpose to 16x8 matrix
288 ;store op2, op1, op0, oq0, oq1, oq2
289 vst1.8 {d6}, [r0], r1
290 vst1.8 {d7}, [r12], r1
291 vst1.8 {d8}, [r0], r1
292 vst1.8 {d9}, [r12], r1
293 vst1.8 {d10}, [r0], r1
294 vst1.8 {d11}, [r12], r1
295 vst1.8 {d12}, [r0], r1
296 vst1.8 {d13}, [r12], r1
297 vst1.8 {d14}, [r0], r1
298 vst1.8 {d15}, [r12], r1
299 vst1.8 {d16}, [r0], r1
300 vst1.8 {d17}, [r12], r1
301 vst1.8 {d18}, [r0], r1
302 vst1.8 {d19}, [r12], r1
307 ENDP ; |vp8_mbloop_filter_vertical_edge_uv_neon|
309 ; void vp8_mbloop_filter_neon()
310 ; This is a helper function for the macroblock loopfilters. The individual
311 ; functions do the necessary load, transpose (if necessary), preserve (if
312 ; necessary) and store.
328 |vp8_mbloop_filter_neon| PROC
331 vabd.u8 q11, q3, q4 ; abs(p3 - p2)
332 vabd.u8 q12, q4, q5 ; abs(p2 - p1)
333 vabd.u8 q13, q5, q6 ; abs(p1 - p0)
334 vabd.u8 q14, q8, q7 ; abs(q1 - q0)
335 vabd.u8 q1, q9, q8 ; abs(q2 - q1)
336 vabd.u8 q0, q10, q9 ; abs(q3 - q2)
338 vmax.u8 q11, q11, q12
339 vmax.u8 q12, q13, q14
341 vmax.u8 q15, q11, q12
343 vabd.u8 q12, q6, q7 ; abs(p0 - q0)
346 vcgt.u8 q13, q13, q2 ; (abs(p1 - p0) > thresh) * -1
347 vcgt.u8 q14, q14, q2 ; (abs(q1 - q0) > thresh) * -1
350 vdup.u8 q1, r3 ; limit
351 vdup.u8 q2, r2 ; mblimit
353 vmov.u8 q0, #0x80 ; 0x80
357 vabd.u8 q1, q5, q8 ; a = abs(p1 - q1)
358 vqadd.u8 q12, q12, q12 ; b = abs(p0 - q0) * 2
359 vmov.u16 q11, #3 ; #3
363 veor q7, q7, q0 ; qs0
364 vshr.u8 q1, q1, #1 ; a = a / 2
365 veor q6, q6, q0 ; ps0
366 veor q5, q5, q0 ; ps1
368 vqadd.u8 q12, q12, q1 ; a = b + a
370 veor q8, q8, q0 ; qs1
371 veor q4, q4, q0 ; ps2
372 veor q9, q9, q0 ; qs2
374 vorr q14, q13, q14 ; vp8_hevmask
376 vcge.u8 q12, q2, q12 ; (a > flimit * 2 + limit) * -1
378 vsubl.s8 q2, d14, d12 ; qs0 - ps0
379 vsubl.s8 q13, d15, d13
381 vqsub.s8 q1, q5, q8 ; vp8_filter = clamp(ps1-qs1)
383 vmul.i16 q2, q2, q11 ; 3 * ( qs0 - ps0)
385 vand q15, q15, q12 ; vp8_filter_mask
387 vmul.i16 q13, q13, q11
391 vaddw.s8 q2, q2, d2 ; vp8_filter + 3 * ( qs0 - ps0)
392 vaddw.s8 q13, q13, d3
396 ; vp8_filter = clamp(vp8_filter + 3 * ( qs0 - ps0))
400 vand q1, q1, q15 ; vp8_filter &= mask
402 vmov.u16 q15, #63 ; #63
404 vand q13, q1, q14 ; Filter2 &= hev
406 vqadd.s8 q2, q13, q11 ; Filter1 = clamp(Filter2+4)
407 vqadd.s8 q13, q13, q12 ; Filter2 = clamp(Filter2+3)
411 vshr.s8 q2, q2, #3 ; Filter1 >>= 3
412 vshr.s8 q13, q13, #3 ; Filter2 >>= 3
417 vqsub.s8 q7, q7, q2 ; qs0 = clamp(qs0 - Filter1)
419 vqadd.s8 q6, q6, q13 ; ps0 = clamp(ps0 + Filter2)
421 vbic q1, q1, q14 ; vp8_filter &= ~hev
423 ; roughly 1/7th difference across boundary
424 ; roughly 2/7th difference across boundary
425 ; roughly 3/7th difference across boundary
428 vmov.u8 d4, #18 ; #18
433 vmlal.s8 q0, d2, d5 ; 63 + Filter2 * 9
435 vmov.u8 d5, #27 ; #27
436 vmlal.s8 q12, d2, d4 ; 63 + Filter2 * 18
438 vmlal.s8 q14, d2, d5 ; 63 + Filter2 * 27
441 vqshrn.s16 d0, q0, #7 ; u = clamp((63 + Filter2 * 9)>>7)
442 vqshrn.s16 d1, q11, #7
443 vqshrn.s16 d24, q12, #7 ; u = clamp((63 + Filter2 * 18)>>7)
444 vqshrn.s16 d25, q13, #7
445 vqshrn.s16 d28, q14, #7 ; u = clamp((63 + Filter2 * 27)>>7)
446 vqshrn.s16 d29, q15, #7
448 vmov.u8 q1, #0x80 ; 0x80
450 vqsub.s8 q11, q9, q0 ; s = clamp(qs2 - u)
451 vqadd.s8 q0, q4, q0 ; s = clamp(ps2 + u)
452 vqsub.s8 q13, q8, q12 ; s = clamp(qs1 - u)
453 vqadd.s8 q12, q5, q12 ; s = clamp(ps1 + u)
454 vqsub.s8 q15, q7, q14 ; s = clamp(qs0 - u)
455 vqadd.s8 q14, q6, q14 ; s = clamp(ps0 + u)
457 veor q9, q11, q1 ; *oq2 = s^0x80
458 veor q4, q0, q1 ; *op2 = s^0x80
459 veor q8, q13, q1 ; *oq1 = s^0x80
460 veor q5, q12, q1 ; *op2 = s^0x80
461 veor q7, q15, q1 ; *oq0 = s^0x80
462 veor q6, q14, q1 ; *op0 = s^0x80
465 ENDP ; |vp8_mbloop_filter_neon|