1b7cd3db6SAvi Kivity #ifndef INT128_H 2b7cd3db6SAvi Kivity #define INT128_H 3b7cd3db6SAvi Kivity 46046c620SPaolo Bonzini #include <assert.h> 56046c620SPaolo Bonzini #include <stdint.h> 66046c620SPaolo Bonzini #include <stdbool.h> 76046c620SPaolo Bonzini 8b7cd3db6SAvi Kivity typedef struct Int128 Int128; 9b7cd3db6SAvi Kivity 10b7cd3db6SAvi Kivity struct Int128 { 11b7cd3db6SAvi Kivity uint64_t lo; 12b7cd3db6SAvi Kivity int64_t hi; 13b7cd3db6SAvi Kivity }; 14b7cd3db6SAvi Kivity 15b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a) 16b7cd3db6SAvi Kivity { 17b7cd3db6SAvi Kivity return (Int128) { a, 0 }; 18b7cd3db6SAvi Kivity } 19b7cd3db6SAvi Kivity 20b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a) 21b7cd3db6SAvi Kivity { 22b7cd3db6SAvi Kivity assert(!a.hi); 23b7cd3db6SAvi Kivity return a.lo; 24b7cd3db6SAvi Kivity } 25b7cd3db6SAvi Kivity 26b7cd3db6SAvi Kivity static inline Int128 int128_zero(void) 27b7cd3db6SAvi Kivity { 28b7cd3db6SAvi Kivity return int128_make64(0); 29b7cd3db6SAvi Kivity } 30b7cd3db6SAvi Kivity 31b7cd3db6SAvi Kivity static inline Int128 int128_one(void) 32b7cd3db6SAvi Kivity { 33b7cd3db6SAvi Kivity return int128_make64(1); 34b7cd3db6SAvi Kivity } 35b7cd3db6SAvi Kivity 36b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void) 37b7cd3db6SAvi Kivity { 38b7cd3db6SAvi Kivity return (Int128) { 0, 1 }; 39b7cd3db6SAvi Kivity } 40b7cd3db6SAvi Kivity 41052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b) 42052e87b0SPaolo Bonzini { 43052e87b0SPaolo Bonzini return (Int128) { a.lo & b.lo, a.hi & b.hi }; 44052e87b0SPaolo Bonzini } 45052e87b0SPaolo Bonzini 46052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n) 47052e87b0SPaolo Bonzini { 48052e87b0SPaolo Bonzini int64_t h; 49052e87b0SPaolo Bonzini if (!n) { 50052e87b0SPaolo Bonzini return a; 51052e87b0SPaolo Bonzini } 52052e87b0SPaolo Bonzini h = a.hi >> (n & 63); 53052e87b0SPaolo Bonzini if (n >= 64) { 54052e87b0SPaolo Bonzini return (Int128) { h, h >> 63 }; 55052e87b0SPaolo Bonzini } else { 56*423d00c8SPeter Maydell return (Int128) { (a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h }; 57052e87b0SPaolo Bonzini } 58052e87b0SPaolo Bonzini } 59052e87b0SPaolo Bonzini 60b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b) 61b7cd3db6SAvi Kivity { 626046c620SPaolo Bonzini uint64_t lo = a.lo + b.lo; 636046c620SPaolo Bonzini 646046c620SPaolo Bonzini /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, 656046c620SPaolo Bonzini * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. 666046c620SPaolo Bonzini * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. 676046c620SPaolo Bonzini * 686046c620SPaolo Bonzini * So the carry is lo < a.lo. 696046c620SPaolo Bonzini */ 706046c620SPaolo Bonzini return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) }; 71b7cd3db6SAvi Kivity } 72b7cd3db6SAvi Kivity 73b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a) 74b7cd3db6SAvi Kivity { 756046c620SPaolo Bonzini uint64_t lo = -a.lo; 766046c620SPaolo Bonzini return (Int128) { lo, ~(uint64_t)a.hi + !lo }; 77b7cd3db6SAvi Kivity } 78b7cd3db6SAvi Kivity 79b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b) 80b7cd3db6SAvi Kivity { 81*423d00c8SPeter Maydell return (Int128){ a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo) }; 82b7cd3db6SAvi Kivity } 83b7cd3db6SAvi Kivity 84b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a) 85b7cd3db6SAvi Kivity { 86b7cd3db6SAvi Kivity return a.hi >= 0; 87b7cd3db6SAvi Kivity } 88b7cd3db6SAvi Kivity 89b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b) 90b7cd3db6SAvi Kivity { 91b7cd3db6SAvi Kivity return a.lo == b.lo && a.hi == b.hi; 92b7cd3db6SAvi Kivity } 93b7cd3db6SAvi Kivity 94b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b) 95b7cd3db6SAvi Kivity { 96b7cd3db6SAvi Kivity return !int128_eq(a, b); 97b7cd3db6SAvi Kivity } 98b7cd3db6SAvi Kivity 99b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b) 100b7cd3db6SAvi Kivity { 1016046c620SPaolo Bonzini return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); 102b7cd3db6SAvi Kivity } 103b7cd3db6SAvi Kivity 104b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b) 105b7cd3db6SAvi Kivity { 106b7cd3db6SAvi Kivity return !int128_ge(a, b); 107b7cd3db6SAvi Kivity } 108b7cd3db6SAvi Kivity 109b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b) 110b7cd3db6SAvi Kivity { 111b7cd3db6SAvi Kivity return int128_ge(b, a); 112b7cd3db6SAvi Kivity } 113b7cd3db6SAvi Kivity 114b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b) 115b7cd3db6SAvi Kivity { 116b7cd3db6SAvi Kivity return !int128_le(a, b); 117b7cd3db6SAvi Kivity } 118b7cd3db6SAvi Kivity 119b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a) 120b7cd3db6SAvi Kivity { 121b7cd3db6SAvi Kivity return a.lo || a.hi; 122b7cd3db6SAvi Kivity } 123b7cd3db6SAvi Kivity 124b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b) 125b7cd3db6SAvi Kivity { 126b7cd3db6SAvi Kivity return int128_le(a, b) ? a : b; 127b7cd3db6SAvi Kivity } 128b7cd3db6SAvi Kivity 129b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b) 130b7cd3db6SAvi Kivity { 131b7cd3db6SAvi Kivity return int128_ge(a, b) ? a : b; 132b7cd3db6SAvi Kivity } 133b7cd3db6SAvi Kivity 134b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b) 135b7cd3db6SAvi Kivity { 136b7cd3db6SAvi Kivity *a = int128_add(*a, b); 137b7cd3db6SAvi Kivity } 138b7cd3db6SAvi Kivity 139b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b) 140b7cd3db6SAvi Kivity { 141b7cd3db6SAvi Kivity *a = int128_sub(*a, b); 142b7cd3db6SAvi Kivity } 143b7cd3db6SAvi Kivity 144b7cd3db6SAvi Kivity #endif 145