]>
Commit | Line | Data |
---|---|---|
b7cd3db6 AK |
1 | #ifndef INT128_H |
2 | #define INT128_H | |
3 | ||
0846beb3 | 4 | #ifdef CONFIG_INT128 |
7ebee43e | 5 | #include "qemu/bswap.h" |
0846beb3 RH |
6 | |
7 | typedef __int128_t Int128; | |
8 | ||
9 | static inline Int128 int128_make64(uint64_t a) | |
10 | { | |
11 | return a; | |
12 | } | |
13 | ||
1edaeee0 RH |
14 | static inline Int128 int128_make128(uint64_t lo, uint64_t hi) |
15 | { | |
16 | return (__uint128_t)hi << 64 | lo; | |
17 | } | |
18 | ||
0846beb3 RH |
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 | ||
7ebee43e RH |
141 | static inline Int128 bswap128(Int128 a) |
142 | { | |
143 | return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a))); | |
144 | } | |
145 | ||
0846beb3 | 146 | #else /* !CONFIG_INT128 */ |
6046c620 | 147 | |
b7cd3db6 AK |
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 | ||
1edaeee0 RH |
160 | static inline Int128 int128_make128(uint64_t lo, uint64_t hi) |
161 | { | |
162 | return (Int128) { lo, hi }; | |
163 | } | |
164 | ||
b7cd3db6 AK |
165 | static inline uint64_t int128_get64(Int128 a) |
166 | { | |
167 | assert(!a.hi); | |
168 | return a.lo; | |
169 | } | |
170 | ||
258dfaaa RH |
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 | ||
b7cd3db6 AK |
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 | ||
12e1129b AK |
196 | static inline Int128 int128_exts64(int64_t a) |
197 | { | |
198 | return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 }; | |
199 | } | |
200 | ||
052e87b0 PB |
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) { | |
1edaeee0 | 214 | return int128_make128(h, h >> 63); |
052e87b0 | 215 | } else { |
1edaeee0 | 216 | return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); |
052e87b0 PB |
217 | } |
218 | } | |
219 | ||
b7cd3db6 AK |
220 | static inline Int128 int128_add(Int128 a, Int128 b) |
221 | { | |
6046c620 PB |
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 | */ | |
1edaeee0 | 230 | return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); |
b7cd3db6 AK |
231 | } |
232 | ||
233 | static inline Int128 int128_neg(Int128 a) | |
234 | { | |
6046c620 | 235 | uint64_t lo = -a.lo; |
1edaeee0 | 236 | return int128_make128(lo, ~(uint64_t)a.hi + !lo); |
b7cd3db6 AK |
237 | } |
238 | ||
239 | static inline Int128 int128_sub(Int128 a, Int128 b) | |
240 | { | |
1edaeee0 | 241 | return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); |
b7cd3db6 AK |
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 | { | |
6046c620 | 261 | return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); |
b7cd3db6 AK |
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 | ||
0846beb3 RH |
304 | #endif /* CONFIG_INT128 */ |
305 | #endif /* INT128_H */ |