|
| 1 | +#ifdef __ARM_NEON__ |
| 2 | +#include <arm_neon.h> |
| 3 | +#endif |
1 | 4 | #include <math.h> |
2 | 5 | #include <string.h> |
3 | 6 |
|
@@ -91,8 +94,15 @@ void vec_shiftr_q128(NO_CPU, union xmm_reg *amount, union xmm_reg *dst) { |
91 | 94 | } |
92 | 95 |
|
93 | 96 | void vec_add_b128(NO_CPU, union xmm_reg *src, union xmm_reg *dst) { |
| 97 | +#ifdef __ARM_NEON__ |
| 98 | + uint8x16_t neon_dst = vld1q_u8(dst->u8); |
| 99 | + uint8x16_t neon_src = vld1q_u8(src->u8); |
| 100 | + uint8x16_t neon_res = vaddq_u8(neon_dst, neon_src); |
| 101 | + vst1q_u8(dst->u8, neon_res); |
| 102 | +#else |
94 | 103 | for (unsigned i = 0; i < array_size(src->u8); i++) |
95 | 104 | dst->u8[i] += src->u8[i]; |
| 105 | +#endif |
96 | 106 | } |
97 | 107 | void vec_add_d128(NO_CPU, union xmm_reg *src, union xmm_reg *dst) { |
98 | 108 | for (unsigned i = 0; i < array_size(src->u32); i++) |
@@ -142,9 +152,16 @@ void vec_xor64(NO_CPU, union mm_reg *src, union mm_reg *dst) { |
142 | 152 | } |
143 | 153 |
|
144 | 154 | void vec_min_ub128(NO_CPU, union xmm_reg *src, union xmm_reg *dst) { |
| 155 | +#ifdef __ARM_NEON__ |
| 156 | + uint8x16_t neon_dst = vld1q_u8(dst->u8); |
| 157 | + uint8x16_t neon_src = vld1q_u8(src->u8); |
| 158 | + uint8x16_t neon_res = vminq_u8(neon_dst, neon_src); |
| 159 | + vst1q_u8(dst->u8, neon_res); |
| 160 | +#else |
145 | 161 | for (unsigned i = 0; i < array_size(src->u8); i++) |
146 | 162 | if (src->u8[i] < dst->u8[i]) |
147 | 163 | dst->u8[i] = src->u8[i]; |
| 164 | +#endif |
148 | 165 | } |
149 | 166 |
|
150 | 167 | static bool cmpd(double a, double b, int type) { |
@@ -253,20 +270,46 @@ void vec_shuffle_d128(NO_CPU, const union xmm_reg *src, union xmm_reg *dst, uint |
253 | 270 | } |
254 | 271 |
|
255 | 272 | void vec_compare_eqb128(NO_CPU, const union xmm_reg *src, union xmm_reg *dst) { |
| 273 | +#ifdef __ARM_NEON__ |
| 274 | + uint8x16_t neon_dst = vld1q_u8(dst->u8); |
| 275 | + uint8x16_t neon_src = vld1q_u8(src->u8); |
| 276 | + uint8x16_t neon_res = vceqq_u8(neon_dst, neon_src); |
| 277 | + vst1q_u8(dst->u8, neon_res); |
| 278 | +#else |
256 | 279 | for (unsigned i = 0; i < array_size(src->u8); i++) |
257 | 280 | dst->u8[i] = dst->u8[i] == src->u8[i] ? ~0 : 0; |
| 281 | +#endif |
258 | 282 | } |
259 | 283 | void vec_compare_eqd128(NO_CPU, const union xmm_reg *src, union xmm_reg *dst) { |
260 | 284 | for (unsigned i = 0; i < array_size(src->u32); i++) |
261 | 285 | dst->u32[i] = dst->u32[i] == src->u32[i] ? ~0 : 0; |
262 | 286 | } |
263 | 287 |
|
| 288 | +/* |
| 289 | + * Neon algo: (only one part (64bits) is demonstrated, algo works the same for another part) |
| 290 | + * z - is a bit which forms the mask, X - is not interesting bit. |
| 291 | + * neon_src: zXXXXXXXzXXXXXXXzXXXXXXXzXXXXXXXzXXXXXXXzXXXXXXXzXXXXXXXzXXXXXXX... |
| 292 | + * step1: 0000000z0000000z0000000z0000000z0000000z0000000z0000000z0000000z... |
| 293 | + * step2: 00000000000000zz00000000000000zz00000000000000zz00000000000000zz... |
| 294 | + * step3: 0000000000000000000000000000zzzz0000000000000000000000000000zzzz... |
| 295 | + * step4: 00000000000000000000000000000000000000000000000000000000zzzzzzzz... |
| 296 | + * After step4, 8 bits at the end of each 64bit lane are loaded into dst. |
| 297 | + */ |
264 | 298 | void vec_movmask_b128(NO_CPU, const union xmm_reg *src, uint32_t *dst) { |
265 | 299 | *dst = 0; |
| 300 | +#if defined(__ARM_NEON__) && defined(__LITTLE_ENDIAN__) |
| 301 | + uint8x16_t neon_src = vld1q_u8(src->u8); |
| 302 | + uint16x8_t step1 = vshrq_n_u8(neon_src, 7); |
| 303 | + uint32x4_t step2 = vsraq_n_u16(step1, step1, 7); |
| 304 | + uint64x2_t step3 = vsraq_n_u32(step2, step2, 14); |
| 305 | + uint16x8_t step4 = vsraq_n_u64(step3, step3, 28); |
| 306 | + *dst |= (vgetq_lane_u8(step4, 8) << 8) | (vgetq_lane_u8(step4, 0)); |
| 307 | +#else |
266 | 308 | for (unsigned i = 0; i < array_size(src->u8); i++) { |
267 | 309 | if (src->u8[i] & (1 << 7)) |
268 | 310 | *dst |= 1 << i; |
269 | 311 | } |
| 312 | +#endif |
270 | 313 | } |
271 | 314 |
|
272 | 315 | void vec_fmovmask_d128(NO_CPU, const union xmm_reg *src, uint32_t *dst) { |
|
0 commit comments