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