1b7cd3db6SAvi Kivity #ifndef INT128_H 2b7cd3db6SAvi Kivity #define INT128_H 3b7cd3db6SAvi Kivity 40846beb3SRichard Henderson #ifdef CONFIG_INT128 5*7ebee43eSRichard Henderson #include "qemu/bswap.h" 60846beb3SRichard Henderson 70846beb3SRichard Henderson typedef __int128_t Int128; 80846beb3SRichard Henderson 90846beb3SRichard Henderson static inline Int128 int128_make64(uint64_t a) 100846beb3SRichard Henderson { 110846beb3SRichard Henderson return a; 120846beb3SRichard Henderson } 130846beb3SRichard Henderson 141edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi) 151edaeee0SRichard Henderson { 161edaeee0SRichard Henderson return (__uint128_t)hi << 64 | lo; 171edaeee0SRichard Henderson } 181edaeee0SRichard Henderson 190846beb3SRichard Henderson static inline uint64_t int128_get64(Int128 a) 200846beb3SRichard Henderson { 210846beb3SRichard Henderson uint64_t r = a; 220846beb3SRichard Henderson assert(r == a); 230846beb3SRichard Henderson return r; 240846beb3SRichard Henderson } 250846beb3SRichard Henderson 260846beb3SRichard Henderson static inline uint64_t int128_getlo(Int128 a) 270846beb3SRichard Henderson { 280846beb3SRichard Henderson return a; 290846beb3SRichard Henderson } 300846beb3SRichard Henderson 310846beb3SRichard Henderson static inline int64_t int128_gethi(Int128 a) 320846beb3SRichard Henderson { 330846beb3SRichard Henderson return a >> 64; 340846beb3SRichard Henderson } 350846beb3SRichard Henderson 360846beb3SRichard Henderson static inline Int128 int128_zero(void) 370846beb3SRichard Henderson { 380846beb3SRichard Henderson return 0; 390846beb3SRichard Henderson } 400846beb3SRichard Henderson 410846beb3SRichard Henderson static inline Int128 int128_one(void) 420846beb3SRichard Henderson { 430846beb3SRichard Henderson return 1; 440846beb3SRichard Henderson } 450846beb3SRichard Henderson 460846beb3SRichard Henderson static inline Int128 int128_2_64(void) 470846beb3SRichard Henderson { 480846beb3SRichard Henderson return (Int128)1 << 64; 490846beb3SRichard Henderson } 500846beb3SRichard Henderson 510846beb3SRichard Henderson static inline Int128 int128_exts64(int64_t a) 520846beb3SRichard Henderson { 530846beb3SRichard Henderson return a; 540846beb3SRichard Henderson } 550846beb3SRichard Henderson 560846beb3SRichard Henderson static inline Int128 int128_and(Int128 a, Int128 b) 570846beb3SRichard Henderson { 580846beb3SRichard Henderson return a & b; 590846beb3SRichard Henderson } 600846beb3SRichard Henderson 610846beb3SRichard Henderson static inline Int128 int128_rshift(Int128 a, int n) 620846beb3SRichard Henderson { 630846beb3SRichard Henderson return a >> n; 640846beb3SRichard Henderson } 650846beb3SRichard Henderson 660846beb3SRichard Henderson static inline Int128 int128_add(Int128 a, Int128 b) 670846beb3SRichard Henderson { 680846beb3SRichard Henderson return a + b; 690846beb3SRichard Henderson } 700846beb3SRichard Henderson 710846beb3SRichard Henderson static inline Int128 int128_neg(Int128 a) 720846beb3SRichard Henderson { 730846beb3SRichard Henderson return -a; 740846beb3SRichard Henderson } 750846beb3SRichard Henderson 760846beb3SRichard Henderson static inline Int128 int128_sub(Int128 a, Int128 b) 770846beb3SRichard Henderson { 780846beb3SRichard Henderson return a - b; 790846beb3SRichard Henderson } 800846beb3SRichard Henderson 810846beb3SRichard Henderson static inline bool int128_nonneg(Int128 a) 820846beb3SRichard Henderson { 830846beb3SRichard Henderson return a >= 0; 840846beb3SRichard Henderson } 850846beb3SRichard Henderson 860846beb3SRichard Henderson static inline bool int128_eq(Int128 a, Int128 b) 870846beb3SRichard Henderson { 880846beb3SRichard Henderson return a == b; 890846beb3SRichard Henderson } 900846beb3SRichard Henderson 910846beb3SRichard Henderson static inline bool int128_ne(Int128 a, Int128 b) 920846beb3SRichard Henderson { 930846beb3SRichard Henderson return a != b; 940846beb3SRichard Henderson } 950846beb3SRichard Henderson 960846beb3SRichard Henderson static inline bool int128_ge(Int128 a, Int128 b) 970846beb3SRichard Henderson { 980846beb3SRichard Henderson return a >= b; 990846beb3SRichard Henderson } 1000846beb3SRichard Henderson 1010846beb3SRichard Henderson static inline bool int128_lt(Int128 a, Int128 b) 1020846beb3SRichard Henderson { 1030846beb3SRichard Henderson return a < b; 1040846beb3SRichard Henderson } 1050846beb3SRichard Henderson 1060846beb3SRichard Henderson static inline bool int128_le(Int128 a, Int128 b) 1070846beb3SRichard Henderson { 1080846beb3SRichard Henderson return a <= b; 1090846beb3SRichard Henderson } 1100846beb3SRichard Henderson 1110846beb3SRichard Henderson static inline bool int128_gt(Int128 a, Int128 b) 1120846beb3SRichard Henderson { 1130846beb3SRichard Henderson return a > b; 1140846beb3SRichard Henderson } 1150846beb3SRichard Henderson 1160846beb3SRichard Henderson static inline bool int128_nz(Int128 a) 1170846beb3SRichard Henderson { 1180846beb3SRichard Henderson return a != 0; 1190846beb3SRichard Henderson } 1200846beb3SRichard Henderson 1210846beb3SRichard Henderson static inline Int128 int128_min(Int128 a, Int128 b) 1220846beb3SRichard Henderson { 1230846beb3SRichard Henderson return a < b ? a : b; 1240846beb3SRichard Henderson } 1250846beb3SRichard Henderson 1260846beb3SRichard Henderson static inline Int128 int128_max(Int128 a, Int128 b) 1270846beb3SRichard Henderson { 1280846beb3SRichard Henderson return a > b ? a : b; 1290846beb3SRichard Henderson } 1300846beb3SRichard Henderson 1310846beb3SRichard Henderson static inline void int128_addto(Int128 *a, Int128 b) 1320846beb3SRichard Henderson { 1330846beb3SRichard Henderson *a += b; 1340846beb3SRichard Henderson } 1350846beb3SRichard Henderson 1360846beb3SRichard Henderson static inline void int128_subfrom(Int128 *a, Int128 b) 1370846beb3SRichard Henderson { 1380846beb3SRichard Henderson *a -= b; 1390846beb3SRichard Henderson } 1400846beb3SRichard Henderson 141*7ebee43eSRichard Henderson static inline Int128 bswap128(Int128 a) 142*7ebee43eSRichard Henderson { 143*7ebee43eSRichard Henderson return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a))); 144*7ebee43eSRichard Henderson } 145*7ebee43eSRichard Henderson 1460846beb3SRichard Henderson #else /* !CONFIG_INT128 */ 1476046c620SPaolo Bonzini 148b7cd3db6SAvi Kivity typedef struct Int128 Int128; 149b7cd3db6SAvi Kivity 150b7cd3db6SAvi Kivity struct Int128 { 151b7cd3db6SAvi Kivity uint64_t lo; 152b7cd3db6SAvi Kivity int64_t hi; 153b7cd3db6SAvi Kivity }; 154b7cd3db6SAvi Kivity 155b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a) 156b7cd3db6SAvi Kivity { 157b7cd3db6SAvi Kivity return (Int128) { a, 0 }; 158b7cd3db6SAvi Kivity } 159b7cd3db6SAvi Kivity 1601edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi) 1611edaeee0SRichard Henderson { 1621edaeee0SRichard Henderson return (Int128) { lo, hi }; 1631edaeee0SRichard Henderson } 1641edaeee0SRichard Henderson 165b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a) 166b7cd3db6SAvi Kivity { 167b7cd3db6SAvi Kivity assert(!a.hi); 168b7cd3db6SAvi Kivity return a.lo; 169b7cd3db6SAvi Kivity } 170b7cd3db6SAvi Kivity 171258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a) 172258dfaaaSRichard Henderson { 173258dfaaaSRichard Henderson return a.lo; 174258dfaaaSRichard Henderson } 175258dfaaaSRichard Henderson 176258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a) 177258dfaaaSRichard Henderson { 178258dfaaaSRichard Henderson return a.hi; 179258dfaaaSRichard Henderson } 180258dfaaaSRichard Henderson 181b7cd3db6SAvi Kivity static inline Int128 int128_zero(void) 182b7cd3db6SAvi Kivity { 183b7cd3db6SAvi Kivity return int128_make64(0); 184b7cd3db6SAvi Kivity } 185b7cd3db6SAvi Kivity 186b7cd3db6SAvi Kivity static inline Int128 int128_one(void) 187b7cd3db6SAvi Kivity { 188b7cd3db6SAvi Kivity return int128_make64(1); 189b7cd3db6SAvi Kivity } 190b7cd3db6SAvi Kivity 191b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void) 192b7cd3db6SAvi Kivity { 193b7cd3db6SAvi Kivity return (Int128) { 0, 1 }; 194b7cd3db6SAvi Kivity } 195b7cd3db6SAvi Kivity 19612e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a) 19712e1129bSAlexey Kardashevskiy { 19812e1129bSAlexey Kardashevskiy return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 }; 19912e1129bSAlexey Kardashevskiy } 20012e1129bSAlexey Kardashevskiy 201052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b) 202052e87b0SPaolo Bonzini { 203052e87b0SPaolo Bonzini return (Int128) { a.lo & b.lo, a.hi & b.hi }; 204052e87b0SPaolo Bonzini } 205052e87b0SPaolo Bonzini 206052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n) 207052e87b0SPaolo Bonzini { 208052e87b0SPaolo Bonzini int64_t h; 209052e87b0SPaolo Bonzini if (!n) { 210052e87b0SPaolo Bonzini return a; 211052e87b0SPaolo Bonzini } 212052e87b0SPaolo Bonzini h = a.hi >> (n & 63); 213052e87b0SPaolo Bonzini if (n >= 64) { 2141edaeee0SRichard Henderson return int128_make128(h, h >> 63); 215052e87b0SPaolo Bonzini } else { 2161edaeee0SRichard Henderson return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); 217052e87b0SPaolo Bonzini } 218052e87b0SPaolo Bonzini } 219052e87b0SPaolo Bonzini 220b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b) 221b7cd3db6SAvi Kivity { 2226046c620SPaolo Bonzini uint64_t lo = a.lo + b.lo; 2236046c620SPaolo Bonzini 2246046c620SPaolo Bonzini /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, 2256046c620SPaolo Bonzini * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. 2266046c620SPaolo Bonzini * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. 2276046c620SPaolo Bonzini * 2286046c620SPaolo Bonzini * So the carry is lo < a.lo. 2296046c620SPaolo Bonzini */ 2301edaeee0SRichard Henderson return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); 231b7cd3db6SAvi Kivity } 232b7cd3db6SAvi Kivity 233b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a) 234b7cd3db6SAvi Kivity { 2356046c620SPaolo Bonzini uint64_t lo = -a.lo; 2361edaeee0SRichard Henderson return int128_make128(lo, ~(uint64_t)a.hi + !lo); 237b7cd3db6SAvi Kivity } 238b7cd3db6SAvi Kivity 239b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b) 240b7cd3db6SAvi Kivity { 2411edaeee0SRichard Henderson return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); 242b7cd3db6SAvi Kivity } 243b7cd3db6SAvi Kivity 244b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a) 245b7cd3db6SAvi Kivity { 246b7cd3db6SAvi Kivity return a.hi >= 0; 247b7cd3db6SAvi Kivity } 248b7cd3db6SAvi Kivity 249b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b) 250b7cd3db6SAvi Kivity { 251b7cd3db6SAvi Kivity return a.lo == b.lo && a.hi == b.hi; 252b7cd3db6SAvi Kivity } 253b7cd3db6SAvi Kivity 254b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b) 255b7cd3db6SAvi Kivity { 256b7cd3db6SAvi Kivity return !int128_eq(a, b); 257b7cd3db6SAvi Kivity } 258b7cd3db6SAvi Kivity 259b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b) 260b7cd3db6SAvi Kivity { 2616046c620SPaolo Bonzini return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); 262b7cd3db6SAvi Kivity } 263b7cd3db6SAvi Kivity 264b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b) 265b7cd3db6SAvi Kivity { 266b7cd3db6SAvi Kivity return !int128_ge(a, b); 267b7cd3db6SAvi Kivity } 268b7cd3db6SAvi Kivity 269b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b) 270b7cd3db6SAvi Kivity { 271b7cd3db6SAvi Kivity return int128_ge(b, a); 272b7cd3db6SAvi Kivity } 273b7cd3db6SAvi Kivity 274b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b) 275b7cd3db6SAvi Kivity { 276b7cd3db6SAvi Kivity return !int128_le(a, b); 277b7cd3db6SAvi Kivity } 278b7cd3db6SAvi Kivity 279b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a) 280b7cd3db6SAvi Kivity { 281b7cd3db6SAvi Kivity return a.lo || a.hi; 282b7cd3db6SAvi Kivity } 283b7cd3db6SAvi Kivity 284b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b) 285b7cd3db6SAvi Kivity { 286b7cd3db6SAvi Kivity return int128_le(a, b) ? a : b; 287b7cd3db6SAvi Kivity } 288b7cd3db6SAvi Kivity 289b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b) 290b7cd3db6SAvi Kivity { 291b7cd3db6SAvi Kivity return int128_ge(a, b) ? a : b; 292b7cd3db6SAvi Kivity } 293b7cd3db6SAvi Kivity 294b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b) 295b7cd3db6SAvi Kivity { 296b7cd3db6SAvi Kivity *a = int128_add(*a, b); 297b7cd3db6SAvi Kivity } 298b7cd3db6SAvi Kivity 299b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b) 300b7cd3db6SAvi Kivity { 301b7cd3db6SAvi Kivity *a = int128_sub(*a, b); 302b7cd3db6SAvi Kivity } 303b7cd3db6SAvi Kivity 3040846beb3SRichard Henderson #endif /* CONFIG_INT128 */ 3050846beb3SRichard Henderson #endif /* INT128_H */ 306