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