Mercurial > vec
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), \