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_predict4x4_neon|
13    ARM
14    REQUIRE8
15    PRESERVE8
16
17    AREA ||.text||, CODE, READONLY, ALIGN=2
18
19filter4_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(lr) int  dst_pitch
35
36|vp8_sixtap_predict4x4_neon| PROC
37    push            {r4, lr}
38
39    adr             r12, filter4_coeff
40    ldr             r4, [sp, #8]            ;load parameters from stack
41    ldr             lr, [sp, #12]           ;load parameters from stack
42
43    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
44    beq             secondpass_filter4x4_only
45
46    add             r2, r12, r2, lsl #5     ;calculate filter location
47
48    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
49    vld1.s32        {q14, q15}, [r2]        ;load first_pass filter
50
51    beq             firstpass_filter4x4_only
52
53    vabs.s32        q12, q14                ;get abs(filer_parameters)
54    vabs.s32        q13, q15
55
56    sub             r0, r0, #2              ;go back 2 columns of src data
57    sub             r0, r0, r1, lsl #1      ;go back 2 lines of src data
58
59;First pass: output_height lines x output_width columns (9x4)
60    vld1.u8         {q3}, [r0], r1          ;load first 4-line src data
61    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
62    vld1.u8         {q4}, [r0], r1
63    vdup.8          d1, d24[4]
64    vld1.u8         {q5}, [r0], r1
65    vdup.8          d2, d25[0]
66    vld1.u8         {q6}, [r0], r1
67    vdup.8          d3, d25[4]
68    vdup.8          d4, d26[0]
69    vdup.8          d5, d26[4]
70
71    pld             [r0]
72    pld             [r0, r1]
73    pld             [r0, r1, lsl #1]
74
75    vext.8          d18, d6, d7, #5         ;construct src_ptr[3]
76    vext.8          d19, d8, d9, #5
77    vext.8          d20, d10, d11, #5
78    vext.8          d21, d12, d13, #5
79
80    vswp            d7, d8                  ;discard 2nd half data after src_ptr[3] is done
81    vswp            d11, d12
82
83    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[3])
84    vzip.32         d20, d21
85    vmull.u8        q7, d18, d5             ;(src_ptr[3] * vp8_filter[5])
86    vmull.u8        q8, d20, d5
87
88    vmov            q4, q3                  ;keep original src data in q4 q6
89    vmov            q6, q5
90
91    vzip.32         d6, d7                  ;construct src_ptr[-2], and put 2-line data together
92    vzip.32         d10, d11
93    vshr.u64        q9, q4, #8              ;construct src_ptr[-1]
94    vshr.u64        q10, q6, #8
95    vmlal.u8        q7, d6, d0              ;+(src_ptr[-2] * vp8_filter[0])
96    vmlal.u8        q8, d10, d0
97
98    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[-1])
99    vzip.32         d20, d21
100    vshr.u64        q3, q4, #32             ;construct src_ptr[2]
101    vshr.u64        q5, q6, #32
102    vmlsl.u8        q7, d18, d1             ;-(src_ptr[-1] * vp8_filter[1])
103    vmlsl.u8        q8, d20, d1
104
105    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[2])
106    vzip.32         d10, d11
107    vshr.u64        q9, q4, #16             ;construct src_ptr[0]
108    vshr.u64        q10, q6, #16
109    vmlsl.u8        q7, d6, d4              ;-(src_ptr[2] * vp8_filter[4])
110    vmlsl.u8        q8, d10, d4
111
112    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[0])
113    vzip.32         d20, d21
114    vshr.u64        q3, q4, #24             ;construct src_ptr[1]
115    vshr.u64        q5, q6, #24
116    vmlal.u8        q7, d18, d2             ;(src_ptr[0] * vp8_filter[2])
117    vmlal.u8        q8, d20, d2
118
119    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[1])
120    vzip.32         d10, d11
121    vmull.u8        q9, d6, d3              ;(src_ptr[1] * vp8_filter[3])
122    vmull.u8        q10, d10, d3
123
124    vld1.u8         {q3}, [r0], r1          ;load rest 5-line src data
125    vld1.u8         {q4}, [r0], r1
126
127    vqadd.s16       q7, q9                  ;sum of all (src_data*filter_parameters)
128    vqadd.s16       q8, q10
129
130    vld1.u8         {q5}, [r0], r1
131    vld1.u8         {q6}, [r0], r1
132
133    vqrshrun.s16    d27, q7, #7             ;shift/round/saturate to u8
134    vqrshrun.s16    d28, q8, #7
135
136    ;First Pass on rest 5-line data
137    vld1.u8         {q11}, [r0], r1
138
139    vext.8          d18, d6, d7, #5         ;construct src_ptr[3]
140    vext.8          d19, d8, d9, #5
141    vext.8          d20, d10, d11, #5
142    vext.8          d21, d12, d13, #5
143
144    vswp            d7, d8                  ;discard 2nd half data after src_ptr[3] is done
145    vswp            d11, d12
146
147    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[3])
148    vzip.32         d20, d21
149    vext.8          d31, d22, d23, #5       ;construct src_ptr[3]
150    vmull.u8        q7, d18, d5             ;(src_ptr[3] * vp8_filter[5])
151    vmull.u8        q8, d20, d5
152    vmull.u8        q12, d31, d5            ;(src_ptr[3] * vp8_filter[5])
153
154    vmov            q4, q3                  ;keep original src data in q4 q6
155    vmov            q6, q5
156
157    vzip.32         d6, d7                  ;construct src_ptr[-2], and put 2-line data together
158    vzip.32         d10, d11
159    vshr.u64        q9, q4, #8              ;construct src_ptr[-1]
160    vshr.u64        q10, q6, #8
161
162    vmlal.u8        q7, d6, d0              ;+(src_ptr[-2] * vp8_filter[0])
163    vmlal.u8        q8, d10, d0
164    vmlal.u8        q12, d22, d0            ;(src_ptr[-2] * vp8_filter[0])
165
166    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[-1])
167    vzip.32         d20, d21
168    vshr.u64        q3, q4, #32             ;construct src_ptr[2]
169    vshr.u64        q5, q6, #32
170    vext.8          d31, d22, d23, #1       ;construct src_ptr[-1]
171
172    vmlsl.u8        q7, d18, d1             ;-(src_ptr[-1] * vp8_filter[1])
173    vmlsl.u8        q8, d20, d1
174    vmlsl.u8        q12, d31, d1            ;-(src_ptr[-1] * vp8_filter[1])
175
176    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[2])
177    vzip.32         d10, d11
178    vshr.u64        q9, q4, #16             ;construct src_ptr[0]
179    vshr.u64        q10, q6, #16
180    vext.8          d31, d22, d23, #4       ;construct src_ptr[2]
181
182    vmlsl.u8        q7, d6, d4              ;-(src_ptr[2] * vp8_filter[4])
183    vmlsl.u8        q8, d10, d4
184    vmlsl.u8        q12, d31, d4            ;-(src_ptr[2] * vp8_filter[4])
185
186    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[0])
187    vzip.32         d20, d21
188    vshr.u64        q3, q4, #24             ;construct src_ptr[1]
189    vshr.u64        q5, q6, #24
190    vext.8          d31, d22, d23, #2       ;construct src_ptr[0]
191
192    vmlal.u8        q7, d18, d2             ;(src_ptr[0] * vp8_filter[2])
193    vmlal.u8        q8, d20, d2
194    vmlal.u8        q12, d31, d2            ;(src_ptr[0] * vp8_filter[2])
195
196    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[1])
197    vzip.32         d10, d11
198    vext.8          d31, d22, d23, #3       ;construct src_ptr[1]
199    vmull.u8        q9, d6, d3              ;(src_ptr[1] * vp8_filter[3])
200    vmull.u8        q10, d10, d3
201    vmull.u8        q11, d31, d3            ;(src_ptr[1] * vp8_filter[3])
202
203    add             r3, r12, r3, lsl #5
204
205    vqadd.s16       q7, q9                  ;sum of all (src_data*filter_parameters)
206    vqadd.s16       q8, q10
207    vqadd.s16       q12, q11
208
209    vext.8          d23, d27, d28, #4
210    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
211
212    vqrshrun.s16    d29, q7, #7             ;shift/round/saturate to u8
213    vqrshrun.s16    d30, q8, #7
214    vqrshrun.s16    d31, q12, #7
215
216;Second pass: 4x4
217    vabs.s32        q7, q5
218    vabs.s32        q8, q6
219
220    vext.8          d24, d28, d29, #4
221    vext.8          d25, d29, d30, #4
222    vext.8          d26, d30, d31, #4
223
224    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
225    vdup.8          d1, d14[4]
226    vdup.8          d2, d15[0]
227    vdup.8          d3, d15[4]
228    vdup.8          d4, d16[0]
229    vdup.8          d5, d16[4]
230
231    vmull.u8        q3, d27, d0             ;(src_ptr[-2] * vp8_filter[0])
232    vmull.u8        q4, d28, d0
233
234    vmull.u8        q5, d25, d5             ;(src_ptr[3] * vp8_filter[5])
235    vmull.u8        q6, d26, d5
236
237    vmlsl.u8        q3, d29, d4             ;-(src_ptr[2] * vp8_filter[4])
238    vmlsl.u8        q4, d30, d4
239
240    vmlsl.u8        q5, d23, d1             ;-(src_ptr[-1] * vp8_filter[1])
241    vmlsl.u8        q6, d24, d1
242
243    vmlal.u8        q3, d28, d2             ;(src_ptr[0] * vp8_filter[2])
244    vmlal.u8        q4, d29, d2
245
246    vmlal.u8        q5, d24, d3             ;(src_ptr[1] * vp8_filter[3])
247    vmlal.u8        q6, d25, d3
248
249    add             r0, r4, lr
250    add             r1, r0, lr
251    add             r2, r1, lr
252
253    vqadd.s16       q5, q3                  ;sum of all (src_data*filter_parameters)
254    vqadd.s16       q6, q4
255
256    vqrshrun.s16    d3, q5, #7              ;shift/round/saturate to u8
257    vqrshrun.s16    d4, q6, #7
258
259    vst1.32         {d3[0]}, [r4]           ;store result
260    vst1.32         {d3[1]}, [r0]
261    vst1.32         {d4[0]}, [r1]
262    vst1.32         {d4[1]}, [r2]
263
264    pop             {r4, pc}
265
266
267;---------------------
268firstpass_filter4x4_only
269    vabs.s32        q12, q14                ;get abs(filer_parameters)
270    vabs.s32        q13, q15
271
272    sub             r0, r0, #2              ;go back 2 columns of src data
273
274;First pass: output_height lines x output_width columns (4x4)
275    vld1.u8         {q3}, [r0], r1          ;load first 4-line src data
276    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
277    vld1.u8         {q4}, [r0], r1
278    vdup.8          d1, d24[4]
279    vld1.u8         {q5}, [r0], r1
280    vdup.8          d2, d25[0]
281    vld1.u8         {q6}, [r0], r1
282
283    vdup.8          d3, d25[4]
284    vdup.8          d4, d26[0]
285    vdup.8          d5, d26[4]
286
287    vext.8          d18, d6, d7, #5         ;construct src_ptr[3]
288    vext.8          d19, d8, d9, #5
289    vext.8          d20, d10, d11, #5
290    vext.8          d21, d12, d13, #5
291
292    vswp            d7, d8                  ;discard 2nd half data after src_ptr[3] is done
293    vswp            d11, d12
294
295    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[3])
296    vzip.32         d20, d21
297    vmull.u8        q7, d18, d5             ;(src_ptr[3] * vp8_filter[5])
298    vmull.u8        q8, d20, d5
299
300    vmov            q4, q3                  ;keep original src data in q4 q6
301    vmov            q6, q5
302
303    vzip.32         d6, d7                  ;construct src_ptr[-2], and put 2-line data together
304    vzip.32         d10, d11
305    vshr.u64        q9, q4, #8              ;construct src_ptr[-1]
306    vshr.u64        q10, q6, #8
307    vmlal.u8        q7, d6, d0              ;+(src_ptr[-2] * vp8_filter[0])
308    vmlal.u8        q8, d10, d0
309
310    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[-1])
311    vzip.32         d20, d21
312    vshr.u64        q3, q4, #32             ;construct src_ptr[2]
313    vshr.u64        q5, q6, #32
314    vmlsl.u8        q7, d18, d1             ;-(src_ptr[-1] * vp8_filter[1])
315    vmlsl.u8        q8, d20, d1
316
317    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[2])
318    vzip.32         d10, d11
319    vshr.u64        q9, q4, #16             ;construct src_ptr[0]
320    vshr.u64        q10, q6, #16
321    vmlsl.u8        q7, d6, d4              ;-(src_ptr[2] * vp8_filter[4])
322    vmlsl.u8        q8, d10, d4
323
324    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[0])
325    vzip.32         d20, d21
326    vshr.u64        q3, q4, #24             ;construct src_ptr[1]
327    vshr.u64        q5, q6, #24
328    vmlal.u8        q7, d18, d2             ;(src_ptr[0] * vp8_filter[2])
329    vmlal.u8        q8, d20, d2
330
331    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[1])
332    vzip.32         d10, d11
333    vmull.u8        q9, d6, d3              ;(src_ptr[1] * vp8_filter[3])
334    vmull.u8        q10, d10, d3
335
336    add             r0, r4, lr
337    add             r1, r0, lr
338    add             r2, r1, lr
339
340    vqadd.s16       q7, q9                  ;sum of all (src_data*filter_parameters)
341    vqadd.s16       q8, q10
342
343    vqrshrun.s16    d27, q7, #7             ;shift/round/saturate to u8
344    vqrshrun.s16    d28, q8, #7
345
346    vst1.32         {d27[0]}, [r4]          ;store result
347    vst1.32         {d27[1]}, [r0]
348    vst1.32         {d28[0]}, [r1]
349    vst1.32         {d28[1]}, [r2]
350
351    pop             {r4, pc}
352
353
354;---------------------
355secondpass_filter4x4_only
356    sub             r0, r0, r1, lsl #1
357    add             r3, r12, r3, lsl #5
358
359    vld1.32         {d27[0]}, [r0], r1      ;load src data
360    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
361    vld1.32         {d27[1]}, [r0], r1
362    vabs.s32        q7, q5
363    vld1.32         {d28[0]}, [r0], r1
364    vabs.s32        q8, q6
365    vld1.32         {d28[1]}, [r0], r1
366    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
367    vld1.32         {d29[0]}, [r0], r1
368    vdup.8          d1, d14[4]
369    vld1.32         {d29[1]}, [r0], r1
370    vdup.8          d2, d15[0]
371    vld1.32         {d30[0]}, [r0], r1
372    vdup.8          d3, d15[4]
373    vld1.32         {d30[1]}, [r0], r1
374    vdup.8          d4, d16[0]
375    vld1.32         {d31[0]}, [r0], r1
376    vdup.8          d5, d16[4]
377
378    vext.8          d23, d27, d28, #4
379    vext.8          d24, d28, d29, #4
380    vext.8          d25, d29, d30, #4
381    vext.8          d26, d30, d31, #4
382
383    vmull.u8        q3, d27, d0             ;(src_ptr[-2] * vp8_filter[0])
384    vmull.u8        q4, d28, d0
385
386    vmull.u8        q5, d25, d5             ;(src_ptr[3] * vp8_filter[5])
387    vmull.u8        q6, d26, d5
388
389    vmlsl.u8        q3, d29, d4             ;-(src_ptr[2] * vp8_filter[4])
390    vmlsl.u8        q4, d30, d4
391
392    vmlsl.u8        q5, d23, d1             ;-(src_ptr[-1] * vp8_filter[1])
393    vmlsl.u8        q6, d24, d1
394
395    vmlal.u8        q3, d28, d2             ;(src_ptr[0] * vp8_filter[2])
396    vmlal.u8        q4, d29, d2
397
398    vmlal.u8        q5, d24, d3             ;(src_ptr[1] * vp8_filter[3])
399    vmlal.u8        q6, d25, d3
400
401    add             r0, r4, lr
402    add             r1, r0, lr
403    add             r2, r1, lr
404
405    vqadd.s16       q5, q3                  ;sum of all (src_data*filter_parameters)
406    vqadd.s16       q6, q4
407
408    vqrshrun.s16    d3, q5, #7              ;shift/round/saturate to u8
409    vqrshrun.s16    d4, q6, #7
410
411    vst1.32         {d3[0]}, [r4]           ;store result
412    vst1.32         {d3[1]}, [r0]
413    vst1.32         {d4[0]}, [r1]
414    vst1.32         {d4[1]}, [r2]
415
416    pop             {r4, pc}
417
418    ENDP
419
420;-----------------
421
422    END
423