xref: /qemu/include/qemu/int128.h (revision 2484cd9c777f6877b178901bcb26663c411fc231)
1b7cd3db6SAvi Kivity #ifndef INT128_H
2b7cd3db6SAvi Kivity #define INT128_H
3b7cd3db6SAvi Kivity 
47ebee43eSRichard Henderson #include "qemu/bswap.h"
50846beb3SRichard Henderson 
6*2484cd9cSMatheus Ferst #ifdef CONFIG_INT128
70846beb3SRichard Henderson typedef __int128_t Int128;
80846beb3SRichard Henderson 
90846beb3SRichard Henderson static inline Int128 int128_make64(uint64_t a)
100846beb3SRichard Henderson {
110846beb3SRichard Henderson     return a;
120846beb3SRichard Henderson }
130846beb3SRichard Henderson 
14703235a3SPeter Maydell static inline Int128 int128_makes64(int64_t a)
15703235a3SPeter Maydell {
16703235a3SPeter Maydell     return a;
17703235a3SPeter Maydell }
18703235a3SPeter Maydell 
191edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
201edaeee0SRichard Henderson {
211edaeee0SRichard Henderson     return (__uint128_t)hi << 64 | lo;
221edaeee0SRichard Henderson }
231edaeee0SRichard Henderson 
240846beb3SRichard Henderson static inline uint64_t int128_get64(Int128 a)
250846beb3SRichard Henderson {
260846beb3SRichard Henderson     uint64_t r = a;
270846beb3SRichard Henderson     assert(r == a);
280846beb3SRichard Henderson     return r;
290846beb3SRichard Henderson }
300846beb3SRichard Henderson 
310846beb3SRichard Henderson static inline uint64_t int128_getlo(Int128 a)
320846beb3SRichard Henderson {
330846beb3SRichard Henderson     return a;
340846beb3SRichard Henderson }
350846beb3SRichard Henderson 
360846beb3SRichard Henderson static inline int64_t int128_gethi(Int128 a)
370846beb3SRichard Henderson {
380846beb3SRichard Henderson     return a >> 64;
390846beb3SRichard Henderson }
400846beb3SRichard Henderson 
410846beb3SRichard Henderson static inline Int128 int128_zero(void)
420846beb3SRichard Henderson {
430846beb3SRichard Henderson     return 0;
440846beb3SRichard Henderson }
450846beb3SRichard Henderson 
460846beb3SRichard Henderson static inline Int128 int128_one(void)
470846beb3SRichard Henderson {
480846beb3SRichard Henderson     return 1;
490846beb3SRichard Henderson }
500846beb3SRichard Henderson 
510846beb3SRichard Henderson static inline Int128 int128_2_64(void)
520846beb3SRichard Henderson {
530846beb3SRichard Henderson     return (Int128)1 << 64;
540846beb3SRichard Henderson }
550846beb3SRichard Henderson 
560846beb3SRichard Henderson static inline Int128 int128_exts64(int64_t a)
570846beb3SRichard Henderson {
580846beb3SRichard Henderson     return a;
590846beb3SRichard Henderson }
600846beb3SRichard Henderson 
610846beb3SRichard Henderson static inline Int128 int128_and(Int128 a, Int128 b)
620846beb3SRichard Henderson {
630846beb3SRichard Henderson     return a & b;
640846beb3SRichard Henderson }
650846beb3SRichard Henderson 
6608895cdaSRichard Henderson static inline Int128 int128_or(Int128 a, Int128 b)
6708895cdaSRichard Henderson {
6808895cdaSRichard Henderson     return a | b;
6908895cdaSRichard Henderson }
7008895cdaSRichard Henderson 
710846beb3SRichard Henderson static inline Int128 int128_rshift(Int128 a, int n)
720846beb3SRichard Henderson {
730846beb3SRichard Henderson     return a >> n;
740846beb3SRichard Henderson }
750846beb3SRichard Henderson 
765be4dd04SRichard Henderson static inline Int128 int128_lshift(Int128 a, int n)
775be4dd04SRichard Henderson {
785be4dd04SRichard Henderson     return a << n;
795be4dd04SRichard Henderson }
805be4dd04SRichard Henderson 
810846beb3SRichard Henderson static inline Int128 int128_add(Int128 a, Int128 b)
820846beb3SRichard Henderson {
830846beb3SRichard Henderson     return a + b;
840846beb3SRichard Henderson }
850846beb3SRichard Henderson 
860846beb3SRichard Henderson static inline Int128 int128_neg(Int128 a)
870846beb3SRichard Henderson {
880846beb3SRichard Henderson     return -a;
890846beb3SRichard Henderson }
900846beb3SRichard Henderson 
910846beb3SRichard Henderson static inline Int128 int128_sub(Int128 a, Int128 b)
920846beb3SRichard Henderson {
930846beb3SRichard Henderson     return a - b;
940846beb3SRichard Henderson }
950846beb3SRichard Henderson 
960846beb3SRichard Henderson static inline bool int128_nonneg(Int128 a)
970846beb3SRichard Henderson {
980846beb3SRichard Henderson     return a >= 0;
990846beb3SRichard Henderson }
1000846beb3SRichard Henderson 
1010846beb3SRichard Henderson static inline bool int128_eq(Int128 a, Int128 b)
1020846beb3SRichard Henderson {
1030846beb3SRichard Henderson     return a == b;
1040846beb3SRichard Henderson }
1050846beb3SRichard Henderson 
1060846beb3SRichard Henderson static inline bool int128_ne(Int128 a, Int128 b)
1070846beb3SRichard Henderson {
1080846beb3SRichard Henderson     return a != b;
1090846beb3SRichard Henderson }
1100846beb3SRichard Henderson 
1110846beb3SRichard Henderson static inline bool int128_ge(Int128 a, Int128 b)
1120846beb3SRichard Henderson {
1130846beb3SRichard Henderson     return a >= b;
1140846beb3SRichard Henderson }
1150846beb3SRichard Henderson 
1160846beb3SRichard Henderson static inline bool int128_lt(Int128 a, Int128 b)
1170846beb3SRichard Henderson {
1180846beb3SRichard Henderson     return a < b;
1190846beb3SRichard Henderson }
1200846beb3SRichard Henderson 
1210846beb3SRichard Henderson static inline bool int128_le(Int128 a, Int128 b)
1220846beb3SRichard Henderson {
1230846beb3SRichard Henderson     return a <= b;
1240846beb3SRichard Henderson }
1250846beb3SRichard Henderson 
1260846beb3SRichard Henderson static inline bool int128_gt(Int128 a, Int128 b)
1270846beb3SRichard Henderson {
1280846beb3SRichard Henderson     return a > b;
1290846beb3SRichard Henderson }
1300846beb3SRichard Henderson 
1310846beb3SRichard Henderson static inline bool int128_nz(Int128 a)
1320846beb3SRichard Henderson {
1330846beb3SRichard Henderson     return a != 0;
1340846beb3SRichard Henderson }
1350846beb3SRichard Henderson 
1360846beb3SRichard Henderson static inline Int128 int128_min(Int128 a, Int128 b)
1370846beb3SRichard Henderson {
1380846beb3SRichard Henderson     return a < b ? a : b;
1390846beb3SRichard Henderson }
1400846beb3SRichard Henderson 
1410846beb3SRichard Henderson static inline Int128 int128_max(Int128 a, Int128 b)
1420846beb3SRichard Henderson {
1430846beb3SRichard Henderson     return a > b ? a : b;
1440846beb3SRichard Henderson }
1450846beb3SRichard Henderson 
1460846beb3SRichard Henderson static inline void int128_addto(Int128 *a, Int128 b)
1470846beb3SRichard Henderson {
1480846beb3SRichard Henderson     *a += b;
1490846beb3SRichard Henderson }
1500846beb3SRichard Henderson 
1510846beb3SRichard Henderson static inline void int128_subfrom(Int128 *a, Int128 b)
1520846beb3SRichard Henderson {
1530846beb3SRichard Henderson     *a -= b;
1540846beb3SRichard Henderson }
1550846beb3SRichard Henderson 
1567ebee43eSRichard Henderson static inline Int128 bswap128(Int128 a)
1577ebee43eSRichard Henderson {
158*2484cd9cSMatheus Ferst #if __has_builtin(__builtin_bswap128)
159*2484cd9cSMatheus Ferst     return __builtin_bswap128(a);
160*2484cd9cSMatheus Ferst #else
1617ebee43eSRichard Henderson     return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a)));
162*2484cd9cSMatheus Ferst #endif
1637ebee43eSRichard Henderson }
1647ebee43eSRichard Henderson 
1650846beb3SRichard Henderson #else /* !CONFIG_INT128 */
1666046c620SPaolo Bonzini 
167b7cd3db6SAvi Kivity typedef struct Int128 Int128;
168b7cd3db6SAvi Kivity 
169181b0c33SMatheus Ferst /*
170181b0c33SMatheus Ferst  * We guarantee that the in-memory byte representation of an
171181b0c33SMatheus Ferst  * Int128 is that of a host-endian-order 128-bit integer
172181b0c33SMatheus Ferst  * (whether using this struct or the __int128_t version of the type).
173181b0c33SMatheus Ferst  * Some code using this type relies on this (eg when copying it into
174181b0c33SMatheus Ferst  * guest memory or a gdb protocol buffer, or by using Int128 in
175181b0c33SMatheus Ferst  * a union with other integer types).
176181b0c33SMatheus Ferst  */
177b7cd3db6SAvi Kivity struct Int128 {
178181b0c33SMatheus Ferst #ifdef HOST_WORDS_BIGENDIAN
179181b0c33SMatheus Ferst     int64_t hi;
180181b0c33SMatheus Ferst     uint64_t lo;
181181b0c33SMatheus Ferst #else
182b7cd3db6SAvi Kivity     uint64_t lo;
183b7cd3db6SAvi Kivity     int64_t hi;
184181b0c33SMatheus Ferst #endif
185b7cd3db6SAvi Kivity };
186b7cd3db6SAvi Kivity 
187b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a)
188b7cd3db6SAvi Kivity {
189181b0c33SMatheus Ferst     return (Int128) { .lo = a, .hi = 0 };
190b7cd3db6SAvi Kivity }
191b7cd3db6SAvi Kivity 
192703235a3SPeter Maydell static inline Int128 int128_makes64(int64_t a)
193703235a3SPeter Maydell {
194181b0c33SMatheus Ferst     return (Int128) { .lo = a, .hi = a >> 63 };
195703235a3SPeter Maydell }
196703235a3SPeter Maydell 
1971edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
1981edaeee0SRichard Henderson {
199181b0c33SMatheus Ferst     return (Int128) { .lo = lo, .hi = hi };
2001edaeee0SRichard Henderson }
2011edaeee0SRichard Henderson 
202b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a)
203b7cd3db6SAvi Kivity {
204b7cd3db6SAvi Kivity     assert(!a.hi);
205b7cd3db6SAvi Kivity     return a.lo;
206b7cd3db6SAvi Kivity }
207b7cd3db6SAvi Kivity 
208258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a)
209258dfaaaSRichard Henderson {
210258dfaaaSRichard Henderson     return a.lo;
211258dfaaaSRichard Henderson }
212258dfaaaSRichard Henderson 
213258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a)
214258dfaaaSRichard Henderson {
215258dfaaaSRichard Henderson     return a.hi;
216258dfaaaSRichard Henderson }
217258dfaaaSRichard Henderson 
218b7cd3db6SAvi Kivity static inline Int128 int128_zero(void)
219b7cd3db6SAvi Kivity {
220b7cd3db6SAvi Kivity     return int128_make64(0);
221b7cd3db6SAvi Kivity }
222b7cd3db6SAvi Kivity 
223b7cd3db6SAvi Kivity static inline Int128 int128_one(void)
224b7cd3db6SAvi Kivity {
225b7cd3db6SAvi Kivity     return int128_make64(1);
226b7cd3db6SAvi Kivity }
227b7cd3db6SAvi Kivity 
228b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void)
229b7cd3db6SAvi Kivity {
230181b0c33SMatheus Ferst     return int128_make128(0, 1);
231b7cd3db6SAvi Kivity }
232b7cd3db6SAvi Kivity 
23312e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a)
23412e1129bSAlexey Kardashevskiy {
235181b0c33SMatheus Ferst     return int128_make128(a, (a < 0) ? -1 : 0);
23612e1129bSAlexey Kardashevskiy }
23712e1129bSAlexey Kardashevskiy 
238052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b)
239052e87b0SPaolo Bonzini {
240181b0c33SMatheus Ferst     return int128_make128(a.lo & b.lo, a.hi & b.hi);
241052e87b0SPaolo Bonzini }
242052e87b0SPaolo Bonzini 
24308895cdaSRichard Henderson static inline Int128 int128_or(Int128 a, Int128 b)
24408895cdaSRichard Henderson {
245181b0c33SMatheus Ferst     return int128_make128(a.lo | b.lo, a.hi | b.hi);
24608895cdaSRichard Henderson }
24708895cdaSRichard Henderson 
248052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n)
249052e87b0SPaolo Bonzini {
250052e87b0SPaolo Bonzini     int64_t h;
251052e87b0SPaolo Bonzini     if (!n) {
252052e87b0SPaolo Bonzini         return a;
253052e87b0SPaolo Bonzini     }
254052e87b0SPaolo Bonzini     h = a.hi >> (n & 63);
255052e87b0SPaolo Bonzini     if (n >= 64) {
2561edaeee0SRichard Henderson         return int128_make128(h, h >> 63);
257052e87b0SPaolo Bonzini     } else {
2581edaeee0SRichard Henderson         return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h);
259052e87b0SPaolo Bonzini     }
260052e87b0SPaolo Bonzini }
261052e87b0SPaolo Bonzini 
2625be4dd04SRichard Henderson static inline Int128 int128_lshift(Int128 a, int n)
2635be4dd04SRichard Henderson {
2645be4dd04SRichard Henderson     uint64_t l = a.lo << (n & 63);
2655be4dd04SRichard Henderson     if (n >= 64) {
2665be4dd04SRichard Henderson         return int128_make128(0, l);
2675be4dd04SRichard Henderson     } else if (n > 0) {
2685be4dd04SRichard Henderson         return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n)));
2695be4dd04SRichard Henderson     }
2705be4dd04SRichard Henderson     return a;
2715be4dd04SRichard Henderson }
2725be4dd04SRichard Henderson 
273b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b)
274b7cd3db6SAvi Kivity {
2756046c620SPaolo Bonzini     uint64_t lo = a.lo + b.lo;
2766046c620SPaolo Bonzini 
2776046c620SPaolo Bonzini     /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64).  Hence,
2786046c620SPaolo Bonzini      * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
2796046c620SPaolo Bonzini      * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
2806046c620SPaolo Bonzini      *
2816046c620SPaolo Bonzini      * So the carry is lo < a.lo.
2826046c620SPaolo Bonzini      */
2831edaeee0SRichard Henderson     return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo));
284b7cd3db6SAvi Kivity }
285b7cd3db6SAvi Kivity 
286b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a)
287b7cd3db6SAvi Kivity {
2886046c620SPaolo Bonzini     uint64_t lo = -a.lo;
2891edaeee0SRichard Henderson     return int128_make128(lo, ~(uint64_t)a.hi + !lo);
290b7cd3db6SAvi Kivity }
291b7cd3db6SAvi Kivity 
292b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b)
293b7cd3db6SAvi Kivity {
2941edaeee0SRichard Henderson     return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo));
295b7cd3db6SAvi Kivity }
296b7cd3db6SAvi Kivity 
297b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a)
298b7cd3db6SAvi Kivity {
299b7cd3db6SAvi Kivity     return a.hi >= 0;
300b7cd3db6SAvi Kivity }
301b7cd3db6SAvi Kivity 
302b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b)
303b7cd3db6SAvi Kivity {
304b7cd3db6SAvi Kivity     return a.lo == b.lo && a.hi == b.hi;
305b7cd3db6SAvi Kivity }
306b7cd3db6SAvi Kivity 
307b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b)
308b7cd3db6SAvi Kivity {
309b7cd3db6SAvi Kivity     return !int128_eq(a, b);
310b7cd3db6SAvi Kivity }
311b7cd3db6SAvi Kivity 
312b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b)
313b7cd3db6SAvi Kivity {
3146046c620SPaolo Bonzini     return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
315b7cd3db6SAvi Kivity }
316b7cd3db6SAvi Kivity 
317b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b)
318b7cd3db6SAvi Kivity {
319b7cd3db6SAvi Kivity     return !int128_ge(a, b);
320b7cd3db6SAvi Kivity }
321b7cd3db6SAvi Kivity 
322b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b)
323b7cd3db6SAvi Kivity {
324b7cd3db6SAvi Kivity     return int128_ge(b, a);
325b7cd3db6SAvi Kivity }
326b7cd3db6SAvi Kivity 
327b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b)
328b7cd3db6SAvi Kivity {
329b7cd3db6SAvi Kivity     return !int128_le(a, b);
330b7cd3db6SAvi Kivity }
331b7cd3db6SAvi Kivity 
332b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a)
333b7cd3db6SAvi Kivity {
334b7cd3db6SAvi Kivity     return a.lo || a.hi;
335b7cd3db6SAvi Kivity }
336b7cd3db6SAvi Kivity 
337b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b)
338b7cd3db6SAvi Kivity {
339b7cd3db6SAvi Kivity     return int128_le(a, b) ? a : b;
340b7cd3db6SAvi Kivity }
341b7cd3db6SAvi Kivity 
342b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b)
343b7cd3db6SAvi Kivity {
344b7cd3db6SAvi Kivity     return int128_ge(a, b) ? a : b;
345b7cd3db6SAvi Kivity }
346b7cd3db6SAvi Kivity 
347b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b)
348b7cd3db6SAvi Kivity {
349b7cd3db6SAvi Kivity     *a = int128_add(*a, b);
350b7cd3db6SAvi Kivity }
351b7cd3db6SAvi Kivity 
352b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b)
353b7cd3db6SAvi Kivity {
354b7cd3db6SAvi Kivity     *a = int128_sub(*a, b);
355b7cd3db6SAvi Kivity }
356b7cd3db6SAvi Kivity 
357*2484cd9cSMatheus Ferst static inline Int128 bswap128(Int128 a)
358*2484cd9cSMatheus Ferst {
359*2484cd9cSMatheus Ferst     return int128_make128(bswap64(a.hi), bswap64(a.lo));
360*2484cd9cSMatheus Ferst }
361*2484cd9cSMatheus Ferst 
3620846beb3SRichard Henderson #endif /* CONFIG_INT128 */
363*2484cd9cSMatheus Ferst 
364*2484cd9cSMatheus Ferst static inline void bswap128s(Int128 *s)
365*2484cd9cSMatheus Ferst {
366*2484cd9cSMatheus Ferst     *s = bswap128(*s);
367*2484cd9cSMatheus Ferst }
368*2484cd9cSMatheus Ferst 
3690846beb3SRichard Henderson #endif /* INT128_H */
370