1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 17 сент. 2018 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #ifndef DSP_ARCH_ARM_NEON_D32_GRAPHICS_H_ 23 #define DSP_ARCH_ARM_NEON_D32_GRAPHICS_H_ 24 25 #ifndef DSP_ARCH_ARM_NEON_32_IMPL 26 #error "This header should not be included directly" 27 #endif /* DSP_ARCH_ARM_NEON_32_IMPL */ 28 29 namespace neon_d32 30 { axis_apply_log1(float * x,const float * v,float zero,float norm_x,size_t count)31 void axis_apply_log1(float *x, const float *v, float zero, float norm_x, size_t count) 32 { 33 IF_ARCH_ARM( 34 float params[8] __lsp_aligned16; 35 params[0] = zero; 36 params[1] = norm_x; 37 const uint32_t *iptr = &LOG_IARGS[4]; 38 const float *fptr = LOG_FARGS; 39 ); 40 41 //--------------------------------------------------------------- 42 // Prepare constants 43 ARCH_ARM_ASM 44 ( 45 __ASM_EMIT("vld1.32 {d0}, [%[params]]") 46 __ASM_EMIT("vdup.32 q1, d0[1]") // q2 = norm_x 47 __ASM_EMIT("vdup.32 q0, d0[0]") // q0 = zero 48 __ASM_EMIT("vst1.32 {q0-q1}, [%[params]]") 49 50 __ASM_EMIT("subs %[count], $16") 51 __ASM_EMIT("blo 2f") 52 53 // Do 16x blocks 54 __ASM_EMIT("1:") 55 __ASM_EMIT("vld1.32 {q4-q5}, [%[v]]!") // q4 = v, q5 = v, v += 8 56 __ASM_EMIT("vld1.32 {q6-q7}, [%[v]]!") 57 __ASM_EMIT("vld1.32 {q12}, [%[fptr]]!") // q12 = X_AMP, fptr += 4 58 __ASM_EMIT("vabs.f32 q4, q4") // q4 = abs(v) 59 __ASM_EMIT("vabs.f32 q5, q5") 60 __ASM_EMIT("vabs.f32 q6, q6") 61 __ASM_EMIT("vabs.f32 q7, q7") 62 __ASM_EMIT("vld1.32 {q13}, [%[params]]") // q13 = zero 63 __ASM_EMIT("vmax.f32 q4, q12") // q12 = max(X_AMP, abs(v)), ignores denormalized values 64 __ASM_EMIT("vmax.f32 q5, q12") 65 __ASM_EMIT("vmax.f32 q6, q12") 66 __ASM_EMIT("vmax.f32 q7, q12") 67 __ASM_EMIT("vmul.f32 q0, q4, q13") // q13 = max(X_AMP, abs(v)) * zero 68 __ASM_EMIT("vmul.f32 q1, q5, q13") 69 __ASM_EMIT("vmul.f32 q2, q6, q13") 70 __ASM_EMIT("vmul.f32 q3, q7, q13") 71 // Step 2: parse float value 72 __ASM_EMIT("vld1.32 {q12-q13}, [%[iptr]]") // q12 = MANT_MASK, q13 = FRAC_SUB = 127 73 __ASM_EMIT("vshr.u32 q4, q0, $23") // q4 = frac(v) 74 __ASM_EMIT("vshr.u32 q5, q1, $23") 75 __ASM_EMIT("vshr.u32 q6, q2, $23") 76 __ASM_EMIT("vshr.u32 q7, q3, $23") 77 __ASM_EMIT("vand.u32 q8, q0, q12") // q8 = mant(v) 78 __ASM_EMIT("vand.u32 q9, q1, q12") 79 __ASM_EMIT("vand.u32 q10, q2, q12") 80 __ASM_EMIT("vand.u32 q11, q3, q12") 81 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8 82 __ASM_EMIT("vsub.i32 q4, q4, q13") // q4 = frac(v) - 127 83 __ASM_EMIT("vsub.i32 q5, q5, q13") 84 __ASM_EMIT("vsub.i32 q6, q6, q13") 85 __ASM_EMIT("vsub.i32 q7, q7, q13") 86 __ASM_EMIT("vorr.i32 q8, q8, q14") // q8 = V = mant(v)+0.5 87 __ASM_EMIT("vorr.i32 q9, q9, q14") 88 __ASM_EMIT("vorr.i32 q10, q10, q14") 89 __ASM_EMIT("vorr.i32 q11, q11, q14") 90 __ASM_EMIT("vcvt.f32.s32 q4, q4") // q4 = E = float(frac(v)-127) 91 __ASM_EMIT("vcvt.f32.s32 q5, q5") 92 __ASM_EMIT("vcvt.f32.s32 q6, q6") 93 __ASM_EMIT("vcvt.f32.s32 q7, q7") 94 // Prepare logarithm approximation calculations 95 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = 1.0, q13 = L0 , fptr += 4 96 __ASM_EMIT("vclt.f32 q0, q8, q15") // q0 = [ V < sqrt(1/2) ] 97 __ASM_EMIT("vclt.f32 q1, q9, q15") 98 __ASM_EMIT("vclt.f32 q2, q10, q15") 99 __ASM_EMIT("vclt.f32 q3, q11, q15") 100 __ASM_EMIT("vand.u32 q0, q0, q8") // q0 = V * [ V < sqrt(1/2) ] 101 __ASM_EMIT("vand.u32 q1, q1, q9") 102 __ASM_EMIT("vand.u32 q2, q2, q10") 103 __ASM_EMIT("vand.u32 q3, q3, q11") 104 __ASM_EMIT("vadd.f32 q0, q0, q8") // q0 = V + V * [ V < sqrt(1/2) ] 105 __ASM_EMIT("vadd.f32 q1, q1, q9") 106 __ASM_EMIT("vadd.f32 q2, q2, q10") 107 __ASM_EMIT("vadd.f32 q3, q3, q11") 108 __ASM_EMIT("vclt.f32 q8, q8, q15") // q8 = [ V < sqrt(1/2) ] 109 __ASM_EMIT("vclt.f32 q9, q9, q15") 110 __ASM_EMIT("vclt.f32 q10, q10, q15") 111 __ASM_EMIT("vclt.f32 q11, q11, q15") 112 __ASM_EMIT("vsub.f32 q0, q0, q12") // q0 = A = V + V & [ V < sqrt(1/2) ] - 1.0 113 __ASM_EMIT("vsub.f32 q1, q1, q12") 114 __ASM_EMIT("vsub.f32 q2, q2, q12") 115 __ASM_EMIT("vsub.f32 q3, q3, q12") 116 __ASM_EMIT("vbic.u32 q8, q12, q8") // q8 = 1.0 & [ V >= sqrt(1/2) ] 117 __ASM_EMIT("vbic.u32 q9, q12, q9") 118 __ASM_EMIT("vbic.u32 q10, q12, q10") 119 __ASM_EMIT("vbic.u32 q11, q12, q11") 120 __ASM_EMIT("vadd.f32 q4, q4, q8") // q4 = B = E + 1.0 & [ V >= sqrt(1/2) ] 121 __ASM_EMIT("vadd.f32 q5, q5, q9") 122 __ASM_EMIT("vadd.f32 q6, q6, q10") 123 __ASM_EMIT("vadd.f32 q7, q7, q11") 124 // Calculate logarithmic values 125 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L1, q15 = L2, fptr += 8 126 __ASM_EMIT("vmul.f32 q8, q0, q13") // q8 = L0*A 127 __ASM_EMIT("vmul.f32 q9, q1, q13") 128 __ASM_EMIT("vmul.f32 q10, q2, q13") 129 __ASM_EMIT("vmul.f32 q11, q3, q13") 130 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L1+L0*A 131 __ASM_EMIT("vadd.f32 q9, q9, q14") 132 __ASM_EMIT("vadd.f32 q10, q10, q14") 133 __ASM_EMIT("vadd.f32 q11, q11, q14") 134 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L3, q13 = L4, fptr += 8 135 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L1+L0*A) 136 __ASM_EMIT("vmul.f32 q9, q9, q1") 137 __ASM_EMIT("vmul.f32 q10, q10, q2") 138 __ASM_EMIT("vmul.f32 q11, q11, q3") 139 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L2+A*(L1+L0*A) 140 __ASM_EMIT("vadd.f32 q9, q9, q15") 141 __ASM_EMIT("vadd.f32 q10, q10, q15") 142 __ASM_EMIT("vadd.f32 q11, q11, q15") 143 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L2+A*(L1+L0*A)) 144 __ASM_EMIT("vmul.f32 q9, q9, q1") 145 __ASM_EMIT("vmul.f32 q10, q10, q2") 146 __ASM_EMIT("vmul.f32 q11, q11, q3") 147 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L3+A*(L2+A*(L1+L0*A)) 148 __ASM_EMIT("vadd.f32 q9, q9, q12") 149 __ASM_EMIT("vadd.f32 q10, q10, q12") 150 __ASM_EMIT("vadd.f32 q11, q11, q12") 151 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L5, q15 = L6, fptr += 8 152 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L3+A*(L2+A*(L1+L0*A))) 153 __ASM_EMIT("vmul.f32 q9, q9, q1") 154 __ASM_EMIT("vmul.f32 q10, q10, q2") 155 __ASM_EMIT("vmul.f32 q11, q11, q3") 156 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L4+A*(L3+A*(L2+A*(L1+L0*A))) 157 __ASM_EMIT("vadd.f32 q9, q9, q13") 158 __ASM_EMIT("vadd.f32 q10, q10, q13") 159 __ASM_EMIT("vadd.f32 q11, q11, q13") 160 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 161 __ASM_EMIT("vmul.f32 q9, q9, q1") 162 __ASM_EMIT("vmul.f32 q10, q10, q2") 163 __ASM_EMIT("vmul.f32 q11, q11, q3") 164 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 165 __ASM_EMIT("vadd.f32 q9, q9, q14") 166 __ASM_EMIT("vadd.f32 q10, q10, q14") 167 __ASM_EMIT("vadd.f32 q11, q11, q14") 168 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L7, q13 = L8, fptr += 8 169 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 170 __ASM_EMIT("vmul.f32 q9, q9, q1") 171 __ASM_EMIT("vmul.f32 q10, q10, q2") 172 __ASM_EMIT("vmul.f32 q11, q11, q3") 173 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 174 __ASM_EMIT("vadd.f32 q9, q9, q15") 175 __ASM_EMIT("vadd.f32 q10, q10, q15") 176 __ASM_EMIT("vadd.f32 q11, q11, q15") 177 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 178 __ASM_EMIT("vmul.f32 q9, q9, q1") 179 __ASM_EMIT("vmul.f32 q10, q10, q2") 180 __ASM_EMIT("vmul.f32 q11, q11, q3") 181 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 182 __ASM_EMIT("vadd.f32 q9, q9, q12") 183 __ASM_EMIT("vadd.f32 q10, q10, q12") 184 __ASM_EMIT("vadd.f32 q11, q11, q12") 185 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]") // q14 = L9, q15 = (LXE + LN2), fptr += 8 186 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 187 __ASM_EMIT("vmul.f32 q9, q9, q1") 188 __ASM_EMIT("vmul.f32 q10, q10, q2") 189 __ASM_EMIT("vmul.f32 q11, q11, q3") 190 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 191 __ASM_EMIT("vadd.f32 q9, q9, q13") 192 __ASM_EMIT("vadd.f32 q10, q10, q13") 193 __ASM_EMIT("vadd.f32 q11, q11, q13") 194 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 195 __ASM_EMIT("vmul.f32 q9, q9, q1") 196 __ASM_EMIT("vmul.f32 q10, q10, q2") 197 __ASM_EMIT("vmul.f32 q11, q11, q3") 198 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 199 __ASM_EMIT("vadd.f32 q9, q9, q14") 200 __ASM_EMIT("vadd.f32 q10, q10, q14") 201 __ASM_EMIT("vadd.f32 q11, q11, q14") 202 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 203 __ASM_EMIT("vmul.f32 q9, q9, q1") 204 __ASM_EMIT("vmul.f32 q10, q10, q2") 205 __ASM_EMIT("vmul.f32 q11, q11, q3") 206 __ASM_EMIT("sub %[fptr], $0xd0") // fptr -= 52 207 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 208 __ASM_EMIT("vmul.f32 q9, q9, q1") 209 __ASM_EMIT("vmul.f32 q10, q10, q2") 210 __ASM_EMIT("vmul.f32 q11, q11, q3") 211 __ASM_EMIT("vmla.f32 q8, q4, q15") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 212 __ASM_EMIT("vmla.f32 q9, q5, q15") 213 __ASM_EMIT("vmla.f32 q10, q6, q15") 214 __ASM_EMIT("vmla.f32 q11, q7, q15") 215 __ASM_EMIT("vadd.f32 q8, q8, q0") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A 216 __ASM_EMIT("vadd.f32 q9, q9, q1") 217 __ASM_EMIT("vadd.f32 q10, q10, q2") 218 __ASM_EMIT("vadd.f32 q11, q11, q3") 219 // Apply values to axes, q0 = log(abs(v*zero)) 220 __ASM_EMIT("vldm %[x], {q4-q7}") // q4-q7 = x 221 __ASM_EMIT("vld1.32 {q12-q13}, [%[params]]") // q12 = zero, q13 = norm_x 222 __ASM_EMIT("vmla.f32 q4, q8, q13") // q4 = x + log(abs(v*zero)) * norm_x 223 __ASM_EMIT("vmla.f32 q5, q9, q13") 224 __ASM_EMIT("vmla.f32 q6, q10, q13") 225 __ASM_EMIT("vmla.f32 q7, q11, q13") 226 __ASM_EMIT("subs %[count], $16") 227 __ASM_EMIT("vstm %[x]!, {q4-q7}") // x += 8 228 __ASM_EMIT("bge 1b") 229 230 // Do 8x block 231 __ASM_EMIT("2:") 232 __ASM_EMIT("adds %[count], $8") 233 __ASM_EMIT("blt 4f") 234 235 __ASM_EMIT("vld1.32 {q4-q5}, [%[v]]!") // q4 = v, q5 = v, v += 8 236 __ASM_EMIT("vld1.32 {q12}, [%[fptr]]!") // q12 = X_AMP, fptr += 4 237 __ASM_EMIT("vabs.f32 q4, q4") // q4 = abs(v) 238 __ASM_EMIT("vabs.f32 q5, q5") 239 __ASM_EMIT("vld1.32 {q13}, [%[params]]") // q13 = zero, params += 4 240 __ASM_EMIT("vmax.f32 q4, q12") // q12 = max(X_AMP, abs(v)), ignores denormalized values 241 __ASM_EMIT("vmax.f32 q5, q12") 242 __ASM_EMIT("vmul.f32 q0, q4, q13") // q13 = max(X_AMP, abs(v)) * zero 243 __ASM_EMIT("vmul.f32 q1, q5, q13") 244 // Step 2: parse float value 245 __ASM_EMIT("vld1.32 {q12-q13}, [%[iptr]]") // q12 = MANT_MASK, q13 = FRAC_SUB = 127 246 __ASM_EMIT("vshr.u32 q4, q0, $23") // q4 = frac(v) 247 __ASM_EMIT("vshr.u32 q5, q1, $23") 248 __ASM_EMIT("vand.u32 q8, q0, q12") // q8 = mant(v) 249 __ASM_EMIT("vand.u32 q9, q1, q12") 250 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8 251 __ASM_EMIT("vsub.i32 q4, q4, q13") // q4 = frac(v) - 127 252 __ASM_EMIT("vsub.i32 q5, q5, q13") 253 __ASM_EMIT("vorr.i32 q8, q8, q14") // q8 = V = mant(v)+0.5 254 __ASM_EMIT("vorr.i32 q9, q9, q14") 255 __ASM_EMIT("vcvt.f32.s32 q4, q4") // q4 = E = float(frac(v)-127) 256 __ASM_EMIT("vcvt.f32.s32 q5, q5") 257 // Prepare logarithm approximation calculations 258 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = 1.0, q13 = L0 , fptr += 4 259 __ASM_EMIT("vclt.f32 q0, q8, q15") // q0 = [ V < sqrt(1/2) ] 260 __ASM_EMIT("vclt.f32 q1, q9, q15") 261 __ASM_EMIT("vand.u32 q0, q0, q8") // q0 = V & [ V < sqrt(1/2) ] 262 __ASM_EMIT("vand.u32 q1, q1, q9") 263 __ASM_EMIT("vadd.f32 q0, q0, q8") // q0 = V + V & [ V < sqrt(1/2) ] 264 __ASM_EMIT("vadd.f32 q1, q1, q9") 265 __ASM_EMIT("vclt.f32 q8, q8, q15") // q8 = [ V < sqrt(1/2) ] 266 __ASM_EMIT("vclt.f32 q9, q9, q15") 267 __ASM_EMIT("vsub.f32 q0, q0, q12") // q0 = A = V + V & [ V < sqrt(1/2) ] - 1.0 268 __ASM_EMIT("vsub.f32 q1, q1, q12") 269 __ASM_EMIT("vbic.u32 q8, q12, q8") // q8 = 1.0 & [ V >= sqrt(1/2) ] 270 __ASM_EMIT("vbic.u32 q9, q12, q9") 271 __ASM_EMIT("vadd.f32 q4, q4, q8") // q4 = B = E + 1.0 & [ V >= sqrt(1/2) ] 272 __ASM_EMIT("vadd.f32 q5, q5, q9") 273 // Calculate logarithmic values 274 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L1, q15 = L2, fptr += 8 275 __ASM_EMIT("vmul.f32 q8, q0, q13") // q8 = L0*A 276 __ASM_EMIT("vmul.f32 q9, q1, q13") 277 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L1+L0*A 278 __ASM_EMIT("vadd.f32 q9, q9, q14") 279 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L3, q13 = L4, fptr += 8 280 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L1+L0*A) 281 __ASM_EMIT("vmul.f32 q9, q9, q1") 282 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L2+A*(L1+L0*A) 283 __ASM_EMIT("vadd.f32 q9, q9, q15") 284 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L2+A*(L1+L0*A)) 285 __ASM_EMIT("vmul.f32 q9, q9, q1") 286 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L3+A*(L2+A*(L1+L0*A)) 287 __ASM_EMIT("vadd.f32 q9, q9, q12") 288 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L5, q15 = L6, fptr += 8 289 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L3+A*(L2+A*(L1+L0*A))) 290 __ASM_EMIT("vmul.f32 q9, q9, q1") 291 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L4+A*(L3+A*(L2+A*(L1+L0*A))) 292 __ASM_EMIT("vadd.f32 q9, q9, q13") 293 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 294 __ASM_EMIT("vmul.f32 q9, q9, q1") 295 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 296 __ASM_EMIT("vadd.f32 q9, q9, q14") 297 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L7, q13 = L8, fptr += 8 298 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 299 __ASM_EMIT("vmul.f32 q9, q9, q1") 300 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 301 __ASM_EMIT("vadd.f32 q9, q9, q15") 302 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 303 __ASM_EMIT("vmul.f32 q9, q9, q1") 304 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 305 __ASM_EMIT("vadd.f32 q9, q9, q12") 306 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]") // q14 = L9, q15 = (LXE + LN2), fptr += 8 307 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 308 __ASM_EMIT("vmul.f32 q9, q9, q1") 309 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 310 __ASM_EMIT("vadd.f32 q9, q9, q13") 311 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 312 __ASM_EMIT("vmul.f32 q9, q9, q1") 313 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 314 __ASM_EMIT("vadd.f32 q9, q9, q14") 315 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 316 __ASM_EMIT("vmul.f32 q9, q9, q1") 317 __ASM_EMIT("sub %[fptr], $0xd0") // fptr -= 52 318 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 319 __ASM_EMIT("vmul.f32 q9, q9, q1") 320 __ASM_EMIT("vmla.f32 q8, q4, q15") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 321 __ASM_EMIT("vmla.f32 q9, q5, q15") 322 __ASM_EMIT("vadd.f32 q8, q8, q0") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A 323 __ASM_EMIT("vadd.f32 q9, q9, q1") 324 // Apply values to axes, q0 = log(abs(v*zero)) 325 __ASM_EMIT("vld1.32 {q4-q5}, [%[x]]") // q4 = x, q5 = x 326 __ASM_EMIT("vld1.32 {q12-q13}, [%[params]]") // q12 = zero, q13 = norm_x 327 __ASM_EMIT("vmla.f32 q4, q8, q13") // q4 = x + log(abs(v*zero)) * norm_x 328 __ASM_EMIT("vmla.f32 q5, q9, q13") 329 __ASM_EMIT("sub %[count], $8") 330 __ASM_EMIT("vst1.32 {q4-q5}, [%[x]]!") // x += 8 331 332 // Do x4 block 333 __ASM_EMIT("4:") 334 __ASM_EMIT("adds %[count], $4") 335 __ASM_EMIT("blt 6f") 336 337 __ASM_EMIT("vld1.32 {q4}, [%[v]]!") // q4 = v, v += 4 338 __ASM_EMIT("vld1.32 {q12}, [%[fptr]]!") // q12 = X_AMP, fptr += 4 339 __ASM_EMIT("vabs.f32 q4, q4") // q4 = abs(v) 340 __ASM_EMIT("vld1.32 {q13}, [%[params]]") // q13 = zero, params += 4 341 __ASM_EMIT("vmax.f32 q4, q12") // q4 = max(X_AMP, abs(v)), ignores denormalized values 342 __ASM_EMIT("vmul.f32 q0, q4, q13") // q0 = max(X_AMP, abs(v)) * zero 343 // Step 2: parse float value 344 __ASM_EMIT("vld1.32 {q12-q13}, [%[iptr]]") // q12 = MANT_MASK, q13 = FRAC_SUB = 127 345 __ASM_EMIT("vshr.u32 q4, q0, $23") // q4 = frac(v) 346 __ASM_EMIT("vand.u32 q8, q0, q12") // q8 = mant(v) 347 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8 348 __ASM_EMIT("vsub.i32 q4, q4, q13") // q4 = frac(v) - 127 349 __ASM_EMIT("vorr.i32 q8, q8, q14") // q8 = V = mant(v)+0.5 350 __ASM_EMIT("vcvt.f32.s32 q4, q4") // q4 = E = float(frac(v)-127) 351 // Prepare logarithm approximation calculations 352 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = 1.0, q13 = L0 , fptr += 4 353 __ASM_EMIT("vclt.f32 q0, q8, q15") // q0 = [ V < sqrt(1/2) ] 354 __ASM_EMIT("vand.u32 q0, q0, q8") // q0 = V & [ V < sqrt(1/2) ] 355 __ASM_EMIT("vadd.f32 q0, q0, q8") // q0 = V + V * [ V < sqrt(1/2) ] 356 __ASM_EMIT("vclt.f32 q8, q8, q15") // q8 = [ V < sqrt(1/2) ] 357 __ASM_EMIT("vsub.f32 q0, q0, q12") // q0 = A = V + V & [ V < sqrt(1/2) ] - 1.0 358 __ASM_EMIT("vbic.u32 q8, q12, q8") // q8 = 1.0 & [ V >= sqrt(1/2) ] 359 __ASM_EMIT("vadd.f32 q4, q4, q8") // q4 = B = E + 1.0 & [ V >= sqrt(1/2) ] 360 // Calculate logarithmic values 361 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L1, q15 = L2, fptr += 8 362 __ASM_EMIT("vmul.f32 q8, q0, q13") // q8 = L0*A 363 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L1+L0*A 364 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L3, q13 = L4, fptr += 8 365 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L1+L0*A) 366 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L2+A*(L1+L0*A) 367 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L2+A*(L1+L0*A)) 368 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L3+A*(L2+A*(L1+L0*A)) 369 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L5, q15 = L6, fptr += 8 370 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L3+A*(L2+A*(L1+L0*A))) 371 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L4+A*(L3+A*(L2+A*(L1+L0*A))) 372 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 373 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 374 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L7, q13 = L8, fptr += 8 375 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 376 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 377 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 378 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 379 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]") // q14 = L9, q15 = (LXE + LN2), fptr += 8 380 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 381 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 382 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 383 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 384 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 385 __ASM_EMIT("sub %[fptr], $0xd0") // fptr -= 52 386 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 387 __ASM_EMIT("vmla.f32 q8, q4, q15") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 388 __ASM_EMIT("vadd.f32 q8, q8, q0") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A 389 // Apply values to axes, q0 = log(abs(v*zero)) 390 __ASM_EMIT("vld1.32 {q4}, [%[x]]") // q4 = x 391 __ASM_EMIT("vld1.32 {q12-q13}, [%[params]]") // q12 = zero, q13 = norm_x 392 __ASM_EMIT("vmla.f32 q4, q8, q13") // q4 = x + log(abs(v*zero)) * norm_x 393 __ASM_EMIT("sub %[count], $4") 394 __ASM_EMIT("vst1.32 {q4}, [%[x]]!") // x += 4 395 396 // Do x1 blocks 397 __ASM_EMIT("6:") 398 __ASM_EMIT("adds %[count], $3") 399 __ASM_EMIT("blt 8f") 400 401 __ASM_EMIT("7:") 402 __ASM_EMIT("vldm %[v]!, {s8}") // d4 = v, v += 4 403 __ASM_EMIT("vld1.32 {q6}, [%[fptr]]!") // d12 = X_AMP, fptr += 4 404 __ASM_EMIT("vabs.f32 d4, d4") // d4 = abs(v) 405 __ASM_EMIT("vld1.32 {q7}, [%[params]]") // d14 = zero, params += 4 406 __ASM_EMIT("vmax.f32 d4, d12") // d4 = max(X_AMP, abs(v)), ignores denormalized values 407 __ASM_EMIT("vmul.f32 d0, d4, d14") // d0 = max(X_AMP, abs(v)) * zero 408 // Step 2: parse float value 409 __ASM_EMIT("vld1.32 {q6-q7}, [%[iptr]]") // d12 = MANT_MASK, d14 = FRAC_SUB = 127 410 __ASM_EMIT("vshr.u32 d4, d0, $23") // d4 = frac(v) 411 __ASM_EMIT("vand.u32 d8, d0, d12") // d8 = mant(v) 412 __ASM_EMIT("vld1.32 {q8-q9}, [%[fptr]]!") // d16 = 0.5f, d18 = sqrt(1/2), fptr += 8 413 __ASM_EMIT("vsub.i32 d4, d4, d14") // d4 = frac(v) - 127 414 __ASM_EMIT("vorr.i32 d8, d8, d16") // d8 = V = mant(v)+0.5 415 __ASM_EMIT("vcvt.f32.s32 d4, d4") // d4 = E = float(frac(v)-127) 416 // Prepare logarithm approximation calculations 417 __ASM_EMIT("vld1.32 {q6-q7}, [%[fptr]]!") // d12 = 1.0, d14 = L0 , fptr += 4 418 __ASM_EMIT("vclt.f32 d0, d8, d18") // d0 = [ V < sqrt(1/2) ] 419 __ASM_EMIT("vand.u32 d0, d0, d8") // d0 = V & [ V < sqrt(1/2) ] 420 __ASM_EMIT("vadd.f32 d0, d0, d8") // d0 = V + V & [ V < sqrt(1/2) ] 421 __ASM_EMIT("vclt.f32 d8, d8, d18") // d8 = [ V < sqrt(1/2) ] 422 __ASM_EMIT("vsub.f32 d0, d0, d12") // d0 = A = V + V & [ V < sqrt(1/2) ] - 1.0 423 __ASM_EMIT("vbic.u32 d8, d12, d8") // d8 = 1.0 & [ V >= sqrt(1/2) ] 424 __ASM_EMIT("vadd.f32 d4, d4, d8") // d4 = B = E + 1.0 & [ V >= sqrt(1/2) ] 425 // Calculate logarithmic values 426 __ASM_EMIT("vld1.32 {q8-q9}, [%[fptr]]!") // d16 = L1, d18 = L2, fptr += 8 427 __ASM_EMIT("vmul.f32 d8, d0, d14") // d8 = L0*A 428 __ASM_EMIT("vadd.f32 d8, d8, d16") // d8 = L1+L0*A 429 __ASM_EMIT("vld1.32 {q6-q7}, [%[fptr]]!") // d12 = L3, d14 = L4, fptr += 8 430 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L1+L0*A) 431 __ASM_EMIT("vadd.f32 d8, d8, d18") // d8 = L2+A*(L1+L0*A) 432 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L2+A*(L1+L0*A)) 433 __ASM_EMIT("vadd.f32 d8, d8, d12") // d8 = L3+A*(L2+A*(L1+L0*A)) 434 __ASM_EMIT("vld1.32 {q8-q9}, [%[fptr]]!") // d16 = L5, d18 = L6, fptr += 8 435 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L3+A*(L2+A*(L1+L0*A))) 436 __ASM_EMIT("vadd.f32 d8, d8, d14") // d8 = L4+A*(L3+A*(L2+A*(L1+L0*A))) 437 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 438 __ASM_EMIT("vadd.f32 d8, d8, d16") // d8 = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 439 __ASM_EMIT("vld1.32 {q6-q7}, [%[fptr]]!") // d12 = L7, d14 = L8, fptr += 8 440 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 441 __ASM_EMIT("vadd.f32 d8, d8, d18") // d8 = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 442 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 443 __ASM_EMIT("vadd.f32 d8, d8, d12") // d8 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 444 __ASM_EMIT("vld1.32 {q8-q9}, [%[fptr]]") // d16 = L9, d18 = (LXE + LN2), fptr += 8 445 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 446 __ASM_EMIT("vadd.f32 d8, d8, d14") // d8 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 447 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 448 __ASM_EMIT("vadd.f32 d8, d8, d16") // d8 = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 449 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 450 __ASM_EMIT("sub %[fptr], $0xd0") // fptr -= 52 451 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 452 __ASM_EMIT("vmla.f32 d8, d4, d18") // d8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 453 __ASM_EMIT("vadd.f32 d8, d8, d0") // d8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A 454 // Apply values to axes, d0 = log(abs(v*zero)) 455 __ASM_EMIT("vldm %[x], {s8}") // d4 = x 456 __ASM_EMIT("vld1.32 {q6-q7}, [%[params]]") // d12 = zero, d14 = norm_x 457 __ASM_EMIT("vmla.f32 d4, d8, d14") // d4 = x + log(abs(v*zero)) * norm_x 458 __ASM_EMIT("subs %[count], $1") 459 __ASM_EMIT("vstm %[x]!, {s8}") // x++ 460 __ASM_EMIT("bge 7b") 461 462 __ASM_EMIT("8:") 463 464 : [v] "+r" (v), [x] "+r" (x), 465 [count] "+r" (count), 466 [iptr] "+r" (iptr), [fptr] "+r" (fptr) 467 : [params] "r" (params) 468 : "cc", "memory", 469 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 470 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 471 ); 472 } 473 axis_apply_log2(float * x,float * y,const float * v,float zero,float norm_x,float norm_y,size_t count)474 void axis_apply_log2(float *x, float *y, const float *v, float zero, float norm_x, float norm_y, size_t count) 475 { 476 IF_ARCH_ARM( 477 float params[12] __lsp_aligned16; 478 params[0] = zero; 479 params[1] = norm_x; 480 params[2] = norm_y; 481 const uint32_t *iptr = &LOG_IARGS[4]; 482 const float *fptr = LOG_FARGS; 483 ); 484 485 //--------------------------------------------------------------- 486 // Prepare constants 487 ARCH_ARM_ASM 488 ( 489 __ASM_EMIT("vld1.32 {q0}, [%[params]]") 490 __ASM_EMIT("vdup.32 q3, d1[0]") // q3 = norm_y 491 __ASM_EMIT("vdup.32 q2, d0[1]") // q2 = norm_x 492 __ASM_EMIT("vdup.32 q0, d0[0]") // q0 = zero 493 __ASM_EMIT("vst1.32 {q0}, [%[params]]!") // params += 4 494 __ASM_EMIT("vst1.32 {q2-q3}, [%[params]]") 495 496 __ASM_EMIT("subs %[count], $16") 497 __ASM_EMIT("blo 2f") 498 499 // Do 16x blocks 500 __ASM_EMIT("1:") 501 __ASM_EMIT("vld1.32 {q4-q5}, [%[v]]!") // q4 = v, q5 = v, v += 8 502 __ASM_EMIT("sub %[params], $0x10") // params -= 4 503 __ASM_EMIT("vld1.32 {q6-q7}, [%[v]]!") 504 __ASM_EMIT("vld1.32 {q12}, [%[fptr]]!") // q12 = X_AMP, fptr += 4 505 __ASM_EMIT("vabs.f32 q4, q4") // q4 = abs(v) 506 __ASM_EMIT("vabs.f32 q5, q5") 507 __ASM_EMIT("vabs.f32 q6, q6") 508 __ASM_EMIT("vabs.f32 q7, q7") 509 __ASM_EMIT("vld1.32 {q13}, [%[params]]!") // q13 = zero, params += 4 510 __ASM_EMIT("vmax.f32 q4, q12") // q12 = max(X_AMP, abs(v)), ignores denormalized values 511 __ASM_EMIT("vmax.f32 q5, q12") 512 __ASM_EMIT("vmax.f32 q6, q12") 513 __ASM_EMIT("vmax.f32 q7, q12") 514 __ASM_EMIT("vmul.f32 q0, q4, q13") // q13 = max(X_AMP, abs(v)) * zero 515 __ASM_EMIT("vmul.f32 q1, q5, q13") 516 __ASM_EMIT("vmul.f32 q2, q6, q13") 517 __ASM_EMIT("vmul.f32 q3, q7, q13") 518 // Step 2: parse float value 519 __ASM_EMIT("vld1.32 {q12-q13}, [%[iptr]]") // q12 = MANT_MASK, q13 = FRAC_SUB = 127 520 __ASM_EMIT("vshr.u32 q4, q0, $23") // q4 = frac(v) 521 __ASM_EMIT("vshr.u32 q5, q1, $23") 522 __ASM_EMIT("vshr.u32 q6, q2, $23") 523 __ASM_EMIT("vshr.u32 q7, q3, $23") 524 __ASM_EMIT("vand.u32 q8, q0, q12") // q8 = mant(v) 525 __ASM_EMIT("vand.u32 q9, q1, q12") 526 __ASM_EMIT("vand.u32 q10, q2, q12") 527 __ASM_EMIT("vand.u32 q11, q3, q12") 528 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8 529 __ASM_EMIT("vsub.i32 q4, q4, q13") // q4 = frac(v) - 127 530 __ASM_EMIT("vsub.i32 q5, q5, q13") 531 __ASM_EMIT("vsub.i32 q6, q6, q13") 532 __ASM_EMIT("vsub.i32 q7, q7, q13") 533 __ASM_EMIT("vorr.i32 q8, q8, q14") // q8 = V = mant(v)+0.5 534 __ASM_EMIT("vorr.i32 q9, q9, q14") 535 __ASM_EMIT("vorr.i32 q10, q10, q14") 536 __ASM_EMIT("vorr.i32 q11, q11, q14") 537 __ASM_EMIT("vcvt.f32.s32 q4, q4") // q4 = E = float(frac(v)-127) 538 __ASM_EMIT("vcvt.f32.s32 q5, q5") 539 __ASM_EMIT("vcvt.f32.s32 q6, q6") 540 __ASM_EMIT("vcvt.f32.s32 q7, q7") 541 // Prepare logarithm approximation calculations 542 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = 1.0, q13 = L0 , fptr += 4 543 __ASM_EMIT("vclt.f32 q0, q8, q15") // q0 = [ V < sqrt(1/2) ] 544 __ASM_EMIT("vclt.f32 q1, q9, q15") 545 __ASM_EMIT("vclt.f32 q2, q10, q15") 546 __ASM_EMIT("vclt.f32 q3, q11, q15") 547 __ASM_EMIT("vand.u32 q0, q0, q8") // q0 = V * [ V < sqrt(1/2) ] 548 __ASM_EMIT("vand.u32 q1, q1, q9") 549 __ASM_EMIT("vand.u32 q2, q2, q10") 550 __ASM_EMIT("vand.u32 q3, q3, q11") 551 __ASM_EMIT("vadd.f32 q0, q0, q8") // q0 = V + V * [ V < sqrt(1/2) ] 552 __ASM_EMIT("vadd.f32 q1, q1, q9") 553 __ASM_EMIT("vadd.f32 q2, q2, q10") 554 __ASM_EMIT("vadd.f32 q3, q3, q11") 555 __ASM_EMIT("vclt.f32 q8, q8, q15") // q8 = [ V < sqrt(1/2) ] 556 __ASM_EMIT("vclt.f32 q9, q9, q15") 557 __ASM_EMIT("vclt.f32 q10, q10, q15") 558 __ASM_EMIT("vclt.f32 q11, q11, q15") 559 __ASM_EMIT("vsub.f32 q0, q0, q12") // q0 = A = V + V & [ V < sqrt(1/2) ] - 1.0 560 __ASM_EMIT("vsub.f32 q1, q1, q12") 561 __ASM_EMIT("vsub.f32 q2, q2, q12") 562 __ASM_EMIT("vsub.f32 q3, q3, q12") 563 __ASM_EMIT("vbic.u32 q8, q12, q8") // q8 = 1.0 & [ V >= sqrt(1/2) ] 564 __ASM_EMIT("vbic.u32 q9, q12, q9") 565 __ASM_EMIT("vbic.u32 q10, q12, q10") 566 __ASM_EMIT("vbic.u32 q11, q12, q11") 567 __ASM_EMIT("vadd.f32 q4, q4, q8") // q4 = B = E + 1.0 & [ V >= sqrt(1/2) ] 568 __ASM_EMIT("vadd.f32 q5, q5, q9") 569 __ASM_EMIT("vadd.f32 q6, q6, q10") 570 __ASM_EMIT("vadd.f32 q7, q7, q11") 571 // Calculate logarithmic values 572 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L1, q15 = L2, fptr += 8 573 __ASM_EMIT("vmul.f32 q8, q0, q13") // q8 = L0*A 574 __ASM_EMIT("vmul.f32 q9, q1, q13") 575 __ASM_EMIT("vmul.f32 q10, q2, q13") 576 __ASM_EMIT("vmul.f32 q11, q3, q13") 577 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L1+L0*A 578 __ASM_EMIT("vadd.f32 q9, q9, q14") 579 __ASM_EMIT("vadd.f32 q10, q10, q14") 580 __ASM_EMIT("vadd.f32 q11, q11, q14") 581 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L3, q13 = L4, fptr += 8 582 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L1+L0*A) 583 __ASM_EMIT("vmul.f32 q9, q9, q1") 584 __ASM_EMIT("vmul.f32 q10, q10, q2") 585 __ASM_EMIT("vmul.f32 q11, q11, q3") 586 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L2+A*(L1+L0*A) 587 __ASM_EMIT("vadd.f32 q9, q9, q15") 588 __ASM_EMIT("vadd.f32 q10, q10, q15") 589 __ASM_EMIT("vadd.f32 q11, q11, q15") 590 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L2+A*(L1+L0*A)) 591 __ASM_EMIT("vmul.f32 q9, q9, q1") 592 __ASM_EMIT("vmul.f32 q10, q10, q2") 593 __ASM_EMIT("vmul.f32 q11, q11, q3") 594 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L3+A*(L2+A*(L1+L0*A)) 595 __ASM_EMIT("vadd.f32 q9, q9, q12") 596 __ASM_EMIT("vadd.f32 q10, q10, q12") 597 __ASM_EMIT("vadd.f32 q11, q11, q12") 598 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L5, q15 = L6, fptr += 8 599 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L3+A*(L2+A*(L1+L0*A))) 600 __ASM_EMIT("vmul.f32 q9, q9, q1") 601 __ASM_EMIT("vmul.f32 q10, q10, q2") 602 __ASM_EMIT("vmul.f32 q11, q11, q3") 603 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L4+A*(L3+A*(L2+A*(L1+L0*A))) 604 __ASM_EMIT("vadd.f32 q9, q9, q13") 605 __ASM_EMIT("vadd.f32 q10, q10, q13") 606 __ASM_EMIT("vadd.f32 q11, q11, q13") 607 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 608 __ASM_EMIT("vmul.f32 q9, q9, q1") 609 __ASM_EMIT("vmul.f32 q10, q10, q2") 610 __ASM_EMIT("vmul.f32 q11, q11, q3") 611 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 612 __ASM_EMIT("vadd.f32 q9, q9, q14") 613 __ASM_EMIT("vadd.f32 q10, q10, q14") 614 __ASM_EMIT("vadd.f32 q11, q11, q14") 615 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L7, q13 = L8, fptr += 8 616 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 617 __ASM_EMIT("vmul.f32 q9, q9, q1") 618 __ASM_EMIT("vmul.f32 q10, q10, q2") 619 __ASM_EMIT("vmul.f32 q11, q11, q3") 620 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 621 __ASM_EMIT("vadd.f32 q9, q9, q15") 622 __ASM_EMIT("vadd.f32 q10, q10, q15") 623 __ASM_EMIT("vadd.f32 q11, q11, q15") 624 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 625 __ASM_EMIT("vmul.f32 q9, q9, q1") 626 __ASM_EMIT("vmul.f32 q10, q10, q2") 627 __ASM_EMIT("vmul.f32 q11, q11, q3") 628 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 629 __ASM_EMIT("vadd.f32 q9, q9, q12") 630 __ASM_EMIT("vadd.f32 q10, q10, q12") 631 __ASM_EMIT("vadd.f32 q11, q11, q12") 632 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]") // q14 = L9, q15 = (LXE + LN2), fptr += 8 633 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 634 __ASM_EMIT("vmul.f32 q9, q9, q1") 635 __ASM_EMIT("vmul.f32 q10, q10, q2") 636 __ASM_EMIT("vmul.f32 q11, q11, q3") 637 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 638 __ASM_EMIT("vadd.f32 q9, q9, q13") 639 __ASM_EMIT("vadd.f32 q10, q10, q13") 640 __ASM_EMIT("vadd.f32 q11, q11, q13") 641 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 642 __ASM_EMIT("vmul.f32 q9, q9, q1") 643 __ASM_EMIT("vmul.f32 q10, q10, q2") 644 __ASM_EMIT("vmul.f32 q11, q11, q3") 645 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 646 __ASM_EMIT("vadd.f32 q9, q9, q14") 647 __ASM_EMIT("vadd.f32 q10, q10, q14") 648 __ASM_EMIT("vadd.f32 q11, q11, q14") 649 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 650 __ASM_EMIT("vmul.f32 q9, q9, q1") 651 __ASM_EMIT("vmul.f32 q10, q10, q2") 652 __ASM_EMIT("vmul.f32 q11, q11, q3") 653 __ASM_EMIT("sub %[fptr], $0xd0") // fptr -= 52 654 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 655 __ASM_EMIT("vmul.f32 q9, q9, q1") 656 __ASM_EMIT("vmul.f32 q10, q10, q2") 657 __ASM_EMIT("vmul.f32 q11, q11, q3") 658 __ASM_EMIT("vmla.f32 q8, q4, q15") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 659 __ASM_EMIT("vmla.f32 q9, q5, q15") 660 __ASM_EMIT("vmla.f32 q10, q6, q15") 661 __ASM_EMIT("vmla.f32 q11, q7, q15") 662 __ASM_EMIT("vadd.f32 q8, q8, q0") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A 663 __ASM_EMIT("vadd.f32 q9, q9, q1") 664 __ASM_EMIT("vadd.f32 q10, q10, q2") 665 __ASM_EMIT("vadd.f32 q11, q11, q3") 666 // Apply values to axes, q0 = log(abs(v*zero)) 667 __ASM_EMIT("vldm %[x], {q4-q7}") // q4 = x, q5 = x, q6 = x, q7 = x 668 __ASM_EMIT("vldm %[y], {q0-q3}") // q0 = y, q1 = y, q2 = y, q3 = y 669 __ASM_EMIT("vld1.32 {q12-q13}, [%[params]]") // q12 = norm_x, q13 = norm_y 670 __ASM_EMIT("vmla.f32 q4, q8, q12") // q4 = x + log(abs(v*zero)) * norm_x 671 __ASM_EMIT("vmla.f32 q5, q9, q12") 672 __ASM_EMIT("vmla.f32 q6, q10, q12") 673 __ASM_EMIT("vmla.f32 q7, q11, q12") 674 __ASM_EMIT("vmla.f32 q0, q8, q13") // q0 = y + log(abs(v*zero)) * norm_y 675 __ASM_EMIT("vmla.f32 q1, q9, q13") 676 __ASM_EMIT("vmla.f32 q2, q10, q13") 677 __ASM_EMIT("vmla.f32 q3, q11, q13") 678 __ASM_EMIT("subs %[count], $16") 679 __ASM_EMIT("vstm %[x]!, {q4-q7}") // x += 16 680 __ASM_EMIT("vstm %[y]!, {q0-q3}") // y += 16 681 __ASM_EMIT("bge 1b") 682 683 // Do 8x block 684 __ASM_EMIT("2:") 685 __ASM_EMIT("adds %[count], $8") 686 __ASM_EMIT("blt 4f") 687 688 __ASM_EMIT("sub %[params], $0x10") // params -= 4 689 __ASM_EMIT("vld1.32 {q4-q5}, [%[v]]!") // q4 = v, q5 = v, v += 8 690 __ASM_EMIT("vld1.32 {q12}, [%[fptr]]!") // q12 = X_AMP, fptr += 4 691 __ASM_EMIT("vabs.f32 q4, q4") // q4 = abs(v) 692 __ASM_EMIT("vabs.f32 q5, q5") 693 __ASM_EMIT("vld1.32 {q13}, [%[params]]!") // q13 = zero, params += 4 694 __ASM_EMIT("vmax.f32 q4, q12") // q12 = max(X_AMP, abs(v)), ignores denormalized values 695 __ASM_EMIT("vmax.f32 q5, q12") 696 __ASM_EMIT("vmul.f32 q0, q4, q13") // q13 = max(X_AMP, abs(v)) * zero 697 __ASM_EMIT("vmul.f32 q1, q5, q13") 698 // Step 2: parse float value 699 __ASM_EMIT("vld1.32 {q12-q13}, [%[iptr]]") // q12 = MANT_MASK, q13 = FRAC_SUB = 127 700 __ASM_EMIT("vshr.u32 q4, q0, $23") // q4 = frac(v) 701 __ASM_EMIT("vshr.u32 q5, q1, $23") 702 __ASM_EMIT("vand.u32 q8, q0, q12") // q8 = mant(v) 703 __ASM_EMIT("vand.u32 q9, q1, q12") 704 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8 705 __ASM_EMIT("vsub.i32 q4, q4, q13") // q4 = frac(v) - 127 706 __ASM_EMIT("vsub.i32 q5, q5, q13") 707 __ASM_EMIT("vorr.i32 q8, q8, q14") // q8 = V = mant(v)+0.5 708 __ASM_EMIT("vorr.i32 q9, q9, q14") 709 __ASM_EMIT("vcvt.f32.s32 q4, q4") // q4 = E = float(frac(v)-127) 710 __ASM_EMIT("vcvt.f32.s32 q5, q5") 711 // Prepare logarithm approximation calculations 712 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = 1.0, q13 = L0 , fptr += 4 713 __ASM_EMIT("vclt.f32 q0, q8, q15") // q0 = [ V < sqrt(1/2) ] 714 __ASM_EMIT("vclt.f32 q1, q9, q15") 715 __ASM_EMIT("vand.u32 q0, q0, q8") // q0 = V & [ V < sqrt(1/2) ] 716 __ASM_EMIT("vand.u32 q1, q1, q9") 717 __ASM_EMIT("vadd.f32 q0, q0, q8") // q0 = V + V & [ V < sqrt(1/2) ] 718 __ASM_EMIT("vadd.f32 q1, q1, q9") 719 __ASM_EMIT("vclt.f32 q8, q8, q15") // q8 = [ V < sqrt(1/2) ] 720 __ASM_EMIT("vclt.f32 q9, q9, q15") 721 __ASM_EMIT("vsub.f32 q0, q0, q12") // q0 = A = V + V & [ V < sqrt(1/2) ] - 1.0 722 __ASM_EMIT("vsub.f32 q1, q1, q12") 723 __ASM_EMIT("vbic.u32 q8, q12, q8") // q8 = 1.0 & [ V >= sqrt(1/2) ] 724 __ASM_EMIT("vbic.u32 q9, q12, q9") 725 __ASM_EMIT("vadd.f32 q4, q4, q8") // q4 = B = E + 1.0 & [ V >= sqrt(1/2) ] 726 __ASM_EMIT("vadd.f32 q5, q5, q9") 727 // Calculate logarithmic values 728 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L1, q15 = L2, fptr += 8 729 __ASM_EMIT("vmul.f32 q8, q0, q13") // q8 = L0*A 730 __ASM_EMIT("vmul.f32 q9, q1, q13") 731 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L1+L0*A 732 __ASM_EMIT("vadd.f32 q9, q9, q14") 733 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L3, q13 = L4, fptr += 8 734 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L1+L0*A) 735 __ASM_EMIT("vmul.f32 q9, q9, q1") 736 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L2+A*(L1+L0*A) 737 __ASM_EMIT("vadd.f32 q9, q9, q15") 738 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L2+A*(L1+L0*A)) 739 __ASM_EMIT("vmul.f32 q9, q9, q1") 740 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L3+A*(L2+A*(L1+L0*A)) 741 __ASM_EMIT("vadd.f32 q9, q9, q12") 742 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L5, q15 = L6, fptr += 8 743 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L3+A*(L2+A*(L1+L0*A))) 744 __ASM_EMIT("vmul.f32 q9, q9, q1") 745 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L4+A*(L3+A*(L2+A*(L1+L0*A))) 746 __ASM_EMIT("vadd.f32 q9, q9, q13") 747 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 748 __ASM_EMIT("vmul.f32 q9, q9, q1") 749 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 750 __ASM_EMIT("vadd.f32 q9, q9, q14") 751 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L7, q13 = L8, fptr += 8 752 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 753 __ASM_EMIT("vmul.f32 q9, q9, q1") 754 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 755 __ASM_EMIT("vadd.f32 q9, q9, q15") 756 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 757 __ASM_EMIT("vmul.f32 q9, q9, q1") 758 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 759 __ASM_EMIT("vadd.f32 q9, q9, q12") 760 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]") // q14 = L9, q15 = (LXE + LN2), fptr += 8 761 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 762 __ASM_EMIT("vmul.f32 q9, q9, q1") 763 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 764 __ASM_EMIT("vadd.f32 q9, q9, q13") 765 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 766 __ASM_EMIT("vmul.f32 q9, q9, q1") 767 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 768 __ASM_EMIT("vadd.f32 q9, q9, q14") 769 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 770 __ASM_EMIT("vmul.f32 q9, q9, q1") 771 __ASM_EMIT("sub %[fptr], $0xd0") // fptr -= 52 772 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 773 __ASM_EMIT("vmul.f32 q9, q9, q1") 774 __ASM_EMIT("vmla.f32 q8, q4, q15") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 775 __ASM_EMIT("vmla.f32 q9, q5, q15") 776 __ASM_EMIT("vadd.f32 q8, q8, q0") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A 777 __ASM_EMIT("vadd.f32 q9, q9, q1") 778 // Apply values to axes, q0 = log(abs(v*zero)) 779 __ASM_EMIT("vld1.32 {q4-q5}, [%[x]]") // q4 = x, q5 = x 780 __ASM_EMIT("vld1.32 {q0-q1}, [%[y]]") // q0 = y, q1 = y 781 __ASM_EMIT("vld1.32 {q12-q13}, [%[params]]") // q12 = norm_x, q13 = norm_y 782 __ASM_EMIT("vmla.f32 q4, q8, q12") // q4 = x + log(abs(v*zero)) * norm_x 783 __ASM_EMIT("vmla.f32 q5, q9, q12") 784 __ASM_EMIT("vmla.f32 q0, q8, q13") // q0 = y + log(abs(v*zero)) * norm_y 785 __ASM_EMIT("vmla.f32 q1, q9, q13") 786 __ASM_EMIT("sub %[count], $8") 787 __ASM_EMIT("vst1.32 {q4-q5}, [%[x]]!") // x += 8 788 __ASM_EMIT("vst1.32 {q0-q1}, [%[y]]!") // y += 8 789 790 // Do x4 block 791 __ASM_EMIT("4:") 792 __ASM_EMIT("adds %[count], $4") 793 __ASM_EMIT("blt 6f") 794 795 __ASM_EMIT("sub %[params], $0x10") // params -= 4 796 __ASM_EMIT("vld1.32 {q4}, [%[v]]!") // q4 = v, v += 4 797 __ASM_EMIT("vld1.32 {q12}, [%[fptr]]!") // q12 = X_AMP, fptr += 4 798 __ASM_EMIT("vabs.f32 q4, q4") // q4 = abs(v) 799 __ASM_EMIT("vld1.32 {q13}, [%[params]]!") // q13 = zero, params += 4 800 __ASM_EMIT("vmax.f32 q4, q12") // q4 = max(X_AMP, abs(v)), ignores denormalized values 801 __ASM_EMIT("vmul.f32 q0, q4, q13") // q0 = max(X_AMP, abs(v)) * zero 802 // Step 2: parse float value 803 __ASM_EMIT("vld1.32 {q12-q13}, [%[iptr]]") // q12 = MANT_MASK, q13 = FRAC_SUB = 127 804 __ASM_EMIT("vshr.u32 q4, q0, $23") // q4 = frac(v) 805 __ASM_EMIT("vand.u32 q8, q0, q12") // q8 = mant(v) 806 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = 0.5f, q15 = sqrt(1/2), fptr += 8 807 __ASM_EMIT("vsub.i32 q4, q4, q13") // q4 = frac(v) - 127 808 __ASM_EMIT("vorr.i32 q8, q8, q14") // q8 = V = mant(v)+0.5 809 __ASM_EMIT("vcvt.f32.s32 q4, q4") // q4 = E = float(frac(v)-127) 810 // Prepare logarithm approximation calculations 811 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = 1.0, q13 = L0 , fptr += 4 812 __ASM_EMIT("vclt.f32 q0, q8, q15") // q0 = [ V < sqrt(1/2) ] 813 __ASM_EMIT("vand.u32 q0, q0, q8") // q0 = V & [ V < sqrt(1/2) ] 814 __ASM_EMIT("vadd.f32 q0, q0, q8") // q0 = V + V * [ V < sqrt(1/2) ] 815 __ASM_EMIT("vclt.f32 q8, q8, q15") // q8 = [ V < sqrt(1/2) ] 816 __ASM_EMIT("vsub.f32 q0, q0, q12") // q0 = A = V + V & [ V < sqrt(1/2) ] - 1.0 817 __ASM_EMIT("vbic.u32 q8, q12, q8") // q8 = 1.0 & [ V >= sqrt(1/2) ] 818 __ASM_EMIT("vadd.f32 q4, q4, q8") // q4 = B = E + 1.0 & [ V >= sqrt(1/2) ] 819 // Calculate logarithmic values 820 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L1, q15 = L2, fptr += 8 821 __ASM_EMIT("vmul.f32 q8, q0, q13") // q8 = L0*A 822 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L1+L0*A 823 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L3, q13 = L4, fptr += 8 824 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L1+L0*A) 825 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L2+A*(L1+L0*A) 826 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L2+A*(L1+L0*A)) 827 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L3+A*(L2+A*(L1+L0*A)) 828 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]!") // q14 = L5, q15 = L6, fptr += 8 829 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L3+A*(L2+A*(L1+L0*A))) 830 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L4+A*(L3+A*(L2+A*(L1+L0*A))) 831 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 832 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 833 __ASM_EMIT("vld1.32 {q12-q13}, [%[fptr]]!") // q12 = L7, q13 = L8, fptr += 8 834 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 835 __ASM_EMIT("vadd.f32 q8, q8, q15") // q8 = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 836 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 837 __ASM_EMIT("vadd.f32 q8, q8, q12") // q8 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 838 __ASM_EMIT("vld1.32 {q14-q15}, [%[fptr]]") // q14 = L9, q15 = (LXE + LN2), fptr += 8 839 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 840 __ASM_EMIT("vadd.f32 q8, q8, q13") // q8 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 841 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 842 __ASM_EMIT("vadd.f32 q8, q8, q14") // q8 = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 843 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 844 __ASM_EMIT("sub %[fptr], $0xd0") // fptr -= 52 845 __ASM_EMIT("vmul.f32 q8, q8, q0") // q8 = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 846 __ASM_EMIT("vmla.f32 q8, q4, q15") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 847 __ASM_EMIT("vadd.f32 q8, q8, q0") // q8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A 848 // Apply values to axes, q0 = log(abs(v*zero)) 849 __ASM_EMIT("vld1.32 {q4}, [%[x]]") // q4 = x 850 __ASM_EMIT("vld1.32 {q0}, [%[y]]") // q0 = y 851 __ASM_EMIT("vld1.32 {q12-q13}, [%[params]]") // q12 = norm_x, q13 = norm_y 852 __ASM_EMIT("vmla.f32 q4, q8, q12") // q4 = x + log(abs(v*zero)) * norm_x 853 __ASM_EMIT("vmla.f32 q0, q8, q13") // q0 = y + log(abs(v*zero)) * norm_y 854 __ASM_EMIT("sub %[count], $4") 855 __ASM_EMIT("vst1.32 {q4}, [%[x]]!") // x += 4 856 __ASM_EMIT("vst1.32 {q0}, [%[y]]!") // y += 4 857 858 // Do x1 block 859 __ASM_EMIT("6:") 860 __ASM_EMIT("adds %[count], $3") 861 __ASM_EMIT("blt 8f") 862 863 __ASM_EMIT("7:") 864 __ASM_EMIT("sub %[params], $0x10") // params -= 4 865 __ASM_EMIT("vldm %[v]!, {s8}") // d4 = v, v += 4 866 __ASM_EMIT("vld1.32 {q6}, [%[fptr]]!") // d12 = X_AMP, fptr += 4 867 __ASM_EMIT("vabs.f32 d4, d4") // d4 = abs(v) 868 __ASM_EMIT("vld1.32 {q7}, [%[params]]!") // d14 = zero, params += 4 869 __ASM_EMIT("vmax.f32 d4, d12") // d4 = max(X_AMP, abs(v)), ignores denormalized values 870 __ASM_EMIT("vmul.f32 d0, d4, d14") // d0 = max(X_AMP, abs(v)) * zero 871 // Step 2: parse float value 872 __ASM_EMIT("vld1.32 {q6-q7}, [%[iptr]]") // d12 = MANT_MASK, d14 = FRAC_SUB = 127 873 __ASM_EMIT("vshr.u32 d4, d0, $23") // d4 = frac(v) 874 __ASM_EMIT("vand.u32 d8, d0, d12") // d8 = mant(v) 875 __ASM_EMIT("vld1.32 {q8-q9}, [%[fptr]]!") // d16 = 0.5f, d18 = sqrt(1/2), fptr += 8 876 __ASM_EMIT("vsub.i32 d4, d4, d14") // d4 = frac(v) - 127 877 __ASM_EMIT("vorr.i32 d8, d8, d16") // d8 = V = mant(v)+0.5 878 __ASM_EMIT("vcvt.f32.s32 d4, d4") // d4 = E = float(frac(v)-127) 879 // Prepare logarithm approximation calculations 880 __ASM_EMIT("vld1.32 {q6-q7}, [%[fptr]]!") // d12 = 1.0, d14 = L0 , fptr += 4 881 __ASM_EMIT("vclt.f32 d0, d8, d18") // d0 = [ V < sqrt(1/2) ] 882 __ASM_EMIT("vand.u32 d0, d0, d8") // d0 = V & [ V < sqrt(1/2) ] 883 __ASM_EMIT("vadd.f32 d0, d0, d8") // d0 = V + V & [ V < sqrt(1/2) ] 884 __ASM_EMIT("vclt.f32 d8, d8, d18") // d8 = [ V < sqrt(1/2) ] 885 __ASM_EMIT("vsub.f32 d0, d0, d12") // d0 = A = V + V & [ V < sqrt(1/2) ] - 1.0 886 __ASM_EMIT("vbic.u32 d8, d12, d8") // d8 = 1.0 & [ V >= sqrt(1/2) ] 887 __ASM_EMIT("vadd.f32 d4, d4, d8") // d4 = B = E + 1.0 & [ V >= sqrt(1/2) ] 888 // Calculate logarithmic values 889 __ASM_EMIT("vld1.32 {q8-q9}, [%[fptr]]!") // d16 = L1, d18 = L2, fptr += 8 890 __ASM_EMIT("vmul.f32 d8, d0, d14") // d8 = L0*A 891 __ASM_EMIT("vadd.f32 d8, d8, d16") // d8 = L1+L0*A 892 __ASM_EMIT("vld1.32 {q6-q7}, [%[fptr]]!") // d12 = L3, d14 = L4, fptr += 8 893 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L1+L0*A) 894 __ASM_EMIT("vadd.f32 d8, d8, d18") // d8 = L2+A*(L1+L0*A) 895 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L2+A*(L1+L0*A)) 896 __ASM_EMIT("vadd.f32 d8, d8, d12") // d8 = L3+A*(L2+A*(L1+L0*A)) 897 __ASM_EMIT("vld1.32 {q8-q9}, [%[fptr]]!") // d16 = L5, d18 = L6, fptr += 8 898 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L3+A*(L2+A*(L1+L0*A))) 899 __ASM_EMIT("vadd.f32 d8, d8, d14") // d8 = L4+A*(L3+A*(L2+A*(L1+L0*A))) 900 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 901 __ASM_EMIT("vadd.f32 d8, d8, d16") // d8 = L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))) 902 __ASM_EMIT("vld1.32 {q6-q7}, [%[fptr]]!") // d12 = L7, d14 = L8, fptr += 8 903 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 904 __ASM_EMIT("vadd.f32 d8, d8, d18") // d8 = L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))) 905 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 906 __ASM_EMIT("vadd.f32 d8, d8, d12") // d8 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))) 907 __ASM_EMIT("vld1.32 {q8-q9}, [%[fptr]]") // d16 = L9, d18 = (LXE + LN2), fptr += 8 908 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 909 __ASM_EMIT("vadd.f32 d8, d8, d14") // d8 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))) 910 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 911 __ASM_EMIT("vadd.f32 d8, d8, d16") // d8 = L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A)))))))) 912 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 913 __ASM_EMIT("sub %[fptr], $0xd0") // fptr -= 52 914 __ASM_EMIT("vmul.f32 d8, d8, d0") // d8 = A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 915 __ASM_EMIT("vmla.f32 d8, d4, d18") // d8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) 916 __ASM_EMIT("vadd.f32 d8, d8, d0") // d8 = B*(LXE + LN2) + A*A*(L9+A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*(L2+A*(L1+L0*A))))))))) + A 917 // Apply values to axes, d0 = log(abs(v*zero)) 918 __ASM_EMIT("vldm %[x], {s8}") // d4 = x 919 __ASM_EMIT("vldm %[y], {s0}") // d0 = y 920 __ASM_EMIT("vld1.32 {q6-q7}, [%[params]]") // d12 = norm_x, d14 = norm_y 921 __ASM_EMIT("vmla.f32 d4, d8, d12") // d4 = x + log(abs(v*zero)) * norm_x 922 __ASM_EMIT("vmla.f32 d0, d8, d14") // d0 = y + log(abs(v*zero)) * norm_y 923 __ASM_EMIT("subs %[count], $1") 924 __ASM_EMIT("vstm %[x]!, {s8}") // x++ 925 __ASM_EMIT("vstm %[y]!, {s0}") // y++ 926 __ASM_EMIT("bge 7b") 927 928 __ASM_EMIT("8:") 929 930 : [v] "+r" (v), [x] "+r" (x) , [y] "+r" (y), 931 [count] "+r" (count), 932 [iptr] "+r" (iptr), [fptr] "+r" (fptr) 933 : [params] "r" (params) 934 : "cc", "memory", 935 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 936 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 937 ); 938 } 939 rgba32_to_bgra32(void * dst,const void * src,size_t count)940 void rgba32_to_bgra32(void *dst, const void *src, size_t count) 941 { 942 IF_ARCH_ARM( 943 uint32_t mask; 944 uint32_t t1, t2; 945 ); 946 947 ARCH_ARM_ASM( 948 // 64x blocks 949 __ASM_EMIT("subs %[count], $64") 950 __ASM_EMIT("blo 2f") 951 __ASM_EMIT("1:") 952 __ASM_EMIT("vld4.8 {q0-q1}, [%[src]]!") // d0 = R, d1 = G, d2 = B, d3 = A 953 __ASM_EMIT("vld4.8 {q2-q3}, [%[src]]!") 954 __ASM_EMIT("vswp d0, d2") 955 __ASM_EMIT("vld4.8 {q4-q5}, [%[src]]!") 956 __ASM_EMIT("vst4.8 {q0-q1}, [%[dst]]!") 957 __ASM_EMIT("vswp d4, d6") 958 __ASM_EMIT("vld4.8 {q6-q7}, [%[src]]!") 959 __ASM_EMIT("vst4.8 {q2-q3}, [%[dst]]!") 960 __ASM_EMIT("vswp d8, d10") 961 __ASM_EMIT("vld4.8 {q8-q9}, [%[src]]!") 962 __ASM_EMIT("vst4.8 {q4-q5}, [%[dst]]!") 963 __ASM_EMIT("vswp d12, d14") 964 __ASM_EMIT("vld4.8 {q10-q11}, [%[src]]!") 965 __ASM_EMIT("vst4.8 {q6-q7}, [%[dst]]!") 966 __ASM_EMIT("vswp d16, d18") 967 __ASM_EMIT("vld4.8 {q12-q13}, [%[src]]!") 968 __ASM_EMIT("vst4.8 {q8-q9}, [%[dst]]!") 969 __ASM_EMIT("vswp d20, d22") 970 __ASM_EMIT("vld4.8 {q14-q15}, [%[src]]!") 971 __ASM_EMIT("vst4.8 {q10-q11}, [%[dst]]!") 972 __ASM_EMIT("vswp d24, d26") 973 __ASM_EMIT("vswp d28, d30") 974 __ASM_EMIT("vst4.8 {q12-q13}, [%[dst]]!") 975 __ASM_EMIT("vst4.8 {q14-q15}, [%[dst]]!") 976 __ASM_EMIT("subs %[count], $64") 977 __ASM_EMIT("bhs 1b") 978 979 // 32x blocks 980 __ASM_EMIT("2:") 981 __ASM_EMIT("adds %[count], $32") 982 __ASM_EMIT("blt 4f") 983 __ASM_EMIT("vld4.8 {q0-q1}, [%[src]]!") // d0 = R, d1 = G, d2 = B, d3 = A 984 __ASM_EMIT("vld4.8 {q2-q3}, [%[src]]!") 985 __ASM_EMIT("vswp d0, d2") 986 __ASM_EMIT("vld4.8 {q4-q5}, [%[src]]!") 987 __ASM_EMIT("vst4.8 {q0-q1}, [%[dst]]!") 988 __ASM_EMIT("vswp d4, d6") 989 __ASM_EMIT("vld4.8 {q6-q7}, [%[src]]!") 990 __ASM_EMIT("vst4.8 {q2-q3}, [%[dst]]!") 991 __ASM_EMIT("vswp d8, d10") 992 __ASM_EMIT("vswp d12, d14") 993 __ASM_EMIT("vst4.8 {q4-q5}, [%[dst]]!") 994 __ASM_EMIT("vst4.8 {q6-q7}, [%[dst]]!") 995 __ASM_EMIT("sub %[count], $32") 996 997 // 16x blocks 998 __ASM_EMIT("4:") 999 __ASM_EMIT("adds %[count], $16") 1000 __ASM_EMIT("blt 6f") 1001 __ASM_EMIT("vld4.8 {q0-q1}, [%[src]]!") // d0 = R, d1 = G, d2 = B, d3 = A 1002 __ASM_EMIT("vld4.8 {q2-q3}, [%[src]]!") 1003 __ASM_EMIT("vswp d0, d2") 1004 __ASM_EMIT("vswp d4, d6") 1005 __ASM_EMIT("vst4.8 {q0-q1}, [%[dst]]!") 1006 __ASM_EMIT("vst4.8 {q2-q3}, [%[dst]]!") 1007 __ASM_EMIT("sub %[count], $16") 1008 1009 // 8x blocks 1010 __ASM_EMIT("6:") 1011 __ASM_EMIT("adds %[count], $8") 1012 __ASM_EMIT("blt 8f") 1013 __ASM_EMIT("vld4.8 {q0-q1}, [%[src]]!") // d0 = R, d1 = G, d2 = B, d3 = A 1014 __ASM_EMIT("vswp d0, d2") 1015 __ASM_EMIT("vst4.8 {q0-q1}, [%[dst]]!") 1016 __ASM_EMIT("sub %[count], $8") 1017 1018 // 4x blocks 1019 __ASM_EMIT("8:") 1020 __ASM_EMIT("adds %[count], $4") 1021 __ASM_EMIT("blt 10f") 1022 __ASM_EMIT("vld2.8 {q0}, [%[src]]!") // d0 = RB, d1 = GA 1023 __ASM_EMIT("vshl.i16 d2, d0, $8") 1024 __ASM_EMIT("vshr.u16 d0, d0, $8") 1025 __ASM_EMIT("vorr d0, d2") 1026 __ASM_EMIT("vst2.8 {q0}, [%[dst]]!") 1027 __ASM_EMIT("sub %[count], $4") 1028 1029 // 1x blocks 1030 __ASM_EMIT("10:") 1031 __ASM_EMIT("adds %[count], $3") 1032 __ASM_EMIT("blt 12f") 1033 __ASM_EMIT("mov %[mask], $0xff") 1034 __ASM_EMIT("orr %[mask], $0xff0000") // mask = ff 00 ff 00 1035 __ASM_EMIT("11:") 1036 __ASM_EMIT("ldr %[t1], [%[src]], $4") // t1 = R G B A 1037 __ASM_EMIT("and %[t2], %[t1], %[mask]") // t2 = R 0 B 0 1038 __ASM_EMIT("and %[t1], %[t1], %[mask], lsl $8") // t1 = 0 G 0 A 1039 __ASM_EMIT("orr %[t1], %[t1], %[t2], ror $16") // t1 = B G R A 1040 __ASM_EMIT("str %[t1], [%[dst]], $4") 1041 __ASM_EMIT("subs %[count], $1") 1042 __ASM_EMIT("bge 11b") 1043 1044 __ASM_EMIT("12:") 1045 : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count), 1046 [t1] "=&r" (t1), [t2] "=&r" (t2), [mask] "=&r" (mask) 1047 : 1048 : "cc", "memory", 1049 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 1050 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 1051 ); 1052 } 1053 1054 #define FILL4_CORE \ 1055 __ASM_EMIT("vld1.32 {q0}, [%[c4]]") /* q0 = c0 c1 c2 c3 */ \ 1056 __ASM_EMIT("vmov q1, q0") /* q1 = c0 c1 c2 c3 */ \ 1057 __ASM_EMIT("vmov q2, q0") /* q2 = c0 c1 c2 c3 */ \ 1058 __ASM_EMIT("vmov q3, q1") /* q3 = c0 c1 c2 c3 */ \ 1059 \ 1060 /* 8x blocks */ \ 1061 __ASM_EMIT("subs %[count], $8") \ 1062 __ASM_EMIT("blo 2f") \ 1063 __ASM_EMIT("vmov q4, q0") /* q4 = c0 c1 c2 c3 */ \ 1064 __ASM_EMIT("vmov q5, q1") /* q5 = c0 c1 c2 c3 */ \ 1065 __ASM_EMIT("vmov q6, q2") /* q6 = c0 c1 c2 c3 */ \ 1066 __ASM_EMIT("vmov q7, q3") /* q7 = c0 c1 c2 c3 */ \ 1067 __ASM_EMIT("1:") \ 1068 __ASM_EMIT("vstm %[dst], {q0-q7}") \ 1069 __ASM_EMIT("subs %[count], $8") \ 1070 __ASM_EMIT("add %[dst], $0x80") \ 1071 __ASM_EMIT("bhs 1b") \ 1072 /* 4x block */ \ 1073 __ASM_EMIT("2:") \ 1074 __ASM_EMIT("adds %[count], $4") \ 1075 __ASM_EMIT("blt 4f") \ 1076 __ASM_EMIT("vstm %[dst], {q0-q3}") \ 1077 __ASM_EMIT("sub %[count], $4") \ 1078 __ASM_EMIT("add %[dst], $0x40") \ 1079 /* 2x block */ \ 1080 __ASM_EMIT("4:") \ 1081 __ASM_EMIT("adds %[count], $2") \ 1082 __ASM_EMIT("blt 6f") \ 1083 __ASM_EMIT("vst1.32 {q0-q1}, [%[dst]]") \ 1084 __ASM_EMIT("sub %[count], $2") \ 1085 __ASM_EMIT("add %[dst], $0x20") \ 1086 /* 1x block */ \ 1087 __ASM_EMIT("6:") \ 1088 __ASM_EMIT("adds %[count], $1") \ 1089 __ASM_EMIT("blt 8f") \ 1090 __ASM_EMIT("vst1.32 {q0}, [%[dst]]") \ 1091 __ASM_EMIT("8:") 1092 fill_rgba(float * dst,float r,float g,float b,float a,size_t count)1093 void fill_rgba(float *dst, float r, float g, float b, float a, size_t count) 1094 { 1095 IF_ARCH_ARM( 1096 float c4[4] __lsp_aligned16; 1097 c4[0] = r; 1098 c4[1] = g; 1099 c4[2] = b; 1100 c4[3] = a; 1101 ) 1102 1103 ARCH_ARM_ASM 1104 ( 1105 FILL4_CORE 1106 : [dst] "+r" (dst), [count] "+r" (count) 1107 : [c4] "r" (&c4[0]) 1108 : "cc", "memory", 1109 "q0", "q1", "q2", "q3", 1110 "q4", "q5", "q6", "q7" 1111 ); 1112 } 1113 fill_hsla(float * dst,float h,float s,float l,float a,size_t count)1114 void fill_hsla(float *dst, float h, float s, float l, float a, size_t count) 1115 { 1116 IF_ARCH_ARM( 1117 float c4[4] __lsp_aligned16; 1118 c4[0] = h; 1119 c4[1] = s; 1120 c4[2] = l; 1121 c4[3] = a; 1122 ); 1123 1124 ARCH_ARM_ASM 1125 ( 1126 FILL4_CORE 1127 : [dst] "+r" (dst), [count] "+r" (count) 1128 : [c4] "r" (&c4[0]) 1129 : "cc", "memory", 1130 "q0", "q1", "q2", "q3", 1131 "q4", "q5", "q6", "q7" 1132 ); 1133 } 1134 1135 #undef FILL4_CORE 1136 1137 #define FVEC4(x) x, x, x, x 1138 1139 IF_ARCH_ARM( 1140 static const float HSL_RGB[] = 1141 { 1142 FVEC4(0.5f), // 1/2 1143 FVEC4(0.333333333333f), // 1/3 1144 FVEC4(1.0f), // 1 1145 FVEC4(6.0f), // 6 1146 FVEC4(0.166666666667f), // 1/6 1147 FVEC4(0.666666666667f) // 2/3 1148 }; 1149 1150 static const float RGB_HSL[] = 1151 { 1152 FVEC4(4.0f), 1153 FVEC4(2.0f), 1154 FVEC4(6.0f), 1155 FVEC4(1.0f), 1156 FVEC4(0.5f), 1157 FVEC4(0.166666666667f) // 1/6 1158 }; 1159 1160 static const float RGBA_TO_BGRA32[] = 1161 { 1162 FVEC4(255.0f), 1163 FVEC4(255.0f) 1164 }; 1165 ) 1166 1167 #undef FVEC4 1168 1169 #define HSLA_TO_RGBA_CORE \ 1170 /* q10 = 1/2, q11 = 1/3, q12 = 1, q13 = 6, q14 = 1/6, q15 = 2/3 */ \ 1171 /* q0 = h0 h1 h2 h3 = H */ \ 1172 /* q1 = l0 l1 l2 l3 = L */ \ 1173 /* q2 = s0 s1 s2 s3 = S */ \ 1174 /* q3 = a0 a1 a2 a3 = A */ \ 1175 /* Calc temp1 (T1) and temp2 (T2) */ \ 1176 __ASM_EMIT("vadd.f32 q4, q2, q1") /* q4 = L+S */ \ 1177 __ASM_EMIT("vadd.f32 q9, q1, q1") /* q9 = L+L */ \ 1178 __ASM_EMIT("vmul.f32 q5, q2, q1") /* q5 = L*S */ \ 1179 __ASM_EMIT("vsub.f32 q4, q4, q5") /* q4 = L+S - L*S */ \ 1180 __ASM_EMIT("vadd.f32 q7, q1, q5") /* q7 = L + L*S */ \ 1181 __ASM_EMIT("vclt.f32 q8, q1, q10") /* q8 = [L < 0.5] */ \ 1182 __ASM_EMIT("vbit q4, q7, q8") /* q4 = T2 = (L+L*S) & [L<0.5]) | (((L+S-L*S) & [L>=0.5]) */ \ 1183 __ASM_EMIT("vmov q2, q0") /* q2 = TG = H */ \ 1184 __ASM_EMIT("vsub.f32 q5, q9, q4") /* q5 = T1 = L+L-T2 */ \ 1185 __ASM_EMIT("vadd.f32 q0, q0, q11") /* q0 = H + 1/3 */ \ 1186 __ASM_EMIT("vsub.f32 q1, q2, q11") /* q1 = H - 1/3 */ \ 1187 __ASM_EMIT("vcgt.f32 q9, q0, q12") /* q9 = [H+1/3 > 1] */ \ 1188 __ASM_EMIT("veor q8, q8") /* q8 = 0 */ \ 1189 __ASM_EMIT("vsub.f32 q6, q0, q12") /* q6 = H + 1/3 - 1 */ \ 1190 __ASM_EMIT("vadd.f32 q7, q2, q12") /* q7 = H - 1/3 + 1 */ \ 1191 __ASM_EMIT("vclt.f32 q8, q1, q8") /* q8 = [H-1/3 < 0] */ \ 1192 __ASM_EMIT("vbit q0, q6, q9") /* q0 = TR = ((H+1/3) & [H+1/3 <= 1]) | ((H+1/3-1) & [H+1/3 > 1]) */ \ 1193 __ASM_EMIT("vbit q1, q7, q8") /* q1 = TB = ((H-1/3) & [H-1/3 >= 0]) | ((H-1/3+1) & [H-1/3 < 0]) */ \ 1194 __ASM_EMIT("vsub.f32 q6, q4, q5") /* q6 = T2 - T1 */ \ 1195 __ASM_EMIT("vmul.f32 q6, q6, q13") /* q6 = K = (T2 - T1)*6 */ \ 1196 /* q0 = TR */ \ 1197 /* q2 = TG */ \ 1198 /* q1 = TB */ \ 1199 /* q3 = A */ \ 1200 /* q4 = T2 */ \ 1201 /* q5 = T1 */ \ 1202 /* q6 = K */ \ 1203 /* Process red color */ \ 1204 __ASM_EMIT("vmov q7, q5") /* q7 = T1 */ \ 1205 __ASM_EMIT("vmov q8, q5") /* q8 = T1 */ \ 1206 __ASM_EMIT("vsub.f32 q9, q15, q0") /* q9 = 2/3 - TR */ \ 1207 __ASM_EMIT("vmla.f32 q7, q6, q0") /* q7 = KTR = T1 + K*TR */ \ 1208 __ASM_EMIT("vmla.f32 q8, q6, q9") /* q8 = RTR = T1 + K*(2/3-TR) */ \ 1209 __ASM_EMIT("vclt.f32 q9, q0, q14") /* q9 = [TR < 1/6] */ \ 1210 __ASM_EMIT("vbif q7, q4, q9") /* q7 = (KTR & [TR < 1/6]) | ((T2) & (TR >= 1/6)) */ \ 1211 __ASM_EMIT("vclt.f32 q9, q0, q15") /* q9 = [TR < 2/3] */ \ 1212 __ASM_EMIT("vbif q8, q5, q9") /* q8 = (RTR & [TR < 2/3]) | ((T1) & (TR >= 2/3)) */ \ 1213 __ASM_EMIT("vclt.f32 q9, q0, q10") /* q9 = [TR < 1/2] */ \ 1214 __ASM_EMIT("vand q0, q7, q9") /* q0 = (KTR & [TR < 1/6] & [TR < 1/2]) | ((T2) & (TR >= 1/6) & [TR < 1/2]) */ \ 1215 __ASM_EMIT("vbif q0, q8, q9") /* q0 = (KTR & [TR < 1/6] & [TR < 1/2]) | ((T2) & (TR >= 1/6) & [TR < 1/2]) | (RTR & [TR < 2/3] & [TR >= 1/2]) | ((T1) & (TR >= 2/3) & [TR >= 1/2]) */ \ 1216 /* Process green color */ \ 1217 __ASM_EMIT("vmov q7, q5") /* q7 = T1 */ \ 1218 __ASM_EMIT("vmov q8, q5") /* q8 = T1 */ \ 1219 __ASM_EMIT("vsub.f32 q9, q15, q2") /* q9 = 2/3 - TG */ \ 1220 __ASM_EMIT("vmla.f32 q7, q6, q2") /* q7 = KTG = T1 + K*TG */ \ 1221 __ASM_EMIT("vmla.f32 q8, q6, q9") /* q8 = RTG = T1 + K*(2/3-TG) */ \ 1222 __ASM_EMIT("vclt.f32 q9, q2, q14") /* q9 = [TG < 1/6] */ \ 1223 __ASM_EMIT("vbif q7, q4, q9") /* q7 = (KTG & [TG < 1/6]) | ((T2) & (TG >= 1/6)) */ \ 1224 __ASM_EMIT("vclt.f32 q9, q2, q15") /* q9 = [TG < 2/3] */ \ 1225 __ASM_EMIT("vbif q8, q5, q9") /* q8 = (RTG & [TG < 2/3]) | ((T1) & (TG >= 2/3)) */ \ 1226 __ASM_EMIT("vclt.f32 q9, q2, q10") /* q9 = [TG < 1/2] */ \ 1227 __ASM_EMIT("vand q2, q7, q9") /* q2 = (KTG & [TG < 1/6] & [TG < 1/2]) | ((T2) & (TG >= 1/6) & [TG < 1/2]) */ \ 1228 __ASM_EMIT("vbif q2, q8, q9") /* q2 = (KTG & [TG < 1/6] & [TG < 1/2]) | ((T2) & (TG >= 1/6) & [TG < 1/2]) | (RTG & [TG < 2/3] & [TG >= 1/2]) | ((T1) & (TG >= 2/3) & [TG >= 1/2]) */ \ 1229 /* Process blue color */ \ 1230 __ASM_EMIT("vmov q7, q5") /* q7 = T1 */ \ 1231 __ASM_EMIT("vmov q8, q5") /* q8 = T1 */ \ 1232 __ASM_EMIT("vsub.f32 q9, q15, q1") /* q9 = 2/3 - TB */ \ 1233 __ASM_EMIT("vmla.f32 q7, q6, q1") /* q7 = KTB = T1 + K*TB */ \ 1234 __ASM_EMIT("vmla.f32 q8, q6, q9") /* q8 = RTB = T1 + K*(2/3-TB) */ \ 1235 __ASM_EMIT("vclt.f32 q9, q1, q14") /* q9 = [TB < 1/6] */ \ 1236 __ASM_EMIT("vbif q7, q4, q9") /* q7 = (KTB & [TB < 1/6]) | ((T2) & (TB >= 1/6)) */ \ 1237 __ASM_EMIT("vclt.f32 q9, q1, q15") /* q9 = [TB < 2/3] */ \ 1238 __ASM_EMIT("vbif q8, q5, q9") /* q8 = (RTB & [TB < 2/3]) | ((T1) & (TB >= 2/3)) */ \ 1239 __ASM_EMIT("vclt.f32 q9, q1, q10") /* q9 = [TB < 1/2] */ \ 1240 __ASM_EMIT("vand q1, q7, q9") /* q1 = (KTB & [TB < 1/6] & [TB < 1/2]) | ((T2) & (TB >= 1/6) & [TB < 1/2]) */ \ 1241 __ASM_EMIT("vbif q1, q8, q9") /* q1 = (KTB & [TB < 1/6] & [TB < 1/2]) | ((T2) & (TB >= 1/6) & [TB < 1/2]) | (RTB & [TB < 2/3] & [TB >= 1/2]) | ((T1) & (TB >= 2/3) & [TB >= 1/2]) */ \ 1242 /* q0 = R */ \ 1243 /* q1 = B */ \ 1244 /* q2 = G */ \ 1245 /* q3 = A */ \ 1246 1247 /* 1248 //Set the temporary values 1249 if (L < HSL_RGB_0_5) 1250 temp2 = L + (L * S); 1251 else 1252 temp2 = (L + S) - (L * S); 1253 1254 temp1 = L + L - temp2; 1255 1256 tempr = H + HSL_RGB_1_3; 1257 tempg = H; 1258 tempb = H - HSL_RGB_1_3; 1259 1260 if (tempr > 1.0f) 1261 tempr -= 1.0f; 1262 if (tempb < 0.0f) 1263 tempb += 1.0f; 1264 1265 k = (temp2 - temp1) * 6.0f; 1266 1267 //Red 1268 if (tempr < HSL_RGB_0_5) 1269 R = (tempr < HSL_RGB_1_6) ? temp1 + k * tempr : temp2; 1270 else 1271 R = (tempr < HSL_RGB_2_3) ? temp1 + k * (HSL_RGB_2_3 - tempr) : temp1; 1272 1273 //Green 1274 if (tempg < HSL_RGB_0_5) 1275 G = (tempg < HSL_RGB_1_6) ? temp1 + k * tempg : temp2; 1276 else 1277 G = (tempg < HSL_RGB_2_3) ? temp1 + k * (HSL_RGB_2_3 - tempg) : temp1; 1278 1279 //Blue 1280 if (tempb < HSL_RGB_0_5) 1281 B = (tempb < HSL_RGB_1_6) ? temp1 + k * tempb : temp2; 1282 else 1283 B = (tempb < HSL_RGB_2_3) ? temp1 + k * (HSL_RGB_2_3 - tempb) : temp1; 1284 */ 1285 1286 1287 hsla_to_rgba(float * dst,const float * src,size_t count)1288 void hsla_to_rgba(float *dst, const float *src, size_t count) 1289 { 1290 ARCH_ARM_ASM 1291 ( 1292 __ASM_EMIT("vldm %[XC], {q10-q15}") // q10 = 1/2, q11 = 1/3, q12 = 1, q13 = 6, q14 = 1/6, q15 = 2/3 1293 __ASM_EMIT("subs %[count], $4") 1294 __ASM_EMIT("blo 2f") 1295 1296 //----------------------------------------------------------------- 1297 // 4x blocks 1298 __ASM_EMIT("1:") 1299 __ASM_EMIT("vld4.32 {q0-q1}, [%[src]]!") // q0 = h0 h1 s0 s1, q1 = l0 l1 a0 a1 1300 __ASM_EMIT("vld4.32 {q2-q3}, [%[src]]!") // q2 = h2 h3 s2 s3, q3 = l2 l3 a2 a3 1301 __ASM_EMIT("vswp d1, d4") // q0 = h0 h1 h2 h3, q2 = s0 s1 s2 s3 1302 __ASM_EMIT("vswp d3, d6") // q1 = l0 l1 l2 l3, q3 = a0 a1 a2 a3 1303 1304 HSLA_TO_RGBA_CORE 1305 1306 __ASM_EMIT("vswp d1, d4") // q0 = r0 r1 g0 g1, q2 = r2 r3 g2 g3 1307 __ASM_EMIT("vswp d3, d6") // q1 = b0 b1 a0 a1, q3 = b2 b3 a2 a3 1308 __ASM_EMIT("vst4.32 {q0-q1}, [%[dst]]!") 1309 __ASM_EMIT("vst4.32 {q2-q3}, [%[dst]]!") 1310 __ASM_EMIT("subs %[count], $4") 1311 __ASM_EMIT("bhs 1b") 1312 1313 __ASM_EMIT("2:") 1314 __ASM_EMIT("adds %[count], $4") 1315 __ASM_EMIT("bls 10f") 1316 1317 //----------------------------------------------------------------- 1318 // 1x-3x block 1319 __ASM_EMIT("tst %[count], $2") 1320 __ASM_EMIT("beq 4f") 1321 __ASM_EMIT("vld1.32 {q0-q1}, [%[src]]!") // q0 = h0 s0 l0 a0, q1 = h1 s1 l1 a1 1322 __ASM_EMIT("4:") 1323 __ASM_EMIT("tst %[count], $1") 1324 __ASM_EMIT("beq 6f") 1325 __ASM_EMIT("vld1.32 {q2}, [%[src]]") // q2 = h2 s2 l2 a2, q3 = ? ? ? ? 1326 __ASM_EMIT("6:") 1327 1328 __ASM_EMIT("vtrn.32 q0, q1") // q0 = h0 h1 l0 l1, q1 = s0 s1 a0 a1 1329 __ASM_EMIT("vtrn.32 q2, q3") // q2 = h2 ? l2 ?, q3 = s2 ? a2 ? 1330 __ASM_EMIT("vswp d1, d4") // q0 = h0 h1 h2 ?, q2 = l0 l1 l2 ? 1331 __ASM_EMIT("vswp d3, d6") // q1 = s0 s1 s2 ?, q3 = a0 a1 a2 ? 1332 1333 __ASM_EMIT("vswp q1, q2") // q1 = l0 l1 l2 ?, q2 = s0 s1 s2 ? 1334 HSLA_TO_RGBA_CORE 1335 __ASM_EMIT("vswp q1, q2") 1336 1337 __ASM_EMIT("vtrn.32 q0, q1") 1338 __ASM_EMIT("vtrn.32 q2, q3") 1339 __ASM_EMIT("vswp d1, d4") 1340 __ASM_EMIT("vswp d3, d6") 1341 1342 __ASM_EMIT("tst %[count], $2") 1343 __ASM_EMIT("beq 8f") 1344 __ASM_EMIT("vst1.32 {q0-q1}, [%[dst]]!") 1345 __ASM_EMIT("8:") 1346 __ASM_EMIT("tst %[count], $1") 1347 __ASM_EMIT("beq 10f") 1348 __ASM_EMIT("vst1.32 {q2}, [%[dst]]") 1349 1350 __ASM_EMIT("10:") 1351 1352 : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count) 1353 : [XC] "r" (&HSL_RGB[0]) 1354 : "cc", "memory", 1355 "q0", "q1", "q2", "q3", 1356 "q4", "q5", "q6", "q7", 1357 "q8", "q9", "q10", "q11", 1358 "q12", "q13", "q14", "q15" 1359 ); 1360 } 1361 1362 #undef HSLA_TO_RGBA_CORE 1363 1364 #define RGBA_TO_HSLA_CORE \ 1365 /* q0 = R */ \ 1366 /* q1 = B */ \ 1367 /* q2 = G */ \ 1368 /* q3 = A */ \ 1369 /* q10 = 4, q11 = 2, q12 = 6, q13 = 1, q14 = 1/2, q15 = 1/6 */ \ 1370 __ASM_EMIT("vmax.f32 q4, q0, q1") \ 1371 __ASM_EMIT("vmin.f32 q5, q0, q1") \ 1372 __ASM_EMIT("vmax.f32 q4, q4, q2") /* q4 = CMAX */ \ 1373 __ASM_EMIT("vmin.f32 q5, q5, q2") /* q5 = CMIN */ \ 1374 __ASM_EMIT("vsub.f32 q6, q4, q5") /* q6 = D = CMAX - CMIN */ \ 1375 __ASM_EMIT("vadd.f32 q5, q4, q5") /* q5 = CMAX + CMIN */ \ 1376 __ASM_EMIT("vstm %[RGBA], {q0-q3}") /* store R, B, G, A */ \ 1377 \ 1378 __ASM_EMIT("vrecpe.f32 q9, q6") /* q9 = RD */ \ 1379 __ASM_EMIT("vrecps.f32 q8, q9, q6") /* q8 = (2 - RD*D) */ \ 1380 __ASM_EMIT("vmul.f32 q9, q8, q9") /* q9 = d' = RD * (2 - RD*D) */ \ 1381 __ASM_EMIT("vrecps.f32 q8, q9, q6") /* q8 = (2 - RD*d') */ \ 1382 __ASM_EMIT("vmul.f32 q9, q8, q9") /* q9 = 1/D = d' * (2 - RD*d') */ \ 1383 \ 1384 /* q0 = R */ \ 1385 /* q1 = B */ \ 1386 /* q2 = G */ \ 1387 /* q3 = A */ \ 1388 /* q4 = CMAX */ \ 1389 /* q5 = CMAX + CMIN */ \ 1390 /* q6 = D */ \ 1391 /* q9 = 1/D */ \ 1392 __ASM_EMIT("vsub.f32 q7, q1, q0") /* q7 = B-R */ \ 1393 __ASM_EMIT("vsub.f32 q8, q0, q2") /* q8 = R-G */ \ 1394 __ASM_EMIT("vsub.f32 q0, q2, q1") /* q0 = G-B */ \ 1395 __ASM_EMIT("vmul.f32 q7, q7, q9") /* q7 = (B-R)/D */ \ 1396 __ASM_EMIT("veor q1, q1") /* q1 = 0 */ \ 1397 __ASM_EMIT("vmul.f32 q0, q0, q9") /* q0 = (G-B)/D */ \ 1398 __ASM_EMIT("vmul.f32 q8, q8, q9") /* q8 = (R-G)/D */ \ 1399 __ASM_EMIT("vclt.f32 q1, q0, q1") /* q1 = [(G-B)/D < 0] */ \ 1400 __ASM_EMIT("vadd.f32 q7, q7, q11") /* q7 = HG = (B-R)/D + 2 */ \ 1401 __ASM_EMIT("vand q1, q12") /* q1 = [(G-B)/D < 0] & 6 */ \ 1402 __ASM_EMIT("vadd.f32 q8, q8, q10") /* q8 = HB = (R-G)/D + 4 */ \ 1403 __ASM_EMIT("vadd.f32 q9, q0, q1") /* q9 = HR = (G-B)/D + [(G-B)/D < 0] & 6 */ \ 1404 __ASM_EMIT("vldm %[RGBA], {q0-q3}") /* load R, B, G, A */ \ 1405 /* q0 = R */ \ 1406 /* q1 = B */ \ 1407 /* q2 = G */ \ 1408 /* q3 = A */ \ 1409 /* q4 = CMAX */ \ 1410 /* q5 = CMAX + CMIN */ \ 1411 /* q6 = D */ \ 1412 /* q7 = HG */ \ 1413 /* q8 = HB */ \ 1414 /* q9 = HR */ \ 1415 __ASM_EMIT("vceq.f32 q2, q2, q4") /* q2 = [G == CMAX] */ \ 1416 __ASM_EMIT("vceq.f32 q0, q0, q4") /* q0 = [R == CMAX] */ \ 1417 __ASM_EMIT("vbsl q2, q7, q8") /* q2 = (HG & [G == CMAX]) | (HB & [G != CMAX]) */ \ 1418 __ASM_EMIT("veor q4, q4") /* q4 = 0 */ \ 1419 __ASM_EMIT("vbsl q0, q9, q2") /* q0 = (HR & [R == CMAX]) | (HG & [G == CMAX] & [R != CMAX]) | (HB & [G != CMAX] & [R != CMAX]) */ \ 1420 __ASM_EMIT("vceq.f32 q4, q4, q6") /* q4 = [ D == 0 ] */ \ 1421 __ASM_EMIT("vmul.f32 q1, q5, q14") /* q1 = L = (CMAX + CMIN) * 0.5 */ \ 1422 __ASM_EMIT("vsub.f32 q2, q13, q1") /* q2 = X = 1 - L */ \ 1423 __ASM_EMIT("vbic q0, q0, q4") /* q0 = H = [D != 0] & ((HR & [R == CMAX]) | (HG & [G == CMAX] & [R != CMAX]) | (HB & [G != CMAX] & [R != CMAX])) */ \ 1424 \ 1425 __ASM_EMIT("vrecpe.f32 q5, q1") /* q5 = RL */ \ 1426 __ASM_EMIT("vrecpe.f32 q9, q2") /* q9 = RX */ \ 1427 __ASM_EMIT("vrecps.f32 q4, q5, q1") /* q4 = (2 - RL*L) */ \ 1428 __ASM_EMIT("vrecps.f32 q8, q9, q2") /* q8 = (2 - RX*X) */ \ 1429 __ASM_EMIT("vmul.f32 q5, q4, q5") /* q5 = l' = L * (2 - RL*L) */ \ 1430 __ASM_EMIT("vmul.f32 q9, q8, q9") /* q9 = x' = X * (2 - RX*X) */ \ 1431 __ASM_EMIT("vrecps.f32 q4, q5, q1") /* q4 = (2 - RL*l') */ \ 1432 __ASM_EMIT("vrecps.f32 q8, q9, q2") /* q8 = (2 - RX*X') */ \ 1433 __ASM_EMIT("vmul.f32 q5, q4, q5") /* q5 = 1/L = l' * (2 - RL*l') */ \ 1434 __ASM_EMIT("vmul.f32 q9, q8, q9") /* q9 = 1/X = x' * (2 - RX*x') */ \ 1435 __ASM_EMIT("vmul.f32 q2, q6, q5") /* q2 = D/L */ \ 1436 __ASM_EMIT("vmul.f32 q4, q6, q9") /* q4 = D/X */ \ 1437 __ASM_EMIT("veor q5, q5") /* q5 = 0 */ \ 1438 \ 1439 __ASM_EMIT("vclt.f32 q6, q1, q13") /* q6 = [L < 1] */ \ 1440 __ASM_EMIT("vceq.f32 q7, q1, q5") /* q7 = [L == 0] */ \ 1441 __ASM_EMIT("vcgt.f32 q8, q1, q13") /* q8 = [L > 1] */ \ 1442 __ASM_EMIT("vbit q6, q5, q7") /* q6 = [L < 1] & [L != 0] */ \ 1443 __ASM_EMIT("vand q8, q8, q4") /* q8 = D/X & [L > 1] */ \ 1444 __ASM_EMIT("vand q6, q6, q2") /* q6 = D/L & [L < 1] & [L != 0] */ \ 1445 __ASM_EMIT("vorr q2, q8, q6") /* q2 = S = (D/L & [L < 1] & [L != 0]) | (D/X & [L > 1]) */ \ 1446 __ASM_EMIT("vmul.f32 q0, q0, q15") /* q0 = H * 1/6 */ \ 1447 __ASM_EMIT("vmul.f32 q2, q2, q14") /* q2 = S * 1/2 */ \ 1448 1449 /* 1450 float cmax = (R < G) ? ((B < G) ? G : B) : ((B < R) ? R : B); 1451 float cmin = (R < G) ? ((B < R) ? B : R) : ((B < G) ? B : G); 1452 float d = cmax - cmin; 1453 1454 H = 0.0f; 1455 S = 0.0f; 1456 L = HSL_RGB_0_5 * (cmax + cmin); 1457 1458 // Calculate hue 1459 if (R == cmax) 1460 { 1461 H = (G - B) / d; 1462 if (H < 0.0f) 1463 H += 6.0f; 1464 } 1465 else if (G == cmax) 1466 H = (B - R) / d + 2.0f; 1467 else 1468 H = (R - G) / d + 4.0f; 1469 1470 // Calculate saturation 1471 if (L < 1.0f) 1472 S = (L != 0.0f) ? d / L : 0.0f; 1473 else 1474 S = (L != 1.0f) ? d / (1.0f - L) : 0.0f; 1475 1476 // Normalize hue and saturation 1477 H *= HSL_RGB_1_6; 1478 S *= HSL_RGB_0_5; 1479 */ 1480 rgba_to_hsla(float * dst,const float * src,size_t count)1481 void rgba_to_hsla(float *dst, const float *src, size_t count) 1482 { 1483 #pragma pack(push, 1) 1484 IF_ARCH_ARM( 1485 struct 1486 { 1487 float r[4], g[4], b[4], a[4]; 1488 } rgba __lsp_aligned16; 1489 ); 1490 #pragma pack(pop) 1491 1492 ARCH_ARM_ASM 1493 ( 1494 __ASM_EMIT("vldm %[XC], {q10-q15}") 1495 __ASM_EMIT("subs %[count], $4") 1496 __ASM_EMIT("blo 2f") 1497 1498 //----------------------------------------------------------------- 1499 // 4x blocks 1500 __ASM_EMIT("1:") 1501 __ASM_EMIT("vld4.32 {q0-q1}, [%[src]]!") 1502 __ASM_EMIT("vld4.32 {q2-q3}, [%[src]]!") 1503 __ASM_EMIT("vswp d1, d4") 1504 __ASM_EMIT("vswp d3, d6") 1505 1506 RGBA_TO_HSLA_CORE 1507 1508 __ASM_EMIT("vswp d1, d4") 1509 __ASM_EMIT("vswp d3, d6") 1510 __ASM_EMIT("vst4.32 {q0-q1}, [%[dst]]!") 1511 __ASM_EMIT("vst4.32 {q2-q3}, [%[dst]]!") 1512 __ASM_EMIT("subs %[count], $4") 1513 __ASM_EMIT("bhs 1b") 1514 1515 __ASM_EMIT("2:") 1516 __ASM_EMIT("adds %[count], $4") 1517 __ASM_EMIT("bls 10f") 1518 1519 //----------------------------------------------------------------- 1520 // 1x-3x block 1521 __ASM_EMIT("tst %[count], $2") 1522 __ASM_EMIT("beq 4f") 1523 __ASM_EMIT("vld1.32 {q0-q1}, [%[src]]!") 1524 __ASM_EMIT("4:") 1525 __ASM_EMIT("tst %[count], $1") 1526 __ASM_EMIT("beq 6f") 1527 __ASM_EMIT("vld1.32 {q2}, [%[src]]") 1528 __ASM_EMIT("6:") 1529 1530 __ASM_EMIT("vtrn.32 q0, q1") 1531 __ASM_EMIT("vtrn.32 q2, q3") 1532 __ASM_EMIT("vswp d1, d4") 1533 __ASM_EMIT("vswp d3, d6") 1534 1535 __ASM_EMIT("vswp q1, q2") 1536 RGBA_TO_HSLA_CORE 1537 __ASM_EMIT("vswp q1, q2") 1538 1539 __ASM_EMIT("vtrn.32 q0, q1") 1540 __ASM_EMIT("vtrn.32 q2, q3") 1541 __ASM_EMIT("vswp d1, d4") 1542 __ASM_EMIT("vswp d3, d6") 1543 1544 __ASM_EMIT("tst %[count], $2") 1545 __ASM_EMIT("beq 8f") 1546 __ASM_EMIT("vst1.32 {q0-q1}, [%[dst]]!") 1547 __ASM_EMIT("8:") 1548 __ASM_EMIT("tst %[count], $1") 1549 __ASM_EMIT("beq 10f") 1550 __ASM_EMIT("vst1.32 {q2}, [%[dst]]") 1551 1552 __ASM_EMIT("10:") 1553 1554 : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count) 1555 : [XC] "r" (&RGB_HSL[0]), [RGBA] "r" (&rgba) 1556 : "cc", "memory", 1557 "q0", "q1", "q2", "q3", 1558 "q4", "q5", "q6", "q7", 1559 "q8", "q9", "q10", "q11", 1560 "q12", "q13", "q14", "q15" 1561 ); 1562 } 1563 1564 #undef RGBA_TO_HSLA_CORE 1565 1566 #define RGBA_TO_BGRA32_CORE_X8 \ 1567 /* Transpose */ \ 1568 __ASM_EMIT("vtrn.32 q0, q1") \ 1569 __ASM_EMIT("vtrn.32 q2, q3") \ 1570 __ASM_EMIT("vtrn.32 q4, q5") \ 1571 __ASM_EMIT("vtrn.32 q6, q7") \ 1572 __ASM_EMIT("vswp d4, d1") \ 1573 __ASM_EMIT("vswp d12, d9") \ 1574 __ASM_EMIT("vswp d6, d3") \ 1575 __ASM_EMIT("vswp d14, d11") \ 1576 \ 1577 /* q0 = r, q1 = g, q2 = b, q3 = a */ \ 1578 __ASM_EMIT("vswp q0, q2") /* q0 = b, q2 = r */ \ 1579 __ASM_EMIT("vswp q4, q6") \ 1580 __ASM_EMIT("vmul.f32 q8, q3, q14") /* q8 = a * 255 */ \ 1581 __ASM_EMIT("vmul.f32 q9, q7, q15") \ 1582 __ASM_EMIT("vsub.f32 q3, q14, q8") /* q3 = A = 255 - a*255 * */ \ 1583 __ASM_EMIT("vsub.f32 q7, q15, q9") \ 1584 __ASM_EMIT("veor q12, q12") /* q12 = 0 */ \ 1585 __ASM_EMIT("veor q13, q13") \ 1586 __ASM_EMIT("vmul.f32 q0, q0, q3") /* q0 = B = b * A */ \ 1587 __ASM_EMIT("vmul.f32 q4, q4, q7") \ 1588 __ASM_EMIT("vmul.f32 q1, q1, q3") /* q1 = G = g * A */ \ 1589 __ASM_EMIT("vmul.f32 q5, q5, q7") \ 1590 __ASM_EMIT("vmul.f32 q2, q2, q3") /* q2 = R = r * A */ \ 1591 __ASM_EMIT("vmul.f32 q6, q6, q7") \ 1592 __ASM_EMIT("vcge.f32 q8, q0, q12") /* q8 = [B >= 0] */ \ 1593 __ASM_EMIT("vcge.f32 q9, q4, q13") \ 1594 __ASM_EMIT("vcge.f32 q10, q1, q12") /* q10 = [G >= 0] */ \ 1595 __ASM_EMIT("vcge.f32 q11, q5, q13") \ 1596 __ASM_EMIT("vcge.f32 q12, q2, q12") /* q11 = [R >= 0] */ \ 1597 __ASM_EMIT("vcge.f32 q13, q6, q13") \ 1598 __ASM_EMIT("vand q0, q0, q8") /* q0 = B & [B >= 0] */ \ 1599 __ASM_EMIT("vand q4, q4, q9") \ 1600 __ASM_EMIT("vand q1, q1, q10") /* q1 = G & [G >= 0] */ \ 1601 __ASM_EMIT("vand q5, q5, q11") \ 1602 __ASM_EMIT("vand q2, q2, q12") /* q2 = R & [R >= 0] */ \ 1603 __ASM_EMIT("vand q6, q6, q13") \ 1604 \ 1605 /* Transpose back */ \ 1606 __ASM_EMIT("vtrn.32 q0, q1") \ 1607 __ASM_EMIT("vtrn.32 q2, q3") \ 1608 __ASM_EMIT("vtrn.32 q4, q5") \ 1609 __ASM_EMIT("vtrn.32 q6, q7") \ 1610 __ASM_EMIT("vswp d4, d1") \ 1611 __ASM_EMIT("vswp d12, d9") \ 1612 __ASM_EMIT("vswp d6, d3") \ 1613 __ASM_EMIT("vswp d14, d11") \ 1614 /* q0 = b0 g0 r0 a0 */ \ 1615 /* q1 = b1 g1 r1 a1 */ \ 1616 /* q2 = b2 g2 r2 a2 */ \ 1617 /* q3 = b3 g3 r3 a3 */ \ 1618 \ 1619 __ASM_EMIT("vcvt.u32.f32 q0, q0") /* q0 = int(b0 g0 r0 a0) */ \ 1620 __ASM_EMIT("vcvt.u32.f32 q4, q4") \ 1621 __ASM_EMIT("vcvt.u32.f32 q1, q1") /* q1 = int(b1 g1 r1 a1) */ \ 1622 __ASM_EMIT("vcvt.u32.f32 q5, q5") \ 1623 __ASM_EMIT("vcvt.u32.f32 q2, q2") /* q2 = int(b2 g2 r2 a2) */ \ 1624 __ASM_EMIT("vcvt.u32.f32 q6, q6") \ 1625 __ASM_EMIT("vcvt.u32.f32 q3, q3") /* q3 = int(b3 g3 r3 a3) */ \ 1626 __ASM_EMIT("vcvt.u32.f32 q7, q7") \ 1627 __ASM_EMIT("vqmovn.u32 d0, q0") \ 1628 __ASM_EMIT("vqmovn.u32 d1, q1") \ 1629 __ASM_EMIT("vqmovn.u32 d2, q2") \ 1630 __ASM_EMIT("vqmovn.u32 d3, q3") \ 1631 __ASM_EMIT("vqmovn.u32 d4, q4") \ 1632 __ASM_EMIT("vqmovn.u32 d5, q5") \ 1633 __ASM_EMIT("vqmovn.u32 d6, q6") \ 1634 __ASM_EMIT("vqmovn.u32 d7, q7") \ 1635 __ASM_EMIT("vqmovn.u16 d0, q0") \ 1636 __ASM_EMIT("vqmovn.u16 d1, q1") \ 1637 __ASM_EMIT("vqmovn.u16 d2, q2") \ 1638 __ASM_EMIT("vqmovn.u16 d3, q3") 1639 1640 #define RGBA_TO_BGRA32_CORE_X4 \ 1641 /* Transpose */ \ 1642 __ASM_EMIT("vtrn.32 q0, q1") \ 1643 __ASM_EMIT("vtrn.32 q2, q3") \ 1644 __ASM_EMIT("vswp d4, d1") \ 1645 __ASM_EMIT("vswp d6, d3") \ 1646 \ 1647 /* q0 = r, q1 = g, q2 = b, q3 = a */ \ 1648 __ASM_EMIT("vswp q0, q2") /* q0 = b, q2 = r */ \ 1649 __ASM_EMIT("vmul.f32 q8, q3, q14") /* q8 = a * 255 */ \ 1650 __ASM_EMIT("vsub.f32 q3, q14, q8") /* q3 = A = 255 - a*255 * */ \ 1651 __ASM_EMIT("veor q12, q12") /* q12 = 0 */ \ 1652 __ASM_EMIT("vmul.f32 q0, q0, q3") /* q0 = B = b * A */ \ 1653 __ASM_EMIT("vmul.f32 q1, q1, q3") /* q1 = G = g * A */ \ 1654 __ASM_EMIT("vmul.f32 q2, q2, q3") /* q2 = R = r * A */ \ 1655 __ASM_EMIT("vcge.f32 q8, q0, q12") /* q8 = [B >= 0] */ \ 1656 __ASM_EMIT("vcge.f32 q10, q1, q12") /* q10 = [G >= 0] */ \ 1657 __ASM_EMIT("vcge.f32 q12, q2, q12") /* q11 = [R >= 0] */ \ 1658 __ASM_EMIT("vand q0, q0, q8") /* q0 = B & [B >= 0] */ \ 1659 __ASM_EMIT("vand q1, q1, q10") /* q1 = G & [G >= 0] */ \ 1660 __ASM_EMIT("vand q2, q2, q12") /* q2 = R & [R >= 0] */ \ 1661 \ 1662 /* Transpose back */ \ 1663 __ASM_EMIT("vtrn.32 q0, q1") \ 1664 __ASM_EMIT("vtrn.32 q2, q3") \ 1665 __ASM_EMIT("vswp d4, d1") \ 1666 __ASM_EMIT("vswp d6, d3") \ 1667 /* q0 = b0 g0 r0 a0 */ \ 1668 /* q1 = b1 g1 r1 a1 */ \ 1669 /* q2 = b2 g2 r2 a2 */ \ 1670 /* q3 = b3 g3 r3 a3 */ \ 1671 \ 1672 __ASM_EMIT("vcvt.u32.f32 q0, q0") /* q0 = int(b0 g0 r0 a0) */ \ 1673 __ASM_EMIT("vcvt.u32.f32 q1, q1") /* q1 = int(b1 g1 r1 a1) */ \ 1674 __ASM_EMIT("vcvt.u32.f32 q2, q2") /* q2 = int(b2 g2 r2 a2) */ \ 1675 __ASM_EMIT("vcvt.u32.f32 q3, q3") /* q3 = int(b3 g3 r3 a3) */ \ 1676 __ASM_EMIT("vqmovn.u32 d0, q0") \ 1677 __ASM_EMIT("vqmovn.u32 d1, q1") \ 1678 __ASM_EMIT("vqmovn.u32 d2, q2") \ 1679 __ASM_EMIT("vqmovn.u32 d3, q3") \ 1680 __ASM_EMIT("vqmovn.u16 d0, q0") \ 1681 __ASM_EMIT("vqmovn.u16 d1, q1") 1682 rgba_to_bgra32(void * dst,const float * src,size_t count)1683 void rgba_to_bgra32(void *dst, const float *src, size_t count) 1684 { 1685 IF_ARCH_ARM( uint32_t fpscr, b_fpscr; ) 1686 1687 ARCH_ARM_ASM 1688 ( 1689 // Set-up rounding mode 1690 __ASM_EMIT("vmsr FPSCR, %[bfp]") 1691 __ASM_EMIT("orr %[fp], %[bfp], $0xc00000") 1692 __ASM_EMIT("vmrs %[fp], FPSCR") 1693 1694 __ASM_EMIT("vld1.32 {q14-q15}, [%[XC]]") 1695 __ASM_EMIT("subs %[count], $8") 1696 __ASM_EMIT("blo 2f") 1697 1698 //----------------------------------------------------------------- 1699 // 8x blocks 1700 __ASM_EMIT("1:") 1701 __ASM_EMIT("vldm %[src]!, {q0-q7}") 1702 RGBA_TO_BGRA32_CORE_X8 1703 __ASM_EMIT("subs %[count], $8") 1704 __ASM_EMIT("vstm %[dst]!, {q0-q1}") 1705 __ASM_EMIT("bhs 1b") 1706 1707 __ASM_EMIT("2:") 1708 __ASM_EMIT("adds %[count], $4") 1709 __ASM_EMIT("blt 4f") 1710 1711 //----------------------------------------------------------------- 1712 // 4x blocks 1713 __ASM_EMIT("vldm %[src]!, {q0-q3}") 1714 RGBA_TO_BGRA32_CORE_X4 1715 __ASM_EMIT("sub %[count], $4") 1716 __ASM_EMIT("vstm %[dst]!, {q0}") 1717 1718 __ASM_EMIT("4:") 1719 __ASM_EMIT("adds %[count], $4") 1720 __ASM_EMIT("bls 12f") 1721 1722 //----------------------------------------------------------------- 1723 // 1x-3x block 1724 __ASM_EMIT("tst %[count], $2") 1725 __ASM_EMIT("beq 6f") 1726 __ASM_EMIT("vld1.32 {q0-q1}, [%[src]]!") 1727 __ASM_EMIT("6:") 1728 __ASM_EMIT("tst %[count], $1") 1729 __ASM_EMIT("beq 8f") 1730 __ASM_EMIT("vld1.32 {q2}, [%[src]]") 1731 __ASM_EMIT("8:") 1732 RGBA_TO_BGRA32_CORE_X4 1733 __ASM_EMIT("tst %[count], $2") 1734 __ASM_EMIT("beq 10f") 1735 __ASM_EMIT("vst1.32 {d0}, [%[dst]]!") 1736 __ASM_EMIT("10:") 1737 __ASM_EMIT("tst %[count], $1") 1738 __ASM_EMIT("beq 12f") 1739 __ASM_EMIT("vstm %[dst], {s2}") 1740 1741 __ASM_EMIT("12:") 1742 1743 // Restore rounding mode 1744 __ASM_EMIT("vmrs %[bfp], FPSCR") 1745 1746 : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count), 1747 [fp] "=&r" (fpscr), [bfp] "=&r" (b_fpscr) 1748 : [XC] "r" (&RGBA_TO_BGRA32[0]) 1749 : "cc", "memory", 1750 "q0", "q1", "q2", "q3", 1751 "q4", "q5", "q6", "q7", 1752 "q8", "q9", "q10", "q11", 1753 "q12", "q13", "q14", "q15" 1754 ); 1755 } 1756 1757 #undef RGBA_TO_BGRA32_CORE_X8 1758 #undef RGBA_TO_BGRA32_CORE_X4 1759 1760 } 1761 1762 1763 #endif /* DSP_ARCH_ARM_NEON_D32_GRAPHICS_H_ */ 1764