xref: /qemu/include/qemu/int128.h (revision 423d00c857ebc814ef6b5fc63f1d6c595cdc005d)
1b7cd3db6SAvi Kivity #ifndef INT128_H
2b7cd3db6SAvi Kivity #define INT128_H
3b7cd3db6SAvi Kivity 
46046c620SPaolo Bonzini #include <assert.h>
56046c620SPaolo Bonzini #include <stdint.h>
66046c620SPaolo Bonzini #include <stdbool.h>
76046c620SPaolo Bonzini 
8b7cd3db6SAvi Kivity typedef struct Int128 Int128;
9b7cd3db6SAvi Kivity 
10b7cd3db6SAvi Kivity struct Int128 {
11b7cd3db6SAvi Kivity     uint64_t lo;
12b7cd3db6SAvi Kivity     int64_t hi;
13b7cd3db6SAvi Kivity };
14b7cd3db6SAvi Kivity 
15b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a)
16b7cd3db6SAvi Kivity {
17b7cd3db6SAvi Kivity     return (Int128) { a, 0 };
18b7cd3db6SAvi Kivity }
19b7cd3db6SAvi Kivity 
20b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a)
21b7cd3db6SAvi Kivity {
22b7cd3db6SAvi Kivity     assert(!a.hi);
23b7cd3db6SAvi Kivity     return a.lo;
24b7cd3db6SAvi Kivity }
25b7cd3db6SAvi Kivity 
26b7cd3db6SAvi Kivity static inline Int128 int128_zero(void)
27b7cd3db6SAvi Kivity {
28b7cd3db6SAvi Kivity     return int128_make64(0);
29b7cd3db6SAvi Kivity }
30b7cd3db6SAvi Kivity 
31b7cd3db6SAvi Kivity static inline Int128 int128_one(void)
32b7cd3db6SAvi Kivity {
33b7cd3db6SAvi Kivity     return int128_make64(1);
34b7cd3db6SAvi Kivity }
35b7cd3db6SAvi Kivity 
36b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void)
37b7cd3db6SAvi Kivity {
38b7cd3db6SAvi Kivity     return (Int128) { 0, 1 };
39b7cd3db6SAvi Kivity }
40b7cd3db6SAvi Kivity 
41052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b)
42052e87b0SPaolo Bonzini {
43052e87b0SPaolo Bonzini     return (Int128) { a.lo & b.lo, a.hi & b.hi };
44052e87b0SPaolo Bonzini }
45052e87b0SPaolo Bonzini 
46052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n)
47052e87b0SPaolo Bonzini {
48052e87b0SPaolo Bonzini     int64_t h;
49052e87b0SPaolo Bonzini     if (!n) {
50052e87b0SPaolo Bonzini         return a;
51052e87b0SPaolo Bonzini     }
52052e87b0SPaolo Bonzini     h = a.hi >> (n & 63);
53052e87b0SPaolo Bonzini     if (n >= 64) {
54052e87b0SPaolo Bonzini         return (Int128) { h, h >> 63 };
55052e87b0SPaolo Bonzini     } else {
56*423d00c8SPeter Maydell         return (Int128) { (a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h };
57052e87b0SPaolo Bonzini     }
58052e87b0SPaolo Bonzini }
59052e87b0SPaolo Bonzini 
60b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b)
61b7cd3db6SAvi Kivity {
626046c620SPaolo Bonzini     uint64_t lo = a.lo + b.lo;
636046c620SPaolo Bonzini 
646046c620SPaolo Bonzini     /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64).  Hence,
656046c620SPaolo Bonzini      * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
666046c620SPaolo Bonzini      * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
676046c620SPaolo Bonzini      *
686046c620SPaolo Bonzini      * So the carry is lo < a.lo.
696046c620SPaolo Bonzini      */
706046c620SPaolo Bonzini     return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) };
71b7cd3db6SAvi Kivity }
72b7cd3db6SAvi Kivity 
73b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a)
74b7cd3db6SAvi Kivity {
756046c620SPaolo Bonzini     uint64_t lo = -a.lo;
766046c620SPaolo Bonzini     return (Int128) { lo, ~(uint64_t)a.hi + !lo };
77b7cd3db6SAvi Kivity }
78b7cd3db6SAvi Kivity 
79b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b)
80b7cd3db6SAvi Kivity {
81*423d00c8SPeter Maydell     return (Int128){ a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo) };
82b7cd3db6SAvi Kivity }
83b7cd3db6SAvi Kivity 
84b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a)
85b7cd3db6SAvi Kivity {
86b7cd3db6SAvi Kivity     return a.hi >= 0;
87b7cd3db6SAvi Kivity }
88b7cd3db6SAvi Kivity 
89b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b)
90b7cd3db6SAvi Kivity {
91b7cd3db6SAvi Kivity     return a.lo == b.lo && a.hi == b.hi;
92b7cd3db6SAvi Kivity }
93b7cd3db6SAvi Kivity 
94b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b)
95b7cd3db6SAvi Kivity {
96b7cd3db6SAvi Kivity     return !int128_eq(a, b);
97b7cd3db6SAvi Kivity }
98b7cd3db6SAvi Kivity 
99b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b)
100b7cd3db6SAvi Kivity {
1016046c620SPaolo Bonzini     return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
102b7cd3db6SAvi Kivity }
103b7cd3db6SAvi Kivity 
104b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b)
105b7cd3db6SAvi Kivity {
106b7cd3db6SAvi Kivity     return !int128_ge(a, b);
107b7cd3db6SAvi Kivity }
108b7cd3db6SAvi Kivity 
109b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b)
110b7cd3db6SAvi Kivity {
111b7cd3db6SAvi Kivity     return int128_ge(b, a);
112b7cd3db6SAvi Kivity }
113b7cd3db6SAvi Kivity 
114b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b)
115b7cd3db6SAvi Kivity {
116b7cd3db6SAvi Kivity     return !int128_le(a, b);
117b7cd3db6SAvi Kivity }
118b7cd3db6SAvi Kivity 
119b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a)
120b7cd3db6SAvi Kivity {
121b7cd3db6SAvi Kivity     return a.lo || a.hi;
122b7cd3db6SAvi Kivity }
123b7cd3db6SAvi Kivity 
124b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b)
125b7cd3db6SAvi Kivity {
126b7cd3db6SAvi Kivity     return int128_le(a, b) ? a : b;
127b7cd3db6SAvi Kivity }
128b7cd3db6SAvi Kivity 
129b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b)
130b7cd3db6SAvi Kivity {
131b7cd3db6SAvi Kivity     return int128_ge(a, b) ? a : b;
132b7cd3db6SAvi Kivity }
133b7cd3db6SAvi Kivity 
134b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b)
135b7cd3db6SAvi Kivity {
136b7cd3db6SAvi Kivity     *a = int128_add(*a, b);
137b7cd3db6SAvi Kivity }
138b7cd3db6SAvi Kivity 
139b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b)
140b7cd3db6SAvi Kivity {
141b7cd3db6SAvi Kivity     *a = int128_sub(*a, b);
142b7cd3db6SAvi Kivity }
143b7cd3db6SAvi Kivity 
144b7cd3db6SAvi Kivity #endif
145