2023-08-15 09:32:59 -05:00
|
|
|
//! Memory implementations
|
|
|
|
|
|
|
|
pub mod softpaging;
|
2023-08-17 18:41:05 -05:00
|
|
|
|
2023-09-26 16:36:27 -05:00
|
|
|
pub(crate) mod addr;
|
2023-08-17 19:31:49 -05:00
|
|
|
|
2023-10-18 05:14:24 -05:00
|
|
|
use crate::utils::impl_display;
|
2024-07-08 00:22:53 -05:00
|
|
|
pub use addr::Address;
|
2023-08-17 19:31:49 -05:00
|
|
|
|
2023-08-17 18:41:05 -05:00
|
|
|
/// Load-store memory access
|
|
|
|
pub trait Memory {
|
|
|
|
/// Load data from memory on address
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// - Shall not overrun the buffer
|
2023-08-17 19:31:49 -05:00
|
|
|
unsafe fn load(
|
|
|
|
&mut self,
|
|
|
|
addr: Address,
|
|
|
|
target: *mut u8,
|
|
|
|
count: usize,
|
|
|
|
) -> Result<(), LoadError>;
|
2023-08-17 18:41:05 -05:00
|
|
|
|
|
|
|
/// Store data to memory on address
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// - Shall not overrun the buffer
|
|
|
|
unsafe fn store(
|
|
|
|
&mut self,
|
2023-08-17 19:31:49 -05:00
|
|
|
addr: Address,
|
2023-08-17 18:41:05 -05:00
|
|
|
source: *const u8,
|
|
|
|
count: usize,
|
|
|
|
) -> Result<(), StoreError>;
|
|
|
|
|
|
|
|
/// Read from program memory to execute
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// - Data read have to be valid
|
2024-09-28 14:56:39 -05:00
|
|
|
unsafe fn prog_read<T: Copy + 'static>(&mut self, addr: Address) -> T;
|
2023-08-17 18:41:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Unhandled load access trap
|
2023-08-19 16:46:47 -05:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
2023-08-17 19:31:49 -05:00
|
|
|
pub struct LoadError(pub Address);
|
2023-08-19 16:46:47 -05:00
|
|
|
impl_display!(for LoadError =>
|
|
|
|
|LoadError(a)| "Load access error at address {a}",
|
|
|
|
);
|
2023-08-17 18:41:05 -05:00
|
|
|
|
|
|
|
/// Unhandled store access trap
|
2023-08-19 16:46:47 -05:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
2023-08-17 19:31:49 -05:00
|
|
|
pub struct StoreError(pub Address);
|
2023-08-19 16:46:47 -05:00
|
|
|
impl_display!(for StoreError =>
|
|
|
|
|StoreError(a)| "Load access error at address {a}",
|
|
|
|
);
|
2023-08-17 18:41:05 -05:00
|
|
|
|
|
|
|
/// Reason to access memory
|
2023-08-19 16:46:47 -05:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
2023-08-17 18:41:05 -05:00
|
|
|
pub enum MemoryAccessReason {
|
|
|
|
/// Memory was accessed for load (read)
|
|
|
|
Load,
|
|
|
|
/// Memory was accessed for store (write)
|
|
|
|
Store,
|
|
|
|
}
|
|
|
|
|
2023-08-19 16:46:47 -05:00
|
|
|
impl_display!(for MemoryAccessReason => match {
|
2023-08-19 16:57:48 -05:00
|
|
|
Self::Load => const "Load";
|
|
|
|
Self::Store => const "Store";
|
2023-08-19 16:46:47 -05:00
|
|
|
});
|
|
|
|
|
2023-08-17 18:41:05 -05:00
|
|
|
impl From<LoadError> for crate::VmRunError {
|
|
|
|
fn from(value: LoadError) -> Self {
|
|
|
|
Self::LoadAccessEx(value.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<StoreError> for crate::VmRunError {
|
|
|
|
fn from(value: StoreError) -> Self {
|
|
|
|
Self::StoreAccessEx(value.0)
|
|
|
|
}
|
|
|
|
}
|
2024-05-19 11:20:42 -05:00
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct HostMemory;
|
|
|
|
impl Memory for HostMemory {
|
|
|
|
#[inline]
|
|
|
|
unsafe fn load(
|
|
|
|
&mut self,
|
|
|
|
addr: Address,
|
|
|
|
target: *mut u8,
|
|
|
|
count: usize,
|
|
|
|
) -> Result<(), LoadError> {
|
|
|
|
unsafe { core::ptr::copy(addr.get() as *const u8, target, count) }
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
unsafe fn store(
|
|
|
|
&mut self,
|
|
|
|
addr: Address,
|
|
|
|
source: *const u8,
|
|
|
|
count: usize,
|
|
|
|
) -> Result<(), StoreError> {
|
|
|
|
debug_assert!(addr.get() != 0);
|
2024-06-21 16:07:32 -05:00
|
|
|
debug_assert!(!source.is_null());
|
2024-05-19 11:20:42 -05:00
|
|
|
unsafe { core::ptr::copy(source, addr.get() as *mut u8, count) }
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
|
|
|
|
debug_assert!(addr.get() != 0);
|
|
|
|
unsafe { core::ptr::read(addr.get() as *const T) }
|
|
|
|
}
|
|
|
|
}
|