comparison src/impl/generic.c @ 23:e26874655738

*: huge refactor, new major release (hahaha) I keep finding things that are broken... The problem NOW was that vec would unintentionally build some functions with extended instruction sets, which is Bad and would mean that for all intents and purposes the CPU detection was completely broken. Now vec is no longer header only either. Boohoo. However this gives a lot more flexibility to vec since we no longer want or need to care about C++ crap. The NEON and Altivec implementations have not been updated which means they won't compile hence why they're commented out in the cmake build file.
author Paper <paper@tflc.us>
date Sun, 24 Nov 2024 02:52:40 -0500
parents
children 92156fe32755
comparison
equal deleted inserted replaced
22:fbcd3fa6f8fc 23:e26874655738
1 #include "vec/impl/generic.h"
2
3 #include <string.h>
4
5 // -----------------------------------------------------------------
6
7 #define VEC_GENERIC_OPERATION(op, sign, csign, bits, size) \
8 do { \
9 for (int i = 0; i < size; i++) \
10 ((union v##sign##int##bits##x##size##_impl_data *)&vec1)->impl[i] = (op); \
11 \
12 return vec1; \
13 } while (0)
14
15 #define VEC_GENERIC_BUILTIN_OPERATION(op, sign, csign, bits, size) \
16 VEC_GENERIC_OPERATION(((union v##sign##int##bits##x##size##_impl_data *)&vec1)->impl[i] op ((union v##sign##int##bits##x##size##_impl_data *)&vec2)->impl[i], sign, csign, bits, size)
17
18 #define VEC_GENERIC_CMP(op, sign, csign, bits, size) \
19 VEC_GENERIC_OPERATION((((union v##sign##int##bits##x##size##_impl_data *)&vec1)->impl[i] op ((union v##sign##int##bits##x##size##_impl_data *)&vec2)->impl[i]) ? VEC_UINT##bits##_MAX : 0, sign, csign, bits, size)
20
21 // TODO implement these so we don't waste stack space by doing the
22 // generics
23 #define VEC_GENERIC_DEFINE_OPERATIONS_SIGN(sign, csign, bits, size) \
24 union v##sign##int##bits##x##size##_impl_data { \
25 v##sign##int##bits##x##size vec; \
26 vec_##sign##int##bits impl[size]; \
27 }; \
28 \
29 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_splat(vec_##sign##int##bits x) \
30 { \
31 v##sign##int##bits##x##size vec; \
32 for (int i = 0; i < size; i++) \
33 ((union v##sign##int##bits##x##size##_impl_data *)&vec)->impl[i] = x; \
34 return vec; \
35 } \
36 \
37 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_load_aligned(const vec_##sign##int##bits in[size]) \
38 { \
39 v##sign##int##bits##x##size vec; \
40 memcpy(&vec, in, sizeof(vec_##sign##int##bits) * size); \
41 return vec; \
42 } \
43 \
44 void v##sign##int##bits##x##size##_generic_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \
45 { \
46 memcpy(out, &vec, sizeof(vec_##sign##int##bits) * size); \
47 } \
48 \
49 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_add(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
50 { \
51 VEC_GENERIC_BUILTIN_OPERATION(+, sign, csign, bits, size); \
52 } \
53 \
54 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_sub(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
55 { \
56 VEC_GENERIC_BUILTIN_OPERATION(-, sign, csign, bits, size); \
57 } \
58 \
59 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_mul(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
60 { \
61 VEC_GENERIC_BUILTIN_OPERATION(*, sign, csign, bits, size); \
62 } \
63 \
64 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_div(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
65 { \
66 VEC_GENERIC_OPERATION(((union v##sign##int##bits##x##size##_impl_data *)&vec2)->impl[i] ? (((union v##sign##int##bits##x##size##_impl_data *)&vec1)->impl[i] / ((union v##sign##int##bits##x##size##_impl_data *)&vec2)->impl[i]) : 0, sign, csign, bits, size); \
67 } \
68 \
69 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_avg(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
70 { \
71 VEC_GENERIC_OPERATION((((union v##sign##int##bits##x##size##_impl_data *)&vec1)->impl[i] + ((union v##sign##int##bits##x##size##_impl_data *)&vec2)->impl[i] + 1) / 2, sign, csign, bits, size); \
72 } \
73 \
74 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
75 { \
76 VEC_GENERIC_BUILTIN_OPERATION(&, sign, csign, bits, size); \
77 } \
78 \
79 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_or(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
80 { \
81 VEC_GENERIC_BUILTIN_OPERATION(|, sign, csign, bits, size); \
82 } \
83 \
84 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_xor(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
85 { \
86 VEC_GENERIC_BUILTIN_OPERATION(^, sign, csign, bits, size); \
87 } \
88 \
89 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_not(v##sign##int##bits##x##size vec) \
90 { \
91 return v##sign##int##bits##x##size##_generic_xor(vec, v##sign##int##bits##x##size##_generic_splat((vec_##sign##int##bits)VEC_UINT##bits##_MAX)); \
92 } \
93 \
94 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_cmplt(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
95 { \
96 VEC_GENERIC_CMP(<, sign, csign, bits, size); \
97 } \
98 \
99 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_cmple(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
100 { \
101 VEC_GENERIC_CMP(<=, sign, csign, bits, size); \
102 } \
103 \
104 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_cmpeq(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
105 { \
106 VEC_GENERIC_CMP(==, sign, csign, bits, size); \
107 } \
108 \
109 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_cmpge(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
110 { \
111 VEC_GENERIC_CMP(>=, sign, csign, bits, size); \
112 } \
113 \
114 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_cmpgt(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
115 { \
116 VEC_GENERIC_CMP(>, sign, csign, bits, size); \
117 } \
118 \
119 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_lshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \
120 { \
121 VEC_GENERIC_OPERATION(vec_##sign##lshift(((union v##sign##int##bits##x##size##_impl_data *)&vec1)->impl[i], ((union v##sign##int##bits##x##size##_impl_data *)&vec2)->impl[i]), sign, csign, bits, size); \
122 } \
123 \
124 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_rshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \
125 { \
126 VEC_GENERIC_OPERATION(vec_##sign##rshift(((union v##sign##int##bits##x##size##_impl_data *)&vec1)->impl[i], ((union v##sign##int##bits##x##size##_impl_data *)&vec2)->impl[i]), sign, csign, bits, size); \
127 } \
128 \
129 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_lrshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \
130 { \
131 VEC_GENERIC_OPERATION(vec_lrshift((vec_uint##bits)(((union v##sign##int##bits##x##size##_impl_data *)&vec1)->impl[i]), ((union v##sign##int##bits##x##size##_impl_data *)&vec2)->impl[i]), sign, csign, bits, size); \
132 } \
133 \
134 const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_generic = { \
135 v##sign##int##bits##x##size##_generic_splat, \
136 v##sign##int##bits##x##size##_generic_load_aligned, \
137 v##sign##int##bits##x##size##_generic_load_aligned, \
138 v##sign##int##bits##x##size##_generic_store_aligned, \
139 v##sign##int##bits##x##size##_generic_store_aligned, \
140 v##sign##int##bits##x##size##_generic_add, \
141 v##sign##int##bits##x##size##_generic_sub, \
142 v##sign##int##bits##x##size##_generic_mul, \
143 v##sign##int##bits##x##size##_generic_div, \
144 v##sign##int##bits##x##size##_generic_avg, \
145 v##sign##int##bits##x##size##_generic_and, \
146 v##sign##int##bits##x##size##_generic_or, \
147 v##sign##int##bits##x##size##_generic_xor, \
148 v##sign##int##bits##x##size##_generic_not, \
149 v##sign##int##bits##x##size##_generic_lshift, \
150 v##sign##int##bits##x##size##_generic_rshift, \
151 v##sign##int##bits##x##size##_generic_lrshift, \
152 v##sign##int##bits##x##size##_generic_cmplt, \
153 v##sign##int##bits##x##size##_generic_cmple, \
154 v##sign##int##bits##x##size##_generic_cmpeq, \
155 v##sign##int##bits##x##size##_generic_cmpge, \
156 v##sign##int##bits##x##size##_generic_cmpgt, \
157 };
158
159 #define VEC_GENERIC_DEFINE_OPERATIONS(bits, size) \
160 VEC_GENERIC_DEFINE_OPERATIONS_SIGN(u, U, bits, size) \
161 VEC_GENERIC_DEFINE_OPERATIONS_SIGN( , , bits, size)
162
163 VEC_GENERIC_DEFINE_OPERATIONS(8, 2)
164 VEC_GENERIC_DEFINE_OPERATIONS(16, 2)
165 VEC_GENERIC_DEFINE_OPERATIONS(32, 2)
166 VEC_GENERIC_DEFINE_OPERATIONS(64, 2)
167
168 #undef VEC_GENERIC_DEFINE_OPERATIONS
169 #undef VEC_GENERIC_DEFINE_OPERATIONS_SIGN
170
171 // -----------------------------------------------------------------
172 // now we can just keep doubling the same implementation
173
174 #define VEC_GENERIC_DEFINE_OPERATIONS_SIGN(sign, csign, bits, size, halfsize) \
175 union v##sign##int##bits##x##size##_impl_data { \
176 v##sign##int##bits##x##size vec; \
177 v##sign##int##bits##x##halfsize impl[2]; \
178 }; \
179 \
180 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_splat(vec_##sign##int##bits x) \
181 { \
182 union v##sign##int##bits##x##size##_impl_data vec; \
183 vec.impl[0] = v##sign##int##bits##x##halfsize##_splat(x); \
184 vec.impl[1] = v##sign##int##bits##x##halfsize##_splat(x); \
185 return vec.vec; \
186 } \
187 \
188 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_load_aligned(const vec_##sign##int##bits in[size]) \
189 { \
190 union v##sign##int##bits##x##size##_impl_data vec; \
191 vec.impl[0] = v##sign##int##bits##x##halfsize##_load_aligned(in); \
192 vec.impl[1] = v##sign##int##bits##x##halfsize##_load_aligned(in + halfsize); \
193 return vec.vec; \
194 } \
195 \
196 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_load(const vec_##sign##int##bits in[size]) \
197 { \
198 union v##sign##int##bits##x##size##_impl_data vec; \
199 vec.impl[0] = v##sign##int##bits##x##halfsize##_load(in); \
200 vec.impl[1] = v##sign##int##bits##x##halfsize##_load(in + halfsize); \
201 return vec.vec; \
202 } \
203 \
204 void v##sign##int##bits##x##size##_generic_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \
205 { \
206 union v##sign##int##bits##x##size##_impl_data *vecd = (union v##sign##int##bits##x##size##_impl_data *)&vec; \
207 \
208 v##sign##int##bits##x##halfsize##_store_aligned(vecd->impl[0], out); \
209 v##sign##int##bits##x##halfsize##_store_aligned(vecd->impl[1], out + halfsize); \
210 } \
211 \
212 void v##sign##int##bits##x##size##_generic_store(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \
213 { \
214 union v##sign##int##bits##x##size##_impl_data *vecd = (union v##sign##int##bits##x##size##_impl_data *)&vec; \
215 \
216 v##sign##int##bits##x##halfsize##_store(vecd->impl[0], out); \
217 v##sign##int##bits##x##halfsize##_store(vecd->impl[1], out + halfsize); \
218 } \
219 \
220 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_add(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
221 { \
222 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
223 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
224 \
225 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_add(vec1d->impl[0], vec2d->impl[0]); \
226 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_add(vec1d->impl[1], vec2d->impl[1]); \
227 \
228 return vec1d->vec; \
229 } \
230 \
231 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_sub(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
232 { \
233 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
234 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
235 \
236 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_sub(vec1d->impl[0], vec2d->impl[0]); \
237 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_sub(vec1d->impl[1], vec2d->impl[1]); \
238 \
239 return vec1d->vec; \
240 } \
241 \
242 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_mul(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
243 { \
244 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
245 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
246 \
247 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_mul(vec1d->impl[0], vec2d->impl[0]); \
248 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_mul(vec1d->impl[1], vec2d->impl[1]); \
249 \
250 return vec1d->vec; \
251 } \
252 \
253 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_div(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
254 { \
255 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
256 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
257 \
258 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_div(vec1d->impl[0], vec2d->impl[0]); \
259 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_div(vec1d->impl[1], vec2d->impl[1]); \
260 \
261 return vec1d->vec; \
262 } \
263 \
264 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_avg(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
265 { \
266 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
267 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
268 \
269 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_avg(vec1d->impl[0], vec2d->impl[0]); \
270 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_avg(vec1d->impl[1], vec2d->impl[1]); \
271 \
272 return vec1d->vec; \
273 } \
274 \
275 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
276 { \
277 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
278 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
279 \
280 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_and(vec1d->impl[0], vec2d->impl[0]); \
281 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_and(vec1d->impl[1], vec2d->impl[1]); \
282 \
283 return vec1d->vec; \
284 } \
285 \
286 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_or(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
287 { \
288 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
289 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
290 \
291 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_or(vec1d->impl[0], vec2d->impl[0]); \
292 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_or(vec1d->impl[1], vec2d->impl[1]); \
293 \
294 return vec1d->vec; \
295 } \
296 \
297 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_xor(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
298 { \
299 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
300 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
301 \
302 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_xor(vec1d->impl[0], vec2d->impl[0]); \
303 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_xor(vec1d->impl[1], vec2d->impl[1]); \
304 \
305 return vec1d->vec; \
306 } \
307 \
308 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_not(v##sign##int##bits##x##size vec1) \
309 { \
310 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
311 \
312 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_not(vec1d->impl[0]); \
313 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_not(vec1d->impl[1]); \
314 \
315 return vec1d->vec; \
316 } \
317 \
318 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_lshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \
319 { \
320 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
321 union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \
322 \
323 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_lshift(vec1d->impl[0], vec2d->impl[0]); \
324 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_lshift(vec1d->impl[1], vec2d->impl[1]); \
325 \
326 return vec1d->vec; \
327 } \
328 \
329 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_rshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \
330 { \
331 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
332 union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \
333 \
334 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_rshift(vec1d->impl[0], vec2d->impl[0]); \
335 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_rshift(vec1d->impl[1], vec2d->impl[1]); \
336 \
337 return vec1d->vec; \
338 } \
339 \
340 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_lrshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \
341 { \
342 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
343 union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \
344 \
345 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_lrshift(vec1d->impl[0], vec2d->impl[0]); \
346 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_lrshift(vec1d->impl[1], vec2d->impl[1]); \
347 \
348 return vec1d->vec; \
349 } \
350 \
351 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_cmplt(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
352 { \
353 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
354 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
355 \
356 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_cmplt(vec1d->impl[0], vec2d->impl[0]); \
357 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_cmplt(vec1d->impl[1], vec2d->impl[1]); \
358 \
359 return vec1d->vec; \
360 } \
361 \
362 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_cmple(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
363 { \
364 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
365 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
366 \
367 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_cmple(vec1d->impl[0], vec2d->impl[0]); \
368 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_cmple(vec1d->impl[1], vec2d->impl[1]); \
369 \
370 return vec1d->vec; \
371 } \
372 \
373 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_cmpeq(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
374 { \
375 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
376 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
377 \
378 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_cmpeq(vec1d->impl[0], vec2d->impl[0]); \
379 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_cmpeq(vec1d->impl[1], vec2d->impl[1]); \
380 \
381 return vec1d->vec; \
382 } \
383 \
384 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_cmpge(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
385 { \
386 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
387 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
388 \
389 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_cmpge(vec1d->impl[0], vec2d->impl[0]); \
390 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_cmpge(vec1d->impl[1], vec2d->impl[1]); \
391 \
392 return vec1d->vec; \
393 } \
394 \
395 v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_cmpgt(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
396 { \
397 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
398 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
399 \
400 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_cmpgt(vec1d->impl[0], vec2d->impl[0]); \
401 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_cmpgt(vec1d->impl[1], vec2d->impl[1]); \
402 \
403 return vec1d->vec; \
404 } \
405 \
406 const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_generic = { \
407 v##sign##int##bits##x##size##_generic_splat, \
408 v##sign##int##bits##x##size##_generic_load_aligned, \
409 v##sign##int##bits##x##size##_generic_load, \
410 v##sign##int##bits##x##size##_generic_store_aligned, \
411 v##sign##int##bits##x##size##_generic_store, \
412 v##sign##int##bits##x##size##_generic_add, \
413 v##sign##int##bits##x##size##_generic_sub, \
414 v##sign##int##bits##x##size##_generic_mul, \
415 v##sign##int##bits##x##size##_generic_div, \
416 v##sign##int##bits##x##size##_generic_avg, \
417 v##sign##int##bits##x##size##_generic_and, \
418 v##sign##int##bits##x##size##_generic_or, \
419 v##sign##int##bits##x##size##_generic_xor, \
420 v##sign##int##bits##x##size##_generic_not, \
421 v##sign##int##bits##x##size##_generic_lshift, \
422 v##sign##int##bits##x##size##_generic_rshift, \
423 v##sign##int##bits##x##size##_generic_lrshift, \
424 v##sign##int##bits##x##size##_generic_cmplt, \
425 v##sign##int##bits##x##size##_generic_cmple, \
426 v##sign##int##bits##x##size##_generic_cmpeq, \
427 v##sign##int##bits##x##size##_generic_cmpge, \
428 v##sign##int##bits##x##size##_generic_cmpgt, \
429 };
430
431 #define VEC_GENERIC_DEFINE_OPERATIONS(bits, size, halfsize) \
432 VEC_GENERIC_DEFINE_OPERATIONS_SIGN(u, U, bits, size, halfsize) \
433 VEC_GENERIC_DEFINE_OPERATIONS_SIGN( , , bits, size, halfsize)
434
435 // 32-bit
436 VEC_GENERIC_DEFINE_OPERATIONS(8, 4, 2)
437
438 // 64-bit
439 VEC_GENERIC_DEFINE_OPERATIONS(8, 8, 4)
440 VEC_GENERIC_DEFINE_OPERATIONS(16, 4, 2)
441
442 // 128-bit
443 VEC_GENERIC_DEFINE_OPERATIONS(8, 16, 8)
444 VEC_GENERIC_DEFINE_OPERATIONS(16, 8, 4)
445 VEC_GENERIC_DEFINE_OPERATIONS(32, 4, 2)
446
447 // 256-bit
448 VEC_GENERIC_DEFINE_OPERATIONS(8, 32, 16)
449 VEC_GENERIC_DEFINE_OPERATIONS(16, 16, 8)
450 VEC_GENERIC_DEFINE_OPERATIONS(32, 8, 4)
451 VEC_GENERIC_DEFINE_OPERATIONS(64, 4, 2)
452
453 // 512-bit
454 VEC_GENERIC_DEFINE_OPERATIONS(8, 64, 32)
455 VEC_GENERIC_DEFINE_OPERATIONS(16, 32, 16)
456 VEC_GENERIC_DEFINE_OPERATIONS(32, 16, 8)
457 VEC_GENERIC_DEFINE_OPERATIONS(64, 8, 4)
458
459 #undef VEC_GENERIC_DEFINE_OPERATIONS
460 #undef VEC_GENERIC_DEFINE_OPERATIONS_SIGN