use crate::{memory_region::MemoryRegion, register_data::RegisterData};
use std::{error::Error, fmt::Display, ops::Range, rc::Rc};
#[derive(Debug, Clone, Copy)]
pub struct MissingRegisterError(gimli::Register);
impl Display for MissingRegisterError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Missing register: {}",
gimli::Arm::register_name(self.0)
.map(|n| n.to_string())
.unwrap_or_else(|| format!("{}", self.0 .0))
)
}
}
impl Error for MissingRegisterError {}
#[derive(Debug, Clone)]
pub struct MemoryReadError(pub Rc<dyn Error>);
impl Display for MemoryReadError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Memory read error: {}", self.0)
}
}
impl Error for MemoryReadError {}
impl PartialEq for MemoryReadError {
fn eq(&self, other: &Self) -> bool {
self.0.to_string() == other.0.to_string()
}
}
pub struct DeviceMemory<'memory, RB: funty::Integral> {
register_data: Vec<Box<dyn RegisterData<RB> + 'memory>>,
memory_regions: Vec<Box<dyn MemoryRegion + 'memory>>,
}
impl<'memory, RB: funty::Integral> DeviceMemory<'memory, RB> {
pub fn new() -> Self {
Self {
register_data: Vec::new(),
memory_regions: Vec::new(),
}
}
pub fn add_memory_region<M: MemoryRegion + 'memory>(&mut self, region: M) {
self.memory_regions.push(Box::new(region));
}
pub fn add_register_data<RD: RegisterData<RB> + 'memory>(&mut self, data: RD) {
self.register_data.push(Box::new(data));
}
pub fn read_slice(
&self,
address_range: Range<u64>,
) -> Result<Option<Vec<u8>>, MemoryReadError> {
for mr in self.memory_regions.iter() {
if let Some(v) = mr.read(address_range.clone())? {
return Ok(Some(v));
}
}
Ok(None)
}
pub fn read_u8(&self, address: u64) -> Result<Option<u8>, MemoryReadError> {
for mr in self.memory_regions.iter() {
if let Some(v) = mr.read_u8(address)? {
return Ok(Some(v));
}
}
Ok(None)
}
pub fn read_u32(
&self,
address: u64,
endianness: gimli::RunTimeEndian,
) -> Result<Option<u32>, MemoryReadError> {
for mr in self.memory_regions.iter() {
if let Some(v) = mr.read_u32(address, endianness)? {
return Ok(Some(v));
}
}
Ok(None)
}
pub fn register(&self, register: gimli::Register) -> Result<RB, MissingRegisterError> {
self.register_data
.iter()
.find_map(|registers| registers.register(register))
.ok_or(MissingRegisterError(register))
}
pub fn register_ref(&self, register: gimli::Register) -> Result<&RB, MissingRegisterError> {
self.register_data
.iter()
.find_map(|registers| registers.register_ref(register))
.ok_or(MissingRegisterError(register))
}
pub fn register_mut(
&mut self,
register: gimli::Register,
) -> Result<&mut RB, MissingRegisterError> {
self.register_data
.iter_mut()
.find_map(|registers| registers.register_mut(register))
.ok_or(MissingRegisterError(register))
}
}
impl<'memory, RB: funty::Integral> Default for DeviceMemory<'memory, RB> {
fn default() -> Self {
Self::new()
}
}