xref: /qemu/include/qemu/int128.h (revision 7ebee43ee3e2fcd7b5063058b7ef74bc43216733)
1b7cd3db6SAvi Kivity #ifndef INT128_H
2b7cd3db6SAvi Kivity #define INT128_H
3b7cd3db6SAvi Kivity 
40846beb3SRichard Henderson #ifdef CONFIG_INT128
5*7ebee43eSRichard Henderson #include "qemu/bswap.h"
60846beb3SRichard Henderson 
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 
141edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
151edaeee0SRichard Henderson {
161edaeee0SRichard Henderson     return (__uint128_t)hi << 64 | lo;
171edaeee0SRichard Henderson }
181edaeee0SRichard Henderson 
190846beb3SRichard Henderson static inline uint64_t int128_get64(Int128 a)
200846beb3SRichard Henderson {
210846beb3SRichard Henderson     uint64_t r = a;
220846beb3SRichard Henderson     assert(r == a);
230846beb3SRichard Henderson     return r;
240846beb3SRichard Henderson }
250846beb3SRichard Henderson 
260846beb3SRichard Henderson static inline uint64_t int128_getlo(Int128 a)
270846beb3SRichard Henderson {
280846beb3SRichard Henderson     return a;
290846beb3SRichard Henderson }
300846beb3SRichard Henderson 
310846beb3SRichard Henderson static inline int64_t int128_gethi(Int128 a)
320846beb3SRichard Henderson {
330846beb3SRichard Henderson     return a >> 64;
340846beb3SRichard Henderson }
350846beb3SRichard Henderson 
360846beb3SRichard Henderson static inline Int128 int128_zero(void)
370846beb3SRichard Henderson {
380846beb3SRichard Henderson     return 0;
390846beb3SRichard Henderson }
400846beb3SRichard Henderson 
410846beb3SRichard Henderson static inline Int128 int128_one(void)
420846beb3SRichard Henderson {
430846beb3SRichard Henderson     return 1;
440846beb3SRichard Henderson }
450846beb3SRichard Henderson 
460846beb3SRichard Henderson static inline Int128 int128_2_64(void)
470846beb3SRichard Henderson {
480846beb3SRichard Henderson     return (Int128)1 << 64;
490846beb3SRichard Henderson }
500846beb3SRichard Henderson 
510846beb3SRichard Henderson static inline Int128 int128_exts64(int64_t a)
520846beb3SRichard Henderson {
530846beb3SRichard Henderson     return a;
540846beb3SRichard Henderson }
550846beb3SRichard Henderson 
560846beb3SRichard Henderson static inline Int128 int128_and(Int128 a, Int128 b)
570846beb3SRichard Henderson {
580846beb3SRichard Henderson     return a & b;
590846beb3SRichard Henderson }
600846beb3SRichard Henderson 
610846beb3SRichard Henderson static inline Int128 int128_rshift(Int128 a, int n)
620846beb3SRichard Henderson {
630846beb3SRichard Henderson     return a >> n;
640846beb3SRichard Henderson }
650846beb3SRichard Henderson 
660846beb3SRichard Henderson static inline Int128 int128_add(Int128 a, Int128 b)
670846beb3SRichard Henderson {
680846beb3SRichard Henderson     return a + b;
690846beb3SRichard Henderson }
700846beb3SRichard Henderson 
710846beb3SRichard Henderson static inline Int128 int128_neg(Int128 a)
720846beb3SRichard Henderson {
730846beb3SRichard Henderson     return -a;
740846beb3SRichard Henderson }
750846beb3SRichard Henderson 
760846beb3SRichard Henderson static inline Int128 int128_sub(Int128 a, Int128 b)
770846beb3SRichard Henderson {
780846beb3SRichard Henderson     return a - b;
790846beb3SRichard Henderson }
800846beb3SRichard Henderson 
810846beb3SRichard Henderson static inline bool int128_nonneg(Int128 a)
820846beb3SRichard Henderson {
830846beb3SRichard Henderson     return a >= 0;
840846beb3SRichard Henderson }
850846beb3SRichard Henderson 
860846beb3SRichard Henderson static inline bool int128_eq(Int128 a, Int128 b)
870846beb3SRichard Henderson {
880846beb3SRichard Henderson     return a == b;
890846beb3SRichard Henderson }
900846beb3SRichard Henderson 
910846beb3SRichard Henderson static inline bool int128_ne(Int128 a, Int128 b)
920846beb3SRichard Henderson {
930846beb3SRichard Henderson     return a != b;
940846beb3SRichard Henderson }
950846beb3SRichard Henderson 
960846beb3SRichard Henderson static inline bool int128_ge(Int128 a, Int128 b)
970846beb3SRichard Henderson {
980846beb3SRichard Henderson     return a >= b;
990846beb3SRichard Henderson }
1000846beb3SRichard Henderson 
1010846beb3SRichard Henderson static inline bool int128_lt(Int128 a, Int128 b)
1020846beb3SRichard Henderson {
1030846beb3SRichard Henderson     return a < b;
1040846beb3SRichard Henderson }
1050846beb3SRichard Henderson 
1060846beb3SRichard Henderson static inline bool int128_le(Int128 a, Int128 b)
1070846beb3SRichard Henderson {
1080846beb3SRichard Henderson     return a <= b;
1090846beb3SRichard Henderson }
1100846beb3SRichard Henderson 
1110846beb3SRichard Henderson static inline bool int128_gt(Int128 a, Int128 b)
1120846beb3SRichard Henderson {
1130846beb3SRichard Henderson     return a > b;
1140846beb3SRichard Henderson }
1150846beb3SRichard Henderson 
1160846beb3SRichard Henderson static inline bool int128_nz(Int128 a)
1170846beb3SRichard Henderson {
1180846beb3SRichard Henderson     return a != 0;
1190846beb3SRichard Henderson }
1200846beb3SRichard Henderson 
1210846beb3SRichard Henderson static inline Int128 int128_min(Int128 a, Int128 b)
1220846beb3SRichard Henderson {
1230846beb3SRichard Henderson     return a < b ? a : b;
1240846beb3SRichard Henderson }
1250846beb3SRichard Henderson 
1260846beb3SRichard Henderson static inline Int128 int128_max(Int128 a, Int128 b)
1270846beb3SRichard Henderson {
1280846beb3SRichard Henderson     return a > b ? a : b;
1290846beb3SRichard Henderson }
1300846beb3SRichard Henderson 
1310846beb3SRichard Henderson static inline void int128_addto(Int128 *a, Int128 b)
1320846beb3SRichard Henderson {
1330846beb3SRichard Henderson     *a += b;
1340846beb3SRichard Henderson }
1350846beb3SRichard Henderson 
1360846beb3SRichard Henderson static inline void int128_subfrom(Int128 *a, Int128 b)
1370846beb3SRichard Henderson {
1380846beb3SRichard Henderson     *a -= b;
1390846beb3SRichard Henderson }
1400846beb3SRichard Henderson 
141*7ebee43eSRichard Henderson static inline Int128 bswap128(Int128 a)
142*7ebee43eSRichard Henderson {
143*7ebee43eSRichard Henderson     return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a)));
144*7ebee43eSRichard Henderson }
145*7ebee43eSRichard Henderson 
1460846beb3SRichard Henderson #else /* !CONFIG_INT128 */
1476046c620SPaolo Bonzini 
148b7cd3db6SAvi Kivity typedef struct Int128 Int128;
149b7cd3db6SAvi Kivity 
150b7cd3db6SAvi Kivity struct Int128 {
151b7cd3db6SAvi Kivity     uint64_t lo;
152b7cd3db6SAvi Kivity     int64_t hi;
153b7cd3db6SAvi Kivity };
154b7cd3db6SAvi Kivity 
155b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a)
156b7cd3db6SAvi Kivity {
157b7cd3db6SAvi Kivity     return (Int128) { a, 0 };
158b7cd3db6SAvi Kivity }
159b7cd3db6SAvi Kivity 
1601edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
1611edaeee0SRichard Henderson {
1621edaeee0SRichard Henderson     return (Int128) { lo, hi };
1631edaeee0SRichard Henderson }
1641edaeee0SRichard Henderson 
165b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a)
166b7cd3db6SAvi Kivity {
167b7cd3db6SAvi Kivity     assert(!a.hi);
168b7cd3db6SAvi Kivity     return a.lo;
169b7cd3db6SAvi Kivity }
170b7cd3db6SAvi Kivity 
171258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a)
172258dfaaaSRichard Henderson {
173258dfaaaSRichard Henderson     return a.lo;
174258dfaaaSRichard Henderson }
175258dfaaaSRichard Henderson 
176258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a)
177258dfaaaSRichard Henderson {
178258dfaaaSRichard Henderson     return a.hi;
179258dfaaaSRichard Henderson }
180258dfaaaSRichard Henderson 
181b7cd3db6SAvi Kivity static inline Int128 int128_zero(void)
182b7cd3db6SAvi Kivity {
183b7cd3db6SAvi Kivity     return int128_make64(0);
184b7cd3db6SAvi Kivity }
185b7cd3db6SAvi Kivity 
186b7cd3db6SAvi Kivity static inline Int128 int128_one(void)
187b7cd3db6SAvi Kivity {
188b7cd3db6SAvi Kivity     return int128_make64(1);
189b7cd3db6SAvi Kivity }
190b7cd3db6SAvi Kivity 
191b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void)
192b7cd3db6SAvi Kivity {
193b7cd3db6SAvi Kivity     return (Int128) { 0, 1 };
194b7cd3db6SAvi Kivity }
195b7cd3db6SAvi Kivity 
19612e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a)
19712e1129bSAlexey Kardashevskiy {
19812e1129bSAlexey Kardashevskiy     return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 };
19912e1129bSAlexey Kardashevskiy }
20012e1129bSAlexey Kardashevskiy 
201052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b)
202052e87b0SPaolo Bonzini {
203052e87b0SPaolo Bonzini     return (Int128) { a.lo & b.lo, a.hi & b.hi };
204052e87b0SPaolo Bonzini }
205052e87b0SPaolo Bonzini 
206052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n)
207052e87b0SPaolo Bonzini {
208052e87b0SPaolo Bonzini     int64_t h;
209052e87b0SPaolo Bonzini     if (!n) {
210052e87b0SPaolo Bonzini         return a;
211052e87b0SPaolo Bonzini     }
212052e87b0SPaolo Bonzini     h = a.hi >> (n & 63);
213052e87b0SPaolo Bonzini     if (n >= 64) {
2141edaeee0SRichard Henderson         return int128_make128(h, h >> 63);
215052e87b0SPaolo Bonzini     } else {
2161edaeee0SRichard Henderson         return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h);
217052e87b0SPaolo Bonzini     }
218052e87b0SPaolo Bonzini }
219052e87b0SPaolo Bonzini 
220b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b)
221b7cd3db6SAvi Kivity {
2226046c620SPaolo Bonzini     uint64_t lo = a.lo + b.lo;
2236046c620SPaolo Bonzini 
2246046c620SPaolo Bonzini     /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64).  Hence,
2256046c620SPaolo Bonzini      * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
2266046c620SPaolo Bonzini      * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
2276046c620SPaolo Bonzini      *
2286046c620SPaolo Bonzini      * So the carry is lo < a.lo.
2296046c620SPaolo Bonzini      */
2301edaeee0SRichard Henderson     return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo));
231b7cd3db6SAvi Kivity }
232b7cd3db6SAvi Kivity 
233b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a)
234b7cd3db6SAvi Kivity {
2356046c620SPaolo Bonzini     uint64_t lo = -a.lo;
2361edaeee0SRichard Henderson     return int128_make128(lo, ~(uint64_t)a.hi + !lo);
237b7cd3db6SAvi Kivity }
238b7cd3db6SAvi Kivity 
239b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b)
240b7cd3db6SAvi Kivity {
2411edaeee0SRichard Henderson     return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo));
242b7cd3db6SAvi Kivity }
243b7cd3db6SAvi Kivity 
244b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a)
245b7cd3db6SAvi Kivity {
246b7cd3db6SAvi Kivity     return a.hi >= 0;
247b7cd3db6SAvi Kivity }
248b7cd3db6SAvi Kivity 
249b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b)
250b7cd3db6SAvi Kivity {
251b7cd3db6SAvi Kivity     return a.lo == b.lo && a.hi == b.hi;
252b7cd3db6SAvi Kivity }
253b7cd3db6SAvi Kivity 
254b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b)
255b7cd3db6SAvi Kivity {
256b7cd3db6SAvi Kivity     return !int128_eq(a, b);
257b7cd3db6SAvi Kivity }
258b7cd3db6SAvi Kivity 
259b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b)
260b7cd3db6SAvi Kivity {
2616046c620SPaolo Bonzini     return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
262b7cd3db6SAvi Kivity }
263b7cd3db6SAvi Kivity 
264b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b)
265b7cd3db6SAvi Kivity {
266b7cd3db6SAvi Kivity     return !int128_ge(a, b);
267b7cd3db6SAvi Kivity }
268b7cd3db6SAvi Kivity 
269b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b)
270b7cd3db6SAvi Kivity {
271b7cd3db6SAvi Kivity     return int128_ge(b, a);
272b7cd3db6SAvi Kivity }
273b7cd3db6SAvi Kivity 
274b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b)
275b7cd3db6SAvi Kivity {
276b7cd3db6SAvi Kivity     return !int128_le(a, b);
277b7cd3db6SAvi Kivity }
278b7cd3db6SAvi Kivity 
279b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a)
280b7cd3db6SAvi Kivity {
281b7cd3db6SAvi Kivity     return a.lo || a.hi;
282b7cd3db6SAvi Kivity }
283b7cd3db6SAvi Kivity 
284b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b)
285b7cd3db6SAvi Kivity {
286b7cd3db6SAvi Kivity     return int128_le(a, b) ? a : b;
287b7cd3db6SAvi Kivity }
288b7cd3db6SAvi Kivity 
289b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b)
290b7cd3db6SAvi Kivity {
291b7cd3db6SAvi Kivity     return int128_ge(a, b) ? a : b;
292b7cd3db6SAvi Kivity }
293b7cd3db6SAvi Kivity 
294b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b)
295b7cd3db6SAvi Kivity {
296b7cd3db6SAvi Kivity     *a = int128_add(*a, b);
297b7cd3db6SAvi Kivity }
298b7cd3db6SAvi Kivity 
299b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b)
300b7cd3db6SAvi Kivity {
301b7cd3db6SAvi Kivity     *a = int128_sub(*a, b);
302b7cd3db6SAvi Kivity }
303b7cd3db6SAvi Kivity 
3040846beb3SRichard Henderson #endif /* CONFIG_INT128 */
3050846beb3SRichard Henderson #endif /* INT128_H */
306