]>
Commit | Line | Data |
---|---|---|
b7cd3db6 AK |
1 | #ifndef INT128_H |
2 | #define INT128_H | |
3 | ||
7ebee43e | 4 | #include "qemu/bswap.h" |
0846beb3 | 5 | |
b959822c RH |
6 | /* |
7 | * With TCI, we need to use libffi for interfacing with TCG helpers. | |
8 | * But libffi does not support __int128_t, and therefore cannot pass | |
9 | * or return values of this type, force use of the Int128 struct. | |
10 | */ | |
11 | #if defined(CONFIG_INT128) && !defined(CONFIG_TCG_INTERPRETER) | |
0846beb3 | 12 | typedef __int128_t Int128; |
34aee9c9 | 13 | typedef __int128_t __attribute__((aligned(16))) Int128Aligned; |
0846beb3 RH |
14 | |
15 | static inline Int128 int128_make64(uint64_t a) | |
16 | { | |
17 | return a; | |
18 | } | |
19 | ||
703235a3 PM |
20 | static inline Int128 int128_makes64(int64_t a) |
21 | { | |
22 | return a; | |
23 | } | |
24 | ||
1edaeee0 RH |
25 | static inline Int128 int128_make128(uint64_t lo, uint64_t hi) |
26 | { | |
27 | return (__uint128_t)hi << 64 | lo; | |
28 | } | |
29 | ||
0846beb3 RH |
30 | static inline uint64_t int128_get64(Int128 a) |
31 | { | |
32 | uint64_t r = a; | |
33 | assert(r == a); | |
34 | return r; | |
35 | } | |
36 | ||
37 | static inline uint64_t int128_getlo(Int128 a) | |
38 | { | |
39 | return a; | |
40 | } | |
41 | ||
42 | static inline int64_t int128_gethi(Int128 a) | |
43 | { | |
44 | return a >> 64; | |
45 | } | |
46 | ||
47 | static inline Int128 int128_zero(void) | |
48 | { | |
49 | return 0; | |
50 | } | |
51 | ||
52 | static inline Int128 int128_one(void) | |
53 | { | |
54 | return 1; | |
55 | } | |
56 | ||
57 | static inline Int128 int128_2_64(void) | |
58 | { | |
59 | return (Int128)1 << 64; | |
60 | } | |
61 | ||
62 | static inline Int128 int128_exts64(int64_t a) | |
63 | { | |
64 | return a; | |
65 | } | |
66 | ||
1c469373 FP |
67 | static inline Int128 int128_not(Int128 a) |
68 | { | |
69 | return ~a; | |
70 | } | |
71 | ||
0846beb3 RH |
72 | static inline Int128 int128_and(Int128 a, Int128 b) |
73 | { | |
74 | return a & b; | |
75 | } | |
76 | ||
08895cda RH |
77 | static inline Int128 int128_or(Int128 a, Int128 b) |
78 | { | |
79 | return a | b; | |
80 | } | |
81 | ||
1c469373 FP |
82 | static inline Int128 int128_xor(Int128 a, Int128 b) |
83 | { | |
84 | return a ^ b; | |
85 | } | |
86 | ||
0846beb3 RH |
87 | static inline Int128 int128_rshift(Int128 a, int n) |
88 | { | |
89 | return a >> n; | |
90 | } | |
91 | ||
613cf0fc MF |
92 | static inline Int128 int128_urshift(Int128 a, int n) |
93 | { | |
94 | return (__uint128_t)a >> n; | |
95 | } | |
96 | ||
5be4dd04 RH |
97 | static inline Int128 int128_lshift(Int128 a, int n) |
98 | { | |
99 | return a << n; | |
100 | } | |
101 | ||
0846beb3 RH |
102 | static inline Int128 int128_add(Int128 a, Int128 b) |
103 | { | |
104 | return a + b; | |
105 | } | |
106 | ||
107 | static inline Int128 int128_neg(Int128 a) | |
108 | { | |
109 | return -a; | |
110 | } | |
111 | ||
112 | static inline Int128 int128_sub(Int128 a, Int128 b) | |
113 | { | |
114 | return a - b; | |
115 | } | |
116 | ||
117 | static inline bool int128_nonneg(Int128 a) | |
118 | { | |
119 | return a >= 0; | |
120 | } | |
121 | ||
122 | static inline bool int128_eq(Int128 a, Int128 b) | |
123 | { | |
124 | return a == b; | |
125 | } | |
126 | ||
127 | static inline bool int128_ne(Int128 a, Int128 b) | |
128 | { | |
129 | return a != b; | |
130 | } | |
131 | ||
132 | static inline bool int128_ge(Int128 a, Int128 b) | |
133 | { | |
134 | return a >= b; | |
135 | } | |
136 | ||
4724bbd2 LMC |
137 | static inline bool int128_uge(Int128 a, Int128 b) |
138 | { | |
139 | return ((__uint128_t)a) >= ((__uint128_t)b); | |
140 | } | |
141 | ||
0846beb3 RH |
142 | static inline bool int128_lt(Int128 a, Int128 b) |
143 | { | |
144 | return a < b; | |
145 | } | |
146 | ||
4724bbd2 LMC |
147 | static inline bool int128_ult(Int128 a, Int128 b) |
148 | { | |
149 | return (__uint128_t)a < (__uint128_t)b; | |
150 | } | |
151 | ||
0846beb3 RH |
152 | static inline bool int128_le(Int128 a, Int128 b) |
153 | { | |
154 | return a <= b; | |
155 | } | |
156 | ||
157 | static inline bool int128_gt(Int128 a, Int128 b) | |
158 | { | |
159 | return a > b; | |
160 | } | |
161 | ||
162 | static inline bool int128_nz(Int128 a) | |
163 | { | |
164 | return a != 0; | |
165 | } | |
166 | ||
167 | static inline Int128 int128_min(Int128 a, Int128 b) | |
168 | { | |
169 | return a < b ? a : b; | |
170 | } | |
171 | ||
172 | static inline Int128 int128_max(Int128 a, Int128 b) | |
173 | { | |
174 | return a > b ? a : b; | |
175 | } | |
176 | ||
177 | static inline void int128_addto(Int128 *a, Int128 b) | |
178 | { | |
179 | *a += b; | |
180 | } | |
181 | ||
182 | static inline void int128_subfrom(Int128 *a, Int128 b) | |
183 | { | |
184 | *a -= b; | |
185 | } | |
186 | ||
7ebee43e RH |
187 | static inline Int128 bswap128(Int128 a) |
188 | { | |
2484cd9c MF |
189 | #if __has_builtin(__builtin_bswap128) |
190 | return __builtin_bswap128(a); | |
191 | #else | |
7ebee43e | 192 | return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a))); |
2484cd9c | 193 | #endif |
7ebee43e RH |
194 | } |
195 | ||
4724bbd2 LMC |
196 | static inline int clz128(Int128 a) |
197 | { | |
198 | if (a >> 64) { | |
199 | return __builtin_clzll(a >> 64); | |
200 | } else { | |
201 | return (a) ? __builtin_clzll((uint64_t)a) + 64 : 128; | |
202 | } | |
203 | } | |
204 | ||
e9d07601 FP |
205 | static inline Int128 int128_divu(Int128 a, Int128 b) |
206 | { | |
207 | return (__uint128_t)a / (__uint128_t)b; | |
208 | } | |
209 | ||
210 | static inline Int128 int128_remu(Int128 a, Int128 b) | |
211 | { | |
212 | return (__uint128_t)a % (__uint128_t)b; | |
213 | } | |
214 | ||
215 | static inline Int128 int128_divs(Int128 a, Int128 b) | |
216 | { | |
217 | return a / b; | |
218 | } | |
219 | ||
220 | static inline Int128 int128_rems(Int128 a, Int128 b) | |
221 | { | |
222 | return a % b; | |
223 | } | |
224 | ||
0846beb3 | 225 | #else /* !CONFIG_INT128 */ |
6046c620 | 226 | |
b7cd3db6 | 227 | typedef struct Int128 Int128; |
34aee9c9 | 228 | typedef struct Int128 __attribute__((aligned(16))) Int128Aligned; |
b7cd3db6 | 229 | |
181b0c33 MF |
230 | /* |
231 | * We guarantee that the in-memory byte representation of an | |
232 | * Int128 is that of a host-endian-order 128-bit integer | |
233 | * (whether using this struct or the __int128_t version of the type). | |
234 | * Some code using this type relies on this (eg when copying it into | |
235 | * guest memory or a gdb protocol buffer, or by using Int128 in | |
236 | * a union with other integer types). | |
237 | */ | |
b7cd3db6 | 238 | struct Int128 { |
e03b5686 | 239 | #if HOST_BIG_ENDIAN |
181b0c33 MF |
240 | int64_t hi; |
241 | uint64_t lo; | |
242 | #else | |
b7cd3db6 AK |
243 | uint64_t lo; |
244 | int64_t hi; | |
181b0c33 | 245 | #endif |
b7cd3db6 AK |
246 | }; |
247 | ||
248 | static inline Int128 int128_make64(uint64_t a) | |
249 | { | |
181b0c33 | 250 | return (Int128) { .lo = a, .hi = 0 }; |
b7cd3db6 AK |
251 | } |
252 | ||
703235a3 PM |
253 | static inline Int128 int128_makes64(int64_t a) |
254 | { | |
181b0c33 | 255 | return (Int128) { .lo = a, .hi = a >> 63 }; |
703235a3 PM |
256 | } |
257 | ||
1edaeee0 RH |
258 | static inline Int128 int128_make128(uint64_t lo, uint64_t hi) |
259 | { | |
181b0c33 | 260 | return (Int128) { .lo = lo, .hi = hi }; |
1edaeee0 RH |
261 | } |
262 | ||
b7cd3db6 AK |
263 | static inline uint64_t int128_get64(Int128 a) |
264 | { | |
265 | assert(!a.hi); | |
266 | return a.lo; | |
267 | } | |
268 | ||
258dfaaa RH |
269 | static inline uint64_t int128_getlo(Int128 a) |
270 | { | |
271 | return a.lo; | |
272 | } | |
273 | ||
274 | static inline int64_t int128_gethi(Int128 a) | |
275 | { | |
276 | return a.hi; | |
277 | } | |
278 | ||
b7cd3db6 AK |
279 | static inline Int128 int128_zero(void) |
280 | { | |
281 | return int128_make64(0); | |
282 | } | |
283 | ||
284 | static inline Int128 int128_one(void) | |
285 | { | |
286 | return int128_make64(1); | |
287 | } | |
288 | ||
289 | static inline Int128 int128_2_64(void) | |
290 | { | |
181b0c33 | 291 | return int128_make128(0, 1); |
b7cd3db6 AK |
292 | } |
293 | ||
12e1129b AK |
294 | static inline Int128 int128_exts64(int64_t a) |
295 | { | |
181b0c33 | 296 | return int128_make128(a, (a < 0) ? -1 : 0); |
12e1129b AK |
297 | } |
298 | ||
1c469373 FP |
299 | static inline Int128 int128_not(Int128 a) |
300 | { | |
301 | return int128_make128(~a.lo, ~a.hi); | |
302 | } | |
303 | ||
052e87b0 PB |
304 | static inline Int128 int128_and(Int128 a, Int128 b) |
305 | { | |
181b0c33 | 306 | return int128_make128(a.lo & b.lo, a.hi & b.hi); |
052e87b0 PB |
307 | } |
308 | ||
08895cda RH |
309 | static inline Int128 int128_or(Int128 a, Int128 b) |
310 | { | |
181b0c33 | 311 | return int128_make128(a.lo | b.lo, a.hi | b.hi); |
08895cda RH |
312 | } |
313 | ||
1c469373 FP |
314 | static inline Int128 int128_xor(Int128 a, Int128 b) |
315 | { | |
316 | return int128_make128(a.lo ^ b.lo, a.hi ^ b.hi); | |
317 | } | |
318 | ||
052e87b0 PB |
319 | static inline Int128 int128_rshift(Int128 a, int n) |
320 | { | |
321 | int64_t h; | |
322 | if (!n) { | |
323 | return a; | |
324 | } | |
325 | h = a.hi >> (n & 63); | |
326 | if (n >= 64) { | |
1edaeee0 | 327 | return int128_make128(h, h >> 63); |
052e87b0 | 328 | } else { |
1edaeee0 | 329 | return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); |
052e87b0 PB |
330 | } |
331 | } | |
332 | ||
613cf0fc MF |
333 | static inline Int128 int128_urshift(Int128 a, int n) |
334 | { | |
335 | uint64_t h = a.hi; | |
336 | if (!n) { | |
337 | return a; | |
338 | } | |
339 | h = h >> (n & 63); | |
340 | if (n >= 64) { | |
341 | return int128_make64(h); | |
342 | } else { | |
343 | return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); | |
344 | } | |
345 | } | |
346 | ||
5be4dd04 RH |
347 | static inline Int128 int128_lshift(Int128 a, int n) |
348 | { | |
349 | uint64_t l = a.lo << (n & 63); | |
350 | if (n >= 64) { | |
351 | return int128_make128(0, l); | |
352 | } else if (n > 0) { | |
353 | return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n))); | |
354 | } | |
355 | return a; | |
356 | } | |
357 | ||
b7cd3db6 AK |
358 | static inline Int128 int128_add(Int128 a, Int128 b) |
359 | { | |
6046c620 PB |
360 | uint64_t lo = a.lo + b.lo; |
361 | ||
362 | /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, | |
363 | * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. | |
364 | * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. | |
365 | * | |
366 | * So the carry is lo < a.lo. | |
367 | */ | |
1edaeee0 | 368 | return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); |
b7cd3db6 AK |
369 | } |
370 | ||
371 | static inline Int128 int128_neg(Int128 a) | |
372 | { | |
6046c620 | 373 | uint64_t lo = -a.lo; |
1edaeee0 | 374 | return int128_make128(lo, ~(uint64_t)a.hi + !lo); |
b7cd3db6 AK |
375 | } |
376 | ||
377 | static inline Int128 int128_sub(Int128 a, Int128 b) | |
378 | { | |
1edaeee0 | 379 | return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); |
b7cd3db6 AK |
380 | } |
381 | ||
382 | static inline bool int128_nonneg(Int128 a) | |
383 | { | |
384 | return a.hi >= 0; | |
385 | } | |
386 | ||
387 | static inline bool int128_eq(Int128 a, Int128 b) | |
388 | { | |
389 | return a.lo == b.lo && a.hi == b.hi; | |
390 | } | |
391 | ||
392 | static inline bool int128_ne(Int128 a, Int128 b) | |
393 | { | |
394 | return !int128_eq(a, b); | |
395 | } | |
396 | ||
397 | static inline bool int128_ge(Int128 a, Int128 b) | |
398 | { | |
6046c620 | 399 | return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); |
b7cd3db6 AK |
400 | } |
401 | ||
4724bbd2 LMC |
402 | static inline bool int128_uge(Int128 a, Int128 b) |
403 | { | |
404 | return (uint64_t)a.hi > (uint64_t)b.hi || (a.hi == b.hi && a.lo >= b.lo); | |
405 | } | |
406 | ||
b7cd3db6 AK |
407 | static inline bool int128_lt(Int128 a, Int128 b) |
408 | { | |
409 | return !int128_ge(a, b); | |
410 | } | |
411 | ||
4724bbd2 LMC |
412 | static inline bool int128_ult(Int128 a, Int128 b) |
413 | { | |
414 | return !int128_uge(a, b); | |
415 | } | |
416 | ||
b7cd3db6 AK |
417 | static inline bool int128_le(Int128 a, Int128 b) |
418 | { | |
419 | return int128_ge(b, a); | |
420 | } | |
421 | ||
422 | static inline bool int128_gt(Int128 a, Int128 b) | |
423 | { | |
424 | return !int128_le(a, b); | |
425 | } | |
426 | ||
427 | static inline bool int128_nz(Int128 a) | |
428 | { | |
429 | return a.lo || a.hi; | |
430 | } | |
431 | ||
432 | static inline Int128 int128_min(Int128 a, Int128 b) | |
433 | { | |
434 | return int128_le(a, b) ? a : b; | |
435 | } | |
436 | ||
437 | static inline Int128 int128_max(Int128 a, Int128 b) | |
438 | { | |
439 | return int128_ge(a, b) ? a : b; | |
440 | } | |
441 | ||
442 | static inline void int128_addto(Int128 *a, Int128 b) | |
443 | { | |
444 | *a = int128_add(*a, b); | |
445 | } | |
446 | ||
447 | static inline void int128_subfrom(Int128 *a, Int128 b) | |
448 | { | |
449 | *a = int128_sub(*a, b); | |
450 | } | |
451 | ||
2484cd9c MF |
452 | static inline Int128 bswap128(Int128 a) |
453 | { | |
454 | return int128_make128(bswap64(a.hi), bswap64(a.lo)); | |
455 | } | |
456 | ||
4724bbd2 LMC |
457 | static inline int clz128(Int128 a) |
458 | { | |
459 | if (a.hi) { | |
460 | return __builtin_clzll(a.hi); | |
461 | } else { | |
462 | return (a.lo) ? __builtin_clzll(a.lo) + 64 : 128; | |
463 | } | |
464 | } | |
465 | ||
e9d07601 FP |
466 | Int128 int128_divu(Int128, Int128); |
467 | Int128 int128_remu(Int128, Int128); | |
468 | Int128 int128_divs(Int128, Int128); | |
469 | Int128 int128_rems(Int128, Int128); | |
b959822c | 470 | #endif /* CONFIG_INT128 && !CONFIG_TCG_INTERPRETER */ |
2484cd9c MF |
471 | |
472 | static inline void bswap128s(Int128 *s) | |
473 | { | |
474 | *s = bswap128(*s); | |
475 | } | |
476 | ||
e9d07601 | 477 | #define UINT128_MAX int128_make128(~0LL, ~0LL) |
bea59230 MF |
478 | #define INT128_MAX int128_make128(UINT64_MAX, INT64_MAX) |
479 | #define INT128_MIN int128_make128(0, INT64_MIN) | |
e9d07601 | 480 | |
b959822c RH |
481 | /* |
482 | * When compiler supports a 128-bit type, define a combination of | |
483 | * a possible structure and the native types. Ease parameter passing | |
484 | * via use of the transparent union extension. | |
485 | */ | |
6479dd74 | 486 | #ifdef CONFIG_INT128_TYPE |
b959822c | 487 | typedef union { |
b959822c | 488 | __uint128_t u; |
c4075353 RH |
489 | __int128_t i; |
490 | Int128 s; | |
b959822c RH |
491 | } Int128Alias __attribute__((transparent_union)); |
492 | #else | |
493 | typedef Int128 Int128Alias; | |
6479dd74 | 494 | #endif /* CONFIG_INT128_TYPE */ |
b959822c | 495 | |
0846beb3 | 496 | #endif /* INT128_H */ |