Initial WebM release
[libvpx.git] / vp8 / encoder / arm / neon / vp8_subpixelvariance16x16_neon.asm
blobaec716e3b18261ea6327b18b7856f3baeeba856e
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|
12 ARM
13 REQUIRE8
14 PRESERVE8
16 AREA ||.text||, CODE, READONLY, ALIGN=2
17 ; r0 unsigned char *src_ptr,
18 ; r1 int src_pixels_per_line,
19 ; r2 int xoffset,
20 ; r3 int yoffset,
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
27 push {r4-r6, lr}
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
47 mov lr, sp
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
56 vdup.8 d1, d31[4]
58 ;First Pass: output_height lines x output_width columns (17x16)
59 vp8e_filt_blk2d_fp16x16_loop_neon
60 pld [r0]
61 pld [r0, r1]
62 pld [r0, r1, lsl #1]
64 vmull.u8 q7, d2, d0 ;(src_ptr[0] * Filter[0])
65 vmull.u8 q8, d3, d0
66 vmull.u8 q9, d5, d0
67 vmull.u8 q10, d6, d0
68 vmull.u8 q11, d8, d0
69 vmull.u8 q12, d9, d0
70 vmull.u8 q13, d11, d0
71 vmull.u8 q14, d12, d0
73 vext.8 d2, d2, d3, #1 ;construct src_ptr[1]
74 vext.8 d5, d5, d6, #1
75 vext.8 d8, d8, d9, #1
76 vext.8 d11, d11, d12, #1
78 vmlal.u8 q7, d2, d1 ;(src_ptr[0] * Filter[1])
79 vmlal.u8 q9, d5, d1
80 vmlal.u8 q11, d8, d1
81 vmlal.u8 q13, d11, d1
83 vext.8 d3, d3, d4, #1
84 vext.8 d6, d6, d7, #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])
89 vmlal.u8 q10, d6, d1
90 vmlal.u8 q12, d9, d1
91 vmlal.u8 q14, d12, d1
93 subs r2, r2, #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])
118 vmull.u8 q10, d3, d0
119 vmull.u8 q11, d5, d0
120 vmull.u8 q12, d6, d0
121 vmull.u8 q13, d8, d0
122 vmull.u8 q14, d9, d0
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])
129 vmlal.u8 q11, d5, d1
130 vmlal.u8 q13, d8, d1
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])
137 vmlal.u8 q12, d6, d1
138 vmlal.u8 q14, d9, d1
140 vmull.u8 q1, d11, d0
141 vmull.u8 q2, d12, d0
142 vmull.u8 q3, d14, d0
143 vmull.u8 q4, d15, d0
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])
149 vmlal.u8 q3, d14, d1
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])
155 vmlal.u8 q4, d15, d1
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]!
172 ;Second pass: 16x16
173 ;secondpass_filter
174 add r3, r12, r3, lsl #3
175 sub lr, lr, #272
177 vld1.u32 {d31}, [r3] ;load second_pass filter
179 sub sp, sp, #256
180 mov r3, sp
182 vld1.u8 {d22, d23}, [lr]! ;load src data
184 vdup.8 d0, d31[0] ;second_pass filter parameters (d0 d1)
185 vdup.8 d1, d31[4]
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]!
192 vmull.u8 q2, d23, d0
193 vld1.u8 {d28, d29}, [lr]!
194 vmull.u8 q3, d24, d0
195 vld1.u8 {d30, d31}, [lr]!
197 vmull.u8 q4, d25, d0
198 vmull.u8 q5, d26, d0
199 vmull.u8 q6, d27, d0
200 vmull.u8 q7, d28, d0
201 vmull.u8 q8, d29, d0
203 vmlal.u8 q1, d24, d1 ;(src_ptr[pixel_step] * Filter[1])
204 vmlal.u8 q2, d25, d1
205 vmlal.u8 q3, d26, d1
206 vmlal.u8 q4, d27, d1
207 vmlal.u8 q5, d28, d1
208 vmlal.u8 q6, d29, d1
209 vmlal.u8 q7, d30, d1
210 vmlal.u8 q8, d31, d1
212 subs r12, r12, #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]!
226 vmov q11, q15
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)
238 vdup.8 d1, d31[4]
239 mov r3, sp
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
248 pld [r0]
249 pld [r0, r1]
250 pld [r0, r1, lsl #1]
252 vmull.u8 q7, d2, d0 ;(src_ptr[0] * Filter[0])
253 vmull.u8 q8, d3, d0
254 vmull.u8 q9, d5, d0
255 vmull.u8 q10, d6, d0
256 vmull.u8 q11, d8, d0
257 vmull.u8 q12, d9, d0
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])
267 vmlal.u8 q9, d5, d1
268 vmlal.u8 q11, d8, d1
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])
277 vmlal.u8 q10, d6, d1
278 vmlal.u8 q12, d9, d1
279 vmlal.u8 q14, d12, d1
281 subs r2, r2, #1
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
303 ;Second pass: 16x16
304 ;secondpass_filter
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
310 mov r3, sp
312 vdup.8 d0, d31[0] ;second_pass filter parameters (d0 d1)
313 vdup.8 d1, d31[4]
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
319 vmull.u8 q2, d23, d0
320 vld1.u8 {d28, d29}, [r0], r1
321 vmull.u8 q3, d24, d0
322 vld1.u8 {d30, d31}, [r0], r1
324 vmull.u8 q4, d25, d0
325 vmull.u8 q5, d26, d0
326 vmull.u8 q6, d27, d0
327 vmull.u8 q7, d28, d0
328 vmull.u8 q8, d29, d0
330 vmlal.u8 q1, d24, d1 ;(src_ptr[pixel_step] * Filter[1])
331 vmlal.u8 q2, d25, d1
332 vmlal.u8 q3, d26, d1
333 vmlal.u8 q4, d27, d1
334 vmlal.u8 q5, d28, d1
335 vmlal.u8 q6, d29, d1
336 vmlal.u8 q7, d30, d1
337 vmlal.u8 q8, d31, d1
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
349 subs r12, r12, #1
350 vst1.u8 {d4, d5}, [r3]!
351 vmov q11, q15
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 ;----------------------------
360 ;variance16x16
361 sub_pixel_variance16x16_neon
362 vmov.i8 q8, #0 ;q8 - sum
363 vmov.i8 q9, #0 ;q9, q10 - sse
364 vmov.i8 q10, #0
366 sub r3, r3, #256
367 mov r12, #8
369 sub_pixel_variance16x16_neon_loop
370 vld1.8 {q0}, [r3]! ;Load up source and reference
371 vld1.8 {q2}, [r4], r5
372 vld1.8 {q1}, [r3]!
373 vld1.8 {q3}, [r4], r5
375 vsubl.u8 q11, d0, d4 ;diff
376 vsubl.u8 q12, d1, d5
377 vsubl.u8 q13, d2, d6
378 vsubl.u8 q14, d3, d7
380 vpadal.s16 q8, q11 ;sum
381 vmlal.s16 q9, d22, d22 ;sse
382 vmlal.s16 q10, d23, d23
384 subs r12, r12, #1
386 vpadal.s16 q8, q12
387 vmlal.s16 q9, d24, d24
388 vmlal.s16 q10, d25, d25
389 vpadal.s16 q8, q13
390 vmlal.s16 q9, d26, d26
391 vmlal.s16 q10, d27, d27
392 vpadal.s16 q8, q14
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
401 vpaddl.u32 q1, q10
402 vadd.s64 d0, d0, d1
403 vadd.u64 d1, d2, d3
405 vmull.s32 q5, d0, d0
406 vst1.32 {d1[0]}, [r6] ;store sse
407 vshr.s32 d10, d10, #8
408 vsub.s32 d0, d1, d10
410 add sp, sp, #528
411 vmov.32 r0, d0[0] ;return
413 pop {r4-r6,pc}
415 ENDP
417 ;-----------------
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 ...
422 _BilinearTaps_coeff_
423 DCD bilinear_taps_coeff
424 bilinear_taps_coeff
425 DCD 128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112