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)