xref: /aosp_15_r20/external/mesa3d/src/nouveau/compiler/bitview/lib.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2022 Collabora, Ltd.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 use std::ops::Range;
7 
8 pub trait BitViewable {
bits(&self) -> usize9     fn bits(&self) -> usize;
10 
get_bit_range_u64(&self, range: Range<usize>) -> u6411     fn get_bit_range_u64(&self, range: Range<usize>) -> u64;
12 }
13 
14 pub trait BitMutViewable: BitViewable {
set_bit_range_u64(&mut self, range: Range<usize>, val: u64)15     fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64);
16 }
17 
u64_mask_for_bits(bits: usize) -> u6418 fn u64_mask_for_bits(bits: usize) -> u64 {
19     assert!(bits > 0 && bits <= 64);
20     !0u64 >> (64 - bits)
21 }
22 
23 macro_rules! decl_bit_set_viewable_for_uint {
24     ($ty: ty) => {
25         impl BitViewable for $ty {
26             fn bits(&self) -> usize {
27                 <$ty>::BITS as usize
28             }
29 
30             fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
31                 assert!(!range.is_empty());
32                 assert!(range.end <= self.bits());
33 
34                 let mask = <$ty>::MAX >> (self.bits() - range.len());
35                 ((self >> range.start) & mask).into()
36             }
37         }
38 
39         impl BitMutViewable for $ty {
40             fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64) {
41                 assert!(!range.is_empty());
42                 assert!(range.end <= self.bits());
43 
44                 let mask = <$ty>::MAX >> (self.bits() - range.len());
45 
46                 assert!((val & u64::from(mask)) == val);
47                 let val = val as $ty;
48 
49                 *self = (*self & !(mask << range.start)) | (val << range.start);
50             }
51         }
52 
53         impl BitViewable for [$ty] {
54             fn bits(&self) -> usize {
55                 self.len() * (<$ty>::BITS as usize)
56             }
57 
58             fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
59                 assert!(!range.is_empty());
60                 assert!(range.end <= self.bits());
61 
62                 let mask = u64_mask_for_bits(range.len());
63 
64                 let bits = <$ty>::BITS as usize;
65                 let c0_idx = range.start / bits;
66                 let c0_start = range.start % bits;
67                 let chunks = (c0_start + range.len()).div_ceil(bits);
68 
69                 let mut val = 0_u64;
70                 for i in 0..chunks {
71                     let chunk = u64::from(self[c0_idx + i]);
72                     if i == 0 {
73                         val |= chunk >> c0_start;
74                     } else {
75                         val |= chunk << (i * bits) - c0_start;
76                     };
77                 }
78                 val & mask
79             }
80         }
81 
82         impl BitMutViewable for [$ty] {
83             fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64) {
84                 assert!(!range.is_empty());
85                 assert!(range.end <= self.bits());
86 
87                 let mask = u64_mask_for_bits(range.len());
88                 assert!((val & u64::from(mask)) == val);
89 
90                 let bits = <$ty>::BITS as usize;
91                 let c0_idx = range.start / bits;
92                 let c0_start = range.start % bits;
93                 let chunks = (c0_start + range.len()).div_ceil(bits);
94 
95                 for i in 0..chunks {
96                     let chunk = &mut self[c0_idx + i];
97                     if i == 0 {
98                         *chunk &= !((mask << c0_start) as $ty);
99                         *chunk |= (val << c0_start) as $ty;
100                     } else {
101                         let shift = (i * bits) - c0_start;
102                         *chunk &= !((mask >> shift) as $ty);
103                         *chunk |= (val >> shift) as $ty;
104                     }
105                 }
106             }
107         }
108 
109         impl<const N: usize> BitViewable for [$ty; N] {
110             fn bits(&self) -> usize {
111                 N * (<$ty>::BITS as usize)
112             }
113 
114             fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
115                 self[..].get_bit_range_u64(range)
116             }
117         }
118 
119         impl<const N: usize> BitMutViewable for [$ty; N] {
120             fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64) {
121                 self[..].set_bit_range_u64(range, val);
122             }
123         }
124     };
125 }
126 
127 decl_bit_set_viewable_for_uint!(u8);
128 decl_bit_set_viewable_for_uint!(u16);
129 decl_bit_set_viewable_for_uint!(u32);
130 decl_bit_set_viewable_for_uint!(u64);
131 
132 pub struct BitView<'a, BS: BitViewable + ?Sized> {
133     parent: &'a BS,
134     range: Range<usize>,
135 }
136 
137 impl<'a, BS: BitViewable + ?Sized> BitView<'a, BS> {
new(parent: &'a BS) -> Self138     pub fn new(parent: &'a BS) -> Self {
139         let len = parent.bits();
140         Self {
141             parent: parent,
142             range: 0..len,
143         }
144     }
145 
new_subset(parent: &'a BS, range: Range<usize>) -> Self146     pub fn new_subset(parent: &'a BS, range: Range<usize>) -> Self {
147         assert!(range.end <= parent.bits());
148         Self {
149             parent: parent,
150             range: range,
151         }
152     }
153 
subset( &'a self, range: Range<usize>, ) -> BitView<'a, BitView<'a, BS>>154     pub fn subset(
155         &'a self,
156         range: Range<usize>,
157     ) -> BitView<'a, BitView<'a, BS>> {
158         BitView::new_subset(self, range)
159     }
160 
range_in_parent(&self, range: Range<usize>) -> Range<usize>161     fn range_in_parent(&self, range: Range<usize>) -> Range<usize> {
162         let new_start = self.range.start + range.start;
163         let new_end = self.range.start + range.end;
164         assert!(new_end <= self.range.end);
165         new_start..new_end
166     }
167 
get_bit(&self, bit: usize) -> bool168     pub fn get_bit(&self, bit: usize) -> bool {
169         self.get_bit_range_u64(bit..(bit + 1)) != 0
170     }
171 }
172 
173 impl<'a, BS: BitViewable + ?Sized> BitViewable for BitView<'a, BS> {
bits(&self) -> usize174     fn bits(&self) -> usize {
175         self.range.end - self.range.start
176     }
177 
get_bit_range_u64(&self, range: Range<usize>) -> u64178     fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
179         self.parent.get_bit_range_u64(self.range_in_parent(range))
180     }
181 }
182 
183 pub struct BitMutView<'a, BS: BitMutViewable + ?Sized> {
184     parent: &'a mut BS,
185     range: Range<usize>,
186 }
187 
188 impl<'a, BS: BitMutViewable + ?Sized> BitMutView<'a, BS> {
new(parent: &'a mut BS) -> Self189     pub fn new(parent: &'a mut BS) -> Self {
190         let len = parent.bits();
191         Self {
192             parent: parent,
193             range: 0..len,
194         }
195     }
196 
new_subset(parent: &'a mut BS, range: Range<usize>) -> Self197     pub fn new_subset(parent: &'a mut BS, range: Range<usize>) -> Self {
198         assert!(range.end <= parent.bits());
199         Self {
200             parent: parent,
201             range: range,
202         }
203     }
204 
subset_mut<'b>( &'b mut self, range: Range<usize>, ) -> BitMutView<'b, BitMutView<'a, BS>>205     pub fn subset_mut<'b>(
206         &'b mut self,
207         range: Range<usize>,
208     ) -> BitMutView<'b, BitMutView<'a, BS>> {
209         BitMutView::new_subset(self, range)
210     }
211 
range_in_parent(&self, range: Range<usize>) -> Range<usize>212     fn range_in_parent(&self, range: Range<usize>) -> Range<usize> {
213         let new_start = self.range.start + range.start;
214         let new_end = self.range.start + range.end;
215         assert!(new_end <= self.range.end);
216         new_start..new_end
217     }
218 
get_bit(&self, bit: usize) -> bool219     pub fn get_bit(&self, bit: usize) -> bool {
220         self.get_bit_range_u64(bit..(bit + 1)) != 0
221     }
222 
set_bit(&mut self, bit: usize, val: bool)223     pub fn set_bit(&mut self, bit: usize, val: bool) {
224         self.set_bit_range_u64(bit..(bit + 1), u64::from(val));
225     }
226 }
227 
228 impl<'a, BS: BitMutViewable + ?Sized> BitViewable for BitMutView<'a, BS> {
bits(&self) -> usize229     fn bits(&self) -> usize {
230         self.range.end - self.range.start
231     }
232 
get_bit_range_u64(&self, range: Range<usize>) -> u64233     fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
234         self.parent.get_bit_range_u64(self.range_in_parent(range))
235     }
236 }
237 
238 impl<'a, BS: BitMutViewable + ?Sized> BitMutViewable for BitMutView<'a, BS> {
set_bit_range_u64(&mut self, range: Range<usize>, val: u64)239     fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64) {
240         self.parent
241             .set_bit_range_u64(self.range_in_parent(range), val);
242     }
243 }
244 
245 pub trait SetFieldU64 {
set_field_u64(&mut self, range: Range<usize>, val: u64)246     fn set_field_u64(&mut self, range: Range<usize>, val: u64);
247 }
248 
249 impl<'a, BS: BitMutViewable + ?Sized> SetFieldU64 for BitMutView<'a, BS> {
set_field_u64(&mut self, range: Range<usize>, val: u64)250     fn set_field_u64(&mut self, range: Range<usize>, val: u64) {
251         let bits = range.end - range.start;
252 
253         /* Check that it fits in the bitfield */
254         assert!((val & u64_mask_for_bits(bits)) == val);
255 
256         self.set_bit_range_u64(range, val);
257     }
258 }
259 
260 pub trait SetField<T> {
set_field(&mut self, range: Range<usize>, val: T)261     fn set_field(&mut self, range: Range<usize>, val: T);
262 }
263 
264 impl<T: SetFieldU64> SetField<u64> for T {
set_field(&mut self, range: Range<usize>, val: u64)265     fn set_field(&mut self, range: Range<usize>, val: u64) {
266         self.set_field_u64(range, val);
267     }
268 }
269 
270 impl<T: SetFieldU64> SetField<u32> for T {
set_field(&mut self, range: Range<usize>, val: u32)271     fn set_field(&mut self, range: Range<usize>, val: u32) {
272         self.set_field(range, u64::from(val));
273     }
274 }
275 
276 impl<T: SetFieldU64> SetField<u16> for T {
set_field(&mut self, range: Range<usize>, val: u16)277     fn set_field(&mut self, range: Range<usize>, val: u16) {
278         self.set_field(range, u64::from(val));
279     }
280 }
281 
282 impl<T: SetFieldU64> SetField<u8> for T {
set_field(&mut self, range: Range<usize>, val: u8)283     fn set_field(&mut self, range: Range<usize>, val: u8) {
284         self.set_field(range, u64::from(val));
285     }
286 }
287 
288 impl<T: SetFieldU64> SetField<bool> for T {
set_field(&mut self, range: Range<usize>, val: bool)289     fn set_field(&mut self, range: Range<usize>, val: bool) {
290         assert!(range.len() == 1);
291         self.set_field(range, u64::from(val));
292     }
293 }
294 
295 impl<T: SetFieldU64> SetField<f32> for T {
set_field(&mut self, range: Range<usize>, val: f32)296     fn set_field(&mut self, range: Range<usize>, val: f32) {
297         assert!(range.len() == 32);
298         self.set_field(range, val.to_bits());
299     }
300 }
301 
302 pub trait SetBit {
set_bit(&mut self, bit: usize, val: bool)303     fn set_bit(&mut self, bit: usize, val: bool);
304 }
305 
306 impl<T: SetFieldU64> SetBit for T {
set_bit(&mut self, bit: usize, val: bool)307     fn set_bit(&mut self, bit: usize, val: bool) {
308         self.set_field(bit..(bit + 1), val);
309     }
310 }
311 
312 impl<T: SetFieldU64> SetField<i64> for T {
set_field(&mut self, range: Range<usize>, val: i64)313     fn set_field(&mut self, range: Range<usize>, val: i64) {
314         let bits = range.end - range.start;
315         let mask = u64_mask_for_bits(bits);
316 
317         /* It's easier to work with a u64 */
318         let val = val as u64;
319 
320         /* Check that it fits in the bitfield, taking sign into account */
321         let sign_mask = !(mask >> 1);
322         assert!((val & sign_mask) == 0 || (val & sign_mask) == sign_mask);
323 
324         self.set_field_u64(range, val & mask);
325     }
326 }
327 
328 impl<T: SetFieldU64> SetField<i32> for T {
set_field(&mut self, range: Range<usize>, val: i32)329     fn set_field(&mut self, range: Range<usize>, val: i32) {
330         self.set_field(range, i64::from(val));
331     }
332 }
333 
334 impl<T: SetFieldU64> SetField<i16> for T {
set_field(&mut self, range: Range<usize>, val: i16)335     fn set_field(&mut self, range: Range<usize>, val: i16) {
336         self.set_field(range, i64::from(val));
337     }
338 }
339 
340 impl<T: SetFieldU64> SetField<i8> for T {
set_field(&mut self, range: Range<usize>, val: i8)341     fn set_field(&mut self, range: Range<usize>, val: i8) {
342         self.set_field(range, i64::from(val));
343     }
344 }
345