Mercurial > vec
comparison src/impl/arm/neon.c @ 31:bf6ad516f1e6
Backed out changeset c6c99ab1088a
| author | Paper <paper@tflc.us> |
|---|---|
| date | Fri, 25 Apr 2025 17:40:33 -0400 |
| parents | c6c99ab1088a |
| children | 0de48dc864ea |
comparison
equal
deleted
inserted
replaced
| 30:641d8c79b1da | 31:bf6ad516f1e6 |
|---|---|
| 37 }; \ | 37 }; \ |
| 38 \ | 38 \ |
| 39 VEC_STATIC_ASSERT(VEC_ALIGNOF(sign##int##bits##x##size##_t) <= VEC_ALIGNOF(v##sign##int##bits##x##size), "vec: v" #sign "int" #bits "x" #size " alignment needs to be expanded to fit intrinsic type size"); \ | 39 VEC_STATIC_ASSERT(VEC_ALIGNOF(sign##int##bits##x##size##_t) <= VEC_ALIGNOF(v##sign##int##bits##x##size), "vec: v" #sign "int" #bits "x" #size " alignment needs to be expanded to fit intrinsic type size"); \ |
| 40 VEC_STATIC_ASSERT(sizeof(sign##int##bits##x##size##_t) <= sizeof(v##sign##int##bits##x##size), "vec: v" #sign "int" #bits "x" #size " needs to be expanded to fit intrinsic type size"); \ | 40 VEC_STATIC_ASSERT(sizeof(sign##int##bits##x##size##_t) <= sizeof(v##sign##int##bits##x##size), "vec: v" #sign "int" #bits "x" #size " needs to be expanded to fit intrinsic type size"); \ |
| 41 \ | 41 \ |
| 42 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_load_aligned(const vec_##sign##int##bits in[size]) \ | 42 static v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_load_aligned(const vec_##sign##int##bits in[size]) \ |
| 43 { \ | 43 { \ |
| 44 union v##sign##int##bits##x##size##_impl_data vec; \ | 44 union v##sign##int##bits##x##size##_impl_data vec; \ |
| 45 vec.neon = vld1_##sign##bits(in); \ | 45 vec.neon = vld1_##sign##bits(in); \ |
| 46 return vec.vec; \ | 46 return vec.vec; \ |
| 47 } \ | 47 } \ |
| 48 \ | 48 \ |
| 49 VEC_FUNC_IMPL void v##sign##int##bits##x##size##_neon_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ | 49 static void v##sign##int##bits##x##size##_neon_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ |
| 50 { \ | 50 { \ |
| 51 vstore_lane_##bits(sign, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->neon, out); \ | 51 vstore_lane_##bits(sign, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->neon, out); \ |
| 52 } \ | 52 } \ |
| 53 \ | 53 \ |
| 54 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_add(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 54 static v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_add(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 55 { \ | 55 { \ |
| 56 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 56 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 57 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 57 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
| 58 \ | 58 \ |
| 59 vec1d->neon = vadd_##sign##bits(vec1d->neon, vec2d->neon); \ | 59 vec1d->neon = vadd_##sign##bits(vec1d->neon, vec2d->neon); \ |
| 60 return vec1d->vec; \ | 60 return vec1d->vec; \ |
| 61 } \ | 61 } \ |
| 62 \ | 62 \ |
| 63 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_sub(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 63 static v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_sub(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 64 { \ | 64 { \ |
| 65 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 65 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 66 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 66 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
| 67 \ | 67 \ |
| 68 vec1d->neon = vsub_##sign##bits(vec1d->neon, vec2d->neon); \ | 68 vec1d->neon = vsub_##sign##bits(vec1d->neon, vec2d->neon); \ |
| 69 return vec1d->vec; \ | 69 return vec1d->vec; \ |
| 70 } \ | 70 } \ |
| 71 \ | 71 \ |
| 72 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_mul(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 72 static v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_mul(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 73 { \ | 73 { \ |
| 74 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 74 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 75 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 75 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
| 76 \ | 76 \ |
| 77 vec1d->neon = vmul_##sign##bits(vec1d->neon, vec2d->neon); \ | 77 vec1d->neon = vmul_##sign##bits(vec1d->neon, vec2d->neon); \ |
| 78 return vec1d->vec; \ | 78 return vec1d->vec; \ |
| 79 } \ | 79 } \ |
| 80 \ | 80 \ |
| 81 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_lshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \ | 81 static v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_lshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \ |
| 82 { \ | 82 { \ |
| 83 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 83 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 84 union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \ | 84 union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \ |
| 85 \ | 85 \ |
| 86 vec1d->neon = vshl_##sign##bits(vec1d->neon, (vreinterpret_##bits##_u##bits)vec2d->neon); \ | 86 vec1d->neon = vshl_##sign##bits(vec1d->neon, (vreinterpret_##bits##_u##bits)vec2d->neon); \ |
| 87 return vec1d->vec; \ | 87 return vec1d->vec; \ |
| 88 } \ | 88 } \ |
| 89 \ | 89 \ |
| 90 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 90 static v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 91 { \ | 91 { \ |
| 92 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 92 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 93 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 93 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
| 94 \ | 94 \ |
| 95 vec1d->neon = vand_##sign##bits(vec1d->neon, vec2d->neon); \ | 95 vec1d->neon = vand_##sign##bits(vec1d->neon, vec2d->neon); \ |
| 96 return vec1d->vec; \ | 96 return vec1d->vec; \ |
| 97 } \ | 97 } \ |
| 98 \ | 98 \ |
| 99 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_or(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 99 static v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_or(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 100 { \ | 100 { \ |
| 101 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 101 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 102 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 102 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
| 103 \ | 103 \ |
| 104 vec1d->neon = vorr_##sign##bits(vec1d->neon, vec2d->neon); \ | 104 vec1d->neon = vorr_##sign##bits(vec1d->neon, vec2d->neon); \ |
| 105 return vec1d->vec; \ | 105 return vec1d->vec; \ |
| 106 } \ | 106 } \ |
| 107 \ | 107 \ |
| 108 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_xor(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 108 static v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_xor(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 109 { \ | 109 { \ |
| 110 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 110 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 111 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 111 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
| 112 \ | 112 \ |
| 113 vec1d->neon = veor_##sign##bits(vec1d->neon, vec2d->neon); \ | 113 vec1d->neon = veor_##sign##bits(vec1d->neon, vec2d->neon); \ |
| 114 return vec1d->vec; \ | 114 return vec1d->vec; \ |
| 115 } \ | 115 } \ |
| 116 \ | 116 \ |
| 117 const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_neon = { \ | 117 static v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_neon = { \ |
| 118 .load = v##sign##int##bits##x##size##_neon_load_aligned, \ | 118 v##sign##int##bits##x##size##_fallback_splat, \ |
| 119 .load_aligned = v##sign##int##bits##x##size##_neon_load_aligned, \ | 119 v##sign##int##bits##x##size##_neon_load_aligned, \ |
| 120 .store = v##sign##int##bits##x##size##_neon_store_aligned, \ | 120 v##sign##int##bits##x##size##_neon_load_aligned, \ |
| 121 .store_aligned = v##sign##int##bits##x##size##_neon_store_aligned, \ | 121 v##sign##int##bits##x##size##_neon_store_aligned, \ |
| 122 .add = v##sign##int##bits##x##size##_neon_add, \ | 122 v##sign##int##bits##x##size##_neon_store_aligned, \ |
| 123 .sub = v##sign##int##bits##x##size##_neon_sub, \ | 123 v##sign##int##bits##x##size##_neon_add, \ |
| 124 .mul = v##sign##int##bits##x##size##_neon_mul, \ | 124 v##sign##int##bits##x##size##_neon_sub, \ |
| 125 .band = v##sign##int##bits##x##size##_neon_and, \ | 125 v##sign##int##bits##x##size##_neon_mul, \ |
| 126 .bor = v##sign##int##bits##x##size##_neon_or, \ | 126 v##sign##int##bits##x##size##_fallback_div, \ |
| 127 .bxor = v##sign##int##bits##x##size##_neon_xor, \ | 127 v##sign##int##bits##x##size##_fallback_avg, \ |
| 128 .lshift = v##sign##int##bits##x##size##_neon_lshift, \ | 128 v##sign##int##bits##x##size##_neon_and, \ |
| 129 v##sign##int##bits##x##size##_neon_or, \ | |
| 130 v##sign##int##bits##x##size##_neon_xor, \ | |
| 131 v##sign##int##bits##x##size##_fallback_not, \ | |
| 132 v##sign##int##bits##x##size##_neon_lshift, \ | |
| 133 v##sign##int##bits##x##size##_fallback_rshift, \ | |
| 134 v##sign##int##bits##x##size##_fallback_lrshift, \ | |
| 135 v##sign##int##bits##x##size##_fallback_cmplt, \ | |
| 136 v##sign##int##bits##x##size##_fallback_cmple, \ | |
| 137 v##sign##int##bits##x##size##_fallback_cmpeq, \ | |
| 138 v##sign##int##bits##x##size##_fallback_cmpge, \ | |
| 139 v##sign##int##bits##x##size##_fallback_cmpgt, \ | |
| 129 }; | 140 }; |
| 130 | 141 |
| 131 #define VEC_DEFINE_OPERATIONS(bits, size) \ | 142 #define VEC_DEFINE_OPERATIONS(bits, size) \ |
| 132 VEC_DEFINE_OPERATIONS_SIGN(u, U, bits, size) \ | 143 VEC_DEFINE_OPERATIONS_SIGN(u, U, bits, size) \ |
| 133 VEC_DEFINE_OPERATIONS_SIGN( , , bits, size) | 144 VEC_DEFINE_OPERATIONS_SIGN( , , bits, size) |
| 231 | 242 |
| 232 // Now we can go ahead and do the 128-bit ones. | 243 // Now we can go ahead and do the 128-bit ones. |
| 233 | 244 |
| 234 // NEON doesn't have native 64-bit multiplication, so we have | 245 // NEON doesn't have native 64-bit multiplication, so we have |
| 235 // to do it ourselves | 246 // to do it ourselves |
| 236 VEC_FUNC_IMPL int64x2_t vmulq_s64(const int64x2_t a, const int64x2_t b) | 247 static inline int64x2_t vmulq_s64(const int64x2_t a, const int64x2_t b) |
| 237 { | 248 { |
| 238 const uint32x2_t ac = vreinterpret_u32_s32(vmovn_s64(a)); | 249 const uint32x2_t ac = vreinterpret_u32_s32(vmovn_s64(a)); |
| 239 const uint32x2_t pr = vreinterpret_u32_s32(vmovn_s64(b)); | 250 const uint32x2_t pr = vreinterpret_u32_s32(vmovn_s64(b)); |
| 240 | 251 |
| 241 const int32x4_t hi = vmulq_s32(vreinterpretq_s32_s64(b), vreinterpretq_s32_s64(a)); | 252 const int32x4_t hi = vmulq_s32(vreinterpretq_s32_s64(b), vreinterpretq_s32_s64(a)); |
| 242 | 253 |
| 243 return vreinterpretq_s64_u64(vmlal_u32(vreinterpretq_u64_s64(vshlq_n_s64(vreinterpretq_s64_u64(vpaddlq_u32(vreinterpretq_u32_s32(hi))), 32)), ac, pr)); | 254 return vreinterpretq_s64_u64(vmlal_u32(vreinterpretq_u64_s64(vshlq_n_s64(vreinterpretq_s64_u64(vpaddlq_u32(vreinterpretq_u32_s32(hi))), 32)), ac, pr)); |
| 244 } | 255 } |
| 245 | 256 |
| 246 VEC_FUNC_IMPL uint64x2_t vmulq_u64(const uint64x2_t a, const uint64x2_t b) | 257 static inline uint64x2_t vmulq_u64(const uint64x2_t a, const uint64x2_t b) |
| 247 { | 258 { |
| 248 const uint32x2_t ac = vmovn_u64(a); | 259 const uint32x2_t ac = vmovn_u64(a); |
| 249 const uint32x2_t pr = vmovn_u64(b); | 260 const uint32x2_t pr = vmovn_u64(b); |
| 250 | 261 |
| 251 const uint32x4_t hi = vmulq_u32(vreinterpretq_u32_u64(b), vreinterpretq_u32_u64(a)); | 262 const uint32x4_t hi = vmulq_u32(vreinterpretq_u32_u64(b), vreinterpretq_u32_u64(a)); |
