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 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 610846beb3SRichard Henderson static inline Int128 int128_and(Int128 a, Int128 b) 620846beb3SRichard Henderson { 630846beb3SRichard Henderson return a & b; 640846beb3SRichard Henderson } 650846beb3SRichard Henderson 6608895cdaSRichard Henderson static inline Int128 int128_or(Int128 a, Int128 b) 6708895cdaSRichard Henderson { 6808895cdaSRichard Henderson return a | b; 6908895cdaSRichard Henderson } 7008895cdaSRichard Henderson 710846beb3SRichard Henderson static inline Int128 int128_rshift(Int128 a, int n) 720846beb3SRichard Henderson { 730846beb3SRichard Henderson return a >> n; 740846beb3SRichard Henderson } 750846beb3SRichard Henderson 765be4dd04SRichard Henderson static inline Int128 int128_lshift(Int128 a, int n) 775be4dd04SRichard Henderson { 785be4dd04SRichard Henderson return a << n; 795be4dd04SRichard Henderson } 805be4dd04SRichard Henderson 810846beb3SRichard Henderson static inline Int128 int128_add(Int128 a, Int128 b) 820846beb3SRichard Henderson { 830846beb3SRichard Henderson return a + b; 840846beb3SRichard Henderson } 850846beb3SRichard Henderson 860846beb3SRichard Henderson static inline Int128 int128_neg(Int128 a) 870846beb3SRichard Henderson { 880846beb3SRichard Henderson return -a; 890846beb3SRichard Henderson } 900846beb3SRichard Henderson 910846beb3SRichard Henderson static inline Int128 int128_sub(Int128 a, Int128 b) 920846beb3SRichard Henderson { 930846beb3SRichard Henderson return a - b; 940846beb3SRichard Henderson } 950846beb3SRichard Henderson 960846beb3SRichard Henderson static inline bool int128_nonneg(Int128 a) 970846beb3SRichard Henderson { 980846beb3SRichard Henderson return a >= 0; 990846beb3SRichard Henderson } 1000846beb3SRichard Henderson 1010846beb3SRichard Henderson static inline bool int128_eq(Int128 a, Int128 b) 1020846beb3SRichard Henderson { 1030846beb3SRichard Henderson return a == b; 1040846beb3SRichard Henderson } 1050846beb3SRichard Henderson 1060846beb3SRichard Henderson static inline bool int128_ne(Int128 a, Int128 b) 1070846beb3SRichard Henderson { 1080846beb3SRichard Henderson return a != b; 1090846beb3SRichard Henderson } 1100846beb3SRichard Henderson 1110846beb3SRichard Henderson static inline bool int128_ge(Int128 a, Int128 b) 1120846beb3SRichard Henderson { 1130846beb3SRichard Henderson return a >= b; 1140846beb3SRichard Henderson } 1150846beb3SRichard Henderson 1160846beb3SRichard Henderson static inline bool int128_lt(Int128 a, Int128 b) 1170846beb3SRichard Henderson { 1180846beb3SRichard Henderson return a < b; 1190846beb3SRichard Henderson } 1200846beb3SRichard Henderson 1210846beb3SRichard Henderson static inline bool int128_le(Int128 a, Int128 b) 1220846beb3SRichard Henderson { 1230846beb3SRichard Henderson return a <= b; 1240846beb3SRichard Henderson } 1250846beb3SRichard Henderson 1260846beb3SRichard Henderson static inline bool int128_gt(Int128 a, Int128 b) 1270846beb3SRichard Henderson { 1280846beb3SRichard Henderson return a > b; 1290846beb3SRichard Henderson } 1300846beb3SRichard Henderson 1310846beb3SRichard Henderson static inline bool int128_nz(Int128 a) 1320846beb3SRichard Henderson { 1330846beb3SRichard Henderson return a != 0; 1340846beb3SRichard Henderson } 1350846beb3SRichard Henderson 1360846beb3SRichard Henderson static inline Int128 int128_min(Int128 a, Int128 b) 1370846beb3SRichard Henderson { 1380846beb3SRichard Henderson return a < b ? a : b; 1390846beb3SRichard Henderson } 1400846beb3SRichard Henderson 1410846beb3SRichard Henderson static inline Int128 int128_max(Int128 a, Int128 b) 1420846beb3SRichard Henderson { 1430846beb3SRichard Henderson return a > b ? a : b; 1440846beb3SRichard Henderson } 1450846beb3SRichard Henderson 1460846beb3SRichard Henderson static inline void int128_addto(Int128 *a, Int128 b) 1470846beb3SRichard Henderson { 1480846beb3SRichard Henderson *a += b; 1490846beb3SRichard Henderson } 1500846beb3SRichard Henderson 1510846beb3SRichard Henderson static inline void int128_subfrom(Int128 *a, Int128 b) 1520846beb3SRichard Henderson { 1530846beb3SRichard Henderson *a -= b; 1540846beb3SRichard Henderson } 1550846beb3SRichard Henderson 1567ebee43eSRichard Henderson static inline Int128 bswap128(Int128 a) 1577ebee43eSRichard Henderson { 1587ebee43eSRichard Henderson return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a))); 1597ebee43eSRichard Henderson } 1607ebee43eSRichard Henderson 1610846beb3SRichard Henderson #else /* !CONFIG_INT128 */ 1626046c620SPaolo Bonzini 163b7cd3db6SAvi Kivity typedef struct Int128 Int128; 164b7cd3db6SAvi Kivity 165*181b0c33SMatheus Ferst /* 166*181b0c33SMatheus Ferst * We guarantee that the in-memory byte representation of an 167*181b0c33SMatheus Ferst * Int128 is that of a host-endian-order 128-bit integer 168*181b0c33SMatheus Ferst * (whether using this struct or the __int128_t version of the type). 169*181b0c33SMatheus Ferst * Some code using this type relies on this (eg when copying it into 170*181b0c33SMatheus Ferst * guest memory or a gdb protocol buffer, or by using Int128 in 171*181b0c33SMatheus Ferst * a union with other integer types). 172*181b0c33SMatheus Ferst */ 173b7cd3db6SAvi Kivity struct Int128 { 174*181b0c33SMatheus Ferst #ifdef HOST_WORDS_BIGENDIAN 175*181b0c33SMatheus Ferst int64_t hi; 176*181b0c33SMatheus Ferst uint64_t lo; 177*181b0c33SMatheus Ferst #else 178b7cd3db6SAvi Kivity uint64_t lo; 179b7cd3db6SAvi Kivity int64_t hi; 180*181b0c33SMatheus Ferst #endif 181b7cd3db6SAvi Kivity }; 182b7cd3db6SAvi Kivity 183b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a) 184b7cd3db6SAvi Kivity { 185*181b0c33SMatheus Ferst return (Int128) { .lo = a, .hi = 0 }; 186b7cd3db6SAvi Kivity } 187b7cd3db6SAvi Kivity 188703235a3SPeter Maydell static inline Int128 int128_makes64(int64_t a) 189703235a3SPeter Maydell { 190*181b0c33SMatheus Ferst return (Int128) { .lo = a, .hi = a >> 63 }; 191703235a3SPeter Maydell } 192703235a3SPeter Maydell 1931edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi) 1941edaeee0SRichard Henderson { 195*181b0c33SMatheus Ferst return (Int128) { .lo = lo, .hi = hi }; 1961edaeee0SRichard Henderson } 1971edaeee0SRichard Henderson 198b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a) 199b7cd3db6SAvi Kivity { 200b7cd3db6SAvi Kivity assert(!a.hi); 201b7cd3db6SAvi Kivity return a.lo; 202b7cd3db6SAvi Kivity } 203b7cd3db6SAvi Kivity 204258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a) 205258dfaaaSRichard Henderson { 206258dfaaaSRichard Henderson return a.lo; 207258dfaaaSRichard Henderson } 208258dfaaaSRichard Henderson 209258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a) 210258dfaaaSRichard Henderson { 211258dfaaaSRichard Henderson return a.hi; 212258dfaaaSRichard Henderson } 213258dfaaaSRichard Henderson 214b7cd3db6SAvi Kivity static inline Int128 int128_zero(void) 215b7cd3db6SAvi Kivity { 216b7cd3db6SAvi Kivity return int128_make64(0); 217b7cd3db6SAvi Kivity } 218b7cd3db6SAvi Kivity 219b7cd3db6SAvi Kivity static inline Int128 int128_one(void) 220b7cd3db6SAvi Kivity { 221b7cd3db6SAvi Kivity return int128_make64(1); 222b7cd3db6SAvi Kivity } 223b7cd3db6SAvi Kivity 224b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void) 225b7cd3db6SAvi Kivity { 226*181b0c33SMatheus Ferst return int128_make128(0, 1); 227b7cd3db6SAvi Kivity } 228b7cd3db6SAvi Kivity 22912e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a) 23012e1129bSAlexey Kardashevskiy { 231*181b0c33SMatheus Ferst return int128_make128(a, (a < 0) ? -1 : 0); 23212e1129bSAlexey Kardashevskiy } 23312e1129bSAlexey Kardashevskiy 234052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b) 235052e87b0SPaolo Bonzini { 236*181b0c33SMatheus Ferst return int128_make128(a.lo & b.lo, a.hi & b.hi); 237052e87b0SPaolo Bonzini } 238052e87b0SPaolo Bonzini 23908895cdaSRichard Henderson static inline Int128 int128_or(Int128 a, Int128 b) 24008895cdaSRichard Henderson { 241*181b0c33SMatheus Ferst return int128_make128(a.lo | b.lo, a.hi | b.hi); 24208895cdaSRichard Henderson } 24308895cdaSRichard Henderson 244052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n) 245052e87b0SPaolo Bonzini { 246052e87b0SPaolo Bonzini int64_t h; 247052e87b0SPaolo Bonzini if (!n) { 248052e87b0SPaolo Bonzini return a; 249052e87b0SPaolo Bonzini } 250052e87b0SPaolo Bonzini h = a.hi >> (n & 63); 251052e87b0SPaolo Bonzini if (n >= 64) { 2521edaeee0SRichard Henderson return int128_make128(h, h >> 63); 253052e87b0SPaolo Bonzini } else { 2541edaeee0SRichard Henderson return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); 255052e87b0SPaolo Bonzini } 256052e87b0SPaolo Bonzini } 257052e87b0SPaolo Bonzini 2585be4dd04SRichard Henderson static inline Int128 int128_lshift(Int128 a, int n) 2595be4dd04SRichard Henderson { 2605be4dd04SRichard Henderson uint64_t l = a.lo << (n & 63); 2615be4dd04SRichard Henderson if (n >= 64) { 2625be4dd04SRichard Henderson return int128_make128(0, l); 2635be4dd04SRichard Henderson } else if (n > 0) { 2645be4dd04SRichard Henderson return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n))); 2655be4dd04SRichard Henderson } 2665be4dd04SRichard Henderson return a; 2675be4dd04SRichard Henderson } 2685be4dd04SRichard Henderson 269b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b) 270b7cd3db6SAvi Kivity { 2716046c620SPaolo Bonzini uint64_t lo = a.lo + b.lo; 2726046c620SPaolo Bonzini 2736046c620SPaolo Bonzini /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, 2746046c620SPaolo Bonzini * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. 2756046c620SPaolo Bonzini * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. 2766046c620SPaolo Bonzini * 2776046c620SPaolo Bonzini * So the carry is lo < a.lo. 2786046c620SPaolo Bonzini */ 2791edaeee0SRichard Henderson return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); 280b7cd3db6SAvi Kivity } 281b7cd3db6SAvi Kivity 282b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a) 283b7cd3db6SAvi Kivity { 2846046c620SPaolo Bonzini uint64_t lo = -a.lo; 2851edaeee0SRichard Henderson return int128_make128(lo, ~(uint64_t)a.hi + !lo); 286b7cd3db6SAvi Kivity } 287b7cd3db6SAvi Kivity 288b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b) 289b7cd3db6SAvi Kivity { 2901edaeee0SRichard Henderson return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); 291b7cd3db6SAvi Kivity } 292b7cd3db6SAvi Kivity 293b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a) 294b7cd3db6SAvi Kivity { 295b7cd3db6SAvi Kivity return a.hi >= 0; 296b7cd3db6SAvi Kivity } 297b7cd3db6SAvi Kivity 298b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b) 299b7cd3db6SAvi Kivity { 300b7cd3db6SAvi Kivity return a.lo == b.lo && a.hi == b.hi; 301b7cd3db6SAvi Kivity } 302b7cd3db6SAvi Kivity 303b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b) 304b7cd3db6SAvi Kivity { 305b7cd3db6SAvi Kivity return !int128_eq(a, b); 306b7cd3db6SAvi Kivity } 307b7cd3db6SAvi Kivity 308b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b) 309b7cd3db6SAvi Kivity { 3106046c620SPaolo Bonzini return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); 311b7cd3db6SAvi Kivity } 312b7cd3db6SAvi Kivity 313b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b) 314b7cd3db6SAvi Kivity { 315b7cd3db6SAvi Kivity return !int128_ge(a, b); 316b7cd3db6SAvi Kivity } 317b7cd3db6SAvi Kivity 318b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b) 319b7cd3db6SAvi Kivity { 320b7cd3db6SAvi Kivity return int128_ge(b, a); 321b7cd3db6SAvi Kivity } 322b7cd3db6SAvi Kivity 323b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b) 324b7cd3db6SAvi Kivity { 325b7cd3db6SAvi Kivity return !int128_le(a, b); 326b7cd3db6SAvi Kivity } 327b7cd3db6SAvi Kivity 328b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a) 329b7cd3db6SAvi Kivity { 330b7cd3db6SAvi Kivity return a.lo || a.hi; 331b7cd3db6SAvi Kivity } 332b7cd3db6SAvi Kivity 333b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b) 334b7cd3db6SAvi Kivity { 335b7cd3db6SAvi Kivity return int128_le(a, b) ? a : b; 336b7cd3db6SAvi Kivity } 337b7cd3db6SAvi Kivity 338b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b) 339b7cd3db6SAvi Kivity { 340b7cd3db6SAvi Kivity return int128_ge(a, b) ? a : b; 341b7cd3db6SAvi Kivity } 342b7cd3db6SAvi Kivity 343b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b) 344b7cd3db6SAvi Kivity { 345b7cd3db6SAvi Kivity *a = int128_add(*a, b); 346b7cd3db6SAvi Kivity } 347b7cd3db6SAvi Kivity 348b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b) 349b7cd3db6SAvi Kivity { 350b7cd3db6SAvi Kivity *a = int128_sub(*a, b); 351b7cd3db6SAvi Kivity } 352b7cd3db6SAvi Kivity 3530846beb3SRichard Henderson #endif /* CONFIG_INT128 */ 3540846beb3SRichard Henderson #endif /* INT128_H */ 355