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: 26 нояб. 2019 г. 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_PMATH_ABS_VV_H_ 23 #define DSP_ARCH_ARM_NEON_D32_PMATH_ABS_VV_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 { 31 #define OP_DSEL(a, b) a 32 #define OP_RSEL(a, b) b 33 34 #define ABS_VV2_CORE(DST, SRC, OP, SEL) \ 35 __ASM_EMIT("subs %[count], $32") \ 36 __ASM_EMIT("blo 2f") \ 37 /* 32x blocks */ \ 38 __ASM_EMIT("1:") \ 39 __ASM_EMIT("vldm %[" SEL(SRC, DST) "], {q8-q15}") \ 40 __ASM_EMIT("vldm %[" SEL(DST, SRC) "], {q0-q7}") \ 41 __ASM_EMIT("vabs.f32 " SEL("q8, q8", "q0, q0")) \ 42 __ASM_EMIT("vabs.f32 " SEL("q9, q9", "q1, q1")) \ 43 __ASM_EMIT("vabs.f32 " SEL("q10, q10", "q2, q2")) \ 44 __ASM_EMIT("vabs.f32 " SEL("q11, q11", "q3, q3")) \ 45 __ASM_EMIT("vabs.f32 " SEL("q12, q12", "q4, q4")) \ 46 __ASM_EMIT("vabs.f32 " SEL("q13, q13", "q5, q5")) \ 47 __ASM_EMIT("vabs.f32 " SEL("q14, q14", "q6, q6")) \ 48 __ASM_EMIT("vabs.f32 " SEL("q15, q15", "q7, q7")) \ 49 __ASM_EMIT(OP ".f32 q0, q0, q8") \ 50 __ASM_EMIT(OP ".f32 q1, q1, q9") \ 51 __ASM_EMIT(OP ".f32 q2, q2, q10") \ 52 __ASM_EMIT(OP ".f32 q3, q3, q11") \ 53 __ASM_EMIT(OP ".f32 q4, q4, q12") \ 54 __ASM_EMIT(OP ".f32 q5, q5, q13") \ 55 __ASM_EMIT(OP ".f32 q6, q6, q14") \ 56 __ASM_EMIT(OP ".f32 q7, q7, q15") \ 57 __ASM_EMIT("subs %[count], $32") \ 58 __ASM_EMIT("vstm %[" DST "]!, {q0-q7}") \ 59 __ASM_EMIT("add %[" SRC "], $0x80") \ 60 __ASM_EMIT("bhs 1b") \ 61 /* 16x block */ \ 62 __ASM_EMIT("2:") \ 63 __ASM_EMIT("adds %[count], $16") /* 32 - 16 */ \ 64 __ASM_EMIT("blt 4f") \ 65 __ASM_EMIT("vldm %[" SEL(SRC, DST) "], {q8-q11}") \ 66 __ASM_EMIT("vldm %[" SEL(DST, SRC) "], {q0-q3}") \ 67 __ASM_EMIT("vabs.f32 " SEL("q8, q8", "q0, q0")) \ 68 __ASM_EMIT("vabs.f32 " SEL("q9, q9", "q1, q1")) \ 69 __ASM_EMIT("vabs.f32 " SEL("q10, q10", "q2, q2")) \ 70 __ASM_EMIT("vabs.f32 " SEL("q11, q11", "q3, q3")) \ 71 __ASM_EMIT(OP ".f32 q0, q0, q8") \ 72 __ASM_EMIT(OP ".f32 q1, q1, q9") \ 73 __ASM_EMIT(OP ".f32 q2, q2, q10") \ 74 __ASM_EMIT(OP ".f32 q3, q3, q11") \ 75 __ASM_EMIT("sub %[count], $16") \ 76 __ASM_EMIT("vstm %[" DST "]!, {q0-q3}") \ 77 __ASM_EMIT("add %[" SRC "], $0x40") \ 78 /* 8x block */ \ 79 __ASM_EMIT("4:") \ 80 __ASM_EMIT("adds %[count], $8") /* 16 - 8 */ \ 81 __ASM_EMIT("blt 6f") \ 82 __ASM_EMIT("vldm %[" SEL(SRC, DST) "], {q8-q9}") \ 83 __ASM_EMIT("vldm %[" SEL(DST, SRC) "], {q0-q1}") \ 84 __ASM_EMIT("vabs.f32 " SEL("q8, q8", "q0, q0")) \ 85 __ASM_EMIT("vabs.f32 " SEL("q9, q9", "q1, q1")) \ 86 __ASM_EMIT(OP ".f32 q0, q0, q8") \ 87 __ASM_EMIT(OP ".f32 q1, q1, q9") \ 88 __ASM_EMIT("sub %[count], $8") \ 89 __ASM_EMIT("vstm %[" DST "]!, {q0-q1}") \ 90 __ASM_EMIT("add %[" SRC "], $0x20") \ 91 /* 4x block */ \ 92 __ASM_EMIT("6:") \ 93 __ASM_EMIT("adds %[count], $4") /* 8 - 4 */ \ 94 __ASM_EMIT("blt 8f") \ 95 __ASM_EMIT("vldm %[" SEL(SRC, DST) "], {q8}") \ 96 __ASM_EMIT("vldm %[" SEL(DST, SRC) "], {q0}") \ 97 __ASM_EMIT("vabs.f32 " SEL("q8, q8", "q0, q0")) \ 98 __ASM_EMIT(OP ".f32 q0, q0, q8") \ 99 __ASM_EMIT("sub %[count], $4") \ 100 __ASM_EMIT("vstm %[" DST "]!, {q0}") \ 101 __ASM_EMIT("add %[" SRC "], $0x10") \ 102 /* 1x block */ \ 103 __ASM_EMIT("8:") \ 104 __ASM_EMIT("adds %[count], $3") /* 4 - 3 */ \ 105 __ASM_EMIT("blt 10f") \ 106 __ASM_EMIT("9:") \ 107 __ASM_EMIT("vld1.32 {d16[], d17[]}, [%[" SEL(SRC, DST) "]]") \ 108 __ASM_EMIT("vld1.32 {d0[], d1[]}, [%[" SEL(DST, SRC) "]]") \ 109 __ASM_EMIT("vabs.f32 " SEL("q8, q8", "q0, q0")) \ 110 __ASM_EMIT(OP ".f32 q0, q0, q8") \ 111 __ASM_EMIT("subs %[count], $1") \ 112 __ASM_EMIT("vst1.32 {d0[0]}, [%[" DST "]]!") \ 113 __ASM_EMIT("add %[" SRC "], $0x04") \ 114 __ASM_EMIT("bge 9b") \ 115 __ASM_EMIT("10:") 116 abs_add2(float * dst,const float * src,size_t count)117 void abs_add2(float *dst, const float *src, size_t count) 118 { 119 ARCH_ARM_ASM 120 ( 121 ABS_VV2_CORE("dst", "src", "vadd", OP_DSEL) 122 : [dst] "+r" (dst), [src] "+r" (src), 123 [count] "+r" (count) 124 : 125 : "cc", "memory", 126 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 127 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 128 ); 129 } 130 abs_sub2(float * dst,const float * src,size_t count)131 void abs_sub2(float *dst, const float *src, size_t count) 132 { 133 ARCH_ARM_ASM 134 ( 135 ABS_VV2_CORE("dst", "src", "vsub", OP_DSEL) 136 : [dst] "+r" (dst), [src] "+r" (src), 137 [count] "+r" (count) 138 : 139 : "cc", "memory", 140 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 141 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 142 ); 143 } 144 abs_rsub2(float * dst,const float * src,size_t count)145 void abs_rsub2(float *dst, const float *src, size_t count) 146 { 147 ARCH_ARM_ASM 148 ( 149 ABS_VV2_CORE("dst", "src", "vsub", OP_RSEL) 150 : [dst] "+r" (dst), [src] "+r" (src), 151 [count] "+r" (count) 152 : 153 : "cc", "memory", 154 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 155 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 156 ); 157 } 158 abs_mul2(float * dst,const float * src,size_t count)159 void abs_mul2(float *dst, const float *src, size_t count) 160 { 161 ARCH_ARM_ASM 162 ( 163 ABS_VV2_CORE("dst", "src", "vmul", OP_DSEL) 164 : [dst] "+r" (dst), [src] "+r" (src), 165 [count] "+r" (count) 166 : 167 : "cc", "memory", 168 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 169 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 170 ); 171 } 172 173 #undef ABS_VV2_CORE 174 175 #define ABS_DIV2_CORE(DST, SRC, SEL) \ 176 __ASM_EMIT("subs %[count], $16") \ 177 __ASM_EMIT("blo 2f") \ 178 /* 16x blocks */ \ 179 __ASM_EMIT("1:") \ 180 __ASM_EMIT("vldm %[" SEL(SRC, DST) "], {q0-q3}") \ 181 __ASM_EMIT("vldm %[" SEL(DST, SRC) "], {q4-q7}") \ 182 __ASM_EMIT("vabs.f32 " SEL("q0, q0", "q4, q4")) \ 183 __ASM_EMIT("vabs.f32 " SEL("q1, q1", "q5, q5")) \ 184 __ASM_EMIT("vabs.f32 " SEL("q2, q2", "q6, q6")) \ 185 __ASM_EMIT("vabs.f32 " SEL("q3, q3", "q7, q7")) \ 186 __ASM_EMIT("vrecpe.f32 q8, q0") /* q8 = s2 */ \ 187 __ASM_EMIT("vrecpe.f32 q9, q1") \ 188 __ASM_EMIT("vrecpe.f32 q10, q2") \ 189 __ASM_EMIT("vrecpe.f32 q11, q3") \ 190 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2) */ \ 191 __ASM_EMIT("vrecps.f32 q13, q9, q1") \ 192 __ASM_EMIT("vrecps.f32 q14, q10, q2") \ 193 __ASM_EMIT("vrecps.f32 q15, q11, q3") \ 194 __ASM_EMIT("vmul.f32 q8, q12, q8") /* q8 = s2' = s2 * (2 - R*s2) */ \ 195 __ASM_EMIT("vmul.f32 q9, q13, q9") \ 196 __ASM_EMIT("vmul.f32 q10, q14, q10") \ 197 __ASM_EMIT("vmul.f32 q11, q15, q11") \ 198 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2') */ \ 199 __ASM_EMIT("vrecps.f32 q13, q9, q1") \ 200 __ASM_EMIT("vrecps.f32 q14, q10, q2") \ 201 __ASM_EMIT("vrecps.f32 q15, q11, q3") \ 202 __ASM_EMIT("vmul.f32 q0, q12, q8") /* q0 = s2" = s2' * (2 - R*s2) = 1/s2 */ \ 203 __ASM_EMIT("vmul.f32 q1, q13, q9") \ 204 __ASM_EMIT("vmul.f32 q2, q14, q10") \ 205 __ASM_EMIT("vmul.f32 q3, q15, q11") \ 206 __ASM_EMIT("vmul.f32 q0, q0, q4") /* s1 / s2 */ \ 207 __ASM_EMIT("vmul.f32 q1, q1, q5") \ 208 __ASM_EMIT("vmul.f32 q2, q2, q6") \ 209 __ASM_EMIT("vmul.f32 q3, q3, q7") \ 210 __ASM_EMIT("vstm %[" DST "]!, {q0-q3}") \ 211 __ASM_EMIT("subs %[count], $16") \ 212 __ASM_EMIT("add %[" SRC "], $0x40") \ 213 __ASM_EMIT("bhs 1b") \ 214 /* 8x block */ \ 215 __ASM_EMIT("2:") \ 216 __ASM_EMIT("adds %[count], $8") \ 217 __ASM_EMIT("blt 4f") \ 218 __ASM_EMIT("vldm %[" SEL(SRC, DST) "], {q0-q1}") \ 219 __ASM_EMIT("vldm %[" SEL(DST, SRC) "], {q4-q5}") \ 220 __ASM_EMIT("vabs.f32 " SEL("q0, q0", "q4, q4")) \ 221 __ASM_EMIT("vabs.f32 " SEL("q1, q1", "q5, q5")) \ 222 __ASM_EMIT("vrecpe.f32 q8, q0") /* q8 = s2 */ \ 223 __ASM_EMIT("vrecpe.f32 q9, q1") \ 224 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2) */ \ 225 __ASM_EMIT("vrecps.f32 q13, q9, q1") \ 226 __ASM_EMIT("vmul.f32 q8, q12, q8") /* q8 = s2' = s2 * (2 - R*s2) */ \ 227 __ASM_EMIT("vmul.f32 q9, q13, q9") \ 228 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2') */ \ 229 __ASM_EMIT("vrecps.f32 q13, q9, q1") \ 230 __ASM_EMIT("vmul.f32 q0, q12, q8") /* q0 = s2" = s2' * (2 - R*s2) = 1/s2 */ \ 231 __ASM_EMIT("vmul.f32 q1, q13, q9") \ 232 __ASM_EMIT("vmul.f32 q0, q0, q4") /* s1 / s2 */ \ 233 __ASM_EMIT("vmul.f32 q1, q1, q5") \ 234 __ASM_EMIT("sub %[count], $8") \ 235 __ASM_EMIT("vstm %[" DST "]!, {q0-q1}") \ 236 __ASM_EMIT("add %[" SRC "], $0x20") \ 237 /* 4x blocks */ \ 238 __ASM_EMIT("4:") \ 239 __ASM_EMIT("adds %[count], $4") \ 240 __ASM_EMIT("blt 6f") \ 241 __ASM_EMIT("vldm %[" SEL(SRC, DST) "], {q0}") \ 242 __ASM_EMIT("vldm %[" SEL(DST, SRC) "], {q4}") \ 243 __ASM_EMIT("vabs.f32 " SEL("q0, q0", "q4, q4")) \ 244 __ASM_EMIT("vrecpe.f32 q8, q0") /* q8 = s2 */ \ 245 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2) */ \ 246 __ASM_EMIT("vmul.f32 q8, q12, q8") /* q8 = s2' = s2 * (2 - R*s2) */ \ 247 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2') */ \ 248 __ASM_EMIT("vmul.f32 q0, q12, q8") /* q0 = s2" = s2' * (2 - R*s2) = 1/s2 */ \ 249 __ASM_EMIT("vmul.f32 q0, q0, q4") /* s1 / s2 */ \ 250 __ASM_EMIT("sub %[count], $4") \ 251 __ASM_EMIT("vstm %[" DST "]!, {q0}") \ 252 __ASM_EMIT("add %[" SRC "], $0x10") \ 253 /* 1x blocks */ \ 254 __ASM_EMIT("6:") \ 255 __ASM_EMIT("adds %[count], $3") \ 256 __ASM_EMIT("blt 8f") \ 257 __ASM_EMIT("7:") \ 258 __ASM_EMIT("vld1.32 {d0[], d1[]}, [%[" SEL(SRC, DST) "]]") \ 259 __ASM_EMIT("vld1.32 {d8[], d9[]}, [%[" SEL(DST, SRC) "]]") \ 260 __ASM_EMIT("vabs.f32 " SEL("q0, q0", "q4, q4")) \ 261 __ASM_EMIT("vrecpe.f32 q8, q0") /* q8 = s2 */ \ 262 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2) */ \ 263 __ASM_EMIT("vmul.f32 q8, q12, q8") /* q8 = s2' = s2 * (2 - R*s2) */ \ 264 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2') */ \ 265 __ASM_EMIT("vmul.f32 q0, q12, q8") /* q0 = s2" = s2' * (2 - R*s2) = 1/s2 */ \ 266 __ASM_EMIT("vmul.f32 q0, q0, q4") /* s1 / s2 */ \ 267 __ASM_EMIT("subs %[count], $1") \ 268 __ASM_EMIT("vst1.32 {d0[0]}, [%[" DST "]]!") \ 269 __ASM_EMIT("add %[" SRC "], $0x04") \ 270 __ASM_EMIT("bge 7b") \ 271 __ASM_EMIT("8:") 272 abs_div2(float * dst,const float * src,size_t count)273 void abs_div2(float *dst, const float *src, size_t count) 274 { 275 ARCH_ARM_ASM 276 ( 277 ABS_DIV2_CORE("dst", "src", OP_DSEL) 278 : [dst] "+r" (dst), [src] "+r" (src), 279 [count] "+r" (count) 280 : 281 : "cc", "memory", 282 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 283 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 284 ); 285 } 286 abs_rdiv2(float * dst,const float * src,size_t count)287 void abs_rdiv2(float *dst, const float *src, size_t count) 288 { 289 ARCH_ARM_ASM 290 ( 291 ABS_DIV2_CORE("dst", "src", OP_RSEL) 292 : [dst] "+r" (dst), [src] "+r" (src), 293 [count] "+r" (count) 294 : 295 : "cc", "memory", 296 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 297 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 298 ); 299 } 300 301 #undef ABS_DIV2_CORE 302 303 #define ABS_VV3_CORE(DST, SRC1, SRC2, OP, SEL) \ 304 __ASM_EMIT("subs %[count], $32") \ 305 __ASM_EMIT("blo 2f") \ 306 /* 32x blocks */ \ 307 __ASM_EMIT("1:") \ 308 __ASM_EMIT("vldm %[" SRC1 "]!, {q0-q7}") \ 309 __ASM_EMIT("vldm %[" SRC2 "]!, {q8-q15}") \ 310 __ASM_EMIT("vabs.f32 q8, q8") \ 311 __ASM_EMIT("vabs.f32 q9, q9") \ 312 __ASM_EMIT("vabs.f32 q10, q10") \ 313 __ASM_EMIT("vabs.f32 q11, q11") \ 314 __ASM_EMIT("vabs.f32 q12, q12") \ 315 __ASM_EMIT("vabs.f32 q13, q13") \ 316 __ASM_EMIT("vabs.f32 q14, q14") \ 317 __ASM_EMIT("vabs.f32 q15, q15") \ 318 __ASM_EMIT(OP ".f32 q0, " SEL("q0, q8", "q8, q0")) \ 319 __ASM_EMIT(OP ".f32 q1, " SEL("q1, q9", "q9, q1")) \ 320 __ASM_EMIT(OP ".f32 q2, " SEL("q2, q10", "q10, q2")) \ 321 __ASM_EMIT(OP ".f32 q3, " SEL("q3, q11", "q11, q3")) \ 322 __ASM_EMIT(OP ".f32 q4, " SEL("q4, q12", "q12, q4")) \ 323 __ASM_EMIT(OP ".f32 q5, " SEL("q5, q13", "q13, q5")) \ 324 __ASM_EMIT(OP ".f32 q6, " SEL("q6, q14", "q14, q6")) \ 325 __ASM_EMIT(OP ".f32 q7, " SEL("q7, q15", "q15, q7")) \ 326 __ASM_EMIT("subs %[count], $32") \ 327 __ASM_EMIT("vstm %[" DST "]!, {q0-q7}") \ 328 __ASM_EMIT("bhs 1b") \ 329 /* 16x block */ \ 330 __ASM_EMIT("2:") \ 331 __ASM_EMIT("adds %[count], $16") /* 32 - 16 */ \ 332 __ASM_EMIT("blt 4f") \ 333 __ASM_EMIT("vldm %[" SRC1 "]!, {q0-q3}") \ 334 __ASM_EMIT("vldm %[" SRC2 "]!, {q8-q11}") \ 335 __ASM_EMIT("vabs.f32 q8, q8") \ 336 __ASM_EMIT("vabs.f32 q9, q9") \ 337 __ASM_EMIT("vabs.f32 q10, q10") \ 338 __ASM_EMIT("vabs.f32 q11, q11") \ 339 __ASM_EMIT(OP ".f32 q0, " SEL("q0, q8", "q8, q0")) \ 340 __ASM_EMIT(OP ".f32 q1, " SEL("q1, q9", "q9, q1")) \ 341 __ASM_EMIT(OP ".f32 q2, " SEL("q2, q10", "q10, q2")) \ 342 __ASM_EMIT(OP ".f32 q3, " SEL("q3, q11", "q11, q3")) \ 343 __ASM_EMIT("sub %[count], $16") \ 344 __ASM_EMIT("vstm %[" DST "]!, {q0-q3}") \ 345 /* 8x block */ \ 346 __ASM_EMIT("4:") \ 347 __ASM_EMIT("adds %[count], $8") /* 16 - 8 */ \ 348 __ASM_EMIT("blt 6f") \ 349 __ASM_EMIT("vldm %[" SRC1 "]!, {q0-q1}") \ 350 __ASM_EMIT("vldm %[" SRC2 "]!, {q8-q9}") \ 351 __ASM_EMIT("vabs.f32 q8, q8") \ 352 __ASM_EMIT("vabs.f32 q9, q9") \ 353 __ASM_EMIT(OP ".f32 q0, " SEL("q0, q8", "q8, q0")) \ 354 __ASM_EMIT(OP ".f32 q1, " SEL("q1, q9", "q9, q1")) \ 355 __ASM_EMIT("sub %[count], $8") \ 356 __ASM_EMIT("vstm %[" DST "]!, {q0-q1}") \ 357 /* 4x block */ \ 358 __ASM_EMIT("6:") \ 359 __ASM_EMIT("adds %[count], $4") /* 8 - 4 */ \ 360 __ASM_EMIT("blt 8f") \ 361 __ASM_EMIT("vldm %[" SRC1 "]!, {q0}") \ 362 __ASM_EMIT("vldm %[" SRC2 "]!, {q8}") \ 363 __ASM_EMIT("vabs.f32 q8, q8") \ 364 __ASM_EMIT(OP ".f32 q0, " SEL("q0, q8", "q8, q0")) \ 365 __ASM_EMIT("sub %[count], $4") \ 366 __ASM_EMIT("vstm %[" DST "]!, {q0}") \ 367 /* 1x block */ \ 368 __ASM_EMIT("8:") \ 369 __ASM_EMIT("adds %[count], $3") /* 4 - 3 */ \ 370 __ASM_EMIT("blt 10f") \ 371 __ASM_EMIT("9:") \ 372 __ASM_EMIT("vld1.32 {d0[], d1[]}, [%[" SRC1 "]]!") \ 373 __ASM_EMIT("vld1.32 {d16[], d17[]}, [%[" SRC2 "]]!") \ 374 __ASM_EMIT("vabs.f32 q8, q8") \ 375 __ASM_EMIT(OP ".f32 q0, " SEL("q0, q8", "q8, q0")) \ 376 __ASM_EMIT("subs %[count], $1") \ 377 __ASM_EMIT("vst1.32 {d0[0]}, [%[" DST "]]!") \ 378 __ASM_EMIT("bge 9b") \ 379 __ASM_EMIT("10:") 380 abs_add3(float * dst,const float * src1,const float * src2,size_t count)381 void abs_add3(float *dst, const float *src1, const float *src2, size_t count) 382 { 383 ARCH_ARM_ASM 384 ( 385 ABS_VV3_CORE("dst", "src1", "src2", "vadd", OP_DSEL) 386 : [dst] "+r" (dst), [src1] "+r" (src1), [src2] "+r" (src2), 387 [count] "+r" (count) 388 : 389 : "cc", "memory", 390 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 391 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 392 ); 393 } 394 abs_sub3(float * dst,const float * src1,const float * src2,size_t count)395 void abs_sub3(float *dst, const float *src1, const float *src2, size_t count) 396 { 397 ARCH_ARM_ASM 398 ( 399 ABS_VV3_CORE("dst", "src1", "src2", "vsub", OP_DSEL) 400 : [dst] "+r" (dst), [src1] "+r" (src1), [src2] "+r" (src2), 401 [count] "+r" (count) 402 : 403 : "cc", "memory", 404 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 405 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 406 ); 407 } 408 abs_rsub3(float * dst,const float * src1,const float * src2,size_t count)409 void abs_rsub3(float *dst, const float *src1, const float *src2, size_t count) 410 { 411 ARCH_ARM_ASM 412 ( 413 ABS_VV3_CORE("dst", "src1", "src2", "vsub", OP_RSEL) 414 : [dst] "+r" (dst), [src1] "+r" (src1), [src2] "+r" (src2), 415 [count] "+r" (count) 416 : 417 : "cc", "memory", 418 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 419 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 420 ); 421 } 422 abs_mul3(float * dst,const float * src1,const float * src2,size_t count)423 void abs_mul3(float *dst, const float *src1, const float *src2, size_t count) 424 { 425 ARCH_ARM_ASM 426 ( 427 ABS_VV3_CORE("dst", "src1", "src2", "vmul", OP_DSEL) 428 : [dst] "+r" (dst), [src1] "+r" (src1), [src2] "+r" (src2), 429 [count] "+r" (count) 430 : 431 : "cc", "memory", 432 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 433 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 434 ); 435 } 436 #undef ABS_VV3_CORE 437 438 #define ABS_DIV3_CORE(DST, SRC1, SRC2, SEL) \ 439 __ASM_EMIT("subs %[count], $16") \ 440 __ASM_EMIT("blo 2f") \ 441 /* 16x blocks */ \ 442 __ASM_EMIT("1:") \ 443 __ASM_EMIT("vldm %[" SEL(SRC2, SRC1) "]!, {q0-q3}") \ 444 __ASM_EMIT("vldm %[" SEL(SRC1, SRC2) "]!, {q4-q7}") \ 445 __ASM_EMIT("vabs.f32 " SEL("q0, q0", "q4, q4")) \ 446 __ASM_EMIT("vabs.f32 " SEL("q1, q1", "q5, q5")) \ 447 __ASM_EMIT("vabs.f32 " SEL("q2, q2", "q6, q6")) \ 448 __ASM_EMIT("vabs.f32 " SEL("q3, q3", "q7, q7")) \ 449 __ASM_EMIT("vrecpe.f32 q8, q0") /* q8 = s2 */ \ 450 __ASM_EMIT("vrecpe.f32 q9, q1") \ 451 __ASM_EMIT("vrecpe.f32 q10, q2") \ 452 __ASM_EMIT("vrecpe.f32 q11, q3") \ 453 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2) */ \ 454 __ASM_EMIT("vrecps.f32 q13, q9, q1") \ 455 __ASM_EMIT("vrecps.f32 q14, q10, q2") \ 456 __ASM_EMIT("vrecps.f32 q15, q11, q3") \ 457 __ASM_EMIT("vmul.f32 q8, q12, q8") /* q8 = s2' = s2 * (2 - R*s2) */ \ 458 __ASM_EMIT("vmul.f32 q9, q13, q9") \ 459 __ASM_EMIT("vmul.f32 q10, q14, q10") \ 460 __ASM_EMIT("vmul.f32 q11, q15, q11") \ 461 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2') */ \ 462 __ASM_EMIT("vrecps.f32 q13, q9, q1") \ 463 __ASM_EMIT("vrecps.f32 q14, q10, q2") \ 464 __ASM_EMIT("vrecps.f32 q15, q11, q3") \ 465 __ASM_EMIT("vmul.f32 q0, q12, q8") /* q0 = s2" = s2' * (2 - R*s2) = 1/s2 */ \ 466 __ASM_EMIT("vmul.f32 q1, q13, q9") \ 467 __ASM_EMIT("vmul.f32 q2, q14, q10") \ 468 __ASM_EMIT("vmul.f32 q3, q15, q11") \ 469 __ASM_EMIT("vmul.f32 q0, q0, q4") /* s1 / s2 */ \ 470 __ASM_EMIT("vmul.f32 q1, q1, q5") \ 471 __ASM_EMIT("vmul.f32 q2, q2, q6") \ 472 __ASM_EMIT("vmul.f32 q3, q3, q7") \ 473 __ASM_EMIT("vstm %[" DST "]!, {q0-q3}") \ 474 __ASM_EMIT("subs %[count], $16") \ 475 __ASM_EMIT("bhs 1b") \ 476 /* 8x block */ \ 477 __ASM_EMIT("2:") \ 478 __ASM_EMIT("adds %[count], $8") \ 479 __ASM_EMIT("blt 4f") \ 480 __ASM_EMIT("vldm %[" SEL(SRC2, SRC1) "]!, {q0-q1}") \ 481 __ASM_EMIT("vldm %[" SEL(SRC1, SRC2) "]!, {q4-q5}") \ 482 __ASM_EMIT("vabs.f32 " SEL("q0, q0", "q4, q4")) \ 483 __ASM_EMIT("vabs.f32 " SEL("q1, q1", "q5, q5")) \ 484 __ASM_EMIT("vrecpe.f32 q8, q0") /* q8 = s2 */ \ 485 __ASM_EMIT("vrecpe.f32 q9, q1") \ 486 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2) */ \ 487 __ASM_EMIT("vrecps.f32 q13, q9, q1") \ 488 __ASM_EMIT("vmul.f32 q8, q12, q8") /* q8 = s2' = s2 * (2 - R*s2) */ \ 489 __ASM_EMIT("vmul.f32 q9, q13, q9") \ 490 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2') */ \ 491 __ASM_EMIT("vrecps.f32 q13, q9, q1") \ 492 __ASM_EMIT("vmul.f32 q0, q12, q8") /* q0 = s2" = s2' * (2 - R*s2) = 1/s2 */ \ 493 __ASM_EMIT("vmul.f32 q1, q13, q9") \ 494 __ASM_EMIT("vmul.f32 q0, q0, q4") /* s1 / s2 */ \ 495 __ASM_EMIT("vmul.f32 q1, q1, q5") \ 496 __ASM_EMIT("sub %[count], $8") \ 497 __ASM_EMIT("vstm %[" DST "]!, {q0-q1}") \ 498 /* 4x blocks */ \ 499 __ASM_EMIT("4:") \ 500 __ASM_EMIT("adds %[count], $4") \ 501 __ASM_EMIT("blt 6f") \ 502 __ASM_EMIT("vldm %[" SEL(SRC2, SRC1) "]!, {q0}") \ 503 __ASM_EMIT("vldm %[" SEL(SRC1, SRC2) "]!, {q4}") \ 504 __ASM_EMIT("vabs.f32 " SEL("q0, q0", "q4, q4")) \ 505 __ASM_EMIT("vrecpe.f32 q8, q0") /* q8 = s2 */ \ 506 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2) */ \ 507 __ASM_EMIT("vmul.f32 q8, q12, q8") /* q8 = s2' = s2 * (2 - R*s2) */ \ 508 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2') */ \ 509 __ASM_EMIT("vmul.f32 q0, q12, q8") /* q0 = s2" = s2' * (2 - R*s2) = 1/s2 */ \ 510 __ASM_EMIT("vmul.f32 q0, q0, q4") /* s1 / s2 */ \ 511 __ASM_EMIT("sub %[count], $4") \ 512 __ASM_EMIT("vstm %[" DST "]!, {q0}") \ 513 /* 1x blocks */ \ 514 __ASM_EMIT("6:") \ 515 __ASM_EMIT("adds %[count], $3") \ 516 __ASM_EMIT("blt 8f") \ 517 __ASM_EMIT("7:") \ 518 __ASM_EMIT("vld1.32 {d0[], d1[]}, [%[" SEL(SRC2, SRC1) "]]!") \ 519 __ASM_EMIT("vld1.32 {d8[], d9[]}, [%[" SEL(SRC1, SRC2) "]]!") \ 520 __ASM_EMIT("vabs.f32 " SEL("q0, q0", "q4, q4")) \ 521 __ASM_EMIT("vrecpe.f32 q8, q0") /* q8 = s2 */ \ 522 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2) */ \ 523 __ASM_EMIT("vmul.f32 q8, q12, q8") /* q8 = s2' = s2 * (2 - R*s2) */ \ 524 __ASM_EMIT("vrecps.f32 q12, q8, q0") /* q12 = (2 - R*s2') */ \ 525 __ASM_EMIT("vmul.f32 q0, q12, q8") /* q0 = s2" = s2' * (2 - R*s2) = 1/s2 */ \ 526 __ASM_EMIT("vmul.f32 q0, q0, q4") /* s1 / s2 */ \ 527 __ASM_EMIT("subs %[count], $1") \ 528 __ASM_EMIT("vst1.32 {d0[0]}, [%[" DST "]]!") \ 529 __ASM_EMIT("bge 7b") \ 530 __ASM_EMIT("8:") 531 abs_div3(float * dst,const float * src1,const float * src2,size_t count)532 void abs_div3(float *dst, const float *src1, const float *src2, size_t count) 533 { 534 ARCH_ARM_ASM 535 ( 536 ABS_DIV3_CORE("dst", "src1", "src2", OP_DSEL) 537 : [dst] "+r" (dst), [src1] "+r" (src1), [src2] "+r" (src2), 538 [count] "+r" (count) 539 : 540 : "cc", "memory", 541 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 542 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 543 ); 544 } 545 abs_rdiv3(float * dst,const float * src1,const float * src2,size_t count)546 void abs_rdiv3(float *dst, const float *src1, const float *src2, size_t count) 547 { 548 ARCH_ARM_ASM 549 ( 550 ABS_DIV3_CORE("dst", "src1", "src2", OP_RSEL) 551 : [dst] "+r" (dst), [src1] "+r" (src1), [src2] "+r" (src2), 552 [count] "+r" (count) 553 : 554 : "cc", "memory", 555 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7", 556 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" 557 ); 558 } 559 560 #undef ABS_DIV3_CORE 561 abs1(float * dst,size_t count)562 void abs1(float *dst, size_t count) 563 { 564 ARCH_ARM_ASM 565 ( 566 /* 32x block */ 567 __ASM_EMIT("subs %[count], $32") 568 __ASM_EMIT("blt 2f") 569 __ASM_EMIT("1:") 570 __ASM_EMIT("vldm %[dst], {q0-q7}") 571 __ASM_EMIT("vabs.f32 q0, q0") 572 __ASM_EMIT("vabs.f32 q1, q1") 573 __ASM_EMIT("vabs.f32 q2, q2") 574 __ASM_EMIT("vabs.f32 q3, q3") 575 __ASM_EMIT("vabs.f32 q4, q4") 576 __ASM_EMIT("vabs.f32 q5, q5") 577 __ASM_EMIT("vabs.f32 q6, q6") 578 __ASM_EMIT("vabs.f32 q7, q7") 579 __ASM_EMIT("vstm %[dst]!, {q0-q7}") 580 __ASM_EMIT("subs %[count], %[count], $32") 581 __ASM_EMIT("bhs 1b") 582 /* 16x block */ 583 __ASM_EMIT("2:") 584 __ASM_EMIT("adds %[count], $16") // 32-16 585 __ASM_EMIT("blt 4f") 586 __ASM_EMIT("vldm %[dst], {q0-q3}") 587 __ASM_EMIT("vabs.f32 q0, q0") 588 __ASM_EMIT("vabs.f32 q1, q1") 589 __ASM_EMIT("vabs.f32 q2, q2") 590 __ASM_EMIT("vabs.f32 q3, q3") 591 __ASM_EMIT("vstm %[dst]!, {q0-q3}") 592 __ASM_EMIT("sub %[count], %[count], $16") 593 /* 8x block */ 594 __ASM_EMIT("4:") 595 __ASM_EMIT("adds %[count], $8") // 16-8 596 __ASM_EMIT("blt 6f") 597 __ASM_EMIT("vldm %[dst], {q0-q1}") 598 __ASM_EMIT("vabs.f32 q0, q0") 599 __ASM_EMIT("vabs.f32 q1, q1") 600 __ASM_EMIT("vstm %[dst]!, {q0-q1}") 601 __ASM_EMIT("sub %[count], $8") 602 /* 4x block */ 603 __ASM_EMIT("6:") 604 __ASM_EMIT("adds %[count], $4") // 8-4 605 __ASM_EMIT("blt 8f") 606 __ASM_EMIT("vldm %[dst], {q0}") 607 __ASM_EMIT("vabs.f32 q0, q0") 608 __ASM_EMIT("vabs.f32 q1, q1") 609 __ASM_EMIT("vstm %[dst]!, {q0}") 610 __ASM_EMIT("sub %[count], $4") 611 /* 1x blocks */ 612 __ASM_EMIT("8:") 613 __ASM_EMIT("adds %[count], $3") // 4-1 614 __ASM_EMIT("blt 10f") 615 __ASM_EMIT("13:") 616 __ASM_EMIT("vld1.32 {d0[], d1[]}, [%[dst]]") 617 __ASM_EMIT("vabs.f32 q0, q0") 618 __ASM_EMIT("vst1.32 {d0[0]}, [%[dst]]!") 619 __ASM_EMIT("subs %[count], $1") 620 __ASM_EMIT("bge 13b") 621 622 /* End of copy */ 623 __ASM_EMIT("10:") 624 625 : [dst] "+r" (dst), 626 [count] "+r" (count) 627 : 628 : "cc", "memory", 629 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7" 630 ); 631 } 632 abs2(float * dst,const float * src,size_t count)633 void abs2(float *dst, const float *src, size_t count) 634 { 635 ARCH_ARM_ASM 636 ( 637 /* 32x block */ 638 __ASM_EMIT("subs %[count], $32") 639 __ASM_EMIT("blt 2f") 640 __ASM_EMIT("1:") 641 __ASM_EMIT("vldm %[src]!, {q0-q7}") 642 __ASM_EMIT("vabs.f32 q0, q0") 643 __ASM_EMIT("vabs.f32 q1, q1") 644 __ASM_EMIT("vabs.f32 q2, q2") 645 __ASM_EMIT("vabs.f32 q3, q3") 646 __ASM_EMIT("vabs.f32 q4, q4") 647 __ASM_EMIT("vabs.f32 q5, q5") 648 __ASM_EMIT("vabs.f32 q6, q6") 649 __ASM_EMIT("vabs.f32 q7, q7") 650 __ASM_EMIT("vstm %[dst]!, {q0-q7}") 651 __ASM_EMIT("subs %[count], %[count], $32") 652 __ASM_EMIT("bhs 1b") 653 /* 16x block */ 654 __ASM_EMIT("2:") 655 __ASM_EMIT("adds %[count], $16") // 32-16 656 __ASM_EMIT("blt 4f") 657 __ASM_EMIT("vldm %[src]!, {q0-q3}") 658 __ASM_EMIT("vabs.f32 q0, q0") 659 __ASM_EMIT("vabs.f32 q1, q1") 660 __ASM_EMIT("vabs.f32 q2, q2") 661 __ASM_EMIT("vabs.f32 q3, q3") 662 __ASM_EMIT("vstm %[dst]!, {q0-q3}") 663 __ASM_EMIT("sub %[count], %[count], $16") 664 /* 8x block */ 665 __ASM_EMIT("4:") 666 __ASM_EMIT("adds %[count], $8") // 16-8 667 __ASM_EMIT("blt 6f") 668 __ASM_EMIT("vldm %[src]!, {q0-q1}") 669 __ASM_EMIT("vabs.f32 q0, q0") 670 __ASM_EMIT("vabs.f32 q1, q1") 671 __ASM_EMIT("vstm %[dst]!, {q0-q1}") 672 __ASM_EMIT("sub %[count], $8") 673 /* 4x block */ 674 __ASM_EMIT("6:") 675 __ASM_EMIT("adds %[count], $4") // 8-4 676 __ASM_EMIT("blt 8f") 677 __ASM_EMIT("vldm %[src]!, {q0}") 678 __ASM_EMIT("vabs.f32 q0, q0") 679 __ASM_EMIT("vabs.f32 q1, q1") 680 __ASM_EMIT("vstm %[dst]!, {q0}") 681 __ASM_EMIT("sub %[count], $4") 682 /* 1x blocks */ 683 __ASM_EMIT("8:") 684 __ASM_EMIT("adds %[count], $3") // 4-1 685 __ASM_EMIT("blt 10f") 686 __ASM_EMIT("13:") 687 __ASM_EMIT("vld1.32 {d0[], d1[]}, [%[src]]!") 688 __ASM_EMIT("vabs.f32 q0, q0") 689 __ASM_EMIT("vst1.32 {d0[0]}, [%[dst]]!") 690 __ASM_EMIT("subs %[count], $1") 691 __ASM_EMIT("bge 13b") 692 693 /* End of copy */ 694 __ASM_EMIT("10:") 695 696 : [dst] "+r" (dst), [src] "+r" (src), 697 [count] "+r" (count) 698 : 699 : "cc", "memory", 700 "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7" 701 ); 702 } 703 704 } 705 706 707 #endif /* DSP_ARCH_ARM_NEON_D32_PMATH_ABS_VV_H_ */ 708