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.
14 EXPORT |vp8_sub_pixel_variance16x16_neon_func|
19 AREA ||.text||, CODE, READONLY, ALIGN=2
20 ; r0 unsigned char *src_ptr,
21 ; r1 int src_pixels_per_line,
24 ; stack(r4) unsigned char *dst_ptr,
25 ; stack(r5) int dst_pixels_per_line,
26 ; stack(r6) unsigned int *sse
27 ;note: most of the code is copied from bilinear_predict16x16_neon and vp8_variance16x16_neon.
30 DCD 128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
32 |vp8_sub_pixel_variance16x16_neon_func| PROC
36 adr r12, bilinear_taps_coeff
37 ldr r4, [sp, #80] ;load *dst_ptr from stack
38 ldr r5, [sp, #84] ;load dst_pixels_per_line from stack
39 ldr r6, [sp, #88] ;load *sse from stack
41 cmp r2, #0 ;skip first_pass filter if xoffset=0
42 beq secondpass_bfilter16x16_only
44 add r2, r12, r2, lsl #3 ;calculate filter location
46 cmp r3, #0 ;skip second_pass filter if yoffset=0
48 vld1.s32 {d31}, [r2] ;load first_pass filter
50 beq firstpass_bfilter16x16_only
52 sub sp, sp, #272 ;reserve space on stack for temporary storage
53 vld1.u8 {d2, d3, d4}, [r0], r1 ;load src data
55 vld1.u8 {d5, d6, d7}, [r0], r1
57 mov r2, #3 ;loop counter
58 vld1.u8 {d8, d9, d10}, [r0], r1
60 vdup.8 d0, d31[0] ;first_pass filter (d0 d1)
61 vld1.u8 {d11, d12, d13}, [r0], r1
65 ;First Pass: output_height lines x output_width columns (17x16)
66 vp8e_filt_blk2d_fp16x16_loop_neon
71 vmull.u8 q7, d2, d0 ;(src_ptr[0] * Filter[0])
80 vext.8 d2, d2, d3, #1 ;construct src_ptr[1]
83 vext.8 d11, d11, d12, #1
85 vmlal.u8 q7, d2, d1 ;(src_ptr[0] * Filter[1])
92 vext.8 d9, d9, d10, #1
93 vext.8 d12, d12, d13, #1
95 vmlal.u8 q8, d3, d1 ;(src_ptr[0] * Filter[1])
102 vqrshrn.u16 d14, q7, #7 ;shift/round/saturate to u8
103 vqrshrn.u16 d15, q8, #7
104 vqrshrn.u16 d16, q9, #7
105 vqrshrn.u16 d17, q10, #7
106 vqrshrn.u16 d18, q11, #7
107 vqrshrn.u16 d19, q12, #7
108 vqrshrn.u16 d20, q13, #7
110 vld1.u8 {d2, d3, d4}, [r0], r1 ;load src data
111 vqrshrn.u16 d21, q14, #7
112 vld1.u8 {d5, d6, d7}, [r0], r1
114 vst1.u8 {d14, d15, d16, d17}, [lr]! ;store result
115 vld1.u8 {d8, d9, d10}, [r0], r1
116 vst1.u8 {d18, d19, d20, d21}, [lr]!
117 vld1.u8 {d11, d12, d13}, [r0], r1
119 bne vp8e_filt_blk2d_fp16x16_loop_neon
121 ;First-pass filtering for rest 5 lines
122 vld1.u8 {d14, d15, d16}, [r0], r1
124 vmull.u8 q9, d2, d0 ;(src_ptr[0] * Filter[0])
131 vext.8 d2, d2, d3, #1 ;construct src_ptr[1]
132 vext.8 d5, d5, d6, #1
133 vext.8 d8, d8, d9, #1
135 vmlal.u8 q9, d2, d1 ;(src_ptr[0] * Filter[1])
139 vext.8 d3, d3, d4, #1
140 vext.8 d6, d6, d7, #1
141 vext.8 d9, d9, d10, #1
143 vmlal.u8 q10, d3, d1 ;(src_ptr[0] * Filter[1])
152 vext.8 d11, d11, d12, #1 ;construct src_ptr[1]
153 vext.8 d14, d14, d15, #1
155 vmlal.u8 q1, d11, d1 ;(src_ptr[0] * Filter[1])
158 vext.8 d12, d12, d13, #1
159 vext.8 d15, d15, d16, #1
161 vmlal.u8 q2, d12, d1 ;(src_ptr[0] * Filter[1])
164 vqrshrn.u16 d10, q9, #7 ;shift/round/saturate to u8
165 vqrshrn.u16 d11, q10, #7
166 vqrshrn.u16 d12, q11, #7
167 vqrshrn.u16 d13, q12, #7
168 vqrshrn.u16 d14, q13, #7
169 vqrshrn.u16 d15, q14, #7
170 vqrshrn.u16 d16, q1, #7
171 vqrshrn.u16 d17, q2, #7
172 vqrshrn.u16 d18, q3, #7
173 vqrshrn.u16 d19, q4, #7
175 vst1.u8 {d10, d11, d12, d13}, [lr]! ;store result
176 vst1.u8 {d14, d15, d16, d17}, [lr]!
177 vst1.u8 {d18, d19}, [lr]!
181 add r3, r12, r3, lsl #3
184 vld1.u32 {d31}, [r3] ;load second_pass filter
189 vld1.u8 {d22, d23}, [lr]! ;load src data
191 vdup.8 d0, d31[0] ;second_pass filter parameters (d0 d1)
193 mov r12, #4 ;loop counter
195 vp8e_filt_blk2d_sp16x16_loop_neon
196 vld1.u8 {d24, d25}, [lr]!
197 vmull.u8 q1, d22, d0 ;(src_ptr[0] * Filter[0])
198 vld1.u8 {d26, d27}, [lr]!
200 vld1.u8 {d28, d29}, [lr]!
202 vld1.u8 {d30, d31}, [lr]!
210 vmlal.u8 q1, d24, d1 ;(src_ptr[pixel_step] * Filter[1])
221 vqrshrn.u16 d2, q1, #7 ;shift/round/saturate to u8
222 vqrshrn.u16 d3, q2, #7
223 vqrshrn.u16 d4, q3, #7
224 vqrshrn.u16 d5, q4, #7
225 vqrshrn.u16 d6, q5, #7
226 vqrshrn.u16 d7, q6, #7
227 vqrshrn.u16 d8, q7, #7
228 vqrshrn.u16 d9, q8, #7
230 vst1.u8 {d2, d3}, [r3]! ;store result
231 vst1.u8 {d4, d5}, [r3]!
232 vst1.u8 {d6, d7}, [r3]!
234 vst1.u8 {d8, d9}, [r3]!
236 bne vp8e_filt_blk2d_sp16x16_loop_neon
238 b sub_pixel_variance16x16_neon
240 ;--------------------
241 firstpass_bfilter16x16_only
242 mov r2, #4 ;loop counter
243 sub sp, sp, #528 ;reserve space on stack for temporary storage
244 vdup.8 d0, d31[0] ;first_pass filter (d0 d1)
248 ;First Pass: output_height lines x output_width columns (16x16)
249 vp8e_filt_blk2d_fpo16x16_loop_neon
250 vld1.u8 {d2, d3, d4}, [r0], r1 ;load src data
251 vld1.u8 {d5, d6, d7}, [r0], r1
252 vld1.u8 {d8, d9, d10}, [r0], r1
253 vld1.u8 {d11, d12, d13}, [r0], r1
259 vmull.u8 q7, d2, d0 ;(src_ptr[0] * Filter[0])
265 vmull.u8 q13, d11, d0
266 vmull.u8 q14, d12, d0
268 vext.8 d2, d2, d3, #1 ;construct src_ptr[1]
269 vext.8 d5, d5, d6, #1
270 vext.8 d8, d8, d9, #1
271 vext.8 d11, d11, d12, #1
273 vmlal.u8 q7, d2, d1 ;(src_ptr[0] * Filter[1])
276 vmlal.u8 q13, d11, d1
278 vext.8 d3, d3, d4, #1
279 vext.8 d6, d6, d7, #1
280 vext.8 d9, d9, d10, #1
281 vext.8 d12, d12, d13, #1
283 vmlal.u8 q8, d3, d1 ;(src_ptr[0] * Filter[1])
286 vmlal.u8 q14, d12, d1
290 vqrshrn.u16 d14, q7, #7 ;shift/round/saturate to u8
291 vqrshrn.u16 d15, q8, #7
292 vqrshrn.u16 d16, q9, #7
293 vqrshrn.u16 d17, q10, #7
294 vqrshrn.u16 d18, q11, #7
295 vqrshrn.u16 d19, q12, #7
296 vqrshrn.u16 d20, q13, #7
297 vst1.u8 {d14, d15}, [r3]! ;store result
298 vqrshrn.u16 d21, q14, #7
300 vst1.u8 {d16, d17}, [r3]!
301 vst1.u8 {d18, d19}, [r3]!
302 vst1.u8 {d20, d21}, [r3]!
304 bne vp8e_filt_blk2d_fpo16x16_loop_neon
306 b sub_pixel_variance16x16_neon
308 ;---------------------
309 secondpass_bfilter16x16_only
312 sub sp, sp, #528 ;reserve space on stack for temporary storage
313 add r3, r12, r3, lsl #3
314 mov r12, #4 ;loop counter
315 vld1.u32 {d31}, [r3] ;load second_pass filter
316 vld1.u8 {d22, d23}, [r0], r1 ;load src data
319 vdup.8 d0, d31[0] ;second_pass filter parameters (d0 d1)
322 vp8e_filt_blk2d_spo16x16_loop_neon
323 vld1.u8 {d24, d25}, [r0], r1
324 vmull.u8 q1, d22, d0 ;(src_ptr[0] * Filter[0])
325 vld1.u8 {d26, d27}, [r0], r1
327 vld1.u8 {d28, d29}, [r0], r1
329 vld1.u8 {d30, d31}, [r0], r1
337 vmlal.u8 q1, d24, d1 ;(src_ptr[pixel_step] * Filter[1])
346 vqrshrn.u16 d2, q1, #7 ;shift/round/saturate to u8
347 vqrshrn.u16 d3, q2, #7
348 vqrshrn.u16 d4, q3, #7
349 vqrshrn.u16 d5, q4, #7
350 vqrshrn.u16 d6, q5, #7
351 vqrshrn.u16 d7, q6, #7
352 vqrshrn.u16 d8, q7, #7
353 vqrshrn.u16 d9, q8, #7
355 vst1.u8 {d2, d3}, [r3]! ;store result
357 vst1.u8 {d4, d5}, [r3]!
359 vst1.u8 {d6, d7}, [r3]!
360 vst1.u8 {d8, d9}, [r3]!
362 bne vp8e_filt_blk2d_spo16x16_loop_neon
364 b sub_pixel_variance16x16_neon
366 ;----------------------------
368 sub_pixel_variance16x16_neon
369 vmov.i8 q8, #0 ;q8 - sum
370 vmov.i8 q9, #0 ;q9, q10 - sse
376 sub_pixel_variance16x16_neon_loop
377 vld1.8 {q0}, [r3]! ;Load up source and reference
378 vld1.8 {q2}, [r4], r5
380 vld1.8 {q3}, [r4], r5
382 vsubl.u8 q11, d0, d4 ;diff
387 vpadal.s16 q8, q11 ;sum
388 vmlal.s16 q9, d22, d22 ;sse
389 vmlal.s16 q10, d23, d23
394 vmlal.s16 q9, d24, d24
395 vmlal.s16 q10, d25, d25
397 vmlal.s16 q9, d26, d26
398 vmlal.s16 q10, d27, d27
400 vmlal.s16 q9, d28, d28
401 vmlal.s16 q10, d29, d29
403 bne sub_pixel_variance16x16_neon_loop
405 vadd.u32 q10, q9, q10 ;accumulate sse
406 vpaddl.s32 q0, q8 ;accumulate sum
413 vst1.32 {d1[0]}, [r6] ;store sse
414 vshr.u32 d10, d10, #8
418 vmov.32 r0, d0[0] ;return