Skip to content
17 changes: 17 additions & 0 deletions src/builder/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
macro_rules! impl_get_bit {
($field: ident, $inner: ident, $getter: ident, $idx: literal) => {
#[inline]
pub fn $field(&self) -> bool {
self.$inner.$getter($idx)
}
};
}

macro_rules! impl_set_bit {
($field_setter: ident, $inner: ident, $setter: ident, $idx: literal) => {
#[inline]
pub fn $field_setter(&mut self, value: bool) {
self.$inner.$setter($idx, value);
}
};
}
128 changes: 128 additions & 0 deletions src/builder/medeleg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//! medeleg register builder

use crate::register::medeleg::*;
use bit_field::BitField;
use core::mem::size_of;

/// medeleg register builder
pub struct MedelegBuilder {
bits: usize,
}

/// medeleg register value
#[derive(Clone, Copy, Debug)]
#[repr(transparent)]
pub struct MedelegValue {
bits: usize,
}

macro_rules! impl_medeleg_writable {
($type_name: ident, $inner: ident) => {
impl $type_name {
impl_set_bit!(set_instruction_misaligned, $inner, set_bit, 0);

impl_set_bit!(set_instruction_fault, $inner, set_bit, 1);

impl_set_bit!(set_illegal_instruction, $inner, set_bit, 2);

impl_set_bit!(set_breakpoint, $inner, set_bit, 3);

impl_set_bit!(set_load_misaligned, $inner, set_bit, 4);

impl_set_bit!(set_load_fault, $inner, set_bit, 5);

impl_set_bit!(set_store_misaligned, $inner, set_bit, 6);

impl_set_bit!(set_store_fault, $inner, set_bit, 7);

impl_set_bit!(set_user_env_call, $inner, set_bit, 8);

impl_set_bit!(set_supervisor_env_call, $inner, set_bit, 9);

impl_set_bit!(set_machine_env_call, $inner, set_bit, 11);

impl_set_bit!(set_instruction_page_fault, $inner, set_bit, 12);

impl_set_bit!(set_load_page_fault, $inner, set_bit, 13);

impl_set_bit!(set_store_page_fault, $inner, set_bit, 15);
}
};
}

macro_rules! impl_medeleg_readable {
($type_name: ident, $inner: ident) => {
impl $type_name {
impl_get_bit!(instruction_misaligned, $inner, get_bit, 0);

impl_get_bit!(instruction_fault, $inner, get_bit, 1);

impl_get_bit!(illegal_instruction, $inner, get_bit, 2);

impl_get_bit!(breakpoint, $inner, get_bit, 3);

impl_get_bit!(load_misaligned, $inner, get_bit, 4);

impl_get_bit!(load_fault, $inner, get_bit, 5);

impl_get_bit!(store_misaligned, $inner, get_bit, 6);

impl_get_bit!(store_fault, $inner, get_bit, 7);

impl_get_bit!(user_env_call, $inner, get_bit, 8);

impl_get_bit!(supervisor_env_call, $inner, get_bit, 9);

impl_get_bit!(machine_env_call, $inner, get_bit, 11);

impl_get_bit!(instruction_page_fault, $inner, get_bit, 12);

impl_get_bit!(load_page_fault, $inner, get_bit, 13);

impl_get_bit!(store_page_fault, $inner, get_bit, 15);
}
};
}

impl_medeleg_writable!(MedelegBuilder, bits);
impl_medeleg_readable!(MedelegBuilder, bits);

impl MedelegBuilder {
#[inline]
pub fn new() -> Self {
Self { bits: 0usize }
}

#[inline]
pub fn bits(&self) -> usize {
self.bits
}

#[inline]
pub fn build(&self) -> MedelegValue {
MedelegValue { bits: self.bits }
}
}

impl_medeleg_readable!(MedelegValue, bits);

impl MedelegValue {
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
}

impl From<MedelegValue> for MedelegBuilder {
#[inline]
fn from(value: MedelegValue) -> Self {
MedelegBuilder { bits: value.bits() }
}
}

impl From<MedelegBuilder> for MedelegValue {
#[inline]
fn from(value: MedelegBuilder) -> Self {
MedelegValue { bits: value.bits() }
}
}
96 changes: 96 additions & 0 deletions src/builder/mideleg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//! mideleg builder

use crate::register::mideleg::*;
use bit_field::BitField;

/// mideleg builder
#[derive(Clone, Copy, Debug)]
pub struct MidelegBuilder {
bits: usize,
}

/// mideleg builder
#[derive(Clone, Copy, Debug)]
#[repr(transparent)]
pub struct MidelegValue {
bits: usize,
}

macro_rules! impl_mideleg_writable {
($type_name: ident, $inner: ident) => {
impl $type_name {
impl_set_bit!(set_usoft, $inner, set_bit, 0);

impl_set_bit!(set_ssoft, $inner, set_bit, 1);

impl_set_bit!(set_utimer, $inner, set_bit, 4);

impl_set_bit!(set_stimer, $inner, set_bit, 5);

impl_set_bit!(set_uext, $inner, set_bit, 8);

impl_set_bit!(set_sext, $inner, set_bit, 9);
}
};
}

macro_rules! impl_mideleg_readable {
($type_name: ident, $inner: ident) => {
impl $type_name {
impl_get_bit!(usoft, $inner, get_bit, 0);

impl_get_bit!(ssoft, $inner, get_bit, 1);

impl_get_bit!(utimer, $inner, get_bit, 4);

impl_get_bit!(stimer, $inner, get_bit, 5);

impl_get_bit!(uext, $inner, get_bit, 8);

impl_get_bit!(sext, $inner, get_bit, 9);
}
};
}

impl_mideleg_readable!(MidelegBuilder, bits);
impl_mideleg_writable!(MidelegBuilder, bits);

impl MidelegBuilder {
#[inline]
pub fn new() -> Self {
Self { bits: 0usize }
}

#[inline]
pub fn bits(&self) -> usize {
self.bits
}

#[inline]
pub fn build(&self) -> MidelegValue {
MidelegValue { bits: self.bits }
}
}

impl_mideleg_readable!(MidelegValue, bits);

impl MidelegValue {
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
}

impl From<MidelegValue> for MidelegBuilder {
#[inline]
fn from(value: MidelegValue) -> Self {
MidelegBuilder { bits: value.bits() }
}
}

impl From<MidelegBuilder> for MidelegValue {
#[inline]
fn from(value: MidelegBuilder) -> Self {
MidelegValue { bits: value.bits() }
}
}
102 changes: 102 additions & 0 deletions src/builder/misa.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//! misa builder

use crate::register::misa::*;
use bit_field::BitField;

/// mstatus register builder
#[derive(Clone, Copy, Debug)]
pub struct MisaBuilder {
bits: usize,
}

/// mstatus register value
#[derive(Clone, Copy, Debug)]
pub struct MisaValue {
bits: usize,
}

impl MisaBuilder {
#[inline]
pub fn new() -> Self {
Self { bits: 0usize }
}

#[inline]
pub fn bits(&self) -> usize {
self.bits
}

#[inline]
pub fn build(&self) -> MisaValue {
MisaValue { bits: self.bits }
}

#[inline]
pub fn mxl(&self) -> MXL {
let value = match () {
#[cfg(target_pointer_width = "32")]
() => (self.bits() >> 30) as u8,
#[cfg(target_pointer_width = "64")]
() => (self.bits() >> 62) as u8,
};
match value {
1 => MXL::XLEN32,
2 => MXL::XLEN64,
3 => MXL::XLEN128,
_ => unreachable!(),
}
}

#[inline]
pub fn set_mxl(&mut self, mxl: MXL) {
let value = match mxl {
MXL::XLEN32 => 1,
MXL::XLEN64 => 2,
MXL::XLEN128 => 3,
_ => unreachable!(),
};
match () {
#[cfg(target_pointer_width = "32")]
() => self.bits.set_bits(30..32, value),
#[cfg(target_pointer_width = "64")]
() => self.bits.set_bits(62..64, value),
};
}
}

impl MisaValue {
#[inline]
pub fn bits(&self) -> usize {
self.bits
}

#[inline]
pub fn mxl(&self) -> MXL {
let value = match () {
#[cfg(target_pointer_width = "32")]
() => (self.bits() >> 30) as u8,
#[cfg(target_pointer_width = "64")]
() => (self.bits() >> 62) as u8,
};
match value {
1 => MXL::XLEN32,
2 => MXL::XLEN64,
3 => MXL::XLEN128,
_ => unreachable!(),
}
}
}

impl From<MisaValue> for MisaBuilder {
#[inline]
fn from(value: MisaValue) -> Self {
MisaBuilder { bits: value.bits() }
}
}

impl From<MisaBuilder> for MisaValue {
#[inline]
fn from(value: MisaBuilder) -> Self {
MisaValue { bits: value.bits() }
}
}
8 changes: 8 additions & 0 deletions src/builder/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#[macro_use]
mod macros;

pub mod medeleg;
pub mod mideleg;
pub mod misa;
pub mod mstatus;
pub mod mtvec;
Loading