Initial WebM release
[libvpx.git] / vp8 / common / arm / neon / sixtappredict8x8_neon.asm
blobd27485e6c6e3a0faf7abaf7572bc99ea5e971a03
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_sixtap_predict8x8_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_pitch
24 |vp8_sixtap_predict8x8_neon| PROC
25 push {r4-r5, lr}
27 ldr r12, _filter8_coeff_
29 ldr r4, [sp, #12] ;load parameters from stack
30 ldr r5, [sp, #16] ;load parameters from stack
32 cmp r2, #0 ;skip first_pass filter if xoffset=0
33 beq secondpass_filter8x8_only
35 add r2, r12, r2, lsl #5 ;calculate filter location
37 cmp r3, #0 ;skip second_pass filter if yoffset=0
39 vld1.s32 {q14, q15}, [r2] ;load first_pass filter
41 beq firstpass_filter8x8_only
43 sub sp, sp, #64 ;reserve space on stack for temporary storage
44 mov lr, sp
46 vabs.s32 q12, q14
47 vabs.s32 q13, q15
49 mov r2, #2 ;loop counter
50 sub r0, r0, #2 ;move srcptr back to (line-2) and (column-2)
51 sub r0, r0, r1, lsl #1
53 vdup.8 d0, d24[0] ;first_pass filter (d0-d5)
54 vdup.8 d1, d24[4]
55 vdup.8 d2, d25[0]
57 ;First pass: output_height lines x output_width columns (13x8)
58 vld1.u8 {q3}, [r0], r1 ;load src data
59 vdup.8 d3, d25[4]
60 vld1.u8 {q4}, [r0], r1
61 vdup.8 d4, d26[0]
62 vld1.u8 {q5}, [r0], r1
63 vdup.8 d5, d26[4]
64 vld1.u8 {q6}, [r0], r1
66 filt_blk2d_fp8x8_loop_neon
67 pld [r0]
68 pld [r0, r1]
69 pld [r0, r1, lsl #1]
71 vmull.u8 q7, d6, d0 ;(src_ptr[-2] * vp8_filter[0])
72 vmull.u8 q8, d8, d0
73 vmull.u8 q9, d10, d0
74 vmull.u8 q10, d12, d0
76 vext.8 d28, d6, d7, #1 ;construct src_ptr[-1]
77 vext.8 d29, d8, d9, #1
78 vext.8 d30, d10, d11, #1
79 vext.8 d31, d12, d13, #1
81 vmlsl.u8 q7, d28, d1 ;-(src_ptr[-1] * vp8_filter[1])
82 vmlsl.u8 q8, d29, d1
83 vmlsl.u8 q9, d30, d1
84 vmlsl.u8 q10, d31, d1
86 vext.8 d28, d6, d7, #4 ;construct src_ptr[2]
87 vext.8 d29, d8, d9, #4
88 vext.8 d30, d10, d11, #4
89 vext.8 d31, d12, d13, #4
91 vmlsl.u8 q7, d28, d4 ;-(src_ptr[2] * vp8_filter[4])
92 vmlsl.u8 q8, d29, d4
93 vmlsl.u8 q9, d30, d4
94 vmlsl.u8 q10, d31, d4
96 vext.8 d28, d6, d7, #2 ;construct src_ptr[0]
97 vext.8 d29, d8, d9, #2
98 vext.8 d30, d10, d11, #2
99 vext.8 d31, d12, d13, #2
101 vmlal.u8 q7, d28, d2 ;(src_ptr[0] * vp8_filter[2])
102 vmlal.u8 q8, d29, d2
103 vmlal.u8 q9, d30, d2
104 vmlal.u8 q10, d31, d2
106 vext.8 d28, d6, d7, #5 ;construct src_ptr[3]
107 vext.8 d29, d8, d9, #5
108 vext.8 d30, d10, d11, #5
109 vext.8 d31, d12, d13, #5
111 vmlal.u8 q7, d28, d5 ;(src_ptr[3] * vp8_filter[5])
112 vmlal.u8 q8, d29, d5
113 vmlal.u8 q9, d30, d5
114 vmlal.u8 q10, d31, d5
116 vext.8 d28, d6, d7, #3 ;construct src_ptr[1]
117 vext.8 d29, d8, d9, #3
118 vext.8 d30, d10, d11, #3
119 vext.8 d31, d12, d13, #3
121 vmull.u8 q3, d28, d3 ;(src_ptr[1] * vp8_filter[3])
122 vmull.u8 q4, d29, d3
123 vmull.u8 q5, d30, d3
124 vmull.u8 q6, d31, d3
126 subs r2, r2, #1
128 vqadd.s16 q7, q3 ;sum of all (src_data*filter_parameters)
129 vqadd.s16 q8, q4
130 vqadd.s16 q9, q5
131 vqadd.s16 q10, q6
133 vld1.u8 {q3}, [r0], r1 ;load src data
135 vqrshrun.s16 d22, q7, #7 ;shift/round/saturate to u8
136 vqrshrun.s16 d23, q8, #7
137 vqrshrun.s16 d24, q9, #7
138 vqrshrun.s16 d25, q10, #7
140 vst1.u8 {d22}, [lr]! ;store result
141 vld1.u8 {q4}, [r0], r1
142 vst1.u8 {d23}, [lr]!
143 vld1.u8 {q5}, [r0], r1
144 vst1.u8 {d24}, [lr]!
145 vld1.u8 {q6}, [r0], r1
146 vst1.u8 {d25}, [lr]!
148 bne filt_blk2d_fp8x8_loop_neon
150 ;first_pass filtering on the rest 5-line data
151 ;vld1.u8 {q3}, [r0], r1 ;load src data
152 ;vld1.u8 {q4}, [r0], r1
153 ;vld1.u8 {q5}, [r0], r1
154 ;vld1.u8 {q6}, [r0], r1
155 vld1.u8 {q7}, [r0], r1
157 vmull.u8 q8, d6, d0 ;(src_ptr[-2] * vp8_filter[0])
158 vmull.u8 q9, d8, d0
159 vmull.u8 q10, d10, d0
160 vmull.u8 q11, d12, d0
161 vmull.u8 q12, d14, d0
163 vext.8 d27, d6, d7, #1 ;construct src_ptr[-1]
164 vext.8 d28, d8, d9, #1
165 vext.8 d29, d10, d11, #1
166 vext.8 d30, d12, d13, #1
167 vext.8 d31, d14, d15, #1
169 vmlsl.u8 q8, d27, d1 ;-(src_ptr[-1] * vp8_filter[1])
170 vmlsl.u8 q9, d28, d1
171 vmlsl.u8 q10, d29, d1
172 vmlsl.u8 q11, d30, d1
173 vmlsl.u8 q12, d31, d1
175 vext.8 d27, d6, d7, #4 ;construct src_ptr[2]
176 vext.8 d28, d8, d9, #4
177 vext.8 d29, d10, d11, #4
178 vext.8 d30, d12, d13, #4
179 vext.8 d31, d14, d15, #4
181 vmlsl.u8 q8, d27, d4 ;-(src_ptr[2] * vp8_filter[4])
182 vmlsl.u8 q9, d28, d4
183 vmlsl.u8 q10, d29, d4
184 vmlsl.u8 q11, d30, d4
185 vmlsl.u8 q12, d31, d4
187 vext.8 d27, d6, d7, #2 ;construct src_ptr[0]
188 vext.8 d28, d8, d9, #2
189 vext.8 d29, d10, d11, #2
190 vext.8 d30, d12, d13, #2
191 vext.8 d31, d14, d15, #2
193 vmlal.u8 q8, d27, d2 ;(src_ptr[0] * vp8_filter[2])
194 vmlal.u8 q9, d28, d2
195 vmlal.u8 q10, d29, d2
196 vmlal.u8 q11, d30, d2
197 vmlal.u8 q12, d31, d2
199 vext.8 d27, d6, d7, #5 ;construct src_ptr[3]
200 vext.8 d28, d8, d9, #5
201 vext.8 d29, d10, d11, #5
202 vext.8 d30, d12, d13, #5
203 vext.8 d31, d14, d15, #5
205 vmlal.u8 q8, d27, d5 ;(src_ptr[3] * vp8_filter[5])
206 vmlal.u8 q9, d28, d5
207 vmlal.u8 q10, d29, d5
208 vmlal.u8 q11, d30, d5
209 vmlal.u8 q12, d31, d5
211 vext.8 d27, d6, d7, #3 ;construct src_ptr[1]
212 vext.8 d28, d8, d9, #3
213 vext.8 d29, d10, d11, #3
214 vext.8 d30, d12, d13, #3
215 vext.8 d31, d14, d15, #3
217 vmull.u8 q3, d27, d3 ;(src_ptr[1] * vp8_filter[3])
218 vmull.u8 q4, d28, d3
219 vmull.u8 q5, d29, d3
220 vmull.u8 q6, d30, d3
221 vmull.u8 q7, d31, d3
223 vqadd.s16 q8, q3 ;sum of all (src_data*filter_parameters)
224 vqadd.s16 q9, q4
225 vqadd.s16 q10, q5
226 vqadd.s16 q11, q6
227 vqadd.s16 q12, q7
229 add r3, r12, r3, lsl #5
231 vqrshrun.s16 d26, q8, #7 ;shift/round/saturate to u8
232 sub lr, lr, #64
233 vqrshrun.s16 d27, q9, #7
234 vld1.u8 {q9}, [lr]! ;load intermediate data from stack
235 vqrshrun.s16 d28, q10, #7
236 vld1.u8 {q10}, [lr]!
238 vld1.s32 {q5, q6}, [r3] ;load second_pass filter
240 vqrshrun.s16 d29, q11, #7
241 vld1.u8 {q11}, [lr]!
243 vabs.s32 q7, q5
244 vabs.s32 q8, q6
246 vqrshrun.s16 d30, q12, #7
247 vld1.u8 {q12}, [lr]!
249 ;Second pass: 8x8
250 mov r3, #2 ;loop counter
252 vdup.8 d0, d14[0] ;second_pass filter parameters (d0-d5)
253 vdup.8 d1, d14[4]
254 vdup.8 d2, d15[0]
255 vdup.8 d3, d15[4]
256 vdup.8 d4, d16[0]
257 vdup.8 d5, d16[4]
259 filt_blk2d_sp8x8_loop_neon
260 vmull.u8 q3, d18, d0 ;(src_ptr[-2] * vp8_filter[0])
261 vmull.u8 q4, d19, d0
262 vmull.u8 q5, d20, d0
263 vmull.u8 q6, d21, d0
265 vmlsl.u8 q3, d19, d1 ;-(src_ptr[-1] * vp8_filter[1])
266 vmlsl.u8 q4, d20, d1
267 vmlsl.u8 q5, d21, d1
268 vmlsl.u8 q6, d22, d1
270 vmlsl.u8 q3, d22, d4 ;-(src_ptr[2] * vp8_filter[4])
271 vmlsl.u8 q4, d23, d4
272 vmlsl.u8 q5, d24, d4
273 vmlsl.u8 q6, d25, d4
275 vmlal.u8 q3, d20, d2 ;(src_ptr[0] * vp8_filter[2])
276 vmlal.u8 q4, d21, d2
277 vmlal.u8 q5, d22, d2
278 vmlal.u8 q6, d23, d2
280 vmlal.u8 q3, d23, d5 ;(src_ptr[3] * vp8_filter[5])
281 vmlal.u8 q4, d24, d5
282 vmlal.u8 q5, d25, d5
283 vmlal.u8 q6, d26, d5
285 vmull.u8 q7, d21, d3 ;(src_ptr[1] * vp8_filter[3])
286 vmull.u8 q8, d22, d3
287 vmull.u8 q9, d23, d3
288 vmull.u8 q10, d24, d3
290 subs r3, r3, #1
292 vqadd.s16 q7, q3 ;sum of all (src_data*filter_parameters)
293 vqadd.s16 q8, q4
294 vqadd.s16 q9, q5
295 vqadd.s16 q10, q6
297 vqrshrun.s16 d6, q7, #7 ;shift/round/saturate to u8
298 vqrshrun.s16 d7, q8, #7
299 vqrshrun.s16 d8, q9, #7
300 vqrshrun.s16 d9, q10, #7
302 vmov q9, q11
303 vst1.u8 {d6}, [r4], r5 ;store result
304 vmov q10, q12
305 vst1.u8 {d7}, [r4], r5
306 vmov q11, q13
307 vst1.u8 {d8}, [r4], r5
308 vmov q12, q14
309 vst1.u8 {d9}, [r4], r5
310 vmov d26, d30
312 bne filt_blk2d_sp8x8_loop_neon
314 add sp, sp, #64
315 pop {r4-r5,pc}
317 ;---------------------
318 firstpass_filter8x8_only
319 ;add r2, r12, r2, lsl #5 ;calculate filter location
320 ;vld1.s32 {q14, q15}, [r2] ;load first_pass filter
321 vabs.s32 q12, q14
322 vabs.s32 q13, q15
324 mov r2, #2 ;loop counter
325 sub r0, r0, #2 ;move srcptr back to (line-2) and (column-2)
327 vdup.8 d0, d24[0] ;first_pass filter (d0-d5)
328 vdup.8 d1, d24[4]
329 vdup.8 d2, d25[0]
330 vdup.8 d3, d25[4]
331 vdup.8 d4, d26[0]
332 vdup.8 d5, d26[4]
334 ;First pass: output_height lines x output_width columns (8x8)
335 filt_blk2d_fpo8x8_loop_neon
336 vld1.u8 {q3}, [r0], r1 ;load src data
337 vld1.u8 {q4}, [r0], r1
338 vld1.u8 {q5}, [r0], r1
339 vld1.u8 {q6}, [r0], r1
341 pld [r0]
342 pld [r0, r1]
343 pld [r0, r1, lsl #1]
345 vmull.u8 q7, d6, d0 ;(src_ptr[-2] * vp8_filter[0])
346 vmull.u8 q8, d8, d0
347 vmull.u8 q9, d10, d0
348 vmull.u8 q10, d12, d0
350 vext.8 d28, d6, d7, #1 ;construct src_ptr[-1]
351 vext.8 d29, d8, d9, #1
352 vext.8 d30, d10, d11, #1
353 vext.8 d31, d12, d13, #1
355 vmlsl.u8 q7, d28, d1 ;-(src_ptr[-1] * vp8_filter[1])
356 vmlsl.u8 q8, d29, d1
357 vmlsl.u8 q9, d30, d1
358 vmlsl.u8 q10, d31, d1
360 vext.8 d28, d6, d7, #4 ;construct src_ptr[2]
361 vext.8 d29, d8, d9, #4
362 vext.8 d30, d10, d11, #4
363 vext.8 d31, d12, d13, #4
365 vmlsl.u8 q7, d28, d4 ;-(src_ptr[2] * vp8_filter[4])
366 vmlsl.u8 q8, d29, d4
367 vmlsl.u8 q9, d30, d4
368 vmlsl.u8 q10, d31, d4
370 vext.8 d28, d6, d7, #2 ;construct src_ptr[0]
371 vext.8 d29, d8, d9, #2
372 vext.8 d30, d10, d11, #2
373 vext.8 d31, d12, d13, #2
375 vmlal.u8 q7, d28, d2 ;(src_ptr[0] * vp8_filter[2])
376 vmlal.u8 q8, d29, d2
377 vmlal.u8 q9, d30, d2
378 vmlal.u8 q10, d31, d2
380 vext.8 d28, d6, d7, #5 ;construct src_ptr[3]
381 vext.8 d29, d8, d9, #5
382 vext.8 d30, d10, d11, #5
383 vext.8 d31, d12, d13, #5
385 vmlal.u8 q7, d28, d5 ;(src_ptr[3] * vp8_filter[5])
386 vmlal.u8 q8, d29, d5
387 vmlal.u8 q9, d30, d5
388 vmlal.u8 q10, d31, d5
390 vext.8 d28, d6, d7, #3 ;construct src_ptr[1]
391 vext.8 d29, d8, d9, #3
392 vext.8 d30, d10, d11, #3
393 vext.8 d31, d12, d13, #3
395 vmull.u8 q3, d28, d3 ;(src_ptr[1] * vp8_filter[3])
396 vmull.u8 q4, d29, d3
397 vmull.u8 q5, d30, d3
398 vmull.u8 q6, d31, d3
400 vqadd.s16 q7, q3 ;sum of all (src_data*filter_parameters)
401 vqadd.s16 q8, q4
402 vqadd.s16 q9, q5
403 vqadd.s16 q10, q6
405 subs r2, r2, #1
407 vqrshrun.s16 d22, q7, #7 ;shift/round/saturate to u8
408 vqrshrun.s16 d23, q8, #7
409 vqrshrun.s16 d24, q9, #7
410 vqrshrun.s16 d25, q10, #7
412 vst1.u8 {d22}, [r4], r5 ;store result
413 vst1.u8 {d23}, [r4], r5
414 vst1.u8 {d24}, [r4], r5
415 vst1.u8 {d25}, [r4], r5
417 bne filt_blk2d_fpo8x8_loop_neon
419 pop {r4-r5,pc}
421 ;---------------------
422 secondpass_filter8x8_only
423 sub r0, r0, r1, lsl #1
424 add r3, r12, r3, lsl #5
426 vld1.u8 {d18}, [r0], r1 ;load src data
427 vld1.s32 {q5, q6}, [r3] ;load second_pass filter
428 vld1.u8 {d19}, [r0], r1
429 vabs.s32 q7, q5
430 vld1.u8 {d20}, [r0], r1
431 vabs.s32 q8, q6
432 vld1.u8 {d21}, [r0], r1
433 mov r3, #2 ;loop counter
434 vld1.u8 {d22}, [r0], r1
435 vdup.8 d0, d14[0] ;second_pass filter parameters (d0-d5)
436 vld1.u8 {d23}, [r0], r1
437 vdup.8 d1, d14[4]
438 vld1.u8 {d24}, [r0], r1
439 vdup.8 d2, d15[0]
440 vld1.u8 {d25}, [r0], r1
441 vdup.8 d3, d15[4]
442 vld1.u8 {d26}, [r0], r1
443 vdup.8 d4, d16[0]
444 vld1.u8 {d27}, [r0], r1
445 vdup.8 d5, d16[4]
446 vld1.u8 {d28}, [r0], r1
447 vld1.u8 {d29}, [r0], r1
448 vld1.u8 {d30}, [r0], r1
450 ;Second pass: 8x8
451 filt_blk2d_spo8x8_loop_neon
452 vmull.u8 q3, d18, d0 ;(src_ptr[-2] * vp8_filter[0])
453 vmull.u8 q4, d19, d0
454 vmull.u8 q5, d20, d0
455 vmull.u8 q6, d21, d0
457 vmlsl.u8 q3, d19, d1 ;-(src_ptr[-1] * vp8_filter[1])
458 vmlsl.u8 q4, d20, d1
459 vmlsl.u8 q5, d21, d1
460 vmlsl.u8 q6, d22, d1
462 vmlsl.u8 q3, d22, d4 ;-(src_ptr[2] * vp8_filter[4])
463 vmlsl.u8 q4, d23, d4
464 vmlsl.u8 q5, d24, d4
465 vmlsl.u8 q6, d25, d4
467 vmlal.u8 q3, d20, d2 ;(src_ptr[0] * vp8_filter[2])
468 vmlal.u8 q4, d21, d2
469 vmlal.u8 q5, d22, d2
470 vmlal.u8 q6, d23, d2
472 vmlal.u8 q3, d23, d5 ;(src_ptr[3] * vp8_filter[5])
473 vmlal.u8 q4, d24, d5
474 vmlal.u8 q5, d25, d5
475 vmlal.u8 q6, d26, d5
477 vmull.u8 q7, d21, d3 ;(src_ptr[1] * vp8_filter[3])
478 vmull.u8 q8, d22, d3
479 vmull.u8 q9, d23, d3
480 vmull.u8 q10, d24, d3
482 subs r3, r3, #1
484 vqadd.s16 q7, q3 ;sum of all (src_data*filter_parameters)
485 vqadd.s16 q8, q4
486 vqadd.s16 q9, q5
487 vqadd.s16 q10, q6
489 vqrshrun.s16 d6, q7, #7 ;shift/round/saturate to u8
490 vqrshrun.s16 d7, q8, #7
491 vqrshrun.s16 d8, q9, #7
492 vqrshrun.s16 d9, q10, #7
494 vmov q9, q11
495 vst1.u8 {d6}, [r4], r5 ;store result
496 vmov q10, q12
497 vst1.u8 {d7}, [r4], r5
498 vmov q11, q13
499 vst1.u8 {d8}, [r4], r5
500 vmov q12, q14
501 vst1.u8 {d9}, [r4], r5
502 vmov d26, d30
504 bne filt_blk2d_spo8x8_loop_neon
506 pop {r4-r5,pc}
508 ENDP
510 ;-----------------
511 AREA subpelfilters8_dat, DATA, READWRITE ;read/write by default
512 ;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
513 ;One word each is reserved. Label filter_coeff can be used to access the data.
514 ;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
515 _filter8_coeff_
516 DCD filter8_coeff
517 filter8_coeff
518 DCD 0, 0, 128, 0, 0, 0, 0, 0
519 DCD 0, -6, 123, 12, -1, 0, 0, 0
520 DCD 2, -11, 108, 36, -8, 1, 0, 0
521 DCD 0, -9, 93, 50, -6, 0, 0, 0
522 DCD 3, -16, 77, 77, -16, 3, 0, 0
523 DCD 0, -6, 50, 93, -9, 0, 0, 0
524 DCD 1, -8, 36, 108, -11, 2, 0, 0
525 DCD 0, -1, 12, 123, -6, 0, 0, 0