]>
Commit | Line | Data |
---|---|---|
b7cd3db6 AK |
1 | #ifndef INT128_H |
2 | #define INT128_H | |
3 | ||
7ebee43e | 4 | #include "qemu/bswap.h" |
0846beb3 | 5 | |
2484cd9c | 6 | #ifdef CONFIG_INT128 |
0846beb3 RH |
7 | typedef __int128_t Int128; |
8 | ||
9 | static inline Int128 int128_make64(uint64_t a) | |
10 | { | |
11 | return a; | |
12 | } | |
13 | ||
703235a3 PM |
14 | static inline Int128 int128_makes64(int64_t a) |
15 | { | |
16 | return a; | |
17 | } | |
18 | ||
1edaeee0 RH |
19 | static inline Int128 int128_make128(uint64_t lo, uint64_t hi) |
20 | { | |
21 | return (__uint128_t)hi << 64 | lo; | |
22 | } | |
23 | ||
0846beb3 RH |
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 | ||
1c469373 FP |
61 | static inline Int128 int128_not(Int128 a) |
62 | { | |
63 | return ~a; | |
64 | } | |
65 | ||
0846beb3 RH |
66 | static inline Int128 int128_and(Int128 a, Int128 b) |
67 | { | |
68 | return a & b; | |
69 | } | |
70 | ||
08895cda RH |
71 | static inline Int128 int128_or(Int128 a, Int128 b) |
72 | { | |
73 | return a | b; | |
74 | } | |
75 | ||
1c469373 FP |
76 | static inline Int128 int128_xor(Int128 a, Int128 b) |
77 | { | |
78 | return a ^ b; | |
79 | } | |
80 | ||
0846beb3 RH |
81 | static inline Int128 int128_rshift(Int128 a, int n) |
82 | { | |
83 | return a >> n; | |
84 | } | |
85 | ||
5be4dd04 RH |
86 | static inline Int128 int128_lshift(Int128 a, int n) |
87 | { | |
88 | return a << n; | |
89 | } | |
90 | ||
0846beb3 RH |
91 | static inline Int128 int128_add(Int128 a, Int128 b) |
92 | { | |
93 | return a + b; | |
94 | } | |
95 | ||
96 | static inline Int128 int128_neg(Int128 a) | |
97 | { | |
98 | return -a; | |
99 | } | |
100 | ||
101 | static inline Int128 int128_sub(Int128 a, Int128 b) | |
102 | { | |
103 | return a - b; | |
104 | } | |
105 | ||
106 | static inline bool int128_nonneg(Int128 a) | |
107 | { | |
108 | return a >= 0; | |
109 | } | |
110 | ||
111 | static inline bool int128_eq(Int128 a, Int128 b) | |
112 | { | |
113 | return a == b; | |
114 | } | |
115 | ||
116 | static inline bool int128_ne(Int128 a, Int128 b) | |
117 | { | |
118 | return a != b; | |
119 | } | |
120 | ||
121 | static inline bool int128_ge(Int128 a, Int128 b) | |
122 | { | |
123 | return a >= b; | |
124 | } | |
125 | ||
126 | static inline bool int128_lt(Int128 a, Int128 b) | |
127 | { | |
128 | return a < b; | |
129 | } | |
130 | ||
131 | static inline bool int128_le(Int128 a, Int128 b) | |
132 | { | |
133 | return a <= b; | |
134 | } | |
135 | ||
136 | static inline bool int128_gt(Int128 a, Int128 b) | |
137 | { | |
138 | return a > b; | |
139 | } | |
140 | ||
141 | static inline bool int128_nz(Int128 a) | |
142 | { | |
143 | return a != 0; | |
144 | } | |
145 | ||
146 | static inline Int128 int128_min(Int128 a, Int128 b) | |
147 | { | |
148 | return a < b ? a : b; | |
149 | } | |
150 | ||
151 | static inline Int128 int128_max(Int128 a, Int128 b) | |
152 | { | |
153 | return a > b ? a : b; | |
154 | } | |
155 | ||
156 | static inline void int128_addto(Int128 *a, Int128 b) | |
157 | { | |
158 | *a += b; | |
159 | } | |
160 | ||
161 | static inline void int128_subfrom(Int128 *a, Int128 b) | |
162 | { | |
163 | *a -= b; | |
164 | } | |
165 | ||
7ebee43e RH |
166 | static inline Int128 bswap128(Int128 a) |
167 | { | |
2484cd9c MF |
168 | #if __has_builtin(__builtin_bswap128) |
169 | return __builtin_bswap128(a); | |
170 | #else | |
7ebee43e | 171 | return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a))); |
2484cd9c | 172 | #endif |
7ebee43e RH |
173 | } |
174 | ||
e9d07601 FP |
175 | static inline Int128 int128_divu(Int128 a, Int128 b) |
176 | { | |
177 | return (__uint128_t)a / (__uint128_t)b; | |
178 | } | |
179 | ||
180 | static inline Int128 int128_remu(Int128 a, Int128 b) | |
181 | { | |
182 | return (__uint128_t)a % (__uint128_t)b; | |
183 | } | |
184 | ||
185 | static inline Int128 int128_divs(Int128 a, Int128 b) | |
186 | { | |
187 | return a / b; | |
188 | } | |
189 | ||
190 | static inline Int128 int128_rems(Int128 a, Int128 b) | |
191 | { | |
192 | return a % b; | |
193 | } | |
194 | ||
0846beb3 | 195 | #else /* !CONFIG_INT128 */ |
6046c620 | 196 | |
b7cd3db6 AK |
197 | typedef struct Int128 Int128; |
198 | ||
181b0c33 MF |
199 | /* |
200 | * We guarantee that the in-memory byte representation of an | |
201 | * Int128 is that of a host-endian-order 128-bit integer | |
202 | * (whether using this struct or the __int128_t version of the type). | |
203 | * Some code using this type relies on this (eg when copying it into | |
204 | * guest memory or a gdb protocol buffer, or by using Int128 in | |
205 | * a union with other integer types). | |
206 | */ | |
b7cd3db6 | 207 | struct Int128 { |
e03b5686 | 208 | #if HOST_BIG_ENDIAN |
181b0c33 MF |
209 | int64_t hi; |
210 | uint64_t lo; | |
211 | #else | |
b7cd3db6 AK |
212 | uint64_t lo; |
213 | int64_t hi; | |
181b0c33 | 214 | #endif |
b7cd3db6 AK |
215 | }; |
216 | ||
217 | static inline Int128 int128_make64(uint64_t a) | |
218 | { | |
181b0c33 | 219 | return (Int128) { .lo = a, .hi = 0 }; |
b7cd3db6 AK |
220 | } |
221 | ||
703235a3 PM |
222 | static inline Int128 int128_makes64(int64_t a) |
223 | { | |
181b0c33 | 224 | return (Int128) { .lo = a, .hi = a >> 63 }; |
703235a3 PM |
225 | } |
226 | ||
1edaeee0 RH |
227 | static inline Int128 int128_make128(uint64_t lo, uint64_t hi) |
228 | { | |
181b0c33 | 229 | return (Int128) { .lo = lo, .hi = hi }; |
1edaeee0 RH |
230 | } |
231 | ||
b7cd3db6 AK |
232 | static inline uint64_t int128_get64(Int128 a) |
233 | { | |
234 | assert(!a.hi); | |
235 | return a.lo; | |
236 | } | |
237 | ||
258dfaaa RH |
238 | static inline uint64_t int128_getlo(Int128 a) |
239 | { | |
240 | return a.lo; | |
241 | } | |
242 | ||
243 | static inline int64_t int128_gethi(Int128 a) | |
244 | { | |
245 | return a.hi; | |
246 | } | |
247 | ||
b7cd3db6 AK |
248 | static inline Int128 int128_zero(void) |
249 | { | |
250 | return int128_make64(0); | |
251 | } | |
252 | ||
253 | static inline Int128 int128_one(void) | |
254 | { | |
255 | return int128_make64(1); | |
256 | } | |
257 | ||
258 | static inline Int128 int128_2_64(void) | |
259 | { | |
181b0c33 | 260 | return int128_make128(0, 1); |
b7cd3db6 AK |
261 | } |
262 | ||
12e1129b AK |
263 | static inline Int128 int128_exts64(int64_t a) |
264 | { | |
181b0c33 | 265 | return int128_make128(a, (a < 0) ? -1 : 0); |
12e1129b AK |
266 | } |
267 | ||
1c469373 FP |
268 | static inline Int128 int128_not(Int128 a) |
269 | { | |
270 | return int128_make128(~a.lo, ~a.hi); | |
271 | } | |
272 | ||
052e87b0 PB |
273 | static inline Int128 int128_and(Int128 a, Int128 b) |
274 | { | |
181b0c33 | 275 | return int128_make128(a.lo & b.lo, a.hi & b.hi); |
052e87b0 PB |
276 | } |
277 | ||
08895cda RH |
278 | static inline Int128 int128_or(Int128 a, Int128 b) |
279 | { | |
181b0c33 | 280 | return int128_make128(a.lo | b.lo, a.hi | b.hi); |
08895cda RH |
281 | } |
282 | ||
1c469373 FP |
283 | static inline Int128 int128_xor(Int128 a, Int128 b) |
284 | { | |
285 | return int128_make128(a.lo ^ b.lo, a.hi ^ b.hi); | |
286 | } | |
287 | ||
052e87b0 PB |
288 | static inline Int128 int128_rshift(Int128 a, int n) |
289 | { | |
290 | int64_t h; | |
291 | if (!n) { | |
292 | return a; | |
293 | } | |
294 | h = a.hi >> (n & 63); | |
295 | if (n >= 64) { | |
1edaeee0 | 296 | return int128_make128(h, h >> 63); |
052e87b0 | 297 | } else { |
1edaeee0 | 298 | return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); |
052e87b0 PB |
299 | } |
300 | } | |
301 | ||
5be4dd04 RH |
302 | static inline Int128 int128_lshift(Int128 a, int n) |
303 | { | |
304 | uint64_t l = a.lo << (n & 63); | |
305 | if (n >= 64) { | |
306 | return int128_make128(0, l); | |
307 | } else if (n > 0) { | |
308 | return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n))); | |
309 | } | |
310 | return a; | |
311 | } | |
312 | ||
b7cd3db6 AK |
313 | static inline Int128 int128_add(Int128 a, Int128 b) |
314 | { | |
6046c620 PB |
315 | uint64_t lo = a.lo + b.lo; |
316 | ||
317 | /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, | |
318 | * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. | |
319 | * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. | |
320 | * | |
321 | * So the carry is lo < a.lo. | |
322 | */ | |
1edaeee0 | 323 | return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); |
b7cd3db6 AK |
324 | } |
325 | ||
326 | static inline Int128 int128_neg(Int128 a) | |
327 | { | |
6046c620 | 328 | uint64_t lo = -a.lo; |
1edaeee0 | 329 | return int128_make128(lo, ~(uint64_t)a.hi + !lo); |
b7cd3db6 AK |
330 | } |
331 | ||
332 | static inline Int128 int128_sub(Int128 a, Int128 b) | |
333 | { | |
1edaeee0 | 334 | return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); |
b7cd3db6 AK |
335 | } |
336 | ||
337 | static inline bool int128_nonneg(Int128 a) | |
338 | { | |
339 | return a.hi >= 0; | |
340 | } | |
341 | ||
342 | static inline bool int128_eq(Int128 a, Int128 b) | |
343 | { | |
344 | return a.lo == b.lo && a.hi == b.hi; | |
345 | } | |
346 | ||
347 | static inline bool int128_ne(Int128 a, Int128 b) | |
348 | { | |
349 | return !int128_eq(a, b); | |
350 | } | |
351 | ||
352 | static inline bool int128_ge(Int128 a, Int128 b) | |
353 | { | |
6046c620 | 354 | return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); |
b7cd3db6 AK |
355 | } |
356 | ||
357 | static inline bool int128_lt(Int128 a, Int128 b) | |
358 | { | |
359 | return !int128_ge(a, b); | |
360 | } | |
361 | ||
362 | static inline bool int128_le(Int128 a, Int128 b) | |
363 | { | |
364 | return int128_ge(b, a); | |
365 | } | |
366 | ||
367 | static inline bool int128_gt(Int128 a, Int128 b) | |
368 | { | |
369 | return !int128_le(a, b); | |
370 | } | |
371 | ||
372 | static inline bool int128_nz(Int128 a) | |
373 | { | |
374 | return a.lo || a.hi; | |
375 | } | |
376 | ||
377 | static inline Int128 int128_min(Int128 a, Int128 b) | |
378 | { | |
379 | return int128_le(a, b) ? a : b; | |
380 | } | |
381 | ||
382 | static inline Int128 int128_max(Int128 a, Int128 b) | |
383 | { | |
384 | return int128_ge(a, b) ? a : b; | |
385 | } | |
386 | ||
387 | static inline void int128_addto(Int128 *a, Int128 b) | |
388 | { | |
389 | *a = int128_add(*a, b); | |
390 | } | |
391 | ||
392 | static inline void int128_subfrom(Int128 *a, Int128 b) | |
393 | { | |
394 | *a = int128_sub(*a, b); | |
395 | } | |
396 | ||
2484cd9c MF |
397 | static inline Int128 bswap128(Int128 a) |
398 | { | |
399 | return int128_make128(bswap64(a.hi), bswap64(a.lo)); | |
400 | } | |
401 | ||
e9d07601 FP |
402 | Int128 int128_divu(Int128, Int128); |
403 | Int128 int128_remu(Int128, Int128); | |
404 | Int128 int128_divs(Int128, Int128); | |
405 | Int128 int128_rems(Int128, Int128); | |
406 | ||
0846beb3 | 407 | #endif /* CONFIG_INT128 */ |
2484cd9c MF |
408 | |
409 | static inline void bswap128s(Int128 *s) | |
410 | { | |
411 | *s = bswap128(*s); | |
412 | } | |
413 | ||
e9d07601 FP |
414 | #define UINT128_MAX int128_make128(~0LL, ~0LL) |
415 | ||
0846beb3 | 416 | #endif /* INT128_H */ |