summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mem.rs136
1 files changed, 130 insertions, 6 deletions
diff --git a/src/mem.rs b/src/mem.rs
index 5959f10..bbaaf38 100644
--- a/src/mem.rs
+++ b/src/mem.rs
@@ -19,10 +19,11 @@ pub struct MemConfig {
}
impl MemConfig {
- pub fn find_device_by_page(&self, page: PageNum) -> Option<Arc<dyn MemDeviceInterface>> {
+ #[allow(clippy::needless_borrow)]
+ pub fn find_device_by_page(&self, page: PageNum) -> Option<&DeviceEntry> {
for entry in self.devices.iter() {
if page_in_range(page, entry.base, entry.size) {
- return Some(entry.interface.clone());
+ return Some(&entry);
}
}
@@ -31,11 +32,134 @@ impl MemConfig {
pub fn read_dword(&self, page: PageNum, offset: u16) -> Result<DWord, MemAccessFault> {
if page_in_range(page, self.ram_start, self.ram.pages) {
- self.ram.read_dword(page, offset)
+ self.ram.read_dword(page - self.ram_start, offset)
} else {
- self.find_device_by_page(page)
- .ok_or(MemAccessFault)?
- .read_dword(page, offset)
+ let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
+
+ entry.interface.read_dword(page - entry.base, offset)
+ }
+ }
+ pub fn read_word(&self, page: PageNum, offset: u16) -> Result<Word, MemAccessFault> {
+ if page_in_range(page, self.ram_start, self.ram.pages) {
+ self.ram.read_word(page - self.ram_start, offset)
+ } else {
+ let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
+
+ entry.interface.read_word(page - entry.base, offset)
+ }
+ }
+ pub fn read_hword(&self, page: PageNum, offset: u16) -> Result<HWord, MemAccessFault> {
+ if page_in_range(page, self.ram_start, self.ram.pages) {
+ self.ram.read_hword(page - self.ram_start, offset)
+ } else {
+ let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
+
+ entry.interface.read_hword(page - entry.base, offset)
+ }
+ }
+ pub fn read_byte(&self, page: PageNum, offset: u16) -> Result<Byte, MemAccessFault> {
+ if page_in_range(page, self.ram_start, self.ram.pages) {
+ self.ram.read_byte(page - self.ram_start, offset)
+ } else {
+ let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
+
+ entry.interface.read_byte(page - entry.base, offset)
+ }
+ }
+
+ pub fn write_dword(
+ &self,
+ page: PageNum,
+ offset: u16,
+ value: DWord,
+ ) -> Result<(), MemAccessFault> {
+ if page_in_range(page, self.ram_start, self.ram.pages) {
+ self.ram.write_dword(page - self.ram_start, offset, value)
+ } else {
+ let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
+ entry
+ .interface
+ .write_dword(page - entry.base, offset, value)
+ }
+ }
+ pub fn write_word(
+ &self,
+ page: PageNum,
+ offset: u16,
+ value: Word,
+ ) -> Result<(), MemAccessFault> {
+ if page_in_range(page, self.ram_start, self.ram.pages) {
+ self.ram.write_word(page - self.ram_start, offset, value)
+ } else {
+ let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
+ entry.interface.write_word(page - entry.base, offset, value)
+ }
+ }
+ pub fn write_hword(
+ &self,
+ page: PageNum,
+ offset: u16,
+ value: HWord,
+ ) -> Result<(), MemAccessFault> {
+ if page_in_range(page, self.ram_start, self.ram.pages) {
+ self.ram.write_hword(page - self.ram_start, offset, value)
+ } else {
+ let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
+ entry
+ .interface
+ .write_hword(page - entry.base, offset, value)
+ }
+ }
+ pub fn write_byte(
+ &self,
+ page: PageNum,
+ offset: u16,
+ value: Byte,
+ ) -> Result<(), MemAccessFault> {
+ if page_in_range(page, self.ram_start, self.ram.pages) {
+ self.ram.write_byte(page - self.ram_start, offset, value)
+ } else {
+ let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
+ entry.interface.write_byte(page - entry.base, offset, value)
+ }
+ }
+
+ pub fn get_atomic_dword(
+ &self,
+ page: PageNum,
+ offset: u16,
+ ) -> Result<&AtomicU64, MemAccessFault> {
+ if page_in_range(page, self.ram_start, self.ram.pages) {
+ debug_assert!(((offset * 8) as usize) < PAGE_SIZE);
+ let index = page * (PAGE_SIZE / 8) + (offset as usize);
+ unsafe {
+ self.ram
+ .buf_transmuted::<AtomicU64>()
+ .get(index)
+ .ok_or(MemAccessFault)
+ }
+ } else {
+ let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
+ entry.interface.get_atomic_dword(page - entry.base, offset)
+ }
+ }
+ pub fn get_atomic_word(
+ &self,
+ page: PageNum,
+ offset: u16,
+ ) -> Result<&AtomicU32, MemAccessFault> {
+ if page_in_range(page, self.ram_start, self.ram.pages) {
+ debug_assert!(((offset * 4) as usize) < PAGE_SIZE);
+ let index = page * (PAGE_SIZE / 4) + (offset as usize);
+ unsafe {
+ self.ram
+ .buf_transmuted::<AtomicU32>()
+ .get(index)
+ .ok_or(MemAccessFault)
+ }
+ } else {
+ let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
+ entry.interface.get_atomic_word(page - entry.base, offset)
}
}
}