Mercurial > vec
comparison src/impl/x86/sse2.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 |
comparison
equal
deleted
inserted
replaced
27:d00b95f95dd1 | 28:c6c99ab1088a |
---|---|
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" | |
27 | 26 |
28 #include <emmintrin.h> | 27 #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 */ | |
29 | 129 |
30 #define VEC_SSE2_OPERATION_8x16(op, sign) \ | 130 #define VEC_SSE2_OPERATION_8x16(op, sign) \ |
31 do { \ | 131 do { \ |
32 /* unpack and multiply */ \ | 132 /* unpack and multiply */ \ |
33 union v##sign##int8x16_impl_data *vec1d = (union v##sign##int8x16_impl_data *)&vec1; \ | 133 union v##sign##int8x16_impl_data *vec1d = (union v##sign##int8x16_impl_data *)&vec1; \ |
90 \ | 190 \ |
91 vec1d->sse = _mm_add_epi64(hi, ac); /* (ab3,ab2,ab1,ab0) */ \ | 191 vec1d->sse = _mm_add_epi64(hi, ac); /* (ab3,ab2,ab1,ab0) */ \ |
92 return vec1d->vec; \ | 192 return vec1d->vec; \ |
93 } while (0) | 193 } while (0) |
94 | 194 |
95 #define VEC_SSE2_CMPEQ_8x16(sign) \ | 195 /* ------------------------------------------------------------------------ */ |
96 do { \ | 196 /* comparison */ |
97 union v##sign##int8x16_impl_data *vec1d = (union v##sign##int8x16_impl_data *)&vec1; \ | 197 |
98 union v##sign##int8x16_impl_data *vec2d = (union v##sign##int8x16_impl_data *)&vec2; \ | 198 /* helper funcs */ |
99 \ | 199 #define VEC_xSSE2_CMP(name, op, sign, bits, size, first, second, VARS, TRANS1, TRANS2) \ |
100 vec1d->sse = _mm_cmpeq_epi8(vec1d->sse, vec2d->sse); \ | 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) \ |
101 return vec1d->vec; \ | 201 { \ |
102 } while (0) | 202 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
103 | 203 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
104 #define VEC_SSE2_CMPEQ_16x8(sign) \ | 204 VARS \ |
105 do { \ | 205 \ |
106 union v##sign##int16x8_impl_data *vec1d = (union v##sign##int16x8_impl_data *)&vec1; \ | 206 TRANS1 \ |
107 union v##sign##int16x8_impl_data *vec2d = (union v##sign##int16x8_impl_data *)&vec2; \ | 207 \ |
108 \ | 208 vec1d->sse = _mm_##op##_epi##bits(vec##first##d->sse, vec##second##d->sse); \ |
109 vec1d->sse = _mm_cmpeq_epi16(vec1d->sse, vec2d->sse); \ | 209 \ |
110 return vec1d->vec; \ | 210 TRANS2 \ |
111 } while (0) | 211 \ |
112 | 212 return vec1d->vec; \ |
113 #define VEC_SSE2_CMPEQ_32x4(sign) \ | 213 } |
114 do { \ | 214 |
115 union v##sign##int32x4_impl_data *vec1d = (union v##sign##int32x4_impl_data *)&vec1; \ | 215 #define VEC_SSE2_CMP(name, op, bits, size, first, second) \ |
116 union v##sign##int32x4_impl_data *vec2d = (union v##sign##int32x4_impl_data *)&vec2; \ | 216 VEC_xSSE2_CMP(name, op, /* nothing */, bits, size, first, second, /* nothing */, /* nothing */, /* nothing */) |
117 \ | 217 |
118 vec1d->sse = _mm_cmpeq_epi32(vec1d->sse, vec2d->sse); \ | 218 #define VEC_uSSE2_CMP(name, op, bits, size, first, second) \ |
119 return vec1d->vec; \ | 219 VEC_xSSE2_CMP(name, op, u, bits, size, first, second, \ |
120 } while (0) | 220 __m128i xor_val = MM_SET1_##bits(1u << (bits - 1)); \ |
121 | 221 , { \ |
122 // SSE2 doesn't have an intrinsic for 64x2 equality comparison, | 222 vec1d->sse = _mm_xor_si128(vec1d->sse, xor_val); \ |
123 // so how can we take a 32x4 comparison result and turn it into | 223 vec2d->sse = _mm_xor_si128(vec2d->sse, xor_val); \ |
124 // a 64x2 comparison result? | 224 }, \ |
125 // | 225 { \ |
126 // well, Intel conveniently provided an operation where we can | 226 /* nothing */ \ |
127 // shuffle around 32-bit integers (_mm_shuffle_epi32). | 227 }) |
128 // | 228 |
129 // this means all we have to do is simply do the 32-bit operation, | 229 /* these are the same for unsigned and signed, for obvious reasons. */ |
130 // shuffle the parts, and then return a bitwise AND of the result. | 230 #define VEC_SSE2_CMPEQ_8x16(sign) VEC_xSSE2_CMP(cmpeq, cmpeq, sign, 8, 16, 1, 2, , ,) |
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. */ | |
131 | 243 |
132 #define VEC_SSE2_CMPEQ_64x2(sign) \ | 244 #define VEC_SSE2_CMPEQ_64x2(sign) \ |
133 do { \ | 245 VEC_FUNC_IMPL v##sign##int64x2 v##sign##int64x2_sse2_cmpeq(v##sign##int64x2 vec1, v##sign##int64x2 vec2) \ |
246 { \ | |
134 union v##sign##int64x2_impl_data *vec1d = (union v##sign##int64x2_impl_data *)&vec1; \ | 247 union v##sign##int64x2_impl_data *vec1d = (union v##sign##int64x2_impl_data *)&vec1; \ |
135 union v##sign##int64x2_impl_data *vec2d = (union v##sign##int64x2_impl_data *)&vec2; \ | 248 union v##sign##int64x2_impl_data *vec2d = (union v##sign##int64x2_impl_data *)&vec2; \ |
136 \ | 249 \ |
137 vec1d->sse = _mm_cmpeq_epi32(vec1d->sse, vec2d->sse); \ | 250 vec1d->sse = _mm_cmpeq_epi32(vec1d->sse, vec2d->sse); \ |
138 vec2d->sse = _mm_shuffle_epi32(vec1d->sse, _MM_SHUFFLE(1, 1, 3, 3)); \ | 251 vec2d->sse = _mm_shuffle_epi32(vec1d->sse, _MM_SHUFFLE(1, 1, 3, 3)); \ |
139 vec1d->sse = _mm_shuffle_epi32(vec1d->sse, _MM_SHUFFLE(0, 0, 2, 2)); \ | 252 vec1d->sse = _mm_shuffle_epi32(vec1d->sse, _MM_SHUFFLE(0, 0, 2, 2)); \ |
140 vec1d->sse = _mm_and_si128(vec1d->sse, vec2d->sse); \ | 253 vec1d->sse = _mm_and_si128(vec1d->sse, vec2d->sse); \ |
141 \ | 254 \ |
142 return vec1d->vec; \ | 255 return vec1d->vec; \ |
143 } while (0) | 256 } |
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 /* ------------------------------------------------------------------------ */ | |
144 | 276 |
145 #define VEC_SSE2_DEFINE_OPERATIONS_SIGN(sign, bits, size) \ | 277 #define VEC_SSE2_DEFINE_OPERATIONS_SIGN(sign, bits, size) \ |
146 union v##sign##int##bits##x##size##_impl_data { \ | 278 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_splat(vec_##sign##int##bits x) \ |
147 v##sign##int##bits##x##size vec; \ | 279 { \ |
148 __m128i sse; \ | 280 union v##sign##int##bits##x##size##_impl_data vec; \ |
149 }; \ | 281 vec.sse = MM_SET1_##bits(x); \ |
150 \ | 282 return vec.vec; \ |
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"); \ | 283 } \ |
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"); \ | 284 \ |
153 \ | 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]) \ |
154 v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_load_aligned(const vec_##sign##int##bits in[size]) \ | |
155 { \ | 286 { \ |
156 union v##sign##int##bits##x##size##_impl_data vec; \ | 287 union v##sign##int##bits##x##size##_impl_data vec; \ |
157 vec.sse = _mm_load_si128((const __m128i *)in); \ | 288 vec.sse = _mm_load_si128((const __m128i *)in); \ |
158 return vec.vec; \ | 289 return vec.vec; \ |
159 } \ | 290 } \ |
160 \ | 291 \ |
161 v##sign##int##bits##x##size v##sign##int##bits##x##size##_sse2_load(const vec_##sign##int##bits in[size]) \ | 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]) \ |
162 { \ | 293 { \ |
163 union v##sign##int##bits##x##size##_impl_data vec; \ | 294 union v##sign##int##bits##x##size##_impl_data vec; \ |
164 vec.sse = _mm_loadu_si128((const __m128i *)in); \ | 295 vec.sse = _mm_loadu_si128((const __m128i *)in); \ |
165 return vec.vec; \ | 296 return vec.vec; \ |
166 } \ | 297 } \ |
167 \ | 298 \ |
168 void v##sign##int##bits##x##size##_sse2_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ | 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]) \ |
169 { \ | 300 { \ |
170 _mm_store_si128((__m128i *)out, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->sse); \ | 301 _mm_store_si128((__m128i *)out, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->sse); \ |
171 } \ | 302 } \ |
172 \ | 303 \ |
173 void v##sign##int##bits##x##size##_sse2_store(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ | 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]) \ |
174 { \ | 305 { \ |
175 _mm_storeu_si128((__m128i *)out, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->sse); \ | 306 _mm_storeu_si128((__m128i *)out, ((union v##sign##int##bits##x##size##_impl_data *)&vec)->sse); \ |
176 } \ | 307 } \ |
177 \ | 308 \ |
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) \ | 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) \ |
179 { \ | 310 { \ |
180 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 311 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
181 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 312 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
182 \ | 313 \ |
183 vec1d->sse = _mm_add_epi##bits(vec1d->sse, vec2d->sse); \ | 314 vec1d->sse = _mm_add_epi##bits(vec1d->sse, vec2d->sse); \ |
184 return vec1d->vec; \ | 315 return vec1d->vec; \ |
185 } \ | 316 } \ |
186 \ | 317 \ |
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) \ | 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) \ |
188 { \ | 319 { \ |
189 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 320 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
190 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 321 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
191 \ | 322 \ |
192 vec1d->sse = _mm_sub_epi##bits(vec1d->sse, vec2d->sse); \ | 323 vec1d->sse = _mm_sub_epi##bits(vec1d->sse, vec2d->sse); \ |
193 return vec1d->vec; \ | 324 return vec1d->vec; \ |
194 } \ | 325 } \ |
195 \ | 326 \ |
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) \ | 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) \ |
197 { \ | 328 { \ |
198 VEC_SSE2_MUL_##bits##x##size(sign); \ | 329 VEC_SSE2_MUL_##bits##x##size(sign); \ |
199 } \ | 330 } \ |
200 \ | 331 \ |
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) \ | 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) \ |
202 { \ | 333 { \ |
203 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 334 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
204 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 335 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
205 \ | 336 \ |
206 vec1d->sse = _mm_and_si128(vec1d->sse, vec2d->sse); \ | 337 vec1d->sse = _mm_and_si128(vec1d->sse, vec2d->sse); \ |
207 return vec1d->vec; \ | 338 return vec1d->vec; \ |
208 } \ | 339 } \ |
209 \ | 340 \ |
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) \ | 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) \ |
211 { \ | 342 { \ |
212 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 343 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
213 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 344 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
214 \ | 345 \ |
215 vec1d->sse = _mm_or_si128(vec1d->sse, vec2d->sse); \ | 346 vec1d->sse = _mm_or_si128(vec1d->sse, vec2d->sse); \ |
216 return vec1d->vec; \ | 347 return vec1d->vec; \ |
217 } \ | 348 } \ |
218 \ | 349 \ |
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) \ | 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) \ |
220 { \ | 351 { \ |
221 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | 352 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ |
222 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | 353 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ |
223 \ | 354 \ |
224 vec1d->sse = _mm_xor_si128(vec1d->sse, vec2d->sse); \ | 355 vec1d->sse = _mm_xor_si128(vec1d->sse, vec2d->sse); \ |
225 return vec1d->vec; \ | 356 return vec1d->vec; \ |
226 } \ | 357 } \ |
227 \ | 358 \ |
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) \ | 359 VEC_SSE2_CMPEQ_##bits##x##size(sign); \ |
229 { \ | 360 VEC_SSE2_CMPLT_##bits##x##size(sign); \ |
230 VEC_SSE2_CMPEQ_##bits##x##size(sign); \ | 361 VEC_SSE2_CMPGT_##bits##x##size(sign); \ |
231 } \ | 362 \ |
363 VEC_SSE2_MINMAX_##sign##bits##x##size(min) \ | |
364 VEC_SSE2_MINMAX_##sign##bits##x##size(max) \ | |
232 \ | 365 \ |
233 const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_sse2 = { \ | 366 const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_sse2 = { \ |
234 v##sign##int##bits##x##size##_generic_splat, \ | 367 .splat = v##sign##int##bits##x##size##_sse2_splat, \ |
235 v##sign##int##bits##x##size##_sse2_load_aligned, \ | 368 .load_aligned = v##sign##int##bits##x##size##_sse2_load_aligned, \ |
236 v##sign##int##bits##x##size##_sse2_load, \ | 369 .load = v##sign##int##bits##x##size##_sse2_load, \ |
237 v##sign##int##bits##x##size##_sse2_store_aligned, \ | 370 .store_aligned = v##sign##int##bits##x##size##_sse2_store_aligned, \ |
238 v##sign##int##bits##x##size##_sse2_store, \ | 371 .store = v##sign##int##bits##x##size##_sse2_store, \ |
239 v##sign##int##bits##x##size##_sse2_add, \ | 372 .add = v##sign##int##bits##x##size##_sse2_add, \ |
240 v##sign##int##bits##x##size##_sse2_sub, \ | 373 .sub = v##sign##int##bits##x##size##_sse2_sub, \ |
241 v##sign##int##bits##x##size##_sse2_mul, \ | 374 .mul = v##sign##int##bits##x##size##_sse2_mul, \ |
242 v##sign##int##bits##x##size##_generic_div, \ | 375 .band = v##sign##int##bits##x##size##_sse2_and, \ |
243 v##sign##int##bits##x##size##_generic_avg, \ | 376 .bor = v##sign##int##bits##x##size##_sse2_or, \ |
244 v##sign##int##bits##x##size##_sse2_and, \ | 377 .bxor = v##sign##int##bits##x##size##_sse2_xor, \ |
245 v##sign##int##bits##x##size##_sse2_or, \ | 378 .cmpeq = v##sign##int##bits##x##size##_sse2_cmpeq, \ |
246 v##sign##int##bits##x##size##_sse2_xor, \ | 379 .cmplt = VEC_SSE2_STRUCT_CMP_##bits##x##size(cmplt, sign), \ |
247 v##sign##int##bits##x##size##_generic_not, \ | 380 .cmpgt = VEC_SSE2_STRUCT_CMP_##bits##x##size(cmpgt, sign), \ |
248 v##sign##int##bits##x##size##_generic_lshift, \ | 381 .min = VEC_SSE2_STRUCT_MINMAX_##bits##x##size(min, sign), \ |
249 v##sign##int##bits##x##size##_generic_rshift, \ | 382 .max = VEC_SSE2_STRUCT_MINMAX_##bits##x##size(max, sign), \ |
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, \ | |
256 }; | 383 }; |
257 | 384 |
258 #define VEC_SSE2_DEFINE_OPERATIONS(bits, size) \ | 385 #define VEC_SSE2_DEFINE_OPERATIONS(bits, size) \ |
259 VEC_SSE2_DEFINE_OPERATIONS_SIGN(u, bits, size) \ | 386 VEC_SSE2_DEFINE_OPERATIONS_SIGN(u, bits, size) \ |
260 VEC_SSE2_DEFINE_OPERATIONS_SIGN( , bits, size) | 387 VEC_SSE2_DEFINE_OPERATIONS_SIGN( , bits, size) |