changeset 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 6c91cd9a2f2d
children
files CMakeLists.txt src/impl/arm/neon.c
diffstat 2 files changed, 64 insertions(+), 122 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Mon Nov 25 04:43:22 2024 +0000
+++ b/CMakeLists.txt	Mon Nov 25 00:33:02 2024 -0500
@@ -37,10 +37,10 @@
 	if(COMPILER_HAS_ALTIVEC)
 		set(COMPILER_ALTIVEC_FLAGS "-maltivec")
 	endif()
-	#check_c_compiler_flag("-mfpu=neon" COMPILER_HAS_NEON)
-	#if(COMPILER_HAS_NEON)
-	#	set(COMPILER_NEON_FLAGS "-mfpu=neon")
-	#endif()
+	check_c_compiler_flag("-mfpu=neon" COMPILER_HAS_NEON)
+	if(COMPILER_HAS_NEON)
+		set(COMPILER_NEON_FLAGS "-mfpu=neon")
+	endif()
 	check_c_compiler_flag("-mmmx" COMPILER_HAS_MMX)
 	if(COMPILER_HAS_MMX)
 		set(COMPILER_MMX_FLAGS "-mmmx")
--- a/src/impl/arm/neon.c	Mon Nov 25 04:43:22 2024 +0000
+++ b/src/impl/arm/neon.c	Mon Nov 25 00:33:02 2024 -0500
@@ -23,6 +23,7 @@
 **/
 
 #include "vec/impl/arm/neon.h"
+#include "vec/impl/generic.h"
 
 #include <arm_neon.h>
 
@@ -30,69 +31,91 @@
 // weren't bad enough... lol)
 
 #define VEC_DEFINE_OPERATIONS_SIGN(sign, csign, bits, size) \
+	union v##sign##int##bits##x##size##_impl_data { \
+		v##sign##int##bits##x##size vec; \
+		sign##int##bits##x##size##_t neon; \
+	}; \
+	\
+	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"); \
+	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"); \
+	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_load_aligned(const vec_##sign##int##bits in[size]) \
 	{ \
-		v##sign##int##bits##x##size vec; \
+		union v##sign##int##bits##x##size##_impl_data vec; \
 		vec.neon = vld1_##sign##bits(in); \
-		return vec; \
+		return vec.vec; \
 	} \
 	\
 	static void v##sign##int##bits##x##size##_neon_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \
 	{ \
-		vstore_lane_##bits(sign, vec.neon, out); \
+		vstore_lane_##bits(sign, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->neon, out); \
 	} \
 	\
 	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) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vadd_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
+		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
+		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
+	\
+		vec1d->neon = vadd_##sign##bits(vec1d->neon, vec2d->neon); \
+		return vec1d->vec; \
 	} \
 	\
 	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) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vsub_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
+		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
+		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
+	\
+		vec1d->neon = vsub_##sign##bits(vec1d->neon, vec2d->neon); \
+		return vec1d->vec; \
 	} \
 	\
 	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) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vmul_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
+		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
+		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
+	\
+		vec1d->neon = vmul_##sign##bits(vec1d->neon, vec2d->neon); \
+		return vec1d->vec; \
 	} \
 	\
 	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) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vshl_##sign##bits(vec1.neon, vreinterpret_##bits##_u##bits(vec2.neon)); \
-		return vec; \
+		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
+		union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \
+	\
+		vec1d->neon = vshl_##sign##bits(vec1d->neon, (vreinterpret_##bits##_u##bits)vec2d->neon); \
+		return vec1d->vec; \
 	} \
 	\
 	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) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vand_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
+		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
+		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
+	\
+		vec1d->neon = vand_##sign##bits(vec1d->neon, vec2d->neon); \
+		return vec1d->vec; \
 	} \
 	\
 	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) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vorr_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
+		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
+		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
+	\
+		vec1d->neon = vorr_##sign##bits(vec1d->neon, vec2d->neon); \
+		return vec1d->vec; \
 	} \
 	\
 	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) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = veor_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
+		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
+		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
+	\
+		vec1d->neon = veor_##sign##bits(vec1d->neon, vec2d->neon); \
+		return vec1d->vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_neon = { \
-		/* .splat = */ NULL, \
+		v##sign##int##bits##x##size##_fallback_splat, \
 		v##sign##int##bits##x##size##_neon_load_aligned, \
 		v##sign##int##bits##x##size##_neon_load_aligned, \
 		v##sign##int##bits##x##size##_neon_store_aligned, \
@@ -100,20 +123,25 @@
 		v##sign##int##bits##x##size##_neon_add, \
 		v##sign##int##bits##x##size##_neon_sub, \
 		v##sign##int##bits##x##size##_neon_mul, \
-		/* .div = */ NULL, \
-		/* .avg = */ NULL, \
+		v##sign##int##bits##x##size##_fallback_div, \
+		v##sign##int##bits##x##size##_fallback_avg, \
 		v##sign##int##bits##x##size##_neon_and, \
 		v##sign##int##bits##x##size##_neon_or, \
 		v##sign##int##bits##x##size##_neon_xor, \
-		/* .not = */ NULL, \
+		v##sign##int##bits##x##size##_fallback_not, \
 		v##sign##int##bits##x##size##_neon_lshift, \
-		/* .rshift = */ NULL, \
-		/* .lrshift = */ NULL, \
+		v##sign##int##bits##x##size##_fallback_rshift, \
+		v##sign##int##bits##x##size##_fallback_lrshift, \
+		v##sign##int##bits##x##size##_fallback_cmplt, \
+		v##sign##int##bits##x##size##_fallback_cmple, \
+		v##sign##int##bits##x##size##_fallback_cmpeq, \
+		v##sign##int##bits##x##size##_fallback_cmpge, \
+		v##sign##int##bits##x##size##_fallback_cmpgt, \
 	};
 
 #define VEC_DEFINE_OPERATIONS(bits, size) \
-	VEC_DEFINE_OPERATIONS_SIGN( ,  , bits, size) \
-	VEC_DEFINE_OPERATIONS_SIGN(u, U, bits, size)
+	VEC_DEFINE_OPERATIONS_SIGN(u, U, bits, size) \
+	VEC_DEFINE_OPERATIONS_SIGN( ,  , bits, size)
 
 // Ok, we'll start out with the 64-bit types.
 
@@ -355,92 +383,6 @@
 #define vreinterpret_32_u32(x) vreinterpretq_s32_u32(x)
 #define vreinterpret_64_u64(x) vreinterpretq_s64_u64(x)
 
-#define VEC_DEFINE_OPERATIONS_SIGN(sign, csign, bits, size) \
-	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_neon_load_aligned(const vec_##sign##int##bits in[size]) \
-	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vld1_##sign##bits(in); \
-		return vec; \
-	} \
-	\
-	static void v##sign##int##bits##x##size##_neon_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \
-	{ \
-		vstore_lane_##bits(sign, vec.neon, out); \
-	} \
-	\
-	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) \
-	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vadd_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
-	} \
-	\
-	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) \
-	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vsub_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
-	} \
-	\
-	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) \
-	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vmul_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
-	} \
-	\
-	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) \
-	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vshl_##sign##bits(vec1.neon, vreinterpret_##bits##_u##bits(vec2.neon)); \
-		return vec; \
-	} \
-	\
-	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) \
-	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vand_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
-	} \
-	\
-	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) \
-	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = vorr_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
-	} \
-	\
-	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) \
-	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.neon = veor_##sign##bits(vec1.neon, vec2.neon); \
-		return vec; \
-	} \
-	\
-	static v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_neon = { \
-		/* .splat = */ NULL, \
-		v##sign##int##bits##x##size##_neon_load_aligned, \
-		v##sign##int##bits##x##size##_neon_load_aligned, \
-		v##sign##int##bits##x##size##_neon_store_aligned, \
-		v##sign##int##bits##x##size##_neon_store_aligned, \
-		v##sign##int##bits##x##size##_neon_add, \
-		v##sign##int##bits##x##size##_neon_sub, \
-		v##sign##int##bits##x##size##_neon_mul, \
-		/* .div = */ NULL, \
-		/* .avg = */ NULL, \
-		v##sign##int##bits##x##size##_neon_and, \
-		v##sign##int##bits##x##size##_neon_or, \
-		v##sign##int##bits##x##size##_neon_xor, \
-		/* .not = */ NULL, \
-		v##sign##int##bits##x##size##_neon_lshift, \
-		/* .rshift = */ NULL, \
-		/* .lrshift = */ NULL, \
-	};
-
-#define VEC_DEFINE_OPERATIONS(bits, size) \
-	VEC_DEFINE_OPERATIONS_SIGN( ,  , bits, size) \
-	VEC_DEFINE_OPERATIONS_SIGN(u, U, bits, size)
-
 VEC_DEFINE_OPERATIONS(8, 16)
 VEC_DEFINE_OPERATIONS(16, 8)
 VEC_DEFINE_OPERATIONS(32, 4)