xref: /qemu/include/qemu/int128.h (revision 1edaeee0955fba7d834b7c8f4e372e7eae030745)
1b7cd3db6SAvi Kivity #ifndef INT128_H
2b7cd3db6SAvi Kivity #define INT128_H
3b7cd3db6SAvi Kivity 
40846beb3SRichard Henderson #ifdef CONFIG_INT128
50846beb3SRichard Henderson 
60846beb3SRichard Henderson typedef __int128_t Int128;
70846beb3SRichard Henderson 
80846beb3SRichard Henderson static inline Int128 int128_make64(uint64_t a)
90846beb3SRichard Henderson {
100846beb3SRichard Henderson     return a;
110846beb3SRichard Henderson }
120846beb3SRichard Henderson 
13*1edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
14*1edaeee0SRichard Henderson {
15*1edaeee0SRichard Henderson     return (__uint128_t)hi << 64 | lo;
16*1edaeee0SRichard Henderson }
17*1edaeee0SRichard Henderson 
180846beb3SRichard Henderson static inline uint64_t int128_get64(Int128 a)
190846beb3SRichard Henderson {
200846beb3SRichard Henderson     uint64_t r = a;
210846beb3SRichard Henderson     assert(r == a);
220846beb3SRichard Henderson     return r;
230846beb3SRichard Henderson }
240846beb3SRichard Henderson 
250846beb3SRichard Henderson static inline uint64_t int128_getlo(Int128 a)
260846beb3SRichard Henderson {
270846beb3SRichard Henderson     return a;
280846beb3SRichard Henderson }
290846beb3SRichard Henderson 
300846beb3SRichard Henderson static inline int64_t int128_gethi(Int128 a)
310846beb3SRichard Henderson {
320846beb3SRichard Henderson     return a >> 64;
330846beb3SRichard Henderson }
340846beb3SRichard Henderson 
350846beb3SRichard Henderson static inline Int128 int128_zero(void)
360846beb3SRichard Henderson {
370846beb3SRichard Henderson     return 0;
380846beb3SRichard Henderson }
390846beb3SRichard Henderson 
400846beb3SRichard Henderson static inline Int128 int128_one(void)
410846beb3SRichard Henderson {
420846beb3SRichard Henderson     return 1;
430846beb3SRichard Henderson }
440846beb3SRichard Henderson 
450846beb3SRichard Henderson static inline Int128 int128_2_64(void)
460846beb3SRichard Henderson {
470846beb3SRichard Henderson     return (Int128)1 << 64;
480846beb3SRichard Henderson }
490846beb3SRichard Henderson 
500846beb3SRichard Henderson static inline Int128 int128_exts64(int64_t a)
510846beb3SRichard Henderson {
520846beb3SRichard Henderson     return a;
530846beb3SRichard Henderson }
540846beb3SRichard Henderson 
550846beb3SRichard Henderson static inline Int128 int128_and(Int128 a, Int128 b)
560846beb3SRichard Henderson {
570846beb3SRichard Henderson     return a & b;
580846beb3SRichard Henderson }
590846beb3SRichard Henderson 
600846beb3SRichard Henderson static inline Int128 int128_rshift(Int128 a, int n)
610846beb3SRichard Henderson {
620846beb3SRichard Henderson     return a >> n;
630846beb3SRichard Henderson }
640846beb3SRichard Henderson 
650846beb3SRichard Henderson static inline Int128 int128_add(Int128 a, Int128 b)
660846beb3SRichard Henderson {
670846beb3SRichard Henderson     return a + b;
680846beb3SRichard Henderson }
690846beb3SRichard Henderson 
700846beb3SRichard Henderson static inline Int128 int128_neg(Int128 a)
710846beb3SRichard Henderson {
720846beb3SRichard Henderson     return -a;
730846beb3SRichard Henderson }
740846beb3SRichard Henderson 
750846beb3SRichard Henderson static inline Int128 int128_sub(Int128 a, Int128 b)
760846beb3SRichard Henderson {
770846beb3SRichard Henderson     return a - b;
780846beb3SRichard Henderson }
790846beb3SRichard Henderson 
800846beb3SRichard Henderson static inline bool int128_nonneg(Int128 a)
810846beb3SRichard Henderson {
820846beb3SRichard Henderson     return a >= 0;
830846beb3SRichard Henderson }
840846beb3SRichard Henderson 
850846beb3SRichard Henderson static inline bool int128_eq(Int128 a, Int128 b)
860846beb3SRichard Henderson {
870846beb3SRichard Henderson     return a == b;
880846beb3SRichard Henderson }
890846beb3SRichard Henderson 
900846beb3SRichard Henderson static inline bool int128_ne(Int128 a, Int128 b)
910846beb3SRichard Henderson {
920846beb3SRichard Henderson     return a != b;
930846beb3SRichard Henderson }
940846beb3SRichard Henderson 
950846beb3SRichard Henderson static inline bool int128_ge(Int128 a, Int128 b)
960846beb3SRichard Henderson {
970846beb3SRichard Henderson     return a >= b;
980846beb3SRichard Henderson }
990846beb3SRichard Henderson 
1000846beb3SRichard Henderson static inline bool int128_lt(Int128 a, Int128 b)
1010846beb3SRichard Henderson {
1020846beb3SRichard Henderson     return a < b;
1030846beb3SRichard Henderson }
1040846beb3SRichard Henderson 
1050846beb3SRichard Henderson static inline bool int128_le(Int128 a, Int128 b)
1060846beb3SRichard Henderson {
1070846beb3SRichard Henderson     return a <= b;
1080846beb3SRichard Henderson }
1090846beb3SRichard Henderson 
1100846beb3SRichard Henderson static inline bool int128_gt(Int128 a, Int128 b)
1110846beb3SRichard Henderson {
1120846beb3SRichard Henderson     return a > b;
1130846beb3SRichard Henderson }
1140846beb3SRichard Henderson 
1150846beb3SRichard Henderson static inline bool int128_nz(Int128 a)
1160846beb3SRichard Henderson {
1170846beb3SRichard Henderson     return a != 0;
1180846beb3SRichard Henderson }
1190846beb3SRichard Henderson 
1200846beb3SRichard Henderson static inline Int128 int128_min(Int128 a, Int128 b)
1210846beb3SRichard Henderson {
1220846beb3SRichard Henderson     return a < b ? a : b;
1230846beb3SRichard Henderson }
1240846beb3SRichard Henderson 
1250846beb3SRichard Henderson static inline Int128 int128_max(Int128 a, Int128 b)
1260846beb3SRichard Henderson {
1270846beb3SRichard Henderson     return a > b ? a : b;
1280846beb3SRichard Henderson }
1290846beb3SRichard Henderson 
1300846beb3SRichard Henderson static inline void int128_addto(Int128 *a, Int128 b)
1310846beb3SRichard Henderson {
1320846beb3SRichard Henderson     *a += b;
1330846beb3SRichard Henderson }
1340846beb3SRichard Henderson 
1350846beb3SRichard Henderson static inline void int128_subfrom(Int128 *a, Int128 b)
1360846beb3SRichard Henderson {
1370846beb3SRichard Henderson     *a -= b;
1380846beb3SRichard Henderson }
1390846beb3SRichard Henderson 
1400846beb3SRichard Henderson #else /* !CONFIG_INT128 */
1416046c620SPaolo Bonzini 
142b7cd3db6SAvi Kivity typedef struct Int128 Int128;
143b7cd3db6SAvi Kivity 
144b7cd3db6SAvi Kivity struct Int128 {
145b7cd3db6SAvi Kivity     uint64_t lo;
146b7cd3db6SAvi Kivity     int64_t hi;
147b7cd3db6SAvi Kivity };
148b7cd3db6SAvi Kivity 
149b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a)
150b7cd3db6SAvi Kivity {
151b7cd3db6SAvi Kivity     return (Int128) { a, 0 };
152b7cd3db6SAvi Kivity }
153b7cd3db6SAvi Kivity 
154*1edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
155*1edaeee0SRichard Henderson {
156*1edaeee0SRichard Henderson     return (Int128) { lo, hi };
157*1edaeee0SRichard Henderson }
158*1edaeee0SRichard Henderson 
159b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a)
160b7cd3db6SAvi Kivity {
161b7cd3db6SAvi Kivity     assert(!a.hi);
162b7cd3db6SAvi Kivity     return a.lo;
163b7cd3db6SAvi Kivity }
164b7cd3db6SAvi Kivity 
165258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a)
166258dfaaaSRichard Henderson {
167258dfaaaSRichard Henderson     return a.lo;
168258dfaaaSRichard Henderson }
169258dfaaaSRichard Henderson 
170258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a)
171258dfaaaSRichard Henderson {
172258dfaaaSRichard Henderson     return a.hi;
173258dfaaaSRichard Henderson }
174258dfaaaSRichard Henderson 
175b7cd3db6SAvi Kivity static inline Int128 int128_zero(void)
176b7cd3db6SAvi Kivity {
177b7cd3db6SAvi Kivity     return int128_make64(0);
178b7cd3db6SAvi Kivity }
179b7cd3db6SAvi Kivity 
180b7cd3db6SAvi Kivity static inline Int128 int128_one(void)
181b7cd3db6SAvi Kivity {
182b7cd3db6SAvi Kivity     return int128_make64(1);
183b7cd3db6SAvi Kivity }
184b7cd3db6SAvi Kivity 
185b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void)
186b7cd3db6SAvi Kivity {
187b7cd3db6SAvi Kivity     return (Int128) { 0, 1 };
188b7cd3db6SAvi Kivity }
189b7cd3db6SAvi Kivity 
19012e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a)
19112e1129bSAlexey Kardashevskiy {
19212e1129bSAlexey Kardashevskiy     return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 };
19312e1129bSAlexey Kardashevskiy }
19412e1129bSAlexey Kardashevskiy 
195052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b)
196052e87b0SPaolo Bonzini {
197052e87b0SPaolo Bonzini     return (Int128) { a.lo & b.lo, a.hi & b.hi };
198052e87b0SPaolo Bonzini }
199052e87b0SPaolo Bonzini 
200052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n)
201052e87b0SPaolo Bonzini {
202052e87b0SPaolo Bonzini     int64_t h;
203052e87b0SPaolo Bonzini     if (!n) {
204052e87b0SPaolo Bonzini         return a;
205052e87b0SPaolo Bonzini     }
206052e87b0SPaolo Bonzini     h = a.hi >> (n & 63);
207052e87b0SPaolo Bonzini     if (n >= 64) {
208*1edaeee0SRichard Henderson         return int128_make128(h, h >> 63);
209052e87b0SPaolo Bonzini     } else {
210*1edaeee0SRichard Henderson         return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h);
211052e87b0SPaolo Bonzini     }
212052e87b0SPaolo Bonzini }
213052e87b0SPaolo Bonzini 
214b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b)
215b7cd3db6SAvi Kivity {
2166046c620SPaolo Bonzini     uint64_t lo = a.lo + b.lo;
2176046c620SPaolo Bonzini 
2186046c620SPaolo Bonzini     /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64).  Hence,
2196046c620SPaolo Bonzini      * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
2206046c620SPaolo Bonzini      * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
2216046c620SPaolo Bonzini      *
2226046c620SPaolo Bonzini      * So the carry is lo < a.lo.
2236046c620SPaolo Bonzini      */
224*1edaeee0SRichard Henderson     return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo));
225b7cd3db6SAvi Kivity }
226b7cd3db6SAvi Kivity 
227b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a)
228b7cd3db6SAvi Kivity {
2296046c620SPaolo Bonzini     uint64_t lo = -a.lo;
230*1edaeee0SRichard Henderson     return int128_make128(lo, ~(uint64_t)a.hi + !lo);
231b7cd3db6SAvi Kivity }
232b7cd3db6SAvi Kivity 
233b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b)
234b7cd3db6SAvi Kivity {
235*1edaeee0SRichard Henderson     return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo));
236b7cd3db6SAvi Kivity }
237b7cd3db6SAvi Kivity 
238b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a)
239b7cd3db6SAvi Kivity {
240b7cd3db6SAvi Kivity     return a.hi >= 0;
241b7cd3db6SAvi Kivity }
242b7cd3db6SAvi Kivity 
243b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b)
244b7cd3db6SAvi Kivity {
245b7cd3db6SAvi Kivity     return a.lo == b.lo && a.hi == b.hi;
246b7cd3db6SAvi Kivity }
247b7cd3db6SAvi Kivity 
248b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b)
249b7cd3db6SAvi Kivity {
250b7cd3db6SAvi Kivity     return !int128_eq(a, b);
251b7cd3db6SAvi Kivity }
252b7cd3db6SAvi Kivity 
253b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b)
254b7cd3db6SAvi Kivity {
2556046c620SPaolo Bonzini     return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
256b7cd3db6SAvi Kivity }
257b7cd3db6SAvi Kivity 
258b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b)
259b7cd3db6SAvi Kivity {
260b7cd3db6SAvi Kivity     return !int128_ge(a, b);
261b7cd3db6SAvi Kivity }
262b7cd3db6SAvi Kivity 
263b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b)
264b7cd3db6SAvi Kivity {
265b7cd3db6SAvi Kivity     return int128_ge(b, a);
266b7cd3db6SAvi Kivity }
267b7cd3db6SAvi Kivity 
268b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b)
269b7cd3db6SAvi Kivity {
270b7cd3db6SAvi Kivity     return !int128_le(a, b);
271b7cd3db6SAvi Kivity }
272b7cd3db6SAvi Kivity 
273b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a)
274b7cd3db6SAvi Kivity {
275b7cd3db6SAvi Kivity     return a.lo || a.hi;
276b7cd3db6SAvi Kivity }
277b7cd3db6SAvi Kivity 
278b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b)
279b7cd3db6SAvi Kivity {
280b7cd3db6SAvi Kivity     return int128_le(a, b) ? a : b;
281b7cd3db6SAvi Kivity }
282b7cd3db6SAvi Kivity 
283b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b)
284b7cd3db6SAvi Kivity {
285b7cd3db6SAvi Kivity     return int128_ge(a, b) ? a : b;
286b7cd3db6SAvi Kivity }
287b7cd3db6SAvi Kivity 
288b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b)
289b7cd3db6SAvi Kivity {
290b7cd3db6SAvi Kivity     *a = int128_add(*a, b);
291b7cd3db6SAvi Kivity }
292b7cd3db6SAvi Kivity 
293b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b)
294b7cd3db6SAvi Kivity {
295b7cd3db6SAvi Kivity     *a = int128_sub(*a, b);
296b7cd3db6SAvi Kivity }
297b7cd3db6SAvi Kivity 
2980846beb3SRichard Henderson #endif /* CONFIG_INT128 */
2990846beb3SRichard Henderson #endif /* INT128_H */
300