1b7cd3db6SAvi Kivity #ifndef INT128_H 2b7cd3db6SAvi Kivity #define INT128_H 3b7cd3db6SAvi Kivity 40846beb3SRichard Henderson #ifdef CONFIG_INT128 57ebee43eSRichard 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 61*08895cdaSRichard Henderson static inline Int128 int128_or(Int128 a, Int128 b) 62*08895cdaSRichard Henderson { 63*08895cdaSRichard Henderson return a | b; 64*08895cdaSRichard Henderson } 65*08895cdaSRichard Henderson 660846beb3SRichard Henderson static inline Int128 int128_rshift(Int128 a, int n) 670846beb3SRichard Henderson { 680846beb3SRichard Henderson return a >> n; 690846beb3SRichard Henderson } 700846beb3SRichard Henderson 715be4dd04SRichard Henderson static inline Int128 int128_lshift(Int128 a, int n) 725be4dd04SRichard Henderson { 735be4dd04SRichard Henderson return a << n; 745be4dd04SRichard Henderson } 755be4dd04SRichard Henderson 760846beb3SRichard Henderson static inline Int128 int128_add(Int128 a, Int128 b) 770846beb3SRichard Henderson { 780846beb3SRichard Henderson return a + b; 790846beb3SRichard Henderson } 800846beb3SRichard Henderson 810846beb3SRichard Henderson static inline Int128 int128_neg(Int128 a) 820846beb3SRichard Henderson { 830846beb3SRichard Henderson return -a; 840846beb3SRichard Henderson } 850846beb3SRichard Henderson 860846beb3SRichard Henderson static inline Int128 int128_sub(Int128 a, Int128 b) 870846beb3SRichard Henderson { 880846beb3SRichard Henderson return a - b; 890846beb3SRichard Henderson } 900846beb3SRichard Henderson 910846beb3SRichard Henderson static inline bool int128_nonneg(Int128 a) 920846beb3SRichard Henderson { 930846beb3SRichard Henderson return a >= 0; 940846beb3SRichard Henderson } 950846beb3SRichard Henderson 960846beb3SRichard Henderson static inline bool int128_eq(Int128 a, Int128 b) 970846beb3SRichard Henderson { 980846beb3SRichard Henderson return a == b; 990846beb3SRichard Henderson } 1000846beb3SRichard Henderson 1010846beb3SRichard Henderson static inline bool int128_ne(Int128 a, Int128 b) 1020846beb3SRichard Henderson { 1030846beb3SRichard Henderson return a != b; 1040846beb3SRichard Henderson } 1050846beb3SRichard Henderson 1060846beb3SRichard Henderson static inline bool int128_ge(Int128 a, Int128 b) 1070846beb3SRichard Henderson { 1080846beb3SRichard Henderson return a >= b; 1090846beb3SRichard Henderson } 1100846beb3SRichard Henderson 1110846beb3SRichard Henderson static inline bool int128_lt(Int128 a, Int128 b) 1120846beb3SRichard Henderson { 1130846beb3SRichard Henderson return a < b; 1140846beb3SRichard Henderson } 1150846beb3SRichard Henderson 1160846beb3SRichard Henderson static inline bool int128_le(Int128 a, Int128 b) 1170846beb3SRichard Henderson { 1180846beb3SRichard Henderson return a <= b; 1190846beb3SRichard Henderson } 1200846beb3SRichard Henderson 1210846beb3SRichard Henderson static inline bool int128_gt(Int128 a, Int128 b) 1220846beb3SRichard Henderson { 1230846beb3SRichard Henderson return a > b; 1240846beb3SRichard Henderson } 1250846beb3SRichard Henderson 1260846beb3SRichard Henderson static inline bool int128_nz(Int128 a) 1270846beb3SRichard Henderson { 1280846beb3SRichard Henderson return a != 0; 1290846beb3SRichard Henderson } 1300846beb3SRichard Henderson 1310846beb3SRichard Henderson static inline Int128 int128_min(Int128 a, Int128 b) 1320846beb3SRichard Henderson { 1330846beb3SRichard Henderson return a < b ? a : b; 1340846beb3SRichard Henderson } 1350846beb3SRichard Henderson 1360846beb3SRichard Henderson static inline Int128 int128_max(Int128 a, Int128 b) 1370846beb3SRichard Henderson { 1380846beb3SRichard Henderson return a > b ? a : b; 1390846beb3SRichard Henderson } 1400846beb3SRichard Henderson 1410846beb3SRichard Henderson static inline void int128_addto(Int128 *a, Int128 b) 1420846beb3SRichard Henderson { 1430846beb3SRichard Henderson *a += b; 1440846beb3SRichard Henderson } 1450846beb3SRichard Henderson 1460846beb3SRichard Henderson static inline void int128_subfrom(Int128 *a, Int128 b) 1470846beb3SRichard Henderson { 1480846beb3SRichard Henderson *a -= b; 1490846beb3SRichard Henderson } 1500846beb3SRichard Henderson 1517ebee43eSRichard Henderson static inline Int128 bswap128(Int128 a) 1527ebee43eSRichard Henderson { 1537ebee43eSRichard Henderson return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a))); 1547ebee43eSRichard Henderson } 1557ebee43eSRichard Henderson 1560846beb3SRichard Henderson #else /* !CONFIG_INT128 */ 1576046c620SPaolo Bonzini 158b7cd3db6SAvi Kivity typedef struct Int128 Int128; 159b7cd3db6SAvi Kivity 160b7cd3db6SAvi Kivity struct Int128 { 161b7cd3db6SAvi Kivity uint64_t lo; 162b7cd3db6SAvi Kivity int64_t hi; 163b7cd3db6SAvi Kivity }; 164b7cd3db6SAvi Kivity 165b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a) 166b7cd3db6SAvi Kivity { 167b7cd3db6SAvi Kivity return (Int128) { a, 0 }; 168b7cd3db6SAvi Kivity } 169b7cd3db6SAvi Kivity 1701edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi) 1711edaeee0SRichard Henderson { 1721edaeee0SRichard Henderson return (Int128) { lo, hi }; 1731edaeee0SRichard Henderson } 1741edaeee0SRichard Henderson 175b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a) 176b7cd3db6SAvi Kivity { 177b7cd3db6SAvi Kivity assert(!a.hi); 178b7cd3db6SAvi Kivity return a.lo; 179b7cd3db6SAvi Kivity } 180b7cd3db6SAvi Kivity 181258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a) 182258dfaaaSRichard Henderson { 183258dfaaaSRichard Henderson return a.lo; 184258dfaaaSRichard Henderson } 185258dfaaaSRichard Henderson 186258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a) 187258dfaaaSRichard Henderson { 188258dfaaaSRichard Henderson return a.hi; 189258dfaaaSRichard Henderson } 190258dfaaaSRichard Henderson 191b7cd3db6SAvi Kivity static inline Int128 int128_zero(void) 192b7cd3db6SAvi Kivity { 193b7cd3db6SAvi Kivity return int128_make64(0); 194b7cd3db6SAvi Kivity } 195b7cd3db6SAvi Kivity 196b7cd3db6SAvi Kivity static inline Int128 int128_one(void) 197b7cd3db6SAvi Kivity { 198b7cd3db6SAvi Kivity return int128_make64(1); 199b7cd3db6SAvi Kivity } 200b7cd3db6SAvi Kivity 201b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void) 202b7cd3db6SAvi Kivity { 203b7cd3db6SAvi Kivity return (Int128) { 0, 1 }; 204b7cd3db6SAvi Kivity } 205b7cd3db6SAvi Kivity 20612e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a) 20712e1129bSAlexey Kardashevskiy { 20812e1129bSAlexey Kardashevskiy return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 }; 20912e1129bSAlexey Kardashevskiy } 21012e1129bSAlexey Kardashevskiy 211052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b) 212052e87b0SPaolo Bonzini { 213052e87b0SPaolo Bonzini return (Int128) { a.lo & b.lo, a.hi & b.hi }; 214052e87b0SPaolo Bonzini } 215052e87b0SPaolo Bonzini 216*08895cdaSRichard Henderson static inline Int128 int128_or(Int128 a, Int128 b) 217*08895cdaSRichard Henderson { 218*08895cdaSRichard Henderson return (Int128) { a.lo | b.lo, a.hi | b.hi }; 219*08895cdaSRichard Henderson } 220*08895cdaSRichard Henderson 221052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n) 222052e87b0SPaolo Bonzini { 223052e87b0SPaolo Bonzini int64_t h; 224052e87b0SPaolo Bonzini if (!n) { 225052e87b0SPaolo Bonzini return a; 226052e87b0SPaolo Bonzini } 227052e87b0SPaolo Bonzini h = a.hi >> (n & 63); 228052e87b0SPaolo Bonzini if (n >= 64) { 2291edaeee0SRichard Henderson return int128_make128(h, h >> 63); 230052e87b0SPaolo Bonzini } else { 2311edaeee0SRichard Henderson return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); 232052e87b0SPaolo Bonzini } 233052e87b0SPaolo Bonzini } 234052e87b0SPaolo Bonzini 2355be4dd04SRichard Henderson static inline Int128 int128_lshift(Int128 a, int n) 2365be4dd04SRichard Henderson { 2375be4dd04SRichard Henderson uint64_t l = a.lo << (n & 63); 2385be4dd04SRichard Henderson if (n >= 64) { 2395be4dd04SRichard Henderson return int128_make128(0, l); 2405be4dd04SRichard Henderson } else if (n > 0) { 2415be4dd04SRichard Henderson return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n))); 2425be4dd04SRichard Henderson } 2435be4dd04SRichard Henderson return a; 2445be4dd04SRichard Henderson } 2455be4dd04SRichard Henderson 246b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b) 247b7cd3db6SAvi Kivity { 2486046c620SPaolo Bonzini uint64_t lo = a.lo + b.lo; 2496046c620SPaolo Bonzini 2506046c620SPaolo Bonzini /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, 2516046c620SPaolo Bonzini * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. 2526046c620SPaolo Bonzini * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. 2536046c620SPaolo Bonzini * 2546046c620SPaolo Bonzini * So the carry is lo < a.lo. 2556046c620SPaolo Bonzini */ 2561edaeee0SRichard Henderson return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); 257b7cd3db6SAvi Kivity } 258b7cd3db6SAvi Kivity 259b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a) 260b7cd3db6SAvi Kivity { 2616046c620SPaolo Bonzini uint64_t lo = -a.lo; 2621edaeee0SRichard Henderson return int128_make128(lo, ~(uint64_t)a.hi + !lo); 263b7cd3db6SAvi Kivity } 264b7cd3db6SAvi Kivity 265b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b) 266b7cd3db6SAvi Kivity { 2671edaeee0SRichard Henderson return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); 268b7cd3db6SAvi Kivity } 269b7cd3db6SAvi Kivity 270b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a) 271b7cd3db6SAvi Kivity { 272b7cd3db6SAvi Kivity return a.hi >= 0; 273b7cd3db6SAvi Kivity } 274b7cd3db6SAvi Kivity 275b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b) 276b7cd3db6SAvi Kivity { 277b7cd3db6SAvi Kivity return a.lo == b.lo && a.hi == b.hi; 278b7cd3db6SAvi Kivity } 279b7cd3db6SAvi Kivity 280b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b) 281b7cd3db6SAvi Kivity { 282b7cd3db6SAvi Kivity return !int128_eq(a, b); 283b7cd3db6SAvi Kivity } 284b7cd3db6SAvi Kivity 285b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b) 286b7cd3db6SAvi Kivity { 2876046c620SPaolo Bonzini return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); 288b7cd3db6SAvi Kivity } 289b7cd3db6SAvi Kivity 290b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b) 291b7cd3db6SAvi Kivity { 292b7cd3db6SAvi Kivity return !int128_ge(a, b); 293b7cd3db6SAvi Kivity } 294b7cd3db6SAvi Kivity 295b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b) 296b7cd3db6SAvi Kivity { 297b7cd3db6SAvi Kivity return int128_ge(b, a); 298b7cd3db6SAvi Kivity } 299b7cd3db6SAvi Kivity 300b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b) 301b7cd3db6SAvi Kivity { 302b7cd3db6SAvi Kivity return !int128_le(a, b); 303b7cd3db6SAvi Kivity } 304b7cd3db6SAvi Kivity 305b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a) 306b7cd3db6SAvi Kivity { 307b7cd3db6SAvi Kivity return a.lo || a.hi; 308b7cd3db6SAvi Kivity } 309b7cd3db6SAvi Kivity 310b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b) 311b7cd3db6SAvi Kivity { 312b7cd3db6SAvi Kivity return int128_le(a, b) ? a : b; 313b7cd3db6SAvi Kivity } 314b7cd3db6SAvi Kivity 315b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b) 316b7cd3db6SAvi Kivity { 317b7cd3db6SAvi Kivity return int128_ge(a, b) ? a : b; 318b7cd3db6SAvi Kivity } 319b7cd3db6SAvi Kivity 320b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b) 321b7cd3db6SAvi Kivity { 322b7cd3db6SAvi Kivity *a = int128_add(*a, b); 323b7cd3db6SAvi Kivity } 324b7cd3db6SAvi Kivity 325b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b) 326b7cd3db6SAvi Kivity { 327b7cd3db6SAvi Kivity *a = int128_sub(*a, b); 328b7cd3db6SAvi Kivity } 329b7cd3db6SAvi Kivity 3300846beb3SRichard Henderson #endif /* CONFIG_INT128 */ 3310846beb3SRichard Henderson #endif /* INT128_H */ 332