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