1b7cd3db6SAvi Kivity #ifndef INT128_H 2b7cd3db6SAvi Kivity #define INT128_H 3b7cd3db6SAvi Kivity 46046c620SPaolo Bonzini 5b7cd3db6SAvi Kivity typedef struct Int128 Int128; 6b7cd3db6SAvi Kivity 7b7cd3db6SAvi Kivity struct Int128 { 8b7cd3db6SAvi Kivity uint64_t lo; 9b7cd3db6SAvi Kivity int64_t hi; 10b7cd3db6SAvi Kivity }; 11b7cd3db6SAvi Kivity 12b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a) 13b7cd3db6SAvi Kivity { 14b7cd3db6SAvi Kivity return (Int128) { a, 0 }; 15b7cd3db6SAvi Kivity } 16b7cd3db6SAvi Kivity 17b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a) 18b7cd3db6SAvi Kivity { 19b7cd3db6SAvi Kivity assert(!a.hi); 20b7cd3db6SAvi Kivity return a.lo; 21b7cd3db6SAvi Kivity } 22b7cd3db6SAvi Kivity 23*258dfaaaSRichard Henderson static inline uint64_t int128_getlo(Int128 a) 24*258dfaaaSRichard Henderson { 25*258dfaaaSRichard Henderson return a.lo; 26*258dfaaaSRichard Henderson } 27*258dfaaaSRichard Henderson 28*258dfaaaSRichard Henderson static inline int64_t int128_gethi(Int128 a) 29*258dfaaaSRichard Henderson { 30*258dfaaaSRichard Henderson return a.hi; 31*258dfaaaSRichard Henderson } 32*258dfaaaSRichard Henderson 33b7cd3db6SAvi Kivity static inline Int128 int128_zero(void) 34b7cd3db6SAvi Kivity { 35b7cd3db6SAvi Kivity return int128_make64(0); 36b7cd3db6SAvi Kivity } 37b7cd3db6SAvi Kivity 38b7cd3db6SAvi Kivity static inline Int128 int128_one(void) 39b7cd3db6SAvi Kivity { 40b7cd3db6SAvi Kivity return int128_make64(1); 41b7cd3db6SAvi Kivity } 42b7cd3db6SAvi Kivity 43b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void) 44b7cd3db6SAvi Kivity { 45b7cd3db6SAvi Kivity return (Int128) { 0, 1 }; 46b7cd3db6SAvi Kivity } 47b7cd3db6SAvi Kivity 4812e1129bSAlexey Kardashevskiy static inline Int128 int128_exts64(int64_t a) 4912e1129bSAlexey Kardashevskiy { 5012e1129bSAlexey Kardashevskiy return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 }; 5112e1129bSAlexey Kardashevskiy } 5212e1129bSAlexey Kardashevskiy 53052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b) 54052e87b0SPaolo Bonzini { 55052e87b0SPaolo Bonzini return (Int128) { a.lo & b.lo, a.hi & b.hi }; 56052e87b0SPaolo Bonzini } 57052e87b0SPaolo Bonzini 58052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n) 59052e87b0SPaolo Bonzini { 60052e87b0SPaolo Bonzini int64_t h; 61052e87b0SPaolo Bonzini if (!n) { 62052e87b0SPaolo Bonzini return a; 63052e87b0SPaolo Bonzini } 64052e87b0SPaolo Bonzini h = a.hi >> (n & 63); 65052e87b0SPaolo Bonzini if (n >= 64) { 66052e87b0SPaolo Bonzini return (Int128) { h, h >> 63 }; 67052e87b0SPaolo Bonzini } else { 68423d00c8SPeter Maydell return (Int128) { (a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h }; 69052e87b0SPaolo Bonzini } 70052e87b0SPaolo Bonzini } 71052e87b0SPaolo Bonzini 72b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b) 73b7cd3db6SAvi Kivity { 746046c620SPaolo Bonzini uint64_t lo = a.lo + b.lo; 756046c620SPaolo Bonzini 766046c620SPaolo Bonzini /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, 776046c620SPaolo Bonzini * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. 786046c620SPaolo Bonzini * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. 796046c620SPaolo Bonzini * 806046c620SPaolo Bonzini * So the carry is lo < a.lo. 816046c620SPaolo Bonzini */ 826046c620SPaolo Bonzini return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) }; 83b7cd3db6SAvi Kivity } 84b7cd3db6SAvi Kivity 85b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a) 86b7cd3db6SAvi Kivity { 876046c620SPaolo Bonzini uint64_t lo = -a.lo; 886046c620SPaolo Bonzini return (Int128) { lo, ~(uint64_t)a.hi + !lo }; 89b7cd3db6SAvi Kivity } 90b7cd3db6SAvi Kivity 91b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b) 92b7cd3db6SAvi Kivity { 93423d00c8SPeter Maydell return (Int128){ a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo) }; 94b7cd3db6SAvi Kivity } 95b7cd3db6SAvi Kivity 96b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a) 97b7cd3db6SAvi Kivity { 98b7cd3db6SAvi Kivity return a.hi >= 0; 99b7cd3db6SAvi Kivity } 100b7cd3db6SAvi Kivity 101b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b) 102b7cd3db6SAvi Kivity { 103b7cd3db6SAvi Kivity return a.lo == b.lo && a.hi == b.hi; 104b7cd3db6SAvi Kivity } 105b7cd3db6SAvi Kivity 106b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b) 107b7cd3db6SAvi Kivity { 108b7cd3db6SAvi Kivity return !int128_eq(a, b); 109b7cd3db6SAvi Kivity } 110b7cd3db6SAvi Kivity 111b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b) 112b7cd3db6SAvi Kivity { 1136046c620SPaolo Bonzini return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); 114b7cd3db6SAvi Kivity } 115b7cd3db6SAvi Kivity 116b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b) 117b7cd3db6SAvi Kivity { 118b7cd3db6SAvi Kivity return !int128_ge(a, b); 119b7cd3db6SAvi Kivity } 120b7cd3db6SAvi Kivity 121b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b) 122b7cd3db6SAvi Kivity { 123b7cd3db6SAvi Kivity return int128_ge(b, a); 124b7cd3db6SAvi Kivity } 125b7cd3db6SAvi Kivity 126b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b) 127b7cd3db6SAvi Kivity { 128b7cd3db6SAvi Kivity return !int128_le(a, b); 129b7cd3db6SAvi Kivity } 130b7cd3db6SAvi Kivity 131b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a) 132b7cd3db6SAvi Kivity { 133b7cd3db6SAvi Kivity return a.lo || a.hi; 134b7cd3db6SAvi Kivity } 135b7cd3db6SAvi Kivity 136b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b) 137b7cd3db6SAvi Kivity { 138b7cd3db6SAvi Kivity return int128_le(a, b) ? a : b; 139b7cd3db6SAvi Kivity } 140b7cd3db6SAvi Kivity 141b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b) 142b7cd3db6SAvi Kivity { 143b7cd3db6SAvi Kivity return int128_ge(a, b) ? a : b; 144b7cd3db6SAvi Kivity } 145b7cd3db6SAvi Kivity 146b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b) 147b7cd3db6SAvi Kivity { 148b7cd3db6SAvi Kivity *a = int128_add(*a, b); 149b7cd3db6SAvi Kivity } 150b7cd3db6SAvi Kivity 151b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b) 152b7cd3db6SAvi Kivity { 153b7cd3db6SAvi Kivity *a = int128_sub(*a, b); 154b7cd3db6SAvi Kivity } 155b7cd3db6SAvi Kivity 156b7cd3db6SAvi Kivity #endif 157