1 /* tnum: tracked (or tristate) numbers
3 * A tnum tracks knowledge about the bits of a value. Each bit can be either
4 * known (0 or 1), or unknown (x). Arithmetic operations on tnums will
5 * propagate the unknown bits such that the tnum result represents all the
6 * possible results for possible values of the operands.
8 #include <linux/kernel.h>
9 #include <linux/tnum.h>
11 #define TNUM(_v, _m) (struct tnum){.value = _v, .mask = _m}
12 /* A completely unknown value */
13 const struct tnum tnum_unknown
= { .value
= 0, .mask
= -1 };
15 struct tnum
tnum_const(u64 value
)
17 return TNUM(value
, 0);
20 struct tnum
tnum_range(u64 min
, u64 max
)
22 u64 chi
= min
^ max
, delta
;
25 /* special case, needed because 1ULL << 64 is undefined */
28 /* e.g. if chi = 4, bits = 3, delta = (1<<3) - 1 = 7.
29 * if chi = 0, bits = 0, delta = (1<<0) - 1 = 0, so we return
30 * constant min (since min == max).
32 delta
= (1ULL << bits
) - 1;
33 return TNUM(min
& ~delta
, delta
);
36 struct tnum
tnum_lshift(struct tnum a
, u8 shift
)
38 return TNUM(a
.value
<< shift
, a
.mask
<< shift
);
41 struct tnum
tnum_rshift(struct tnum a
, u8 shift
)
43 return TNUM(a
.value
>> shift
, a
.mask
>> shift
);
46 struct tnum
tnum_add(struct tnum a
, struct tnum b
)
48 u64 sm
, sv
, sigma
, chi
, mu
;
51 sv
= a
.value
+ b
.value
;
54 mu
= chi
| a
.mask
| b
.mask
;
55 return TNUM(sv
& ~mu
, mu
);
58 struct tnum
tnum_sub(struct tnum a
, struct tnum b
)
60 u64 dv
, alpha
, beta
, chi
, mu
;
62 dv
= a
.value
- b
.value
;
66 mu
= chi
| a
.mask
| b
.mask
;
67 return TNUM(dv
& ~mu
, mu
);
70 struct tnum
tnum_and(struct tnum a
, struct tnum b
)
74 alpha
= a
.value
| a
.mask
;
75 beta
= b
.value
| b
.mask
;
76 v
= a
.value
& b
.value
;
77 return TNUM(v
, alpha
& beta
& ~v
);
80 struct tnum
tnum_or(struct tnum a
, struct tnum b
)
84 v
= a
.value
| b
.value
;
86 return TNUM(v
, mu
& ~v
);
89 struct tnum
tnum_xor(struct tnum a
, struct tnum b
)
93 v
= a
.value
^ b
.value
;
95 return TNUM(v
& ~mu
, mu
);
98 /* half-multiply add: acc += (unknown * mask * value).
99 * An intermediate step in the multiply algorithm.
101 static struct tnum
hma(struct tnum acc
, u64 value
, u64 mask
)
105 acc
= tnum_add(acc
, TNUM(0, value
));
112 struct tnum
tnum_mul(struct tnum a
, struct tnum b
)
117 pi
= a
.value
* b
.value
;
118 acc
= hma(TNUM(pi
, 0), a
.mask
, b
.mask
| b
.value
);
119 return hma(acc
, b
.mask
, a
.value
);
122 /* Note that if a and b disagree - i.e. one has a 'known 1' where the other has
123 * a 'known 0' - this will return a 'known 1' for that bit.
125 struct tnum
tnum_intersect(struct tnum a
, struct tnum b
)
129 v
= a
.value
| b
.value
;
130 mu
= a
.mask
& b
.mask
;
131 return TNUM(v
& ~mu
, mu
);
134 struct tnum
tnum_cast(struct tnum a
, u8 size
)
136 a
.value
&= (1ULL << (size
* 8)) - 1;
137 a
.mask
&= (1ULL << (size
* 8)) - 1;
141 bool tnum_is_aligned(struct tnum a
, u64 size
)
145 return !((a
.value
| a
.mask
) & (size
- 1));
148 bool tnum_in(struct tnum a
, struct tnum b
)
150 if (b
.mask
& ~a
.mask
)
153 return a
.value
== b
.value
;
156 int tnum_strn(char *str
, size_t size
, struct tnum a
)
158 return snprintf(str
, size
, "(%#llx; %#llx)", a
.value
, a
.mask
);
160 EXPORT_SYMBOL_GPL(tnum_strn
);
162 int tnum_sbin(char *str
, size_t size
, struct tnum a
)
166 for (n
= 64; n
; n
--) {
170 else if (a
.value
& 1)
178 str
[min(size
- 1, (size_t)64)] = 0;