diff src/impl/ppc/altivec.c @ 25:92156fe32755

impl/ppc/altivec: update to new implementation the signed average function is wrong; it needs to round up the number when only one of them is odd, but that doesn't necessarily seem to be true because altivec is weird, and that's what we need to emulate the quirks for. ugh. also the altivec backend uses the generic functions instead of fallbacks because it does indeed use the exact same memory structure as the generic implementation...
author Paper <paper@tflc.us>
date Sun, 24 Nov 2024 11:15:59 +0000
parents e26874655738
children
line wrap: on
line diff
--- a/src/impl/ppc/altivec.c	Sun Nov 24 03:32:53 2024 -0500
+++ b/src/impl/ppc/altivec.c	Sun Nov 24 11:15:59 2024 +0000
@@ -23,38 +23,61 @@
 **/
 
 #include "vec/impl/ppc/altivec.h"
+#include "vec/impl/generic.h"
 
 #include <altivec.h>
 
+#define VEC_DEFINE_IMPL_DATA(sign, bits, size, type) \
+    union v##sign##int##bits##x##size##_impl_data { \
+	    v##sign##int##bits##x##size vec; \
+	    vector type altivec; \
+    }; \
+    \
+	VEC_STATIC_ASSERT(VEC_ALIGNOF(vector type) <= 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(vector type) <= sizeof(v##sign##int##bits##x##size), "vec: v" #sign "int" #bits "x" #size " needs to be expanded to fit intrinsic type size");
+
+VEC_DEFINE_IMPL_DATA( , 8,  16, signed char)
+VEC_DEFINE_IMPL_DATA(u, 8,  16, unsigned char)
+VEC_DEFINE_IMPL_DATA( , 16, 8,  signed short)
+VEC_DEFINE_IMPL_DATA(u, 16, 8,  unsigned short)
+VEC_DEFINE_IMPL_DATA( , 32, 4,  signed int)
+VEC_DEFINE_IMPL_DATA(u, 32, 4,  unsigned int)
+
+#undef VEC_DEFINE_IMPL_DATA
+
 /* GCC 4.2.1 on Mac OS X doesn't have these for some reason */
 #ifdef vec_mul
 # define VEC_ALTIVEC_DEFINE_MUL(sign, csign, bits, size) \
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_mul(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = vec_mul(vec1.altivec, vec2.altivec); \
-		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->altivec = vec_mul(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	}
 # define VEC_ALTIVEC_STRUCT_MUL(sign, csign, bits, size) \
 	v##sign##int##bits##x##size##_altivec_mul
 #else
 # define VEC_ALTIVEC_DEFINE_MUL(sign, csign, bits, size)
-# define VEC_ALTIVEC_STRUCT_MUL(sign, csign, bits, size) NULL
+# define VEC_ALTIVEC_STRUCT_MUL(sign, csign, bits, size) \
+    v##sign##int##bits##x##size##_generic_mul
 #endif
 
 #ifdef vec_splats
 # define VEC_ALTIVEC_DEFINE_SPLAT(sign, csign, bits, size) \
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_splat(vec_##sign##int##bits x) \
 	{ \
-		v##sign##int##bits##x##size vec; \
+		union v##sign##int##bits##x##size##_impl_data vec; \
 		vec.altivec = vec_splats(x); \
-		return vec; \
+		return vec.vec; \
 	}
 # define VEC_ALTIVEC_STRUCT_SPLAT(sign, csign, bits, size) \
 	v##sign##int##bits##x##size##_altivec_splat
 #else
 # define VEC_ALTIVEC_DEFINE_SPLAT(sign, csign, bits, size)
-# define VEC_ALTIVEC_STRUCT_SPLAT(sign, csign, bits, size) NULL
+# define VEC_ALTIVEC_STRUCT_SPLAT(sign, csign, bits, size) \
+    v##sign##int##bits##x##size##_generic_splat
 #endif
 
 #define VEC_ALTIVEC_uRSHIFT vec_sr
@@ -63,15 +86,18 @@
 #define VEC_ALTIVEC_DEFINE_uLRSHIFT(sign, csign, bits, size) \
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_lrshift(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = vec_sr(vec1.altivec, vec2.altivec); \
-		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->altivec = vec_sr(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	}
 #define VEC_ALTIVEC_STRUCT_uLRSHIFT(sign, csign, bits, size) \
 	v##sign##int##bits##x##size##_altivec_lrshift
 
 #define VEC_ALTIVEC_DEFINE_LRSHIFT(sign, csign, bits, size)
-#define VEC_ALTIVEC_STRUCT_LRSHIFT(sign, csign, bits, size) NULL
+#define VEC_ALTIVEC_STRUCT_LRSHIFT(sign, csign, bits, size) \
+    v##sign##int##bits##x##size##_generic_lrshift
 
 #define VEC_ALTIVEC_CAST_BOOL_8 (vector signed char)
 #define VEC_ALTIVEC_CAST_BOOL_U8 (vector unsigned char)
@@ -85,135 +111,161 @@
 #define VEC_DEFINE_OPERATIONS_SIGN(sign, csign, bits, size) \
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_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.altivec = vec_ld(0, in); \
-		return vec; \
+		return vec.vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_load(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.altivec = vec_perm(vec_ld(0, in), vec_ld(15, in), vec_lvsl(0, in)); \
-		return vec; \
+		return vec.vec; \
 	} \
 	\
 	static void v##sign##int##bits##x##size##_altivec_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \
 	{ \
-		vec_st(vec.altivec, 0, out); \
+		vec_st(((union v##sign##int##bits##x##size##_impl_data *)&vec)->altivec, 0, out); \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_add(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = vec_add(vec1.altivec, vec2.altivec); \
-		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->altivec = vec_add(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_sub(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = vec_sub(vec1.altivec, vec2.altivec); \
-		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->altivec = vec_sub(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	} \
 	\
 	VEC_ALTIVEC_DEFINE_MUL(sign, csign, bits, size) \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_lshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = vec_sl(vec1.altivec, vec2.altivec); \
-		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->altivec = vec_sl(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_rshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = VEC_ALTIVEC_##sign##RSHIFT(vec1.altivec, vec2.altivec); \
-		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->altivec = VEC_ALTIVEC_##sign##RSHIFT(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	} \
 	\
 	VEC_ALTIVEC_DEFINE_##sign##LRSHIFT(sign, csign, bits, size) \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_avg(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = vec_avg(vec1.altivec, vec2.altivec); \
-		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->altivec = vec_avg(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = vec_and(vec1.altivec, vec2.altivec); \
-		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->altivec = vec_and(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_or(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = vec_or(vec1.altivec, vec2.altivec); \
-		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->altivec = vec_or(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_xor(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = vec_xor(vec1.altivec, vec2.altivec); \
-		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->altivec = vec_xor(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	} \
 	\
 	VEC_ALTIVEC_DEFINE_SPLAT(sign, csign, bits, size) \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_cmplt(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits  vec_cmplt(vec1.altivec, vec2.altivec); \
-		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->altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits  vec_cmplt(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_cmple(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_or(vec_cmplt(vec1.altivec, vec2.altivec), vec_cmpeq(vec1.altivec, vec2.altivec)); \
-		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->altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_or(vec_cmplt(vec1d->altivec, vec2d->altivec), vec_cmpeq(vec1d->altivec, vec2d->altivec)); \
+		return vec1d->vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_cmpeq(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_cmpeq(vec1.altivec, vec2.altivec); \
-		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->altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_cmpeq(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_cmpge(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_or(vec_cmpgt(vec1.altivec, vec2.altivec), vec_cmpeq(vec1.altivec, vec2.altivec)); \
-		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->altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_or(vec_cmpgt(vec1d->altivec, vec2d->altivec), vec_cmpeq(vec1d->altivec, vec2d->altivec)); \
+		return vec1d->vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_cmpgt(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		v##sign##int##bits##x##size vec; \
-		vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_cmpgt(vec1.altivec, vec2.altivec); \
-		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->altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_cmpgt(vec1d->altivec, vec2d->altivec); \
+		return vec1d->vec; \
 	} \
 	\
-	static v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_altivec = { \
+	const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_altivec = { \
 		VEC_ALTIVEC_STRUCT_SPLAT(sign, csign, bits, size), \
 		v##sign##int##bits##x##size##_altivec_load_aligned, \
 		v##sign##int##bits##x##size##_altivec_load, \
 		v##sign##int##bits##x##size##_altivec_store_aligned, \
-		/* .store = */ NULL, \
+		v##sign##int##bits##x##size##_generic_store, \
 		v##sign##int##bits##x##size##_altivec_add, \
 		v##sign##int##bits##x##size##_altivec_sub, \
 		VEC_ALTIVEC_STRUCT_MUL(sign, csign, bits, size), \
-		/* .div = */ NULL, \
+		v##sign##int##bits##x##size##_generic_div, \
 		v##sign##int##bits##x##size##_altivec_avg, \
 		v##sign##int##bits##x##size##_altivec_and, \
 		v##sign##int##bits##x##size##_altivec_or, \
 		v##sign##int##bits##x##size##_altivec_xor, \
-		/* .not = */ NULL, \
+		v##sign##int##bits##x##size##_generic_not, \
 		v##sign##int##bits##x##size##_altivec_lshift, \
 		v##sign##int##bits##x##size##_altivec_rshift, \
 		VEC_ALTIVEC_STRUCT_##sign##LRSHIFT(sign, csign, bits, size), \