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

Side by Side Diff: source/libvpx/vp9/common/arm/neon/vp9_loopfilter_neon.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_4_neon|
12 EXPORT |vp9_lpf_vertical_4_neon|
13 EXPORT |vp9_lpf_horizontal_8_neon|
14 EXPORT |vp9_lpf_vertical_8_neon|
15 ARM
16
17 AREA ||.text||, CODE, READONLY, ALIGN=2
18
19 ; Currently vp9 only works on iterations 8 at a time. The vp8 loop filter
20 ; works on 16 iterations at a time.
21 ; TODO(fgalligan): See about removing the count code as this function is only
22 ; called with a count of 1.
23 ;
24 ; void vp9_lpf_horizontal_4_neon(uint8_t *s,
25 ; int p /* pitch */,
26 ; const uint8_t *blimit,
27 ; const uint8_t *limit,
28 ; const uint8_t *thresh,
29 ; int count)
30 ;
31 ; r0 uint8_t *s,
32 ; r1 int p, /* pitch */
33 ; r2 const uint8_t *blimit,
34 ; r3 const uint8_t *limit,
35 ; sp const uint8_t *thresh,
36 ; sp+4 int count
37 |vp9_lpf_horizontal_4_neon| PROC
38 push {lr}
39
40 vld1.8 {d0[]}, [r2] ; duplicate *blimit
41 ldr r12, [sp, #8] ; load count
42 ldr r2, [sp, #4] ; load thresh
43 add r1, r1, r1 ; double pitch
44
45 cmp r12, #0
46 beq end_vp9_lf_h_edge
47
48 vld1.8 {d1[]}, [r3] ; duplicate *limit
49 vld1.8 {d2[]}, [r2] ; duplicate *thresh
50
51 count_lf_h_loop
52 sub r2, r0, r1, lsl #1 ; move src pointer down by 4 lines
53 add r3, r2, r1, lsr #1 ; set to 3 lines down
54
55 vld1.u8 {d3}, [r2@64], r1 ; p3
56 vld1.u8 {d4}, [r3@64], r1 ; p2
57 vld1.u8 {d5}, [r2@64], r1 ; p1
58 vld1.u8 {d6}, [r3@64], r1 ; p0
59 vld1.u8 {d7}, [r2@64], r1 ; q0
60 vld1.u8 {d16}, [r3@64], r1 ; q1
61 vld1.u8 {d17}, [r2@64] ; q2
62 vld1.u8 {d18}, [r3@64] ; q3
63
64 sub r2, r2, r1, lsl #1
65 sub r3, r3, r1, lsl #1
66
67 bl vp9_loop_filter_neon
68
69 vst1.u8 {d4}, [r2@64], r1 ; store op1
70 vst1.u8 {d5}, [r3@64], r1 ; store op0
71 vst1.u8 {d6}, [r2@64], r1 ; store oq0
72 vst1.u8 {d7}, [r3@64], r1 ; store oq1
73
74 add r0, r0, #8
75 subs r12, r12, #1
76 bne count_lf_h_loop
77
78 end_vp9_lf_h_edge
79 pop {pc}
80 ENDP ; |vp9_lpf_horizontal_4_neon|
81
82 ; Currently vp9 only works on iterations 8 at a time. The vp8 loop filter
83 ; works on 16 iterations at a time.
84 ; TODO(fgalligan): See about removing the count code as this function is only
85 ; called with a count of 1.
86 ;
87 ; void vp9_lpf_vertical_4_neon(uint8_t *s,
88 ; int p /* pitch */,
89 ; const uint8_t *blimit,
90 ; const uint8_t *limit,
91 ; const uint8_t *thresh,
92 ; int count)
93 ;
94 ; r0 uint8_t *s,
95 ; r1 int p, /* pitch */
96 ; r2 const uint8_t *blimit,
97 ; r3 const uint8_t *limit,
98 ; sp const uint8_t *thresh,
99 ; sp+4 int count
100 |vp9_lpf_vertical_4_neon| PROC
101 push {lr}
102
103 vld1.8 {d0[]}, [r2] ; duplicate *blimit
104 ldr r12, [sp, #8] ; load count
105 vld1.8 {d1[]}, [r3] ; duplicate *limit
106
107 ldr r3, [sp, #4] ; load thresh
108 sub r2, r0, #4 ; move s pointer down by 4 columns
109 cmp r12, #0
110 beq end_vp9_lf_v_edge
111
112 vld1.8 {d2[]}, [r3] ; duplicate *thresh
113
114 count_lf_v_loop
115 vld1.u8 {d3}, [r2], r1 ; load s data
116 vld1.u8 {d4}, [r2], r1
117 vld1.u8 {d5}, [r2], r1
118 vld1.u8 {d6}, [r2], r1
119 vld1.u8 {d7}, [r2], r1
120 vld1.u8 {d16}, [r2], r1
121 vld1.u8 {d17}, [r2], r1
122 vld1.u8 {d18}, [r2]
123
124 ;transpose to 8x16 matrix
125 vtrn.32 d3, d7
126 vtrn.32 d4, d16
127 vtrn.32 d5, d17
128 vtrn.32 d6, d18
129
130 vtrn.16 d3, d5
131 vtrn.16 d4, d6
132 vtrn.16 d7, d17
133 vtrn.16 d16, d18
134
135 vtrn.8 d3, d4
136 vtrn.8 d5, d6
137 vtrn.8 d7, d16
138 vtrn.8 d17, d18
139
140 bl vp9_loop_filter_neon
141
142 sub r0, r0, #2
143
144 ;store op1, op0, oq0, oq1
145 vst4.8 {d4[0], d5[0], d6[0], d7[0]}, [r0], r1
146 vst4.8 {d4[1], d5[1], d6[1], d7[1]}, [r0], r1
147 vst4.8 {d4[2], d5[2], d6[2], d7[2]}, [r0], r1
148 vst4.8 {d4[3], d5[3], d6[3], d7[3]}, [r0], r1
149 vst4.8 {d4[4], d5[4], d6[4], d7[4]}, [r0], r1
150 vst4.8 {d4[5], d5[5], d6[5], d7[5]}, [r0], r1
151 vst4.8 {d4[6], d5[6], d6[6], d7[6]}, [r0], r1
152 vst4.8 {d4[7], d5[7], d6[7], d7[7]}, [r0]
153
154 add r0, r0, r1, lsl #3 ; s += pitch * 8
155 subs r12, r12, #1
156 subne r2, r0, #4 ; move s pointer down by 4 columns
157 bne count_lf_v_loop
158
159 end_vp9_lf_v_edge
160 pop {pc}
161 ENDP ; |vp9_lpf_vertical_4_neon|
162
163 ; void vp9_loop_filter_neon();
164 ; This is a helper function for the loopfilters. The invidual functions do the
165 ; necessary load, transpose (if necessary) and store. The function does not use
166 ; registers d8-d15.
167 ;
168 ; Inputs:
169 ; r0-r3, r12 PRESERVE
170 ; d0 blimit
171 ; d1 limit
172 ; d2 thresh
173 ; d3 p3
174 ; d4 p2
175 ; d5 p1
176 ; d6 p0
177 ; d7 q0
178 ; d16 q1
179 ; d17 q2
180 ; d18 q3
181 ;
182 ; Outputs:
183 ; d4 op1
184 ; d5 op0
185 ; d6 oq0
186 ; d7 oq1
187 |vp9_loop_filter_neon| PROC
188 ; filter_mask
189 vabd.u8 d19, d3, d4 ; m1 = abs(p3 - p2)
190 vabd.u8 d20, d4, d5 ; m2 = abs(p2 - p1)
191 vabd.u8 d21, d5, d6 ; m3 = abs(p1 - p0)
192 vabd.u8 d22, d16, d7 ; m4 = abs(q1 - q0)
193 vabd.u8 d3, d17, d16 ; m5 = abs(q2 - q1)
194 vabd.u8 d4, d18, d17 ; m6 = abs(q3 - q2)
195
196 ; only compare the largest value to limit
197 vmax.u8 d19, d19, d20 ; m1 = max(m1, m2)
198 vmax.u8 d20, d21, d22 ; m2 = max(m3, m4)
199
200 vabd.u8 d17, d6, d7 ; abs(p0 - q0)
201
202 vmax.u8 d3, d3, d4 ; m3 = max(m5, m6)
203
204 vmov.u8 d18, #0x80
205
206 vmax.u8 d23, d19, d20 ; m1 = max(m1, m2)
207
208 ; hevmask
209 vcgt.u8 d21, d21, d2 ; (abs(p1 - p0) > thresh)*-1
210 vcgt.u8 d22, d22, d2 ; (abs(q1 - q0) > thresh)*-1
211 vmax.u8 d23, d23, d3 ; m1 = max(m1, m3)
212
213 vabd.u8 d28, d5, d16 ; a = abs(p1 - q1)
214 vqadd.u8 d17, d17, d17 ; b = abs(p0 - q0) * 2
215
216 veor d7, d7, d18 ; qs0
217
218 vcge.u8 d23, d1, d23 ; abs(m1) > limit
219
220 ; filter() function
221 ; convert to signed
222
223 vshr.u8 d28, d28, #1 ; a = a / 2
224 veor d6, d6, d18 ; ps0
225
226 veor d5, d5, d18 ; ps1
227 vqadd.u8 d17, d17, d28 ; a = b + a
228
229 veor d16, d16, d18 ; qs1
230
231 vmov.u8 d19, #3
232
233 vsub.s8 d28, d7, d6 ; ( qs0 - ps0)
234
235 vcge.u8 d17, d0, d17 ; a > blimit
236
237 vqsub.s8 d27, d5, d16 ; filter = clamp(ps1-qs1)
238 vorr d22, d21, d22 ; hevmask
239
240 vmull.s8 q12, d28, d19 ; 3 * ( qs0 - ps0)
241
242 vand d27, d27, d22 ; filter &= hev
243 vand d23, d23, d17 ; filter_mask
244
245 vaddw.s8 q12, q12, d27 ; filter + 3 * (qs0 - ps0)
246
247 vmov.u8 d17, #4
248
249 ; filter = clamp(filter + 3 * ( qs0 - ps0))
250 vqmovn.s16 d27, q12
251
252 vand d27, d27, d23 ; filter &= mask
253
254 vqadd.s8 d28, d27, d19 ; filter2 = clamp(filter+3)
255 vqadd.s8 d27, d27, d17 ; filter1 = clamp(filter+4)
256 vshr.s8 d28, d28, #3 ; filter2 >>= 3
257 vshr.s8 d27, d27, #3 ; filter1 >>= 3
258
259 vqadd.s8 d19, d6, d28 ; u = clamp(ps0 + filter2)
260 vqsub.s8 d26, d7, d27 ; u = clamp(qs0 - filter1)
261
262 ; outer tap adjustments
263 vrshr.s8 d27, d27, #1 ; filter = ++filter1 >> 1
264
265 veor d6, d26, d18 ; *oq0 = u^0x80
266
267 vbic d27, d27, d22 ; filter &= ~hev
268
269 vqadd.s8 d21, d5, d27 ; u = clamp(ps1 + filter)
270 vqsub.s8 d20, d16, d27 ; u = clamp(qs1 - filter)
271
272 veor d5, d19, d18 ; *op0 = u^0x80
273 veor d4, d21, d18 ; *op1 = u^0x80
274 veor d7, d20, d18 ; *oq1 = u^0x80
275
276 bx lr
277 ENDP ; |vp9_loop_filter_neon|
278
279 ; void vp9_lpf_horizontal_8_neon(uint8_t *s, int p,
280 ; const uint8_t *blimit,
281 ; const uint8_t *limit,
282 ; const uint8_t *thresh,
283 ; int count)
284 ; r0 uint8_t *s,
285 ; r1 int p, /* pitch */
286 ; r2 const uint8_t *blimit,
287 ; r3 const uint8_t *limit,
288 ; sp const uint8_t *thresh,
289 ; sp+4 int count
290 |vp9_lpf_horizontal_8_neon| PROC
291 push {r4-r5, lr}
292
293 vld1.8 {d0[]}, [r2] ; duplicate *blimit
294 ldr r12, [sp, #16] ; load count
295 ldr r2, [sp, #12] ; load thresh
296 add r1, r1, r1 ; double pitch
297
298 cmp r12, #0
299 beq end_vp9_mblf_h_edge
300
301 vld1.8 {d1[]}, [r3] ; duplicate *limit
302 vld1.8 {d2[]}, [r2] ; duplicate *thresh
303
304 count_mblf_h_loop
305 sub r3, r0, r1, lsl #1 ; move src pointer down by 4 lines
306 add r2, r3, r1, lsr #1 ; set to 3 lines down
307
308 vld1.u8 {d3}, [r3@64], r1 ; p3
309 vld1.u8 {d4}, [r2@64], r1 ; p2
310 vld1.u8 {d5}, [r3@64], r1 ; p1
311 vld1.u8 {d6}, [r2@64], r1 ; p0
312 vld1.u8 {d7}, [r3@64], r1 ; q0
313 vld1.u8 {d16}, [r2@64], r1 ; q1
314 vld1.u8 {d17}, [r3@64] ; q2
315 vld1.u8 {d18}, [r2@64], r1 ; q3
316
317 sub r3, r3, r1, lsl #1
318 sub r2, r2, r1, lsl #2
319
320 bl vp9_mbloop_filter_neon
321
322 vst1.u8 {d0}, [r2@64], r1 ; store op2
323 vst1.u8 {d1}, [r3@64], r1 ; store op1
324 vst1.u8 {d2}, [r2@64], r1 ; store op0
325 vst1.u8 {d3}, [r3@64], r1 ; store oq0
326 vst1.u8 {d4}, [r2@64], r1 ; store oq1
327 vst1.u8 {d5}, [r3@64], r1 ; store oq2
328
329 add r0, r0, #8
330 subs r12, r12, #1
331 bne count_mblf_h_loop
332
333 end_vp9_mblf_h_edge
334 pop {r4-r5, pc}
335
336 ENDP ; |vp9_lpf_horizontal_8_neon|
337
338 ; void vp9_lpf_vertical_8_neon(uint8_t *s,
339 ; int pitch,
340 ; const uint8_t *blimit,
341 ; const uint8_t *limit,
342 ; const uint8_t *thresh,
343 ; int count)
344 ;
345 ; r0 uint8_t *s,
346 ; r1 int pitch,
347 ; r2 const uint8_t *blimit,
348 ; r3 const uint8_t *limit,
349 ; sp const uint8_t *thresh,
350 ; sp+4 int count
351 |vp9_lpf_vertical_8_neon| PROC
352 push {r4-r5, lr}
353
354 vld1.8 {d0[]}, [r2] ; duplicate *blimit
355 ldr r12, [sp, #16] ; load count
356 vld1.8 {d1[]}, [r3] ; duplicate *limit
357
358 ldr r3, [sp, #12] ; load thresh
359 sub r2, r0, #4 ; move s pointer down by 4 columns
360 cmp r12, #0
361 beq end_vp9_mblf_v_edge
362
363 vld1.8 {d2[]}, [r3] ; duplicate *thresh
364
365 count_mblf_v_loop
366 vld1.u8 {d3}, [r2], r1 ; load s data
367 vld1.u8 {d4}, [r2], r1
368 vld1.u8 {d5}, [r2], r1
369 vld1.u8 {d6}, [r2], r1
370 vld1.u8 {d7}, [r2], r1
371 vld1.u8 {d16}, [r2], r1
372 vld1.u8 {d17}, [r2], r1
373 vld1.u8 {d18}, [r2]
374
375 ;transpose to 8x16 matrix
376 vtrn.32 d3, d7
377 vtrn.32 d4, d16
378 vtrn.32 d5, d17
379 vtrn.32 d6, d18
380
381 vtrn.16 d3, d5
382 vtrn.16 d4, d6
383 vtrn.16 d7, d17
384 vtrn.16 d16, d18
385
386 vtrn.8 d3, d4
387 vtrn.8 d5, d6
388 vtrn.8 d7, d16
389 vtrn.8 d17, d18
390
391 sub r2, r0, #3
392 add r3, r0, #1
393
394 bl vp9_mbloop_filter_neon
395
396 ;store op2, op1, op0, oq0
397 vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r2], r1
398 vst4.8 {d0[1], d1[1], d2[1], d3[1]}, [r2], r1
399 vst4.8 {d0[2], d1[2], d2[2], d3[2]}, [r2], r1
400 vst4.8 {d0[3], d1[3], d2[3], d3[3]}, [r2], r1
401 vst4.8 {d0[4], d1[4], d2[4], d3[4]}, [r2], r1
402 vst4.8 {d0[5], d1[5], d2[5], d3[5]}, [r2], r1
403 vst4.8 {d0[6], d1[6], d2[6], d3[6]}, [r2], r1
404 vst4.8 {d0[7], d1[7], d2[7], d3[7]}, [r2]
405
406 ;store oq1, oq2
407 vst2.8 {d4[0], d5[0]}, [r3], r1
408 vst2.8 {d4[1], d5[1]}, [r3], r1
409 vst2.8 {d4[2], d5[2]}, [r3], r1
410 vst2.8 {d4[3], d5[3]}, [r3], r1
411 vst2.8 {d4[4], d5[4]}, [r3], r1
412 vst2.8 {d4[5], d5[5]}, [r3], r1
413 vst2.8 {d4[6], d5[6]}, [r3], r1
414 vst2.8 {d4[7], d5[7]}, [r3]
415
416 add r0, r0, r1, lsl #3 ; s += pitch * 8
417 subs r12, r12, #1
418 subne r2, r0, #4 ; move s pointer down by 4 columns
419 bne count_mblf_v_loop
420
421 end_vp9_mblf_v_edge
422 pop {r4-r5, pc}
423 ENDP ; |vp9_lpf_vertical_8_neon|
424
425 ; void vp9_mbloop_filter_neon();
426 ; This is a helper function for the loopfilters. The invidual functions do the
427 ; necessary load, transpose (if necessary) and store. The function does not use
428 ; registers d8-d15.
429 ;
430 ; Inputs:
431 ; r0-r3, r12 PRESERVE
432 ; d0 blimit
433 ; d1 limit
434 ; d2 thresh
435 ; d3 p3
436 ; d4 p2
437 ; d5 p1
438 ; d6 p0
439 ; d7 q0
440 ; d16 q1
441 ; d17 q2
442 ; d18 q3
443 ;
444 ; Outputs:
445 ; d0 op2
446 ; d1 op1
447 ; d2 op0
448 ; d3 oq0
449 ; d4 oq1
450 ; d5 oq2
451 |vp9_mbloop_filter_neon| PROC
452 ; filter_mask
453 vabd.u8 d19, d3, d4 ; m1 = abs(p3 - p2)
454 vabd.u8 d20, d4, d5 ; m2 = abs(p2 - p1)
455 vabd.u8 d21, d5, d6 ; m3 = abs(p1 - p0)
456 vabd.u8 d22, d16, d7 ; m4 = abs(q1 - q0)
457 vabd.u8 d23, d17, d16 ; m5 = abs(q2 - q1)
458 vabd.u8 d24, d18, d17 ; m6 = abs(q3 - q2)
459
460 ; only compare the largest value to limit
461 vmax.u8 d19, d19, d20 ; m1 = max(m1, m2)
462 vmax.u8 d20, d21, d22 ; m2 = max(m3, m4)
463
464 vabd.u8 d25, d6, d4 ; m7 = abs(p0 - p2)
465
466 vmax.u8 d23, d23, d24 ; m3 = max(m5, m6)
467
468 vabd.u8 d26, d7, d17 ; m8 = abs(q0 - q2)
469
470 vmax.u8 d19, d19, d20
471
472 vabd.u8 d24, d6, d7 ; m9 = abs(p0 - q0)
473 vabd.u8 d27, d3, d6 ; m10 = abs(p3 - p0)
474 vabd.u8 d28, d18, d7 ; m11 = abs(q3 - q0)
475
476 vmax.u8 d19, d19, d23
477
478 vabd.u8 d23, d5, d16 ; a = abs(p1 - q1)
479 vqadd.u8 d24, d24, d24 ; b = abs(p0 - q0) * 2
480
481 ; abs () > limit
482 vcge.u8 d19, d1, d19
483
484 ; only compare the largest value to thresh
485 vmax.u8 d25, d25, d26 ; m4 = max(m7, m8)
486 vmax.u8 d26, d27, d28 ; m5 = max(m10, m11)
487
488 vshr.u8 d23, d23, #1 ; a = a / 2
489
490 vmax.u8 d25, d25, d26 ; m4 = max(m4, m5)
491
492 vqadd.u8 d24, d24, d23 ; a = b + a
493
494 vmax.u8 d20, d20, d25 ; m2 = max(m2, m4)
495
496 vmov.u8 d23, #1
497 vcge.u8 d24, d0, d24 ; a > blimit
498
499 vcgt.u8 d21, d21, d2 ; (abs(p1 - p0) > thresh)*-1
500
501 vcge.u8 d20, d23, d20 ; flat
502
503 vand d19, d19, d24 ; mask
504
505 vcgt.u8 d23, d22, d2 ; (abs(q1 - q0) > thresh)*-1
506
507 vand d20, d20, d19 ; flat & mask
508
509 vmov.u8 d22, #0x80
510
511 vorr d23, d21, d23 ; hev
512
513 ; This instruction will truncate the "flat & mask" masks down to 4 bits
514 ; each to fit into one 32 bit arm register. The values are stored in
515 ; q10.64[0].
516 vshrn.u16 d30, q10, #4
517 vmov.u32 r4, d30[0] ; flat & mask 4bits
518
519 adds r5, r4, #1 ; Check for all 1's
520
521 ; If mask and flat are 1's for all vectors, then we only need to execute
522 ; the power branch for all vectors.
523 beq power_branch_only
524
525 cmp r4, #0 ; Check for 0, set flag for later
526
527 ; mbfilter() function
528 ; filter() function
529 ; convert to signed
530 veor d21, d7, d22 ; qs0
531 veor d24, d6, d22 ; ps0
532 veor d25, d5, d22 ; ps1
533 veor d26, d16, d22 ; qs1
534
535 vmov.u8 d27, #3
536
537 vsub.s8 d28, d21, d24 ; ( qs0 - ps0)
538
539 vqsub.s8 d29, d25, d26 ; filter = clamp(ps1-qs1)
540
541 vmull.s8 q15, d28, d27 ; 3 * ( qs0 - ps0)
542
543 vand d29, d29, d23 ; filter &= hev
544
545 vaddw.s8 q15, q15, d29 ; filter + 3 * (qs0 - ps0)
546
547 vmov.u8 d29, #4
548
549 ; filter = clamp(filter + 3 * ( qs0 - ps0))
550 vqmovn.s16 d28, q15
551
552 vand d28, d28, d19 ; filter &= mask
553
554 vqadd.s8 d30, d28, d27 ; filter2 = clamp(filter+3)
555 vqadd.s8 d29, d28, d29 ; filter1 = clamp(filter+4)
556 vshr.s8 d30, d30, #3 ; filter2 >>= 3
557 vshr.s8 d29, d29, #3 ; filter1 >>= 3
558
559 vqadd.s8 d24, d24, d30 ; op0 = clamp(ps0 + filter2)
560 vqsub.s8 d21, d21, d29 ; oq0 = clamp(qs0 - filter1)
561
562 ; outer tap adjustments: ++filter1 >> 1
563 vrshr.s8 d29, d29, #1
564 vbic d29, d29, d23 ; filter &= ~hev
565
566 vqadd.s8 d25, d25, d29 ; op1 = clamp(ps1 + filter)
567 vqsub.s8 d26, d26, d29 ; oq1 = clamp(qs1 - filter)
568
569 ; If mask and flat are 0's for all vectors, then we only need to execute
570 ; the filter branch for all vectors.
571 beq filter_branch_only
572
573 ; If mask and flat are mixed then we must perform both branches and
574 ; combine the data.
575 veor d24, d24, d22 ; *f_op0 = u^0x80
576 veor d21, d21, d22 ; *f_oq0 = u^0x80
577 veor d25, d25, d22 ; *f_op1 = u^0x80
578 veor d26, d26, d22 ; *f_oq1 = u^0x80
579
580 ; At this point we have already executed the filter branch. The filter
581 ; branch does not set op2 or oq2, so use p2 and q2. Execute the power
582 ; branch and combine the data.
583 vmov.u8 d23, #2
584 vaddl.u8 q14, d6, d7 ; r_op2 = p0 + q0
585 vmlal.u8 q14, d3, d27 ; r_op2 += p3 * 3
586 vmlal.u8 q14, d4, d23 ; r_op2 += p2 * 2
587
588 vbif d0, d4, d20 ; op2 |= p2 & ~(flat & mask)
589
590 vaddw.u8 q14, d5 ; r_op2 += p1
591
592 vbif d1, d25, d20 ; op1 |= f_op1 & ~(flat & mask)
593
594 vqrshrn.u16 d30, q14, #3 ; r_op2
595
596 vsubw.u8 q14, d3 ; r_op1 = r_op2 - p3
597 vsubw.u8 q14, d4 ; r_op1 -= p2
598 vaddw.u8 q14, d5 ; r_op1 += p1
599 vaddw.u8 q14, d16 ; r_op1 += q1
600
601 vbif d2, d24, d20 ; op0 |= f_op0 & ~(flat & mask)
602
603 vqrshrn.u16 d31, q14, #3 ; r_op1
604
605 vsubw.u8 q14, d3 ; r_op0 = r_op1 - p3
606 vsubw.u8 q14, d5 ; r_op0 -= p1
607 vaddw.u8 q14, d6 ; r_op0 += p0
608 vaddw.u8 q14, d17 ; r_op0 += q2
609
610 vbit d0, d30, d20 ; op2 |= r_op2 & (flat & mask)
611
612 vqrshrn.u16 d23, q14, #3 ; r_op0
613
614 vsubw.u8 q14, d3 ; r_oq0 = r_op0 - p3
615 vsubw.u8 q14, d6 ; r_oq0 -= p0
616 vaddw.u8 q14, d7 ; r_oq0 += q0
617
618 vbit d1, d31, d20 ; op1 |= r_op1 & (flat & mask)
619
620 vaddw.u8 q14, d18 ; oq0 += q3
621
622 vbit d2, d23, d20 ; op0 |= r_op0 & (flat & mask)
623
624 vqrshrn.u16 d22, q14, #3 ; r_oq0
625
626 vsubw.u8 q14, d4 ; r_oq1 = r_oq0 - p2
627 vsubw.u8 q14, d7 ; r_oq1 -= q0
628 vaddw.u8 q14, d16 ; r_oq1 += q1
629
630 vbif d3, d21, d20 ; oq0 |= f_oq0 & ~(flat & mask)
631
632 vaddw.u8 q14, d18 ; r_oq1 += q3
633
634 vbif d4, d26, d20 ; oq1 |= f_oq1 & ~(flat & mask)
635
636 vqrshrn.u16 d6, q14, #3 ; r_oq1
637
638 vsubw.u8 q14, d5 ; r_oq2 = r_oq1 - p1
639 vsubw.u8 q14, d16 ; r_oq2 -= q1
640 vaddw.u8 q14, d17 ; r_oq2 += q2
641 vaddw.u8 q14, d18 ; r_oq2 += q3
642
643 vbif d5, d17, d20 ; oq2 |= q2 & ~(flat & mask)
644
645 vqrshrn.u16 d7, q14, #3 ; r_oq2
646
647 vbit d3, d22, d20 ; oq0 |= r_oq0 & (flat & mask)
648 vbit d4, d6, d20 ; oq1 |= r_oq1 & (flat & mask)
649 vbit d5, d7, d20 ; oq2 |= r_oq2 & (flat & mask)
650
651 bx lr
652
653 power_branch_only
654 vmov.u8 d27, #3
655 vmov.u8 d21, #2
656 vaddl.u8 q14, d6, d7 ; op2 = p0 + q0
657 vmlal.u8 q14, d3, d27 ; op2 += p3 * 3
658 vmlal.u8 q14, d4, d21 ; op2 += p2 * 2
659 vaddw.u8 q14, d5 ; op2 += p1
660 vqrshrn.u16 d0, q14, #3 ; op2
661
662 vsubw.u8 q14, d3 ; op1 = op2 - p3
663 vsubw.u8 q14, d4 ; op1 -= p2
664 vaddw.u8 q14, d5 ; op1 += p1
665 vaddw.u8 q14, d16 ; op1 += q1
666 vqrshrn.u16 d1, q14, #3 ; op1
667
668 vsubw.u8 q14, d3 ; op0 = op1 - p3
669 vsubw.u8 q14, d5 ; op0 -= p1
670 vaddw.u8 q14, d6 ; op0 += p0
671 vaddw.u8 q14, d17 ; op0 += q2
672 vqrshrn.u16 d2, q14, #3 ; op0
673
674 vsubw.u8 q14, d3 ; oq0 = op0 - p3
675 vsubw.u8 q14, d6 ; oq0 -= p0
676 vaddw.u8 q14, d7 ; oq0 += q0
677 vaddw.u8 q14, d18 ; oq0 += q3
678 vqrshrn.u16 d3, q14, #3 ; oq0
679
680 vsubw.u8 q14, d4 ; oq1 = oq0 - p2
681 vsubw.u8 q14, d7 ; oq1 -= q0
682 vaddw.u8 q14, d16 ; oq1 += q1
683 vaddw.u8 q14, d18 ; oq1 += q3
684 vqrshrn.u16 d4, q14, #3 ; oq1
685
686 vsubw.u8 q14, d5 ; oq2 = oq1 - p1
687 vsubw.u8 q14, d16 ; oq2 -= q1
688 vaddw.u8 q14, d17 ; oq2 += q2
689 vaddw.u8 q14, d18 ; oq2 += q3
690 vqrshrn.u16 d5, q14, #3 ; oq2
691
692 bx lr
693
694 filter_branch_only
695 ; TODO(fgalligan): See if we can rearange registers so we do not need to
696 ; do the 2 vswp.
697 vswp d0, d4 ; op2
698 vswp d5, d17 ; oq2
699 veor d2, d24, d22 ; *op0 = u^0x80
700 veor d3, d21, d22 ; *oq0 = u^0x80
701 veor d1, d25, d22 ; *op1 = u^0x80
702 veor d4, d26, d22 ; *oq1 = u^0x80
703
704 bx lr
705
706 ENDP ; |vp9_mbloop_filter_neon|
707
708 END
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698