xref: /qemu/include/qemu/int128.h (revision 052e87b073cb70afcd767d32f45af2794a5a65de)
1b7cd3db6SAvi Kivity #ifndef INT128_H
2b7cd3db6SAvi Kivity #define INT128_H
3b7cd3db6SAvi Kivity 
4b7cd3db6SAvi Kivity typedef struct Int128 Int128;
5b7cd3db6SAvi Kivity 
6b7cd3db6SAvi Kivity struct Int128 {
7b7cd3db6SAvi Kivity     uint64_t lo;
8b7cd3db6SAvi Kivity     int64_t hi;
9b7cd3db6SAvi Kivity };
10b7cd3db6SAvi Kivity 
11b7cd3db6SAvi Kivity static inline Int128 int128_make64(uint64_t a)
12b7cd3db6SAvi Kivity {
13b7cd3db6SAvi Kivity     return (Int128) { a, 0 };
14b7cd3db6SAvi Kivity }
15b7cd3db6SAvi Kivity 
16b7cd3db6SAvi Kivity static inline uint64_t int128_get64(Int128 a)
17b7cd3db6SAvi Kivity {
18b7cd3db6SAvi Kivity     assert(!a.hi);
19b7cd3db6SAvi Kivity     return a.lo;
20b7cd3db6SAvi Kivity }
21b7cd3db6SAvi Kivity 
22b7cd3db6SAvi Kivity static inline Int128 int128_zero(void)
23b7cd3db6SAvi Kivity {
24b7cd3db6SAvi Kivity     return int128_make64(0);
25b7cd3db6SAvi Kivity }
26b7cd3db6SAvi Kivity 
27b7cd3db6SAvi Kivity static inline Int128 int128_one(void)
28b7cd3db6SAvi Kivity {
29b7cd3db6SAvi Kivity     return int128_make64(1);
30b7cd3db6SAvi Kivity }
31b7cd3db6SAvi Kivity 
32b7cd3db6SAvi Kivity static inline Int128 int128_2_64(void)
33b7cd3db6SAvi Kivity {
34b7cd3db6SAvi Kivity     return (Int128) { 0, 1 };
35b7cd3db6SAvi Kivity }
36b7cd3db6SAvi Kivity 
37*052e87b0SPaolo Bonzini static inline Int128 int128_and(Int128 a, Int128 b)
38*052e87b0SPaolo Bonzini {
39*052e87b0SPaolo Bonzini     return (Int128) { a.lo & b.lo, a.hi & b.hi };
40*052e87b0SPaolo Bonzini }
41*052e87b0SPaolo Bonzini 
42*052e87b0SPaolo Bonzini static inline Int128 int128_rshift(Int128 a, int n)
43*052e87b0SPaolo Bonzini {
44*052e87b0SPaolo Bonzini     int64_t h;
45*052e87b0SPaolo Bonzini     if (!n) {
46*052e87b0SPaolo Bonzini         return a;
47*052e87b0SPaolo Bonzini     }
48*052e87b0SPaolo Bonzini     h = a.hi >> (n & 63);
49*052e87b0SPaolo Bonzini     if (n >= 64) {
50*052e87b0SPaolo Bonzini         return (Int128) { h, h >> 63 };
51*052e87b0SPaolo Bonzini     } else {
52*052e87b0SPaolo Bonzini         return (Int128) { (a.lo >> n) | (a.hi << (64 - n)), h };
53*052e87b0SPaolo Bonzini     }
54*052e87b0SPaolo Bonzini }
55*052e87b0SPaolo Bonzini 
56b7cd3db6SAvi Kivity static inline Int128 int128_add(Int128 a, Int128 b)
57b7cd3db6SAvi Kivity {
58b7cd3db6SAvi Kivity     Int128 r = { a.lo + b.lo, a.hi + b.hi };
59b7cd3db6SAvi Kivity     r.hi += (r.lo < a.lo) || (r.lo < b.lo);
60b7cd3db6SAvi Kivity     return r;
61b7cd3db6SAvi Kivity }
62b7cd3db6SAvi Kivity 
63b7cd3db6SAvi Kivity static inline Int128 int128_neg(Int128 a)
64b7cd3db6SAvi Kivity {
65b7cd3db6SAvi Kivity     a.lo = ~a.lo;
66b7cd3db6SAvi Kivity     a.hi = ~a.hi;
67b7cd3db6SAvi Kivity     return int128_add(a, int128_one());
68b7cd3db6SAvi Kivity }
69b7cd3db6SAvi Kivity 
70b7cd3db6SAvi Kivity static inline Int128 int128_sub(Int128 a, Int128 b)
71b7cd3db6SAvi Kivity {
72b7cd3db6SAvi Kivity     return int128_add(a, int128_neg(b));
73b7cd3db6SAvi Kivity }
74b7cd3db6SAvi Kivity 
75b7cd3db6SAvi Kivity static inline bool int128_nonneg(Int128 a)
76b7cd3db6SAvi Kivity {
77b7cd3db6SAvi Kivity     return a.hi >= 0;
78b7cd3db6SAvi Kivity }
79b7cd3db6SAvi Kivity 
80b7cd3db6SAvi Kivity static inline bool int128_eq(Int128 a, Int128 b)
81b7cd3db6SAvi Kivity {
82b7cd3db6SAvi Kivity     return a.lo == b.lo && a.hi == b.hi;
83b7cd3db6SAvi Kivity }
84b7cd3db6SAvi Kivity 
85b7cd3db6SAvi Kivity static inline bool int128_ne(Int128 a, Int128 b)
86b7cd3db6SAvi Kivity {
87b7cd3db6SAvi Kivity     return !int128_eq(a, b);
88b7cd3db6SAvi Kivity }
89b7cd3db6SAvi Kivity 
90b7cd3db6SAvi Kivity static inline bool int128_ge(Int128 a, Int128 b)
91b7cd3db6SAvi Kivity {
92b7cd3db6SAvi Kivity     return int128_nonneg(int128_sub(a, b));
93b7cd3db6SAvi Kivity }
94b7cd3db6SAvi Kivity 
95b7cd3db6SAvi Kivity static inline bool int128_lt(Int128 a, Int128 b)
96b7cd3db6SAvi Kivity {
97b7cd3db6SAvi Kivity     return !int128_ge(a, b);
98b7cd3db6SAvi Kivity }
99b7cd3db6SAvi Kivity 
100b7cd3db6SAvi Kivity static inline bool int128_le(Int128 a, Int128 b)
101b7cd3db6SAvi Kivity {
102b7cd3db6SAvi Kivity     return int128_ge(b, a);
103b7cd3db6SAvi Kivity }
104b7cd3db6SAvi Kivity 
105b7cd3db6SAvi Kivity static inline bool int128_gt(Int128 a, Int128 b)
106b7cd3db6SAvi Kivity {
107b7cd3db6SAvi Kivity     return !int128_le(a, b);
108b7cd3db6SAvi Kivity }
109b7cd3db6SAvi Kivity 
110b7cd3db6SAvi Kivity static inline bool int128_nz(Int128 a)
111b7cd3db6SAvi Kivity {
112b7cd3db6SAvi Kivity     return a.lo || a.hi;
113b7cd3db6SAvi Kivity }
114b7cd3db6SAvi Kivity 
115b7cd3db6SAvi Kivity static inline Int128 int128_min(Int128 a, Int128 b)
116b7cd3db6SAvi Kivity {
117b7cd3db6SAvi Kivity     return int128_le(a, b) ? a : b;
118b7cd3db6SAvi Kivity }
119b7cd3db6SAvi Kivity 
120b7cd3db6SAvi Kivity static inline Int128 int128_max(Int128 a, Int128 b)
121b7cd3db6SAvi Kivity {
122b7cd3db6SAvi Kivity     return int128_ge(a, b) ? a : b;
123b7cd3db6SAvi Kivity }
124b7cd3db6SAvi Kivity 
125b7cd3db6SAvi Kivity static inline void int128_addto(Int128 *a, Int128 b)
126b7cd3db6SAvi Kivity {
127b7cd3db6SAvi Kivity     *a = int128_add(*a, b);
128b7cd3db6SAvi Kivity }
129b7cd3db6SAvi Kivity 
130b7cd3db6SAvi Kivity static inline void int128_subfrom(Int128 *a, Int128 b)
131b7cd3db6SAvi Kivity {
132b7cd3db6SAvi Kivity     *a = int128_sub(*a, b);
133b7cd3db6SAvi Kivity }
134b7cd3db6SAvi Kivity 
135b7cd3db6SAvi Kivity #endif
136