arm: remove duplicate functions
[libvpx.git] / vp8 / common / arm / neon / sixtappredict16x16_neon.asm
blobe434a709c43aee4fd2a8eb538dbfd18b147434f3
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.
12 EXPORT |vp8_sixtap_predict16x16_neon|
13 ARM
14 REQUIRE8
15 PRESERVE8
17 AREA ||.text||, CODE, READONLY, ALIGN=2
18 ; r0 unsigned char *src_ptr,
19 ; r1 int src_pixels_per_line,
20 ; r2 int xoffset,
21 ; r3 int yoffset,
22 ; r4 unsigned char *dst_ptr,
23 ; stack(r5) int dst_pitch
25 ;Note: To take advantage of 8-bit mulplication instruction in NEON. First apply abs() to
26 ; filter coeffs to make them u8. Then, use vmlsl for negtive coeffs. After multiplication,
27 ; the result can be negtive. So, I treat the result as s16. But, since it is also possible
28 ; that the result can be a large positive number (> 2^15-1), which could be confused as a
29 ; negtive number. To avoid that error, apply filter coeffs in the order of 0, 1, 4 ,5 ,2,
30 ; which ensures that the result stays in s16 range. Finally, saturated add the result by
31 ; applying 3rd filter coeff. Same applys to other filter functions.
33 |vp8_sixtap_predict16x16_neon| PROC
34 push {r4-r5, lr}
36 ldr r12, _filter16_coeff_
37 ldr r4, [sp, #12] ;load parameters from stack
38 ldr r5, [sp, #16] ;load parameters from stack
40 cmp r2, #0 ;skip first_pass filter if xoffset=0
41 beq secondpass_filter16x16_only
43 add r2, r12, r2, lsl #5 ;calculate filter location
45 cmp r3, #0 ;skip second_pass filter if yoffset=0
47 vld1.s32 {q14, q15}, [r2] ;load first_pass filter
49 beq firstpass_filter16x16_only
51 sub sp, sp, #336 ;reserve space on stack for temporary storage
52 mov lr, sp
54 vabs.s32 q12, q14
55 vabs.s32 q13, q15
57 mov r2, #7 ;loop counter
58 sub r0, r0, #2 ;move srcptr back to (line-2) and (column-2)
59 sub r0, r0, r1, lsl #1
61 vdup.8 d0, d24[0] ;first_pass filter (d0-d5)
62 vdup.8 d1, d24[4]
63 vdup.8 d2, d25[0]
64 vdup.8 d3, d25[4]
65 vdup.8 d4, d26[0]
66 vdup.8 d5, d26[4]
68 ;First Pass: output_height lines x output_width columns (21x16)
69 filt_blk2d_fp16x16_loop_neon
70 vld1.u8 {d6, d7, d8}, [r0], r1 ;load src data
71 vld1.u8 {d9, d10, d11}, [r0], r1
72 vld1.u8 {d12, d13, d14}, [r0], r1
74 pld [r0]
75 pld [r0, r1]
76 pld [r0, r1, lsl #1]
78 vmull.u8 q8, d6, d0 ;(src_ptr[-2] * vp8_filter[0])
79 vmull.u8 q9, d7, d0
80 vmull.u8 q10, d9, d0
81 vmull.u8 q11, d10, d0
82 vmull.u8 q12, d12, d0
83 vmull.u8 q13, d13, d0
85 vext.8 d28, d6, d7, #1 ;construct src_ptr[-1]
86 vext.8 d29, d9, d10, #1
87 vext.8 d30, d12, d13, #1
89 vmlsl.u8 q8, d28, d1 ;-(src_ptr[-1] * vp8_filter[1])
90 vmlsl.u8 q10, d29, d1
91 vmlsl.u8 q12, d30, d1
93 vext.8 d28, d7, d8, #1
94 vext.8 d29, d10, d11, #1
95 vext.8 d30, d13, d14, #1
97 vmlsl.u8 q9, d28, d1 ;-(src_ptr[-1] * vp8_filter[1])
98 vmlsl.u8 q11, d29, d1
99 vmlsl.u8 q13, d30, d1
101 vext.8 d28, d6, d7, #4 ;construct src_ptr[2]
102 vext.8 d29, d9, d10, #4
103 vext.8 d30, d12, d13, #4
105 vmlsl.u8 q8, d28, d4 ;-(src_ptr[2] * vp8_filter[4])
106 vmlsl.u8 q10, d29, d4
107 vmlsl.u8 q12, d30, d4
109 vext.8 d28, d7, d8, #4
110 vext.8 d29, d10, d11, #4
111 vext.8 d30, d13, d14, #4
113 vmlsl.u8 q9, d28, d4 ;-(src_ptr[2] * vp8_filter[4])
114 vmlsl.u8 q11, d29, d4
115 vmlsl.u8 q13, d30, d4
117 vext.8 d28, d6, d7, #5 ;construct src_ptr[3]
118 vext.8 d29, d9, d10, #5
119 vext.8 d30, d12, d13, #5
121 vmlal.u8 q8, d28, d5 ;(src_ptr[3] * vp8_filter[5])
122 vmlal.u8 q10, d29, d5
123 vmlal.u8 q12, d30, d5
125 vext.8 d28, d7, d8, #5
126 vext.8 d29, d10, d11, #5
127 vext.8 d30, d13, d14, #5
129 vmlal.u8 q9, d28, d5 ;(src_ptr[3] * vp8_filter[5])
130 vmlal.u8 q11, d29, d5
131 vmlal.u8 q13, d30, d5
133 vext.8 d28, d6, d7, #2 ;construct src_ptr[0]
134 vext.8 d29, d9, d10, #2
135 vext.8 d30, d12, d13, #2
137 vmlal.u8 q8, d28, d2 ;(src_ptr[0] * vp8_filter[2])
138 vmlal.u8 q10, d29, d2
139 vmlal.u8 q12, d30, d2
141 vext.8 d28, d7, d8, #2
142 vext.8 d29, d10, d11, #2
143 vext.8 d30, d13, d14, #2
145 vmlal.u8 q9, d28, d2 ;(src_ptr[0] * vp8_filter[2])
146 vmlal.u8 q11, d29, d2
147 vmlal.u8 q13, d30, d2
149 vext.8 d28, d6, d7, #3 ;construct src_ptr[1]
150 vext.8 d29, d9, d10, #3
151 vext.8 d30, d12, d13, #3
153 vext.8 d15, d7, d8, #3
154 vext.8 d31, d10, d11, #3
155 vext.8 d6, d13, d14, #3
157 vmull.u8 q4, d28, d3 ;(src_ptr[1] * vp8_filter[3])
158 vmull.u8 q5, d29, d3
159 vmull.u8 q6, d30, d3
161 vqadd.s16 q8, q4 ;sum of all (src_data*filter_parameters)
162 vqadd.s16 q10, q5
163 vqadd.s16 q12, q6
165 vmull.u8 q6, d15, d3 ;(src_ptr[1] * vp8_filter[3])
166 vmull.u8 q7, d31, d3
167 vmull.u8 q3, d6, d3
169 subs r2, r2, #1
171 vqadd.s16 q9, q6
172 vqadd.s16 q11, q7
173 vqadd.s16 q13, q3
175 vqrshrun.s16 d6, q8, #7 ;shift/round/saturate to u8
176 vqrshrun.s16 d7, q9, #7
177 vqrshrun.s16 d8, q10, #7
178 vqrshrun.s16 d9, q11, #7
179 vqrshrun.s16 d10, q12, #7
180 vqrshrun.s16 d11, q13, #7
182 vst1.u8 {d6, d7, d8}, [lr]! ;store result
183 vst1.u8 {d9, d10, d11}, [lr]!
185 bne filt_blk2d_fp16x16_loop_neon
187 ;Second pass: 16x16
188 ;secondpass_filter - do first 8-columns and then second 8-columns
189 add r3, r12, r3, lsl #5
190 sub lr, lr, #336
192 vld1.s32 {q5, q6}, [r3] ;load second_pass filter
193 mov r3, #2 ;loop counter
195 vabs.s32 q7, q5
196 vabs.s32 q8, q6
198 mov r2, #16
200 vdup.8 d0, d14[0] ;second_pass filter parameters (d0-d5)
201 vdup.8 d1, d14[4]
202 vdup.8 d2, d15[0]
203 vdup.8 d3, d15[4]
204 vdup.8 d4, d16[0]
205 vdup.8 d5, d16[4]
207 filt_blk2d_sp16x16_outloop_neon
208 vld1.u8 {d18}, [lr], r2 ;load src data
209 vld1.u8 {d19}, [lr], r2
210 vld1.u8 {d20}, [lr], r2
211 vld1.u8 {d21}, [lr], r2
212 mov r12, #4 ;loop counter
213 vld1.u8 {d22}, [lr], r2
215 secondpass_inner_loop_neon
216 vld1.u8 {d23}, [lr], r2 ;load src data
217 vld1.u8 {d24}, [lr], r2
218 vld1.u8 {d25}, [lr], r2
219 vld1.u8 {d26}, [lr], r2
221 vmull.u8 q3, d18, d0 ;(src_ptr[-2] * vp8_filter[0])
222 vmull.u8 q4, d19, d0
223 vmull.u8 q5, d20, d0
224 vmull.u8 q6, d21, d0
226 vmlsl.u8 q3, d19, d1 ;-(src_ptr[-1] * vp8_filter[1])
227 vmlsl.u8 q4, d20, d1
228 vmlsl.u8 q5, d21, d1
229 vmlsl.u8 q6, d22, d1
231 vmlsl.u8 q3, d22, d4 ;-(src_ptr[2] * vp8_filter[4])
232 vmlsl.u8 q4, d23, d4
233 vmlsl.u8 q5, d24, d4
234 vmlsl.u8 q6, d25, d4
236 vmlal.u8 q3, d20, d2 ;(src_ptr[0] * vp8_filter[2])
237 vmlal.u8 q4, d21, d2
238 vmlal.u8 q5, d22, d2
239 vmlal.u8 q6, d23, d2
241 vmlal.u8 q3, d23, d5 ;(src_ptr[3] * vp8_filter[5])
242 vmlal.u8 q4, d24, d5
243 vmlal.u8 q5, d25, d5
244 vmlal.u8 q6, d26, d5
246 vmull.u8 q7, d21, d3 ;(src_ptr[1] * vp8_filter[3])
247 vmull.u8 q8, d22, d3
248 vmull.u8 q9, d23, d3
249 vmull.u8 q10, d24, d3
251 subs r12, r12, #1
253 vqadd.s16 q7, q3 ;sum of all (src_data*filter_parameters)
254 vqadd.s16 q8, q4
255 vqadd.s16 q9, q5
256 vqadd.s16 q10, q6
258 vqrshrun.s16 d6, q7, #7 ;shift/round/saturate to u8
259 vqrshrun.s16 d7, q8, #7
260 vqrshrun.s16 d8, q9, #7
261 vqrshrun.s16 d9, q10, #7
263 vst1.u8 {d6}, [r4], r5 ;store result
264 vmov q9, q11
265 vst1.u8 {d7}, [r4], r5
266 vmov q10, q12
267 vst1.u8 {d8}, [r4], r5
268 vmov d22, d26
269 vst1.u8 {d9}, [r4], r5
271 bne secondpass_inner_loop_neon
273 subs r3, r3, #1
274 sub lr, lr, #336
275 add lr, lr, #8
277 sub r4, r4, r5, lsl #4
278 add r4, r4, #8
280 bne filt_blk2d_sp16x16_outloop_neon
282 add sp, sp, #336
283 pop {r4-r5,pc}
285 ;--------------------
286 firstpass_filter16x16_only
287 vabs.s32 q12, q14
288 vabs.s32 q13, q15
290 mov r2, #8 ;loop counter
291 sub r0, r0, #2 ;move srcptr back to (column-2)
293 vdup.8 d0, d24[0] ;first_pass filter (d0-d5)
294 vdup.8 d1, d24[4]
295 vdup.8 d2, d25[0]
296 vdup.8 d3, d25[4]
297 vdup.8 d4, d26[0]
298 vdup.8 d5, d26[4]
300 ;First Pass: output_height lines x output_width columns (16x16)
301 filt_blk2d_fpo16x16_loop_neon
302 vld1.u8 {d6, d7, d8}, [r0], r1 ;load src data
303 vld1.u8 {d9, d10, d11}, [r0], r1
305 pld [r0]
306 pld [r0, r1]
308 vmull.u8 q6, d6, d0 ;(src_ptr[-2] * vp8_filter[0])
309 vmull.u8 q7, d7, d0
310 vmull.u8 q8, d9, d0
311 vmull.u8 q9, d10, d0
313 vext.8 d20, d6, d7, #1 ;construct src_ptr[-1]
314 vext.8 d21, d9, d10, #1
315 vext.8 d22, d7, d8, #1
316 vext.8 d23, d10, d11, #1
317 vext.8 d24, d6, d7, #4 ;construct src_ptr[2]
318 vext.8 d25, d9, d10, #4
319 vext.8 d26, d7, d8, #4
320 vext.8 d27, d10, d11, #4
321 vext.8 d28, d6, d7, #5 ;construct src_ptr[3]
322 vext.8 d29, d9, d10, #5
324 vmlsl.u8 q6, d20, d1 ;-(src_ptr[-1] * vp8_filter[1])
325 vmlsl.u8 q8, d21, d1
326 vmlsl.u8 q7, d22, d1 ;-(src_ptr[-1] * vp8_filter[1])
327 vmlsl.u8 q9, d23, d1
328 vmlsl.u8 q6, d24, d4 ;-(src_ptr[2] * vp8_filter[4])
329 vmlsl.u8 q8, d25, d4
330 vmlsl.u8 q7, d26, d4 ;-(src_ptr[2] * vp8_filter[4])
331 vmlsl.u8 q9, d27, d4
332 vmlal.u8 q6, d28, d5 ;(src_ptr[3] * vp8_filter[5])
333 vmlal.u8 q8, d29, d5
335 vext.8 d20, d7, d8, #5
336 vext.8 d21, d10, d11, #5
337 vext.8 d22, d6, d7, #2 ;construct src_ptr[0]
338 vext.8 d23, d9, d10, #2
339 vext.8 d24, d7, d8, #2
340 vext.8 d25, d10, d11, #2
342 vext.8 d26, d6, d7, #3 ;construct src_ptr[1]
343 vext.8 d27, d9, d10, #3
344 vext.8 d28, d7, d8, #3
345 vext.8 d29, d10, d11, #3
347 vmlal.u8 q7, d20, d5 ;(src_ptr[3] * vp8_filter[5])
348 vmlal.u8 q9, d21, d5
349 vmlal.u8 q6, d22, d2 ;(src_ptr[0] * vp8_filter[2])
350 vmlal.u8 q8, d23, d2
351 vmlal.u8 q7, d24, d2 ;(src_ptr[0] * vp8_filter[2])
352 vmlal.u8 q9, d25, d2
354 vmull.u8 q10, d26, d3 ;(src_ptr[1] * vp8_filter[3])
355 vmull.u8 q11, d27, d3
356 vmull.u8 q12, d28, d3 ;(src_ptr[1] * vp8_filter[3])
357 vmull.u8 q15, d29, d3
359 vqadd.s16 q6, q10 ;sum of all (src_data*filter_parameters)
360 vqadd.s16 q8, q11
361 vqadd.s16 q7, q12
362 vqadd.s16 q9, q15
364 subs r2, r2, #1
366 vqrshrun.s16 d6, q6, #7 ;shift/round/saturate to u8
367 vqrshrun.s16 d7, q7, #7
368 vqrshrun.s16 d8, q8, #7
369 vqrshrun.s16 d9, q9, #7
371 vst1.u8 {q3}, [r4], r5 ;store result
372 vst1.u8 {q4}, [r4], r5
374 bne filt_blk2d_fpo16x16_loop_neon
376 pop {r4-r5,pc}
378 ;--------------------
379 secondpass_filter16x16_only
380 ;Second pass: 16x16
381 add r3, r12, r3, lsl #5
382 sub r0, r0, r1, lsl #1
384 vld1.s32 {q5, q6}, [r3] ;load second_pass filter
385 mov r3, #2 ;loop counter
387 vabs.s32 q7, q5
388 vabs.s32 q8, q6
390 vdup.8 d0, d14[0] ;second_pass filter parameters (d0-d5)
391 vdup.8 d1, d14[4]
392 vdup.8 d2, d15[0]
393 vdup.8 d3, d15[4]
394 vdup.8 d4, d16[0]
395 vdup.8 d5, d16[4]
397 filt_blk2d_spo16x16_outloop_neon
398 vld1.u8 {d18}, [r0], r1 ;load src data
399 vld1.u8 {d19}, [r0], r1
400 vld1.u8 {d20}, [r0], r1
401 vld1.u8 {d21}, [r0], r1
402 mov r12, #4 ;loop counter
403 vld1.u8 {d22}, [r0], r1
405 secondpass_only_inner_loop_neon
406 vld1.u8 {d23}, [r0], r1 ;load src data
407 vld1.u8 {d24}, [r0], r1
408 vld1.u8 {d25}, [r0], r1
409 vld1.u8 {d26}, [r0], r1
411 vmull.u8 q3, d18, d0 ;(src_ptr[-2] * vp8_filter[0])
412 vmull.u8 q4, d19, d0
413 vmull.u8 q5, d20, d0
414 vmull.u8 q6, d21, d0
416 vmlsl.u8 q3, d19, d1 ;-(src_ptr[-1] * vp8_filter[1])
417 vmlsl.u8 q4, d20, d1
418 vmlsl.u8 q5, d21, d1
419 vmlsl.u8 q6, d22, d1
421 vmlsl.u8 q3, d22, d4 ;-(src_ptr[2] * vp8_filter[4])
422 vmlsl.u8 q4, d23, d4
423 vmlsl.u8 q5, d24, d4
424 vmlsl.u8 q6, d25, d4
426 vmlal.u8 q3, d20, d2 ;(src_ptr[0] * vp8_filter[2])
427 vmlal.u8 q4, d21, d2
428 vmlal.u8 q5, d22, d2
429 vmlal.u8 q6, d23, d2
431 vmlal.u8 q3, d23, d5 ;(src_ptr[3] * vp8_filter[5])
432 vmlal.u8 q4, d24, d5
433 vmlal.u8 q5, d25, d5
434 vmlal.u8 q6, d26, d5
436 vmull.u8 q7, d21, d3 ;(src_ptr[1] * vp8_filter[3])
437 vmull.u8 q8, d22, d3
438 vmull.u8 q9, d23, d3
439 vmull.u8 q10, d24, d3
441 subs r12, r12, #1
443 vqadd.s16 q7, q3 ;sum of all (src_data*filter_parameters)
444 vqadd.s16 q8, q4
445 vqadd.s16 q9, q5
446 vqadd.s16 q10, q6
448 vqrshrun.s16 d6, q7, #7 ;shift/round/saturate to u8
449 vqrshrun.s16 d7, q8, #7
450 vqrshrun.s16 d8, q9, #7
451 vqrshrun.s16 d9, q10, #7
453 vst1.u8 {d6}, [r4], r5 ;store result
454 vmov q9, q11
455 vst1.u8 {d7}, [r4], r5
456 vmov q10, q12
457 vst1.u8 {d8}, [r4], r5
458 vmov d22, d26
459 vst1.u8 {d9}, [r4], r5
461 bne secondpass_only_inner_loop_neon
463 subs r3, r3, #1
464 sub r0, r0, r1, lsl #4
465 sub r0, r0, r1, lsl #2
466 sub r0, r0, r1
467 add r0, r0, #8
469 sub r4, r4, r5, lsl #4
470 add r4, r4, #8
472 bne filt_blk2d_spo16x16_outloop_neon
474 pop {r4-r5,pc}
476 ENDP
478 ;-----------------
479 AREA subpelfilters16_dat, DATA, READWRITE ;read/write by default
480 ;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
481 ;One word each is reserved. Label filter_coeff can be used to access the data.
482 ;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
483 _filter16_coeff_
484 DCD filter16_coeff
485 filter16_coeff
486 DCD 0, 0, 128, 0, 0, 0, 0, 0
487 DCD 0, -6, 123, 12, -1, 0, 0, 0
488 DCD 2, -11, 108, 36, -8, 1, 0, 0
489 DCD 0, -9, 93, 50, -6, 0, 0, 0
490 DCD 3, -16, 77, 77, -16, 3, 0, 0
491 DCD 0, -6, 50, 93, -9, 0, 0, 0
492 DCD 1, -8, 36, 108, -11, 2, 0, 0
493 DCD 0, -1, 12, 123, -6, 0, 0, 0