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> { + #[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 { 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 { + 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 { + 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 { + 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::() + .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::() + .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) } } }