diff --git a/.cargo/config.toml b/.cargo/config.toml index 22dd7c6..7b9f8a7 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -11,5 +11,6 @@ rustflags = [ "-C", "target-feature=-fp-armv8", "-C", "target-cpu=cortex-a53", "-C", "embed-bitcode=yes", + "-Z", "macro-backtrace", ] runner = "cargo make test-runner" diff --git a/crates/tock-registers/src/registers.rs b/crates/tock-registers/src/registers.rs index 60eddaa..3664863 100644 --- a/crates/tock-registers/src/registers.rs +++ b/crates/tock-registers/src/registers.rs @@ -79,32 +79,20 @@ pub trait IntLike: fn zero() -> Self; } -impl IntLike for u8 { - fn zero() -> Self { - 0 - } -} -impl IntLike for u16 { - fn zero() -> Self { - 0 - } -} -impl IntLike for u32 { - fn zero() -> Self { - 0 - } -} -impl IntLike for u64 { - fn zero() -> Self { - 0 - } -} -impl IntLike for u128 { - fn zero() -> Self { - 0 - } +macro_rules! IntLike_impl_for { + ( $( $type:ty ),+ $(,)? ) => { + $( + impl IntLike for $type { + fn zero() -> Self { + 0 + } + } + )* + }; } +IntLike_impl_for!(u8, u16, u32, u64, u128); + /// Descriptive name for each register. pub trait RegisterLongName {} @@ -408,29 +396,19 @@ impl fmt::Debug for LocalRegisterC } } -impl From> for u8 { - fn from(r: LocalRegisterCopy) -> u8 { - r.value - } +macro_rules! From_impl_for { + ( $( $type:ty ),+ $(,)? ) => { + $( + impl From> for $type { + fn from(r: LocalRegisterCopy<$type, R>) -> $type { + r.value + } + } + )* + }; } -impl From> for u16 { - fn from(r: LocalRegisterCopy) -> u16 { - r.value - } -} - -impl From> for u32 { - fn from(r: LocalRegisterCopy) -> u32 { - r.value - } -} - -impl From> for u64 { - fn from(r: LocalRegisterCopy) -> u64 { - r.value - } -} +From_impl_for!(u8, u16, u32, u64, u128); /// In memory volatile register. // To successfully alias this structure onto hardware registers in memory, this @@ -506,6 +484,8 @@ impl InMemoryRegister { } /// Specific section of a register. +/// +/// For the Field, the mask is unshifted, ie. the LSB should always be set. #[derive(Copy, Clone)] pub struct Field { mask: T, @@ -514,6 +494,14 @@ pub struct Field { } impl Field { + pub const fn new(mask: T, shift: usize) -> Field { + Field { + mask: mask, + shift: shift, + associated_register: PhantomData, + } + } + /// Get the raw bitmask used by this Field. pub fn mask(&self) -> T { (self.mask as T) << self.shift @@ -537,66 +525,24 @@ impl Field { } } -// For the Field, the mask is unshifted, ie. the LSB should always be set -impl Field { - pub const fn new(mask: u8, shift: usize) -> Field { - Field { - mask: mask, - shift: shift, - associated_register: PhantomData, +macro_rules! Field_impl_for { + ( $( $type:ty ),+ $(,)? ) => { + $( + impl Field<$type, R> { + pub fn val(&self, value: $type) -> FieldValue<$type, R> { + FieldValue::<$type, R>::new(self.mask, self.shift, value) + } } - } - - pub fn val(&self, value: u8) -> FieldValue { - FieldValue::::new(self.mask, self.shift, value) - } + )* + }; } -impl Field { - pub const fn new(mask: u16, shift: usize) -> Field { - Field { - mask: mask, - shift: shift, - associated_register: PhantomData, - } - } - - pub fn val(&self, value: u16) -> FieldValue { - FieldValue::::new(self.mask, self.shift, value) - } -} - -impl Field { - pub const fn new(mask: u32, shift: usize) -> Field { - Field { - mask: mask, - shift: shift, - associated_register: PhantomData, - } - } - - pub fn val(&self, value: u32) -> FieldValue { - FieldValue::::new(self.mask, self.shift, value) - } -} - -impl Field { - pub const fn new(mask: u64, shift: usize) -> Field { - Field { - mask: mask, - shift: shift, - associated_register: PhantomData, - } - } - - pub fn val(&self, value: u64) -> FieldValue { - FieldValue::::new(self.mask, self.shift, value) - } -} +Field_impl_for!(u8, u16, u32, u64, u128); /// Values for the specific register fields. -// For the FieldValue, the masks and values are shifted into their actual -// location in the register. +/// +/// For the FieldValue, the masks and values are shifted into their actual +/// location in the register. #[derive(Copy, Clone)] pub struct FieldValue { mask: T, @@ -604,76 +550,37 @@ pub struct FieldValue { associated_register: PhantomData, } -// Necessary to split the implementation of new() out because the bitwise -// math isn't treated as const when the type is generic. -// Tracking issue: https://github.com/rust-lang/rfcs/pull/2632 -impl FieldValue { - pub const fn new(mask: u8, shift: usize, value: u8) -> Self { - FieldValue { - mask: mask << shift, - value: (value & mask) << shift, - associated_register: PhantomData, +macro_rules! FieldValue_impl_for { + ( $( $type:ty ),+ $(,)? ) => { + $( + // Necessary to split the implementation of new() out because the bitwise + // math isn't treated as const when the type is generic. + // Tracking issue: https://github.com/rust-lang/rfcs/pull/2632 + impl FieldValue<$type, R> { + pub const fn new(mask: $type, shift: usize, value: $type) -> Self { + FieldValue { + mask: mask << shift, + value: (value & mask) << shift, + associated_register: PhantomData, + } + } } - } -} - -impl From> for u8 { - fn from(val: FieldValue) -> u8 { - val.value - } -} - -impl FieldValue { - pub const fn new(mask: u16, shift: usize, value: u16) -> Self { - FieldValue { - mask: mask << shift, - value: (value & mask) << shift, - associated_register: PhantomData, + // Necessary to split the implementation of From<> out because of the orphan rule + // for foreign trait implementation (see [E0210](https://doc.rust-lang.org/error-index.html#E0210)). + impl From> for $type { + fn from(val: FieldValue<$type, R>) -> $type { + val.value + } } - } + )* + }; } -impl From> for u16 { - fn from(val: FieldValue) -> u16 { - val.value - } -} - -impl FieldValue { - pub const fn new(mask: u32, shift: usize, value: u32) -> Self { - FieldValue { - mask: mask << shift, - value: (value & mask) << shift, - associated_register: PhantomData, - } - } -} - -impl From> for u32 { - fn from(val: FieldValue) -> u32 { - val.value - } -} - -impl FieldValue { - pub const fn new(mask: u64, shift: usize, value: u64) -> Self { - FieldValue { - mask: mask << shift, - value: (value & mask) << shift, - associated_register: PhantomData, - } - } -} - -impl From> for u64 { - fn from(val: FieldValue) -> u64 { - val.value - } -} +FieldValue_impl_for!(u8, u16, u32, u64, u128); impl FieldValue { /// Get the raw bitmask represented by this FieldValue. - pub fn mask(self) -> T { + pub fn mask(&self) -> T { self.mask as T }