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_bilinear_predict16x16_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; r4    unsigned char *dst_ptr,
23; stack(r5) int  dst_pitch
24
25|vp8_bilinear_predict16x16_neon| PROC
26    push            {r4-r5, lr}
27
28    adr             r12, bifilter16_coeff
29    ldr             r4, [sp, #12]           ;load parameters from stack
30    ldr             r5, [sp, #16]           ;load parameters from stack
31
32    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
33    beq             secondpass_bfilter16x16_only
34
35    add             r2, r12, r2, lsl #3     ;calculate filter location
36
37    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
38
39    vld1.s32        {d31}, [r2]             ;load first_pass filter
40
41    beq             firstpass_bfilter16x16_only
42
43    sub             sp, sp, #272            ;reserve space on stack for temporary storage
44    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
45    mov             lr, sp
46    vld1.u8         {d5, d6, d7}, [r0], r1
47
48    mov             r2, #3                  ;loop counter
49    vld1.u8         {d8, d9, d10}, [r0], r1
50
51    vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
52    vld1.u8         {d11, d12, d13}, [r0], r1
53
54    vdup.8          d1, d31[4]
55
56;First Pass: output_height lines x output_width columns (17x16)
57filt_blk2d_fp16x16_loop_neon
58    pld             [r0]
59    pld             [r0, r1]
60    pld             [r0, r1, lsl #1]
61
62    vmull.u8        q7, d2, d0              ;(src_ptr[0] * vp8_filter[0])
63    vmull.u8        q8, d3, d0
64    vmull.u8        q9, d5, d0
65    vmull.u8        q10, d6, d0
66    vmull.u8        q11, d8, d0
67    vmull.u8        q12, d9, d0
68    vmull.u8        q13, d11, d0
69    vmull.u8        q14, d12, d0
70
71    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
72    vext.8          d5, d5, d6, #1
73    vext.8          d8, d8, d9, #1
74    vext.8          d11, d11, d12, #1
75
76    vmlal.u8        q7, d2, d1              ;(src_ptr[0] * vp8_filter[1])
77    vmlal.u8        q9, d5, d1
78    vmlal.u8        q11, d8, d1
79    vmlal.u8        q13, d11, d1
80
81    vext.8          d3, d3, d4, #1
82    vext.8          d6, d6, d7, #1
83    vext.8          d9, d9, d10, #1
84    vext.8          d12, d12, d13, #1
85
86    vmlal.u8        q8, d3, d1              ;(src_ptr[0] * vp8_filter[1])
87    vmlal.u8        q10, d6, d1
88    vmlal.u8        q12, d9, d1
89    vmlal.u8        q14, d12, d1
90
91    subs            r2, r2, #1
92
93    vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
94    vqrshrn.u16    d15, q8, #7
95    vqrshrn.u16    d16, q9, #7
96    vqrshrn.u16    d17, q10, #7
97    vqrshrn.u16    d18, q11, #7
98    vqrshrn.u16    d19, q12, #7
99    vqrshrn.u16    d20, q13, #7
100
101    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
102    vqrshrn.u16    d21, q14, #7
103    vld1.u8         {d5, d6, d7}, [r0], r1
104
105    vst1.u8         {d14, d15, d16, d17}, [lr]!     ;store result
106    vld1.u8         {d8, d9, d10}, [r0], r1
107    vst1.u8         {d18, d19, d20, d21}, [lr]!
108    vld1.u8         {d11, d12, d13}, [r0], r1
109
110    bne             filt_blk2d_fp16x16_loop_neon
111
112;First-pass filtering for rest 5 lines
113    vld1.u8         {d14, d15, d16}, [r0], r1
114
115    vmull.u8        q9, d2, d0              ;(src_ptr[0] * vp8_filter[0])
116    vmull.u8        q10, d3, d0
117    vmull.u8        q11, d5, d0
118    vmull.u8        q12, d6, d0
119    vmull.u8        q13, d8, d0
120    vmull.u8        q14, d9, d0
121
122    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
123    vext.8          d5, d5, d6, #1
124    vext.8          d8, d8, d9, #1
125
126    vmlal.u8        q9, d2, d1              ;(src_ptr[0] * vp8_filter[1])
127    vmlal.u8        q11, d5, d1
128    vmlal.u8        q13, d8, d1
129
130    vext.8          d3, d3, d4, #1
131    vext.8          d6, d6, d7, #1
132    vext.8          d9, d9, d10, #1
133
134    vmlal.u8        q10, d3, d1             ;(src_ptr[0] * vp8_filter[1])
135    vmlal.u8        q12, d6, d1
136    vmlal.u8        q14, d9, d1
137
138    vmull.u8        q1, d11, d0
139    vmull.u8        q2, d12, d0
140    vmull.u8        q3, d14, d0
141    vmull.u8        q4, d15, d0
142
143    vext.8          d11, d11, d12, #1       ;construct src_ptr[1]
144    vext.8          d14, d14, d15, #1
145
146    vmlal.u8        q1, d11, d1             ;(src_ptr[0] * vp8_filter[1])
147    vmlal.u8        q3, d14, d1
148
149    vext.8          d12, d12, d13, #1
150    vext.8          d15, d15, d16, #1
151
152    vmlal.u8        q2, d12, d1             ;(src_ptr[0] * vp8_filter[1])
153    vmlal.u8        q4, d15, d1
154
155    vqrshrn.u16    d10, q9, #7              ;shift/round/saturate to u8
156    vqrshrn.u16    d11, q10, #7
157    vqrshrn.u16    d12, q11, #7
158    vqrshrn.u16    d13, q12, #7
159    vqrshrn.u16    d14, q13, #7
160    vqrshrn.u16    d15, q14, #7
161    vqrshrn.u16    d16, q1, #7
162    vqrshrn.u16    d17, q2, #7
163    vqrshrn.u16    d18, q3, #7
164    vqrshrn.u16    d19, q4, #7
165
166    vst1.u8         {d10, d11, d12, d13}, [lr]!         ;store result
167    vst1.u8         {d14, d15, d16, d17}, [lr]!
168    vst1.u8         {d18, d19}, [lr]!
169
170;Second pass: 16x16
171;secondpass_filter
172    add             r3, r12, r3, lsl #3
173    sub             lr, lr, #272
174
175    vld1.u32        {d31}, [r3]             ;load second_pass filter
176
177    vld1.u8         {d22, d23}, [lr]!       ;load src data
178
179    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
180    vdup.8          d1, d31[4]
181    mov             r12, #4                 ;loop counter
182
183filt_blk2d_sp16x16_loop_neon
184    vld1.u8         {d24, d25}, [lr]!
185    vmull.u8        q1, d22, d0             ;(src_ptr[0] * vp8_filter[0])
186    vld1.u8         {d26, d27}, [lr]!
187    vmull.u8        q2, d23, d0
188    vld1.u8         {d28, d29}, [lr]!
189    vmull.u8        q3, d24, d0
190    vld1.u8         {d30, d31}, [lr]!
191
192    vmull.u8        q4, d25, d0
193    vmull.u8        q5, d26, d0
194    vmull.u8        q6, d27, d0
195    vmull.u8        q7, d28, d0
196    vmull.u8        q8, d29, d0
197
198    vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * vp8_filter[1])
199    vmlal.u8        q2, d25, d1
200    vmlal.u8        q3, d26, d1
201    vmlal.u8        q4, d27, d1
202    vmlal.u8        q5, d28, d1
203    vmlal.u8        q6, d29, d1
204    vmlal.u8        q7, d30, d1
205    vmlal.u8        q8, d31, d1
206
207    subs            r12, r12, #1
208
209    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
210    vqrshrn.u16    d3, q2, #7
211    vqrshrn.u16    d4, q3, #7
212    vqrshrn.u16    d5, q4, #7
213    vqrshrn.u16    d6, q5, #7
214    vqrshrn.u16    d7, q6, #7
215    vqrshrn.u16    d8, q7, #7
216    vqrshrn.u16    d9, q8, #7
217
218    vst1.u8         {d2, d3}, [r4], r5      ;store result
219    vst1.u8         {d4, d5}, [r4], r5
220    vst1.u8         {d6, d7}, [r4], r5
221    vmov            q11, q15
222    vst1.u8         {d8, d9}, [r4], r5
223
224    bne             filt_blk2d_sp16x16_loop_neon
225
226    add             sp, sp, #272
227
228    pop             {r4-r5,pc}
229
230;--------------------
231firstpass_bfilter16x16_only
232    mov             r2, #4                      ;loop counter
233    vdup.8          d0, d31[0]                  ;first_pass filter (d0 d1)
234    vdup.8          d1, d31[4]
235
236;First Pass: output_height lines x output_width columns (16x16)
237filt_blk2d_fpo16x16_loop_neon
238    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
239    vld1.u8         {d5, d6, d7}, [r0], r1
240    vld1.u8         {d8, d9, d10}, [r0], r1
241    vld1.u8         {d11, d12, d13}, [r0], r1
242
243    pld             [r0]
244    pld             [r0, r1]
245    pld             [r0, r1, lsl #1]
246
247    vmull.u8        q7, d2, d0              ;(src_ptr[0] * vp8_filter[0])
248    vmull.u8        q8, d3, d0
249    vmull.u8        q9, d5, d0
250    vmull.u8        q10, d6, d0
251    vmull.u8        q11, d8, d0
252    vmull.u8        q12, d9, d0
253    vmull.u8        q13, d11, d0
254    vmull.u8        q14, d12, d0
255
256    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
257    vext.8          d5, d5, d6, #1
258    vext.8          d8, d8, d9, #1
259    vext.8          d11, d11, d12, #1
260
261    vmlal.u8        q7, d2, d1              ;(src_ptr[0] * vp8_filter[1])
262    vmlal.u8        q9, d5, d1
263    vmlal.u8        q11, d8, d1
264    vmlal.u8        q13, d11, d1
265
266    vext.8          d3, d3, d4, #1
267    vext.8          d6, d6, d7, #1
268    vext.8          d9, d9, d10, #1
269    vext.8          d12, d12, d13, #1
270
271    vmlal.u8        q8, d3, d1              ;(src_ptr[0] * vp8_filter[1])
272    vmlal.u8        q10, d6, d1
273    vmlal.u8        q12, d9, d1
274    vmlal.u8        q14, d12, d1
275
276    subs            r2, r2, #1
277
278    vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
279    vqrshrn.u16    d15, q8, #7
280    vqrshrn.u16    d16, q9, #7
281    vqrshrn.u16    d17, q10, #7
282    vqrshrn.u16    d18, q11, #7
283    vqrshrn.u16    d19, q12, #7
284    vqrshrn.u16    d20, q13, #7
285    vst1.u8         {d14, d15}, [r4], r5        ;store result
286    vqrshrn.u16    d21, q14, #7
287
288    vst1.u8         {d16, d17}, [r4], r5
289    vst1.u8         {d18, d19}, [r4], r5
290    vst1.u8         {d20, d21}, [r4], r5
291
292    bne             filt_blk2d_fpo16x16_loop_neon
293    pop             {r4-r5,pc}
294
295;---------------------
296secondpass_bfilter16x16_only
297;Second pass: 16x16
298;secondpass_filter
299    add             r3, r12, r3, lsl #3
300    mov             r12, #4                     ;loop counter
301    vld1.u32        {d31}, [r3]                 ;load second_pass filter
302    vld1.u8         {d22, d23}, [r0], r1        ;load src data
303
304    vdup.8          d0, d31[0]                  ;second_pass filter parameters (d0 d1)
305    vdup.8          d1, d31[4]
306
307filt_blk2d_spo16x16_loop_neon
308    vld1.u8         {d24, d25}, [r0], r1
309    vmull.u8        q1, d22, d0             ;(src_ptr[0] * vp8_filter[0])
310    vld1.u8         {d26, d27}, [r0], r1
311    vmull.u8        q2, d23, d0
312    vld1.u8         {d28, d29}, [r0], r1
313    vmull.u8        q3, d24, d0
314    vld1.u8         {d30, d31}, [r0], r1
315
316    vmull.u8        q4, d25, d0
317    vmull.u8        q5, d26, d0
318    vmull.u8        q6, d27, d0
319    vmull.u8        q7, d28, d0
320    vmull.u8        q8, d29, d0
321
322    vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * vp8_filter[1])
323    vmlal.u8        q2, d25, d1
324    vmlal.u8        q3, d26, d1
325    vmlal.u8        q4, d27, d1
326    vmlal.u8        q5, d28, d1
327    vmlal.u8        q6, d29, d1
328    vmlal.u8        q7, d30, d1
329    vmlal.u8        q8, d31, d1
330
331    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
332    vqrshrn.u16    d3, q2, #7
333    vqrshrn.u16    d4, q3, #7
334    vqrshrn.u16    d5, q4, #7
335    vqrshrn.u16    d6, q5, #7
336    vqrshrn.u16    d7, q6, #7
337    vqrshrn.u16    d8, q7, #7
338    vqrshrn.u16    d9, q8, #7
339
340    vst1.u8         {d2, d3}, [r4], r5      ;store result
341    subs            r12, r12, #1
342    vst1.u8         {d4, d5}, [r4], r5
343    vmov            q11, q15
344    vst1.u8         {d6, d7}, [r4], r5
345    vst1.u8         {d8, d9}, [r4], r5
346
347    bne             filt_blk2d_spo16x16_loop_neon
348    pop             {r4-r5,pc}
349
350    ENDP
351
352;-----------------
353
354bifilter16_coeff
355    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
356
357    END
358