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.
13 DCD 128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
17 EXPORT |vp8_sub_pixel_variance16x16_neon_func|
22 AREA ||.text||, CODE, READONLY, ALIGN=2
23 ; r0 unsigned char *src_ptr,
24 ; r1 int src_pixels_per_line,
27 ; stack(r4) unsigned char *dst_ptr,
28 ; stack(r5) int dst_pixels_per_line,
29 ; stack(r6) unsigned int *sse
30 ;note: most of the code is copied from bilinear_predict16x16_neon and vp8_variance16x16_neon.
32 |vp8_sub_pixel_variance16x16_neon_func| PROC
35 adr r12, bilinear_taps_coeff
36 ldr r4, [sp, #16] ;load *dst_ptr from stack
37 ldr r5, [sp, #20] ;load dst_pixels_per_line from stack
38 ldr r6, [sp, #24] ;load *sse from stack
40 cmp r2, #0 ;skip first_pass filter if xoffset=0
41 beq secondpass_bfilter16x16_only
43 add r2, r12, r2, lsl #3 ;calculate filter location
45 cmp r3, #0 ;skip second_pass filter if yoffset=0
47 vld1.s32 {d31}, [r2] ;load first_pass filter
49 beq firstpass_bfilter16x16_only
51 sub sp, sp, #272 ;reserve space on stack for temporary storage
52 vld1.u8 {d2, d3, d4}, [r0], r1 ;load src data
54 vld1.u8 {d5, d6, d7}, [r0], r1
56 mov r2, #3 ;loop counter
57 vld1.u8 {d8, d9, d10}, [r0], r1
59 vdup.8 d0, d31[0] ;first_pass filter (d0 d1)
60 vld1.u8 {d11, d12, d13}, [r0], r1
64 ;First Pass: output_height lines x output_width columns (17x16)
65 vp8e_filt_blk2d_fp16x16_loop_neon
70 vmull.u8 q7, d2, d0 ;(src_ptr[0] * Filter[0])
79 vext.8 d2, d2, d3, #1 ;construct src_ptr[1]
82 vext.8 d11, d11, d12, #1
84 vmlal.u8 q7, d2, d1 ;(src_ptr[0] * Filter[1])
91 vext.8 d9, d9, d10, #1
92 vext.8 d12, d12, d13, #1
94 vmlal.u8 q8, d3, d1 ;(src_ptr[0] * Filter[1])
101 vqrshrn.u16 d14, q7, #7 ;shift/round/saturate to u8
102 vqrshrn.u16 d15, q8, #7
103 vqrshrn.u16 d16, q9, #7
104 vqrshrn.u16 d17, q10, #7
105 vqrshrn.u16 d18, q11, #7
106 vqrshrn.u16 d19, q12, #7
107 vqrshrn.u16 d20, q13, #7
109 vld1.u8 {d2, d3, d4}, [r0], r1 ;load src data
110 vqrshrn.u16 d21, q14, #7
111 vld1.u8 {d5, d6, d7}, [r0], r1
113 vst1.u8 {d14, d15, d16, d17}, [lr]! ;store result
114 vld1.u8 {d8, d9, d10}, [r0], r1
115 vst1.u8 {d18, d19, d20, d21}, [lr]!
116 vld1.u8 {d11, d12, d13}, [r0], r1
118 bne vp8e_filt_blk2d_fp16x16_loop_neon
120 ;First-pass filtering for rest 5 lines
121 vld1.u8 {d14, d15, d16}, [r0], r1
123 vmull.u8 q9, d2, d0 ;(src_ptr[0] * Filter[0])
130 vext.8 d2, d2, d3, #1 ;construct src_ptr[1]
131 vext.8 d5, d5, d6, #1
132 vext.8 d8, d8, d9, #1
134 vmlal.u8 q9, d2, d1 ;(src_ptr[0] * Filter[1])
138 vext.8 d3, d3, d4, #1
139 vext.8 d6, d6, d7, #1
140 vext.8 d9, d9, d10, #1
142 vmlal.u8 q10, d3, d1 ;(src_ptr[0] * Filter[1])
151 vext.8 d11, d11, d12, #1 ;construct src_ptr[1]
152 vext.8 d14, d14, d15, #1
154 vmlal.u8 q1, d11, d1 ;(src_ptr[0] * Filter[1])
157 vext.8 d12, d12, d13, #1
158 vext.8 d15, d15, d16, #1
160 vmlal.u8 q2, d12, d1 ;(src_ptr[0] * Filter[1])
163 vqrshrn.u16 d10, q9, #7 ;shift/round/saturate to u8
164 vqrshrn.u16 d11, q10, #7
165 vqrshrn.u16 d12, q11, #7
166 vqrshrn.u16 d13, q12, #7
167 vqrshrn.u16 d14, q13, #7
168 vqrshrn.u16 d15, q14, #7
169 vqrshrn.u16 d16, q1, #7
170 vqrshrn.u16 d17, q2, #7
171 vqrshrn.u16 d18, q3, #7
172 vqrshrn.u16 d19, q4, #7
174 vst1.u8 {d10, d11, d12, d13}, [lr]! ;store result
175 vst1.u8 {d14, d15, d16, d17}, [lr]!
176 vst1.u8 {d18, d19}, [lr]!
180 add r3, r12, r3, lsl #3
183 vld1.u32 {d31}, [r3] ;load second_pass filter
188 vld1.u8 {d22, d23}, [lr]! ;load src data
190 vdup.8 d0, d31[0] ;second_pass filter parameters (d0 d1)
192 mov r12, #4 ;loop counter
194 vp8e_filt_blk2d_sp16x16_loop_neon
195 vld1.u8 {d24, d25}, [lr]!
196 vmull.u8 q1, d22, d0 ;(src_ptr[0] * Filter[0])
197 vld1.u8 {d26, d27}, [lr]!
199 vld1.u8 {d28, d29}, [lr]!
201 vld1.u8 {d30, d31}, [lr]!
209 vmlal.u8 q1, d24, d1 ;(src_ptr[pixel_step] * Filter[1])
220 vqrshrn.u16 d2, q1, #7 ;shift/round/saturate to u8
221 vqrshrn.u16 d3, q2, #7
222 vqrshrn.u16 d4, q3, #7
223 vqrshrn.u16 d5, q4, #7
224 vqrshrn.u16 d6, q5, #7
225 vqrshrn.u16 d7, q6, #7
226 vqrshrn.u16 d8, q7, #7
227 vqrshrn.u16 d9, q8, #7
229 vst1.u8 {d2, d3}, [r3]! ;store result
230 vst1.u8 {d4, d5}, [r3]!
231 vst1.u8 {d6, d7}, [r3]!
233 vst1.u8 {d8, d9}, [r3]!
235 bne vp8e_filt_blk2d_sp16x16_loop_neon
237 b sub_pixel_variance16x16_neon
239 ;--------------------
240 firstpass_bfilter16x16_only
241 mov r2, #4 ;loop counter
242 sub sp, sp, #528 ;reserve space on stack for temporary storage
243 vdup.8 d0, d31[0] ;first_pass filter (d0 d1)
247 ;First Pass: output_height lines x output_width columns (16x16)
248 vp8e_filt_blk2d_fpo16x16_loop_neon
249 vld1.u8 {d2, d3, d4}, [r0], r1 ;load src data
250 vld1.u8 {d5, d6, d7}, [r0], r1
251 vld1.u8 {d8, d9, d10}, [r0], r1
252 vld1.u8 {d11, d12, d13}, [r0], r1
258 vmull.u8 q7, d2, d0 ;(src_ptr[0] * Filter[0])
264 vmull.u8 q13, d11, d0
265 vmull.u8 q14, d12, d0
267 vext.8 d2, d2, d3, #1 ;construct src_ptr[1]
268 vext.8 d5, d5, d6, #1
269 vext.8 d8, d8, d9, #1
270 vext.8 d11, d11, d12, #1
272 vmlal.u8 q7, d2, d1 ;(src_ptr[0] * Filter[1])
275 vmlal.u8 q13, d11, d1
277 vext.8 d3, d3, d4, #1
278 vext.8 d6, d6, d7, #1
279 vext.8 d9, d9, d10, #1
280 vext.8 d12, d12, d13, #1
282 vmlal.u8 q8, d3, d1 ;(src_ptr[0] * Filter[1])
285 vmlal.u8 q14, d12, d1
289 vqrshrn.u16 d14, q7, #7 ;shift/round/saturate to u8
290 vqrshrn.u16 d15, q8, #7
291 vqrshrn.u16 d16, q9, #7
292 vqrshrn.u16 d17, q10, #7
293 vqrshrn.u16 d18, q11, #7
294 vqrshrn.u16 d19, q12, #7
295 vqrshrn.u16 d20, q13, #7
296 vst1.u8 {d14, d15}, [r3]! ;store result
297 vqrshrn.u16 d21, q14, #7
299 vst1.u8 {d16, d17}, [r3]!
300 vst1.u8 {d18, d19}, [r3]!
301 vst1.u8 {d20, d21}, [r3]!
303 bne vp8e_filt_blk2d_fpo16x16_loop_neon
305 b sub_pixel_variance16x16_neon
307 ;---------------------
308 secondpass_bfilter16x16_only
311 sub sp, sp, #528 ;reserve space on stack for temporary storage
312 add r3, r12, r3, lsl #3
313 mov r12, #4 ;loop counter
314 vld1.u32 {d31}, [r3] ;load second_pass filter
315 vld1.u8 {d22, d23}, [r0], r1 ;load src data
318 vdup.8 d0, d31[0] ;second_pass filter parameters (d0 d1)
321 vp8e_filt_blk2d_spo16x16_loop_neon
322 vld1.u8 {d24, d25}, [r0], r1
323 vmull.u8 q1, d22, d0 ;(src_ptr[0] * Filter[0])
324 vld1.u8 {d26, d27}, [r0], r1
326 vld1.u8 {d28, d29}, [r0], r1
328 vld1.u8 {d30, d31}, [r0], r1
336 vmlal.u8 q1, d24, d1 ;(src_ptr[pixel_step] * Filter[1])
345 vqrshrn.u16 d2, q1, #7 ;shift/round/saturate to u8
346 vqrshrn.u16 d3, q2, #7
347 vqrshrn.u16 d4, q3, #7
348 vqrshrn.u16 d5, q4, #7
349 vqrshrn.u16 d6, q5, #7
350 vqrshrn.u16 d7, q6, #7
351 vqrshrn.u16 d8, q7, #7
352 vqrshrn.u16 d9, q8, #7
354 vst1.u8 {d2, d3}, [r3]! ;store result
356 vst1.u8 {d4, d5}, [r3]!
358 vst1.u8 {d6, d7}, [r3]!
359 vst1.u8 {d8, d9}, [r3]!
361 bne vp8e_filt_blk2d_spo16x16_loop_neon
363 b sub_pixel_variance16x16_neon
365 ;----------------------------
367 sub_pixel_variance16x16_neon
368 vmov.i8 q8, #0 ;q8 - sum
369 vmov.i8 q9, #0 ;q9, q10 - sse
375 sub_pixel_variance16x16_neon_loop
376 vld1.8 {q0}, [r3]! ;Load up source and reference
377 vld1.8 {q2}, [r4], r5
379 vld1.8 {q3}, [r4], r5
381 vsubl.u8 q11, d0, d4 ;diff
386 vpadal.s16 q8, q11 ;sum
387 vmlal.s16 q9, d22, d22 ;sse
388 vmlal.s16 q10, d23, d23
393 vmlal.s16 q9, d24, d24
394 vmlal.s16 q10, d25, d25
396 vmlal.s16 q9, d26, d26
397 vmlal.s16 q10, d27, d27
399 vmlal.s16 q9, d28, d28
400 vmlal.s16 q10, d29, d29
402 bne sub_pixel_variance16x16_neon_loop
404 vadd.u32 q10, q9, q10 ;accumulate sse
405 vpaddl.s32 q0, q8 ;accumulate sum
412 vst1.32 {d1[0]}, [r6] ;store sse
413 vshr.u32 d10, d10, #8
417 vmov.32 r0, d0[0] ;return