Mercurial > vec
comparison src/impl/x86/sse2.c @ 31:bf6ad516f1e6
Backed out changeset c6c99ab1088a
| author | Paper <paper@tflc.us> |
|---|---|
| date | Fri, 25 Apr 2025 17:40:33 -0400 |
| parents | c6c99ab1088a |
| children | 99e4539f922f |
comparison
equal
deleted
inserted
replaced
| 30:641d8c79b1da | 31:bf6ad516f1e6 |
|---|---|
| 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/x86/sse2.h" | 25 #include "vec/impl/x86/sse2.h" |
| 26 #include "vec/impl/generic.h" | |
| 26 | 27 |
| 27 #include <emmintrin.h> | 28 #include <emmintrin.h> |
| 28 | |
| 29 #define VEC_SSE2_DEFINE_IMPL_DATA(sign, bits, size) \ | |
| 30 union v##sign##int##bits##x##size##_impl_data { \ | |
| 31 v##sign##int##bits##x##size vec; \ | |
| 32 __m128i sse; \ | |
| 33 }; \ | |
| 34 \ | |
| 35 VEC_STATIC_ASSERT(VEC_ALIGNOF(__m128i) <= 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"); \ | |
| 36 VEC_STATIC_ASSERT(sizeof(__m128i) <= sizeof(v##sign##int##bits##x##size), "vec: v" #sign "int" #bits "x" #size " needs to be expanded to fit intrinsic type size"); | |
| 37 | |
| 38 VEC_SSE2_DEFINE_IMPL_DATA( , 8, 16) | |
| 39 VEC_SSE2_DEFINE_IMPL_DATA(u, 8, 16) | |
| 40 VEC_SSE2_DEFINE_IMPL_DATA( , 16, 8) | |
| 41 VEC_SSE2_DEFINE_IMPL_DATA(u, 16, 8) | |
| 42 VEC_SSE2_DEFINE_IMPL_DATA( , 32, 4) | |
| 43 VEC_SSE2_DEFINE_IMPL_DATA(u, 32, 4) | |
| 44 VEC_SSE2_DEFINE_IMPL_DATA( , 64, 2) | |
| 45 VEC_SSE2_DEFINE_IMPL_DATA(u, 64, 2) | |
| 46 | |
| 47 /* eh */ | |
| 48 #define MM_SET1_8(x) _mm_set1_epi8(x) | |
| 49 #define MM_SET1_16(x) _mm_set1_epi16(x) | |
| 50 #define MM_SET1_32(x) _mm_set1_epi32(x) | |
| 51 #define MM_SET1_64(x) _mm_set1_epi64x(x) | |
| 52 | |
| 53 /* ------------------------------------------------------------------------ */ | |
| 54 | |
| 55 /* unfortunately doing this for SSE2 is PREPROCESSOR HELL */ | |
| 56 #define VEC_SSE2_MINMAX_8x16_TEMPLATE(SIGN, OP, VALS, ADDITIONAL1, ADDITIONAL2) \ | |
| 57 VEC_FUNC_IMPL v##SIGN##int8x16 v##SIGN##int8x16_sse2_##OP(v##SIGN##int8x16 vec1, v##SIGN##int8x16 vec2) \ | |
| 58 { \ | |
| 59 union v##SIGN##int8x16_impl_data *vec1d = (union v##SIGN##int8x16_impl_data *)&vec1; \ | |
| 60 union v##SIGN##int8x16_impl_data *vec2d = (union v##SIGN##int8x16_impl_data *)&vec2; \ | |
| 61 VALS \ | |
| 62 \ | |
| 63 ADDITIONAL1 \ | |
| 64 \ | |
| 65 vec1d->sse = _mm_##OP##_epu8(vec1d->sse, vec2d->sse); \ | |
| 66 \ | |
| 67 ADDITIONAL2 \ | |
| 68 \ | |
| 69 return vec1d->vec; \ | |
| 70 } | |
| 71 | |
| 72 /* conveniently, this looks like K&R C ;) */ | |
| 73 #define VEC_SSE2_MINMAX_8x16(OP) \ | |
| 74 VEC_SSE2_MINMAX_8x16_TEMPLATE(/* nothing */, OP, \ | |
| 75 __m128i xor_val = _mm_set1_epi8(0x80u); \ | |
| 76 , { \ | |
| 77 vec1d->sse = _mm_xor_si128(vec1d->sse, xor_val); \ | |
| 78 vec2d->sse = _mm_xor_si128(vec2d->sse, xor_val); \ | |
| 79 }, \ | |
| 80 { \ | |
| 81 vec1d->sse = _mm_xor_si128(vec1d->sse, xor_val); \ | |
| 82 }) | |
| 83 | |
| 84 #define VEC_SSE2_MINMAX_u8x16(OP) \ | |
| 85 VEC_SSE2_MINMAX_8x16_TEMPLATE(u, OP, /* nothing */, /* nothing */, /* nothing */) | |
| 86 | |
| 87 #define VEC_SSE2_MINMAX_16x8_TEMPLATE(SIGN, OP, VALS, ADDITIONAL1, ADDITIONAL2) \ | |
| 88 VEC_FUNC_IMPL v##SIGN##int16x8 v##SIGN##int16x8_sse2_##OP(v##SIGN##int16x8 vec1, v##SIGN##int16x8 vec2) \ | |
| 89 { \ | |
| 90 union v##SIGN##int16x8_impl_data *vec1d = (union v##SIGN##int16x8_impl_data *)&vec1; \ | |
| 91 union v##SIGN##int16x8_impl_data *vec2d = (union v##SIGN##int16x8_impl_data *)&vec2; \ | |
| 92 VALS \ | |
| 93 \ | |
| 94 ADDITIONAL1 \ | |
| 95 \ | |
| 96 vec1d->sse = _mm_##OP##_epi16(vec1d->sse, vec2d->sse); \ | |
| 97 \ | |
| 98 ADDITIONAL2 \ | |
| 99 \ | |
| 100 return vec1d->vec; \ | |
| 101 } | |
| 102 | |
| 103 #define VEC_SSE2_MINMAX_16x8(OP) \ | |
| 104 VEC_SSE2_MINMAX_16x8_TEMPLATE(/* nothing */, OP, /* nothing */, /* nothing */, /* nothing */) | |
| 105 | |
| 106 #define VEC_SSE2_MINMAX_u16x8(OP) \ | |
| 107 VEC_SSE2_MINMAX_16x8_TEMPLATE(u, OP, \ | |
| 108 __m128i xor_val = _mm_set1_epi16(0x8000u); \ | |
| 109 , { \ | |
| 110 vec1d->sse = _mm_xor_si128(vec1d->sse, xor_val); \ | |
| 111 vec2d->sse = _mm_xor_si128(vec2d->sse, xor_val); \ | |
| 112 }, \ | |
| 113 { \ | |
| 114 vec1d->sse = _mm_xor_si128(vec1d->sse, xor_val); \ | |
| 115 }) | |
| 116 | |
| 117 #define VEC_SSE2_MINMAX_32x4(OP) /* none */ | |
| 118 #define VEC_SSE2_MINMAX_64x2(OP) /* none */ | |
| 119 #define VEC_SSE2_MINMAX_u32x4(OP) /* none */ | |
| 120 #define VEC_SSE2_MINMAX_u64x2(OP) /* none */ | |
| 121 | |
| 122 #define VEC_SSE2_STRUCT_MINMAX_8x16(OP, SIGN) v##SIGN##int8x16_sse2_##OP | |
| 123 #define VEC_SSE2_STRUCT_MINMAX_16x8(OP, SIGN) v##SIGN##int16x8_sse2_##OP | |
| 124 #define VEC_SSE2_STRUCT_MINMAX_32x4(OP, SIGN) NULL | |
| 125 #define VEC_SSE2_STRUCT_MINMAX_64x2(OP, SIGN) NULL | |
| 126 | |
| 127 /* ------------------------------------------------------------------------ */ | |
| 128 /* multiplication */ | |
| 129 | 29 |
| 130 #define VEC_SSE2_OPERATION_8x16(op, sign) \ | 30 #define VEC_SSE2_OPERATION_8x16(op, sign) \ |
| 131 do { \ | 31 do { \ |
| 132 /* unpack and multiply */ \ | 32 /* unpack and multiply */ \ |
| 133 union v##sign##int8x16_impl_data *vec1d = (union v##sign##int8x16_impl_data *)&vec1; \ | 33 union v##sign##int8x16_impl_data *vec1d = (union v##sign##int8x16_impl_data *)&vec1; \ |
| 190 \ | 90 \ |
| 191 vec1d->sse = _mm_add_epi64(hi, ac); /* (ab3,ab2,ab1,ab0) */ \ | 91 vec1d->sse = _mm_add_epi64(hi, ac); /* (ab3,ab2,ab1,ab0) */ \ |
| 192 return vec1d->vec; \ | 92 return vec1d->vec; \ |
| 193 } while (0) | 93 } while (0) |
| 194 | 94 |
| 195 /* ------------------------------------------------------------------------ */ | 95 #define VEC_SSE2_CMPEQ_8x16(sign) \ |
| 196 /* comparison */ | 96 do { \ |
| 197 | 97 union v##sign##int8x16_impl_data *vec1d = (union v##sign##int8x16_impl_data *)&vec1; \ |
| 198 /* helper funcs */ | 98 union v##sign##int8x16_impl_data *vec2d = (union v##sign##int8x16_impl_data *)&vec2; \ |
| 199 #define VEC_xSSE2_CMP(name, op, sign, bits, size, first, second, VARS, TRANS1, TRANS2) \ | 99 \ |
| 200 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_##name(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 100 vec1d->sse = _mm_cmpeq_epi8(vec1d->sse, vec2d->sse); \ |
| 201 { \ | 101 return vec1d->vec; \ |
| 202 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 102 } while (0) |
| 203 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 103 |
| 204 VARS \ | 104 #define VEC_SSE2_CMPEQ_16x8(sign) \ |
| 205 \ | 105 do { \ |
| 206 TRANS1 \ | 106 union v##sign##int16x8_impl_data *vec1d = (union v##sign##int16x8_impl_data *)&vec1; \ |
| 207 \ | 107 union v##sign##int16x8_impl_data *vec2d = (union v##sign##int16x8_impl_data *)&vec2; \ |
| 208 vec1d->sse = _mm_##op##_epi##bits(vec##first##d->sse, vec##second##d->sse); \ | 108 \ |
| 209 \ | 109 vec1d->sse = _mm_cmpeq_epi16(vec1d->sse, vec2d->sse); \ |
| 210 TRANS2 \ | 110 return vec1d->vec; \ |
| 211 \ | 111 } while (0) |
| 212 return vec1d->vec; \ | 112 |
| 213 } | 113 #define VEC_SSE2_CMPEQ_32x4(sign) \ |
| 214 | 114 do { \ |
| 215 #define VEC_SSE2_CMP(name, op, bits, size, first, second) \ | 115 union v##sign##int32x4_impl_data *vec1d = (union v##sign##int32x4_impl_data *)&vec1; \ |
| 216 VEC_xSSE2_CMP(name, op, /* nothing */, bits, size, first, second, /* nothing */, /* nothing */, /* nothing */) | 116 union v##sign##int32x4_impl_data *vec2d = (union v##sign##int32x4_impl_data *)&vec2; \ |
| 217 | 117 \ |
| 218 #define VEC_uSSE2_CMP(name, op, bits, size, first, second) \ | 118 vec1d->sse = _mm_cmpeq_epi32(vec1d->sse, vec2d->sse); \ |
| 219 VEC_xSSE2_CMP(name, op, u, bits, size, first, second, \ | 119 return vec1d->vec; \ |
| 220 __m128i xor_val = MM_SET1_##bits(1u << (bits - 1)); \ | 120 } while (0) |
| 221 , { \ | 121 |
| 222 vec1d->sse = _mm_xor_si128(vec1d->sse, xor_val); \ | 122 // SSE2 doesn't have an intrinsic for 64x2 equality comparison, |
| 223 vec2d->sse = _mm_xor_si128(vec2d->sse, xor_val); \ | 123 // so how can we take a 32x4 comparison result and turn it into |
| 224 }, \ | 124 // a 64x2 comparison result? |
| 225 { \ | 125 // |
| 226 /* nothing */ \ | 126 // well, Intel conveniently provided an operation where we can |
| 227 }) | 127 // shuffle around 32-bit integers (_mm_shuffle_epi32). |
| 228 | 128 // |
| 229 /* these are the same for unsigned and signed, for obvious reasons. */ | 129 // this means all we have to do is simply do the 32-bit operation, |
| 230 #define VEC_SSE2_CMPEQ_8x16(sign) VEC_xSSE2_CMP(cmpeq, cmpeq, sign, 8, 16, 1, 2, , ,) | 130 // shuffle the parts, and then return a bitwise AND of the result. |
| 231 #define VEC_SSE2_CMPEQ_16x8(sign) VEC_xSSE2_CMP(cmpeq, cmpeq, sign, 16, 8, 1, 2, , ,) | |
| 232 #define VEC_SSE2_CMPEQ_32x4(sign) VEC_xSSE2_CMP(cmpeq, cmpeq, sign, 32, 4, 1, 2, , ,) | |
| 233 | |
| 234 /* SSE2 doesn't have an intrinsic for 64x2 equality comparison, | |
| 235 * so how can we take a 32x4 comparison result and turn it into | |
| 236 * a 64x2 comparison result? | |
| 237 * | |
| 238 * well, Intel conveniently provided an operation where we can | |
| 239 * shuffle around 32-bit integers (_mm_shuffle_epi32). | |
| 240 * | |
| 241 * this means all we have to do is simply do the 32-bit operation, | |
| 242 * shuffle the parts, and then return a bitwise AND of the result. */ | |
| 243 | 131 |
| 244 #define VEC_SSE2_CMPEQ_64x2(sign) \ | 132 #define VEC_SSE2_CMPEQ_64x2(sign) \ |
| 245 VEC_FUNC_IMPL v##sign##int64x2 v##sign##int64x2_sse2_cmpeq(v##sign##int64x2 vec1, v##sign##int64x2 vec2) \ | 133 do { \ |
| 246 { \ | |
| 247 union v##sign##int64x2_impl_data *vec1d = (union v##sign##int64x2_impl_data *)&vec1; \ | 134 union v##sign##int64x2_impl_data *vec1d = (union v##sign##int64x2_impl_data *)&vec1; \ |
| 248 union v##sign##int64x2_impl_data *vec2d = (union v##sign##int64x2_impl_data *)&vec2; \ | 135 union v##sign##int64x2_impl_data *vec2d = (union v##sign##int64x2_impl_data *)&vec2; \ |
| 249 \ | 136 \ |
| 250 vec1d->sse = _mm_cmpeq_epi32(vec1d->sse, vec2d->sse); \ | 137 vec1d->sse = _mm_cmpeq_epi32(vec1d->sse, vec2d->sse); \ |
| 251 vec2d->sse = _mm_shuffle_epi32(vec1d->sse, _MM_SHUFFLE(1, 1, 3, 3)); \ | 138 vec2d->sse = _mm_shuffle_epi32(vec1d->sse, _MM_SHUFFLE(1, 1, 3, 3)); \ |
| 252 vec1d->sse = _mm_shuffle_epi32(vec1d->sse, _MM_SHUFFLE(0, 0, 2, 2)); \ | 139 vec1d->sse = _mm_shuffle_epi32(vec1d->sse, _MM_SHUFFLE(0, 0, 2, 2)); \ |
| 253 vec1d->sse = _mm_and_si128(vec1d->sse, vec2d->sse); \ | 140 vec1d->sse = _mm_and_si128(vec1d->sse, vec2d->sse); \ |
| 254 \ | 141 \ |
| 255 return vec1d->vec; \ | 142 return vec1d->vec; \ |
| 256 } | 143 } while (0) |
| 257 | |
| 258 /* ------------------------------------------------------------------------ */ | |
| 259 | |
| 260 #define VEC_SSE2_CMPLT_8x16(sign) VEC_##sign##SSE2_CMP(cmplt, cmpgt, 8, 16, 2, 1) | |
| 261 #define VEC_SSE2_CMPLT_16x8(sign) VEC_##sign##SSE2_CMP(cmplt, cmpgt, 16, 8, 2, 1) | |
| 262 #define VEC_SSE2_CMPLT_32x4(sign) VEC_##sign##SSE2_CMP(cmplt, cmpgt, 32, 4, 2, 1) | |
| 263 #define VEC_SSE2_CMPLT_64x2(sign) /* nothing */ | |
| 264 | |
| 265 #define VEC_SSE2_CMPGT_8x16(sign) VEC_##sign##SSE2_CMP(cmpgt, cmpgt, 8, 16, 1, 2) | |
| 266 #define VEC_SSE2_CMPGT_16x8(sign) VEC_##sign##SSE2_CMP(cmpgt, cmpgt, 16, 8, 1, 2) | |
| 267 #define VEC_SSE2_CMPGT_32x4(sign) VEC_##sign##SSE2_CMP(cmpgt, cmpgt, 32, 4, 1, 2) | |
| 268 #define VEC_SSE2_CMPGT_64x2(sign) /* nothing */ | |
| 269 | |
| 270 #define VEC_SSE2_STRUCT_CMP_8x16(name, sign) v##sign##int8x16_sse2_##name | |
| 271 #define VEC_SSE2_STRUCT_CMP_16x8(name, sign) v##sign##int16x8_sse2_##name | |
| 272 #define VEC_SSE2_STRUCT_CMP_32x4(name, sign) v##sign##int32x4_sse2_##name | |
| 273 #define VEC_SSE2_STRUCT_CMP_64x2(name, sign) NULL | |
| 274 | |
| 275 /* ------------------------------------------------------------------------ */ | |
| 276 | 144 |
| 277 #define VEC_SSE2_DEFINE_OPERATIONS_SIGN(sign, bits, size) \ | 145 #define VEC_SSE2_DEFINE_OPERATIONS_SIGN(sign, bits, size) \ |
| 278 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_splat(vec_##sign##int##bits x) \ | 146 union v##sign##int##bits##x##size##_impl_data { \ |
| 279 { \ | 147 v##sign##int##bits##x##size vec; \ |
| 280 union v##sign##int##bits##x##size##_impl_data vec; \ | 148 __m128i sse; \ |
| 281 vec.sse = MM_SET1_##bits(x); \ | 149 }; \ |
| 282 return vec.vec; \ | 150 \ |
| 283 } \ | 151 VEC_STATIC_ASSERT(VEC_ALIGNOF(__m128i) <= 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"); \ |
| 284 \ | 152 VEC_STATIC_ASSERT(sizeof(__m128i) <= sizeof(v##sign##int##bits##x##size), "vec: v" #sign "int" #bits "x" #size " needs to be expanded to fit intrinsic type size"); \ |
| 285 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_load_aligned(const vec_##sign##int##bits in[size]) \ | 153 \ |
| 154 v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_load_aligned(const vec_##sign##int##bits in[size]) \ | |
| 286 { \ | 155 { \ |
| 287 union v##sign##int##bits##x##size##_impl_data vec; \ | 156 union v##sign##int##bits##x##size##_impl_data vec; \ |
| 288 vec.sse = _mm_load_si128((const __m128i *)in); \ | 157 vec.sse = _mm_load_si128((const __m128i *)in); \ |
| 289 return vec.vec; \ | 158 return vec.vec; \ |
| 290 } \ | 159 } \ |
| 291 \ | 160 \ |
| 292 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_load(const vec_##sign##int##bits in[size]) \ | 161 v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_load(const vec_##sign##int##bits in[size]) \ |
| 293 { \ | 162 { \ |
| 294 union v##sign##int##bits##x##size##_impl_data vec; \ | 163 union v##sign##int##bits##x##size##_impl_data vec; \ |
| 295 vec.sse = _mm_loadu_si128((const __m128i *)in); \ | 164 vec.sse = _mm_loadu_si128((const __m128i *)in); \ |
| 296 return vec.vec; \ | 165 return vec.vec; \ |
| 297 } \ | 166 } \ |
| 298 \ | 167 \ |
| 299 VEC_FUNC_IMPL void v##sign##int##bits##x##size##_sse2_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ | 168 void v##sign##int##bits##x##size##_sse2_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ |
| 300 { \ | 169 { \ |
| 301 _mm_store_si128((__m128i *)out, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->sse); \ | 170 _mm_store_si128((__m128i *)out, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->sse); \ |
| 302 } \ | 171 } \ |
| 303 \ | 172 \ |
| 304 VEC_FUNC_IMPL void v##sign##int##bits##x##size##_sse2_store(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ | 173 void v##sign##int##bits##x##size##_sse2_store(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ |
| 305 { \ | 174 { \ |
| 306 _mm_storeu_si128((__m128i *)out, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->sse); \ | 175 _mm_storeu_si128((__m128i *)out, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->sse); \ |
| 307 } \ | 176 } \ |
| 308 \ | 177 \ |
| 309 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_add(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 178 v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_add(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 310 { \ | 179 { \ |
| 311 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 180 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 312 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 181 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
| 313 \ | 182 \ |
| 314 vec1d->sse = _mm_add_epi##bits(vec1d->sse, vec2d->sse); \ | 183 vec1d->sse = _mm_add_epi##bits(vec1d->sse, vec2d->sse); \ |
| 315 return vec1d->vec; \ | 184 return vec1d->vec; \ |
| 316 } \ | 185 } \ |
| 317 \ | 186 \ |
| 318 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_sub(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 187 v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_sub(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 319 { \ | 188 { \ |
| 320 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 189 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 321 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 190 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
| 322 \ | 191 \ |
| 323 vec1d->sse = _mm_sub_epi##bits(vec1d->sse, vec2d->sse); \ | 192 vec1d->sse = _mm_sub_epi##bits(vec1d->sse, vec2d->sse); \ |
| 324 return vec1d->vec; \ | 193 return vec1d->vec; \ |
| 325 } \ | 194 } \ |
| 326 \ | 195 \ |
| 327 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_mul(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 196 v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_mul(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 328 { \ | 197 { \ |
| 329 VEC_SSE2_MUL_##bits##x##size(sign); \ | 198 VEC_SSE2_MUL_##bits##x##size(sign); \ |
| 330 } \ | 199 } \ |
| 331 \ | 200 \ |
| 332 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 201 v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 333 { \ | 202 { \ |
| 334 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 203 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 335 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 204 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
| 336 \ | 205 \ |
| 337 vec1d->sse = _mm_and_si128(vec1d->sse, vec2d->sse); \ | 206 vec1d->sse = _mm_and_si128(vec1d->sse, vec2d->sse); \ |
| 338 return vec1d->vec; \ | 207 return vec1d->vec; \ |
| 339 } \ | 208 } \ |
| 340 \ | 209 \ |
| 341 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_or(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 210 v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_or(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 342 { \ | 211 { \ |
| 343 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 212 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 344 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 213 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
| 345 \ | 214 \ |
| 346 vec1d->sse = _mm_or_si128(vec1d->sse, vec2d->sse); \ | 215 vec1d->sse = _mm_or_si128(vec1d->sse, vec2d->sse); \ |
| 347 return vec1d->vec; \ | 216 return vec1d->vec; \ |
| 348 } \ | 217 } \ |
| 349 \ | 218 \ |
| 350 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_xor(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | 219 v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_xor(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 351 { \ | 220 { \ |
| 352 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 221 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
| 353 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 222 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
| 354 \ | 223 \ |
| 355 vec1d->sse = _mm_xor_si128(vec1d->sse, vec2d->sse); \ | 224 vec1d->sse = _mm_xor_si128(vec1d->sse, vec2d->sse); \ |
| 356 return vec1d->vec; \ | 225 return vec1d->vec; \ |
| 357 } \ | 226 } \ |
| 358 \ | 227 \ |
| 359 VEC_SSE2_CMPEQ_##bits##x##size(sign); \ | 228 v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_cmpeq(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ |
| 360 VEC_SSE2_CMPLT_##bits##x##size(sign); \ | 229 { \ |
| 361 VEC_SSE2_CMPGT_##bits##x##size(sign); \ | 230 VEC_SSE2_CMPEQ_##bits##x##size(sign); \ |
| 362 \ | 231 } \ |
| 363 VEC_SSE2_MINMAX_##sign##bits##x##size(min) \ | |
| 364 VEC_SSE2_MINMAX_##sign##bits##x##size(max) \ | |
| 365 \ | 232 \ |
| 366 const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_sse2 = { \ | 233 const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_sse2 = { \ |
| 367 .splat = v##sign##int##bits##x##size##_sse2_splat, \ | 234 v##sign##int##bits##x##size##_generic_splat, \ |
| 368 .load_aligned = v##sign##int##bits##x##size##_sse2_load_aligned, \ | 235 v##sign##int##bits##x##size##_sse2_load_aligned, \ |
| 369 .load = v##sign##int##bits##x##size##_sse2_load, \ | 236 v##sign##int##bits##x##size##_sse2_load, \ |
| 370 .store_aligned = v##sign##int##bits##x##size##_sse2_store_aligned, \ | 237 v##sign##int##bits##x##size##_sse2_store_aligned, \ |
| 371 .store = v##sign##int##bits##x##size##_sse2_store, \ | 238 v##sign##int##bits##x##size##_sse2_store, \ |
| 372 .add = v##sign##int##bits##x##size##_sse2_add, \ | 239 v##sign##int##bits##x##size##_sse2_add, \ |
| 373 .sub = v##sign##int##bits##x##size##_sse2_sub, \ | 240 v##sign##int##bits##x##size##_sse2_sub, \ |
| 374 .mul = v##sign##int##bits##x##size##_sse2_mul, \ | 241 v##sign##int##bits##x##size##_sse2_mul, \ |
| 375 .band = v##sign##int##bits##x##size##_sse2_and, \ | 242 v##sign##int##bits##x##size##_generic_div, \ |
| 376 .bor = v##sign##int##bits##x##size##_sse2_or, \ | 243 v##sign##int##bits##x##size##_generic_avg, \ |
| 377 .bxor = v##sign##int##bits##x##size##_sse2_xor, \ | 244 v##sign##int##bits##x##size##_sse2_and, \ |
| 378 .cmpeq = v##sign##int##bits##x##size##_sse2_cmpeq, \ | 245 v##sign##int##bits##x##size##_sse2_or, \ |
| 379 .cmplt = VEC_SSE2_STRUCT_CMP_##bits##x##size(cmplt, sign), \ | 246 v##sign##int##bits##x##size##_sse2_xor, \ |
| 380 .cmpgt = VEC_SSE2_STRUCT_CMP_##bits##x##size(cmpgt, sign), \ | 247 v##sign##int##bits##x##size##_generic_not, \ |
| 381 .min = VEC_SSE2_STRUCT_MINMAX_##bits##x##size(min, sign), \ | 248 v##sign##int##bits##x##size##_generic_lshift, \ |
| 382 .max = VEC_SSE2_STRUCT_MINMAX_##bits##x##size(max, sign), \ | 249 v##sign##int##bits##x##size##_generic_rshift, \ |
| 250 v##sign##int##bits##x##size##_generic_lrshift, \ | |
| 251 v##sign##int##bits##x##size##_generic_cmplt, \ | |
| 252 v##sign##int##bits##x##size##_generic_cmple, \ | |
| 253 v##sign##int##bits##x##size##_sse2_cmpeq, \ | |
| 254 v##sign##int##bits##x##size##_generic_cmpge, \ | |
| 255 v##sign##int##bits##x##size##_generic_cmpgt, \ | |
| 383 }; | 256 }; |
| 384 | 257 |
| 385 #define VEC_SSE2_DEFINE_OPERATIONS(bits, size) \ | 258 #define VEC_SSE2_DEFINE_OPERATIONS(bits, size) \ |
| 386 VEC_SSE2_DEFINE_OPERATIONS_SIGN(u, bits, size) \ | 259 VEC_SSE2_DEFINE_OPERATIONS_SIGN(u, bits, size) \ |
| 387 VEC_SSE2_DEFINE_OPERATIONS_SIGN( , bits, size) | 260 VEC_SSE2_DEFINE_OPERATIONS_SIGN( , bits, size) |
