use crate::processor::elements::registers::*;
use super::capability::*;
use crate::processor::elements::cheri::CheriRVFuncs;
pub struct CheriRV64RegisterFile {
regs: [SafeTaggedCap; 31],
}
impl CheriRV64RegisterFile {
pub fn read_u64(&mut self, idx: u8) -> Result<u64, RegisterFileError> {
<Self as RegisterFile<u64>>::read(self, idx)
}
pub fn write_u64(&mut self, idx: u8, val: u64) -> Result<(), RegisterFileError> {
<Self as RegisterFile<u64>>::write(self, idx, val)
}
pub fn read_maybe_cap(&mut self, idx: u8) -> Result<SafeTaggedCap, RegisterFileError> {
<Self as RegisterFile<SafeTaggedCap>>::read(self, idx)
}
pub fn write_maybe_cap(&mut self, idx: u8, val: SafeTaggedCap) -> Result<(), RegisterFileError> {
<Self as RegisterFile<SafeTaggedCap>>::write(self, idx, val)
}
pub fn dump(&self) {
const REGISTER_NAMES: [&str; 32] = [
"zero", "ra", "sp", "gp",
"tp", "t0", "t1", "t2",
"fp", "s1", "a0", "a1",
"a2", "a3", "a4", "a5",
"a6", "a7", "s2", "s3",
"s4", "s5", "s6", "s7",
"s8", "s9", "s10", "s11",
"t3", "t4", "t5", "t6"
];
println!("x{} = {} = 0x{:016x}", 0, REGISTER_NAMES[0], 0);
for i in 1..32 {
match self.regs[i - 1] {
SafeTaggedCap::RawData{ top, bot } => {
println!("x{} = {} = 0x{:08x}{:08x}", i, REGISTER_NAMES[i], top, bot);
}
SafeTaggedCap::ValidCap(cap) => {
println!("x{} = {} = {:x?}", i, REGISTER_NAMES[i], cap);
}
};
}
}
pub fn reset(&mut self) {
self.regs = [SafeTaggedCap::RawData{top: 0, bot: 0}; 31];
}
}
impl RegisterFile<SafeTaggedCap> for CheriRV64RegisterFile {
fn read(&mut self, idx: u8) -> Result<SafeTaggedCap, RegisterFileError> {
let val = match idx {
0 => Ok(SafeTaggedCap::RawData{top: 0, bot: 0}),
1..=31 => Ok(self.regs[(idx - 1) as usize]),
_ => Err(RegisterFileError::InvalidIndex(idx))
}?;
Ok(val)
}
fn write(&mut self, idx: u8, val: SafeTaggedCap) -> Result<(), RegisterFileError> {
match idx {
0 => Ok(()),
1..=31 => {
self.regs[(idx - 1) as usize] = val;
Ok(())
},
_ => Err(RegisterFileError::InvalidIndex(idx))
}?;
Ok(())
}
}
impl RegisterFile<u64> for CheriRV64RegisterFile {
fn read(&mut self, idx: u8) -> Result<u64, RegisterFileError> {
let val = match idx {
0 => Ok(0),
1..=31 => match self.regs[(idx - 1) as usize] {
SafeTaggedCap::RawData{top: _, bot} => Ok(bot),
SafeTaggedCap::ValidCap(cap) => Ok(cap.address())
},
_ => Err(RegisterFileError::InvalidIndex(idx))
}?;
Ok(val as u64)
}
fn write(&mut self, idx: u8, val: u64) -> Result<(), RegisterFileError> {
let val = SafeTaggedCap::RawData{top: 0, bot: val};
match idx {
0 => Ok(()),
1..=31 => {
self.regs[(idx - 1) as usize] = val;
Ok(())
},
_ => Err(RegisterFileError::InvalidIndex(idx))
}?;
Ok(())
}
}
impl Default for CheriRV64RegisterFile {
fn default() -> Self {
CheriRV64RegisterFile {
regs: [SafeTaggedCap::RawData{ top: 0, bot: 0 }; 31],
}
}
}
pub struct IntegerModeCheriRV64RegisterFile<'a> {
base_reg: &'a mut CheriRV64RegisterFile,
base_cap: Cc128Cap
}
impl<'a> RegisterFile<u64> for IntegerModeCheriRV64RegisterFile<'a> {
fn read(&mut self, idx: u8) -> Result<u64, RegisterFileError> {
self.base_reg.read_u64(idx)
}
fn write(&mut self, idx: u8, val: u64) -> Result<(), RegisterFileError> {
self.base_reg.write_u64(idx, val)
}
}
impl<'a> IntegerModeCheriRV64RegisterFile<'a> {
pub fn read_ddc_offset_cap(&mut self, idx: u8) -> anyhow::Result<Cc128Cap> {
let addr = self.read(idx)?;
let cap = self.base_cap.clone();
let (success, new_cap) = Cc128::setCapOffset(&cap, addr);
if !success {
bail!("Setting offset of DDC failed");
}
Ok(new_cap)
}
pub fn wrap(base_reg: &'a mut CheriRV64RegisterFile, base_cap: Cc128Cap) -> Self {
IntegerModeCheriRV64RegisterFile {
base_reg,
base_cap
}
}
}