Mercurial > vec
diff src/impl/x86/mmx.c @ 28:c6c99ab1088a
*: add min/max functions and a big big refactor (again)
agh, this time I added a few more implementations (and generally
made the code just a little faster...)
author | Paper <paper@tflc.us> |
---|---|
date | Thu, 24 Apr 2025 00:54:02 -0400 |
parents | e49e70f7012f |
children | bf6ad516f1e6 |
line wrap: on
line diff
--- a/src/impl/x86/mmx.c Mon Nov 25 00:33:02 2024 -0500 +++ b/src/impl/x86/mmx.c Thu Apr 24 00:54:02 2025 -0400 @@ -24,46 +24,67 @@ #include "vec/vec.h" #include "vec/impl/x86/mmx.h" -#include "vec/impl/generic.h" #include <mmintrin.h> #include <string.h> -#define VEC_MMX_OPERATION_8x8(op, sign) \ - do { \ - /* unpack and multiply */ \ - union v##sign##int8x8_impl_data *vec1d = (union v##sign##int8x8_impl_data *)&vec1; \ - union v##sign##int8x8_impl_data *vec2d = (union v##sign##int8x8_impl_data *)&vec2; \ - \ - __m64 dst_even = _mm_##op##_pi16(vec1d->mmx, vec2d->mmx); \ - __m64 dst_odd = _mm_##op##_pi16(_mm_srli_pi16(vec1d->mmx, 8), _mm_srli_pi16(vec2d->mmx, 8)); \ - \ - /* repack */ \ - vec1d->mmx = _mm_or_si64( \ - _mm_slli_pi16(dst_odd, 8), \ - _mm_srli_pi16(_mm_slli_pi16(dst_even, 8), 8) \ - ); \ - return vec1d->vec; \ - } while (0) +/* ------------------------------------------------------------------------ */ -// shared between MMX variations -#define VEC_MMX_MUL_8x8(sign) \ - VEC_MMX_OPERATION_8x8(mullo, sign) - +#define VEC_MMX_MUL_8x8(sign) /* nothing */ #define VEC_MMX_MUL_16x4(sign) \ - do { \ + VEC_FUNC_IMPL v##sign##int16x4 v##sign##int16x4_mmx_mul(v##sign##int16x4 vec1, v##sign##int16x4 vec2) \ + { \ union v##sign##int16x4_impl_data *vec1d = (union v##sign##int16x4_impl_data *)&vec1; \ union vuint16x4_impl_data *vec2d = (union vuint16x4_impl_data *)&vec2; \ \ vec1d->mmx = _mm_mullo_pi16(vec1d->mmx, vec2d->mmx); \ return vec1d->vec; \ - } while (0) + } +#define VEC_MMX_MUL_32x2(sign) /* nothing */ + +#define VEC_MMX_STRUCT_MUL_8x8(sign) NULL +#define VEC_MMX_STRUCT_MUL_16x4(sign) v##sign##int16x4_mmx_mul +#define VEC_MMX_STRUCT_MUL_32x8(sign) NULL + +/* ------------------------------------------------------------------------ */ +/* comparison */ -#define VEC_MMX_MUL_32x2(sign) \ - /* TODO implement this for real */ \ - do { \ - return v##sign##int32x2_generic_mul(vec1, vec2); \ - } while (0) +/* helper funcs */ +#define VEC_xMMX_CMP(name, op, sign, bits, size, first, second, VARS, TRANS1, TRANS2) \ + VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_##name(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ + { \ + 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; \ + VARS \ + \ + TRANS1 \ + \ + vec1d->mmx = _mm_##op##_pi##bits(vec##first##d->mmx, vec##second##d->mmx); \ + \ + TRANS2 \ + \ + return vec1d->vec; \ + } + +#define VEC_MMX_CMP(name, op, bits, size, first, second) \ + VEC_xMMX_CMP(name, op, /* nothing */, bits, size, first, second, /* nothing */, /* nothing */, /* nothing */) + +#define VEC_uMMX_CMP(name, op, bits, size, first, second) \ + VEC_xMMX_CMP(name, op, u, bits, size, first, second, \ + __m64 xor_val = _mm_set1_pi##bits(1u << (bits - 1)); \ + , { \ + vec1d->mmx = _mm_xor_si64(vec1d->mmx, xor_val); \ + vec2d->mmx = _mm_xor_si64(vec2d->mmx, xor_val); \ + }, \ + { \ + /* nothing */ \ + }) + +#define VEC_MMX_CMPEQ(sign, bits, size) VEC_xMMX_CMP(cmpeq, cmpeq, sign, bits, size, 1, 2, , ,) +#define VEC_MMX_CMPLT(sign, bits, size) VEC_##sign##MMX_CMP(cmplt, cmpgt, bits, size, 2, 1) +#define VEC_MMX_CMPGT(sign, bits, size) VEC_##sign##MMX_CMP(cmpgt, cmpgt, bits, size, 1, 2) + +/* ------------------------------------------------------------------------ */ #define VEC_MMX_DEFINE_OPERATIONS_SIGN(sign, bits, size) \ union v##sign##int##bits##x##size##_impl_data { \ @@ -74,19 +95,19 @@ VEC_STATIC_ASSERT(VEC_ALIGNOF(__m64) <= 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(__m64) <= 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##_mmx_load_aligned(const vec_##sign##int##bits in[size]) \ + VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_load_aligned(const vec_##sign##int##bits in[size]) \ { \ v##sign##int##bits##x##size vec; \ memcpy(&vec, in, sizeof(vec)); \ return vec; \ } \ \ - static void v##sign##int##bits##x##size##_mmx_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ + VEC_FUNC_IMPL void v##sign##int##bits##x##size##_mmx_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ { \ memcpy(out, &vec, sizeof(vec)); \ } \ \ - static v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_add(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ + VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_add(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ { \ 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; \ @@ -96,7 +117,7 @@ return vec1d->vec; \ } \ \ - static v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_sub(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ + VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_sub(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ { \ 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; \ @@ -106,12 +127,9 @@ return vec1d->vec; \ } \ \ - static v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_mul(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ - { \ - VEC_MMX_MUL_##bits##x##size(sign); \ - } \ + VEC_MMX_MUL_##bits##x##size(sign) \ \ - static v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ + VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ { \ 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; \ @@ -121,7 +139,7 @@ return vec1d->vec; \ } \ \ - static v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_or(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ + VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_or(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ { \ 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; \ @@ -131,7 +149,7 @@ return vec1d->vec; \ } \ \ - static v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_xor(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ + VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_mmx_xor(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ { \ 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; \ @@ -141,29 +159,22 @@ return vec1d->vec; \ } \ \ + VEC_MMX_CMPEQ(sign, bits, size) \ + VEC_MMX_CMPLT(sign, bits, size) \ + VEC_MMX_CMPGT(sign, bits, size) \ + \ const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_mmx = { \ - v##sign##int##bits##x##size##_generic_splat, \ - v##sign##int##bits##x##size##_mmx_load_aligned, \ - v##sign##int##bits##x##size##_mmx_load_aligned, \ - v##sign##int##bits##x##size##_mmx_store_aligned, \ - v##sign##int##bits##x##size##_mmx_store_aligned, \ - v##sign##int##bits##x##size##_mmx_add, \ - v##sign##int##bits##x##size##_mmx_sub, \ - v##sign##int##bits##x##size##_mmx_mul, \ - v##sign##int##bits##x##size##_generic_div, \ - v##sign##int##bits##x##size##_generic_avg, \ - v##sign##int##bits##x##size##_mmx_and, \ - v##sign##int##bits##x##size##_mmx_or, \ - v##sign##int##bits##x##size##_mmx_xor, \ - v##sign##int##bits##x##size##_generic_not, \ - v##sign##int##bits##x##size##_generic_lshift, \ - v##sign##int##bits##x##size##_generic_rshift, \ - v##sign##int##bits##x##size##_generic_lrshift, \ - v##sign##int##bits##x##size##_generic_cmplt, \ - v##sign##int##bits##x##size##_generic_cmple, \ - v##sign##int##bits##x##size##_generic_cmpeq, \ - v##sign##int##bits##x##size##_generic_cmpge, \ - v##sign##int##bits##x##size##_generic_cmpgt, \ + .load_aligned = v##sign##int##bits##x##size##_mmx_load_aligned, \ + .load = v##sign##int##bits##x##size##_mmx_load_aligned, \ + .store_aligned = v##sign##int##bits##x##size##_mmx_store_aligned, \ + .store = v##sign##int##bits##x##size##_mmx_store_aligned, \ + .add = v##sign##int##bits##x##size##_mmx_add, \ + .sub = v##sign##int##bits##x##size##_mmx_sub, \ + .mul = VEC_MMX_STRUCT_MUL_8x8(sign), \ + .band = v##sign##int##bits##x##size##_mmx_and, \ + .bor = v##sign##int##bits##x##size##_mmx_or, \ + .bxor = v##sign##int##bits##x##size##_mmx_xor, \ + .cmpeq = v##sign##int##bits##x##size##_mmx_cmpeq, \ }; #define VEC_MMX_DEFINE_OPERATIONS(bits, size) \