• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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;Note: To take advantage of 8-bit mulplication instruction in NEON. First apply abs() to
26; filter coeffs to make them u8. Then, use vmlsl for negtive coeffs. After multiplication,
27; the result can be negtive. So, I treat the result as s16. But, since it is also possible
28; that the result can be a large positive number (> 2^15-1), which could be confused as a
29; negtive number. To avoid that error, apply filter coeffs in the order of 0, 1, 4 ,5 ,2,
30; which ensures that the result stays in s16 range. Finally, saturated add the result by
31; applying 3rd filter coeff. Same applys to other filter functions.
32
33|vp8_sixtap_predict16x16_neon| PROC
34    push            {r4-r5, lr}
35
36    ldr             r12, _filter16_coeff_
37    ldr             r4, [sp, #12]           ;load parameters from stack
38    ldr             r5, [sp, #16]           ;load parameters from stack
39
40    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
41    beq             secondpass_filter16x16_only
42
43    add             r2, r12, r2, lsl #5     ;calculate filter location
44
45    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
46
47    vld1.s32        {q14, q15}, [r2]        ;load first_pass filter
48
49    beq             firstpass_filter16x16_only
50
51    sub             sp, sp, #336            ;reserve space on stack for temporary storage
52    mov             lr, sp
53
54    vabs.s32        q12, q14
55    vabs.s32        q13, q15
56
57    mov             r2, #7                  ;loop counter
58    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
59    sub             r0, r0, r1, lsl #1
60
61    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
62    vdup.8          d1, d24[4]
63    vdup.8          d2, d25[0]
64    vdup.8          d3, d25[4]
65    vdup.8          d4, d26[0]
66    vdup.8          d5, d26[4]
67
68;First Pass: output_height lines x output_width columns (21x16)
69filt_blk2d_fp16x16_loop_neon
70    vld1.u8         {d6, d7, d8}, [r0], r1      ;load src data
71    vld1.u8         {d9, d10, d11}, [r0], r1
72    vld1.u8         {d12, d13, d14}, [r0], r1
73
74    pld             [r0]
75    pld             [r0, r1]
76    pld             [r0, r1, lsl #1]
77
78    vmull.u8        q8, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
79    vmull.u8        q9, d7, d0
80    vmull.u8        q10, d9, d0
81    vmull.u8        q11, d10, d0
82    vmull.u8        q12, d12, d0
83    vmull.u8        q13, d13, d0
84
85    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
86    vext.8          d29, d9, d10, #1
87    vext.8          d30, d12, d13, #1
88
89    vmlsl.u8        q8, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
90    vmlsl.u8        q10, d29, d1
91    vmlsl.u8        q12, d30, d1
92
93    vext.8          d28, d7, d8, #1
94    vext.8          d29, d10, d11, #1
95    vext.8          d30, d13, d14, #1
96
97    vmlsl.u8        q9, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
98    vmlsl.u8        q11, d29, d1
99    vmlsl.u8        q13, d30, d1
100
101    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
102    vext.8          d29, d9, d10, #4
103    vext.8          d30, d12, d13, #4
104
105    vmlsl.u8        q8, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
106    vmlsl.u8        q10, d29, d4
107    vmlsl.u8        q12, d30, d4
108
109    vext.8          d28, d7, d8, #4
110    vext.8          d29, d10, d11, #4
111    vext.8          d30, d13, d14, #4
112
113    vmlsl.u8        q9, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
114    vmlsl.u8        q11, d29, d4
115    vmlsl.u8        q13, d30, d4
116
117    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
118    vext.8          d29, d9, d10, #5
119    vext.8          d30, d12, d13, #5
120
121    vmlal.u8        q8, d28, d5             ;(src_ptr[3] * vp8_filter[5])
122    vmlal.u8        q10, d29, d5
123    vmlal.u8        q12, d30, d5
124
125    vext.8          d28, d7, d8, #5
126    vext.8          d29, d10, d11, #5
127    vext.8          d30, d13, d14, #5
128
129    vmlal.u8        q9, d28, d5             ;(src_ptr[3] * vp8_filter[5])
130    vmlal.u8        q11, d29, d5
131    vmlal.u8        q13, d30, d5
132
133    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
134    vext.8          d29, d9, d10, #2
135    vext.8          d30, d12, d13, #2
136
137    vmlal.u8        q8, d28, d2             ;(src_ptr[0] * vp8_filter[2])
138    vmlal.u8        q10, d29, d2
139    vmlal.u8        q12, d30, d2
140
141    vext.8          d28, d7, d8, #2
142    vext.8          d29, d10, d11, #2
143    vext.8          d30, d13, d14, #2
144
145    vmlal.u8        q9, d28, d2             ;(src_ptr[0] * vp8_filter[2])
146    vmlal.u8        q11, d29, d2
147    vmlal.u8        q13, d30, d2
148
149    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
150    vext.8          d29, d9, d10, #3
151    vext.8          d30, d12, d13, #3
152
153    vext.8          d15, d7, d8, #3
154    vext.8          d31, d10, d11, #3
155    vext.8          d6, d13, d14, #3
156
157    vmull.u8        q4, d28, d3             ;(src_ptr[1] * vp8_filter[3])
158    vmull.u8        q5, d29, d3
159    vmull.u8        q6, d30, d3
160
161    vqadd.s16       q8, q4                  ;sum of all (src_data*filter_parameters)
162    vqadd.s16       q10, q5
163    vqadd.s16       q12, q6
164
165    vmull.u8        q6, d15, d3             ;(src_ptr[1] * vp8_filter[3])
166    vmull.u8        q7, d31, d3
167    vmull.u8        q3, d6, d3
168
169    subs            r2, r2, #1
170
171    vqadd.s16       q9, q6
172    vqadd.s16       q11, q7
173    vqadd.s16       q13, q3
174
175    vqrshrun.s16    d6, q8, #7              ;shift/round/saturate to u8
176    vqrshrun.s16    d7, q9, #7
177    vqrshrun.s16    d8, q10, #7
178    vqrshrun.s16    d9, q11, #7
179    vqrshrun.s16    d10, q12, #7
180    vqrshrun.s16    d11, q13, #7
181
182    vst1.u8         {d6, d7, d8}, [lr]!     ;store result
183    vst1.u8         {d9, d10, d11}, [lr]!
184
185    bne             filt_blk2d_fp16x16_loop_neon
186
187;Second pass: 16x16
188;secondpass_filter - do first 8-columns and then second 8-columns
189    add             r3, r12, r3, lsl #5
190    sub             lr, lr, #336
191
192    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
193    mov             r3, #2                  ;loop counter
194
195    vabs.s32        q7, q5
196    vabs.s32        q8, q6
197
198    mov             r2, #16
199
200    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
201    vdup.8          d1, d14[4]
202    vdup.8          d2, d15[0]
203    vdup.8          d3, d15[4]
204    vdup.8          d4, d16[0]
205    vdup.8          d5, d16[4]
206
207filt_blk2d_sp16x16_outloop_neon
208    vld1.u8         {d18}, [lr], r2         ;load src data
209    vld1.u8         {d19}, [lr], r2
210    vld1.u8         {d20}, [lr], r2
211    vld1.u8         {d21}, [lr], r2
212    mov             r12, #4                 ;loop counter
213    vld1.u8         {d22}, [lr], r2
214
215secondpass_inner_loop_neon
216    vld1.u8         {d23}, [lr], r2         ;load src data
217    vld1.u8         {d24}, [lr], r2
218    vld1.u8         {d25}, [lr], r2
219    vld1.u8         {d26}, [lr], r2
220
221    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
222    vmull.u8        q4, d19, d0
223    vmull.u8        q5, d20, d0
224    vmull.u8        q6, d21, d0
225
226    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
227    vmlsl.u8        q4, d20, d1
228    vmlsl.u8        q5, d21, d1
229    vmlsl.u8        q6, d22, d1
230
231    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
232    vmlsl.u8        q4, d23, d4
233    vmlsl.u8        q5, d24, d4
234    vmlsl.u8        q6, d25, d4
235
236    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
237    vmlal.u8        q4, d21, d2
238    vmlal.u8        q5, d22, d2
239    vmlal.u8        q6, d23, d2
240
241    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
242    vmlal.u8        q4, d24, d5
243    vmlal.u8        q5, d25, d5
244    vmlal.u8        q6, d26, d5
245
246    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
247    vmull.u8        q8, d22, d3
248    vmull.u8        q9, d23, d3
249    vmull.u8        q10, d24, d3
250
251    subs            r12, r12, #1
252
253    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
254    vqadd.s16       q8, q4
255    vqadd.s16       q9, q5
256    vqadd.s16       q10, q6
257
258    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
259    vqrshrun.s16    d7, q8, #7
260    vqrshrun.s16    d8, q9, #7
261    vqrshrun.s16    d9, q10, #7
262
263    vst1.u8         {d6}, [r4], r5          ;store result
264    vmov            q9, q11
265    vst1.u8         {d7}, [r4], r5
266    vmov            q10, q12
267    vst1.u8         {d8}, [r4], r5
268    vmov            d22, d26
269    vst1.u8         {d9}, [r4], r5
270
271    bne             secondpass_inner_loop_neon
272
273    subs            r3, r3, #1
274    sub             lr, lr, #336
275    add             lr, lr, #8
276
277    sub             r4, r4, r5, lsl #4
278    add             r4, r4, #8
279
280    bne filt_blk2d_sp16x16_outloop_neon
281
282    add             sp, sp, #336
283    pop             {r4-r5,pc}
284
285;--------------------
286firstpass_filter16x16_only
287    vabs.s32        q12, q14
288    vabs.s32        q13, q15
289
290    mov             r2, #8                  ;loop counter
291    sub             r0, r0, #2              ;move srcptr back to (column-2)
292
293    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
294    vdup.8          d1, d24[4]
295    vdup.8          d2, d25[0]
296    vdup.8          d3, d25[4]
297    vdup.8          d4, d26[0]
298    vdup.8          d5, d26[4]
299
300;First Pass: output_height lines x output_width columns (16x16)
301filt_blk2d_fpo16x16_loop_neon
302    vld1.u8         {d6, d7, d8}, [r0], r1      ;load src data
303    vld1.u8         {d9, d10, d11}, [r0], r1
304
305    pld             [r0]
306    pld             [r0, r1]
307
308    vmull.u8        q6, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
309    vmull.u8        q7, d7, d0
310    vmull.u8        q8, d9, d0
311    vmull.u8        q9, d10, d0
312
313    vext.8          d20, d6, d7, #1         ;construct src_ptr[-1]
314    vext.8          d21, d9, d10, #1
315    vext.8          d22, d7, d8, #1
316    vext.8          d23, d10, d11, #1
317    vext.8          d24, d6, d7, #4         ;construct src_ptr[2]
318    vext.8          d25, d9, d10, #4
319    vext.8          d26, d7, d8, #4
320    vext.8          d27, d10, d11, #4
321    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
322    vext.8          d29, d9, d10, #5
323
324    vmlsl.u8        q6, d20, d1             ;-(src_ptr[-1] * vp8_filter[1])
325    vmlsl.u8        q8, d21, d1
326    vmlsl.u8        q7, d22, d1             ;-(src_ptr[-1] * vp8_filter[1])
327    vmlsl.u8        q9, d23, d1
328    vmlsl.u8        q6, d24, d4             ;-(src_ptr[2] * vp8_filter[4])
329    vmlsl.u8        q8, d25, d4
330    vmlsl.u8        q7, d26, d4             ;-(src_ptr[2] * vp8_filter[4])
331    vmlsl.u8        q9, d27, d4
332    vmlal.u8        q6, d28, d5             ;(src_ptr[3] * vp8_filter[5])
333    vmlal.u8        q8, d29, d5
334
335    vext.8          d20, d7, d8, #5
336    vext.8          d21, d10, d11, #5
337    vext.8          d22, d6, d7, #2         ;construct src_ptr[0]
338    vext.8          d23, d9, d10, #2
339    vext.8          d24, d7, d8, #2
340    vext.8          d25, d10, d11, #2
341
342    vext.8          d26, d6, d7, #3         ;construct src_ptr[1]
343    vext.8          d27, d9, d10, #3
344    vext.8          d28, d7, d8, #3
345    vext.8          d29, d10, d11, #3
346
347    vmlal.u8        q7, d20, d5             ;(src_ptr[3] * vp8_filter[5])
348    vmlal.u8        q9, d21, d5
349    vmlal.u8        q6, d22, d2             ;(src_ptr[0] * vp8_filter[2])
350    vmlal.u8        q8, d23, d2
351    vmlal.u8        q7, d24, d2             ;(src_ptr[0] * vp8_filter[2])
352    vmlal.u8        q9, d25, d2
353
354    vmull.u8        q10, d26, d3            ;(src_ptr[1] * vp8_filter[3])
355    vmull.u8        q11, d27, d3
356    vmull.u8        q12, d28, d3            ;(src_ptr[1] * vp8_filter[3])
357    vmull.u8        q15, d29, d3
358
359    vqadd.s16       q6, q10                 ;sum of all (src_data*filter_parameters)
360    vqadd.s16       q8, q11
361    vqadd.s16       q7, q12
362    vqadd.s16       q9, q15
363
364    subs            r2, r2, #1
365
366    vqrshrun.s16    d6, q6, #7              ;shift/round/saturate to u8
367    vqrshrun.s16    d7, q7, #7
368    vqrshrun.s16    d8, q8, #7
369    vqrshrun.s16    d9, q9, #7
370
371    vst1.u8         {q3}, [r4], r5              ;store result
372    vst1.u8         {q4}, [r4], r5
373
374    bne             filt_blk2d_fpo16x16_loop_neon
375
376    pop             {r4-r5,pc}
377
378;--------------------
379secondpass_filter16x16_only
380;Second pass: 16x16
381    add             r3, r12, r3, lsl #5
382    sub             r0, r0, r1, lsl #1
383
384    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
385    mov             r3, #2                  ;loop counter
386
387    vabs.s32        q7, q5
388    vabs.s32        q8, q6
389
390    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
391    vdup.8          d1, d14[4]
392    vdup.8          d2, d15[0]
393    vdup.8          d3, d15[4]
394    vdup.8          d4, d16[0]
395    vdup.8          d5, d16[4]
396
397filt_blk2d_spo16x16_outloop_neon
398    vld1.u8         {d18}, [r0], r1         ;load src data
399    vld1.u8         {d19}, [r0], r1
400    vld1.u8         {d20}, [r0], r1
401    vld1.u8         {d21}, [r0], r1
402    mov             r12, #4                 ;loop counter
403    vld1.u8         {d22}, [r0], r1
404
405secondpass_only_inner_loop_neon
406    vld1.u8         {d23}, [r0], r1         ;load src data
407    vld1.u8         {d24}, [r0], r1
408    vld1.u8         {d25}, [r0], r1
409    vld1.u8         {d26}, [r0], r1
410
411    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
412    vmull.u8        q4, d19, d0
413    vmull.u8        q5, d20, d0
414    vmull.u8        q6, d21, d0
415
416    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
417    vmlsl.u8        q4, d20, d1
418    vmlsl.u8        q5, d21, d1
419    vmlsl.u8        q6, d22, d1
420
421    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
422    vmlsl.u8        q4, d23, d4
423    vmlsl.u8        q5, d24, d4
424    vmlsl.u8        q6, d25, d4
425
426    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
427    vmlal.u8        q4, d21, d2
428    vmlal.u8        q5, d22, d2
429    vmlal.u8        q6, d23, d2
430
431    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
432    vmlal.u8        q4, d24, d5
433    vmlal.u8        q5, d25, d5
434    vmlal.u8        q6, d26, d5
435
436    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
437    vmull.u8        q8, d22, d3
438    vmull.u8        q9, d23, d3
439    vmull.u8        q10, d24, d3
440
441    subs            r12, r12, #1
442
443    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
444    vqadd.s16       q8, q4
445    vqadd.s16       q9, q5
446    vqadd.s16       q10, q6
447
448    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
449    vqrshrun.s16    d7, q8, #7
450    vqrshrun.s16    d8, q9, #7
451    vqrshrun.s16    d9, q10, #7
452
453    vst1.u8         {d6}, [r4], r5          ;store result
454    vmov            q9, q11
455    vst1.u8         {d7}, [r4], r5
456    vmov            q10, q12
457    vst1.u8         {d8}, [r4], r5
458    vmov            d22, d26
459    vst1.u8         {d9}, [r4], r5
460
461    bne             secondpass_only_inner_loop_neon
462
463    subs            r3, r3, #1
464    sub             r0, r0, r1, lsl #4
465    sub             r0, r0, r1, lsl #2
466    sub             r0, r0, r1
467    add             r0, r0, #8
468
469    sub             r4, r4, r5, lsl #4
470    add             r4, r4, #8
471
472    bne filt_blk2d_spo16x16_outloop_neon
473
474    pop             {r4-r5,pc}
475
476    ENDP
477
478;-----------------
479
480_filter16_coeff_
481    DCD     filter16_coeff
482filter16_coeff
483    DCD     0,  0,  128,    0,   0,  0,   0,  0
484    DCD     0, -6,  123,   12,  -1,  0,   0,  0
485    DCD     2, -11, 108,   36,  -8,  1,   0,  0
486    DCD     0, -9,   93,   50,  -6,  0,   0,  0
487    DCD     3, -16,  77,   77, -16,  3,   0,  0
488    DCD     0, -6,   50,   93,  -9,  0,   0,  0
489    DCD     1, -8,   36,  108, -11,  2,   0,  0
490    DCD     0, -1,   12,  123,  -6,   0,  0,  0
491
492    END
493