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: mask,
90 shift: 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 {
218 fn from(val: FieldValue<$type, R>) -> $type {
219 val.value
220 }
221 }
222 };
223}
224
225FieldValue_impl_for!(u8);
226FieldValue_impl_for!(u16);
227FieldValue_impl_for!(u32);
228FieldValue_impl_for!(u64);
229FieldValue_impl_for!(u128);
230FieldValue_impl_for!(usize);
231
232impl<T: UIntLike, R: RegisterLongName> FieldValue<T, R> {
233 #[inline]
234 pub fn none() -> Self {
235 Self {
236 mask: T::zero(),
237 value: T::zero(),
238 associated_register: PhantomData,
239 }
240 }
241
242 #[inline]
244 pub const fn mask(&self) -> T {
245 self.mask as T
246 }
247
248 #[inline]
249 pub fn read(&self, field: Field<T, R>) -> T {
250 field.read(self.value)
251 }
252
253 #[inline]
255 pub fn modify(self, val: T) -> T {
256 (val & !self.mask) | self.value
257 }
258
259 #[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_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 };
326 {
327 $(#[$outer:meta])*
330 $valtype:ident, $reg_desc:ident, [
331 $( $(#[$inner:meta])* $field:ident $offset:expr ),+ $(,)?
332 ]
333 } => {
334 $(#[$outer])*
335 $( $crate::register_bitmasks!($valtype, $reg_desc, $(#[$inner])* $field, $offset, 1, []); )*
336 };
337
338 {
339 $(#[$outer:meta])*
341 $valtype:ident, $reg_desc:ident, [
342 $( $(#[$inner:meta])* $field:ident OFFSET($offset:expr) NUMBITS($numbits:expr) ),+ $(,)?
343 ]
344 } => {
345 $(#[$outer])*
346 $( $crate::register_bitmasks!($valtype, $reg_desc, $(#[$inner])* $field, $offset, $numbits, []); )*
347 };
348
349 {
350 $(#[$outer:meta])*
352 $valtype:ident, $reg_desc:ident, [
353 $( $(#[$inner:meta])* $field:ident OFFSET($offset:expr) NUMBITS($numbits:expr)
354 $values:tt ),+ $(,)?
355 ]
356 } => {
357 $(#[$outer])*
358 $( $crate::register_bitmasks!($valtype, $reg_desc, $(#[$inner])* $field, $offset, $numbits,
359 $values); )*
360 };
361 {
362 $valtype:ident, $reg_desc:ident, $(#[$outer:meta])* $field:ident,
363 $offset:expr, $numbits:expr,
364 [$( $(#[$inner:meta])* $valname:ident = $value:expr ),+ $(,)?]
365 } => { #[allow(non_upper_case_globals)]
369 #[allow(unused)]
370 pub const $field: Field<$valtype, $reg_desc> =
371 Field::<$valtype, $reg_desc>::new($crate::bitmask!($numbits), $offset);
372
373 #[allow(non_snake_case)]
374 #[allow(unused)]
375 $(#[$outer])*
376 pub mod $field {
377 #[allow(unused_imports)]
378 use $crate::fields::{TryFromValue, FieldValue};
379 use super::$reg_desc;
380
381 $(
382 #[allow(non_upper_case_globals)]
383 #[allow(unused)]
384 $(#[$inner])*
385 pub const $valname: FieldValue<$valtype, $reg_desc> =
386 FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
387 $offset, $value);
388 )*
389
390 #[allow(non_upper_case_globals)]
391 #[allow(unused)]
392 pub const SET: FieldValue<$valtype, $reg_desc> =
393 FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
394 $offset, $crate::bitmask!($numbits));
395
396 #[allow(non_upper_case_globals)]
397 #[allow(unused)]
398 pub const CLEAR: FieldValue<$valtype, $reg_desc> =
399 FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
400 $offset, 0);
401
402 #[allow(dead_code)]
403 #[allow(non_camel_case_types)]
404 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
405 #[repr($valtype)] $(#[$outer])*
407 pub enum Value {
408 $(
409 $(#[$inner])*
410 $valname = $value,
411 )*
412 }
413
414 impl TryFromValue<$valtype> for Value {
415 type EnumType = Value;
416
417 fn try_from_value(v: $valtype) -> Option<Self::EnumType> {
418 match v {
419 $(
420 $(#[$inner])*
421 x if x == Value::$valname as $valtype => Some(Value::$valname),
422 )*
423
424 _ => Option::None
425 }
426 }
427 }
428
429 impl From<Value> for FieldValue<$valtype, $reg_desc> {
430 fn from(v: Value) -> Self {
431 Self::new($crate::bitmask!($numbits), $offset, v as $valtype)
432 }
433 }
434 }
435 };
436 {
437 $valtype:ident, $reg_desc:ident, $(#[$outer:meta])* $field:ident,
438 $offset:expr, $numbits:expr,
439 []
440 } => { #[allow(non_upper_case_globals)]
442 #[allow(unused)]
443 pub const $field: Field<$valtype, $reg_desc> =
444 Field::<$valtype, $reg_desc>::new($crate::bitmask!($numbits), $offset);
445
446 #[allow(non_snake_case)]
447 #[allow(unused)]
448 $(#[$outer])*
449 pub mod $field {
450 #[allow(unused_imports)]
451 use $crate::fields::{FieldValue, TryFromValue};
452 use super::$reg_desc;
453
454 #[allow(non_upper_case_globals)]
455 #[allow(unused)]
456 pub const SET: FieldValue<$valtype, $reg_desc> =
457 FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
458 $offset, $crate::bitmask!($numbits));
459
460 #[allow(non_upper_case_globals)]
461 #[allow(unused)]
462 pub const CLEAR: FieldValue<$valtype, $reg_desc> =
463 FieldValue::<$valtype, $reg_desc>::new($crate::bitmask!($numbits),
464 $offset, 0);
465
466 #[allow(dead_code)]
467 #[allow(non_camel_case_types)]
468 $(#[$outer])*
469 pub enum Value {}
470
471 impl TryFromValue<$valtype> for Value {
472 type EnumType = Value;
473
474 fn try_from_value(_v: $valtype) -> Option<Self::EnumType> {
475 Option::None
476 }
477 }
478 }
479 };
480}
481
482#[macro_export]
484macro_rules! register_bitfields {
485 {
486 $valtype:ident, $( $(#[$inner:meta])* $vis:vis $reg:ident $fields:tt ),* $(,)?
487 } => {
488 $(
489 #[allow(non_snake_case)]
490 $(#[$inner])*
491 $vis mod $reg {
492 #[derive(Clone, Copy)]
498 pub struct Register;
499 impl $crate::RegisterLongName for Register {}
500
501 use $crate::fields::Field;
502
503 $crate::register_bitmasks!( $valtype, Register, $fields );
504 }
505 )*
506 }
507}
508
509#[cfg(test)]
510mod tests {
511 #[derive(Debug, PartialEq, Eq)]
512 enum Foo {
513 Foo0,
514 Foo1,
515 Foo2,
516 Foo3,
517 Foo4,
518 Foo5,
519 Foo6,
520 Foo7,
521 }
522
523 impl crate::fields::TryFromValue<u16> for Foo {
524 type EnumType = Foo;
525
526 fn try_from_value(v: u16) -> Option<Self::EnumType> {
527 Self::try_from_value(v as u32)
528 }
529 }
530 impl crate::fields::TryFromValue<u32> for Foo {
531 type EnumType = Foo;
532
533 fn try_from_value(v: u32) -> Option<Self::EnumType> {
534 match v {
535 0 => Some(Foo::Foo0),
536 1 => Some(Foo::Foo1),
537 2 => Some(Foo::Foo2),
538 3 => Some(Foo::Foo3),
539 4 => Some(Foo::Foo4),
540 5 => Some(Foo::Foo5),
541 6 => Some(Foo::Foo6),
542 7 => Some(Foo::Foo7),
543 _ => None,
544 }
545 }
546 }
547
548 mod field {
549 use super::Foo;
550 use crate::fields::{Field, TryFromValue};
551
552 #[test]
553 fn test_new() {
554 let field8 = Field::<u8, ()>::new(0x12, 3);
555 assert_eq!(field8.mask, 0x12_u8);
556 assert_eq!(field8.shift, 3);
557 let field16 = Field::<u16, ()>::new(0x1234, 5);
558 assert_eq!(field16.mask, 0x1234_u16);
559 assert_eq!(field16.shift, 5);
560 let field32 = Field::<u32, ()>::new(0x12345678, 9);
561 assert_eq!(field32.mask, 0x12345678_u32);
562 assert_eq!(field32.shift, 9);
563 let field64 = Field::<u64, ()>::new(0x12345678_9abcdef0, 1);
564 assert_eq!(field64.mask, 0x12345678_9abcdef0_u64);
565 assert_eq!(field64.shift, 1);
566 let field128 = Field::<u128, ()>::new(0x12345678_9abcdef0_0fedcba9_87654321, 1);
567 assert_eq!(field128.mask, 0x12345678_9abcdef0_0fedcba9_87654321_u128);
568 assert_eq!(field128.shift, 1);
569 }
570
571 #[test]
572 fn test_read() {
573 let field = Field::<u32, ()>::new(0xFF, 4);
574 assert_eq!(field.read(0x123), 0x12);
575 let field = Field::<u32, ()>::new(0xF0F, 4);
576 assert_eq!(field.read(0x1234), 0x103);
577 }
578
579 #[test]
580 fn test_is_set() {
581 let field = Field::<u16, ()>::new(0xFF, 4);
582 assert_eq!(field.is_set(0), false);
583 assert_eq!(field.is_set(0xFFFF), true);
584 assert_eq!(field.is_set(0x0FF0), true);
585 assert_eq!(field.is_set(0x1000), false);
586 assert_eq!(field.is_set(0x0100), true);
587 assert_eq!(field.is_set(0x0010), true);
588 assert_eq!(field.is_set(0x0001), false);
589
590 for shift in 0..24 {
591 let field = Field::<u32, ()>::new(0xFF, shift);
592 for x in 1..=0xFF {
593 assert_eq!(field.is_set(x << shift), true);
594 }
595 assert_eq!(field.is_set(!(0xFF << shift)), false);
596 }
597 }
598
599 #[test]
600 fn test_read_as_enum() {
601 let field = Field::<u16, ()>::new(0x7, 4);
602 assert_eq!(field.read_as_enum(0x1234), Some(Foo::Foo3));
603 assert_eq!(field.read_as_enum(0x5678), Some(Foo::Foo7));
604 assert_eq!(field.read_as_enum(0xFFFF), Some(Foo::Foo7));
605 assert_eq!(field.read_as_enum(0x0000), Some(Foo::Foo0));
606 assert_eq!(field.read_as_enum(0x0010), Some(Foo::Foo1));
607 assert_eq!(field.read_as_enum(0x1204), Some(Foo::Foo0));
608
609 for shift in 0..29 {
610 let field = Field::<u32, ()>::new(0x7, shift);
611 for x in 0..8 {
612 assert_eq!(field.read_as_enum(x << shift), Foo::try_from_value(x));
613 }
614 }
615 }
616 }
617
618 mod field_value {
619 use crate::fields::Field;
620
621 #[test]
622 fn test_from() {
623 let field = Field::<u32, ()>::new(0xFF, 4);
624 assert_eq!(u32::from(field.val(0)), 0);
625 assert_eq!(u32::from(field.val(0xFFFFFFFF)), 0xFF0);
626 assert_eq!(u32::from(field.val(0x12)), 0x120);
627 assert_eq!(u32::from(field.val(0x123)), 0x230);
628
629 for shift in 0..32 {
630 let field = Field::<u32, ()>::new(0xFF, shift);
631 for x in 0..=0xFF {
632 assert_eq!(u32::from(field.val(x)), x << shift);
633 }
634 }
635 }
636
637 #[test]
638 fn test_read_same_field() {
639 let field = Field::<u32, ()>::new(0xFF, 4);
640 assert_eq!(field.val(0).read(field), 0);
641 assert_eq!(field.val(0xFFFFFFFF).read(field), 0xFF);
642 assert_eq!(field.val(0x12).read(field), 0x12);
643 assert_eq!(field.val(0x123).read(field), 0x23);
644
645 for shift in 0..24 {
646 let field = Field::<u32, ()>::new(0xFF, shift);
647 for x in 0..=0xFF {
648 assert_eq!(field.val(x).read(field), x);
649 }
650 }
651 }
652
653 #[test]
654 fn test_read_disjoint_fields() {
655 for shift in 0..24 {
656 let field1 = Field::<u32, ()>::new(0xF0, shift);
657 let field2 = Field::<u32, ()>::new(0x0F, shift);
658 for x in 0..=0xFF {
659 assert_eq!(field1.val(x).read(field2), 0);
660 assert_eq!(field2.val(x).read(field1), 0);
661 }
662 }
663 for shift in 0..24 {
664 let field1 = Field::<u32, ()>::new(0xF, shift);
665 let field2 = Field::<u32, ()>::new(0xF, shift + 4);
666 for x in 0..=0xFF {
667 assert_eq!(field1.val(x).read(field2), 0);
668 assert_eq!(field2.val(x).read(field1), 0);
669 }
670 }
671 }
672
673 #[test]
674 fn test_modify() {
675 let field = Field::<u32, ()>::new(0xFF, 4);
676 assert_eq!(field.val(0x23).modify(0x0000), 0x0230);
677 assert_eq!(field.val(0x23).modify(0xFFFF), 0xF23F);
678 assert_eq!(field.val(0x23).modify(0x1234), 0x1234);
679 assert_eq!(field.val(0x23).modify(0x5678), 0x5238);
680 }
681
682 #[test]
683 fn test_any_matching_bits_set() {
684 let field = Field::<u32, ()>::new(0xFF, 4);
685 assert_eq!(field.val(0x23).any_matching_bits_set(0x1234), true);
686 assert_eq!(field.val(0x23).any_matching_bits_set(0x5678), true);
687 assert_eq!(field.val(0x23).any_matching_bits_set(0x5008), false);
688
689 for shift in 0..24 {
690 let field = Field::<u32, ()>::new(0xFF, shift);
691 let field_value = field.val(0xff);
692 for y in 1..=0xff {
693 assert_eq!(field_value.any_matching_bits_set(y << shift), true,);
694 }
695 assert_eq!(field_value.any_matching_bits_set(0), false);
696 assert_eq!(field_value.any_matching_bits_set(!(0xFF << shift)), false);
697 }
698 }
699
700 #[test]
701 fn test_matches_all() {
702 let field = Field::<u32, ()>::new(0xFF, 4);
703 assert_eq!(field.val(0x23).matches_all(0x1234), true);
704 assert_eq!(field.val(0x23).matches_all(0x5678), false);
705
706 for shift in 0..24 {
707 let field = Field::<u32, ()>::new(0xFF, shift);
708 for x in 0..=0xFF {
709 assert_eq!(field.val(x).matches_all(x << shift), true);
710 assert_eq!(field.val(x + 1).matches_all(x << shift), false);
711 }
712 }
713 }
714
715 #[test]
716 fn test_matches_any() {
717 register_bitfields! {
718 u32,
719
720 TEST [
721 FLAG OFFSET(18) NUMBITS(1) [],
722 SIZE OFFSET(0) NUMBITS(2) [
723 Byte = 0,
724 Halfword = 1,
725 Word = 2
726 ],
727 ]
728 }
729
730 let value: crate::LocalRegisterCopy<u32, TEST::Register> =
731 crate::LocalRegisterCopy::new(2);
732 assert!(value.matches_any(&[TEST::SIZE::Word]));
733 assert!(!value.matches_any(&[TEST::SIZE::Halfword]));
734 assert!(!value.matches_any(&[TEST::SIZE::Byte]));
735 assert!(value.matches_any(&[TEST::SIZE::Word, TEST::FLAG::SET]));
736 assert!(value.matches_any(&[TEST::SIZE::Halfword, TEST::FLAG::CLEAR]));
737 assert!(!value.matches_any(&[TEST::SIZE::Halfword, TEST::FLAG::SET]));
738 let value: crate::LocalRegisterCopy<u32, TEST::Register> =
739 crate::LocalRegisterCopy::new(266241);
740 assert!(value.matches_any(&[TEST::FLAG::SET]));
741 assert!(!value.matches_any(&[TEST::FLAG::CLEAR]));
742 }
743
744 #[test]
745 fn test_add_disjoint_fields() {
746 let field1 = Field::<u32, ()>::new(0xFF, 24);
747 let field2 = Field::<u32, ()>::new(0xFF, 16);
748 let field3 = Field::<u32, ()>::new(0xFF, 8);
749 let field4 = Field::<u32, ()>::new(0xFF, 0);
750 assert_eq!(
751 u32::from(
752 field1.val(0x12) + field2.val(0x34) + field3.val(0x56) + field4.val(0x78)
753 ),
754 0x12345678
755 );
756
757 for shift in 0..24 {
758 let field1 = Field::<u32, ()>::new(0xF, shift);
759 let field2 = Field::<u32, ()>::new(0xF, shift + 4);
760 for x in 0..=0xF {
761 for y in 0..=0xF {
762 assert_eq!(
763 u32::from(field1.val(x) + field2.val(y)),
764 (x | (y << 4)) << shift
765 );
766 }
767 }
768 }
769 }
770
771 #[test]
772 fn test_add_assign_disjoint_fields() {
773 let field1 = Field::<u32, ()>::new(0xFF, 24);
774 let field2 = Field::<u32, ()>::new(0xFF, 16);
775 let field3 = Field::<u32, ()>::new(0xFF, 8);
776 let field4 = Field::<u32, ()>::new(0xFF, 0);
777
778 let mut value = field1.val(0x12);
779 value += field2.val(0x34);
780 value += field3.val(0x56);
781 value += field4.val(0x78);
782 assert_eq!(u32::from(value), 0x12345678);
783
784 for shift in 0..24 {
785 let field1 = Field::<u32, ()>::new(0xF, shift);
786 let field2 = Field::<u32, ()>::new(0xF, shift + 4);
787 for x in 0..=0xF {
788 for y in 0..=0xF {
789 let mut value = field1.val(x);
790 value += field2.val(y);
791 assert_eq!(u32::from(value), (x | (y << 4)) << shift);
792 }
793 }
794 }
795 }
796 }
797
798 }