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