#[macro_export]
macro_rules! define_cpu_register {
($register:ident as $num_ty:ty => $(
$(#[$field_attr:meta])*
$perm:ident $name:ident: $from:literal $( .. $to:literal =
$(#[$kind_attr:meta])*
$kind_type:ident $kind_name:ident [
$(
$(#[$kind_variant_attr:meta])*
$kind_variant:ident = $kind_variant_val:expr
),*$(,)?
]
)?
),*$(,)?) => {
const _: fn() = || {
fn assert_impl<T: $crate::Int>() {}
assert_impl::<$num_ty>();
};
$($(
$crate::__generate_field_kinds__!($num_ty, $perm, $from .. $to,
$(#[$kind_attr])*
$kind_type $kind_name [
$(
$(#[$kind_variant_attr])*
$kind_variant = $kind_variant_val
),*
]
);
)*)?
$(
$(#[$field_attr])*
#[allow(non_snake_case, dead_code)]
pub mod $name {
$crate::define_cpu_register!(@internal, $num_ty, $register, $perm $name: $from $(.. $to =
$kind_type $kind_name [
$($kind_variant = $kind_variant_val),*
]
)?);
}
)*
$crate::__generate_if_perm__! { @read
pub fn get() -> $num_ty {
<$register as $crate::cpu::RegisterRead<$num_ty>>::read()
}
=> $($perm) *
}
$crate::__generate_if_perm__! { @read
pub fn read<P: $crate::perm::Readable>(field: $crate::Field<$num_ty, P>) -> $num_ty {
let val = <$register as $crate::cpu::RegisterRead<$num_ty>>::read();
$crate::Field::<$num_ty, P>::read(field, val)
}
=> $($perm) *
}
$crate::__generate_if_perm__! { @read
pub fn is_set<P: $crate::perm::Readable>(field: $crate::Field<$num_ty, P>) -> ::core::primitive::bool {
let val = <$register as $crate::cpu::RegisterRead<$num_ty>>::read();
$crate::Field::<$num_ty, P>::read(field, val) != 0
}
=> $($perm) *
}
$crate::__generate_if_perm__! { @write
pub fn set(val: $num_ty) {
<$register as $crate::cpu::RegisterWrite<$num_ty>>::write(val);
}
=> $($perm) *
}
$crate::__generate_if_perm__! { @write
pub fn write(val: $crate::Value<$num_ty>) {
let val = $crate::Value::<$num_ty>::modify(val, 0);
<$register as $crate::cpu::RegisterWrite<$num_ty>>::write(val);
}
=> $($perm) *
}
$crate::__generate_if_perm__! { @read_write
pub fn modify(val: $crate::Value<$num_ty>) {
let reg = <$register as $crate::cpu::RegisterRead<$num_ty>>::read();
let reg = $crate::Value::<$num_ty>::modify(val, reg);
<$register as $crate::cpu::RegisterWrite<$num_ty>>::write(reg);
}
=> $($perm) *
}
};
(@internal, $num_ty:ty, $register:ident, rw $name:ident: $from:literal .. $to:literal = flags $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
$crate::define_cpu_register!(@internal, $num_ty, $register, r $name: $from .. $to = flags $kind_name [
$($kind_variant = $kind_variant_val),*
]);
$crate::define_cpu_register!(@internal, $num_ty, $register, w $name: $from .. $to = flags $kind_name [
$($kind_variant = $kind_variant_val),*
]);
};
(@internal, $num_ty:ty, $register:ident, r $name:ident: $from:literal .. $to:literal = flags $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
pub fn get() -> super::$kind_name {
let val = <super::$register as $crate::cpu::RegisterRead<$num_ty>>::read();
super::$kind_name::from_bits_truncate($crate::get_bits(val, ($from, $to)))
}
};
(@internal, $num_ty:ty, $register:ident, w $name:ident: $from:literal .. $to:literal = flags $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
pub fn set(flags: super::$kind_name) {
let bits = super::$kind_name::bits(&flags);
let val = <super::$register as $crate::cpu::RegisterRead<$num_ty>>::read();
let val = $crate::set_bits(val, ($from, $to), bits);
<super::$register as $crate::cpu::RegisterWrite<$num_ty>>::write(val);
}
};
(@internal, $num_ty:ty, $register:ident, rw $name:ident: $from:literal .. $to:literal = enum $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
$crate::define_cpu_register!(@internal, $num_ty, $register, r $name: $from .. $to = enum $kind_name [
$($kind_variant = $kind_variant_val),*
]);
$crate::define_cpu_register!(@internal, $num_ty, $register, w $name: $from .. $to = enum $kind_name [
$($kind_variant = $kind_variant_val),*
]);
};
(@internal, $num_ty:ty, $register:ident, r $name:ident: $from:literal .. $to:literal = enum $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
pub fn get() -> ::core::option::Option<super::$kind_name> {
let val = <super::$register as $crate::cpu::RegisterRead<$num_ty>>::read();
match $crate::get_bits(val, ($from, $to)) {
$($kind_variant_val => ::core::option::Option::Some(super::$kind_name::$kind_variant),)*
_ => ::core::option::Option::None,
}
}
};
(@internal, $num_ty:ty, $register:ident, w $name:ident: $from:literal .. $to:literal = enum $kind_name:ident [
$($kind_variant:ident = $kind_variant_val:expr),*
]) => {
pub fn set(val: super::$kind_name) {
let bits = match val {
$(super::$kind_name::$kind_variant => $kind_variant_val,)*
};
let val = <super::$register as $crate::cpu::RegisterRead<$num_ty>>::read();
let val = $crate::set_bits(val, ($from, $to), bits);
<super::$register as $crate::cpu::RegisterWrite<$num_ty>>::write(val);
}
};
(@internal, $num_ty:ty, $register:ident, $perm:ident $name:ident: $bit:literal) => {
pub const FIELD: $crate::Field<$num_ty, $crate::__perm_for_name__!($perm)> = $crate::Field::<$num_ty, _>::new(1 << $bit);
$crate::define_cpu_register!(@internal_bit, $num_ty, $register, $perm $name: $bit);
};
(@internal_bit, $num_ty:ty, $register:ident, rw $name:ident: $bit:literal) => {
$crate::define_cpu_register!(@internal_bit, $num_ty, $register, r $name: $bit);
$crate::define_cpu_register!(@internal_bit, $num_ty, $register, w $name: $bit);
};
(@internal_bit, $num_ty:ty, $register:ident, r $name:ident: $bit:literal) => {
pub fn get() -> ::core::primitive::bool {
let val = <super::$register as $crate::cpu::RegisterRead<$num_ty>>::read();
val & (1 << $bit) != 0
}
};
(@internal_bit, $num_ty:ty, $register:ident, w $name:ident: $bit:literal) => {
pub const SET: $crate::Value<$num_ty> = $crate::Value::<$num_ty>::new(1 << $bit, 1 << $bit);
pub const CLEAR: $crate::Value<$num_ty> = $crate::Value::<$num_ty>::new(1 << $bit, 0);
pub fn set(x: ::core::primitive::bool) {
const MASK: $num_ty = 1 << $bit;
match x {
true => <super::$register as $crate::cpu::RegisterWrite<$num_ty>>::set(MASK),
false => <super::$register as $crate::cpu::RegisterWrite<$num_ty>>::clear(MASK),
}
}
};
}
#[macro_export]
macro_rules! impl_cpu_set {
($this:ident, $mask:ident) => {
<$this as $crate::cpu::RegisterWrite<_>>::write(
<$this as $crate::cpu::RegisterRead<_>>::read() | $mask,
)
};
}
#[macro_export]
macro_rules! impl_cpu_clear {
($this:ident, $mask:ident) => {
<$this as $crate::cpu::RegisterWrite<_>>::write(
<$this as $crate::cpu::RegisterRead<_>>::read() & !$mask,
)
};
}