master
h 495 lines 9.3 KB
Raw
1 #ifndef INT128_H
2 #define INT128_H
3
4 /*
5 * With TCI, we need to use libffi for interfacing with TCG helpers.
6 * But libffi does not support __int128_t, and therefore cannot pass
7 * or return values of this type, force use of the Int128 struct.
8 */
9 #if defined(CONFIG_INT128) && !defined(CONFIG_TCG_INTERPRETER)
10 typedef __int128_t Int128;
11 typedef __int128_t __attribute__((aligned(16))) Int128Aligned;
12
13 static inline Int128 int128_make64(uint64_t a)
14 {
15 return a;
16 }
17
18 static inline Int128 int128_makes64(int64_t a)
19 {
20 return a;
21 }
22
23 static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
24 {
25 return (__uint128_t)hi << 64 | lo;
26 }
27
28 static inline uint64_t int128_get64(Int128 a)
29 {
30 uint64_t r = a;
31 assert(r == a);
32 return r;
33 }
34
35 static inline uint64_t int128_getlo(Int128 a)
36 {
37 return a;
38 }
39
40 static inline int64_t int128_gethi(Int128 a)
41 {
42 return a >> 64;
43 }
44
45 static inline Int128 int128_zero(void)
46 {
47 return 0;
48 }
49
50 static inline Int128 int128_one(void)
51 {
52 return 1;
53 }
54
55 static inline Int128 int128_2_64(void)
56 {
57 return (Int128)1 << 64;
58 }
59
60 static inline Int128 int128_exts64(int64_t a)
61 {
62 return a;
63 }
64
65 static inline Int128 int128_not(Int128 a)
66 {
67 return ~a;
68 }
69
70 static inline Int128 int128_and(Int128 a, Int128 b)
71 {
72 return a & b;
73 }
74
75 static inline Int128 int128_or(Int128 a, Int128 b)
76 {
77 return a | b;
78 }
79
80 static inline Int128 int128_xor(Int128 a, Int128 b)
81 {
82 return a ^ b;
83 }
84
85 static inline Int128 int128_rshift(Int128 a, int n)
86 {
87 return a >> n;
88 }
89
90 static inline Int128 int128_urshift(Int128 a, int n)
91 {
92 return (__uint128_t)a >> n;
93 }
94
95 static inline Int128 int128_lshift(Int128 a, int n)
96 {
97 return a << n;
98 }
99
100 static inline Int128 int128_add(Int128 a, Int128 b)
101 {
102 return a + b;
103 }
104
105 static inline Int128 int128_neg(Int128 a)
106 {
107 return -a;
108 }
109
110 static inline Int128 int128_sub(Int128 a, Int128 b)
111 {
112 return a - b;
113 }
114
115 static inline bool int128_nonneg(Int128 a)
116 {
117 return a >= 0;
118 }
119
120 static inline bool int128_eq(Int128 a, Int128 b)
121 {
122 return a == b;
123 }
124
125 static inline bool int128_ne(Int128 a, Int128 b)
126 {
127 return a != b;
128 }
129
130 static inline bool int128_ge(Int128 a, Int128 b)
131 {
132 return a >= b;
133 }
134
135 static inline bool int128_uge(Int128 a, Int128 b)
136 {
137 return ((__uint128_t)a) >= ((__uint128_t)b);
138 }
139
140 static inline bool int128_lt(Int128 a, Int128 b)
141 {
142 return a < b;
143 }
144
145 static inline bool int128_ult(Int128 a, Int128 b)
146 {
147 return (__uint128_t)a < (__uint128_t)b;
148 }
149
150 static inline bool int128_le(Int128 a, Int128 b)
151 {
152 return a <= b;
153 }
154
155 static inline bool int128_gt(Int128 a, Int128 b)
156 {
157 return a > b;
158 }
159
160 static inline bool int128_nz(Int128 a)
161 {
162 return a != 0;
163 }
164
165 static inline Int128 int128_min(Int128 a, Int128 b)
166 {
167 return a < b ? a : b;
168 }
169
170 static inline Int128 int128_max(Int128 a, Int128 b)
171 {
172 return a > b ? a : b;
173 }
174
175 static inline void int128_addto(Int128 *a, Int128 b)
176 {
177 *a += b;
178 }
179
180 static inline void int128_subfrom(Int128 *a, Int128 b)
181 {
182 *a -= b;
183 }
184
185 static inline Int128 bswap128(Int128 a)
186 {
187 #if __has_builtin(__builtin_bswap128)
188 return __builtin_bswap128(a);
189 #else
190 return int128_make128(__builtin_bswap64(int128_gethi(a)),
191 __builtin_bswap64(int128_getlo(a)));
192 #endif
193 }
194
195 static inline int clz128(Int128 a)
196 {
197 if (a >> 64) {
198 return __builtin_clzll(a >> 64);
199 } else {
200 return (a) ? __builtin_clzll((uint64_t)a) + 64 : 128;
201 }
202 }
203
204 static inline Int128 int128_divu(Int128 a, Int128 b)
205 {
206 return (__uint128_t)a / (__uint128_t)b;
207 }
208
209 static inline Int128 int128_remu(Int128 a, Int128 b)
210 {
211 return (__uint128_t)a % (__uint128_t)b;
212 }
213
214 static inline Int128 int128_divs(Int128 a, Int128 b)
215 {
216 return a / b;
217 }
218
219 static inline Int128 int128_rems(Int128 a, Int128 b)
220 {
221 return a % b;
222 }
223
224 #else /* !CONFIG_INT128 */
225
226 typedef struct Int128 Int128;
227 typedef struct Int128 __attribute__((aligned(16))) Int128Aligned;
228
229 /*
230 * We guarantee that the in-memory byte representation of an
231 * Int128 is that of a host-endian-order 128-bit integer
232 * (whether using this struct or the __int128_t version of the type).
233 * Some code using this type relies on this (eg when copying it into
234 * guest memory or a gdb protocol buffer, or by using Int128 in
235 * a union with other integer types).
236 */
237 struct Int128 {
238 #if HOST_BIG_ENDIAN
239 int64_t hi;
240 uint64_t lo;
241 #else
242 uint64_t lo;
243 int64_t hi;
244 #endif
245 };
246
247 static inline Int128 int128_make64(uint64_t a)
248 {
249 return (Int128) { .lo = a, .hi = 0 };
250 }
251
252 static inline Int128 int128_makes64(int64_t a)
253 {
254 return (Int128) { .lo = a, .hi = a >> 63 };
255 }
256
257 static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
258 {
259 return (Int128) { .lo = lo, .hi = hi };
260 }
261
262 static inline uint64_t int128_get64(Int128 a)
263 {
264 assert(!a.hi);
265 return a.lo;
266 }
267
268 static inline uint64_t int128_getlo(Int128 a)
269 {
270 return a.lo;
271 }
272
273 static inline int64_t int128_gethi(Int128 a)
274 {
275 return a.hi;
276 }
277
278 static inline Int128 int128_zero(void)
279 {
280 return int128_make64(0);
281 }
282
283 static inline Int128 int128_one(void)
284 {
285 return int128_make64(1);
286 }
287
288 static inline Int128 int128_2_64(void)
289 {
290 return int128_make128(0, 1);
291 }
292
293 static inline Int128 int128_exts64(int64_t a)
294 {
295 return int128_make128(a, (a < 0) ? -1 : 0);
296 }
297
298 static inline Int128 int128_not(Int128 a)
299 {
300 return int128_make128(~a.lo, ~a.hi);
301 }
302
303 static inline Int128 int128_and(Int128 a, Int128 b)
304 {
305 return int128_make128(a.lo & b.lo, a.hi & b.hi);
306 }
307
308 static inline Int128 int128_or(Int128 a, Int128 b)
309 {
310 return int128_make128(a.lo | b.lo, a.hi | b.hi);
311 }
312
313 static inline Int128 int128_xor(Int128 a, Int128 b)
314 {
315 return int128_make128(a.lo ^ b.lo, a.hi ^ b.hi);
316 }
317
318 static inline Int128 int128_rshift(Int128 a, int n)
319 {
320 int64_t h;
321 if (!n) {
322 return a;
323 }
324 h = a.hi >> (n & 63);
325 if (n >= 64) {
326 return int128_make128(h, h >> 63);
327 } else {
328 return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h);
329 }
330 }
331
332 static inline Int128 int128_urshift(Int128 a, int n)
333 {
334 uint64_t h = a.hi;
335 if (!n) {
336 return a;
337 }
338 h = h >> (n & 63);
339 if (n >= 64) {
340 return int128_make64(h);
341 } else {
342 return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h);
343 }
344 }
345
346 static inline Int128 int128_lshift(Int128 a, int n)
347 {
348 uint64_t l = a.lo << (n & 63);
349 if (n >= 64) {
350 return int128_make128(0, l);
351 } else if (n > 0) {
352 return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n)));
353 }
354 return a;
355 }
356
357 static inline Int128 int128_add(Int128 a, Int128 b)
358 {
359 uint64_t lo = a.lo + b.lo;
360
361 /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence,
362 * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
363 * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
364 *
365 * So the carry is lo < a.lo.
366 */
367 return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo));
368 }
369
370 static inline Int128 int128_neg(Int128 a)
371 {
372 uint64_t lo = -a.lo;
373 return int128_make128(lo, ~(uint64_t)a.hi + !lo);
374 }
375
376 static inline Int128 int128_sub(Int128 a, Int128 b)
377 {
378 return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo));
379 }
380
381 static inline bool int128_nonneg(Int128 a)
382 {
383 return a.hi >= 0;
384 }
385
386 static inline bool int128_eq(Int128 a, Int128 b)
387 {
388 return a.lo == b.lo && a.hi == b.hi;
389 }
390
391 static inline bool int128_ne(Int128 a, Int128 b)
392 {
393 return !int128_eq(a, b);
394 }
395
396 static inline bool int128_ge(Int128 a, Int128 b)
397 {
398 return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
399 }
400
401 static inline bool int128_uge(Int128 a, Int128 b)
402 {
403 return (uint64_t)a.hi > (uint64_t)b.hi || (a.hi == b.hi && a.lo >= b.lo);
404 }
405
406 static inline bool int128_lt(Int128 a, Int128 b)
407 {
408 return !int128_ge(a, b);
409 }
410
411 static inline bool int128_ult(Int128 a, Int128 b)
412 {
413 return !int128_uge(a, b);
414 }
415
416 static inline bool int128_le(Int128 a, Int128 b)
417 {
418 return int128_ge(b, a);
419 }
420
421 static inline bool int128_gt(Int128 a, Int128 b)
422 {
423 return !int128_le(a, b);
424 }
425
426 static inline bool int128_nz(Int128 a)
427 {
428 return a.lo || a.hi;
429 }
430
431 static inline Int128 int128_min(Int128 a, Int128 b)
432 {
433 return int128_le(a, b) ? a : b;
434 }
435
436 static inline Int128 int128_max(Int128 a, Int128 b)
437 {
438 return int128_ge(a, b) ? a : b;
439 }
440
441 static inline void int128_addto(Int128 *a, Int128 b)
442 {
443 *a = int128_add(*a, b);
444 }
445
446 static inline void int128_subfrom(Int128 *a, Int128 b)
447 {
448 *a = int128_sub(*a, b);
449 }
450
451 static inline Int128 bswap128(Int128 a)
452 {
453 return int128_make128(__builtin_bswap64(a.hi), __builtin_bswap64(a.lo));
454 }
455
456 static inline int clz128(Int128 a)
457 {
458 if (a.hi) {
459 return __builtin_clzll(a.hi);
460 } else {
461 return (a.lo) ? __builtin_clzll(a.lo) + 64 : 128;
462 }
463 }
464
465 Int128 int128_divu(Int128, Int128);
466 Int128 int128_remu(Int128, Int128);
467 Int128 int128_divs(Int128, Int128);
468 Int128 int128_rems(Int128, Int128);
469 #endif /* CONFIG_INT128 && !CONFIG_TCG_INTERPRETER */
470
471 static inline void bswap128s(Int128 *s)
472 {
473 *s = bswap128(*s);
474 }
475
476 #define UINT128_MAX int128_make128(~0LL, ~0LL)
477 #define INT128_MAX int128_make128(UINT64_MAX, INT64_MAX)
478 #define INT128_MIN int128_make128(0, INT64_MIN)
479
480 /*
481 * When compiler supports a 128-bit type, define a combination of
482 * a possible structure and the native types. Ease parameter passing
483 * via use of the transparent union extension.
484 */
485 #ifdef CONFIG_INT128_TYPE
486 typedef union {
487 __uint128_t u;
488 __int128_t i;
489 Int128 s;
490 } Int128Alias __attribute__((transparent_union));
491 #else
492 typedef Int128 Int128Alias;
493 #endif /* CONFIG_INT128_TYPE */
494
495 #endif /* INT128_H */