]> granicus.if.org Git - libvpx/blob - vp8/common/arm/neon/mbloopfilterhorizontaledge_y_neon.asm
safety check to avoid divide by 0s
[libvpx] / vp8 / common / arm / neon / mbloopfilterhorizontaledge_y_neon.asm
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_mbloop_filter_horizontal_edge_y_neon|
13     ARM
14     REQUIRE8
15     PRESERVE8
16
17     AREA ||.text||, CODE, READONLY, ALIGN=2
18 ;Note: flimit, limit, and thresh shpuld be positive numbers. All 16 elements in flimit
19 ;are equal. So, in the code, only one load is needed
20 ;for flimit. Same way applies to limit and thresh.
21 ; r0    unsigned char *s,
22 ; r1    int p, //pitch
23 ; r2    const signed char *flimit,
24 ; r3    const signed char *limit,
25 ; stack(r4) const signed char *thresh,
26 ; //stack(r5)   int count --unused
27 |vp8_mbloop_filter_horizontal_edge_y_neon| PROC
28     sub         r0, r0, r1, lsl #2          ; move src pointer down by 4 lines
29     ldr         r12, [sp, #0]               ; load thresh pointer
30
31     vld1.u8     {q3}, [r0], r1              ; p3
32     vld1.s8     {d2[], d3[]}, [r3]          ; limit
33     vld1.u8     {q4}, [r0], r1              ; p2
34     vld1.s8     {d4[], d5[]}, [r12]         ; thresh
35     vld1.u8     {q5}, [r0], r1              ; p1
36     ldr         r12, _mbhlfy_coeff_
37     vld1.u8     {q6}, [r0], r1              ; p0
38
39     ; vp8_filter_mask
40     vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
41     vld1.u8     {q7}, [r0], r1              ; q0
42     vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
43     vld1.u8     {q8}, [r0], r1              ; q1
44     vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
45     vld1.u8     {q9}, [r0], r1              ; q2
46     vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
47     vld1.u8     {q10}, [r0], r1             ; q3
48     vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
49     vabd.u8     q0, q10, q9                 ; abs(q3 - q2)
50
51     vmax.u8     q11, q11, q12
52     vmax.u8     q12, q13, q14
53     vmax.u8     q3, q3, q0
54     vmax.u8     q15, q11, q12
55
56     vabd.u8     q12, q6, q7                 ; abs(p0 - q0)
57
58     ; vp8_hevmask
59     vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
60     vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
61     vmax.u8     q15, q15, q3
62
63     vld1.s8     {d4[], d5[]}, [r2]          ; flimit
64
65     vld1.u8     {q0}, [r12]!
66
67     vadd.u8     q2, q2, q2                  ; flimit * 2
68     vadd.u8     q2, q2, q1                  ; flimit * 2 + limit
69     vcge.u8     q15, q1, q15
70
71     vabd.u8     q1, q5, q8                  ; abs(p1 - q1)
72     vqadd.u8    q12, q12, q12               ; abs(p0 - q0) * 2
73     vshr.u8     q1, q1, #1                  ; abs(p1 - q1) / 2
74     vqadd.u8    q12, q12, q1                ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
75     vcge.u8     q12, q2, q12                ; (abs(p0 - q0)*2 + abs(p1 - q1)/2 > flimit*2 + limit)*-1
76
77     ;vp8_filter() function
78     veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
79     veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
80     veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
81     veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
82     veor        q4, q4, q0                  ; ps2: p2 offset to convert to a signed value
83     veor        q9, q9, q0                  ; qs2: q2 offset to convert to a signed value
84 ;;;;;;;;;;;;;
85     vorr        q14, q13, q14               ; q14: vp8_hevmask
86
87     vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
88     vsubl.s8    q13, d15, d13
89
90     vqsub.s8    q1, q5, q8                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
91
92     vadd.s16    q10, q2, q2                 ; 3 * ( qs0 - ps0)
93     vadd.s16    q11, q13, q13
94     vand        q15, q15, q12               ; vp8_filter_mask
95
96     vadd.s16    q2, q2, q10
97     vadd.s16    q13, q13, q11
98
99     vld1.u8     {q12}, [r12]!               ;#3
100
101     vaddw.s8    q2, q2, d2                  ; vp8_filter + 3 * ( qs0 - ps0)
102     vaddw.s8    q13, q13, d3
103
104     vld1.u8     {q11}, [r12]!               ;#4
105
106     vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
107     vqmovn.s16  d3, q13
108
109 ;;;;;;;;;;;;;;
110     vand        q1, q1, q15                 ; vp8_filter &= mask
111
112     vld1.u8     {q15}, [r12]!               ;#63
113     ;
114     vand        q13, q1, q14                ; Filter2: q13; Filter2 &= hev
115
116     vld1.u8     {d7}, [r12]!                ;#9
117     sub         r0, r0, r1, lsl #3
118
119     vqadd.s8    q2, q13, q11                ; Filter1 = vp8_signed_char_clamp(Filter2+4)
120     vqadd.s8    q13, q13, q12               ; Filter2 = vp8_signed_char_clamp(Filter2+3)
121
122     vld1.u8     {d6}, [r12]!                ;#18
123     add         r0, r0, r1
124     add         r2, r0, r1
125
126     vshr.s8     q2, q2, #3                  ; Filter1 >>= 3
127     vshr.s8     q13, q13, #3                ; Filter2 >>= 3
128
129     vmov        q10, q15
130     vmov        q12, q15
131
132     vqsub.s8    q7, q7, q2                  ; qs0 = vp8_signed_char_clamp(qs0 - Filter1)
133
134     vld1.u8     {d5}, [r12]!                ;#27
135     add         r3, r2, r1
136
137     vqadd.s8    q6, q6, q13                 ; ps0 = vp8_signed_char_clamp(ps0 + Filter2)
138 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
139
140     vbic        q1, q1, q14                 ; Filter2: q1; vp8_filter &= ~hev; Filter2 = vp8_filter
141
142     ; roughly 1/7th difference across boundary
143     ; roughly 2/7th difference across boundary
144     ; roughly 3/7th difference across boundary
145     vmov        q11, q15
146     vmov        q13, q15
147     vmov        q14, q15
148
149     vmlal.s8    q10, d2, d7                 ; Filter2 * 9
150     vmlal.s8    q11, d3, d7
151     vmlal.s8    q12, d2, d6                 ; Filter2 * 18
152     vmlal.s8    q13, d3, d6
153     vmlal.s8    q14, d2, d5                 ; Filter2 * 27
154     vmlal.s8    q15, d3, d5
155     vqshrn.s16  d20, q10, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
156     vqshrn.s16  d21, q11, #7
157     vqshrn.s16  d24, q12, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
158     vqshrn.s16  d25, q13, #7
159     vqshrn.s16  d28, q14, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
160     vqshrn.s16  d29, q15, #7
161
162     vqsub.s8    q11, q9, q10                ; s = vp8_signed_char_clamp(qs2 - u)
163     vqadd.s8    q10, q4, q10                ; s = vp8_signed_char_clamp(ps2 + u)
164     vqsub.s8    q13, q8, q12                ; s = vp8_signed_char_clamp(qs1 - u)
165     vqadd.s8    q12, q5, q12                ; s = vp8_signed_char_clamp(ps1 + u)
166     vqsub.s8    q15, q7, q14                ; s = vp8_signed_char_clamp(qs0 - u)
167     vqadd.s8    q14, q6, q14                ; s = vp8_signed_char_clamp(ps0 + u)
168     veor        q9, q11, q0                 ; *oq2 = s^0x80
169     veor        q4, q10, q0                 ; *op2 = s^0x80
170     veor        q5, q12, q0                 ; *op2 = s^0x80
171     veor        q6, q14, q0                 ; *op0 = s^0x80
172     veor        q8, q13, q0                 ; *oq1 = s^0x80
173     veor        q7, q15, q0                 ; *oq0 = s^0x80
174
175     vst1.u8     {q4}, [r0]                  ; store op2
176     vst1.u8     {q5}, [r2]                  ; store op1
177     vst1.u8     {q6}, [r3], r1              ; store op0
178     add         r12, r3, r1
179     vst1.u8     {q7}, [r3]                  ; store oq0
180     vst1.u8     {q8}, [r12], r1             ; store oq1
181     vst1.u8     {q9}, [r12]             ; store oq2
182
183     bx          lr
184     ENDP        ; |vp8_mbloop_filter_horizontal_edge_y_neon|
185
186 ;-----------------
187     AREA    mbhloopfiltery_dat, DATA, READWRITE         ;read/write by default
188 ;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
189 ;One word each is reserved. Label filter_coeff can be used to access the data.
190 ;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
191 _mbhlfy_coeff_
192     DCD     mbhlfy_coeff
193 mbhlfy_coeff
194     DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
195     DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
196     DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
197     DCD     0x003f003f, 0x003f003f, 0x003f003f, 0x003f003f
198     DCD     0x09090909, 0x09090909, 0x12121212, 0x12121212
199     DCD     0x1b1b1b1b, 0x1b1b1b1b
200
201     END