1b7cd3db6SAvi Kivity #ifndef INT128_H 2b7cd3db6SAvi Kivity #define INT128_H 3b7cd3db6SAvi Kivity 47ebee43eSRichard Henderson #include "qemu/bswap.h" 50846beb3SRichard Henderson 6*2484cd9cSMatheus 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 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 { 158*2484cd9cSMatheus Ferst #if __has_builtin(__builtin_bswap128) 159*2484cd9cSMatheus Ferst return __builtin_bswap128(a); 160*2484cd9cSMatheus Ferst #else 1617ebee43eSRichard Henderson return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a))); 162*2484cd9cSMatheus Ferst #endif 1637ebee43eSRichard Henderson } 1647ebee43eSRichard Henderson 1650846beb3SRichard Henderson #else /* !CONFIG_INT128 */ 1666046c620SPaolo Bonzini 167b7cd3db6SAvi Kivity typedef struct Int128 Int128; 168b7cd3db6SAvi Kivity 169181b0c33SMatheus Ferst /* 170181b0c33SMatheus Ferst * We guarantee that the in-memory byte representation of an 171181b0c33SMatheus Ferst * Int128 is that of a host-endian-order 128-bit integer 172181b0c33SMatheus Ferst * (whether using this struct or the __int128_t version of the type). 173181b0c33SMatheus Ferst * Some code using this type relies on this (eg when copying it into 174181b0c33SMatheus Ferst * guest memory or a gdb protocol buffer, or by using Int128 in 175181b0c33SMatheus Ferst * a union with other integer types). 176181b0c33SMatheus Ferst */ 177b7cd3db6SAvi Kivity struct Int128 { 178181b0c33SMatheus Ferst #ifdef HOST_WORDS_BIGENDIAN 179181b0c33SMatheus Ferst int64_t hi; 180181b0c33SMatheus Ferst uint64_t lo; 181181b0c33SMatheus Ferst #else 182b7cd3db6SAvi Kivity uint64_t lo; 183b7cd3db6SAvi Kivity int64_t hi; 184181b0c33SMatheus Ferst #endif 185b7cd3db6SAvi Kivity }; 186b7cd3db6SAvi Kivity 187b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a) 188b7cd3db6SAvi Kivity { 189181b0c33SMatheus Ferst return (Int128) { .lo = a, .hi = 0 }; 190b7cd3db6SAvi Kivity } 191b7cd3db6SAvi Kivity 192703235a3SPeter Maydell static inline Int128 int128_makes64(int64_t a) 193703235a3SPeter Maydell { 194181b0c33SMatheus Ferst return (Int128) { .lo = a, .hi = a >> 63 }; 195703235a3SPeter Maydell } 196703235a3SPeter Maydell 1971edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi) 1981edaeee0SRichard Henderson { 199181b0c33SMatheus Ferst return (Int128) { .lo = lo, .hi = hi }; 2001edaeee0SRichard Henderson } 2011edaeee0SRichard Henderson 202b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a) 203b7cd3db6SAvi Kivity { 204b7cd3db6SAvi Kivity assert(!a.hi); 205b7cd3db6SAvi Kivity return a.lo; 206b7cd3db6SAvi Kivity } 207b7cd3db6SAvi Kivity 208258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a) 209258dfaaaSRichard Henderson { 210258dfaaaSRichard Henderson return a.lo; 211258dfaaaSRichard Henderson } 212258dfaaaSRichard Henderson 213258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a) 214258dfaaaSRichard Henderson { 215258dfaaaSRichard Henderson return a.hi; 216258dfaaaSRichard Henderson } 217258dfaaaSRichard Henderson 218b7cd3db6SAvi Kivity static inline Int128 int128_zero(void) 219b7cd3db6SAvi Kivity { 220b7cd3db6SAvi Kivity return int128_make64(0); 221b7cd3db6SAvi Kivity } 222b7cd3db6SAvi Kivity 223b7cd3db6SAvi Kivity static inline Int128 int128_one(void) 224b7cd3db6SAvi Kivity { 225b7cd3db6SAvi Kivity return int128_make64(1); 226b7cd3db6SAvi Kivity } 227b7cd3db6SAvi Kivity 228b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void) 229b7cd3db6SAvi Kivity { 230181b0c33SMatheus Ferst return int128_make128(0, 1); 231b7cd3db6SAvi Kivity } 232b7cd3db6SAvi Kivity 23312e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a) 23412e1129bSAlexey Kardashevskiy { 235181b0c33SMatheus Ferst return int128_make128(a, (a < 0) ? -1 : 0); 23612e1129bSAlexey Kardashevskiy } 23712e1129bSAlexey Kardashevskiy 238052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b) 239052e87b0SPaolo Bonzini { 240181b0c33SMatheus Ferst return int128_make128(a.lo & b.lo, a.hi & b.hi); 241052e87b0SPaolo Bonzini } 242052e87b0SPaolo Bonzini 24308895cdaSRichard Henderson static inline Int128 int128_or(Int128 a, Int128 b) 24408895cdaSRichard Henderson { 245181b0c33SMatheus Ferst return int128_make128(a.lo | b.lo, a.hi | b.hi); 24608895cdaSRichard Henderson } 24708895cdaSRichard Henderson 248052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n) 249052e87b0SPaolo Bonzini { 250052e87b0SPaolo Bonzini int64_t h; 251052e87b0SPaolo Bonzini if (!n) { 252052e87b0SPaolo Bonzini return a; 253052e87b0SPaolo Bonzini } 254052e87b0SPaolo Bonzini h = a.hi >> (n & 63); 255052e87b0SPaolo Bonzini if (n >= 64) { 2561edaeee0SRichard Henderson return int128_make128(h, h >> 63); 257052e87b0SPaolo Bonzini } else { 2581edaeee0SRichard Henderson return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); 259052e87b0SPaolo Bonzini } 260052e87b0SPaolo Bonzini } 261052e87b0SPaolo Bonzini 2625be4dd04SRichard Henderson static inline Int128 int128_lshift(Int128 a, int n) 2635be4dd04SRichard Henderson { 2645be4dd04SRichard Henderson uint64_t l = a.lo << (n & 63); 2655be4dd04SRichard Henderson if (n >= 64) { 2665be4dd04SRichard Henderson return int128_make128(0, l); 2675be4dd04SRichard Henderson } else if (n > 0) { 2685be4dd04SRichard Henderson return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n))); 2695be4dd04SRichard Henderson } 2705be4dd04SRichard Henderson return a; 2715be4dd04SRichard Henderson } 2725be4dd04SRichard Henderson 273b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b) 274b7cd3db6SAvi Kivity { 2756046c620SPaolo Bonzini uint64_t lo = a.lo + b.lo; 2766046c620SPaolo Bonzini 2776046c620SPaolo Bonzini /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, 2786046c620SPaolo Bonzini * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. 2796046c620SPaolo Bonzini * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. 2806046c620SPaolo Bonzini * 2816046c620SPaolo Bonzini * So the carry is lo < a.lo. 2826046c620SPaolo Bonzini */ 2831edaeee0SRichard Henderson return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); 284b7cd3db6SAvi Kivity } 285b7cd3db6SAvi Kivity 286b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a) 287b7cd3db6SAvi Kivity { 2886046c620SPaolo Bonzini uint64_t lo = -a.lo; 2891edaeee0SRichard Henderson return int128_make128(lo, ~(uint64_t)a.hi + !lo); 290b7cd3db6SAvi Kivity } 291b7cd3db6SAvi Kivity 292b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b) 293b7cd3db6SAvi Kivity { 2941edaeee0SRichard Henderson return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); 295b7cd3db6SAvi Kivity } 296b7cd3db6SAvi Kivity 297b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a) 298b7cd3db6SAvi Kivity { 299b7cd3db6SAvi Kivity return a.hi >= 0; 300b7cd3db6SAvi Kivity } 301b7cd3db6SAvi Kivity 302b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b) 303b7cd3db6SAvi Kivity { 304b7cd3db6SAvi Kivity return a.lo == b.lo && a.hi == b.hi; 305b7cd3db6SAvi Kivity } 306b7cd3db6SAvi Kivity 307b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b) 308b7cd3db6SAvi Kivity { 309b7cd3db6SAvi Kivity return !int128_eq(a, b); 310b7cd3db6SAvi Kivity } 311b7cd3db6SAvi Kivity 312b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b) 313b7cd3db6SAvi Kivity { 3146046c620SPaolo Bonzini return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); 315b7cd3db6SAvi Kivity } 316b7cd3db6SAvi Kivity 317b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b) 318b7cd3db6SAvi Kivity { 319b7cd3db6SAvi Kivity return !int128_ge(a, b); 320b7cd3db6SAvi Kivity } 321b7cd3db6SAvi Kivity 322b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b) 323b7cd3db6SAvi Kivity { 324b7cd3db6SAvi Kivity return int128_ge(b, a); 325b7cd3db6SAvi Kivity } 326b7cd3db6SAvi Kivity 327b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b) 328b7cd3db6SAvi Kivity { 329b7cd3db6SAvi Kivity return !int128_le(a, b); 330b7cd3db6SAvi Kivity } 331b7cd3db6SAvi Kivity 332b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a) 333b7cd3db6SAvi Kivity { 334b7cd3db6SAvi Kivity return a.lo || a.hi; 335b7cd3db6SAvi Kivity } 336b7cd3db6SAvi Kivity 337b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b) 338b7cd3db6SAvi Kivity { 339b7cd3db6SAvi Kivity return int128_le(a, b) ? a : b; 340b7cd3db6SAvi Kivity } 341b7cd3db6SAvi Kivity 342b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b) 343b7cd3db6SAvi Kivity { 344b7cd3db6SAvi Kivity return int128_ge(a, b) ? a : b; 345b7cd3db6SAvi Kivity } 346b7cd3db6SAvi Kivity 347b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b) 348b7cd3db6SAvi Kivity { 349b7cd3db6SAvi Kivity *a = int128_add(*a, b); 350b7cd3db6SAvi Kivity } 351b7cd3db6SAvi Kivity 352b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b) 353b7cd3db6SAvi Kivity { 354b7cd3db6SAvi Kivity *a = int128_sub(*a, b); 355b7cd3db6SAvi Kivity } 356b7cd3db6SAvi Kivity 357*2484cd9cSMatheus Ferst static inline Int128 bswap128(Int128 a) 358*2484cd9cSMatheus Ferst { 359*2484cd9cSMatheus Ferst return int128_make128(bswap64(a.hi), bswap64(a.lo)); 360*2484cd9cSMatheus Ferst } 361*2484cd9cSMatheus Ferst 3620846beb3SRichard Henderson #endif /* CONFIG_INT128 */ 363*2484cd9cSMatheus Ferst 364*2484cd9cSMatheus Ferst static inline void bswap128s(Int128 *s) 365*2484cd9cSMatheus Ferst { 366*2484cd9cSMatheus Ferst *s = bswap128(*s); 367*2484cd9cSMatheus Ferst } 368*2484cd9cSMatheus Ferst 3690846beb3SRichard Henderson #endif /* INT128_H */ 370