1#![cfg_attr(not(test), no_std)]
6
7#[cfg(test)]
9extern crate self as bitrs;
10
11use core::fmt;
12
13#[doc(hidden)]
18pub use ::zerocopy as __zerocopy;
19
20pub use bitrs_macro::layout;
24
25pub use bitrs_macro::multilayout;
30
31pub use bitrs_macro::bitfield_repr;
47
48#[doc(hidden)]
57#[macro_export]
58macro_rules! get_bit {
59 ($int:expr, $low_bit:literal) => {
60 (($int) & (1 << $low_bit)) != 0
61 };
62}
63
64#[doc(hidden)]
65#[macro_export]
66macro_rules! set_bit {
67 ($int:expr, $low_bit:literal, $value:ident) => {
68 if $value {
69 $int |= (1 << $low_bit);
70 } else {
71 $int &= !(1 << $low_bit);
72 }
73 };
74}
75
76#[doc(hidden)]
77#[macro_export]
78macro_rules! shifted_mask {
79 ($base:ty, $high_bit:literal, $low_bit:literal) => {{
80 const WIDTH: usize = $high_bit - $low_bit + 1;
81 if (<$base>::BITS as usize) == WIDTH { <$base>::MAX } else { (1 << WIDTH) - 1 }
82 }};
83}
84
85#[doc(hidden)]
86#[macro_export]
87macro_rules! get_field {
88 ($base:ty, $clamped:ty, $high_bit:literal, $low_bit:literal, $shifted:literal, $int:expr) => {{
89 const SHIFTED_MASK: $base = $crate::shifted_mask!($base, $high_bit, $low_bit);
90 let value = if $shifted {
91 ($int >> $low_bit) & SHIFTED_MASK
92 } else {
93 const UNSHIFTED_MASK: $base = SHIFTED_MASK << $low_bit;
94 $int & UNSHIFTED_MASK
95 };
96 value as $clamped
97 }};
98}
99
100#[doc(hidden)]
101#[macro_export]
102macro_rules! set_field {
103 ($base:ty, $high_bit:literal, $low_bit:literal, $shifted:literal, $int:expr, $value:ident) => {
104 const SHIFTED_MASK: $base = $crate::shifted_mask!($base, $high_bit, $low_bit);
105 const UNSHIFTED_MASK: $base = SHIFTED_MASK << $low_bit;
106
107 $int &= !UNSHIFTED_MASK;
108 if $shifted {
109 debug_assert!(($value & !SHIFTED_MASK) == 0);
110 $int |= ($value & SHIFTED_MASK) << $low_bit;
111 } else {
112 debug_assert!(($value & !UNSHIFTED_MASK) == 0);
113 $int |= $value & UNSHIFTED_MASK;
114 }
115 };
116}
117
118pub trait Unsigned: fmt::Debug + private::Sealed {}
121impl Unsigned for u8 {}
122impl Unsigned for u16 {}
123impl Unsigned for u32 {}
124impl Unsigned for u64 {}
125impl Unsigned for u128 {}
126
127mod private {
129 pub trait Sealed {}
130 impl Sealed for u8 {}
131 impl Sealed for u16 {}
132 impl Sealed for u32 {}
133 impl Sealed for u64 {}
134 impl Sealed for u128 {}
135}
136
137#[derive(Debug)]
141pub struct InvalidBits<Base: Unsigned>(pub Base);
142
143#[derive(Debug)]
148pub struct FieldMetadata<Base: Unsigned> {
149 pub name: &'static str,
151 pub high_bit: u32,
153 pub low_bit: u32,
155 pub default: Base,
157}
158
159#[cfg(test)]
160mod tests {
161 use super::{FieldMetadata, bitfield_repr, layout, multilayout};
162
163 layout!({
164 struct EmptyU8(u8);
165 {}
166 });
167
168 layout!({
169 struct OneFieldU16(u16);
170 {
171 let a @ 15..0;
172 }
173 });
174
175 layout!({
176 struct TwoFieldsU32(u32);
177 {
178 let a @ 31..16;
179 let b @ 15..0;
180 }
181 });
182
183 layout!({
184 struct ThreeFieldsU64(u64);
185 {
186 let a @ 63..32;
187 let b @ 31..16;
188 let c @ 15..0;
189 }
190 });
191
192 layout!({
193 struct FourFieldsU128(u128);
194 {
195 let a @ 127..96;
196 let b @ 95..64;
197 let c @ 63..32;
198 let d @ 31..0;
199 }
200 });
201
202 #[test]
203 fn size_and_alignment() {
204 assert_eq!(size_of::<EmptyU8>(), size_of::<u8>());
205 assert_eq!(align_of::<EmptyU8>(), align_of::<u8>());
206
207 assert_eq!(size_of::<OneFieldU16>(), size_of::<u16>());
208 assert_eq!(align_of::<OneFieldU16>(), align_of::<u16>());
209
210 assert_eq!(size_of::<TwoFieldsU32>(), size_of::<u32>());
211 assert_eq!(align_of::<TwoFieldsU32>(), align_of::<u32>());
212
213 assert_eq!(size_of::<ThreeFieldsU64>(), size_of::<u64>());
214 assert_eq!(align_of::<ThreeFieldsU64>(), align_of::<u64>());
215
216 assert_eq!(size_of::<FourFieldsU128>(), size_of::<u128>());
217 assert_eq!(align_of::<FourFieldsU128>(), align_of::<u128>());
218 }
219
220 #[bitfield_repr(u8)]
221 pub enum CustomFieldRepr {
222 Option1 = 0xa,
223 Option2 = 0xf,
224 }
225
226 layout!({
227 pub struct Example(u64);
228 {
229 let u32_repr @ 44..27;
230 let custom @ 26..23: CustomFieldRepr;
231 let custom_with_default @ 22..19: CustomFieldRepr = CustomFieldRepr::Option1;
232 let __ @ 18..11 = 0xef;
233 let with_default @ 10..9 = 0b11;
234 let bit @ 8;
235 let u8_repr @ 7..4;
236 let __ @ 3..2 = 1;
237 let __ @ 1..0;
238 }
239 });
240
241 #[test]
242 fn constants() {
243 assert_eq!(Example::RSVD1_MASK, (0xef << 11) | (0b01 << 2));
244 assert_eq!(Example::RSVD0_MASK, (0x10 << 11) | (0b10 << 2));
245
246 assert_eq!(
247 Example::DEFAULT,
248 (0xef << 11) | (0b01 << 2) | ((CustomFieldRepr::Option1 as u64) << 19) | (0b11 << 9)
249 );
250
251 assert_eq!(Example::U32_REPR_MASK, 0x1fff_f800_0000);
252 assert_eq!(Example::U32_REPR_SHIFT, 27usize,);
253
254 assert_eq!(Example::CUSTOM_MASK, 0x780_0000);
255 assert_eq!(Example::CUSTOM_SHIFT, 23usize);
256
257 assert_eq!(Example::CUSTOM_WITH_DEFAULT_MASK, 0x78_0000);
258 assert_eq!(Example::CUSTOM_WITH_DEFAULT_SHIFT, 19usize);
259
260 assert_eq!(Example::RSVD_18_11, 0xef << 11);
261
262 assert_eq!(Example::WITH_DEFAULT_MASK, 0x600);
263 assert_eq!(Example::WITH_DEFAULT_SHIFT, 9usize);
264
265 assert_eq!(Example::BIT_SHIFT, 8usize);
266
267 assert_eq!(Example::U8_REPR_MASK, 0xf0);
268 assert_eq!(Example::U8_REPR_SHIFT, 4usize);
269
270 assert_eq!(Example::RSVD_3_2, 1 << 2);
271 }
272
273 #[test]
275 fn new() {
276 assert_eq!(Example::new().bits(), Example::RSVD1_MASK);
277 }
278
279 #[test]
282 fn default() {
283 assert_eq!(Example::default().bits(), Example::DEFAULT);
284 }
285
286 #[test]
287 fn from() {
288 assert_eq!(Example::from(Example::RSVD1_MASK).bits(), Example::RSVD1_MASK);
289 assert_eq!(Example::from(1 | Example::RSVD1_MASK).bits(), 1 | Example::RSVD1_MASK);
290 assert_eq!(
291 Example::from(0xffff_0000_0000_0000 | Example::RSVD1_MASK).bits(),
292 0xffff_0000_0000_0000 | Example::RSVD1_MASK
293 );
294 }
295
296 #[test]
297 fn from_then_get() {
298 let example = Example::from(
299 0xabcd << 27
300 | (CustomFieldRepr::Option1 as u64) << 23
301 | (CustomFieldRepr::Option2 as u64) << 19
302 | 0b10 << 9
303 | 1 << 8
304 | 0xc << 4
305 | Example::RSVD1_MASK,
306 );
307 assert_eq!(example.u32_repr(), 0xabcd);
308 assert_eq!(example.custom(), CustomFieldRepr::Option1);
309 assert_eq!(example.custom_with_default(), CustomFieldRepr::Option2);
310 assert_eq!(example.with_default(), 0b10);
311 assert!(example.bit());
312 assert_eq!(example.u8_repr(), 0xc);
313 }
314
315 #[test]
316 fn set_then_get() {
317 let example = *Example::new()
318 .set_u32_repr(0xabcd)
319 .set_custom(CustomFieldRepr::Option1)
320 .set_custom_with_default(CustomFieldRepr::Option2)
321 .set_with_default(0b10)
322 .set_bit(true)
323 .set_u8_repr(0xc);
324 assert_eq!(example.u32_repr(), 0xabcd);
325 assert_eq!(example.custom(), CustomFieldRepr::Option1);
326 assert_eq!(example.custom_with_default(), CustomFieldRepr::Option2);
327 assert_eq!(example.with_default(), 0b10);
328 assert!(example.bit());
329 assert_eq!(example.u8_repr(), 0xc);
330 }
331
332 #[test]
333 fn iter() {
334 type Metadata = FieldMetadata<u64>;
335
336 const EXPECTED: [(u64, Metadata); 6] = [
337 (0xabcd, Metadata { name: "u32_repr", high_bit: 44, low_bit: 27, default: 0 }),
338 (0xa, Metadata { name: "custom", high_bit: 26, low_bit: 23, default: 0 }),
339 (
340 0xf,
341 Metadata { name: "custom_with_default", high_bit: 22, low_bit: 19, default: 0xa },
342 ),
343 (0b10, Metadata { name: "with_default", high_bit: 10, low_bit: 9, default: 0b11 }),
344 (0b1, Metadata { name: "bit", high_bit: 8, low_bit: 8, default: 0 }),
345 (0xc, Metadata { name: "u8_repr", high_bit: 7, low_bit: 4, default: 0 }),
346 ];
347
348 let example = *Example::new()
349 .set_u32_repr(0xabcd)
350 .set_custom(CustomFieldRepr::Option1)
351 .set_custom_with_default(CustomFieldRepr::Option2)
352 .set_with_default(0b10)
353 .set_bit(true)
354 .set_u8_repr(0xc);
355
356 let actual: Vec<(&'static Metadata, u64)> = example.into_iter().collect();
357 let rev_actual: Vec<(&'static Metadata, u64)> = example.into_iter().rev().collect();
358
359 assert_eq!(actual.len(), EXPECTED.len());
360 assert_eq!(rev_actual.len(), EXPECTED.len());
361 for i in 0..EXPECTED.len() {
362 let (expected_val, expected_metadata) = &EXPECTED[i];
363 for (label, (actual_metadata, actual_val)) in
364 [("fwd", &actual[i]), ("rev", &rev_actual[EXPECTED.len() - 1 - i])]
365 {
366 assert_eq!(actual_val, expected_val, "{label}:{i}");
367 assert_eq!(actual_metadata.name, expected_metadata.name, "{label}:{i}");
368 assert_eq!(actual_metadata.high_bit, expected_metadata.high_bit, "{label}:{i}");
369 assert_eq!(actual_metadata.low_bit, expected_metadata.low_bit, "{label}:{i}");
370 assert_eq!(actual_metadata.default, expected_metadata.default, "{label}:{i}");
371 }
372 }
373 }
374
375 layout!({
376 struct Unshifted(u32);
377 {
378 let field @ 19..16;
379 #[unshifted]
380 let unshifted_field @ 15..12;
381 let __ @ 11..9;
382 #[unshifted]
383 let unshifted_bit @ 8;
384 let normal_bit @ 7;
385 let __ @ 6..0;
386 }
387 });
388
389 #[test]
390 fn unshifted_multi_bit_getter() {
391 let val = Unshifted::from(0x5 << 12);
392 assert_eq!(val.unshifted_field(), 0x5000);
393 }
394
395 #[test]
396 fn unshifted_multi_bit_setter() {
397 let mut val = Unshifted::new();
398 val.set_unshifted_field(0xa000);
399 assert_eq!(val.unshifted_field(), 0xa000);
400 assert_eq!(val.bits() & (0xf << 12), 0xa000);
401 }
402
403 #[test]
404 fn unshifted_single_bit_getter() {
405 let val = Unshifted::from(1 << 8);
406 assert_eq!(val.unshifted_bit(), 1 << 8);
407
408 let val = Unshifted::from(0);
409 assert_eq!(val.unshifted_bit(), 0);
410 }
411
412 #[test]
413 fn unshifted_single_bit_setter() {
414 let mut val = Unshifted::new();
415 val.set_unshifted_bit(1 << 8);
416 assert_eq!(val.unshifted_bit(), 1 << 8);
417
418 val.set_unshifted_bit(0);
419 assert_eq!(val.unshifted_bit(), 0);
420 }
421
422 #[test]
423 fn unshifted_round_trip() {
424 let val = *Unshifted::new()
425 .set_unshifted_field(0x7000)
426 .set_unshifted_bit(1 << 8)
427 .set_field(0xa)
428 .set_normal_bit(true);
429 assert_eq!(val.unshifted_field(), 0x7000);
430 assert_eq!(val.unshifted_bit(), 1 << 8);
431 assert_eq!(val.field(), 0xa);
432 assert!(val.normal_bit());
433 }
434
435 #[test]
436 fn unshifted_ignores_other_bits() {
437 let val = Unshifted::from(0xffff_ffff);
438 assert_eq!(val.unshifted_field(), 0xf000);
439 assert_eq!(val.unshifted_bit(), 1 << 8);
440 }
441
442 multilayout!({
443 #[bitrs(m, rv32)]
444 pub struct Mstatus32(u32);
445 #[bitrs(m, rv64)]
446 pub struct Mstatus64(u64);
447 #[bitrs(rv32)]
448 pub struct Sstatus32(u32);
449 #[bitrs(rv64)]
450 pub struct Sstatus64(u64);
451
452 #[rv32]
453 {
454 let sd @ 31;
455 }
456 #[rv64]
457 {
458 let sd @ 63;
459 }
460 #[all(m, rv64)]
461 {
462 let mbe @ 37;
463 let sbe @ 36;
464 let sxl @ 35..34;
465 }
466 #[rv64]
467 {
468 let uxl @ 33..32;
469 }
470 #[m]
471 {
472 let tsr @ 22;
473 let tw @ 21;
474 let tvm @ 20;
475 let mprv @ 17;
476 let mpp @ 12..11;
477 let mpie @ 7;
478 let mie @ 3;
479 }
480 {
481 let mxr @ 19;
482 let sum @ 18;
483 let xs @ 16..15;
484 let fs @ 14..13;
485 let vs @ 10..9;
486 let spp @ 8;
487 let ube @ 6;
488 let spie @ 5;
489 let sie @ 1;
490 }
491 });
492
493 #[test]
494 fn sd_at_xlen_minus_1() {
495 let m32 = *Mstatus32::new().set_sd(true);
498 let m64 = *Mstatus64::new().set_sd(true);
499 let s32 = *Sstatus32::new().set_sd(true);
500 let s64 = *Sstatus64::new().set_sd(true);
501 assert_eq!(m32.bits() & Mstatus32::SD_MASK, 1u32 << 31);
502 assert_eq!(m64.bits() & Mstatus64::SD_MASK, 1u64 << 63);
503 assert_eq!(s32.bits() & Sstatus32::SD_MASK, 1u32 << 31);
504 assert_eq!(s64.bits() & Sstatus64::SD_MASK, 1u64 << 63);
505 }
506
507 #[test]
508 fn mstatus_round_trip() {
509 let m = *Mstatus64::new().set_tsr(true).set_mpp(0b11).set_mxr(true).set_mie(true);
512 assert!(m.tsr());
513 assert_eq!(m.mpp(), 0b11);
514 assert!(m.mxr());
515 assert!(m.mie());
516 }
517
518 #[test]
519 fn uxl_visible_in_both_modes() {
520 let m = *Mstatus64::new().set_uxl(0b10);
523 let s = *Sstatus64::new().set_uxl(0b10);
524 assert_eq!(m.uxl(), 0b10);
525 assert_eq!(s.uxl(), 0b10);
526 }
527
528 #[test]
529 fn sstatus_shared_low_half_round_trip() {
530 let s32 = *Sstatus32::new().set_mxr(true).set_sum(true).set_spp(true).set_sie(true);
533 let s64 = *Sstatus64::new().set_mxr(true).set_sum(true).set_spp(true).set_sie(true);
534 assert!(s32.mxr() && s32.sum() && s32.spp() && s32.sie());
535 assert!(s64.mxr() && s64.sum() && s64.spp() && s64.sie());
536 }
537
538 multilayout!({
539 #[bitrs(a, x)]
540 struct PredA(u32);
541 #[bitrs(b, x)]
542 struct PredB(u32);
543 #[bitrs(c, y)]
544 struct PredC(u32);
545
546 #[any(a, b)]
548 {
549 let ab_shared @ 0;
550 }
551
552 #[not(c)]
554 {
555 let not_c @ 1;
556 }
557
558 #[all(x, any(a, not(b)))]
560 {
561 let nested @ 2;
562 }
563
564 #[c]
566 {
567 let custom @ 6..3: CustomFieldRepr = CustomFieldRepr::Option1;
568 #[unshifted]
569 let unshifted @ 15..12;
570 let __ @ 19..16 = 0xa;
571 }
572 });
573
574 #[test]
575 fn any_not_and_nested_predicates() {
576 let a = *PredA::new().set_ab_shared(true).set_not_c(true).set_nested(true);
577 assert!(a.ab_shared());
578 assert!(a.not_c());
579 assert!(a.nested());
580
581 let b = *PredB::new().set_ab_shared(true).set_not_c(true);
582 assert!(b.ab_shared());
583 assert!(b.not_c());
584 }
585
586 #[test]
587 fn multilayout_feature_interactions() {
588 assert_eq!(PredC::new().bits(), PredC::RSVD1_MASK);
589 assert_eq!(PredC::RSVD1_MASK, 0xa << 16);
590
591 let mut c = PredC::default();
592 assert_eq!(c.custom(), CustomFieldRepr::Option1);
593 assert_eq!(c.bits(), PredC::DEFAULT);
594
595 c.set_custom(CustomFieldRepr::Option2);
596 assert_eq!(c.custom(), CustomFieldRepr::Option2);
597
598 c.set_unshifted(0x5000);
599 assert_eq!(c.unshifted(), 0x5000);
600
601 let fields: Vec<(&'static FieldMetadata<u32>, u32)> = c.iter().collect();
602 assert_eq!(fields.len(), 2);
603 assert_eq!(fields[0].0.name, "unshifted");
604 assert_eq!(fields[0].1, 0x5);
605 assert_eq!(fields[1].0.name, "custom");
606 assert_eq!(fields[1].1, CustomFieldRepr::Option2 as u32);
607 }
608}