Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(509)

Side by Side Diff: source/libvpx/vp9/common/arm/neon/vp9_loopfilter_8_neon_asm.asm

Issue 812033011: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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_8_neon|
12 EXPORT |vp9_lpf_vertical_8_neon|
13 ARM
14
15 AREA ||.text||, CODE, READONLY, ALIGN=2
16
17 ; Currently vp9 only works on iterations 8 at a time. The vp8 loop filter
18 ; works on 16 iterations at a time.
19 ; TODO(fgalligan): See about removing the count code as this function is only
20 ; called with a count of 1.
21 ;
22 ; void vp9_lpf_horizontal_8_neon(uint8_t *s, int p,
23 ; const uint8_t *blimit,
24 ; const uint8_t *limit,
25 ; const uint8_t *thresh,
26 ; int count)
27 ; r0 uint8_t *s,
28 ; r1 int p, /* pitch */
29 ; r2 const uint8_t *blimit,
30 ; r3 const uint8_t *limit,
31 ; sp const uint8_t *thresh,
32 ; sp+4 int count
33 |vp9_lpf_horizontal_8_neon| PROC
34 push {r4-r5, lr}
35
36 vld1.8 {d0[]}, [r2] ; duplicate *blimit
37 ldr r12, [sp, #16] ; load count
38 ldr r2, [sp, #12] ; load thresh
39 add r1, r1, r1 ; double pitch
40
41 cmp r12, #0
42 beq end_vp9_mblf_h_edge
43
44 vld1.8 {d1[]}, [r3] ; duplicate *limit
45 vld1.8 {d2[]}, [r2] ; duplicate *thresh
46
47 count_mblf_h_loop
48 sub r3, r0, r1, lsl #1 ; move src pointer down by 4 lines
49 add r2, r3, r1, lsr #1 ; set to 3 lines down
50
51 vld1.u8 {d3}, [r3@64], r1 ; p3
52 vld1.u8 {d4}, [r2@64], r1 ; p2
53 vld1.u8 {d5}, [r3@64], r1 ; p1
54 vld1.u8 {d6}, [r2@64], r1 ; p0
55 vld1.u8 {d7}, [r3@64], r1 ; q0
56 vld1.u8 {d16}, [r2@64], r1 ; q1
57 vld1.u8 {d17}, [r3@64] ; q2
58 vld1.u8 {d18}, [r2@64], r1 ; q3
59
60 sub r3, r3, r1, lsl #1
61 sub r2, r2, r1, lsl #2
62
63 bl vp9_mbloop_filter_neon
64
65 vst1.u8 {d0}, [r2@64], r1 ; store op2
66 vst1.u8 {d1}, [r3@64], r1 ; store op1
67 vst1.u8 {d2}, [r2@64], r1 ; store op0
68 vst1.u8 {d3}, [r3@64], r1 ; store oq0
69 vst1.u8 {d4}, [r2@64], r1 ; store oq1
70 vst1.u8 {d5}, [r3@64], r1 ; store oq2
71
72 add r0, r0, #8
73 subs r12, r12, #1
74 bne count_mblf_h_loop
75
76 end_vp9_mblf_h_edge
77 pop {r4-r5, pc}
78
79 ENDP ; |vp9_lpf_horizontal_8_neon|
80
81 ; void vp9_lpf_vertical_8_neon(uint8_t *s,
82 ; int pitch,
83 ; const uint8_t *blimit,
84 ; const uint8_t *limit,
85 ; const uint8_t *thresh,
86 ; int count)
87 ;
88 ; r0 uint8_t *s,
89 ; r1 int pitch,
90 ; r2 const uint8_t *blimit,
91 ; r3 const uint8_t *limit,
92 ; sp const uint8_t *thresh,
93 ; sp+4 int count
94 |vp9_lpf_vertical_8_neon| PROC
95 push {r4-r5, lr}
96
97 vld1.8 {d0[]}, [r2] ; duplicate *blimit
98 ldr r12, [sp, #16] ; load count
99 vld1.8 {d1[]}, [r3] ; duplicate *limit
100
101 ldr r3, [sp, #12] ; load thresh
102 sub r2, r0, #4 ; move s pointer down by 4 columns
103 cmp r12, #0
104 beq end_vp9_mblf_v_edge
105
106 vld1.8 {d2[]}, [r3] ; duplicate *thresh
107
108 count_mblf_v_loop
109 vld1.u8 {d3}, [r2], r1 ; load s data
110 vld1.u8 {d4}, [r2], r1
111 vld1.u8 {d5}, [r2], r1
112 vld1.u8 {d6}, [r2], r1
113 vld1.u8 {d7}, [r2], r1
114 vld1.u8 {d16}, [r2], r1
115 vld1.u8 {d17}, [r2], r1
116 vld1.u8 {d18}, [r2]
117
118 ;transpose to 8x16 matrix
119 vtrn.32 d3, d7
120 vtrn.32 d4, d16
121 vtrn.32 d5, d17
122 vtrn.32 d6, d18
123
124 vtrn.16 d3, d5
125 vtrn.16 d4, d6
126 vtrn.16 d7, d17
127 vtrn.16 d16, d18
128
129 vtrn.8 d3, d4
130 vtrn.8 d5, d6
131 vtrn.8 d7, d16
132 vtrn.8 d17, d18
133
134 sub r2, r0, #3
135 add r3, r0, #1
136
137 bl vp9_mbloop_filter_neon
138
139 ;store op2, op1, op0, oq0
140 vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r2], r1
141 vst4.8 {d0[1], d1[1], d2[1], d3[1]}, [r2], r1
142 vst4.8 {d0[2], d1[2], d2[2], d3[2]}, [r2], r1
143 vst4.8 {d0[3], d1[3], d2[3], d3[3]}, [r2], r1
144 vst4.8 {d0[4], d1[4], d2[4], d3[4]}, [r2], r1
145 vst4.8 {d0[5], d1[5], d2[5], d3[5]}, [r2], r1
146 vst4.8 {d0[6], d1[6], d2[6], d3[6]}, [r2], r1
147 vst4.8 {d0[7], d1[7], d2[7], d3[7]}, [r2]
148
149 ;store oq1, oq2
150 vst2.8 {d4[0], d5[0]}, [r3], r1
151 vst2.8 {d4[1], d5[1]}, [r3], r1
152 vst2.8 {d4[2], d5[2]}, [r3], r1
153 vst2.8 {d4[3], d5[3]}, [r3], r1
154 vst2.8 {d4[4], d5[4]}, [r3], r1
155 vst2.8 {d4[5], d5[5]}, [r3], r1
156 vst2.8 {d4[6], d5[6]}, [r3], r1
157 vst2.8 {d4[7], d5[7]}, [r3]
158
159 add r0, r0, r1, lsl #3 ; s += pitch * 8
160 subs r12, r12, #1
161 subne r2, r0, #4 ; move s pointer down by 4 columns
162 bne count_mblf_v_loop
163
164 end_vp9_mblf_v_edge
165 pop {r4-r5, pc}
166 ENDP ; |vp9_lpf_vertical_8_neon|
167
168 ; void vp9_mbloop_filter_neon();
169 ; This is a helper function for the loopfilters. The invidual functions do the
170 ; necessary load, transpose (if necessary) and store. The function does not use
171 ; registers d8-d15.
172 ;
173 ; Inputs:
174 ; r0-r3, r12 PRESERVE
175 ; d0 blimit
176 ; d1 limit
177 ; d2 thresh
178 ; d3 p3
179 ; d4 p2
180 ; d5 p1
181 ; d6 p0
182 ; d7 q0
183 ; d16 q1
184 ; d17 q2
185 ; d18 q3
186 ;
187 ; Outputs:
188 ; d0 op2
189 ; d1 op1
190 ; d2 op0
191 ; d3 oq0
192 ; d4 oq1
193 ; d5 oq2
194 |vp9_mbloop_filter_neon| PROC
195 ; filter_mask
196 vabd.u8 d19, d3, d4 ; m1 = abs(p3 - p2)
197 vabd.u8 d20, d4, d5 ; m2 = abs(p2 - p1)
198 vabd.u8 d21, d5, d6 ; m3 = abs(p1 - p0)
199 vabd.u8 d22, d16, d7 ; m4 = abs(q1 - q0)
200 vabd.u8 d23, d17, d16 ; m5 = abs(q2 - q1)
201 vabd.u8 d24, d18, d17 ; m6 = abs(q3 - q2)
202
203 ; only compare the largest value to limit
204 vmax.u8 d19, d19, d20 ; m1 = max(m1, m2)
205 vmax.u8 d20, d21, d22 ; m2 = max(m3, m4)
206
207 vabd.u8 d25, d6, d4 ; m7 = abs(p0 - p2)
208
209 vmax.u8 d23, d23, d24 ; m3 = max(m5, m6)
210
211 vabd.u8 d26, d7, d17 ; m8 = abs(q0 - q2)
212
213 vmax.u8 d19, d19, d20
214
215 vabd.u8 d24, d6, d7 ; m9 = abs(p0 - q0)
216 vabd.u8 d27, d3, d6 ; m10 = abs(p3 - p0)
217 vabd.u8 d28, d18, d7 ; m11 = abs(q3 - q0)
218
219 vmax.u8 d19, d19, d23
220
221 vabd.u8 d23, d5, d16 ; a = abs(p1 - q1)
222 vqadd.u8 d24, d24, d24 ; b = abs(p0 - q0) * 2
223
224 ; abs () > limit
225 vcge.u8 d19, d1, d19
226
227 ; only compare the largest value to thresh
228 vmax.u8 d25, d25, d26 ; m4 = max(m7, m8)
229 vmax.u8 d26, d27, d28 ; m5 = max(m10, m11)
230
231 vshr.u8 d23, d23, #1 ; a = a / 2
232
233 vmax.u8 d25, d25, d26 ; m4 = max(m4, m5)
234
235 vqadd.u8 d24, d24, d23 ; a = b + a
236
237 vmax.u8 d20, d20, d25 ; m2 = max(m2, m4)
238
239 vmov.u8 d23, #1
240 vcge.u8 d24, d0, d24 ; a > blimit
241
242 vcgt.u8 d21, d21, d2 ; (abs(p1 - p0) > thresh)*-1
243
244 vcge.u8 d20, d23, d20 ; flat
245
246 vand d19, d19, d24 ; mask
247
248 vcgt.u8 d23, d22, d2 ; (abs(q1 - q0) > thresh)*-1
249
250 vand d20, d20, d19 ; flat & mask
251
252 vmov.u8 d22, #0x80
253
254 vorr d23, d21, d23 ; hev
255
256 ; This instruction will truncate the "flat & mask" masks down to 4 bits
257 ; each to fit into one 32 bit arm register. The values are stored in
258 ; q10.64[0].
259 vshrn.u16 d30, q10, #4
260 vmov.u32 r4, d30[0] ; flat & mask 4bits
261
262 adds r5, r4, #1 ; Check for all 1's
263
264 ; If mask and flat are 1's for all vectors, then we only need to execute
265 ; the power branch for all vectors.
266 beq power_branch_only
267
268 cmp r4, #0 ; Check for 0, set flag for later
269
270 ; mbfilter() function
271 ; filter() function
272 ; convert to signed
273 veor d21, d7, d22 ; qs0
274 veor d24, d6, d22 ; ps0
275 veor d25, d5, d22 ; ps1
276 veor d26, d16, d22 ; qs1
277
278 vmov.u8 d27, #3
279
280 vsub.s8 d28, d21, d24 ; ( qs0 - ps0)
281
282 vqsub.s8 d29, d25, d26 ; filter = clamp(ps1-qs1)
283
284 vmull.s8 q15, d28, d27 ; 3 * ( qs0 - ps0)
285
286 vand d29, d29, d23 ; filter &= hev
287
288 vaddw.s8 q15, q15, d29 ; filter + 3 * (qs0 - ps0)
289
290 vmov.u8 d29, #4
291
292 ; filter = clamp(filter + 3 * ( qs0 - ps0))
293 vqmovn.s16 d28, q15
294
295 vand d28, d28, d19 ; filter &= mask
296
297 vqadd.s8 d30, d28, d27 ; filter2 = clamp(filter+3)
298 vqadd.s8 d29, d28, d29 ; filter1 = clamp(filter+4)
299 vshr.s8 d30, d30, #3 ; filter2 >>= 3
300 vshr.s8 d29, d29, #3 ; filter1 >>= 3
301
302 vqadd.s8 d24, d24, d30 ; op0 = clamp(ps0 + filter2)
303 vqsub.s8 d21, d21, d29 ; oq0 = clamp(qs0 - filter1)
304
305 ; outer tap adjustments: ++filter1 >> 1
306 vrshr.s8 d29, d29, #1
307 vbic d29, d29, d23 ; filter &= ~hev
308
309 vqadd.s8 d25, d25, d29 ; op1 = clamp(ps1 + filter)
310 vqsub.s8 d26, d26, d29 ; oq1 = clamp(qs1 - filter)
311
312 ; If mask and flat are 0's for all vectors, then we only need to execute
313 ; the filter branch for all vectors.
314 beq filter_branch_only
315
316 ; If mask and flat are mixed then we must perform both branches and
317 ; combine the data.
318 veor d24, d24, d22 ; *f_op0 = u^0x80
319 veor d21, d21, d22 ; *f_oq0 = u^0x80
320 veor d25, d25, d22 ; *f_op1 = u^0x80
321 veor d26, d26, d22 ; *f_oq1 = u^0x80
322
323 ; At this point we have already executed the filter branch. The filter
324 ; branch does not set op2 or oq2, so use p2 and q2. Execute the power
325 ; branch and combine the data.
326 vmov.u8 d23, #2
327 vaddl.u8 q14, d6, d7 ; r_op2 = p0 + q0
328 vmlal.u8 q14, d3, d27 ; r_op2 += p3 * 3
329 vmlal.u8 q14, d4, d23 ; r_op2 += p2 * 2
330
331 vbif d0, d4, d20 ; op2 |= p2 & ~(flat & mask)
332
333 vaddw.u8 q14, d5 ; r_op2 += p1
334
335 vbif d1, d25, d20 ; op1 |= f_op1 & ~(flat & mask)
336
337 vqrshrn.u16 d30, q14, #3 ; r_op2
338
339 vsubw.u8 q14, d3 ; r_op1 = r_op2 - p3
340 vsubw.u8 q14, d4 ; r_op1 -= p2
341 vaddw.u8 q14, d5 ; r_op1 += p1
342 vaddw.u8 q14, d16 ; r_op1 += q1
343
344 vbif d2, d24, d20 ; op0 |= f_op0 & ~(flat & mask)
345
346 vqrshrn.u16 d31, q14, #3 ; r_op1
347
348 vsubw.u8 q14, d3 ; r_op0 = r_op1 - p3
349 vsubw.u8 q14, d5 ; r_op0 -= p1
350 vaddw.u8 q14, d6 ; r_op0 += p0
351 vaddw.u8 q14, d17 ; r_op0 += q2
352
353 vbit d0, d30, d20 ; op2 |= r_op2 & (flat & mask)
354
355 vqrshrn.u16 d23, q14, #3 ; r_op0
356
357 vsubw.u8 q14, d3 ; r_oq0 = r_op0 - p3
358 vsubw.u8 q14, d6 ; r_oq0 -= p0
359 vaddw.u8 q14, d7 ; r_oq0 += q0
360
361 vbit d1, d31, d20 ; op1 |= r_op1 & (flat & mask)
362
363 vaddw.u8 q14, d18 ; oq0 += q3
364
365 vbit d2, d23, d20 ; op0 |= r_op0 & (flat & mask)
366
367 vqrshrn.u16 d22, q14, #3 ; r_oq0
368
369 vsubw.u8 q14, d4 ; r_oq1 = r_oq0 - p2
370 vsubw.u8 q14, d7 ; r_oq1 -= q0
371 vaddw.u8 q14, d16 ; r_oq1 += q1
372
373 vbif d3, d21, d20 ; oq0 |= f_oq0 & ~(flat & mask)
374
375 vaddw.u8 q14, d18 ; r_oq1 += q3
376
377 vbif d4, d26, d20 ; oq1 |= f_oq1 & ~(flat & mask)
378
379 vqrshrn.u16 d6, q14, #3 ; r_oq1
380
381 vsubw.u8 q14, d5 ; r_oq2 = r_oq1 - p1
382 vsubw.u8 q14, d16 ; r_oq2 -= q1
383 vaddw.u8 q14, d17 ; r_oq2 += q2
384 vaddw.u8 q14, d18 ; r_oq2 += q3
385
386 vbif d5, d17, d20 ; oq2 |= q2 & ~(flat & mask)
387
388 vqrshrn.u16 d7, q14, #3 ; r_oq2
389
390 vbit d3, d22, d20 ; oq0 |= r_oq0 & (flat & mask)
391 vbit d4, d6, d20 ; oq1 |= r_oq1 & (flat & mask)
392 vbit d5, d7, d20 ; oq2 |= r_oq2 & (flat & mask)
393
394 bx lr
395
396 power_branch_only
397 vmov.u8 d27, #3
398 vmov.u8 d21, #2
399 vaddl.u8 q14, d6, d7 ; op2 = p0 + q0
400 vmlal.u8 q14, d3, d27 ; op2 += p3 * 3
401 vmlal.u8 q14, d4, d21 ; op2 += p2 * 2
402 vaddw.u8 q14, d5 ; op2 += p1
403 vqrshrn.u16 d0, q14, #3 ; op2
404
405 vsubw.u8 q14, d3 ; op1 = op2 - p3
406 vsubw.u8 q14, d4 ; op1 -= p2
407 vaddw.u8 q14, d5 ; op1 += p1
408 vaddw.u8 q14, d16 ; op1 += q1
409 vqrshrn.u16 d1, q14, #3 ; op1
410
411 vsubw.u8 q14, d3 ; op0 = op1 - p3
412 vsubw.u8 q14, d5 ; op0 -= p1
413 vaddw.u8 q14, d6 ; op0 += p0
414 vaddw.u8 q14, d17 ; op0 += q2
415 vqrshrn.u16 d2, q14, #3 ; op0
416
417 vsubw.u8 q14, d3 ; oq0 = op0 - p3
418 vsubw.u8 q14, d6 ; oq0 -= p0
419 vaddw.u8 q14, d7 ; oq0 += q0
420 vaddw.u8 q14, d18 ; oq0 += q3
421 vqrshrn.u16 d3, q14, #3 ; oq0
422
423 vsubw.u8 q14, d4 ; oq1 = oq0 - p2
424 vsubw.u8 q14, d7 ; oq1 -= q0
425 vaddw.u8 q14, d16 ; oq1 += q1
426 vaddw.u8 q14, d18 ; oq1 += q3
427 vqrshrn.u16 d4, q14, #3 ; oq1
428
429 vsubw.u8 q14, d5 ; oq2 = oq1 - p1
430 vsubw.u8 q14, d16 ; oq2 -= q1
431 vaddw.u8 q14, d17 ; oq2 += q2
432 vaddw.u8 q14, d18 ; oq2 += q3
433 vqrshrn.u16 d5, q14, #3 ; oq2
434
435 bx lr
436
437 filter_branch_only
438 ; TODO(fgalligan): See if we can rearange registers so we do not need to
439 ; do the 2 vswp.
440 vswp d0, d4 ; op2
441 vswp d5, d17 ; oq2
442 veor d2, d24, d22 ; *op0 = u^0x80
443 veor d3, d21, d22 ; *oq0 = u^0x80
444 veor d1, d25, d22 ; *op1 = u^0x80
445 veor d4, d26, d22 ; *oq1 = u^0x80
446
447 bx lr
448
449 ENDP ; |vp9_mbloop_filter_neon|
450
451 END
OLDNEW
« no previous file with comments | « source/libvpx/vp9/common/arm/neon/vp9_loopfilter_8_neon.c ('k') | source/libvpx/vp9/common/arm/neon/vp9_loopfilter_neon.asm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698