1b7cd3db6SAvi Kivity #ifndef INT128_H 2b7cd3db6SAvi Kivity #define INT128_H 3b7cd3db6SAvi Kivity 40846beb3SRichard Henderson #ifdef CONFIG_INT128 50846beb3SRichard Henderson 60846beb3SRichard Henderson typedef __int128_t Int128; 70846beb3SRichard Henderson 80846beb3SRichard Henderson static inline Int128 int128_make64(uint64_t a) 90846beb3SRichard Henderson { 100846beb3SRichard Henderson return a; 110846beb3SRichard Henderson } 120846beb3SRichard Henderson 13*1edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi) 14*1edaeee0SRichard Henderson { 15*1edaeee0SRichard Henderson return (__uint128_t)hi << 64 | lo; 16*1edaeee0SRichard Henderson } 17*1edaeee0SRichard Henderson 180846beb3SRichard Henderson static inline uint64_t int128_get64(Int128 a) 190846beb3SRichard Henderson { 200846beb3SRichard Henderson uint64_t r = a; 210846beb3SRichard Henderson assert(r == a); 220846beb3SRichard Henderson return r; 230846beb3SRichard Henderson } 240846beb3SRichard Henderson 250846beb3SRichard Henderson static inline uint64_t int128_getlo(Int128 a) 260846beb3SRichard Henderson { 270846beb3SRichard Henderson return a; 280846beb3SRichard Henderson } 290846beb3SRichard Henderson 300846beb3SRichard Henderson static inline int64_t int128_gethi(Int128 a) 310846beb3SRichard Henderson { 320846beb3SRichard Henderson return a >> 64; 330846beb3SRichard Henderson } 340846beb3SRichard Henderson 350846beb3SRichard Henderson static inline Int128 int128_zero(void) 360846beb3SRichard Henderson { 370846beb3SRichard Henderson return 0; 380846beb3SRichard Henderson } 390846beb3SRichard Henderson 400846beb3SRichard Henderson static inline Int128 int128_one(void) 410846beb3SRichard Henderson { 420846beb3SRichard Henderson return 1; 430846beb3SRichard Henderson } 440846beb3SRichard Henderson 450846beb3SRichard Henderson static inline Int128 int128_2_64(void) 460846beb3SRichard Henderson { 470846beb3SRichard Henderson return (Int128)1 << 64; 480846beb3SRichard Henderson } 490846beb3SRichard Henderson 500846beb3SRichard Henderson static inline Int128 int128_exts64(int64_t a) 510846beb3SRichard Henderson { 520846beb3SRichard Henderson return a; 530846beb3SRichard Henderson } 540846beb3SRichard Henderson 550846beb3SRichard Henderson static inline Int128 int128_and(Int128 a, Int128 b) 560846beb3SRichard Henderson { 570846beb3SRichard Henderson return a & b; 580846beb3SRichard Henderson } 590846beb3SRichard Henderson 600846beb3SRichard Henderson static inline Int128 int128_rshift(Int128 a, int n) 610846beb3SRichard Henderson { 620846beb3SRichard Henderson return a >> n; 630846beb3SRichard Henderson } 640846beb3SRichard Henderson 650846beb3SRichard Henderson static inline Int128 int128_add(Int128 a, Int128 b) 660846beb3SRichard Henderson { 670846beb3SRichard Henderson return a + b; 680846beb3SRichard Henderson } 690846beb3SRichard Henderson 700846beb3SRichard Henderson static inline Int128 int128_neg(Int128 a) 710846beb3SRichard Henderson { 720846beb3SRichard Henderson return -a; 730846beb3SRichard Henderson } 740846beb3SRichard Henderson 750846beb3SRichard Henderson static inline Int128 int128_sub(Int128 a, Int128 b) 760846beb3SRichard Henderson { 770846beb3SRichard Henderson return a - b; 780846beb3SRichard Henderson } 790846beb3SRichard Henderson 800846beb3SRichard Henderson static inline bool int128_nonneg(Int128 a) 810846beb3SRichard Henderson { 820846beb3SRichard Henderson return a >= 0; 830846beb3SRichard Henderson } 840846beb3SRichard Henderson 850846beb3SRichard Henderson static inline bool int128_eq(Int128 a, Int128 b) 860846beb3SRichard Henderson { 870846beb3SRichard Henderson return a == b; 880846beb3SRichard Henderson } 890846beb3SRichard Henderson 900846beb3SRichard Henderson static inline bool int128_ne(Int128 a, Int128 b) 910846beb3SRichard Henderson { 920846beb3SRichard Henderson return a != b; 930846beb3SRichard Henderson } 940846beb3SRichard Henderson 950846beb3SRichard Henderson static inline bool int128_ge(Int128 a, Int128 b) 960846beb3SRichard Henderson { 970846beb3SRichard Henderson return a >= b; 980846beb3SRichard Henderson } 990846beb3SRichard Henderson 1000846beb3SRichard Henderson static inline bool int128_lt(Int128 a, Int128 b) 1010846beb3SRichard Henderson { 1020846beb3SRichard Henderson return a < b; 1030846beb3SRichard Henderson } 1040846beb3SRichard Henderson 1050846beb3SRichard Henderson static inline bool int128_le(Int128 a, Int128 b) 1060846beb3SRichard Henderson { 1070846beb3SRichard Henderson return a <= b; 1080846beb3SRichard Henderson } 1090846beb3SRichard Henderson 1100846beb3SRichard Henderson static inline bool int128_gt(Int128 a, Int128 b) 1110846beb3SRichard Henderson { 1120846beb3SRichard Henderson return a > b; 1130846beb3SRichard Henderson } 1140846beb3SRichard Henderson 1150846beb3SRichard Henderson static inline bool int128_nz(Int128 a) 1160846beb3SRichard Henderson { 1170846beb3SRichard Henderson return a != 0; 1180846beb3SRichard Henderson } 1190846beb3SRichard Henderson 1200846beb3SRichard Henderson static inline Int128 int128_min(Int128 a, Int128 b) 1210846beb3SRichard Henderson { 1220846beb3SRichard Henderson return a < b ? a : b; 1230846beb3SRichard Henderson } 1240846beb3SRichard Henderson 1250846beb3SRichard Henderson static inline Int128 int128_max(Int128 a, Int128 b) 1260846beb3SRichard Henderson { 1270846beb3SRichard Henderson return a > b ? a : b; 1280846beb3SRichard Henderson } 1290846beb3SRichard Henderson 1300846beb3SRichard Henderson static inline void int128_addto(Int128 *a, Int128 b) 1310846beb3SRichard Henderson { 1320846beb3SRichard Henderson *a += b; 1330846beb3SRichard Henderson } 1340846beb3SRichard Henderson 1350846beb3SRichard Henderson static inline void int128_subfrom(Int128 *a, Int128 b) 1360846beb3SRichard Henderson { 1370846beb3SRichard Henderson *a -= b; 1380846beb3SRichard Henderson } 1390846beb3SRichard Henderson 1400846beb3SRichard Henderson #else /* !CONFIG_INT128 */ 1416046c620SPaolo Bonzini 142b7cd3db6SAvi Kivity typedef struct Int128 Int128; 143b7cd3db6SAvi Kivity 144b7cd3db6SAvi Kivity struct Int128 { 145b7cd3db6SAvi Kivity uint64_t lo; 146b7cd3db6SAvi Kivity int64_t hi; 147b7cd3db6SAvi Kivity }; 148b7cd3db6SAvi Kivity 149b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a) 150b7cd3db6SAvi Kivity { 151b7cd3db6SAvi Kivity return (Int128) { a, 0 }; 152b7cd3db6SAvi Kivity } 153b7cd3db6SAvi Kivity 154*1edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi) 155*1edaeee0SRichard Henderson { 156*1edaeee0SRichard Henderson return (Int128) { lo, hi }; 157*1edaeee0SRichard Henderson } 158*1edaeee0SRichard Henderson 159b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a) 160b7cd3db6SAvi Kivity { 161b7cd3db6SAvi Kivity assert(!a.hi); 162b7cd3db6SAvi Kivity return a.lo; 163b7cd3db6SAvi Kivity } 164b7cd3db6SAvi Kivity 165258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a) 166258dfaaaSRichard Henderson { 167258dfaaaSRichard Henderson return a.lo; 168258dfaaaSRichard Henderson } 169258dfaaaSRichard Henderson 170258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a) 171258dfaaaSRichard Henderson { 172258dfaaaSRichard Henderson return a.hi; 173258dfaaaSRichard Henderson } 174258dfaaaSRichard Henderson 175b7cd3db6SAvi Kivity static inline Int128 int128_zero(void) 176b7cd3db6SAvi Kivity { 177b7cd3db6SAvi Kivity return int128_make64(0); 178b7cd3db6SAvi Kivity } 179b7cd3db6SAvi Kivity 180b7cd3db6SAvi Kivity static inline Int128 int128_one(void) 181b7cd3db6SAvi Kivity { 182b7cd3db6SAvi Kivity return int128_make64(1); 183b7cd3db6SAvi Kivity } 184b7cd3db6SAvi Kivity 185b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void) 186b7cd3db6SAvi Kivity { 187b7cd3db6SAvi Kivity return (Int128) { 0, 1 }; 188b7cd3db6SAvi Kivity } 189b7cd3db6SAvi Kivity 19012e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a) 19112e1129bSAlexey Kardashevskiy { 19212e1129bSAlexey Kardashevskiy return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 }; 19312e1129bSAlexey Kardashevskiy } 19412e1129bSAlexey Kardashevskiy 195052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b) 196052e87b0SPaolo Bonzini { 197052e87b0SPaolo Bonzini return (Int128) { a.lo & b.lo, a.hi & b.hi }; 198052e87b0SPaolo Bonzini } 199052e87b0SPaolo Bonzini 200052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n) 201052e87b0SPaolo Bonzini { 202052e87b0SPaolo Bonzini int64_t h; 203052e87b0SPaolo Bonzini if (!n) { 204052e87b0SPaolo Bonzini return a; 205052e87b0SPaolo Bonzini } 206052e87b0SPaolo Bonzini h = a.hi >> (n & 63); 207052e87b0SPaolo Bonzini if (n >= 64) { 208*1edaeee0SRichard Henderson return int128_make128(h, h >> 63); 209052e87b0SPaolo Bonzini } else { 210*1edaeee0SRichard Henderson return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); 211052e87b0SPaolo Bonzini } 212052e87b0SPaolo Bonzini } 213052e87b0SPaolo Bonzini 214b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b) 215b7cd3db6SAvi Kivity { 2166046c620SPaolo Bonzini uint64_t lo = a.lo + b.lo; 2176046c620SPaolo Bonzini 2186046c620SPaolo Bonzini /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, 2196046c620SPaolo Bonzini * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. 2206046c620SPaolo Bonzini * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. 2216046c620SPaolo Bonzini * 2226046c620SPaolo Bonzini * So the carry is lo < a.lo. 2236046c620SPaolo Bonzini */ 224*1edaeee0SRichard Henderson return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); 225b7cd3db6SAvi Kivity } 226b7cd3db6SAvi Kivity 227b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a) 228b7cd3db6SAvi Kivity { 2296046c620SPaolo Bonzini uint64_t lo = -a.lo; 230*1edaeee0SRichard Henderson return int128_make128(lo, ~(uint64_t)a.hi + !lo); 231b7cd3db6SAvi Kivity } 232b7cd3db6SAvi Kivity 233b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b) 234b7cd3db6SAvi Kivity { 235*1edaeee0SRichard Henderson return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); 236b7cd3db6SAvi Kivity } 237b7cd3db6SAvi Kivity 238b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a) 239b7cd3db6SAvi Kivity { 240b7cd3db6SAvi Kivity return a.hi >= 0; 241b7cd3db6SAvi Kivity } 242b7cd3db6SAvi Kivity 243b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b) 244b7cd3db6SAvi Kivity { 245b7cd3db6SAvi Kivity return a.lo == b.lo && a.hi == b.hi; 246b7cd3db6SAvi Kivity } 247b7cd3db6SAvi Kivity 248b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b) 249b7cd3db6SAvi Kivity { 250b7cd3db6SAvi Kivity return !int128_eq(a, b); 251b7cd3db6SAvi Kivity } 252b7cd3db6SAvi Kivity 253b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b) 254b7cd3db6SAvi Kivity { 2556046c620SPaolo Bonzini return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); 256b7cd3db6SAvi Kivity } 257b7cd3db6SAvi Kivity 258b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b) 259b7cd3db6SAvi Kivity { 260b7cd3db6SAvi Kivity return !int128_ge(a, b); 261b7cd3db6SAvi Kivity } 262b7cd3db6SAvi Kivity 263b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b) 264b7cd3db6SAvi Kivity { 265b7cd3db6SAvi Kivity return int128_ge(b, a); 266b7cd3db6SAvi Kivity } 267b7cd3db6SAvi Kivity 268b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b) 269b7cd3db6SAvi Kivity { 270b7cd3db6SAvi Kivity return !int128_le(a, b); 271b7cd3db6SAvi Kivity } 272b7cd3db6SAvi Kivity 273b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a) 274b7cd3db6SAvi Kivity { 275b7cd3db6SAvi Kivity return a.lo || a.hi; 276b7cd3db6SAvi Kivity } 277b7cd3db6SAvi Kivity 278b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b) 279b7cd3db6SAvi Kivity { 280b7cd3db6SAvi Kivity return int128_le(a, b) ? a : b; 281b7cd3db6SAvi Kivity } 282b7cd3db6SAvi Kivity 283b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b) 284b7cd3db6SAvi Kivity { 285b7cd3db6SAvi Kivity return int128_ge(a, b) ? a : b; 286b7cd3db6SAvi Kivity } 287b7cd3db6SAvi Kivity 288b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b) 289b7cd3db6SAvi Kivity { 290b7cd3db6SAvi Kivity *a = int128_add(*a, b); 291b7cd3db6SAvi Kivity } 292b7cd3db6SAvi Kivity 293b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b) 294b7cd3db6SAvi Kivity { 295b7cd3db6SAvi Kivity *a = int128_sub(*a, b); 296b7cd3db6SAvi Kivity } 297b7cd3db6SAvi Kivity 2980846beb3SRichard Henderson #endif /* CONFIG_INT128 */ 2990846beb3SRichard Henderson #endif /* INT128_H */ 300