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 vst1.u8 {q3}, [sp]! 71 ldr r12, _mbvlfuv_coeff_ 72 vst1.u8 {q10}, [sp]! 73 74 ;vp8_filter_mask() function 75 ;vp8_hevmask() function 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 vcge.u8 q15, q1, q11 ; (abs(p3 - p2) > limit)*-1 84 vcge.u8 q12, q1, q12 ; (abs(p2 - p1) > limit)*-1 85 vcge.u8 q10, q1, q13 ; (abs(p1 - p0) > limit)*-1 86 vcge.u8 q11, q1, q14 ; (abs(q1 - q0) > limit)*-1 87 vcge.u8 q3, q1, q3 ; (abs(q2 - q1) > limit)*-1 88 vcge.u8 q0, q1, q0 ; (abs(q3 - q2) > limit)*-1 89 90 vand q15, q15, q12 91 92 vabd.u8 q12, q6, q7 ; abs(p0 - q0) 93 94 vcgt.u8 q13, q13, q2 ; (abs(p1 - p0) > thresh)*-1 95 vcgt.u8 q14, q14, q2 ; (abs(q1 - q0) > thresh)*-1 96 97 vld1.s8 {d4[], d5[]}, [r2] ; flimit 98 99 vand q10, q10, q11 100 vand q3, q3, q0 101 102 vld1.u8 {q0}, [r12]! 103 104 vadd.u8 q2, q2, q2 ; flimit * 2 105 vadd.u8 q2, q2, q1 ; flimit * 2 + limit 106 107 vabd.u8 q1, q5, q8 ; abs(p1 - q1) 108 vqadd.u8 q12, q12, q12 ; abs(p0 - q0) * 2 109 vshr.u8 q1, q1, #1 ; abs(p1 - q1) / 2 110 vqadd.u8 q12, q12, q1 ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2 111 vcge.u8 q12, q2, q12 ; (abs(p0 - q0)*2 + abs(p1 - q1)/2 > flimit*2 + limit)*-1 112 113 vand q15, q15, q10 114 115 ;vp8_filter() function 116 veor q7, q7, q0 ; qs0: q0 offset to convert to a signed value 117 veor q6, q6, q0 ; ps0: p0 offset to convert to a signed value 118 veor q5, q5, q0 ; ps1: p1 offset to convert to a signed value 119 veor q8, q8, q0 ; qs1: q1 offset to convert to a signed value 120 veor q4, q4, q0 ; ps2: p2 offset to convert to a signed value 121 veor q9, q9, q0 ; qs2: q2 offset to convert to a signed value 122 ;;;;;;;;;;;;; 123 vorr q14, q13, q14 ; q14: vp8_hevmask 124 125 ;vqsub.s8 q2, q7, q6 ; ( qs0 - ps0) 126 vsubl.s8 q2, d14, d12 ; ( qs0 - ps0) 127 vsubl.s8 q13, d15, d13 128 129 vqsub.s8 q1, q5, q8 ; vp8_filter = vp8_signed_char_clamp(ps1-qs1) 130 131 ;vadd.s8 q10, q2, q2 ; 3 * ( qs0 - ps0) 132 vadd.s16 q10, q2, q2 ; 3 * ( qs0 - ps0) 133 vadd.s16 q11, q13, q13 134 135 vand q3, q3, q12 136 137 ;vadd.s8 q2, q2, q10 138 vadd.s16 q2, q2, q10 139 vadd.s16 q13, q13, q11 140 141 vld1.u8 {q12}, [r12]! ;#3 142 143 ;vqadd.s8 q1, q1, q2 ; vp8_filter + 3 * ( qs0 - ps0) 144 vaddw.s8 q2, q2, d2 ; vp8_filter + 3 * ( qs0 - ps0) 145 vaddw.s8 q13, q13, d3 146 147 vand q15, q15, q3 ; q15: vp8_filter_mask 148 vld1.u8 {q11}, [r12]! ;#4 149 150 vqmovn.s16 d2, q2 ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0)) 151 vqmovn.s16 d3, q13 152 153 ;;;;;;;;;;;;;; 154 vand q1, q1, q15 ; vp8_filter &= mask 155 156 vld1.u8 {q15}, [r12]! ;#63 157 ; 158 vand q13, q1, q14 ; Filter2: q13; Filter2 &= hev 159 160 vld1.u8 {d7}, [r12]! ;#9 161 ; 162 163 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Change for VP8 from VP7 164 ; vand q2, q13, q12 ; s = Filter2 & 7 165 166 ; vqadd.s8 q13, q13, q11 ; Filter2 = vp8_signed_char_clamp(Filter2+4) 167 ; vld1.u8 {d6}, [r12]! ;#18 168 169 ; sub r0, r0, r1, lsl #3 170 ; sub r3, r3, r1, lsl #3 171 ; sub sp, sp, #32 172 173 ; vshr.s8 q13, q13, #3 ; Filter2 >>= 3 174 ; vceq.i8 q2, q2, q11 ; s = (s==4)*-1 175 176 ; vqsub.s8 q7, q7, q13 ; qs0 = vp8_signed_char_clamp(qs0 - Filter2) 177 ; vqadd.s8 q11, q2, q13 ; u = vp8_signed_char_clamp(s + Filter2) 178 179 ; vld1.u8 {d5}, [r12]! ;#27 180 ; vmov q10, q15 181 ; vmov q12, q15 182 183 ; vqadd.s8 q6, q6, q11 ; ps0 = vp8_signed_char_clamp(ps0 + u) 184 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 185 vqadd.s8 q2, q13, q11 ; Filter1 = vp8_signed_char_clamp(Filter2+4) 186 vqadd.s8 q13, q13, q12 ; Filter2 = vp8_signed_char_clamp(Filter2+3) 187 188 vld1.u8 {d6}, [r12]! ;#18 189 190 sub r0, r0, r1, lsl #3 191 sub r3, r3, r1, lsl #3 192 193 vshr.s8 q2, q2, #3 ; Filter1 >>= 3 194 vshr.s8 q13, q13, #3 ; Filter2 >>= 3 195 196 vmov q10, q15 197 vmov q12, q15 198 199 vqsub.s8 q7, q7, q2 ; qs0 = vp8_signed_char_clamp(qs0 - Filter1) 200 201 vld1.u8 {d5}, [r12]! ;#27 202 203 sub sp, sp, #32 204 205 vqadd.s8 q6, q6, q13 ; ps0 = vp8_signed_char_clamp(ps0 + Filter2) 206 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 207 208 vbic q1, q1, q14 ; Filter2: q1; vp8_filter &= ~hev; Filter2 = vp8_filter 209 210 ; roughly 1/7th difference across boundary 211 ; roughly 2/7th difference across boundary 212 ; roughly 3/7th difference across boundary 213 vmov q11, q15 214 vmov q13, q15 215 vmov q14, q15 216 217 vmlal.s8 q10, d2, d7 ; Filter2 * 9 218 vmlal.s8 q11, d3, d7 219 vmlal.s8 q12, d2, d6 ; Filter2 * 18 220 vmlal.s8 q13, d3, d6 221 vmlal.s8 q14, d2, d5 ; Filter2 * 27 222 vmlal.s8 q15, d3, d5 223 vqshrn.s16 d20, q10, #7 ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7) 224 vqshrn.s16 d21, q11, #7 225 vqshrn.s16 d24, q12, #7 ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7) 226 vqshrn.s16 d25, q13, #7 227 vqshrn.s16 d28, q14, #7 ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7) 228 vqshrn.s16 d29, q15, #7 229 230 vqsub.s8 q11, q9, q10 ; s = vp8_signed_char_clamp(qs2 - u) 231 vqadd.s8 q10, q4, q10 ; s = vp8_signed_char_clamp(ps2 + u) 232 vqsub.s8 q13, q8, q12 ; s = vp8_signed_char_clamp(qs1 - u) 233 vqadd.s8 q12, q5, q12 ; s = vp8_signed_char_clamp(ps1 + u) 234 vqsub.s8 q15, q7, q14 ; s = vp8_signed_char_clamp(qs0 - u) 235 vqadd.s8 q14, q6, q14 ; s = vp8_signed_char_clamp(ps0 + u) 236 veor q9, q11, q0 ; *oq2 = s^0x80 237 veor q4, q10, q0 ; *op2 = s^0x80 238 veor q8, q13, q0 ; *oq1 = s^0x80 239 veor q5, q12, q0 ; *op2 = s^0x80 240 veor q7, q15, q0 ; *oq0 = s^0x80 241 vld1.u8 {q3}, [sp]! 242 veor q6, q14, q0 ; *op0 = s^0x80 243 vld1.u8 {q10}, [sp]! 244 245 ;transpose to 16x8 matrix 246 vtrn.32 q3, q7 247 vtrn.32 q4, q8 248 vtrn.32 q5, q9 249 vtrn.32 q6, q10 250 251 vtrn.16 q3, q5 252 vtrn.16 q4, q6 253 vtrn.16 q7, q9 254 vtrn.16 q8, q10 255 256 vtrn.8 q3, q4 257 vtrn.8 q5, q6 258 vtrn.8 q7, q8 259 vtrn.8 q9, q10 260 261 ;store op2, op1, op0, oq0, oq1, oq2 262 vst1.8 {d6}, [r0], r1 263 vst1.8 {d7}, [r3], r1 264 vst1.8 {d8}, [r0], r1 265 vst1.8 {d9}, [r3], r1 266 vst1.8 {d10}, [r0], r1 267 vst1.8 {d11}, [r3], r1 268 vst1.8 {d12}, [r0], r1 269 vst1.8 {d13}, [r3], r1 270 vst1.8 {d14}, [r0], r1 271 vst1.8 {d15}, [r3], r1 272 vst1.8 {d16}, [r0], r1 273 vst1.8 {d17}, [r3], r1 274 vst1.8 {d18}, [r0], r1 275 vst1.8 {d19}, [r3], r1 276 vst1.8 {d20}, [r0], r1 277 vst1.8 {d21}, [r3], r1 278 279 bx lr 280 ENDP ; |vp8_mbloop_filter_vertical_edge_uv_neon| 281 282 ;----------------- 283 AREA mbvloopfilteruv_dat, DATA, READWRITE ;read/write by default 284 ;Data section with name data_area is specified. DCD reserves space in memory for 16 data. 285 ;One word each is reserved. Label filter_coeff can be used to access the data. 286 ;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ... 287 _mbvlfuv_coeff_ 288 DCD mbvlfuv_coeff 289 mbvlfuv_coeff 290 DCD 0x80808080, 0x80808080, 0x80808080, 0x80808080 291 DCD 0x03030303, 0x03030303, 0x03030303, 0x03030303 292 DCD 0x04040404, 0x04040404, 0x04040404, 0x04040404 293 DCD 0x003f003f, 0x003f003f, 0x003f003f, 0x003f003f 294 DCD 0x09090909, 0x09090909, 0x12121212, 0x12121212 295 DCD 0x1b1b1b1b, 0x1b1b1b1b 296 297 END 298