comparison src/impl/arm/neon.c @ 27:d00b95f95dd1 default tip

impl/arm/neon: it compiles again, but is untested
author Paper <paper@tflc.us>
date Mon, 25 Nov 2024 00:33:02 -0500
parents e26874655738
children
comparison
equal deleted inserted replaced
26:6c91cd9a2f2d 27:d00b95f95dd1
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE. 22 * SOFTWARE.
23 **/ 23 **/
24 24
25 #include "vec/impl/arm/neon.h" 25 #include "vec/impl/arm/neon.h"
26 #include "vec/impl/generic.h"
26 27
27 #include <arm_neon.h> 28 #include <arm_neon.h>
28 29
29 // There is LOTS of preprocessor hacking here (as if the other files 30 // There is LOTS of preprocessor hacking here (as if the other files
30 // weren't bad enough... lol) 31 // weren't bad enough... lol)
31 32
32 #define VEC_DEFINE_OPERATIONS_SIGN(sign, csign, bits, size) \ 33 #define VEC_DEFINE_OPERATIONS_SIGN(sign, csign, bits, size) \
34 union v##sign##int##bits##x##size##_impl_data { \
35 v##sign##int##bits##x##size vec; \
36 sign##int##bits##x##size##_t neon; \
37 }; \
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"); \
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 \
33 static 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]) \
34 { \ 43 { \
35 v##sign##int##bits##x##size vec; \ 44 union v##sign##int##bits##x##size##_impl_data vec; \
36 vec.neon = vld1_##sign##bits(in); \ 45 vec.neon = vld1_##sign##bits(in); \
37 return vec; \ 46 return vec.vec; \
38 } \ 47 } \
39 \ 48 \
40 static 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]) \
41 { \ 50 { \
42 vstore_lane_##bits(sign, vec.neon, out); \ 51 vstore_lane_##bits(sign, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->neon, out); \
43 } \ 52 } \
44 \ 53 \
45 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) \ 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) \
46 { \ 55 { \
47 v##sign##int##bits##x##size vec; \ 56 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
48 vec.neon = vadd_##sign##bits(vec1.neon, vec2.neon); \ 57 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
49 return vec; \ 58 \
59 vec1d->neon = vadd_##sign##bits(vec1d->neon, vec2d->neon); \
60 return vec1d->vec; \
50 } \ 61 } \
51 \ 62 \
52 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) \ 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) \
53 { \ 64 { \
54 v##sign##int##bits##x##size vec; \ 65 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
55 vec.neon = vsub_##sign##bits(vec1.neon, vec2.neon); \ 66 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
56 return vec; \ 67 \
68 vec1d->neon = vsub_##sign##bits(vec1d->neon, vec2d->neon); \
69 return vec1d->vec; \
57 } \ 70 } \
58 \ 71 \
59 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) \ 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) \
60 { \ 73 { \
61 v##sign##int##bits##x##size vec; \ 74 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
62 vec.neon = vmul_##sign##bits(vec1.neon, vec2.neon); \ 75 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
63 return vec; \ 76 \
77 vec1d->neon = vmul_##sign##bits(vec1d->neon, vec2d->neon); \
78 return vec1d->vec; \
64 } \ 79 } \
65 \ 80 \
66 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) \ 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) \
67 { \ 82 { \
68 v##sign##int##bits##x##size vec; \ 83 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
69 vec.neon = vshl_##sign##bits(vec1.neon, vreinterpret_##bits##_u##bits(vec2.neon)); \ 84 union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \
70 return vec; \ 85 \
86 vec1d->neon = vshl_##sign##bits(vec1d->neon, (vreinterpret_##bits##_u##bits)vec2d->neon); \
87 return vec1d->vec; \
71 } \ 88 } \
72 \ 89 \
73 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) \ 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) \
74 { \ 91 { \
75 v##sign##int##bits##x##size vec; \ 92 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
76 vec.neon = vand_##sign##bits(vec1.neon, vec2.neon); \ 93 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
77 return vec; \ 94 \
95 vec1d->neon = vand_##sign##bits(vec1d->neon, vec2d->neon); \
96 return vec1d->vec; \
78 } \ 97 } \
79 \ 98 \
80 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) \ 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) \
81 { \ 100 { \
82 v##sign##int##bits##x##size vec; \ 101 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
83 vec.neon = vorr_##sign##bits(vec1.neon, vec2.neon); \ 102 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
84 return vec; \ 103 \
104 vec1d->neon = vorr_##sign##bits(vec1d->neon, vec2d->neon); \
105 return vec1d->vec; \
85 } \ 106 } \
86 \ 107 \
87 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) \ 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) \
88 { \ 109 { \
89 v##sign##int##bits##x##size vec; \ 110 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
90 vec.neon = veor_##sign##bits(vec1.neon, vec2.neon); \ 111 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
91 return vec; \ 112 \
113 vec1d->neon = veor_##sign##bits(vec1d->neon, vec2d->neon); \
114 return vec1d->vec; \
92 } \ 115 } \
93 \ 116 \
94 static 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 = { \
95 /* .splat = */ NULL, \ 118 v##sign##int##bits##x##size##_fallback_splat, \
96 v##sign##int##bits##x##size##_neon_load_aligned, \ 119 v##sign##int##bits##x##size##_neon_load_aligned, \
97 v##sign##int##bits##x##size##_neon_load_aligned, \ 120 v##sign##int##bits##x##size##_neon_load_aligned, \
98 v##sign##int##bits##x##size##_neon_store_aligned, \ 121 v##sign##int##bits##x##size##_neon_store_aligned, \
99 v##sign##int##bits##x##size##_neon_store_aligned, \ 122 v##sign##int##bits##x##size##_neon_store_aligned, \
100 v##sign##int##bits##x##size##_neon_add, \ 123 v##sign##int##bits##x##size##_neon_add, \
101 v##sign##int##bits##x##size##_neon_sub, \ 124 v##sign##int##bits##x##size##_neon_sub, \
102 v##sign##int##bits##x##size##_neon_mul, \ 125 v##sign##int##bits##x##size##_neon_mul, \
103 /* .div = */ NULL, \ 126 v##sign##int##bits##x##size##_fallback_div, \
104 /* .avg = */ NULL, \ 127 v##sign##int##bits##x##size##_fallback_avg, \
105 v##sign##int##bits##x##size##_neon_and, \ 128 v##sign##int##bits##x##size##_neon_and, \
106 v##sign##int##bits##x##size##_neon_or, \ 129 v##sign##int##bits##x##size##_neon_or, \
107 v##sign##int##bits##x##size##_neon_xor, \ 130 v##sign##int##bits##x##size##_neon_xor, \
108 /* .not = */ NULL, \ 131 v##sign##int##bits##x##size##_fallback_not, \
109 v##sign##int##bits##x##size##_neon_lshift, \ 132 v##sign##int##bits##x##size##_neon_lshift, \
110 /* .rshift = */ NULL, \ 133 v##sign##int##bits##x##size##_fallback_rshift, \
111 /* .lrshift = */ NULL, \ 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, \
112 }; 140 };
113 141
114 #define VEC_DEFINE_OPERATIONS(bits, size) \ 142 #define VEC_DEFINE_OPERATIONS(bits, size) \
115 VEC_DEFINE_OPERATIONS_SIGN( , , bits, size) \ 143 VEC_DEFINE_OPERATIONS_SIGN(u, U, bits, size) \
116 VEC_DEFINE_OPERATIONS_SIGN(u, U, bits, size) 144 VEC_DEFINE_OPERATIONS_SIGN( , , bits, size)
117 145
118 // Ok, we'll start out with the 64-bit types. 146 // Ok, we'll start out with the 64-bit types.
119 147
120 #define vadd_8 vadd_s8 148 #define vadd_8 vadd_s8
121 #define vadd_16 vadd_s16 149 #define vadd_16 vadd_s16
353 #define vreinterpret_8_u8(x) vreinterpretq_s8_u8(x) 381 #define vreinterpret_8_u8(x) vreinterpretq_s8_u8(x)
354 #define vreinterpret_16_u16(x) vreinterpretq_s16_u16(x) 382 #define vreinterpret_16_u16(x) vreinterpretq_s16_u16(x)
355 #define vreinterpret_32_u32(x) vreinterpretq_s32_u32(x) 383 #define vreinterpret_32_u32(x) vreinterpretq_s32_u32(x)
356 #define vreinterpret_64_u64(x) vreinterpretq_s64_u64(x) 384 #define vreinterpret_64_u64(x) vreinterpretq_s64_u64(x)
357 385
358 #define VEC_DEFINE_OPERATIONS_SIGN(sign, csign, bits, size) \
359 static v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_load_aligned(const vec_##sign##int##bits in[size]) \
360 { \
361 v##sign##int##bits##x##size vec; \
362 vec.neon = vld1_##sign##bits(in); \
363 return vec; \
364 } \
365 \
366 static void v##sign##int##bits##x##size##_neon_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \
367 { \
368 vstore_lane_##bits(sign, vec.neon, out); \
369 } \
370 \
371 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) \
372 { \
373 v##sign##int##bits##x##size vec; \
374 vec.neon = vadd_##sign##bits(vec1.neon, vec2.neon); \
375 return vec; \
376 } \
377 \
378 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) \
379 { \
380 v##sign##int##bits##x##size vec; \
381 vec.neon = vsub_##sign##bits(vec1.neon, vec2.neon); \
382 return vec; \
383 } \
384 \
385 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) \
386 { \
387 v##sign##int##bits##x##size vec; \
388 vec.neon = vmul_##sign##bits(vec1.neon, vec2.neon); \
389 return vec; \
390 } \
391 \
392 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) \
393 { \
394 v##sign##int##bits##x##size vec; \
395 vec.neon = vshl_##sign##bits(vec1.neon, vreinterpret_##bits##_u##bits(vec2.neon)); \
396 return vec; \
397 } \
398 \
399 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) \
400 { \
401 v##sign##int##bits##x##size vec; \
402 vec.neon = vand_##sign##bits(vec1.neon, vec2.neon); \
403 return vec; \
404 } \
405 \
406 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) \
407 { \
408 v##sign##int##bits##x##size vec; \
409 vec.neon = vorr_##sign##bits(vec1.neon, vec2.neon); \
410 return vec; \
411 } \
412 \
413 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) \
414 { \
415 v##sign##int##bits##x##size vec; \
416 vec.neon = veor_##sign##bits(vec1.neon, vec2.neon); \
417 return vec; \
418 } \
419 \
420 static v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_neon = { \
421 /* .splat = */ NULL, \
422 v##sign##int##bits##x##size##_neon_load_aligned, \
423 v##sign##int##bits##x##size##_neon_load_aligned, \
424 v##sign##int##bits##x##size##_neon_store_aligned, \
425 v##sign##int##bits##x##size##_neon_store_aligned, \
426 v##sign##int##bits##x##size##_neon_add, \
427 v##sign##int##bits##x##size##_neon_sub, \
428 v##sign##int##bits##x##size##_neon_mul, \
429 /* .div = */ NULL, \
430 /* .avg = */ NULL, \
431 v##sign##int##bits##x##size##_neon_and, \
432 v##sign##int##bits##x##size##_neon_or, \
433 v##sign##int##bits##x##size##_neon_xor, \
434 /* .not = */ NULL, \
435 v##sign##int##bits##x##size##_neon_lshift, \
436 /* .rshift = */ NULL, \
437 /* .lrshift = */ NULL, \
438 };
439
440 #define VEC_DEFINE_OPERATIONS(bits, size) \
441 VEC_DEFINE_OPERATIONS_SIGN( , , bits, size) \
442 VEC_DEFINE_OPERATIONS_SIGN(u, U, bits, size)
443
444 VEC_DEFINE_OPERATIONS(8, 16) 386 VEC_DEFINE_OPERATIONS(8, 16)
445 VEC_DEFINE_OPERATIONS(16, 8) 387 VEC_DEFINE_OPERATIONS(16, 8)
446 VEC_DEFINE_OPERATIONS(32, 4) 388 VEC_DEFINE_OPERATIONS(32, 4)
447 VEC_DEFINE_OPERATIONS(64, 2) 389 VEC_DEFINE_OPERATIONS(64, 2)
448 390