Mercurial > vec
comparison src/impl/gcc.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 | |
| children |
comparison
equal
deleted
inserted
replaced
| 27:d00b95f95dd1 | 28:c6c99ab1088a |
|---|---|
| 1 /** | |
| 2 * vec - a tiny SIMD vector library in C99 | |
| 3 * | |
| 4 * Copyright (c) 2024 Paper | |
| 5 * | |
| 6 * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 7 * of this software and associated documentation files (the "Software"), to deal | |
| 8 * in the Software without restriction, including without limitation the rights | |
| 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 10 * copies of the Software, and to permit persons to whom the Software is | |
| 11 * furnished to do so, subject to the following conditions: | |
| 12 * | |
| 13 * The above copyright notice and this permission notice shall be included in all | |
| 14 * copies or substantial portions of the Software. | |
| 15 * | |
| 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 22 * SOFTWARE. | |
| 23 **/ | |
| 24 | |
| 25 #include "vec/impl/gcc.h" | |
| 26 | |
| 27 // ----------------------------------------------------------------- | |
| 28 | |
| 29 #define VEC_GENERIC_OPERATION(op, sign, csign, bits, size) \ | |
| 30 do { \ | |
| 31 for (int i = 0; i < size; i++) \ | |
| 32 ((union v##sign##int##bits##x##size##_impl_data *)&vec1)->impl[i] = (op); \ | |
| 33 \ | |
| 34 return vec1; \ | |
| 35 } while (0) | |
| 36 | |
| 37 #define VEC_GENERIC_BUILTIN_OPERATION(op, sign, csign, bits, size) \ | |
| 38 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) | |
| 39 | |
| 40 #define VEC_GENERIC_CMP(op, sign, csign, bits, size) \ | |
| 41 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) | |
| 42 | |
| 43 // TODO implement these so we don't waste stack space by doing the | |
| 44 // generics | |
| 45 #define VEC_GENERIC_DEFINE_OPERATIONS_SIGN(sign, csign, bits, size) \ | |
| 46 union v##sign##int##bits##x##size##_impl_data { \ | |
| 47 v##sign##int##bits##x##size vec; \ | |
| 48 vec_##sign##int##bits impl[size]; \ | |
| 49 }; \ | |
| 50 \ | |
| 51 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_splat(vec_##sign##int##bits x) \ | |
| 52 { \ | |
| 53 v##sign##int##bits##x##size vec; \ | |
| 54 for (int i = 0; i < size; i++) \ | |
| 55 ((union v##sign##int##bits##x##size##_impl_data *)&vec)->impl[i] = x; \ | |
| 56 return vec; \ | |
| 57 } \ | |
| 58 \ | |
| 59 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_load_aligned(const vec_##sign##int##bits in[size]) \ | |
| 60 { \ | |
| 61 v##sign##int##bits##x##size vec; \ | |
| 62 memcpy(&vec, in, sizeof(vec_##sign##int##bits) * size); \ | |
| 63 return vec; \ | |
| 64 } \ | |
| 65 \ | |
| 66 VEC_FUNC_IMPL void v##sign##int##bits##x##size##_generic_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ | |
| 67 { \ | |
| 68 memcpy(out, &vec, sizeof(vec_##sign##int##bits) * size); \ | |
| 69 } \ | |
| 70 \ | |
| 71 VEC_FUNC_IMPL 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) \ | |
| 72 { \ | |
| 73 VEC_GENERIC_BUILTIN_OPERATION(+, sign, csign, bits, size); \ | |
| 74 } \ | |
| 75 \ | |
| 76 VEC_FUNC_IMPL 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) \ | |
| 77 { \ | |
| 78 VEC_GENERIC_BUILTIN_OPERATION(-, sign, csign, bits, size); \ | |
| 79 } \ | |
| 80 \ | |
| 81 VEC_FUNC_IMPL 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) \ | |
| 82 { \ | |
| 83 VEC_GENERIC_BUILTIN_OPERATION(*, sign, csign, bits, size); \ | |
| 84 } \ | |
| 85 \ | |
| 86 VEC_FUNC_IMPL 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) \ | |
| 87 { \ | |
| 88 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); \ | |
| 89 } \ | |
| 90 \ | |
| 91 VEC_FUNC_IMPL 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) \ | |
| 92 { \ | |
| 93 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 94 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | |
| 95 \ | |
| 96 for (int i = 0; i < size; i++) \ | |
| 97 vec1d->impl[i] = vec_##sign##avg(vec1d->impl[i], vec2d->impl[i]); \ | |
| 98 \ | |
| 99 return vec1d->vec; \ | |
| 100 } \ | |
| 101 \ | |
| 102 VEC_FUNC_IMPL 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) \ | |
| 103 { \ | |
| 104 VEC_GENERIC_BUILTIN_OPERATION(&, sign, csign, bits, size); \ | |
| 105 } \ | |
| 106 \ | |
| 107 VEC_FUNC_IMPL 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) \ | |
| 108 { \ | |
| 109 VEC_GENERIC_BUILTIN_OPERATION(|, sign, csign, bits, size); \ | |
| 110 } \ | |
| 111 \ | |
| 112 VEC_FUNC_IMPL 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) \ | |
| 113 { \ | |
| 114 VEC_GENERIC_BUILTIN_OPERATION(^, sign, csign, bits, size); \ | |
| 115 } \ | |
| 116 \ | |
| 117 VEC_FUNC_IMPL 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) \ | |
| 118 { \ | |
| 119 VEC_GENERIC_CMP(<, sign, csign, bits, size); \ | |
| 120 } \ | |
| 121 \ | |
| 122 VEC_FUNC_IMPL 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) \ | |
| 123 { \ | |
| 124 return v##sign##int##bits##x##size##_not(v##sign##int##bits##x##size##_cmpgt(vec1, vec2)); \ | |
| 125 } \ | |
| 126 \ | |
| 127 VEC_FUNC_IMPL 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) \ | |
| 128 { \ | |
| 129 VEC_GENERIC_CMP(==, sign, csign, bits, size); \ | |
| 130 } \ | |
| 131 \ | |
| 132 VEC_FUNC_IMPL 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) \ | |
| 133 { \ | |
| 134 return v##sign##int##bits##x##size##_not(v##sign##int##bits##x##size##_cmplt(vec1, vec2)); \ | |
| 135 } \ | |
| 136 \ | |
| 137 VEC_FUNC_IMPL 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) \ | |
| 138 { \ | |
| 139 VEC_GENERIC_CMP(>, sign, csign, bits, size); \ | |
| 140 } \ | |
| 141 \ | |
| 142 VEC_FUNC_IMPL 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) \ | |
| 143 { \ | |
| 144 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); \ | |
| 145 } \ | |
| 146 \ | |
| 147 VEC_FUNC_IMPL 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) \ | |
| 148 { \ | |
| 149 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); \ | |
| 150 } \ | |
| 151 \ | |
| 152 VEC_FUNC_IMPL 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) \ | |
| 153 { \ | |
| 154 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); \ | |
| 155 } \ | |
| 156 \ | |
| 157 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_min(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | |
| 158 { \ | |
| 159 v##sign##int##bits##x##size cmplt = v##sign##int##bits##x##size##_cmplt(vec1, vec2); \ | |
| 160 \ | |
| 161 v##sign##int##bits##x##size a = v##sign##int##bits##x##size##_and(vec1, cmplt); \ | |
| 162 v##sign##int##bits##x##size b = v##sign##int##bits##x##size##_and(vec2, v##sign##int##bits##x##size##_not(cmplt)); \ | |
| 163 \ | |
| 164 return v##sign##int##bits##x##size##_or(a, b); \ | |
| 165 } \ | |
| 166 \ | |
| 167 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_max(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | |
| 168 { \ | |
| 169 v##sign##int##bits##x##size cmplt = v##sign##int##bits##x##size##_cmpgt(vec1, vec2); \ | |
| 170 \ | |
| 171 v##sign##int##bits##x##size a = v##sign##int##bits##x##size##_and(vec1, cmplt); \ | |
| 172 v##sign##int##bits##x##size b = v##sign##int##bits##x##size##_and(vec2, v##sign##int##bits##x##size##_not(cmplt)); \ | |
| 173 \ | |
| 174 return v##sign##int##bits##x##size##_or(a, b); \ | |
| 175 } \ | |
| 176 \ | |
| 177 const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_generic = { \ | |
| 178 .splat = v##sign##int##bits##x##size##_generic_splat, \ | |
| 179 .load_aligned = v##sign##int##bits##x##size##_generic_load_aligned, \ | |
| 180 .load = v##sign##int##bits##x##size##_generic_load_aligned, \ | |
| 181 .store_aligned = v##sign##int##bits##x##size##_generic_store_aligned, \ | |
| 182 .store = v##sign##int##bits##x##size##_generic_store_aligned, \ | |
| 183 .add = v##sign##int##bits##x##size##_generic_add, \ | |
| 184 .sub = v##sign##int##bits##x##size##_generic_sub, \ | |
| 185 .mul = v##sign##int##bits##x##size##_generic_mul, \ | |
| 186 .div = v##sign##int##bits##x##size##_generic_div, \ | |
| 187 .avg = v##sign##int##bits##x##size##_generic_avg, \ | |
| 188 .band = v##sign##int##bits##x##size##_generic_and, \ | |
| 189 .bor = v##sign##int##bits##x##size##_generic_or, \ | |
| 190 .bxor = v##sign##int##bits##x##size##_generic_xor, \ | |
| 191 .lshift = v##sign##int##bits##x##size##_generic_lshift, \ | |
| 192 .rshift = v##sign##int##bits##x##size##_generic_rshift, \ | |
| 193 .lrshift = v##sign##int##bits##x##size##_generic_lrshift, \ | |
| 194 .cmplt = v##sign##int##bits##x##size##_generic_cmplt, \ | |
| 195 .cmple = v##sign##int##bits##x##size##_generic_cmple, \ | |
| 196 .cmpeq = v##sign##int##bits##x##size##_generic_cmpeq, \ | |
| 197 .cmpge = v##sign##int##bits##x##size##_generic_cmpge, \ | |
| 198 .cmpgt = v##sign##int##bits##x##size##_generic_cmpgt, \ | |
| 199 .min = v##sign##int##bits##x##size##_generic_min, \ | |
| 200 .max = v##sign##int##bits##x##size##_generic_max, \ | |
| 201 }; | |
| 202 | |
| 203 #define VEC_GENERIC_DEFINE_OPERATIONS(bits, size) \ | |
| 204 VEC_GENERIC_DEFINE_OPERATIONS_SIGN(u, U, bits, size) \ | |
| 205 VEC_GENERIC_DEFINE_OPERATIONS_SIGN( , , bits, size) | |
| 206 | |
| 207 VEC_GENERIC_DEFINE_OPERATIONS(8, 2) | |
| 208 VEC_GENERIC_DEFINE_OPERATIONS(16, 2) | |
| 209 VEC_GENERIC_DEFINE_OPERATIONS(32, 2) | |
| 210 VEC_GENERIC_DEFINE_OPERATIONS(64, 2) | |
| 211 | |
| 212 #undef VEC_GENERIC_DEFINE_OPERATIONS | |
| 213 #undef VEC_GENERIC_DEFINE_OPERATIONS_SIGN | |
| 214 | |
| 215 // ----------------------------------------------------------------- | |
| 216 // now we can just keep doubling the same implementation | |
| 217 | |
| 218 #define VEC_GENERIC_DEFINE_OPERATIONS_SIGN(sign, csign, bits, size, halfsize) \ | |
| 219 union v##sign##int##bits##x##size##_impl_data { \ | |
| 220 v##sign##int##bits##x##size vec; \ | |
| 221 v##sign##int##bits##x##halfsize impl[2]; \ | |
| 222 }; \ | |
| 223 \ | |
| 224 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_splat(vec_##sign##int##bits x) \ | |
| 225 { \ | |
| 226 union v##sign##int##bits##x##size##_impl_data vec; \ | |
| 227 vec.impl[0] = v##sign##int##bits##x##halfsize##_splat(x); \ | |
| 228 vec.impl[1] = v##sign##int##bits##x##halfsize##_splat(x); \ | |
| 229 return vec.vec; \ | |
| 230 } \ | |
| 231 \ | |
| 232 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_load_aligned(const vec_##sign##int##bits in[size]) \ | |
| 233 { \ | |
| 234 union v##sign##int##bits##x##size##_impl_data vec; \ | |
| 235 vec.impl[0] = v##sign##int##bits##x##halfsize##_load_aligned(in); \ | |
| 236 vec.impl[1] = v##sign##int##bits##x##halfsize##_load_aligned(in + halfsize); \ | |
| 237 return vec.vec; \ | |
| 238 } \ | |
| 239 \ | |
| 240 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_load(const vec_##sign##int##bits in[size]) \ | |
| 241 { \ | |
| 242 union v##sign##int##bits##x##size##_impl_data vec; \ | |
| 243 vec.impl[0] = v##sign##int##bits##x##halfsize##_load(in); \ | |
| 244 vec.impl[1] = v##sign##int##bits##x##halfsize##_load(in + halfsize); \ | |
| 245 return vec.vec; \ | |
| 246 } \ | |
| 247 \ | |
| 248 VEC_FUNC_IMPL void v##sign##int##bits##x##size##_generic_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ | |
| 249 { \ | |
| 250 union v##sign##int##bits##x##size##_impl_data *vecd = (union v##sign##int##bits##x##size##_impl_data *)&vec; \ | |
| 251 \ | |
| 252 v##sign##int##bits##x##halfsize##_store_aligned(vecd->impl[0], out); \ | |
| 253 v##sign##int##bits##x##halfsize##_store_aligned(vecd->impl[1], out + halfsize); \ | |
| 254 } \ | |
| 255 \ | |
| 256 VEC_FUNC_IMPL void v##sign##int##bits##x##size##_generic_store(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \ | |
| 257 { \ | |
| 258 union v##sign##int##bits##x##size##_impl_data *vecd = (union v##sign##int##bits##x##size##_impl_data *)&vec; \ | |
| 259 \ | |
| 260 v##sign##int##bits##x##halfsize##_store(vecd->impl[0], out); \ | |
| 261 v##sign##int##bits##x##halfsize##_store(vecd->impl[1], out + halfsize); \ | |
| 262 } \ | |
| 263 \ | |
| 264 VEC_FUNC_IMPL 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) \ | |
| 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##_add(vec1d->impl[0], vec2d->impl[0]); \ | |
| 270 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_add(vec1d->impl[1], vec2d->impl[1]); \ | |
| 271 \ | |
| 272 return vec1d->vec; \ | |
| 273 } \ | |
| 274 \ | |
| 275 VEC_FUNC_IMPL 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) \ | |
| 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##_sub(vec1d->impl[0], vec2d->impl[0]); \ | |
| 281 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_sub(vec1d->impl[1], vec2d->impl[1]); \ | |
| 282 \ | |
| 283 return vec1d->vec; \ | |
| 284 } \ | |
| 285 \ | |
| 286 VEC_FUNC_IMPL 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) \ | |
| 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##_mul(vec1d->impl[0], vec2d->impl[0]); \ | |
| 292 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_mul(vec1d->impl[1], vec2d->impl[1]); \ | |
| 293 \ | |
| 294 return vec1d->vec; \ | |
| 295 } \ | |
| 296 \ | |
| 297 VEC_FUNC_IMPL 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) \ | |
| 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##_div(vec1d->impl[0], vec2d->impl[0]); \ | |
| 303 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_div(vec1d->impl[1], vec2d->impl[1]); \ | |
| 304 \ | |
| 305 return vec1d->vec; \ | |
| 306 } \ | |
| 307 \ | |
| 308 VEC_FUNC_IMPL 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) \ | |
| 309 { \ | |
| 310 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 *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | |
| 312 \ | |
| 313 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_avg(vec1d->impl[0], vec2d->impl[0]); \ | |
| 314 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_avg(vec1d->impl[1], vec2d->impl[1]); \ | |
| 315 \ | |
| 316 return vec1d->vec; \ | |
| 317 } \ | |
| 318 \ | |
| 319 VEC_FUNC_IMPL 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) \ | |
| 320 { \ | |
| 321 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 322 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | |
| 323 \ | |
| 324 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_and(vec1d->impl[0], vec2d->impl[0]); \ | |
| 325 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_and(vec1d->impl[1], vec2d->impl[1]); \ | |
| 326 \ | |
| 327 return vec1d->vec; \ | |
| 328 } \ | |
| 329 \ | |
| 330 VEC_FUNC_IMPL 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) \ | |
| 331 { \ | |
| 332 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 333 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | |
| 334 \ | |
| 335 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_or(vec1d->impl[0], vec2d->impl[0]); \ | |
| 336 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_or(vec1d->impl[1], vec2d->impl[1]); \ | |
| 337 \ | |
| 338 return vec1d->vec; \ | |
| 339 } \ | |
| 340 \ | |
| 341 VEC_FUNC_IMPL 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) \ | |
| 342 { \ | |
| 343 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; \ | |
| 345 \ | |
| 346 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_xor(vec1d->impl[0], vec2d->impl[0]); \ | |
| 347 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_xor(vec1d->impl[1], vec2d->impl[1]); \ | |
| 348 \ | |
| 349 return vec1d->vec; \ | |
| 350 } \ | |
| 351 \ | |
| 352 VEC_FUNC_IMPL 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) \ | |
| 353 { \ | |
| 354 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 355 union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \ | |
| 356 \ | |
| 357 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_lshift(vec1d->impl[0], vec2d->impl[0]); \ | |
| 358 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_lshift(vec1d->impl[1], vec2d->impl[1]); \ | |
| 359 \ | |
| 360 return vec1d->vec; \ | |
| 361 } \ | |
| 362 \ | |
| 363 VEC_FUNC_IMPL 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) \ | |
| 364 { \ | |
| 365 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 366 union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \ | |
| 367 \ | |
| 368 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_rshift(vec1d->impl[0], vec2d->impl[0]); \ | |
| 369 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_rshift(vec1d->impl[1], vec2d->impl[1]); \ | |
| 370 \ | |
| 371 return vec1d->vec; \ | |
| 372 } \ | |
| 373 \ | |
| 374 VEC_FUNC_IMPL 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) \ | |
| 375 { \ | |
| 376 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 377 union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \ | |
| 378 \ | |
| 379 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_lrshift(vec1d->impl[0], vec2d->impl[0]); \ | |
| 380 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_lrshift(vec1d->impl[1], vec2d->impl[1]); \ | |
| 381 \ | |
| 382 return vec1d->vec; \ | |
| 383 } \ | |
| 384 \ | |
| 385 VEC_FUNC_IMPL 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) \ | |
| 386 { \ | |
| 387 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 388 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | |
| 389 \ | |
| 390 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_cmplt(vec1d->impl[0], vec2d->impl[0]); \ | |
| 391 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_cmplt(vec1d->impl[1], vec2d->impl[1]); \ | |
| 392 \ | |
| 393 return vec1d->vec; \ | |
| 394 } \ | |
| 395 \ | |
| 396 VEC_FUNC_IMPL 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) \ | |
| 397 { \ | |
| 398 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 399 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | |
| 400 \ | |
| 401 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_cmple(vec1d->impl[0], vec2d->impl[0]); \ | |
| 402 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_cmple(vec1d->impl[1], vec2d->impl[1]); \ | |
| 403 \ | |
| 404 return vec1d->vec; \ | |
| 405 } \ | |
| 406 \ | |
| 407 VEC_FUNC_IMPL 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) \ | |
| 408 { \ | |
| 409 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 410 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | |
| 411 \ | |
| 412 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_cmpeq(vec1d->impl[0], vec2d->impl[0]); \ | |
| 413 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_cmpeq(vec1d->impl[1], vec2d->impl[1]); \ | |
| 414 \ | |
| 415 return vec1d->vec; \ | |
| 416 } \ | |
| 417 \ | |
| 418 VEC_FUNC_IMPL 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) \ | |
| 419 { \ | |
| 420 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 421 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | |
| 422 \ | |
| 423 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_cmpge(vec1d->impl[0], vec2d->impl[0]); \ | |
| 424 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_cmpge(vec1d->impl[1], vec2d->impl[1]); \ | |
| 425 \ | |
| 426 return vec1d->vec; \ | |
| 427 } \ | |
| 428 \ | |
| 429 VEC_FUNC_IMPL 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) \ | |
| 430 { \ | |
| 431 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 432 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | |
| 433 \ | |
| 434 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_cmpgt(vec1d->impl[0], vec2d->impl[0]); \ | |
| 435 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_cmpgt(vec1d->impl[1], vec2d->impl[1]); \ | |
| 436 \ | |
| 437 return vec1d->vec; \ | |
| 438 } \ | |
| 439 \ | |
| 440 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_min(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | |
| 441 { \ | |
| 442 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 443 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | |
| 444 \ | |
| 445 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_min(vec1d->impl[0], vec2d->impl[0]); \ | |
| 446 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_min(vec1d->impl[1], vec2d->impl[1]); \ | |
| 447 \ | |
| 448 return vec1d->vec; \ | |
| 449 } \ | |
| 450 \ | |
| 451 VEC_FUNC_IMPL v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_max(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \ | |
| 452 { \ | |
| 453 union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \ | |
| 454 union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \ | |
| 455 \ | |
| 456 vec1d->impl[0] = v##sign##int##bits##x##halfsize##_max(vec1d->impl[0], vec2d->impl[0]); \ | |
| 457 vec1d->impl[1] = v##sign##int##bits##x##halfsize##_max(vec1d->impl[1], vec2d->impl[1]); \ | |
| 458 \ | |
| 459 return vec1d->vec; \ | |
| 460 } \ | |
| 461 \ | |
| 462 const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_generic = { \ | |
| 463 .splat = v##sign##int##bits##x##size##_generic_splat, \ | |
| 464 .load_aligned = v##sign##int##bits##x##size##_generic_load_aligned, \ | |
| 465 .load = v##sign##int##bits##x##size##_generic_load, \ | |
| 466 .store_aligned = v##sign##int##bits##x##size##_generic_store_aligned, \ | |
| 467 .store = v##sign##int##bits##x##size##_generic_store, \ | |
| 468 .add = v##sign##int##bits##x##size##_generic_add, \ | |
| 469 .sub = v##sign##int##bits##x##size##_generic_sub, \ | |
| 470 .mul = v##sign##int##bits##x##size##_generic_mul, \ | |
| 471 .div = v##sign##int##bits##x##size##_generic_div, \ | |
| 472 .avg = v##sign##int##bits##x##size##_generic_avg, \ | |
| 473 .band = v##sign##int##bits##x##size##_generic_and, \ | |
| 474 .bor = v##sign##int##bits##x##size##_generic_or, \ | |
| 475 .bxor = v##sign##int##bits##x##size##_generic_xor, \ | |
| 476 .lshift = v##sign##int##bits##x##size##_generic_lshift, \ | |
| 477 .rshift = v##sign##int##bits##x##size##_generic_rshift, \ | |
| 478 .lrshift = v##sign##int##bits##x##size##_generic_lrshift, \ | |
| 479 .cmplt = v##sign##int##bits##x##size##_generic_cmplt, \ | |
| 480 .cmple = v##sign##int##bits##x##size##_generic_cmple, \ | |
| 481 .cmpeq = v##sign##int##bits##x##size##_generic_cmpeq, \ | |
| 482 .cmpge = v##sign##int##bits##x##size##_generic_cmpge, \ | |
| 483 .cmpgt = v##sign##int##bits##x##size##_generic_cmpgt, \ | |
| 484 .min = v##sign##int##bits##x##size##_generic_min, \ | |
| 485 .max = v##sign##int##bits##x##size##_generic_max, \ | |
| 486 }; | |
| 487 | |
| 488 #define VEC_GENERIC_DEFINE_OPERATIONS(bits, size, halfsize) \ | |
| 489 VEC_GENERIC_DEFINE_OPERATIONS_SIGN(u, U, bits, size, halfsize) \ | |
| 490 VEC_GENERIC_DEFINE_OPERATIONS_SIGN( , , bits, size, halfsize) | |
| 491 | |
| 492 // 32-bit | |
| 493 VEC_GENERIC_DEFINE_OPERATIONS(8, 4, 2) | |
| 494 | |
| 495 // 64-bit | |
| 496 VEC_GENERIC_DEFINE_OPERATIONS(8, 8, 4) | |
| 497 VEC_GENERIC_DEFINE_OPERATIONS(16, 4, 2) | |
| 498 | |
| 499 // 128-bit | |
| 500 VEC_GENERIC_DEFINE_OPERATIONS(8, 16, 8) | |
| 501 VEC_GENERIC_DEFINE_OPERATIONS(16, 8, 4) | |
| 502 VEC_GENERIC_DEFINE_OPERATIONS(32, 4, 2) | |
| 503 | |
| 504 // 256-bit | |
| 505 VEC_GENERIC_DEFINE_OPERATIONS(8, 32, 16) | |
| 506 VEC_GENERIC_DEFINE_OPERATIONS(16, 16, 8) | |
| 507 VEC_GENERIC_DEFINE_OPERATIONS(32, 8, 4) | |
| 508 VEC_GENERIC_DEFINE_OPERATIONS(64, 4, 2) | |
| 509 | |
| 510 // 512-bit | |
| 511 VEC_GENERIC_DEFINE_OPERATIONS(8, 64, 32) | |
| 512 VEC_GENERIC_DEFINE_OPERATIONS(16, 32, 16) | |
| 513 VEC_GENERIC_DEFINE_OPERATIONS(32, 16, 8) | |
| 514 VEC_GENERIC_DEFINE_OPERATIONS(64, 8, 4) | |
| 515 | |
| 516 #undef VEC_GENERIC_DEFINE_OPERATIONS | |
| 517 #undef VEC_GENERIC_DEFINE_OPERATIONS_SIGN |
