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