1 | #ifndef INT128_H |
2 | #define INT128_H |
3 | |
4 | #ifdef CONFIG_INT128 |
5 | #include "qemu/bswap.h" |
6 | |
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_make128(uint64_t lo, uint64_t hi) |
15 | { |
16 | return (__uint128_t)hi << 64 | lo; |
17 | } |
18 | |
19 | static inline uint64_t int128_get64(Int128 a) |
20 | { |
21 | uint64_t r = a; |
22 | assert(r == a); |
23 | return r; |
24 | } |
25 | |
26 | static inline uint64_t int128_getlo(Int128 a) |
27 | { |
28 | return a; |
29 | } |
30 | |
31 | static inline int64_t int128_gethi(Int128 a) |
32 | { |
33 | return a >> 64; |
34 | } |
35 | |
36 | static inline Int128 int128_zero(void) |
37 | { |
38 | return 0; |
39 | } |
40 | |
41 | static inline Int128 int128_one(void) |
42 | { |
43 | return 1; |
44 | } |
45 | |
46 | static inline Int128 int128_2_64(void) |
47 | { |
48 | return (Int128)1 << 64; |
49 | } |
50 | |
51 | static inline Int128 int128_exts64(int64_t a) |
52 | { |
53 | return a; |
54 | } |
55 | |
56 | static inline Int128 int128_and(Int128 a, Int128 b) |
57 | { |
58 | return a & b; |
59 | } |
60 | |
61 | static inline Int128 int128_rshift(Int128 a, int n) |
62 | { |
63 | return a >> n; |
64 | } |
65 | |
66 | static inline Int128 int128_add(Int128 a, Int128 b) |
67 | { |
68 | return a + b; |
69 | } |
70 | |
71 | static inline Int128 int128_neg(Int128 a) |
72 | { |
73 | return -a; |
74 | } |
75 | |
76 | static inline Int128 int128_sub(Int128 a, Int128 b) |
77 | { |
78 | return a - b; |
79 | } |
80 | |
81 | static inline bool int128_nonneg(Int128 a) |
82 | { |
83 | return a >= 0; |
84 | } |
85 | |
86 | static inline bool int128_eq(Int128 a, Int128 b) |
87 | { |
88 | return a == b; |
89 | } |
90 | |
91 | static inline bool int128_ne(Int128 a, Int128 b) |
92 | { |
93 | return a != b; |
94 | } |
95 | |
96 | static inline bool int128_ge(Int128 a, Int128 b) |
97 | { |
98 | return a >= b; |
99 | } |
100 | |
101 | static inline bool int128_lt(Int128 a, Int128 b) |
102 | { |
103 | return a < b; |
104 | } |
105 | |
106 | static inline bool int128_le(Int128 a, Int128 b) |
107 | { |
108 | return a <= b; |
109 | } |
110 | |
111 | static inline bool int128_gt(Int128 a, Int128 b) |
112 | { |
113 | return a > b; |
114 | } |
115 | |
116 | static inline bool int128_nz(Int128 a) |
117 | { |
118 | return a != 0; |
119 | } |
120 | |
121 | static inline Int128 int128_min(Int128 a, Int128 b) |
122 | { |
123 | return a < b ? a : b; |
124 | } |
125 | |
126 | static inline Int128 int128_max(Int128 a, Int128 b) |
127 | { |
128 | return a > b ? a : b; |
129 | } |
130 | |
131 | static inline void int128_addto(Int128 *a, Int128 b) |
132 | { |
133 | *a += b; |
134 | } |
135 | |
136 | static inline void int128_subfrom(Int128 *a, Int128 b) |
137 | { |
138 | *a -= b; |
139 | } |
140 | |
141 | static inline Int128 bswap128(Int128 a) |
142 | { |
143 | return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a))); |
144 | } |
145 | |
146 | #else /* !CONFIG_INT128 */ |
147 | |
148 | typedef struct Int128 Int128; |
149 | |
150 | struct Int128 { |
151 | uint64_t lo; |
152 | int64_t hi; |
153 | }; |
154 | |
155 | static inline Int128 int128_make64(uint64_t a) |
156 | { |
157 | return (Int128) { a, 0 }; |
158 | } |
159 | |
160 | static inline Int128 int128_make128(uint64_t lo, uint64_t hi) |
161 | { |
162 | return (Int128) { lo, hi }; |
163 | } |
164 | |
165 | static inline uint64_t int128_get64(Int128 a) |
166 | { |
167 | assert(!a.hi); |
168 | return a.lo; |
169 | } |
170 | |
171 | static inline uint64_t int128_getlo(Int128 a) |
172 | { |
173 | return a.lo; |
174 | } |
175 | |
176 | static inline int64_t int128_gethi(Int128 a) |
177 | { |
178 | return a.hi; |
179 | } |
180 | |
181 | static inline Int128 int128_zero(void) |
182 | { |
183 | return int128_make64(0); |
184 | } |
185 | |
186 | static inline Int128 int128_one(void) |
187 | { |
188 | return int128_make64(1); |
189 | } |
190 | |
191 | static inline Int128 int128_2_64(void) |
192 | { |
193 | return (Int128) { 0, 1 }; |
194 | } |
195 | |
196 | static inline Int128 int128_exts64(int64_t a) |
197 | { |
198 | return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 }; |
199 | } |
200 | |
201 | static inline Int128 int128_and(Int128 a, Int128 b) |
202 | { |
203 | return (Int128) { a.lo & b.lo, a.hi & b.hi }; |
204 | } |
205 | |
206 | static inline Int128 int128_rshift(Int128 a, int n) |
207 | { |
208 | int64_t h; |
209 | if (!n) { |
210 | return a; |
211 | } |
212 | h = a.hi >> (n & 63); |
213 | if (n >= 64) { |
214 | return int128_make128(h, h >> 63); |
215 | } else { |
216 | return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); |
217 | } |
218 | } |
219 | |
220 | static inline Int128 int128_add(Int128 a, Int128 b) |
221 | { |
222 | uint64_t lo = a.lo + b.lo; |
223 | |
224 | /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, |
225 | * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. |
226 | * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. |
227 | * |
228 | * So the carry is lo < a.lo. |
229 | */ |
230 | return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); |
231 | } |
232 | |
233 | static inline Int128 int128_neg(Int128 a) |
234 | { |
235 | uint64_t lo = -a.lo; |
236 | return int128_make128(lo, ~(uint64_t)a.hi + !lo); |
237 | } |
238 | |
239 | static inline Int128 int128_sub(Int128 a, Int128 b) |
240 | { |
241 | return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); |
242 | } |
243 | |
244 | static inline bool int128_nonneg(Int128 a) |
245 | { |
246 | return a.hi >= 0; |
247 | } |
248 | |
249 | static inline bool int128_eq(Int128 a, Int128 b) |
250 | { |
251 | return a.lo == b.lo && a.hi == b.hi; |
252 | } |
253 | |
254 | static inline bool int128_ne(Int128 a, Int128 b) |
255 | { |
256 | return !int128_eq(a, b); |
257 | } |
258 | |
259 | static inline bool int128_ge(Int128 a, Int128 b) |
260 | { |
261 | return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); |
262 | } |
263 | |
264 | static inline bool int128_lt(Int128 a, Int128 b) |
265 | { |
266 | return !int128_ge(a, b); |
267 | } |
268 | |
269 | static inline bool int128_le(Int128 a, Int128 b) |
270 | { |
271 | return int128_ge(b, a); |
272 | } |
273 | |
274 | static inline bool int128_gt(Int128 a, Int128 b) |
275 | { |
276 | return !int128_le(a, b); |
277 | } |
278 | |
279 | static inline bool int128_nz(Int128 a) |
280 | { |
281 | return a.lo || a.hi; |
282 | } |
283 | |
284 | static inline Int128 int128_min(Int128 a, Int128 b) |
285 | { |
286 | return int128_le(a, b) ? a : b; |
287 | } |
288 | |
289 | static inline Int128 int128_max(Int128 a, Int128 b) |
290 | { |
291 | return int128_ge(a, b) ? a : b; |
292 | } |
293 | |
294 | static inline void int128_addto(Int128 *a, Int128 b) |
295 | { |
296 | *a = int128_add(*a, b); |
297 | } |
298 | |
299 | static inline void int128_subfrom(Int128 *a, Int128 b) |
300 | { |
301 | *a = int128_sub(*a, b); |
302 | } |
303 | |
304 | #endif /* CONFIG_INT128 */ |
305 | #endif /* INT128_H */ |
306 | |