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)