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 610846beb3SRichard Henderson static inline Int128 int128_rshift(Int128 a, int n) 620846beb3SRichard Henderson { 630846beb3SRichard Henderson return a >> n; 640846beb3SRichard Henderson } 650846beb3SRichard Henderson 66*5be4dd04SRichard Henderson static inline Int128 int128_lshift(Int128 a, int n) 67*5be4dd04SRichard Henderson { 68*5be4dd04SRichard Henderson return a << n; 69*5be4dd04SRichard Henderson } 70*5be4dd04SRichard Henderson 710846beb3SRichard Henderson static inline Int128 int128_add(Int128 a, Int128 b) 720846beb3SRichard Henderson { 730846beb3SRichard Henderson return a + b; 740846beb3SRichard Henderson } 750846beb3SRichard Henderson 760846beb3SRichard Henderson static inline Int128 int128_neg(Int128 a) 770846beb3SRichard Henderson { 780846beb3SRichard Henderson return -a; 790846beb3SRichard Henderson } 800846beb3SRichard Henderson 810846beb3SRichard Henderson static inline Int128 int128_sub(Int128 a, Int128 b) 820846beb3SRichard Henderson { 830846beb3SRichard Henderson return a - b; 840846beb3SRichard Henderson } 850846beb3SRichard Henderson 860846beb3SRichard Henderson static inline bool int128_nonneg(Int128 a) 870846beb3SRichard Henderson { 880846beb3SRichard Henderson return a >= 0; 890846beb3SRichard Henderson } 900846beb3SRichard Henderson 910846beb3SRichard Henderson static inline bool int128_eq(Int128 a, Int128 b) 920846beb3SRichard Henderson { 930846beb3SRichard Henderson return a == b; 940846beb3SRichard Henderson } 950846beb3SRichard Henderson 960846beb3SRichard Henderson static inline bool int128_ne(Int128 a, Int128 b) 970846beb3SRichard Henderson { 980846beb3SRichard Henderson return a != b; 990846beb3SRichard Henderson } 1000846beb3SRichard Henderson 1010846beb3SRichard Henderson static inline bool int128_ge(Int128 a, Int128 b) 1020846beb3SRichard Henderson { 1030846beb3SRichard Henderson return a >= b; 1040846beb3SRichard Henderson } 1050846beb3SRichard Henderson 1060846beb3SRichard Henderson static inline bool int128_lt(Int128 a, Int128 b) 1070846beb3SRichard Henderson { 1080846beb3SRichard Henderson return a < b; 1090846beb3SRichard Henderson } 1100846beb3SRichard Henderson 1110846beb3SRichard Henderson static inline bool int128_le(Int128 a, Int128 b) 1120846beb3SRichard Henderson { 1130846beb3SRichard Henderson return a <= b; 1140846beb3SRichard Henderson } 1150846beb3SRichard Henderson 1160846beb3SRichard Henderson static inline bool int128_gt(Int128 a, Int128 b) 1170846beb3SRichard Henderson { 1180846beb3SRichard Henderson return a > b; 1190846beb3SRichard Henderson } 1200846beb3SRichard Henderson 1210846beb3SRichard Henderson static inline bool int128_nz(Int128 a) 1220846beb3SRichard Henderson { 1230846beb3SRichard Henderson return a != 0; 1240846beb3SRichard Henderson } 1250846beb3SRichard Henderson 1260846beb3SRichard Henderson static inline Int128 int128_min(Int128 a, Int128 b) 1270846beb3SRichard Henderson { 1280846beb3SRichard Henderson return a < b ? a : b; 1290846beb3SRichard Henderson } 1300846beb3SRichard Henderson 1310846beb3SRichard Henderson static inline Int128 int128_max(Int128 a, Int128 b) 1320846beb3SRichard Henderson { 1330846beb3SRichard Henderson return a > b ? a : b; 1340846beb3SRichard Henderson } 1350846beb3SRichard Henderson 1360846beb3SRichard Henderson static inline void int128_addto(Int128 *a, Int128 b) 1370846beb3SRichard Henderson { 1380846beb3SRichard Henderson *a += b; 1390846beb3SRichard Henderson } 1400846beb3SRichard Henderson 1410846beb3SRichard Henderson static inline void int128_subfrom(Int128 *a, Int128 b) 1420846beb3SRichard Henderson { 1430846beb3SRichard Henderson *a -= b; 1440846beb3SRichard Henderson } 1450846beb3SRichard Henderson 1467ebee43eSRichard Henderson static inline Int128 bswap128(Int128 a) 1477ebee43eSRichard Henderson { 1487ebee43eSRichard Henderson return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a))); 1497ebee43eSRichard Henderson } 1507ebee43eSRichard Henderson 1510846beb3SRichard Henderson #else /* !CONFIG_INT128 */ 1526046c620SPaolo Bonzini 153b7cd3db6SAvi Kivity typedef struct Int128 Int128; 154b7cd3db6SAvi Kivity 155b7cd3db6SAvi Kivity struct Int128 { 156b7cd3db6SAvi Kivity uint64_t lo; 157b7cd3db6SAvi Kivity int64_t hi; 158b7cd3db6SAvi Kivity }; 159b7cd3db6SAvi Kivity 160b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a) 161b7cd3db6SAvi Kivity { 162b7cd3db6SAvi Kivity return (Int128) { a, 0 }; 163b7cd3db6SAvi Kivity } 164b7cd3db6SAvi Kivity 1651edaeee0SRichard Henderson static inline Int128 int128_make128(uint64_t lo, uint64_t hi) 1661edaeee0SRichard Henderson { 1671edaeee0SRichard Henderson return (Int128) { lo, hi }; 1681edaeee0SRichard Henderson } 1691edaeee0SRichard Henderson 170b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a) 171b7cd3db6SAvi Kivity { 172b7cd3db6SAvi Kivity assert(!a.hi); 173b7cd3db6SAvi Kivity return a.lo; 174b7cd3db6SAvi Kivity } 175b7cd3db6SAvi Kivity 176258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a) 177258dfaaaSRichard Henderson { 178258dfaaaSRichard Henderson return a.lo; 179258dfaaaSRichard Henderson } 180258dfaaaSRichard Henderson 181258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a) 182258dfaaaSRichard Henderson { 183258dfaaaSRichard Henderson return a.hi; 184258dfaaaSRichard Henderson } 185258dfaaaSRichard Henderson 186b7cd3db6SAvi Kivity static inline Int128 int128_zero(void) 187b7cd3db6SAvi Kivity { 188b7cd3db6SAvi Kivity return int128_make64(0); 189b7cd3db6SAvi Kivity } 190b7cd3db6SAvi Kivity 191b7cd3db6SAvi Kivity static inline Int128 int128_one(void) 192b7cd3db6SAvi Kivity { 193b7cd3db6SAvi Kivity return int128_make64(1); 194b7cd3db6SAvi Kivity } 195b7cd3db6SAvi Kivity 196b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void) 197b7cd3db6SAvi Kivity { 198b7cd3db6SAvi Kivity return (Int128) { 0, 1 }; 199b7cd3db6SAvi Kivity } 200b7cd3db6SAvi Kivity 20112e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a) 20212e1129bSAlexey Kardashevskiy { 20312e1129bSAlexey Kardashevskiy return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 }; 20412e1129bSAlexey Kardashevskiy } 20512e1129bSAlexey Kardashevskiy 206052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b) 207052e87b0SPaolo Bonzini { 208052e87b0SPaolo Bonzini return (Int128) { a.lo & b.lo, a.hi & b.hi }; 209052e87b0SPaolo Bonzini } 210052e87b0SPaolo Bonzini 211052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n) 212052e87b0SPaolo Bonzini { 213052e87b0SPaolo Bonzini int64_t h; 214052e87b0SPaolo Bonzini if (!n) { 215052e87b0SPaolo Bonzini return a; 216052e87b0SPaolo Bonzini } 217052e87b0SPaolo Bonzini h = a.hi >> (n & 63); 218052e87b0SPaolo Bonzini if (n >= 64) { 2191edaeee0SRichard Henderson return int128_make128(h, h >> 63); 220052e87b0SPaolo Bonzini } else { 2211edaeee0SRichard Henderson return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); 222052e87b0SPaolo Bonzini } 223052e87b0SPaolo Bonzini } 224052e87b0SPaolo Bonzini 225*5be4dd04SRichard Henderson static inline Int128 int128_lshift(Int128 a, int n) 226*5be4dd04SRichard Henderson { 227*5be4dd04SRichard Henderson uint64_t l = a.lo << (n & 63); 228*5be4dd04SRichard Henderson if (n >= 64) { 229*5be4dd04SRichard Henderson return int128_make128(0, l); 230*5be4dd04SRichard Henderson } else if (n > 0) { 231*5be4dd04SRichard Henderson return int128_make128(l, (a.hi << n) | (a.lo >> (64 - n))); 232*5be4dd04SRichard Henderson } 233*5be4dd04SRichard Henderson return a; 234*5be4dd04SRichard Henderson } 235*5be4dd04SRichard Henderson 236b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b) 237b7cd3db6SAvi Kivity { 2386046c620SPaolo Bonzini uint64_t lo = a.lo + b.lo; 2396046c620SPaolo Bonzini 2406046c620SPaolo Bonzini /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, 2416046c620SPaolo Bonzini * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. 2426046c620SPaolo Bonzini * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. 2436046c620SPaolo Bonzini * 2446046c620SPaolo Bonzini * So the carry is lo < a.lo. 2456046c620SPaolo Bonzini */ 2461edaeee0SRichard Henderson return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); 247b7cd3db6SAvi Kivity } 248b7cd3db6SAvi Kivity 249b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a) 250b7cd3db6SAvi Kivity { 2516046c620SPaolo Bonzini uint64_t lo = -a.lo; 2521edaeee0SRichard Henderson return int128_make128(lo, ~(uint64_t)a.hi + !lo); 253b7cd3db6SAvi Kivity } 254b7cd3db6SAvi Kivity 255b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b) 256b7cd3db6SAvi Kivity { 2571edaeee0SRichard Henderson return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); 258b7cd3db6SAvi Kivity } 259b7cd3db6SAvi Kivity 260b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a) 261b7cd3db6SAvi Kivity { 262b7cd3db6SAvi Kivity return a.hi >= 0; 263b7cd3db6SAvi Kivity } 264b7cd3db6SAvi Kivity 265b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b) 266b7cd3db6SAvi Kivity { 267b7cd3db6SAvi Kivity return a.lo == b.lo && a.hi == b.hi; 268b7cd3db6SAvi Kivity } 269b7cd3db6SAvi Kivity 270b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b) 271b7cd3db6SAvi Kivity { 272b7cd3db6SAvi Kivity return !int128_eq(a, b); 273b7cd3db6SAvi Kivity } 274b7cd3db6SAvi Kivity 275b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b) 276b7cd3db6SAvi Kivity { 2776046c620SPaolo Bonzini return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); 278b7cd3db6SAvi Kivity } 279b7cd3db6SAvi Kivity 280b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b) 281b7cd3db6SAvi Kivity { 282b7cd3db6SAvi Kivity return !int128_ge(a, b); 283b7cd3db6SAvi Kivity } 284b7cd3db6SAvi Kivity 285b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b) 286b7cd3db6SAvi Kivity { 287b7cd3db6SAvi Kivity return int128_ge(b, a); 288b7cd3db6SAvi Kivity } 289b7cd3db6SAvi Kivity 290b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b) 291b7cd3db6SAvi Kivity { 292b7cd3db6SAvi Kivity return !int128_le(a, b); 293b7cd3db6SAvi Kivity } 294b7cd3db6SAvi Kivity 295b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a) 296b7cd3db6SAvi Kivity { 297b7cd3db6SAvi Kivity return a.lo || a.hi; 298b7cd3db6SAvi Kivity } 299b7cd3db6SAvi Kivity 300b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b) 301b7cd3db6SAvi Kivity { 302b7cd3db6SAvi Kivity return int128_le(a, b) ? a : b; 303b7cd3db6SAvi Kivity } 304b7cd3db6SAvi Kivity 305b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b) 306b7cd3db6SAvi Kivity { 307b7cd3db6SAvi Kivity return int128_ge(a, b) ? a : b; 308b7cd3db6SAvi Kivity } 309b7cd3db6SAvi Kivity 310b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b) 311b7cd3db6SAvi Kivity { 312b7cd3db6SAvi Kivity *a = int128_add(*a, b); 313b7cd3db6SAvi Kivity } 314b7cd3db6SAvi Kivity 315b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b) 316b7cd3db6SAvi Kivity { 317b7cd3db6SAvi Kivity *a = int128_sub(*a, b); 318b7cd3db6SAvi Kivity } 319b7cd3db6SAvi Kivity 3200846beb3SRichard Henderson #endif /* CONFIG_INT128 */ 3210846beb3SRichard Henderson #endif /* INT128_H */ 322