xref: /qemu/include/qemu/int128.h (revision 0846beb36641e8f0c3ee55a5bb84d468b653c852)
1b7cd3db6SAvi Kivity #ifndef INT128_H
2b7cd3db6SAvi Kivity #define INT128_H
3b7cd3db6SAvi Kivity 
4*0846beb3SRichard Henderson #ifdef CONFIG_INT128
5*0846beb3SRichard Henderson 
6*0846beb3SRichard Henderson typedef __int128_t Int128;
7*0846beb3SRichard Henderson 
8*0846beb3SRichard Henderson static inline Int128 int128_make64(uint64_t a)
9*0846beb3SRichard Henderson {
10*0846beb3SRichard Henderson     return a;
11*0846beb3SRichard Henderson }
12*0846beb3SRichard Henderson 
13*0846beb3SRichard Henderson static inline uint64_t int128_get64(Int128 a)
14*0846beb3SRichard Henderson {
15*0846beb3SRichard Henderson     uint64_t r = a;
16*0846beb3SRichard Henderson     assert(r == a);
17*0846beb3SRichard Henderson     return r;
18*0846beb3SRichard Henderson }
19*0846beb3SRichard Henderson 
20*0846beb3SRichard Henderson static inline uint64_t int128_getlo(Int128 a)
21*0846beb3SRichard Henderson {
22*0846beb3SRichard Henderson     return a;
23*0846beb3SRichard Henderson }
24*0846beb3SRichard Henderson 
25*0846beb3SRichard Henderson static inline int64_t int128_gethi(Int128 a)
26*0846beb3SRichard Henderson {
27*0846beb3SRichard Henderson     return a >> 64;
28*0846beb3SRichard Henderson }
29*0846beb3SRichard Henderson 
30*0846beb3SRichard Henderson static inline Int128 int128_zero(void)
31*0846beb3SRichard Henderson {
32*0846beb3SRichard Henderson     return 0;
33*0846beb3SRichard Henderson }
34*0846beb3SRichard Henderson 
35*0846beb3SRichard Henderson static inline Int128 int128_one(void)
36*0846beb3SRichard Henderson {
37*0846beb3SRichard Henderson     return 1;
38*0846beb3SRichard Henderson }
39*0846beb3SRichard Henderson 
40*0846beb3SRichard Henderson static inline Int128 int128_2_64(void)
41*0846beb3SRichard Henderson {
42*0846beb3SRichard Henderson     return (Int128)1 << 64;
43*0846beb3SRichard Henderson }
44*0846beb3SRichard Henderson 
45*0846beb3SRichard Henderson static inline Int128 int128_exts64(int64_t a)
46*0846beb3SRichard Henderson {
47*0846beb3SRichard Henderson     return a;
48*0846beb3SRichard Henderson }
49*0846beb3SRichard Henderson 
50*0846beb3SRichard Henderson static inline Int128 int128_and(Int128 a, Int128 b)
51*0846beb3SRichard Henderson {
52*0846beb3SRichard Henderson     return a & b;
53*0846beb3SRichard Henderson }
54*0846beb3SRichard Henderson 
55*0846beb3SRichard Henderson static inline Int128 int128_rshift(Int128 a, int n)
56*0846beb3SRichard Henderson {
57*0846beb3SRichard Henderson     return a >> n;
58*0846beb3SRichard Henderson }
59*0846beb3SRichard Henderson 
60*0846beb3SRichard Henderson static inline Int128 int128_add(Int128 a, Int128 b)
61*0846beb3SRichard Henderson {
62*0846beb3SRichard Henderson     return a + b;
63*0846beb3SRichard Henderson }
64*0846beb3SRichard Henderson 
65*0846beb3SRichard Henderson static inline Int128 int128_neg(Int128 a)
66*0846beb3SRichard Henderson {
67*0846beb3SRichard Henderson     return -a;
68*0846beb3SRichard Henderson }
69*0846beb3SRichard Henderson 
70*0846beb3SRichard Henderson static inline Int128 int128_sub(Int128 a, Int128 b)
71*0846beb3SRichard Henderson {
72*0846beb3SRichard Henderson     return a - b;
73*0846beb3SRichard Henderson }
74*0846beb3SRichard Henderson 
75*0846beb3SRichard Henderson static inline bool int128_nonneg(Int128 a)
76*0846beb3SRichard Henderson {
77*0846beb3SRichard Henderson     return a >= 0;
78*0846beb3SRichard Henderson }
79*0846beb3SRichard Henderson 
80*0846beb3SRichard Henderson static inline bool int128_eq(Int128 a, Int128 b)
81*0846beb3SRichard Henderson {
82*0846beb3SRichard Henderson     return a == b;
83*0846beb3SRichard Henderson }
84*0846beb3SRichard Henderson 
85*0846beb3SRichard Henderson static inline bool int128_ne(Int128 a, Int128 b)
86*0846beb3SRichard Henderson {
87*0846beb3SRichard Henderson     return a != b;
88*0846beb3SRichard Henderson }
89*0846beb3SRichard Henderson 
90*0846beb3SRichard Henderson static inline bool int128_ge(Int128 a, Int128 b)
91*0846beb3SRichard Henderson {
92*0846beb3SRichard Henderson     return a >= b;
93*0846beb3SRichard Henderson }
94*0846beb3SRichard Henderson 
95*0846beb3SRichard Henderson static inline bool int128_lt(Int128 a, Int128 b)
96*0846beb3SRichard Henderson {
97*0846beb3SRichard Henderson     return a < b;
98*0846beb3SRichard Henderson }
99*0846beb3SRichard Henderson 
100*0846beb3SRichard Henderson static inline bool int128_le(Int128 a, Int128 b)
101*0846beb3SRichard Henderson {
102*0846beb3SRichard Henderson     return a <= b;
103*0846beb3SRichard Henderson }
104*0846beb3SRichard Henderson 
105*0846beb3SRichard Henderson static inline bool int128_gt(Int128 a, Int128 b)
106*0846beb3SRichard Henderson {
107*0846beb3SRichard Henderson     return a > b;
108*0846beb3SRichard Henderson }
109*0846beb3SRichard Henderson 
110*0846beb3SRichard Henderson static inline bool int128_nz(Int128 a)
111*0846beb3SRichard Henderson {
112*0846beb3SRichard Henderson     return a != 0;
113*0846beb3SRichard Henderson }
114*0846beb3SRichard Henderson 
115*0846beb3SRichard Henderson static inline Int128 int128_min(Int128 a, Int128 b)
116*0846beb3SRichard Henderson {
117*0846beb3SRichard Henderson     return a < b ? a : b;
118*0846beb3SRichard Henderson }
119*0846beb3SRichard Henderson 
120*0846beb3SRichard Henderson static inline Int128 int128_max(Int128 a, Int128 b)
121*0846beb3SRichard Henderson {
122*0846beb3SRichard Henderson     return a > b ? a : b;
123*0846beb3SRichard Henderson }
124*0846beb3SRichard Henderson 
125*0846beb3SRichard Henderson static inline void int128_addto(Int128 *a, Int128 b)
126*0846beb3SRichard Henderson {
127*0846beb3SRichard Henderson     *a += b;
128*0846beb3SRichard Henderson }
129*0846beb3SRichard Henderson 
130*0846beb3SRichard Henderson static inline void int128_subfrom(Int128 *a, Int128 b)
131*0846beb3SRichard Henderson {
132*0846beb3SRichard Henderson     *a -= b;
133*0846beb3SRichard Henderson }
134*0846beb3SRichard Henderson 
135*0846beb3SRichard Henderson #else /* !CONFIG_INT128 */
1366046c620SPaolo Bonzini 
137b7cd3db6SAvi Kivity typedef struct Int128 Int128;
138b7cd3db6SAvi Kivity 
139b7cd3db6SAvi Kivity struct Int128 {
140b7cd3db6SAvi Kivity     uint64_t lo;
141b7cd3db6SAvi Kivity     int64_t hi;
142b7cd3db6SAvi Kivity };
143b7cd3db6SAvi Kivity 
144b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a)
145b7cd3db6SAvi Kivity {
146b7cd3db6SAvi Kivity     return (Int128) { a, 0 };
147b7cd3db6SAvi Kivity }
148b7cd3db6SAvi Kivity 
149b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a)
150b7cd3db6SAvi Kivity {
151b7cd3db6SAvi Kivity     assert(!a.hi);
152b7cd3db6SAvi Kivity     return a.lo;
153b7cd3db6SAvi Kivity }
154b7cd3db6SAvi Kivity 
155258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a)
156258dfaaaSRichard Henderson {
157258dfaaaSRichard Henderson     return a.lo;
158258dfaaaSRichard Henderson }
159258dfaaaSRichard Henderson 
160258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a)
161258dfaaaSRichard Henderson {
162258dfaaaSRichard Henderson     return a.hi;
163258dfaaaSRichard Henderson }
164258dfaaaSRichard Henderson 
165b7cd3db6SAvi Kivity static inline Int128 int128_zero(void)
166b7cd3db6SAvi Kivity {
167b7cd3db6SAvi Kivity     return int128_make64(0);
168b7cd3db6SAvi Kivity }
169b7cd3db6SAvi Kivity 
170b7cd3db6SAvi Kivity static inline Int128 int128_one(void)
171b7cd3db6SAvi Kivity {
172b7cd3db6SAvi Kivity     return int128_make64(1);
173b7cd3db6SAvi Kivity }
174b7cd3db6SAvi Kivity 
175b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void)
176b7cd3db6SAvi Kivity {
177b7cd3db6SAvi Kivity     return (Int128) { 0, 1 };
178b7cd3db6SAvi Kivity }
179b7cd3db6SAvi Kivity 
18012e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a)
18112e1129bSAlexey Kardashevskiy {
18212e1129bSAlexey Kardashevskiy     return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 };
18312e1129bSAlexey Kardashevskiy }
18412e1129bSAlexey Kardashevskiy 
185052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b)
186052e87b0SPaolo Bonzini {
187052e87b0SPaolo Bonzini     return (Int128) { a.lo & b.lo, a.hi & b.hi };
188052e87b0SPaolo Bonzini }
189052e87b0SPaolo Bonzini 
190052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n)
191052e87b0SPaolo Bonzini {
192052e87b0SPaolo Bonzini     int64_t h;
193052e87b0SPaolo Bonzini     if (!n) {
194052e87b0SPaolo Bonzini         return a;
195052e87b0SPaolo Bonzini     }
196052e87b0SPaolo Bonzini     h = a.hi >> (n & 63);
197052e87b0SPaolo Bonzini     if (n >= 64) {
198052e87b0SPaolo Bonzini         return (Int128) { h, h >> 63 };
199052e87b0SPaolo Bonzini     } else {
200423d00c8SPeter Maydell         return (Int128) { (a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h };
201052e87b0SPaolo Bonzini     }
202052e87b0SPaolo Bonzini }
203052e87b0SPaolo Bonzini 
204b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b)
205b7cd3db6SAvi Kivity {
2066046c620SPaolo Bonzini     uint64_t lo = a.lo + b.lo;
2076046c620SPaolo Bonzini 
2086046c620SPaolo Bonzini     /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64).  Hence,
2096046c620SPaolo Bonzini      * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
2106046c620SPaolo Bonzini      * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
2116046c620SPaolo Bonzini      *
2126046c620SPaolo Bonzini      * So the carry is lo < a.lo.
2136046c620SPaolo Bonzini      */
2146046c620SPaolo Bonzini     return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) };
215b7cd3db6SAvi Kivity }
216b7cd3db6SAvi Kivity 
217b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a)
218b7cd3db6SAvi Kivity {
2196046c620SPaolo Bonzini     uint64_t lo = -a.lo;
2206046c620SPaolo Bonzini     return (Int128) { lo, ~(uint64_t)a.hi + !lo };
221b7cd3db6SAvi Kivity }
222b7cd3db6SAvi Kivity 
223b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b)
224b7cd3db6SAvi Kivity {
225423d00c8SPeter Maydell     return (Int128){ a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo) };
226b7cd3db6SAvi Kivity }
227b7cd3db6SAvi Kivity 
228b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a)
229b7cd3db6SAvi Kivity {
230b7cd3db6SAvi Kivity     return a.hi >= 0;
231b7cd3db6SAvi Kivity }
232b7cd3db6SAvi Kivity 
233b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b)
234b7cd3db6SAvi Kivity {
235b7cd3db6SAvi Kivity     return a.lo == b.lo && a.hi == b.hi;
236b7cd3db6SAvi Kivity }
237b7cd3db6SAvi Kivity 
238b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b)
239b7cd3db6SAvi Kivity {
240b7cd3db6SAvi Kivity     return !int128_eq(a, b);
241b7cd3db6SAvi Kivity }
242b7cd3db6SAvi Kivity 
243b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b)
244b7cd3db6SAvi Kivity {
2456046c620SPaolo Bonzini     return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
246b7cd3db6SAvi Kivity }
247b7cd3db6SAvi Kivity 
248b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b)
249b7cd3db6SAvi Kivity {
250b7cd3db6SAvi Kivity     return !int128_ge(a, b);
251b7cd3db6SAvi Kivity }
252b7cd3db6SAvi Kivity 
253b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b)
254b7cd3db6SAvi Kivity {
255b7cd3db6SAvi Kivity     return int128_ge(b, a);
256b7cd3db6SAvi Kivity }
257b7cd3db6SAvi Kivity 
258b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b)
259b7cd3db6SAvi Kivity {
260b7cd3db6SAvi Kivity     return !int128_le(a, b);
261b7cd3db6SAvi Kivity }
262b7cd3db6SAvi Kivity 
263b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a)
264b7cd3db6SAvi Kivity {
265b7cd3db6SAvi Kivity     return a.lo || a.hi;
266b7cd3db6SAvi Kivity }
267b7cd3db6SAvi Kivity 
268b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b)
269b7cd3db6SAvi Kivity {
270b7cd3db6SAvi Kivity     return int128_le(a, b) ? a : b;
271b7cd3db6SAvi Kivity }
272b7cd3db6SAvi Kivity 
273b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b)
274b7cd3db6SAvi Kivity {
275b7cd3db6SAvi Kivity     return int128_ge(a, b) ? a : b;
276b7cd3db6SAvi Kivity }
277b7cd3db6SAvi Kivity 
278b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b)
279b7cd3db6SAvi Kivity {
280b7cd3db6SAvi Kivity     *a = int128_add(*a, b);
281b7cd3db6SAvi Kivity }
282b7cd3db6SAvi Kivity 
283b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b)
284b7cd3db6SAvi Kivity {
285b7cd3db6SAvi Kivity     *a = int128_sub(*a, b);
286b7cd3db6SAvi Kivity }
287b7cd3db6SAvi Kivity 
288*0846beb3SRichard Henderson #endif /* CONFIG_INT128 */
289*0846beb3SRichard Henderson #endif /* INT128_H */
290