]> granicus.if.org Git - libvpx/blob - vp8/common/arm/neon/mbloopfilterverticaledge_uv_neon.asm
safety check to avoid divide by 0s
[libvpx] / vp8 / common / arm / neon / mbloopfilterverticaledge_uv_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_vertical_edge_uv_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 *u,
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) unsigned char *v
27 |vp8_mbloop_filter_vertical_edge_uv_neon| PROC
28     sub         r0, r0, #4                  ; move src pointer down by 4 columns
29     vld1.s8     {d2[], d3[]}, [r3]          ; limit
30     ldr         r3, [sp, #4]                ; load v ptr
31     ldr         r12, [sp, #0]               ; load thresh pointer
32
33     sub         r3, r3, #4                  ; move v pointer down by 4 columns
34
35     vld1.u8     {d6}, [r0], r1              ;load u data
36     vld1.u8     {d7}, [r3], r1              ;load v data
37     vld1.u8     {d8}, [r0], r1
38     vld1.u8     {d9}, [r3], r1
39     vld1.u8     {d10}, [r0], r1
40     vld1.u8     {d11}, [r3], r1
41     vld1.u8     {d12}, [r0], r1
42     vld1.u8     {d13}, [r3], r1
43     vld1.u8     {d14}, [r0], r1
44     vld1.u8     {d15}, [r3], r1
45     vld1.u8     {d16}, [r0], r1
46     vld1.u8     {d17}, [r3], r1
47     vld1.u8     {d18}, [r0], r1
48     vld1.u8     {d19}, [r3], r1
49     vld1.u8     {d20}, [r0], r1
50     vld1.u8     {d21}, [r3], r1
51
52     ;transpose to 8x16 matrix
53     vtrn.32     q3, q7
54     vtrn.32     q4, q8
55     vtrn.32     q5, q9
56     vtrn.32     q6, q10
57
58     vtrn.16     q3, q5
59     vtrn.16     q4, q6
60     vtrn.16     q7, q9
61     vtrn.16     q8, q10
62
63     vtrn.8      q3, q4
64     vtrn.8      q5, q6
65     vtrn.8      q7, q8
66     vtrn.8      q9, q10
67
68     sub         sp, sp, #32
69     vld1.s8     {d4[], d5[]}, [r12]         ; thresh
70     mov         r12, sp
71     vst1.u8     {q3}, [r12]!
72     vst1.u8     {q10}, [r12]!
73     ldr         r12, _mbvlfuv_coeff_
74
75     ; vp8_filter_mask
76     vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
77     vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
78     vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
79     vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
80     vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
81     vabd.u8     q0, q10, q9                 ; abs(q3 - q2)
82
83     vmax.u8     q11, q11, q12
84     vmax.u8     q12, q13, q14
85     vmax.u8     q3, q3, q0
86     vmax.u8     q15, q11, q12
87
88     vabd.u8     q12, q6, q7                 ; abs(p0 - q0)
89
90     ; vp8_hevmask
91     vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
92     vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
93     vmax.u8     q15, q15, q3
94
95     vld1.s8     {d4[], d5[]}, [r2]          ; flimit
96
97     vld1.u8     {q0}, [r12]!
98
99     vadd.u8     q2, q2, q2                  ; flimit * 2
100     vadd.u8     q2, q2, q1                  ; flimit * 2 + limit
101     vcge.u8     q15, q1, q15
102
103     vabd.u8     q1, q5, q8                  ; abs(p1 - q1)
104     vqadd.u8    q12, q12, q12               ; abs(p0 - q0) * 2
105     vshr.u8     q1, q1, #1                  ; abs(p1 - q1) / 2
106     vqadd.u8    q12, q12, q1                ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
107     vcge.u8     q12, q2, q12                ; (abs(p0 - q0)*2 + abs(p1 - q1)/2 > flimit*2 + limit)*-1
108
109     ;vp8_filter() function
110     veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
111     veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
112     veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
113     veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
114     veor        q4, q4, q0                  ; ps2: p2 offset to convert to a signed value
115     veor        q9, q9, q0                  ; qs2: q2 offset to convert to a signed value
116 ;;;;;;;;;;;;;
117     vorr        q14, q13, q14               ; q14: vp8_hevmask
118
119     vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
120     vsubl.s8    q13, d15, d13
121
122     vqsub.s8    q1, q5, q8                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
123
124     vadd.s16    q10, q2, q2                 ; 3 * ( qs0 - ps0)
125     vadd.s16    q11, q13, q13
126     vand        q15, q15, q12               ; vp8_filter_mask
127
128     vadd.s16    q2, q2, q10
129     vadd.s16    q13, q13, q11
130
131     vld1.u8     {q12}, [r12]!               ;#3
132
133     vaddw.s8    q2, q2, d2                  ; vp8_filter + 3 * ( qs0 - ps0)
134     vaddw.s8    q13, q13, d3
135
136     vld1.u8     {q11}, [r12]!               ;#4
137
138     vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
139     vqmovn.s16  d3, q13
140
141 ;;;;;;;;;;;;;;
142     vand        q1, q1, q15                 ; vp8_filter &= mask
143
144     vld1.u8     {q15}, [r12]!               ;#63
145     ;
146     vand        q13, q1, q14                ; Filter2: q13; Filter2 &= hev
147
148     vld1.u8     {d7}, [r12]!                ;#9
149     ;
150
151     vqadd.s8    q2, q13, q11                ; Filter1 = vp8_signed_char_clamp(Filter2+4)
152     vqadd.s8    q13, q13, q12               ; Filter2 = vp8_signed_char_clamp(Filter2+3)
153
154     vld1.u8     {d6}, [r12]!                ;#18
155
156     sub         r0, r0, r1, lsl #3
157     sub         r3, r3, r1, lsl #3
158
159     vshr.s8     q2, q2, #3                  ; Filter1 >>= 3
160     vshr.s8     q13, q13, #3                ; Filter2 >>= 3
161
162     vmov        q10, q15
163     vmov        q12, q15
164
165     vqsub.s8    q7, q7, q2                  ; qs0 = vp8_signed_char_clamp(qs0 - Filter1)
166
167     vld1.u8     {d5}, [r12]!                ;#27
168
169     vqadd.s8    q6, q6, q13                 ; ps0 = vp8_signed_char_clamp(ps0 + Filter2)
170 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
171
172     vbic        q1, q1, q14                 ; Filter2: q1; vp8_filter &= ~hev; Filter2 = vp8_filter
173
174     ; roughly 1/7th difference across boundary
175     ; roughly 2/7th difference across boundary
176     ; roughly 3/7th difference across boundary
177     vmov        q11, q15
178     vmov        q13, q15
179     vmov        q14, q15
180
181     vmlal.s8    q10, d2, d7                 ; Filter2 * 9
182     vmlal.s8    q11, d3, d7
183     vmlal.s8    q12, d2, d6                 ; Filter2 * 18
184     vmlal.s8    q13, d3, d6
185     vmlal.s8    q14, d2, d5                 ; Filter2 * 27
186     vmlal.s8    q15, d3, d5
187     vqshrn.s16  d20, q10, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
188     vqshrn.s16  d21, q11, #7
189     vqshrn.s16  d24, q12, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
190     vqshrn.s16  d25, q13, #7
191     vqshrn.s16  d28, q14, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
192     vqshrn.s16  d29, q15, #7
193
194     vqsub.s8    q11, q9, q10                ; s = vp8_signed_char_clamp(qs2 - u)
195     vqadd.s8    q10, q4, q10                ; s = vp8_signed_char_clamp(ps2 + u)
196     vqsub.s8    q13, q8, q12                ; s = vp8_signed_char_clamp(qs1 - u)
197     vqadd.s8    q12, q5, q12                ; s = vp8_signed_char_clamp(ps1 + u)
198     vqsub.s8    q15, q7, q14                ; s = vp8_signed_char_clamp(qs0 - u)
199     vqadd.s8    q14, q6, q14                ; s = vp8_signed_char_clamp(ps0 + u)
200     veor        q9, q11, q0                 ; *oq2 = s^0x80
201     veor        q4, q10, q0                 ; *op2 = s^0x80
202     veor        q8, q13, q0                 ; *oq1 = s^0x80
203     veor        q5, q12, q0                 ; *op2 = s^0x80
204     veor        q7, q15, q0                 ; *oq0 = s^0x80
205     vld1.u8     {q3}, [sp]!
206     veor        q6, q14, q0                 ; *op0 = s^0x80
207     vld1.u8     {q10}, [sp]!
208
209     ;transpose to 16x8 matrix
210     vtrn.32     q3, q7
211     vtrn.32     q4, q8
212     vtrn.32     q5, q9
213     vtrn.32     q6, q10
214
215     vtrn.16     q3, q5
216     vtrn.16     q4, q6
217     vtrn.16     q7, q9
218     vtrn.16     q8, q10
219
220     vtrn.8      q3, q4
221     vtrn.8      q5, q6
222     vtrn.8      q7, q8
223     vtrn.8      q9, q10
224
225     ;store op2, op1, op0, oq0, oq1, oq2
226     vst1.8      {d6}, [r0], r1
227     vst1.8      {d7}, [r3], r1
228     vst1.8      {d8}, [r0], r1
229     vst1.8      {d9}, [r3], r1
230     vst1.8      {d10}, [r0], r1
231     vst1.8      {d11}, [r3], r1
232     vst1.8      {d12}, [r0], r1
233     vst1.8      {d13}, [r3], r1
234     vst1.8      {d14}, [r0], r1
235     vst1.8      {d15}, [r3], r1
236     vst1.8      {d16}, [r0], r1
237     vst1.8      {d17}, [r3], r1
238     vst1.8      {d18}, [r0], r1
239     vst1.8      {d19}, [r3], r1
240     vst1.8      {d20}, [r0], r1
241     vst1.8      {d21}, [r3], r1
242
243     bx          lr
244     ENDP        ; |vp8_mbloop_filter_vertical_edge_uv_neon|
245
246 ;-----------------
247     AREA    mbvloopfilteruv_dat, DATA, READWRITE            ;read/write by default
248 ;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
249 ;One word each is reserved. Label filter_coeff can be used to access the data.
250 ;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
251 _mbvlfuv_coeff_
252     DCD     mbvlfuv_coeff
253 mbvlfuv_coeff
254     DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
255     DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
256     DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
257     DCD     0x003f003f, 0x003f003f, 0x003f003f, 0x003f003f
258     DCD     0x09090909, 0x09090909, 0x12121212, 0x12121212
259     DCD     0x1b1b1b1b, 0x1b1b1b1b
260
261     END