1b7cd3db6SAvi Kivity #ifndef INT128_H 2b7cd3db6SAvi Kivity #define INT128_H 3b7cd3db6SAvi Kivity 47ebee43eSRichard Henderson #include "qemu/bswap.h" 50846beb3SRichard Henderson 62484cd9cSMatheus Ferst #ifdef CONFIG_INT128 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 14703235a3SPeter Maydell static inline Int128 int128_makes64(int64_t a) 15703235a3SPeter Maydell { 16703235a3SPeter Maydell return a; 17703235a3SPeter Maydell } 18703235a3SPeter Maydell 191edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi) 201edaeee0SRichard Henderson { 211edaeee0SRichard Henderson return (__uint128_t)hi << 64 | lo; 221edaeee0SRichard Henderson } 231edaeee0SRichard Henderson 240846beb3SRichard Henderson static inline uint64_t int128_get64(Int128 a) 250846beb3SRichard Henderson { 260846beb3SRichard Henderson uint64_t r = a; 270846beb3SRichard Henderson assert(r == a); 280846beb3SRichard Henderson return r; 290846beb3SRichard Henderson } 300846beb3SRichard Henderson 310846beb3SRichard Henderson static inline uint64_t int128_getlo(Int128 a) 320846beb3SRichard Henderson { 330846beb3SRichard Henderson return a; 340846beb3SRichard Henderson } 350846beb3SRichard Henderson 360846beb3SRichard Henderson static inline int64_t int128_gethi(Int128 a) 370846beb3SRichard Henderson { 380846beb3SRichard Henderson return a >> 64; 390846beb3SRichard Henderson } 400846beb3SRichard Henderson 410846beb3SRichard Henderson static inline Int128 int128_zero(void) 420846beb3SRichard Henderson { 430846beb3SRichard Henderson return 0; 440846beb3SRichard Henderson } 450846beb3SRichard Henderson 460846beb3SRichard Henderson static inline Int128 int128_one(void) 470846beb3SRichard Henderson { 480846beb3SRichard Henderson return 1; 490846beb3SRichard Henderson } 500846beb3SRichard Henderson 510846beb3SRichard Henderson static inline Int128 int128_2_64(void) 520846beb3SRichard Henderson { 530846beb3SRichard Henderson return (Int128)1 << 64; 540846beb3SRichard Henderson } 550846beb3SRichard Henderson 560846beb3SRichard Henderson static inline Int128 int128_exts64(int64_t a) 570846beb3SRichard Henderson { 580846beb3SRichard Henderson return a; 590846beb3SRichard Henderson } 600846beb3SRichard Henderson 611c469373SFrédéric Pétrot static inline Int128 int128_not(Int128 a) 621c469373SFrédéric Pétrot { 631c469373SFrédéric Pétrot return ~a; 641c469373SFrédéric Pétrot } 651c469373SFrédéric Pétrot 660846beb3SRichard Henderson static inline Int128 int128_and(Int128 a, Int128 b) 670846beb3SRichard Henderson { 680846beb3SRichard Henderson return a & b; 690846beb3SRichard Henderson } 700846beb3SRichard Henderson 7108895cdaSRichard Henderson static inline Int128 int128_or(Int128 a, Int128 b) 7208895cdaSRichard Henderson { 7308895cdaSRichard Henderson return a | b; 7408895cdaSRichard Henderson } 7508895cdaSRichard Henderson 761c469373SFrédéric Pétrot static inline Int128 int128_xor(Int128 a, Int128 b) 771c469373SFrédéric Pétrot { 781c469373SFrédéric Pétrot return a ^ b; 791c469373SFrédéric Pétrot } 801c469373SFrédéric Pétrot 810846beb3SRichard Henderson static inline Int128 int128_rshift(Int128 a, int n) 820846beb3SRichard Henderson { 830846beb3SRichard Henderson return a >> n; 840846beb3SRichard Henderson } 850846beb3SRichard Henderson 865be4dd04SRichard Henderson static inline Int128 int128_lshift(Int128 a, int n) 875be4dd04SRichard Henderson { 885be4dd04SRichard Henderson return a << n; 895be4dd04SRichard Henderson } 905be4dd04SRichard Henderson 910846beb3SRichard Henderson static inline Int128 int128_add(Int128 a, Int128 b) 920846beb3SRichard Henderson { 930846beb3SRichard Henderson return a + b; 940846beb3SRichard Henderson } 950846beb3SRichard Henderson 960846beb3SRichard Henderson static inline Int128 int128_neg(Int128 a) 970846beb3SRichard Henderson { 980846beb3SRichard Henderson return -a; 990846beb3SRichard Henderson } 1000846beb3SRichard Henderson 1010846beb3SRichard Henderson static inline Int128 int128_sub(Int128 a, Int128 b) 1020846beb3SRichard Henderson { 1030846beb3SRichard Henderson return a - b; 1040846beb3SRichard Henderson } 1050846beb3SRichard Henderson 1060846beb3SRichard Henderson static inline bool int128_nonneg(Int128 a) 1070846beb3SRichard Henderson { 1080846beb3SRichard Henderson return a >= 0; 1090846beb3SRichard Henderson } 1100846beb3SRichard Henderson 1110846beb3SRichard Henderson static inline bool int128_eq(Int128 a, Int128 b) 1120846beb3SRichard Henderson { 1130846beb3SRichard Henderson return a == b; 1140846beb3SRichard Henderson } 1150846beb3SRichard Henderson 1160846beb3SRichard Henderson static inline bool int128_ne(Int128 a, Int128 b) 1170846beb3SRichard Henderson { 1180846beb3SRichard Henderson return a != b; 1190846beb3SRichard Henderson } 1200846beb3SRichard Henderson 1210846beb3SRichard Henderson static inline bool int128_ge(Int128 a, Int128 b) 1220846beb3SRichard Henderson { 1230846beb3SRichard Henderson return a >= b; 1240846beb3SRichard Henderson } 1250846beb3SRichard Henderson 1260846beb3SRichard Henderson static inline bool int128_lt(Int128 a, Int128 b) 1270846beb3SRichard Henderson { 1280846beb3SRichard Henderson return a < b; 1290846beb3SRichard Henderson } 1300846beb3SRichard Henderson 1310846beb3SRichard Henderson static inline bool int128_le(Int128 a, Int128 b) 1320846beb3SRichard Henderson { 1330846beb3SRichard Henderson return a <= b; 1340846beb3SRichard Henderson } 1350846beb3SRichard Henderson 1360846beb3SRichard Henderson static inline bool int128_gt(Int128 a, Int128 b) 1370846beb3SRichard Henderson { 1380846beb3SRichard Henderson return a > b; 1390846beb3SRichard Henderson } 1400846beb3SRichard Henderson 1410846beb3SRichard Henderson static inline bool int128_nz(Int128 a) 1420846beb3SRichard Henderson { 1430846beb3SRichard Henderson return a != 0; 1440846beb3SRichard Henderson } 1450846beb3SRichard Henderson 1460846beb3SRichard Henderson static inline Int128 int128_min(Int128 a, Int128 b) 1470846beb3SRichard Henderson { 1480846beb3SRichard Henderson return a < b ? a : b; 1490846beb3SRichard Henderson } 1500846beb3SRichard Henderson 1510846beb3SRichard Henderson static inline Int128 int128_max(Int128 a, Int128 b) 1520846beb3SRichard Henderson { 1530846beb3SRichard Henderson return a > b ? a : b; 1540846beb3SRichard Henderson } 1550846beb3SRichard Henderson 1560846beb3SRichard Henderson static inline void int128_addto(Int128 *a, Int128 b) 1570846beb3SRichard Henderson { 1580846beb3SRichard Henderson *a += b; 1590846beb3SRichard Henderson } 1600846beb3SRichard Henderson 1610846beb3SRichard Henderson static inline void int128_subfrom(Int128 *a, Int128 b) 1620846beb3SRichard Henderson { 1630846beb3SRichard Henderson *a -= b; 1640846beb3SRichard Henderson } 1650846beb3SRichard Henderson 1667ebee43eSRichard Henderson static inline Int128 bswap128(Int128 a) 1677ebee43eSRichard Henderson { 1682484cd9cSMatheus Ferst #if __has_builtin(__builtin_bswap128) 1692484cd9cSMatheus Ferst return __builtin_bswap128(a); 1702484cd9cSMatheus Ferst #else 1717ebee43eSRichard Henderson return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a))); 1722484cd9cSMatheus Ferst #endif 1737ebee43eSRichard Henderson } 1747ebee43eSRichard Henderson 175*e9d07601SFrédéric Pétrot static inline Int128 int128_divu(Int128 a, Int128 b) 176*e9d07601SFrédéric Pétrot { 177*e9d07601SFrédéric Pétrot return (__uint128_t)a / (__uint128_t)b; 178*e9d07601SFrédéric Pétrot } 179*e9d07601SFrédéric Pétrot 180*e9d07601SFrédéric Pétrot static inline Int128 int128_remu(Int128 a, Int128 b) 181*e9d07601SFrédéric Pétrot { 182*e9d07601SFrédéric Pétrot return (__uint128_t)a % (__uint128_t)b; 183*e9d07601SFrédéric Pétrot } 184*e9d07601SFrédéric Pétrot 185*e9d07601SFrédéric Pétrot static inline Int128 int128_divs(Int128 a, Int128 b) 186*e9d07601SFrédéric Pétrot { 187*e9d07601SFrédéric Pétrot return a / b; 188*e9d07601SFrédéric Pétrot } 189*e9d07601SFrédéric Pétrot 190*e9d07601SFrédéric Pétrot static inline Int128 int128_rems(Int128 a, Int128 b) 191*e9d07601SFrédéric Pétrot { 192*e9d07601SFrédéric Pétrot return a % b; 193*e9d07601SFrédéric Pétrot } 194*e9d07601SFrédéric Pétrot 1950846beb3SRichard Henderson #else /* !CONFIG_INT128 */ 1966046c620SPaolo Bonzini 197b7cd3db6SAvi Kivity typedef struct Int128 Int128; 198b7cd3db6SAvi Kivity 199181b0c33SMatheus Ferst /* 200181b0c33SMatheus Ferst * We guarantee that the in-memory byte representation of an 201181b0c33SMatheus Ferst * Int128 is that of a host-endian-order 128-bit integer 202181b0c33SMatheus Ferst * (whether using this struct or the __int128_t version of the type). 203181b0c33SMatheus Ferst * Some code using this type relies on this (eg when copying it into 204181b0c33SMatheus Ferst * guest memory or a gdb protocol buffer, or by using Int128 in 205181b0c33SMatheus Ferst * a union with other integer types). 206181b0c33SMatheus Ferst */ 207b7cd3db6SAvi Kivity struct Int128 { 208181b0c33SMatheus Ferst #ifdef HOST_WORDS_BIGENDIAN 209181b0c33SMatheus Ferst int64_t hi; 210181b0c33SMatheus Ferst uint64_t lo; 211181b0c33SMatheus Ferst #else 212b7cd3db6SAvi Kivity uint64_t lo; 213b7cd3db6SAvi Kivity int64_t hi; 214181b0c33SMatheus Ferst #endif 215b7cd3db6SAvi Kivity }; 216b7cd3db6SAvi Kivity 217b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a) 218b7cd3db6SAvi Kivity { 219181b0c33SMatheus Ferst return (Int128) { .lo = a, .hi = 0 }; 220b7cd3db6SAvi Kivity } 221b7cd3db6SAvi Kivity 222703235a3SPeter Maydell static inline Int128 int128_makes64(int64_t a) 223703235a3SPeter Maydell { 224181b0c33SMatheus Ferst return (Int128) { .lo = a, .hi = a >> 63 }; 225703235a3SPeter Maydell } 226703235a3SPeter Maydell 2271edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi) 2281edaeee0SRichard Henderson { 229181b0c33SMatheus Ferst return (Int128) { .lo = lo, .hi = hi }; 2301edaeee0SRichard Henderson } 2311edaeee0SRichard Henderson 232b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a) 233b7cd3db6SAvi Kivity { 234b7cd3db6SAvi Kivity assert(!a.hi); 235b7cd3db6SAvi Kivity return a.lo; 236b7cd3db6SAvi Kivity } 237b7cd3db6SAvi Kivity 238258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a) 239258dfaaaSRichard Henderson { 240258dfaaaSRichard Henderson return a.lo; 241258dfaaaSRichard Henderson } 242258dfaaaSRichard Henderson 243258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a) 244258dfaaaSRichard Henderson { 245258dfaaaSRichard Henderson return a.hi; 246258dfaaaSRichard Henderson } 247258dfaaaSRichard Henderson 248b7cd3db6SAvi Kivity static inline Int128 int128_zero(void) 249b7cd3db6SAvi Kivity { 250b7cd3db6SAvi Kivity return int128_make64(0); 251b7cd3db6SAvi Kivity } 252b7cd3db6SAvi Kivity 253b7cd3db6SAvi Kivity static inline Int128 int128_one(void) 254b7cd3db6SAvi Kivity { 255b7cd3db6SAvi Kivity return int128_make64(1); 256b7cd3db6SAvi Kivity } 257b7cd3db6SAvi Kivity 258b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void) 259b7cd3db6SAvi Kivity { 260181b0c33SMatheus Ferst return int128_make128(0, 1); 261b7cd3db6SAvi Kivity } 262b7cd3db6SAvi Kivity 26312e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a) 26412e1129bSAlexey Kardashevskiy { 265181b0c33SMatheus Ferst return int128_make128(a, (a < 0) ? -1 : 0); 26612e1129bSAlexey Kardashevskiy } 26712e1129bSAlexey Kardashevskiy 2681c469373SFrédéric Pétrot static inline Int128 int128_not(Int128 a) 2691c469373SFrédéric Pétrot { 2701c469373SFrédéric Pétrot return int128_make128(~a.lo, ~a.hi); 2711c469373SFrédéric Pétrot } 2721c469373SFrédéric Pétrot 273052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b) 274052e87b0SPaolo Bonzini { 275181b0c33SMatheus Ferst return int128_make128(a.lo & b.lo, a.hi & b.hi); 276052e87b0SPaolo Bonzini } 277052e87b0SPaolo Bonzini 27808895cdaSRichard Henderson static inline Int128 int128_or(Int128 a, Int128 b) 27908895cdaSRichard Henderson { 280181b0c33SMatheus Ferst return int128_make128(a.lo | b.lo, a.hi | b.hi); 28108895cdaSRichard Henderson } 28208895cdaSRichard Henderson 2831c469373SFrédéric Pétrot static inline Int128 int128_xor(Int128 a, Int128 b) 2841c469373SFrédéric Pétrot { 2851c469373SFrédéric Pétrot return int128_make128(a.lo ^ b.lo, a.hi ^ b.hi); 2861c469373SFrédéric Pétrot } 2871c469373SFrédéric Pétrot 288052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n) 289052e87b0SPaolo Bonzini { 290052e87b0SPaolo Bonzini int64_t h; 291052e87b0SPaolo Bonzini if (!n) { 292052e87b0SPaolo Bonzini return a; 293052e87b0SPaolo Bonzini } 294052e87b0SPaolo Bonzini h = a.hi >> (n & 63); 295052e87b0SPaolo Bonzini if (n >= 64) { 2961edaeee0SRichard Henderson return int128_make128(h, h >> 63); 297052e87b0SPaolo Bonzini } else { 2981edaeee0SRichard Henderson return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); 299052e87b0SPaolo Bonzini } 300052e87b0SPaolo Bonzini } 301052e87b0SPaolo Bonzini 3025be4dd04SRichard Henderson static inline Int128 int128_lshift(Int128 a, int n) 3035be4dd04SRichard Henderson { 3045be4dd04SRichard Henderson uint64_t l = a.lo << (n & 63); 3055be4dd04SRichard Henderson if (n >= 64) { 3065be4dd04SRichard Henderson return int128_make128(0, l); 3075be4dd04SRichard Henderson } else if (n > 0) { 3085be4dd04SRichard Henderson return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n))); 3095be4dd04SRichard Henderson } 3105be4dd04SRichard Henderson return a; 3115be4dd04SRichard Henderson } 3125be4dd04SRichard Henderson 313b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b) 314b7cd3db6SAvi Kivity { 3156046c620SPaolo Bonzini uint64_t lo = a.lo + b.lo; 3166046c620SPaolo Bonzini 3176046c620SPaolo Bonzini /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, 3186046c620SPaolo Bonzini * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. 3196046c620SPaolo Bonzini * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. 3206046c620SPaolo Bonzini * 3216046c620SPaolo Bonzini * So the carry is lo < a.lo. 3226046c620SPaolo Bonzini */ 3231edaeee0SRichard Henderson return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); 324b7cd3db6SAvi Kivity } 325b7cd3db6SAvi Kivity 326b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a) 327b7cd3db6SAvi Kivity { 3286046c620SPaolo Bonzini uint64_t lo = -a.lo; 3291edaeee0SRichard Henderson return int128_make128(lo, ~(uint64_t)a.hi + !lo); 330b7cd3db6SAvi Kivity } 331b7cd3db6SAvi Kivity 332b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b) 333b7cd3db6SAvi Kivity { 3341edaeee0SRichard Henderson return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); 335b7cd3db6SAvi Kivity } 336b7cd3db6SAvi Kivity 337b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a) 338b7cd3db6SAvi Kivity { 339b7cd3db6SAvi Kivity return a.hi >= 0; 340b7cd3db6SAvi Kivity } 341b7cd3db6SAvi Kivity 342b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b) 343b7cd3db6SAvi Kivity { 344b7cd3db6SAvi Kivity return a.lo == b.lo && a.hi == b.hi; 345b7cd3db6SAvi Kivity } 346b7cd3db6SAvi Kivity 347b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b) 348b7cd3db6SAvi Kivity { 349b7cd3db6SAvi Kivity return !int128_eq(a, b); 350b7cd3db6SAvi Kivity } 351b7cd3db6SAvi Kivity 352b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b) 353b7cd3db6SAvi Kivity { 3546046c620SPaolo Bonzini return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); 355b7cd3db6SAvi Kivity } 356b7cd3db6SAvi Kivity 357b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b) 358b7cd3db6SAvi Kivity { 359b7cd3db6SAvi Kivity return !int128_ge(a, b); 360b7cd3db6SAvi Kivity } 361b7cd3db6SAvi Kivity 362b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b) 363b7cd3db6SAvi Kivity { 364b7cd3db6SAvi Kivity return int128_ge(b, a); 365b7cd3db6SAvi Kivity } 366b7cd3db6SAvi Kivity 367b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b) 368b7cd3db6SAvi Kivity { 369b7cd3db6SAvi Kivity return !int128_le(a, b); 370b7cd3db6SAvi Kivity } 371b7cd3db6SAvi Kivity 372b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a) 373b7cd3db6SAvi Kivity { 374b7cd3db6SAvi Kivity return a.lo || a.hi; 375b7cd3db6SAvi Kivity } 376b7cd3db6SAvi Kivity 377b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b) 378b7cd3db6SAvi Kivity { 379b7cd3db6SAvi Kivity return int128_le(a, b) ? a : b; 380b7cd3db6SAvi Kivity } 381b7cd3db6SAvi Kivity 382b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b) 383b7cd3db6SAvi Kivity { 384b7cd3db6SAvi Kivity return int128_ge(a, b) ? a : b; 385b7cd3db6SAvi Kivity } 386b7cd3db6SAvi Kivity 387b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b) 388b7cd3db6SAvi Kivity { 389b7cd3db6SAvi Kivity *a = int128_add(*a, b); 390b7cd3db6SAvi Kivity } 391b7cd3db6SAvi Kivity 392b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b) 393b7cd3db6SAvi Kivity { 394b7cd3db6SAvi Kivity *a = int128_sub(*a, b); 395b7cd3db6SAvi Kivity } 396b7cd3db6SAvi Kivity 3972484cd9cSMatheus Ferst static inline Int128 bswap128(Int128 a) 3982484cd9cSMatheus Ferst { 3992484cd9cSMatheus Ferst return int128_make128(bswap64(a.hi), bswap64(a.lo)); 4002484cd9cSMatheus Ferst } 4012484cd9cSMatheus Ferst 402*e9d07601SFrédéric Pétrot Int128 int128_divu(Int128, Int128); 403*e9d07601SFrédéric Pétrot Int128 int128_remu(Int128, Int128); 404*e9d07601SFrédéric Pétrot Int128 int128_divs(Int128, Int128); 405*e9d07601SFrédéric Pétrot Int128 int128_rems(Int128, Int128); 406*e9d07601SFrédéric Pétrot 4070846beb3SRichard Henderson #endif /* CONFIG_INT128 */ 4082484cd9cSMatheus Ferst 4092484cd9cSMatheus Ferst static inline void bswap128s(Int128 *s) 4102484cd9cSMatheus Ferst { 4112484cd9cSMatheus Ferst *s = bswap128(*s); 4122484cd9cSMatheus Ferst } 4132484cd9cSMatheus Ferst 414*e9d07601SFrédéric Pétrot #define UINT128_MAX int128_make128(~0LL, ~0LL) 415*e9d07601SFrédéric Pétrot 4160846beb3SRichard Henderson #endif /* INT128_H */ 417