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