Mercurial > vec
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 |