xref: /qemu/include/qemu/int128.h (revision 258dfaaad05a5fbe32a142b794e1df3e16501d0e)
1b7cd3db6SAvi Kivity #ifndef INT128_H
2b7cd3db6SAvi Kivity #define INT128_H
3b7cd3db6SAvi Kivity 
46046c620SPaolo Bonzini 
5b7cd3db6SAvi Kivity typedef struct Int128 Int128;
6b7cd3db6SAvi Kivity 
7b7cd3db6SAvi Kivity struct Int128 {
8b7cd3db6SAvi Kivity     uint64_t lo;
9b7cd3db6SAvi Kivity     int64_t hi;
10b7cd3db6SAvi Kivity };
11b7cd3db6SAvi Kivity 
12b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a)
13b7cd3db6SAvi Kivity {
14b7cd3db6SAvi Kivity     return (Int128) { a, 0 };
15b7cd3db6SAvi Kivity }
16b7cd3db6SAvi Kivity 
17b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a)
18b7cd3db6SAvi Kivity {
19b7cd3db6SAvi Kivity     assert(!a.hi);
20b7cd3db6SAvi Kivity     return a.lo;
21b7cd3db6SAvi Kivity }
22b7cd3db6SAvi Kivity 
23*258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a)
24*258dfaaaSRichard Henderson {
25*258dfaaaSRichard Henderson     return a.lo;
26*258dfaaaSRichard Henderson }
27*258dfaaaSRichard Henderson 
28*258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a)
29*258dfaaaSRichard Henderson {
30*258dfaaaSRichard Henderson     return a.hi;
31*258dfaaaSRichard Henderson }
32*258dfaaaSRichard Henderson 
33b7cd3db6SAvi Kivity static inline Int128 int128_zero(void)
34b7cd3db6SAvi Kivity {
35b7cd3db6SAvi Kivity     return int128_make64(0);
36b7cd3db6SAvi Kivity }
37b7cd3db6SAvi Kivity 
38b7cd3db6SAvi Kivity static inline Int128 int128_one(void)
39b7cd3db6SAvi Kivity {
40b7cd3db6SAvi Kivity     return int128_make64(1);
41b7cd3db6SAvi Kivity }
42b7cd3db6SAvi Kivity 
43b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void)
44b7cd3db6SAvi Kivity {
45b7cd3db6SAvi Kivity     return (Int128) { 0, 1 };
46b7cd3db6SAvi Kivity }
47b7cd3db6SAvi Kivity 
4812e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a)
4912e1129bSAlexey Kardashevskiy {
5012e1129bSAlexey Kardashevskiy     return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 };
5112e1129bSAlexey Kardashevskiy }
5212e1129bSAlexey Kardashevskiy 
53052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b)
54052e87b0SPaolo Bonzini {
55052e87b0SPaolo Bonzini     return (Int128) { a.lo & b.lo, a.hi & b.hi };
56052e87b0SPaolo Bonzini }
57052e87b0SPaolo Bonzini 
58052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n)
59052e87b0SPaolo Bonzini {
60052e87b0SPaolo Bonzini     int64_t h;
61052e87b0SPaolo Bonzini     if (!n) {
62052e87b0SPaolo Bonzini         return a;
63052e87b0SPaolo Bonzini     }
64052e87b0SPaolo Bonzini     h = a.hi >> (n & 63);
65052e87b0SPaolo Bonzini     if (n >= 64) {
66052e87b0SPaolo Bonzini         return (Int128) { h, h >> 63 };
67052e87b0SPaolo Bonzini     } else {
68423d00c8SPeter Maydell         return (Int128) { (a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h };
69052e87b0SPaolo Bonzini     }
70052e87b0SPaolo Bonzini }
71052e87b0SPaolo Bonzini 
72b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b)
73b7cd3db6SAvi Kivity {
746046c620SPaolo Bonzini     uint64_t lo = a.lo + b.lo;
756046c620SPaolo Bonzini 
766046c620SPaolo Bonzini     /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64).  Hence,
776046c620SPaolo Bonzini      * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
786046c620SPaolo Bonzini      * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
796046c620SPaolo Bonzini      *
806046c620SPaolo Bonzini      * So the carry is lo < a.lo.
816046c620SPaolo Bonzini      */
826046c620SPaolo Bonzini     return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) };
83b7cd3db6SAvi Kivity }
84b7cd3db6SAvi Kivity 
85b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a)
86b7cd3db6SAvi Kivity {
876046c620SPaolo Bonzini     uint64_t lo = -a.lo;
886046c620SPaolo Bonzini     return (Int128) { lo, ~(uint64_t)a.hi + !lo };
89b7cd3db6SAvi Kivity }
90b7cd3db6SAvi Kivity 
91b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b)
92b7cd3db6SAvi Kivity {
93423d00c8SPeter Maydell     return (Int128){ a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo) };
94b7cd3db6SAvi Kivity }
95b7cd3db6SAvi Kivity 
96b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a)
97b7cd3db6SAvi Kivity {
98b7cd3db6SAvi Kivity     return a.hi >= 0;
99b7cd3db6SAvi Kivity }
100b7cd3db6SAvi Kivity 
101b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b)
102b7cd3db6SAvi Kivity {
103b7cd3db6SAvi Kivity     return a.lo == b.lo && a.hi == b.hi;
104b7cd3db6SAvi Kivity }
105b7cd3db6SAvi Kivity 
106b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b)
107b7cd3db6SAvi Kivity {
108b7cd3db6SAvi Kivity     return !int128_eq(a, b);
109b7cd3db6SAvi Kivity }
110b7cd3db6SAvi Kivity 
111b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b)
112b7cd3db6SAvi Kivity {
1136046c620SPaolo Bonzini     return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
114b7cd3db6SAvi Kivity }
115b7cd3db6SAvi Kivity 
116b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b)
117b7cd3db6SAvi Kivity {
118b7cd3db6SAvi Kivity     return !int128_ge(a, b);
119b7cd3db6SAvi Kivity }
120b7cd3db6SAvi Kivity 
121b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b)
122b7cd3db6SAvi Kivity {
123b7cd3db6SAvi Kivity     return int128_ge(b, a);
124b7cd3db6SAvi Kivity }
125b7cd3db6SAvi Kivity 
126b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b)
127b7cd3db6SAvi Kivity {
128b7cd3db6SAvi Kivity     return !int128_le(a, b);
129b7cd3db6SAvi Kivity }
130b7cd3db6SAvi Kivity 
131b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a)
132b7cd3db6SAvi Kivity {
133b7cd3db6SAvi Kivity     return a.lo || a.hi;
134b7cd3db6SAvi Kivity }
135b7cd3db6SAvi Kivity 
136b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b)
137b7cd3db6SAvi Kivity {
138b7cd3db6SAvi Kivity     return int128_le(a, b) ? a : b;
139b7cd3db6SAvi Kivity }
140b7cd3db6SAvi Kivity 
141b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b)
142b7cd3db6SAvi Kivity {
143b7cd3db6SAvi Kivity     return int128_ge(a, b) ? a : b;
144b7cd3db6SAvi Kivity }
145b7cd3db6SAvi Kivity 
146b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b)
147b7cd3db6SAvi Kivity {
148b7cd3db6SAvi Kivity     *a = int128_add(*a, b);
149b7cd3db6SAvi Kivity }
150b7cd3db6SAvi Kivity 
151b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b)
152b7cd3db6SAvi Kivity {
153b7cd3db6SAvi Kivity     *a = int128_sub(*a, b);
154b7cd3db6SAvi Kivity }
155b7cd3db6SAvi Kivity 
156b7cd3db6SAvi Kivity #endif
157