xref: /qemu/include/qemu/int128.h (revision 06905f64)
1 #ifndef INT128_H
2 #define INT128_H
3 
4 #include "qemu/bswap.h"
5 
6 #ifdef CONFIG_INT128
7 typedef __int128_t Int128;
8 
9 static inline Int128 int128_make64(uint64_t a)
10 {
11     return a;
12 }
13 
14 static inline Int128 int128_makes64(int64_t a)
15 {
16     return a;
17 }
18 
19 static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
20 {
21     return (__uint128_t)hi << 64 | lo;
22 }
23 
24 static inline uint64_t int128_get64(Int128 a)
25 {
26     uint64_t r = a;
27     assert(r == a);
28     return r;
29 }
30 
31 static inline uint64_t int128_getlo(Int128 a)
32 {
33     return a;
34 }
35 
36 static inline int64_t int128_gethi(Int128 a)
37 {
38     return a >> 64;
39 }
40 
41 static inline Int128 int128_zero(void)
42 {
43     return 0;
44 }
45 
46 static inline Int128 int128_one(void)
47 {
48     return 1;
49 }
50 
51 static inline Int128 int128_2_64(void)
52 {
53     return (Int128)1 << 64;
54 }
55 
56 static inline Int128 int128_exts64(int64_t a)
57 {
58     return a;
59 }
60 
61 static inline Int128 int128_and(Int128 a, Int128 b)
62 {
63     return a & b;
64 }
65 
66 static inline Int128 int128_or(Int128 a, Int128 b)
67 {
68     return a | b;
69 }
70 
71 static inline Int128 int128_rshift(Int128 a, int n)
72 {
73     return a >> n;
74 }
75 
76 static inline Int128 int128_lshift(Int128 a, int n)
77 {
78     return a << n;
79 }
80 
81 static inline Int128 int128_add(Int128 a, Int128 b)
82 {
83     return a + b;
84 }
85 
86 static inline Int128 int128_neg(Int128 a)
87 {
88     return -a;
89 }
90 
91 static inline Int128 int128_sub(Int128 a, Int128 b)
92 {
93     return a - b;
94 }
95 
96 static inline bool int128_nonneg(Int128 a)
97 {
98     return a >= 0;
99 }
100 
101 static inline bool int128_eq(Int128 a, Int128 b)
102 {
103     return a == b;
104 }
105 
106 static inline bool int128_ne(Int128 a, Int128 b)
107 {
108     return a != b;
109 }
110 
111 static inline bool int128_ge(Int128 a, Int128 b)
112 {
113     return a >= b;
114 }
115 
116 static inline bool int128_lt(Int128 a, Int128 b)
117 {
118     return a < b;
119 }
120 
121 static inline bool int128_le(Int128 a, Int128 b)
122 {
123     return a <= b;
124 }
125 
126 static inline bool int128_gt(Int128 a, Int128 b)
127 {
128     return a > b;
129 }
130 
131 static inline bool int128_nz(Int128 a)
132 {
133     return a != 0;
134 }
135 
136 static inline Int128 int128_min(Int128 a, Int128 b)
137 {
138     return a < b ? a : b;
139 }
140 
141 static inline Int128 int128_max(Int128 a, Int128 b)
142 {
143     return a > b ? a : b;
144 }
145 
146 static inline void int128_addto(Int128 *a, Int128 b)
147 {
148     *a += b;
149 }
150 
151 static inline void int128_subfrom(Int128 *a, Int128 b)
152 {
153     *a -= b;
154 }
155 
156 static inline Int128 bswap128(Int128 a)
157 {
158 #if __has_builtin(__builtin_bswap128)
159     return __builtin_bswap128(a);
160 #else
161     return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a)));
162 #endif
163 }
164 
165 #else /* !CONFIG_INT128 */
166 
167 typedef struct Int128 Int128;
168 
169 /*
170  * We guarantee that the in-memory byte representation of an
171  * Int128 is that of a host-endian-order 128-bit integer
172  * (whether using this struct or the __int128_t version of the type).
173  * Some code using this type relies on this (eg when copying it into
174  * guest memory or a gdb protocol buffer, or by using Int128 in
175  * a union with other integer types).
176  */
177 struct Int128 {
178 #ifdef HOST_WORDS_BIGENDIAN
179     int64_t hi;
180     uint64_t lo;
181 #else
182     uint64_t lo;
183     int64_t hi;
184 #endif
185 };
186 
187 static inline Int128 int128_make64(uint64_t a)
188 {
189     return (Int128) { .lo = a, .hi = 0 };
190 }
191 
192 static inline Int128 int128_makes64(int64_t a)
193 {
194     return (Int128) { .lo = a, .hi = a >> 63 };
195 }
196 
197 static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
198 {
199     return (Int128) { .lo = lo, .hi = hi };
200 }
201 
202 static inline uint64_t int128_get64(Int128 a)
203 {
204     assert(!a.hi);
205     return a.lo;
206 }
207 
208 static inline uint64_t int128_getlo(Int128 a)
209 {
210     return a.lo;
211 }
212 
213 static inline int64_t int128_gethi(Int128 a)
214 {
215     return a.hi;
216 }
217 
218 static inline Int128 int128_zero(void)
219 {
220     return int128_make64(0);
221 }
222 
223 static inline Int128 int128_one(void)
224 {
225     return int128_make64(1);
226 }
227 
228 static inline Int128 int128_2_64(void)
229 {
230     return int128_make128(0, 1);
231 }
232 
233 static inline Int128 int128_exts64(int64_t a)
234 {
235     return int128_make128(a, (a < 0) ? -1 : 0);
236 }
237 
238 static inline Int128 int128_and(Int128 a, Int128 b)
239 {
240     return int128_make128(a.lo & b.lo, a.hi & b.hi);
241 }
242 
243 static inline Int128 int128_or(Int128 a, Int128 b)
244 {
245     return int128_make128(a.lo | b.lo, a.hi | b.hi);
246 }
247 
248 static inline Int128 int128_rshift(Int128 a, int n)
249 {
250     int64_t h;
251     if (!n) {
252         return a;
253     }
254     h = a.hi >> (n & 63);
255     if (n >= 64) {
256         return int128_make128(h, h >> 63);
257     } else {
258         return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h);
259     }
260 }
261 
262 static inline Int128 int128_lshift(Int128 a, int n)
263 {
264     uint64_t l = a.lo << (n & 63);
265     if (n >= 64) {
266         return int128_make128(0, l);
267     } else if (n > 0) {
268         return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n)));
269     }
270     return a;
271 }
272 
273 static inline Int128 int128_add(Int128 a, Int128 b)
274 {
275     uint64_t lo = a.lo + b.lo;
276 
277     /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64).  Hence,
278      * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
279      * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
280      *
281      * So the carry is lo < a.lo.
282      */
283     return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo));
284 }
285 
286 static inline Int128 int128_neg(Int128 a)
287 {
288     uint64_t lo = -a.lo;
289     return int128_make128(lo, ~(uint64_t)a.hi + !lo);
290 }
291 
292 static inline Int128 int128_sub(Int128 a, Int128 b)
293 {
294     return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo));
295 }
296 
297 static inline bool int128_nonneg(Int128 a)
298 {
299     return a.hi >= 0;
300 }
301 
302 static inline bool int128_eq(Int128 a, Int128 b)
303 {
304     return a.lo == b.lo && a.hi == b.hi;
305 }
306 
307 static inline bool int128_ne(Int128 a, Int128 b)
308 {
309     return !int128_eq(a, b);
310 }
311 
312 static inline bool int128_ge(Int128 a, Int128 b)
313 {
314     return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
315 }
316 
317 static inline bool int128_lt(Int128 a, Int128 b)
318 {
319     return !int128_ge(a, b);
320 }
321 
322 static inline bool int128_le(Int128 a, Int128 b)
323 {
324     return int128_ge(b, a);
325 }
326 
327 static inline bool int128_gt(Int128 a, Int128 b)
328 {
329     return !int128_le(a, b);
330 }
331 
332 static inline bool int128_nz(Int128 a)
333 {
334     return a.lo || a.hi;
335 }
336 
337 static inline Int128 int128_min(Int128 a, Int128 b)
338 {
339     return int128_le(a, b) ? a : b;
340 }
341 
342 static inline Int128 int128_max(Int128 a, Int128 b)
343 {
344     return int128_ge(a, b) ? a : b;
345 }
346 
347 static inline void int128_addto(Int128 *a, Int128 b)
348 {
349     *a = int128_add(*a, b);
350 }
351 
352 static inline void int128_subfrom(Int128 *a, Int128 b)
353 {
354     *a = int128_sub(*a, b);
355 }
356 
357 static inline Int128 bswap128(Int128 a)
358 {
359     return int128_make128(bswap64(a.hi), bswap64(a.lo));
360 }
361 
362 #endif /* CONFIG_INT128 */
363 
364 static inline void bswap128s(Int128 *s)
365 {
366     *s = bswap128(*s);
367 }
368 
369 #endif /* INT128_H */
370