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) |