1;
2;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3;
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.
9;
10
11
12    EXPORT  |vp8_sixtap_predict8x8_neon|
13    ARM
14    REQUIRE8
15    PRESERVE8
16
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; stack(r4) unsigned char *dst_ptr,
23; stack(r5) int  dst_pitch
24
25|vp8_sixtap_predict8x8_neon| PROC
26    push            {r4-r5, lr}
27
28    adrl            r12, filter8_coeff
29
30    ldr             r4, [sp, #12]           ;load parameters from stack
31    ldr             r5, [sp, #16]           ;load parameters from stack
32
33    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
34    beq             secondpass_filter8x8_only
35
36    add             r2, r12, r2, lsl #5     ;calculate filter location
37
38    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
39
40    vld1.s32        {q14, q15}, [r2]        ;load first_pass filter
41
42    beq             firstpass_filter8x8_only
43
44    sub             sp, sp, #64             ;reserve space on stack for temporary storage
45    mov             lr, sp
46
47    vabs.s32        q12, q14
48    vabs.s32        q13, q15
49
50    mov             r2, #2                  ;loop counter
51    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
52    sub             r0, r0, r1, lsl #1
53
54    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
55    vdup.8          d1, d24[4]
56    vdup.8          d2, d25[0]
57
58;First pass: output_height lines x output_width columns (13x8)
59    vld1.u8         {q3}, [r0], r1          ;load src data
60    vdup.8          d3, d25[4]
61    vld1.u8         {q4}, [r0], r1
62    vdup.8          d4, d26[0]
63    vld1.u8         {q5}, [r0], r1
64    vdup.8          d5, d26[4]
65    vld1.u8         {q6}, [r0], r1
66
67filt_blk2d_fp8x8_loop_neon
68    pld             [r0]
69    pld             [r0, r1]
70    pld             [r0, r1, lsl #1]
71
72    vmull.u8        q7, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
73    vmull.u8        q8, d8, d0
74    vmull.u8        q9, d10, d0
75    vmull.u8        q10, d12, d0
76
77    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
78    vext.8          d29, d8, d9, #1
79    vext.8          d30, d10, d11, #1
80    vext.8          d31, d12, d13, #1
81
82    vmlsl.u8        q7, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
83    vmlsl.u8        q8, d29, d1
84    vmlsl.u8        q9, d30, d1
85    vmlsl.u8        q10, d31, d1
86
87    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
88    vext.8          d29, d8, d9, #4
89    vext.8          d30, d10, d11, #4
90    vext.8          d31, d12, d13, #4
91
92    vmlsl.u8        q7, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
93    vmlsl.u8        q8, d29, d4
94    vmlsl.u8        q9, d30, d4
95    vmlsl.u8        q10, d31, d4
96
97    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
98    vext.8          d29, d8, d9, #2
99    vext.8          d30, d10, d11, #2
100    vext.8          d31, d12, d13, #2
101
102    vmlal.u8        q7, d28, d2             ;(src_ptr[0] * vp8_filter[2])
103    vmlal.u8        q8, d29, d2
104    vmlal.u8        q9, d30, d2
105    vmlal.u8        q10, d31, d2
106
107    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
108    vext.8          d29, d8, d9, #5
109    vext.8          d30, d10, d11, #5
110    vext.8          d31, d12, d13, #5
111
112    vmlal.u8        q7, d28, d5             ;(src_ptr[3] * vp8_filter[5])
113    vmlal.u8        q8, d29, d5
114    vmlal.u8        q9, d30, d5
115    vmlal.u8        q10, d31, d5
116
117    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
118    vext.8          d29, d8, d9, #3
119    vext.8          d30, d10, d11, #3
120    vext.8          d31, d12, d13, #3
121
122    vmull.u8        q3, d28, d3             ;(src_ptr[1] * vp8_filter[3])
123    vmull.u8        q4, d29, d3
124    vmull.u8        q5, d30, d3
125    vmull.u8        q6, d31, d3
126
127    subs            r2, r2, #1
128
129    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
130    vqadd.s16       q8, q4
131    vqadd.s16       q9, q5
132    vqadd.s16       q10, q6
133
134    vld1.u8         {q3}, [r0], r1          ;load src data
135
136    vqrshrun.s16    d22, q7, #7             ;shift/round/saturate to u8
137    vqrshrun.s16    d23, q8, #7
138    vqrshrun.s16    d24, q9, #7
139    vqrshrun.s16    d25, q10, #7
140
141    vst1.u8         {d22}, [lr]!            ;store result
142    vld1.u8         {q4}, [r0], r1
143    vst1.u8         {d23}, [lr]!
144    vld1.u8         {q5}, [r0], r1
145    vst1.u8         {d24}, [lr]!
146    vld1.u8         {q6}, [r0], r1
147    vst1.u8         {d25}, [lr]!
148
149    bne             filt_blk2d_fp8x8_loop_neon
150
151    ;first_pass filtering on the rest 5-line data
152    ;vld1.u8            {q3}, [r0], r1          ;load src data
153    ;vld1.u8            {q4}, [r0], r1
154    ;vld1.u8            {q5}, [r0], r1
155    ;vld1.u8            {q6}, [r0], r1
156    vld1.u8         {q7}, [r0], r1
157
158    vmull.u8        q8, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
159    vmull.u8        q9, d8, d0
160    vmull.u8        q10, d10, d0
161    vmull.u8        q11, d12, d0
162    vmull.u8        q12, d14, d0
163
164    vext.8          d27, d6, d7, #1         ;construct src_ptr[-1]
165    vext.8          d28, d8, d9, #1
166    vext.8          d29, d10, d11, #1
167    vext.8          d30, d12, d13, #1
168    vext.8          d31, d14, d15, #1
169
170    vmlsl.u8        q8, d27, d1             ;-(src_ptr[-1] * vp8_filter[1])
171    vmlsl.u8        q9, d28, d1
172    vmlsl.u8        q10, d29, d1
173    vmlsl.u8        q11, d30, d1
174    vmlsl.u8        q12, d31, d1
175
176    vext.8          d27, d6, d7, #4         ;construct src_ptr[2]
177    vext.8          d28, d8, d9, #4
178    vext.8          d29, d10, d11, #4
179    vext.8          d30, d12, d13, #4
180    vext.8          d31, d14, d15, #4
181
182    vmlsl.u8        q8, d27, d4             ;-(src_ptr[2] * vp8_filter[4])
183    vmlsl.u8        q9, d28, d4
184    vmlsl.u8        q10, d29, d4
185    vmlsl.u8        q11, d30, d4
186    vmlsl.u8        q12, d31, d4
187
188    vext.8          d27, d6, d7, #2         ;construct src_ptr[0]
189    vext.8          d28, d8, d9, #2
190    vext.8          d29, d10, d11, #2
191    vext.8          d30, d12, d13, #2
192    vext.8          d31, d14, d15, #2
193
194    vmlal.u8        q8, d27, d2             ;(src_ptr[0] * vp8_filter[2])
195    vmlal.u8        q9, d28, d2
196    vmlal.u8        q10, d29, d2
197    vmlal.u8        q11, d30, d2
198    vmlal.u8        q12, d31, d2
199
200    vext.8          d27, d6, d7, #5         ;construct src_ptr[3]
201    vext.8          d28, d8, d9, #5
202    vext.8          d29, d10, d11, #5
203    vext.8          d30, d12, d13, #5
204    vext.8          d31, d14, d15, #5
205
206    vmlal.u8        q8, d27, d5             ;(src_ptr[3] * vp8_filter[5])
207    vmlal.u8        q9, d28, d5
208    vmlal.u8        q10, d29, d5
209    vmlal.u8        q11, d30, d5
210    vmlal.u8        q12, d31, d5
211
212    vext.8          d27, d6, d7, #3         ;construct src_ptr[1]
213    vext.8          d28, d8, d9, #3
214    vext.8          d29, d10, d11, #3
215    vext.8          d30, d12, d13, #3
216    vext.8          d31, d14, d15, #3
217
218    vmull.u8        q3, d27, d3             ;(src_ptr[1] * vp8_filter[3])
219    vmull.u8        q4, d28, d3
220    vmull.u8        q5, d29, d3
221    vmull.u8        q6, d30, d3
222    vmull.u8        q7, d31, d3
223
224    vqadd.s16       q8, q3                  ;sum of all (src_data*filter_parameters)
225    vqadd.s16       q9, q4
226    vqadd.s16       q10, q5
227    vqadd.s16       q11, q6
228    vqadd.s16       q12, q7
229
230    add             r3, r12, r3, lsl #5
231
232    vqrshrun.s16    d26, q8, #7             ;shift/round/saturate to u8
233    sub             lr, lr, #64
234    vqrshrun.s16    d27, q9, #7
235    vld1.u8         {q9}, [lr]!             ;load intermediate data from stack
236    vqrshrun.s16    d28, q10, #7
237    vld1.u8         {q10}, [lr]!
238
239    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
240
241    vqrshrun.s16    d29, q11, #7
242    vld1.u8         {q11}, [lr]!
243
244    vabs.s32        q7, q5
245    vabs.s32        q8, q6
246
247    vqrshrun.s16    d30, q12, #7
248    vld1.u8         {q12}, [lr]!
249
250;Second pass: 8x8
251    mov             r3, #2                  ;loop counter
252
253    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
254    vdup.8          d1, d14[4]
255    vdup.8          d2, d15[0]
256    vdup.8          d3, d15[4]
257    vdup.8          d4, d16[0]
258    vdup.8          d5, d16[4]
259
260filt_blk2d_sp8x8_loop_neon
261    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
262    vmull.u8        q4, d19, d0
263    vmull.u8        q5, d20, d0
264    vmull.u8        q6, d21, d0
265
266    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
267    vmlsl.u8        q4, d20, d1
268    vmlsl.u8        q5, d21, d1
269    vmlsl.u8        q6, d22, d1
270
271    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
272    vmlsl.u8        q4, d23, d4
273    vmlsl.u8        q5, d24, d4
274    vmlsl.u8        q6, d25, d4
275
276    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
277    vmlal.u8        q4, d21, d2
278    vmlal.u8        q5, d22, d2
279    vmlal.u8        q6, d23, d2
280
281    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
282    vmlal.u8        q4, d24, d5
283    vmlal.u8        q5, d25, d5
284    vmlal.u8        q6, d26, d5
285
286    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
287    vmull.u8        q8, d22, d3
288    vmull.u8        q9, d23, d3
289    vmull.u8        q10, d24, d3
290
291    subs            r3, r3, #1
292
293    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
294    vqadd.s16       q8, q4
295    vqadd.s16       q9, q5
296    vqadd.s16       q10, q6
297
298    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
299    vqrshrun.s16    d7, q8, #7
300    vqrshrun.s16    d8, q9, #7
301    vqrshrun.s16    d9, q10, #7
302
303    vmov            q9, q11
304    vst1.u8         {d6}, [r4], r5          ;store result
305    vmov            q10, q12
306    vst1.u8         {d7}, [r4], r5
307    vmov            q11, q13
308    vst1.u8         {d8}, [r4], r5
309    vmov            q12, q14
310    vst1.u8         {d9}, [r4], r5
311    vmov            d26, d30
312
313    bne filt_blk2d_sp8x8_loop_neon
314
315    add             sp, sp, #64
316    pop             {r4-r5,pc}
317
318;---------------------
319firstpass_filter8x8_only
320    ;add                r2, r12, r2, lsl #5     ;calculate filter location
321    ;vld1.s32       {q14, q15}, [r2]        ;load first_pass filter
322    vabs.s32        q12, q14
323    vabs.s32        q13, q15
324
325    mov             r2, #2                  ;loop counter
326    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
327
328    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
329    vdup.8          d1, d24[4]
330    vdup.8          d2, d25[0]
331    vdup.8          d3, d25[4]
332    vdup.8          d4, d26[0]
333    vdup.8          d5, d26[4]
334
335;First pass: output_height lines x output_width columns (8x8)
336filt_blk2d_fpo8x8_loop_neon
337    vld1.u8         {q3}, [r0], r1          ;load src data
338    vld1.u8         {q4}, [r0], r1
339    vld1.u8         {q5}, [r0], r1
340    vld1.u8         {q6}, [r0], r1
341
342    pld             [r0]
343    pld             [r0, r1]
344    pld             [r0, r1, lsl #1]
345
346    vmull.u8        q7, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
347    vmull.u8        q8, d8, d0
348    vmull.u8        q9, d10, d0
349    vmull.u8        q10, d12, d0
350
351    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
352    vext.8          d29, d8, d9, #1
353    vext.8          d30, d10, d11, #1
354    vext.8          d31, d12, d13, #1
355
356    vmlsl.u8        q7, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
357    vmlsl.u8        q8, d29, d1
358    vmlsl.u8        q9, d30, d1
359    vmlsl.u8        q10, d31, d1
360
361    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
362    vext.8          d29, d8, d9, #4
363    vext.8          d30, d10, d11, #4
364    vext.8          d31, d12, d13, #4
365
366    vmlsl.u8        q7, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
367    vmlsl.u8        q8, d29, d4
368    vmlsl.u8        q9, d30, d4
369    vmlsl.u8        q10, d31, d4
370
371    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
372    vext.8          d29, d8, d9, #2
373    vext.8          d30, d10, d11, #2
374    vext.8          d31, d12, d13, #2
375
376    vmlal.u8        q7, d28, d2             ;(src_ptr[0] * vp8_filter[2])
377    vmlal.u8        q8, d29, d2
378    vmlal.u8        q9, d30, d2
379    vmlal.u8        q10, d31, d2
380
381    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
382    vext.8          d29, d8, d9, #5
383    vext.8          d30, d10, d11, #5
384    vext.8          d31, d12, d13, #5
385
386    vmlal.u8        q7, d28, d5             ;(src_ptr[3] * vp8_filter[5])
387    vmlal.u8        q8, d29, d5
388    vmlal.u8        q9, d30, d5
389    vmlal.u8        q10, d31, d5
390
391    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
392    vext.8          d29, d8, d9, #3
393    vext.8          d30, d10, d11, #3
394    vext.8          d31, d12, d13, #3
395
396    vmull.u8        q3, d28, d3             ;(src_ptr[1] * vp8_filter[3])
397    vmull.u8        q4, d29, d3
398    vmull.u8        q5, d30, d3
399    vmull.u8        q6, d31, d3
400 ;
401    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
402    vqadd.s16       q8, q4
403    vqadd.s16       q9, q5
404    vqadd.s16       q10, q6
405
406    subs            r2, r2, #1
407
408    vqrshrun.s16    d22, q7, #7             ;shift/round/saturate to u8
409    vqrshrun.s16    d23, q8, #7
410    vqrshrun.s16    d24, q9, #7
411    vqrshrun.s16    d25, q10, #7
412
413    vst1.u8         {d22}, [r4], r5         ;store result
414    vst1.u8         {d23}, [r4], r5
415    vst1.u8         {d24}, [r4], r5
416    vst1.u8         {d25}, [r4], r5
417
418    bne             filt_blk2d_fpo8x8_loop_neon
419
420    pop             {r4-r5,pc}
421
422;---------------------
423secondpass_filter8x8_only
424    sub             r0, r0, r1, lsl #1
425    add             r3, r12, r3, lsl #5
426
427    vld1.u8         {d18}, [r0], r1         ;load src data
428    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
429    vld1.u8         {d19}, [r0], r1
430    vabs.s32        q7, q5
431    vld1.u8         {d20}, [r0], r1
432    vabs.s32        q8, q6
433    vld1.u8         {d21}, [r0], r1
434    mov             r3, #2                  ;loop counter
435    vld1.u8         {d22}, [r0], r1
436    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
437    vld1.u8         {d23}, [r0], r1
438    vdup.8          d1, d14[4]
439    vld1.u8         {d24}, [r0], r1
440    vdup.8          d2, d15[0]
441    vld1.u8         {d25}, [r0], r1
442    vdup.8          d3, d15[4]
443    vld1.u8         {d26}, [r0], r1
444    vdup.8          d4, d16[0]
445    vld1.u8         {d27}, [r0], r1
446    vdup.8          d5, d16[4]
447    vld1.u8         {d28}, [r0], r1
448    vld1.u8         {d29}, [r0], r1
449    vld1.u8         {d30}, [r0], r1
450
451;Second pass: 8x8
452filt_blk2d_spo8x8_loop_neon
453    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
454    vmull.u8        q4, d19, d0
455    vmull.u8        q5, d20, d0
456    vmull.u8        q6, d21, d0
457
458    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
459    vmlsl.u8        q4, d20, d1
460    vmlsl.u8        q5, d21, d1
461    vmlsl.u8        q6, d22, d1
462
463    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
464    vmlsl.u8        q4, d23, d4
465    vmlsl.u8        q5, d24, d4
466    vmlsl.u8        q6, d25, d4
467
468    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
469    vmlal.u8        q4, d21, d2
470    vmlal.u8        q5, d22, d2
471    vmlal.u8        q6, d23, d2
472
473    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
474    vmlal.u8        q4, d24, d5
475    vmlal.u8        q5, d25, d5
476    vmlal.u8        q6, d26, d5
477
478    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
479    vmull.u8        q8, d22, d3
480    vmull.u8        q9, d23, d3
481    vmull.u8        q10, d24, d3
482
483    subs            r3, r3, #1
484
485    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
486    vqadd.s16       q8, q4
487    vqadd.s16       q9, q5
488    vqadd.s16       q10, q6
489
490    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
491    vqrshrun.s16    d7, q8, #7
492    vqrshrun.s16    d8, q9, #7
493    vqrshrun.s16    d9, q10, #7
494
495    vmov            q9, q11
496    vst1.u8         {d6}, [r4], r5          ;store result
497    vmov            q10, q12
498    vst1.u8         {d7}, [r4], r5
499    vmov            q11, q13
500    vst1.u8         {d8}, [r4], r5
501    vmov            q12, q14
502    vst1.u8         {d9}, [r4], r5
503    vmov            d26, d30
504
505    bne filt_blk2d_spo8x8_loop_neon
506
507    pop             {r4-r5,pc}
508
509    ENDP
510
511;-----------------
512
513filter8_coeff
514    DCD     0,  0,  128,    0,   0,  0,   0,  0
515    DCD     0, -6,  123,   12,  -1,  0,   0,  0
516    DCD     2, -11, 108,   36,  -8,  1,   0,  0
517    DCD     0, -9,   93,   50,  -6,  0,   0,  0
518    DCD     3, -16,  77,   77, -16,  3,   0,  0
519    DCD     0, -6,   50,   93,  -9,  0,   0,  0
520    DCD     1, -8,   36,  108, -11,  2,   0,  0
521    DCD     0, -1,   12,  123,  -6,   0,  0,  0
522
523    END
524