2 ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4 ; Use of this source code is governed by a BSD-style license and patent
5 ; grant that can be found in the LICENSE file in the root of the source
6 ; tree. All contributing project authors may be found in the AUTHORS
7 ; file in the root of the source tree.
11 EXPORT |vp8_sub_pixel_variance16x16_neon|
16 AREA ||.text||
, CODE
, READONLY
, ALIGN=2
17 ; r0 unsigned char *src_ptr,
18 ; r1 int src_pixels_per_line,
21 ; stack(r4) unsigned char *dst_ptr,
22 ; stack(r5) int dst_pixels_per_line,
23 ; stack(r6) unsigned int *sse
24 ;note: most of the code is copied from bilinear_predict16x16_neon and vp8_variance16x16_neon.
26 |vp8_sub_pixel_variance16x16_neon|
PROC
29 ldr r12
, _BilinearTaps_coeff_
30 ldr r4
, [sp, #
16] ;load *dst_ptr from stack
31 ldr r5
, [sp, #
20] ;load dst_pixels_per_line from stack
32 ldr r6
, [sp, #
24] ;load *sse from stack
34 cmp r2
, #
0 ;skip first_pass filter if xoffset=0
35 beq secondpass_bfilter16x16_only
37 add r2
, r12
, r2
, lsl #
3 ;calculate filter location
39 cmp r3
, #
0 ;skip second_pass filter if yoffset=0
41 vld1.s32
{d31}, [r2
] ;load first_pass filter
43 beq firstpass_bfilter16x16_only
45 sub sp, sp, #
272 ;reserve space on stack for temporary storage
46 vld1.u8
{d2, d3, d4}, [r0
], r1
;load src data
48 vld1.u8
{d5, d6, d7}, [r0
], r1
50 mov r2
, #
3 ;loop counter
51 vld1.u8
{d8, d9, d10}, [r0
], r1
53 vdup
.8 d0
, d31
[0] ;first_pass filter (d0 d1)
54 vld1.u8
{d11, d12, d13}, [r0
], r1
58 ;First Pass: output_height lines x output_width columns (17x16)
59 vp8e_filt_blk2d_fp16x16_loop_neon
64 vmull.u8 q7
, d2
, d0
;(src_ptr[0] * Filter[0])
73 vext
.8 d2
, d2
, d3
, #
1 ;construct src_ptr[1]
76 vext
.8 d11
, d11
, d12
, #
1
78 vmlal.u8 q7
, d2
, d1
;(src_ptr[0] * Filter[1])
85 vext
.8 d9
, d9
, d10
, #
1
86 vext
.8 d12
, d12
, d13
, #
1
88 vmlal.u8 q8
, d3
, d1
;(src_ptr[0] * Filter[1])
95 vqrshrn.u16 d14
, q7
, #
7 ;shift/round/saturate to u8
96 vqrshrn.u16 d15
, q8
, #
7
97 vqrshrn.u16 d16
, q9
, #
7
98 vqrshrn.u16 d17
, q10
, #
7
99 vqrshrn.u16 d18
, q11
, #
7
100 vqrshrn.u16 d19
, q12
, #
7
101 vqrshrn.u16 d20
, q13
, #
7
103 vld1.u8
{d2, d3, d4}, [r0
], r1
;load src data
104 vqrshrn.u16 d21
, q14
, #
7
105 vld1.u8
{d5, d6, d7}, [r0
], r1
107 vst1.u8
{d14, d15, d16, d17}, [lr
]! ;store result
108 vld1.u8
{d8, d9, d10}, [r0
], r1
109 vst1.u8
{d18, d19, d20, d21}, [lr
]!
110 vld1.u8
{d11, d12, d13}, [r0
], r1
112 bne vp8e_filt_blk2d_fp16x16_loop_neon
114 ;First-pass filtering for rest 5 lines
115 vld1.u8
{d14, d15, d16}, [r0
], r1
117 vmull.u8 q9
, d2
, d0
;(src_ptr[0] * Filter[0])
124 vext
.8 d2
, d2
, d3
, #
1 ;construct src_ptr[1]
125 vext
.8 d5
, d5
, d6
, #
1
126 vext
.8 d8
, d8
, d9
, #
1
128 vmlal.u8 q9
, d2
, d1
;(src_ptr[0] * Filter[1])
132 vext
.8 d3
, d3
, d4
, #
1
133 vext
.8 d6
, d6
, d7
, #
1
134 vext
.8 d9
, d9
, d10
, #
1
136 vmlal.u8 q10
, d3
, d1
;(src_ptr[0] * Filter[1])
145 vext
.8 d11
, d11
, d12
, #
1 ;construct src_ptr[1]
146 vext
.8 d14
, d14
, d15
, #
1
148 vmlal.u8 q1
, d11
, d1
;(src_ptr[0] * Filter[1])
151 vext
.8 d12
, d12
, d13
, #
1
152 vext
.8 d15
, d15
, d16
, #
1
154 vmlal.u8 q2
, d12
, d1
;(src_ptr[0] * Filter[1])
157 vqrshrn.u16 d10
, q9
, #
7 ;shift/round/saturate to u8
158 vqrshrn.u16 d11
, q10
, #
7
159 vqrshrn.u16 d12
, q11
, #
7
160 vqrshrn.u16 d13
, q12
, #
7
161 vqrshrn.u16 d14
, q13
, #
7
162 vqrshrn.u16 d15
, q14
, #
7
163 vqrshrn.u16 d16
, q1
, #
7
164 vqrshrn.u16 d17
, q2
, #
7
165 vqrshrn.u16 d18
, q3
, #
7
166 vqrshrn.u16 d19
, q4
, #
7
168 vst1.u8
{d10, d11, d12, d13}, [lr
]! ;store result
169 vst1.u8
{d14, d15, d16, d17}, [lr
]!
170 vst1.u8
{d18, d19}, [lr
]!
174 add r3
, r12
, r3
, lsl #
3
177 vld1.u32
{d31}, [r3
] ;load second_pass filter
182 vld1.u8
{d22, d23}, [lr
]! ;load src data
184 vdup
.8 d0
, d31
[0] ;second_pass filter parameters (d0 d1)
186 mov r12
, #
4 ;loop counter
188 vp8e_filt_blk2d_sp16x16_loop_neon
189 vld1.u8
{d24, d25}, [lr
]!
190 vmull.u8 q1
, d22
, d0
;(src_ptr[0] * Filter[0])
191 vld1.u8
{d26, d27}, [lr
]!
193 vld1.u8
{d28, d29}, [lr
]!
195 vld1.u8
{d30, d31}, [lr
]!
203 vmlal.u8 q1
, d24
, d1
;(src_ptr[pixel_step] * Filter[1])
214 vqrshrn.u16 d2
, q1
, #
7 ;shift/round/saturate to u8
215 vqrshrn.u16 d3
, q2
, #
7
216 vqrshrn.u16 d4
, q3
, #
7
217 vqrshrn.u16 d5
, q4
, #
7
218 vqrshrn.u16 d6
, q5
, #
7
219 vqrshrn.u16 d7
, q6
, #
7
220 vqrshrn.u16 d8
, q7
, #
7
221 vqrshrn.u16 d9
, q8
, #
7
223 vst1.u8
{d2, d3}, [r3
]! ;store result
224 vst1.u8
{d4, d5}, [r3
]!
225 vst1.u8
{d6, d7}, [r3
]!
227 vst1.u8
{d8, d9}, [r3
]!
229 bne vp8e_filt_blk2d_sp16x16_loop_neon
231 b sub_pixel_variance16x16_neon
233 ;--------------------
234 firstpass_bfilter16x16_only
235 mov r2
, #
4 ;loop counter
236 sub sp, sp, #
528 ;reserve space on stack for temporary storage
237 vdup
.8 d0
, d31
[0] ;first_pass filter (d0 d1)
241 ;First Pass: output_height lines x output_width columns (16x16)
242 vp8e_filt_blk2d_fpo16x16_loop_neon
243 vld1.u8
{d2, d3, d4}, [r0
], r1
;load src data
244 vld1.u8
{d5, d6, d7}, [r0
], r1
245 vld1.u8
{d8, d9, d10}, [r0
], r1
246 vld1.u8
{d11, d12, d13}, [r0
], r1
252 vmull.u8 q7
, d2
, d0
;(src_ptr[0] * Filter[0])
258 vmull.u8 q13
, d11
, d0
259 vmull.u8 q14
, d12
, d0
261 vext
.8 d2
, d2
, d3
, #
1 ;construct src_ptr[1]
262 vext
.8 d5
, d5
, d6
, #
1
263 vext
.8 d8
, d8
, d9
, #
1
264 vext
.8 d11
, d11
, d12
, #
1
266 vmlal.u8 q7
, d2
, d1
;(src_ptr[0] * Filter[1])
269 vmlal.u8 q13
, d11
, d1
271 vext
.8 d3
, d3
, d4
, #
1
272 vext
.8 d6
, d6
, d7
, #
1
273 vext
.8 d9
, d9
, d10
, #
1
274 vext
.8 d12
, d12
, d13
, #
1
276 vmlal.u8 q8
, d3
, d1
;(src_ptr[0] * Filter[1])
279 vmlal.u8 q14
, d12
, d1
283 vqrshrn.u16 d14
, q7
, #
7 ;shift/round/saturate to u8
284 vqrshrn.u16 d15
, q8
, #
7
285 vqrshrn.u16 d16
, q9
, #
7
286 vqrshrn.u16 d17
, q10
, #
7
287 vqrshrn.u16 d18
, q11
, #
7
288 vqrshrn.u16 d19
, q12
, #
7
289 vqrshrn.u16 d20
, q13
, #
7
290 vst1.u8
{d14, d15}, [r3
]! ;store result
291 vqrshrn.u16 d21
, q14
, #
7
293 vst1.u8
{d16, d17}, [r3
]!
294 vst1.u8
{d18, d19}, [r3
]!
295 vst1.u8
{d20, d21}, [r3
]!
297 bne vp8e_filt_blk2d_fpo16x16_loop_neon
299 b sub_pixel_variance16x16_neon
301 ;---------------------
302 secondpass_bfilter16x16_only
305 sub sp, sp, #
528 ;reserve space on stack for temporary storage
306 add r3
, r12
, r3
, lsl #
3
307 mov r12
, #
4 ;loop counter
308 vld1.u32
{d31}, [r3
] ;load second_pass filter
309 vld1.u8
{d22, d23}, [r0
], r1
;load src data
312 vdup
.8 d0
, d31
[0] ;second_pass filter parameters (d0 d1)
315 vp8e_filt_blk2d_spo16x16_loop_neon
316 vld1.u8
{d24, d25}, [r0
], r1
317 vmull.u8 q1
, d22
, d0
;(src_ptr[0] * Filter[0])
318 vld1.u8
{d26, d27}, [r0
], r1
320 vld1.u8
{d28, d29}, [r0
], r1
322 vld1.u8
{d30, d31}, [r0
], r1
330 vmlal.u8 q1
, d24
, d1
;(src_ptr[pixel_step] * Filter[1])
339 vqrshrn.u16 d2
, q1
, #
7 ;shift/round/saturate to u8
340 vqrshrn.u16 d3
, q2
, #
7
341 vqrshrn.u16 d4
, q3
, #
7
342 vqrshrn.u16 d5
, q4
, #
7
343 vqrshrn.u16 d6
, q5
, #
7
344 vqrshrn.u16 d7
, q6
, #
7
345 vqrshrn.u16 d8
, q7
, #
7
346 vqrshrn.u16 d9
, q8
, #
7
348 vst1.u8
{d2, d3}, [r3
]! ;store result
350 vst1.u8
{d4, d5}, [r3
]!
352 vst1.u8
{d6, d7}, [r3
]!
353 vst1.u8
{d8, d9}, [r3
]!
355 bne vp8e_filt_blk2d_spo16x16_loop_neon
357 b sub_pixel_variance16x16_neon
359 ;----------------------------
361 sub_pixel_variance16x16_neon
362 vmov.i8 q8
, #
0 ;q8 - sum
363 vmov.i8 q9
, #
0 ;q9, q10 - sse
369 sub_pixel_variance16x16_neon_loop
370 vld1.8
{q0}, [r3
]! ;Load up source and reference
371 vld1.8
{q2}, [r4
], r5
373 vld1.8
{q3}, [r4
], r5
375 vsubl.u8 q11
, d0
, d4
;diff
380 vpadal.s16 q8
, q11
;sum
381 vmlal.s16 q9
, d22
, d22
;sse
382 vmlal.s16 q10
, d23
, d23
387 vmlal.s16 q9
, d24
, d24
388 vmlal.s16 q10
, d25
, d25
390 vmlal.s16 q9
, d26
, d26
391 vmlal.s16 q10
, d27
, d27
393 vmlal.s16 q9
, d28
, d28
394 vmlal.s16 q10
, d29
, d29
396 bne sub_pixel_variance16x16_neon_loop
398 vadd.u32 q10
, q9
, q10
;accumulate sse
399 vpaddl.s32 q0
, q8
;accumulate sum
406 vst1.32
{d1[0]}, [r6
] ;store sse
407 vshr.s32 d10
, d10
, #
8
411 vmov
.32 r0
, d0
[0] ;return
418 AREA vp8e_bilinear_taps_dat
, DATA
, READWRITE
;read/write by default
419 ;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
420 ;One word each is reserved. Label filter_coeff can be used to access the data.
421 ;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
423 DCD bilinear_taps_coeff
425 DCD
128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112