1#![allow(clippy::suspicious_op_assign_impl)]
70#![allow(clippy::suspicious_arithmetic_impl)]
71
72use core::marker::PhantomData;
73use core::ops::{Add, AddAssign};
74
75use crate::{RegisterLongName, UIntLike};
76
77pub struct Field<T: UIntLike, R: RegisterLongName> {
81 pub mask: T,
82 pub shift: usize,
83 associated_register: PhantomData<R>,
84}
85
86impl<T: UIntLike, R: RegisterLongName> Field<T, R> {
87 pub const fn new(mask: T, shift: usize) -> Field<T, R> {
88 Field {
89 mask,
90 shift,
91 associated_register: PhantomData,
92 }
93 }
94
95 #[inline]
96 pub fn read(self, val: T) -> T {
97 (val & (self.mask << self.shift)) >> self.shift
98 }
99
100 #[inline]
101 pub fn is_set(self, val: T) -> bool {
103 val & (self.mask << self.shift) != T::zero()
104 }
105
106 #[inline]
107 pub fn read_as_enum<E: TryFromValue<T, EnumType = E>>(self, val: T) -> Option<E> {
145 E::try_from_value(self.read(val))
146 }
147}
148
149impl<T: UIntLike, R: RegisterLongName> Clone for Field<T, R> {
166 fn clone(&self) -> Self {
167 *self
168 }
169}
170impl<T: UIntLike, R: RegisterLongName> Copy for Field<T, R> {}
171
172macro_rules! Field_impl_for {
173 ($type:ty) => {
174 impl<R: RegisterLongName> Field<$type, R> {
175 pub const fn val(&self, value: $type) -> FieldValue<$type, R> {
176 FieldValue::<$type, R>::new(self.mask, self.shift, value)
177 }
178 }
179 };
180}
181
182Field_impl_for!(u8);
183Field_impl_for!(u16);
184Field_impl_for!(u32);
185Field_impl_for!(u64);
186Field_impl_for!(u128);
187Field_impl_for!(usize);
188
189#[derive(Copy, Clone)]
194pub struct FieldValue<T: UIntLike, R: RegisterLongName> {
195 mask: T,
196 pub value: T,
197 associated_register: PhantomData<R>,
198}
199
200macro_rules! FieldValue_impl_for {
201 ($type:ty) => {
202 impl<R: RegisterLongName> FieldValue<$type, R> {
206 pub const fn new(mask: $type, shift: usize, value: $type) -> Self {
207 FieldValue {
208 mask: mask << shift,
209 value: (value & mask) << shift,
210 associated_register: PhantomData,
211 }
212 }
213 }
214
215 impl<R: RegisterLongName> From<FieldValue<$type, R>> for $type {
219 fn from(val: FieldValue<$type, R>) -> $type {
220 val.value
221 }
222 }
223 };
224}
225
226FieldValue_impl_for!(u8);
227FieldValue_impl_for!(u16);
228FieldValue_impl_for!(u32);
229FieldValue_impl_for!(u64);
230FieldValue_impl_for!(u128);
231FieldValue_impl_for!(usize);
232
233impl<T: UIntLike, R: RegisterLongName> FieldValue<T, R> {
234 #[inline]
235 pub fn none() -> Self {
236 Self {
237 mask: T::zero(),
238 value: T::zero(),
239 associated_register: PhantomData,
240 }
241 }
242
243 #[inline]
245 pub const fn mask(&self) -> T {
246 self.mask as T
247 }
248
249 #[inline]
250 pub fn read(&self, field: Field<T, R>) -> T {
251 field.read(self.value)
252 }
253
254 #[inline]
256 pub fn modify(self, val: T) -> T {
257 (val & !self.mask) | self.value
258 }
259
260 #[inline]
263 pub fn any_matching_bits_set(&self, val: T) -> bool {
264 val & self.mask & self.value != T::zero()
265 }
266
267 #[inline]
269 pub fn matches_all(&self, val: T) -> bool {
270 val & self.mask == self.value
271 }
272}
273
274impl<T: UIntLike, R: RegisterLongName> Add for FieldValue<T, R> {
276 type Output = Self;
277
278 #[inline]
279 fn add(self, rhs: Self) -> Self {
280 FieldValue {
281 mask: self.mask | rhs.mask,
282 value: self.value | rhs.value,
283 associated_register: PhantomData,
284 }
285 }
286}
287
288impl<T: UIntLike, R: RegisterLongName> AddAssign for FieldValue<T, R> {
290 #[inline]
291 fn add_assign(&mut self, rhs: FieldValue<T, R>) {
292 self.mask |= rhs.mask;
293 self.value |= rhs.value;
294 }
295}
296
297pub trait TryFromValue<V> {
300 type EnumType;
301
302 fn try_from_value(v: V) -> Option<Self::EnumType>;
303}
304
305#[macro_export]
307macro_rules! bitmask {
308 ($numbits:expr) => {
309 (1 << ($numbits - 1)) + ((1 << ($numbits - 1)) - 1)
310 };
311}
312
313#[macro_export]
315macro_rules! register_bitmasks {
316 {
317 $(#[$outer:meta])*
319 $valtype:ident, $reg_mod:ident, $reg_desc:ident, [
320 $( $(#[$inner:meta])* $field:ident OFFSET($offset:expr)),+ $(,)?
321 ]
322 } => {
323 $(#[$outer])*
324 $( $crate::register_bitmasks!($valtype, $reg_desc, $(#[$inner])* $field, $offset, 1, []); )*
325 $crate::register_bitmasks!(@debug $valtype, $reg_mod, $reg_desc, [$($field),*]);
326 };
327
328 {
329 $(#[$outer:meta])*
332 $valtype:ident, $reg_mod:ident, $reg_desc:ident, [
333 $( $(#[$inner:meta])* $field:ident $offset:expr ),+ $(,)?
334 ]
335 } => {
336 $(#[$outer])*
337 $( $crate::register_bitmasks!($valtype, $reg_desc, $(#[$inner])* $field, $offset, 1, []); )*
338 $crate::register_bitmasks!(@debug $valtype, $reg_mod, $reg_desc, [$($field),*]);
339 };
340
341 {
342 $(#[$outer:meta])*
344 $valtype:ident, $reg_mod:ident, $reg_desc:ident, [
345 $( $(#[$inner:meta])* $field:ident OFFSET($offset:expr) NUMBITS($numbits:expr) ),+ $(,)?
346 ]
347 } => {
348 $(#[$outer])*
349 $( $crate::register_bitmasks!($valtype, $reg_desc, $(#[$inner])* $field, $offset, $numbits, []); )*
350 $crate::register_bitmasks!(@debug $valtype, $reg_mod, $reg_desc, [$($field),*]);
351 };
352
353 {
354 $(#[$outer:meta])*
356 $valtype:ident, $reg_mod:ident, $reg_desc:ident, [
357 $( $(#[$inner:meta])* $field:ident OFFSET($offset:expr) NUMBITS($numbits:expr)
358 $values:tt ),+ $(,)?
359 ]
360 } => {
361 $(#[$outer])*
362 $( $crate::register_bitmasks!($valtype, $reg_desc, $(#[$inner])* $field, $offset, $numbits,
363 $values); )*
364 $crate::register_bitmasks!(@debug $valtype, $reg_mod, $reg_desc, [$($field),*]);
365 };
366
367 {
368 $valtype:ident, $reg_desc:ident, $(#[$outer:meta])* $field:ident,
369 $offset:expr, $numbits:expr,
370 [$( $(#[$inner:meta])* $valname:ident = $value:expr ),+ $(,)?]
371 } => {
372 #[allow(non_upper_case_globals)]
377 #[allow(unused)]
378 pub const $field: Field<$valtype, $reg_desc> =
379 Field::<$valtype, $reg_desc>::new($crate::bitmask!($numbits), $offset);
380
381 #[allow(non_snake_case)]
382 #[allow(unused)]
383 $(#[$outer])*
384 pub mod $field {
385 #[allow(unused_imports)]
386 use $crate::fields::{TryFromValue, FieldValue};
387 use super::$reg_desc;
388
389 $(
390 #[allow(non_upper_case_globals)]
391 #[allow(unused)]
392 $(#[$inner])*
393 pub const $valname: FieldValue<$valtype, $reg_desc> =
394 FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
395 $offset, $value);
396 )*
397
398 #[allow(non_upper_case_globals)]
399 #[allow(unused)]
400 pub const SET: FieldValue<$valtype, $reg_desc> =
401 FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
402 $offset, $crate::bitmask!($numbits));
403
404 #[allow(non_upper_case_globals)]
405 #[allow(unused)]
406 pub const CLEAR: FieldValue<$valtype, $reg_desc> =
407 FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
408 $offset, 0);
409
410 #[allow(dead_code)]
411 #[allow(non_camel_case_types)]
412 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
413 #[repr($valtype)] $(#[$outer])*
415 pub enum Value {
416 $(
417 $(#[$inner])*
418 $valname = $value,
419 )*
420 }
421
422 impl TryFromValue<$valtype> for Value {
423 type EnumType = Value;
424
425 fn try_from_value(v: $valtype) -> Option<Self::EnumType> {
426 match v {
427 $(
428 $(#[$inner])*
429 x if x == Value::$valname as $valtype => Some(Value::$valname),
430 )*
431
432 _ => Option::None
433 }
434 }
435 }
436
437 impl From<Value> for FieldValue<$valtype, $reg_desc> {
438 fn from(v: Value) -> Self {
439 Self::new($crate::bitmask!($numbits), $offset, v as $valtype)
440 }
441 }
442 }
443 };
444 {
445 $valtype:ident, $reg_desc:ident, $(#[$outer:meta])* $field:ident,
446 $offset:expr, $numbits:expr,
447 []
448 } => {
449 #[allow(non_upper_case_globals)]
452 #[allow(unused)]
453 pub const $field: Field<$valtype, $reg_desc> =
454 Field::<$valtype, $reg_desc>::new($crate::bitmask!($numbits), $offset);
455
456 #[allow(non_snake_case)]
457 #[allow(unused)]
458 $(#[$outer])*
459 pub mod $field {
460 #[allow(unused_imports)]
461 use $crate::fields::{FieldValue, TryFromValue};
462 use super::$reg_desc;
463
464 #[allow(non_upper_case_globals)]
465 #[allow(unused)]
466 pub const SET: FieldValue<$valtype, $reg_desc> =
467 FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
468 $offset, $crate::bitmask!($numbits));
469
470 #[allow(non_upper_case_globals)]
471 #[allow(unused)]
472 pub const CLEAR: FieldValue<$valtype, $reg_desc> =
473 FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
474 $offset, 0);
475
476 #[allow(dead_code)]
477 #[allow(non_camel_case_types)]
478 #[derive(Debug)]
479 $(#[$outer])*
480 pub enum Value {}
481
482 impl TryFromValue<$valtype> for Value {
483 type EnumType = Value;
484
485 fn try_from_value(_v: $valtype) -> Option<Self::EnumType> {
486 Option::None
487 }
488 }
489 }
490 };
491
492 (
495 @debug $valtype:ident, $reg_mod:ident, $reg_desc:ident, [$($field:ident),*]
497 ) => {
498 impl $crate::debug::RegisterDebugInfo<$valtype> for $reg_desc {
499 type FieldValueEnumTypes = $crate::register_bitmasks!(
502 @fv_enum_type_seq $valtype, $($field::Value),*
503 );
504
505 fn name() -> &'static str {
506 stringify!($reg_mod)
507 }
508
509 fn field_names() -> &'static [&'static str] {
510 &[
511 $(
512 stringify!($field)
513 ),*
514 ]
515 }
516
517 fn fields() -> &'static [Field<$valtype, Self>] {
518 &[
519 $(
520 $field
521 ),*
522 ]
523 }
524 }
525 };
526
527 (
540 @fv_enum_type_seq $valtype:ident, $enum_val:path $(, $($rest:path),+)?
541 ) => {
542 $crate::debug::FieldValueEnumCons<
543 $valtype,
544 $enum_val,
545 $crate::register_bitmasks!(@fv_enum_type_seq $valtype $(, $($rest),*)*)
546 >
547 };
548 (
549 @fv_enum_type_seq $valtype:ident $(,)?
550 ) => {
551 $crate::debug::FieldValueEnumNil
552 };
553}
554
555#[macro_export]
586macro_rules! register_bitfields {
587 {
588 $valtype:ident, $( $(#[$inner:meta])* $vis:vis $reg:ident $fields:tt ),* $(,)?
589 } => {
590 $(
591 #[allow(non_snake_case)]
592 $(#[$inner])*
593 $vis mod $reg {
594 #[derive(Clone, Copy)]
600 pub struct Register;
601 impl $crate::RegisterLongName for Register {}
602
603 use $crate::fields::Field;
604
605 $crate::register_bitmasks!( $valtype, $reg, Register, $fields );
606 }
607 )*
608 }
609}
610
611#[cfg(test)]
612mod tests {
613 #[derive(Debug, PartialEq, Eq)]
614 enum Foo {
615 Foo0,
616 Foo1,
617 Foo2,
618 Foo3,
619 Foo4,
620 Foo5,
621 Foo6,
622 Foo7,
623 }
624
625 impl crate::fields::TryFromValue<u16> for Foo {
626 type EnumType = Foo;
627
628 fn try_from_value(v: u16) -> Option<Self::EnumType> {
629 Self::try_from_value(v as u32)
630 }
631 }
632 impl crate::fields::TryFromValue<u32> for Foo {
633 type EnumType = Foo;
634
635 fn try_from_value(v: u32) -> Option<Self::EnumType> {
636 match v {
637 0 => Some(Foo::Foo0),
638 1 => Some(Foo::Foo1),
639 2 => Some(Foo::Foo2),
640 3 => Some(Foo::Foo3),
641 4 => Some(Foo::Foo4),
642 5 => Some(Foo::Foo5),
643 6 => Some(Foo::Foo6),
644 7 => Some(Foo::Foo7),
645 _ => None,
646 }
647 }
648 }
649
650 mod field {
651 use super::Foo;
652 use crate::fields::{Field, TryFromValue};
653
654 #[test]
655 fn test_new() {
656 let field8 = Field::<u8, ()>::new(0x12, 3);
657 assert_eq!(field8.mask, 0x12_u8);
658 assert_eq!(field8.shift, 3);
659 let field16 = Field::<u16, ()>::new(0x1234, 5);
660 assert_eq!(field16.mask, 0x1234_u16);
661 assert_eq!(field16.shift, 5);
662 let field32 = Field::<u32, ()>::new(0x12345678, 9);
663 assert_eq!(field32.mask, 0x12345678_u32);
664 assert_eq!(field32.shift, 9);
665 let field64 = Field::<u64, ()>::new(0x12345678_9abcdef0, 1);
666 assert_eq!(field64.mask, 0x12345678_9abcdef0_u64);
667 assert_eq!(field64.shift, 1);
668 let field128 = Field::<u128, ()>::new(0x12345678_9abcdef0_0fedcba9_87654321, 1);
669 assert_eq!(field128.mask, 0x12345678_9abcdef0_0fedcba9_87654321_u128);
670 assert_eq!(field128.shift, 1);
671 }
672
673 #[test]
674 fn test_read() {
675 let field = Field::<u32, ()>::new(0xFF, 4);
676 assert_eq!(field.read(0x123), 0x12);
677 let field = Field::<u32, ()>::new(0xF0F, 4);
678 assert_eq!(field.read(0x1234), 0x103);
679 }
680
681 #[test]
682 fn test_is_set() {
683 let field = Field::<u16, ()>::new(0xFF, 4);
684 assert_eq!(field.is_set(0), false);
685 assert_eq!(field.is_set(0xFFFF), true);
686 assert_eq!(field.is_set(0x0FF0), true);
687 assert_eq!(field.is_set(0x1000), false);
688 assert_eq!(field.is_set(0x0100), true);
689 assert_eq!(field.is_set(0x0010), true);
690 assert_eq!(field.is_set(0x0001), false);
691
692 for shift in 0..24 {
693 let field = Field::<u32, ()>::new(0xFF, shift);
694 for x in 1..=0xFF {
695 assert_eq!(field.is_set(x << shift), true);
696 }
697 assert_eq!(field.is_set(!(0xFF << shift)), false);
698 }
699 }
700
701 #[test]
702 fn test_read_as_enum() {
703 let field = Field::<u16, ()>::new(0x7, 4);
704 assert_eq!(field.read_as_enum(0x1234), Some(Foo::Foo3));
705 assert_eq!(field.read_as_enum(0x5678), Some(Foo::Foo7));
706 assert_eq!(field.read_as_enum(0xFFFF), Some(Foo::Foo7));
707 assert_eq!(field.read_as_enum(0x0000), Some(Foo::Foo0));
708 assert_eq!(field.read_as_enum(0x0010), Some(Foo::Foo1));
709 assert_eq!(field.read_as_enum(0x1204), Some(Foo::Foo0));
710
711 for shift in 0..29 {
712 let field = Field::<u32, ()>::new(0x7, shift);
713 for x in 0..8 {
714 assert_eq!(field.read_as_enum(x << shift), Foo::try_from_value(x));
715 }
716 }
717 }
718 }
719
720 mod field_value {
721 use crate::fields::Field;
722
723 #[test]
724 fn test_from() {
725 let field = Field::<u32, ()>::new(0xFF, 4);
726 assert_eq!(u32::from(field.val(0)), 0);
727 assert_eq!(u32::from(field.val(0xFFFFFFFF)), 0xFF0);
728 assert_eq!(u32::from(field.val(0x12)), 0x120);
729 assert_eq!(u32::from(field.val(0x123)), 0x230);
730
731 for shift in 0..32 {
732 let field = Field::<u32, ()>::new(0xFF, shift);
733 for x in 0..=0xFF {
734 assert_eq!(u32::from(field.val(x)), x << shift);
735 }
736 }
737 }
738
739 #[test]
740 fn test_read_same_field() {
741 let field = Field::<u32, ()>::new(0xFF, 4);
742 assert_eq!(field.val(0).read(field), 0);
743 assert_eq!(field.val(0xFFFFFFFF).read(field), 0xFF);
744 assert_eq!(field.val(0x12).read(field), 0x12);
745 assert_eq!(field.val(0x123).read(field), 0x23);
746
747 for shift in 0..24 {
748 let field = Field::<u32, ()>::new(0xFF, shift);
749 for x in 0..=0xFF {
750 assert_eq!(field.val(x).read(field), x);
751 }
752 }
753 }
754
755 #[test]
756 fn test_read_disjoint_fields() {
757 for shift in 0..24 {
758 let field1 = Field::<u32, ()>::new(0xF0, shift);
759 let field2 = Field::<u32, ()>::new(0x0F, shift);
760 for x in 0..=0xFF {
761 assert_eq!(field1.val(x).read(field2), 0);
762 assert_eq!(field2.val(x).read(field1), 0);
763 }
764 }
765 for shift in 0..24 {
766 let field1 = Field::<u32, ()>::new(0xF, shift);
767 let field2 = Field::<u32, ()>::new(0xF, shift + 4);
768 for x in 0..=0xFF {
769 assert_eq!(field1.val(x).read(field2), 0);
770 assert_eq!(field2.val(x).read(field1), 0);
771 }
772 }
773 }
774
775 #[test]
776 fn test_modify() {
777 let field = Field::<u32, ()>::new(0xFF, 4);
778 assert_eq!(field.val(0x23).modify(0x0000), 0x0230);
779 assert_eq!(field.val(0x23).modify(0xFFFF), 0xF23F);
780 assert_eq!(field.val(0x23).modify(0x1234), 0x1234);
781 assert_eq!(field.val(0x23).modify(0x5678), 0x5238);
782 }
783
784 #[test]
785 fn test_any_matching_bits_set() {
786 let field = Field::<u32, ()>::new(0xFF, 4);
787 assert_eq!(field.val(0x23).any_matching_bits_set(0x1234), true);
788 assert_eq!(field.val(0x23).any_matching_bits_set(0x5678), true);
789 assert_eq!(field.val(0x23).any_matching_bits_set(0x5008), false);
790
791 for shift in 0..24 {
792 let field = Field::<u32, ()>::new(0xFF, shift);
793 let field_value = field.val(0xff);
794 for y in 1..=0xff {
795 assert_eq!(field_value.any_matching_bits_set(y << shift), true,);
796 }
797 assert_eq!(field_value.any_matching_bits_set(0), false);
798 assert_eq!(field_value.any_matching_bits_set(!(0xFF << shift)), false);
799 }
800 }
801
802 #[test]
803 fn test_matches_all() {
804 let field = Field::<u32, ()>::new(0xFF, 4);
805 assert_eq!(field.val(0x23).matches_all(0x1234), true);
806 assert_eq!(field.val(0x23).matches_all(0x5678), false);
807
808 for shift in 0..24 {
809 let field = Field::<u32, ()>::new(0xFF, shift);
810 for x in 0..=0xFF {
811 assert_eq!(field.val(x).matches_all(x << shift), true);
812 assert_eq!(field.val(x + 1).matches_all(x << shift), false);
813 }
814 }
815 }
816
817 #[test]
818 fn test_matches_any() {
819 register_bitfields! {
820 u32,
821
822 TEST [
823 FLAG OFFSET(18) NUMBITS(1) [],
824 SIZE OFFSET(0) NUMBITS(2) [
825 Byte = 0,
826 Halfword = 1,
827 Word = 2
828 ],
829 ]
830 }
831
832 let value: crate::LocalRegisterCopy<u32, TEST::Register> =
833 crate::LocalRegisterCopy::new(2);
834 assert!(value.matches_any(&[TEST::SIZE::Word]));
835 assert!(!value.matches_any(&[TEST::SIZE::Halfword]));
836 assert!(!value.matches_any(&[TEST::SIZE::Byte]));
837 assert!(value.matches_any(&[TEST::SIZE::Word, TEST::FLAG::SET]));
838 assert!(value.matches_any(&[TEST::SIZE::Halfword, TEST::FLAG::CLEAR]));
839 assert!(!value.matches_any(&[TEST::SIZE::Halfword, TEST::FLAG::SET]));
840 let value: crate::LocalRegisterCopy<u32, TEST::Register> =
841 crate::LocalRegisterCopy::new(266241);
842 assert!(value.matches_any(&[TEST::FLAG::SET]));
843 assert!(!value.matches_any(&[TEST::FLAG::CLEAR]));
844 }
845
846 #[test]
847 fn test_add_disjoint_fields() {
848 let field1 = Field::<u32, ()>::new(0xFF, 24);
849 let field2 = Field::<u32, ()>::new(0xFF, 16);
850 let field3 = Field::<u32, ()>::new(0xFF, 8);
851 let field4 = Field::<u32, ()>::new(0xFF, 0);
852 assert_eq!(
853 u32::from(
854 field1.val(0x12) + field2.val(0x34) + field3.val(0x56) + field4.val(0x78)
855 ),
856 0x12345678
857 );
858
859 for shift in 0..24 {
860 let field1 = Field::<u32, ()>::new(0xF, shift);
861 let field2 = Field::<u32, ()>::new(0xF, shift + 4);
862 for x in 0..=0xF {
863 for y in 0..=0xF {
864 assert_eq!(
865 u32::from(field1.val(x) + field2.val(y)),
866 (x | (y << 4)) << shift
867 );
868 }
869 }
870 }
871 }
872
873 #[test]
874 fn test_add_assign_disjoint_fields() {
875 let field1 = Field::<u32, ()>::new(0xFF, 24);
876 let field2 = Field::<u32, ()>::new(0xFF, 16);
877 let field3 = Field::<u32, ()>::new(0xFF, 8);
878 let field4 = Field::<u32, ()>::new(0xFF, 0);
879
880 let mut value = field1.val(0x12);
881 value += field2.val(0x34);
882 value += field3.val(0x56);
883 value += field4.val(0x78);
884 assert_eq!(u32::from(value), 0x12345678);
885
886 for shift in 0..24 {
887 let field1 = Field::<u32, ()>::new(0xF, shift);
888 let field2 = Field::<u32, ()>::new(0xF, shift + 4);
889 for x in 0..=0xF {
890 for y in 0..=0xF {
891 let mut value = field1.val(x);
892 value += field2.val(y);
893 assert_eq!(u32::from(value), (x | (y << 4)) << shift);
894 }
895 }
896 }
897 }
898 }
899
900 }