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_sixtap_predict16x16_neon|
17 AREA ||.text||
, CODE
, READONLY
, ALIGN=2
18 ; r0 unsigned char *src_ptr,
19 ; r1 int src_pixels_per_line,
22 ; r4 unsigned char *dst_ptr,
23 ; stack(r5) int dst_pitch
25 ;Note: To take advantage of 8-bit mulplication instruction in NEON. First apply abs() to
26 ; filter coeffs to make them u8. Then, use vmlsl for negtive coeffs. After multiplication,
27 ; the result can be negtive. So, I treat the result as s16. But, since it is also possible
28 ; that the result can be a large positive number (> 2^15-1), which could be confused as a
29 ; negtive number. To avoid that error, apply filter coeffs in the order of 0, 1, 4 ,5 ,2,
30 ; which ensures that the result stays in s16 range. Finally, saturated add the result by
31 ; applying 3rd filter coeff. Same applys to other filter functions.
33 |vp8_sixtap_predict16x16_neon|
PROC
36 ldr r12
, _filter16_coeff_
37 ldr r4
, [sp, #
12] ;load parameters from stack
38 ldr r5
, [sp, #
16] ;load parameters from stack
40 cmp r2
, #
0 ;skip first_pass filter if xoffset=0
41 beq secondpass_filter16x16_only
43 add r2
, r12
, r2
, lsl #
5 ;calculate filter location
45 cmp r3
, #
0 ;skip second_pass filter if yoffset=0
47 vld1.s32
{q14, q15}, [r2
] ;load first_pass filter
49 beq firstpass_filter16x16_only
51 sub sp, sp, #
336 ;reserve space on stack for temporary storage
57 mov r2
, #
7 ;loop counter
58 sub r0
, r0
, #
2 ;move srcptr back to (line-2) and (column-2)
59 sub r0
, r0
, r1
, lsl #
1
61 vdup
.8 d0
, d24
[0] ;first_pass filter (d0-d5)
68 ;First Pass: output_height lines x output_width columns (21x16)
69 filt_blk2d_fp16x16_loop_neon
70 vld1.u8
{d6, d7, d8}, [r0
], r1
;load src data
71 vld1.u8
{d9, d10, d11}, [r0
], r1
72 vld1.u8
{d12, d13, d14}, [r0
], r1
78 vmull.u8 q8
, d6
, d0
;(src_ptr[-2] * vp8_filter[0])
85 vext
.8 d28
, d6
, d7
, #
1 ;construct src_ptr[-1]
86 vext
.8 d29
, d9
, d10
, #
1
87 vext
.8 d30
, d12
, d13
, #
1
89 vmlsl.u8 q8
, d28
, d1
;-(src_ptr[-1] * vp8_filter[1])
93 vext
.8 d28
, d7
, d8
, #
1
94 vext
.8 d29
, d10
, d11
, #
1
95 vext
.8 d30
, d13
, d14
, #
1
97 vmlsl.u8 q9
, d28
, d1
;-(src_ptr[-1] * vp8_filter[1])
101 vext
.8 d28
, d6
, d7
, #
4 ;construct src_ptr[2]
102 vext
.8 d29
, d9
, d10
, #
4
103 vext
.8 d30
, d12
, d13
, #
4
105 vmlsl.u8 q8
, d28
, d4
;-(src_ptr[2] * vp8_filter[4])
106 vmlsl.u8 q10
, d29
, d4
107 vmlsl.u8 q12
, d30
, d4
109 vext
.8 d28
, d7
, d8
, #
4
110 vext
.8 d29
, d10
, d11
, #
4
111 vext
.8 d30
, d13
, d14
, #
4
113 vmlsl.u8 q9
, d28
, d4
;-(src_ptr[2] * vp8_filter[4])
114 vmlsl.u8 q11
, d29
, d4
115 vmlsl.u8 q13
, d30
, d4
117 vext
.8 d28
, d6
, d7
, #
5 ;construct src_ptr[3]
118 vext
.8 d29
, d9
, d10
, #
5
119 vext
.8 d30
, d12
, d13
, #
5
121 vmlal.u8 q8
, d28
, d5
;(src_ptr[3] * vp8_filter[5])
122 vmlal.u8 q10
, d29
, d5
123 vmlal.u8 q12
, d30
, d5
125 vext
.8 d28
, d7
, d8
, #
5
126 vext
.8 d29
, d10
, d11
, #
5
127 vext
.8 d30
, d13
, d14
, #
5
129 vmlal.u8 q9
, d28
, d5
;(src_ptr[3] * vp8_filter[5])
130 vmlal.u8 q11
, d29
, d5
131 vmlal.u8 q13
, d30
, d5
133 vext
.8 d28
, d6
, d7
, #
2 ;construct src_ptr[0]
134 vext
.8 d29
, d9
, d10
, #
2
135 vext
.8 d30
, d12
, d13
, #
2
137 vmlal.u8 q8
, d28
, d2
;(src_ptr[0] * vp8_filter[2])
138 vmlal.u8 q10
, d29
, d2
139 vmlal.u8 q12
, d30
, d2
141 vext
.8 d28
, d7
, d8
, #
2
142 vext
.8 d29
, d10
, d11
, #
2
143 vext
.8 d30
, d13
, d14
, #
2
145 vmlal.u8 q9
, d28
, d2
;(src_ptr[0] * vp8_filter[2])
146 vmlal.u8 q11
, d29
, d2
147 vmlal.u8 q13
, d30
, d2
149 vext
.8 d28
, d6
, d7
, #
3 ;construct src_ptr[1]
150 vext
.8 d29
, d9
, d10
, #
3
151 vext
.8 d30
, d12
, d13
, #
3
153 vext
.8 d15
, d7
, d8
, #
3
154 vext
.8 d31
, d10
, d11
, #
3
155 vext
.8 d6
, d13
, d14
, #
3
157 vmull.u8 q4
, d28
, d3
;(src_ptr[1] * vp8_filter[3])
161 vqadd.s16 q8
, q4
;sum of all (src_data*filter_parameters)
165 vmull.u8 q6
, d15
, d3
;(src_ptr[1] * vp8_filter[3])
175 vqrshrun.s16 d6
, q8
, #
7 ;shift/round/saturate to u8
176 vqrshrun.s16 d7
, q9
, #
7
177 vqrshrun.s16 d8
, q10
, #
7
178 vqrshrun.s16 d9
, q11
, #
7
179 vqrshrun.s16 d10
, q12
, #
7
180 vqrshrun.s16 d11
, q13
, #
7
182 vst1.u8
{d6, d7, d8}, [lr
]! ;store result
183 vst1.u8
{d9, d10, d11}, [lr
]!
185 bne filt_blk2d_fp16x16_loop_neon
188 ;secondpass_filter - do first 8-columns and then second 8-columns
189 add r3
, r12
, r3
, lsl #
5
192 vld1.s32
{q5, q6}, [r3
] ;load second_pass filter
193 mov r3
, #
2 ;loop counter
200 vdup
.8 d0
, d14
[0] ;second_pass filter parameters (d0-d5)
207 filt_blk2d_sp16x16_outloop_neon
208 vld1.u8
{d18}, [lr
], r2
;load src data
209 vld1.u8
{d19}, [lr
], r2
210 vld1.u8
{d20}, [lr
], r2
211 vld1.u8
{d21}, [lr
], r2
212 mov r12
, #
4 ;loop counter
213 vld1.u8
{d22}, [lr
], r2
215 secondpass_inner_loop_neon
216 vld1.u8
{d23}, [lr
], r2
;load src data
217 vld1.u8
{d24}, [lr
], r2
218 vld1.u8
{d25}, [lr
], r2
219 vld1.u8
{d26}, [lr
], r2
221 vmull.u8 q3
, d18
, d0
;(src_ptr[-2] * vp8_filter[0])
226 vmlsl.u8 q3
, d19
, d1
;-(src_ptr[-1] * vp8_filter[1])
231 vmlsl.u8 q3
, d22
, d4
;-(src_ptr[2] * vp8_filter[4])
236 vmlal.u8 q3
, d20
, d2
;(src_ptr[0] * vp8_filter[2])
241 vmlal.u8 q3
, d23
, d5
;(src_ptr[3] * vp8_filter[5])
246 vmull.u8 q7
, d21
, d3
;(src_ptr[1] * vp8_filter[3])
249 vmull.u8 q10
, d24
, d3
253 vqadd.s16 q7
, q3
;sum of all (src_data*filter_parameters)
258 vqrshrun.s16 d6
, q7
, #
7 ;shift/round/saturate to u8
259 vqrshrun.s16 d7
, q8
, #
7
260 vqrshrun.s16 d8
, q9
, #
7
261 vqrshrun.s16 d9
, q10
, #
7
263 vst1.u8
{d6}, [r4
], r5
;store result
265 vst1.u8
{d7}, [r4
], r5
267 vst1.u8
{d8}, [r4
], r5
269 vst1.u8
{d9}, [r4
], r5
271 bne secondpass_inner_loop_neon
277 sub r4
, r4
, r5
, lsl #
4
280 bne filt_blk2d_sp16x16_outloop_neon
285 ;--------------------
286 firstpass_filter16x16_only
290 mov r2
, #
8 ;loop counter
291 sub r0
, r0
, #
2 ;move srcptr back to (column-2)
293 vdup
.8 d0
, d24
[0] ;first_pass filter (d0-d5)
300 ;First Pass: output_height lines x output_width columns (16x16)
301 filt_blk2d_fpo16x16_loop_neon
302 vld1.u8
{d6, d7, d8}, [r0
], r1
;load src data
303 vld1.u8
{d9, d10, d11}, [r0
], r1
308 vmull.u8 q6
, d6
, d0
;(src_ptr[-2] * vp8_filter[0])
313 vext
.8 d20
, d6
, d7
, #
1 ;construct src_ptr[-1]
314 vext
.8 d21
, d9
, d10
, #
1
315 vext
.8 d22
, d7
, d8
, #
1
316 vext
.8 d23
, d10
, d11
, #
1
317 vext
.8 d24
, d6
, d7
, #
4 ;construct src_ptr[2]
318 vext
.8 d25
, d9
, d10
, #
4
319 vext
.8 d26
, d7
, d8
, #
4
320 vext
.8 d27
, d10
, d11
, #
4
321 vext
.8 d28
, d6
, d7
, #
5 ;construct src_ptr[3]
322 vext
.8 d29
, d9
, d10
, #
5
324 vmlsl.u8 q6
, d20
, d1
;-(src_ptr[-1] * vp8_filter[1])
326 vmlsl.u8 q7
, d22
, d1
;-(src_ptr[-1] * vp8_filter[1])
328 vmlsl.u8 q6
, d24
, d4
;-(src_ptr[2] * vp8_filter[4])
330 vmlsl.u8 q7
, d26
, d4
;-(src_ptr[2] * vp8_filter[4])
332 vmlal.u8 q6
, d28
, d5
;(src_ptr[3] * vp8_filter[5])
335 vext
.8 d20
, d7
, d8
, #
5
336 vext
.8 d21
, d10
, d11
, #
5
337 vext
.8 d22
, d6
, d7
, #
2 ;construct src_ptr[0]
338 vext
.8 d23
, d9
, d10
, #
2
339 vext
.8 d24
, d7
, d8
, #
2
340 vext
.8 d25
, d10
, d11
, #
2
342 vext
.8 d26
, d6
, d7
, #
3 ;construct src_ptr[1]
343 vext
.8 d27
, d9
, d10
, #
3
344 vext
.8 d28
, d7
, d8
, #
3
345 vext
.8 d29
, d10
, d11
, #
3
347 vmlal.u8 q7
, d20
, d5
;(src_ptr[3] * vp8_filter[5])
349 vmlal.u8 q6
, d22
, d2
;(src_ptr[0] * vp8_filter[2])
351 vmlal.u8 q7
, d24
, d2
;(src_ptr[0] * vp8_filter[2])
354 vmull.u8 q10
, d26
, d3
;(src_ptr[1] * vp8_filter[3])
355 vmull.u8 q11
, d27
, d3
356 vmull.u8 q12
, d28
, d3
;(src_ptr[1] * vp8_filter[3])
357 vmull.u8 q15
, d29
, d3
359 vqadd.s16 q6
, q10
;sum of all (src_data*filter_parameters)
366 vqrshrun.s16 d6
, q6
, #
7 ;shift/round/saturate to u8
367 vqrshrun.s16 d7
, q7
, #
7
368 vqrshrun.s16 d8
, q8
, #
7
369 vqrshrun.s16 d9
, q9
, #
7
371 vst1.u8
{q3}, [r4
], r5
;store result
372 vst1.u8
{q4}, [r4
], r5
374 bne filt_blk2d_fpo16x16_loop_neon
378 ;--------------------
379 secondpass_filter16x16_only
381 add r3
, r12
, r3
, lsl #
5
382 sub r0
, r0
, r1
, lsl #
1
384 vld1.s32
{q5, q6}, [r3
] ;load second_pass filter
385 mov r3
, #
2 ;loop counter
390 vdup
.8 d0
, d14
[0] ;second_pass filter parameters (d0-d5)
397 filt_blk2d_spo16x16_outloop_neon
398 vld1.u8
{d18}, [r0
], r1
;load src data
399 vld1.u8
{d19}, [r0
], r1
400 vld1.u8
{d20}, [r0
], r1
401 vld1.u8
{d21}, [r0
], r1
402 mov r12
, #
4 ;loop counter
403 vld1.u8
{d22}, [r0
], r1
405 secondpass_only_inner_loop_neon
406 vld1.u8
{d23}, [r0
], r1
;load src data
407 vld1.u8
{d24}, [r0
], r1
408 vld1.u8
{d25}, [r0
], r1
409 vld1.u8
{d26}, [r0
], r1
411 vmull.u8 q3
, d18
, d0
;(src_ptr[-2] * vp8_filter[0])
416 vmlsl.u8 q3
, d19
, d1
;-(src_ptr[-1] * vp8_filter[1])
421 vmlsl.u8 q3
, d22
, d4
;-(src_ptr[2] * vp8_filter[4])
426 vmlal.u8 q3
, d20
, d2
;(src_ptr[0] * vp8_filter[2])
431 vmlal.u8 q3
, d23
, d5
;(src_ptr[3] * vp8_filter[5])
436 vmull.u8 q7
, d21
, d3
;(src_ptr[1] * vp8_filter[3])
439 vmull.u8 q10
, d24
, d3
443 vqadd.s16 q7
, q3
;sum of all (src_data*filter_parameters)
448 vqrshrun.s16 d6
, q7
, #
7 ;shift/round/saturate to u8
449 vqrshrun.s16 d7
, q8
, #
7
450 vqrshrun.s16 d8
, q9
, #
7
451 vqrshrun.s16 d9
, q10
, #
7
453 vst1.u8
{d6}, [r4
], r5
;store result
455 vst1.u8
{d7}, [r4
], r5
457 vst1.u8
{d8}, [r4
], r5
459 vst1.u8
{d9}, [r4
], r5
461 bne secondpass_only_inner_loop_neon
464 sub r0
, r0
, r1
, lsl #
4
465 sub r0
, r0
, r1
, lsl #
2
469 sub r4
, r4
, r5
, lsl #
4
472 bne filt_blk2d_spo16x16_outloop_neon
479 AREA subpelfilters16_dat
, DATA
, READWRITE
;read/write by default
480 ;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
481 ;One word each is reserved. Label filter_coeff can be used to access the data.
482 ;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
486 DCD
0, 0, 128, 0, 0, 0, 0, 0
487 DCD
0, -6, 123, 12, -1, 0, 0, 0
488 DCD
2, -11, 108, 36, -8, 1, 0, 0
489 DCD
0, -9, 93, 50, -6, 0, 0, 0
490 DCD
3, -16, 77, 77, -16, 3, 0, 0
491 DCD
0, -6, 50, 93, -9, 0, 0, 0
492 DCD
1, -8, 36, 108, -11, 2, 0, 0
493 DCD
0, -1, 12, 123, -6, 0, 0, 0