From 6858c9e7c97f772eb357e3eee0c1fcfb8adcb699 Mon Sep 17 00:00:00 2001 From: Nathan Lee Date: Fri, 25 Sep 2026 22:39:01 -0500 Subject: scaffold emulator from wrv32em --- website-emu/src/mem.rs | 105 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 website-emu/src/mem.rs (limited to 'website-emu/src/mem.rs') diff --git a/website-emu/src/mem.rs b/website-emu/src/mem.rs new file mode 100644 index 0000000..c5f1b5c --- /dev/null +++ b/website-emu/src/mem.rs @@ -0,0 +1,105 @@ +use std::ops::Range; + +pub trait MemoryDevice { + fn read(&self, address: u32) -> Result; + fn write(&mut self, address: u32, value: u8) -> Result<(), ()>; +} + +pub struct CpuMemory { + pub devices: Vec<(Range, Box)>, +} + +impl CpuMemory { + fn get_device(&self, address: u32) -> Option<&Box> { + self.devices + .iter() + .find(|(range, _)| range.contains(&address)) + .map(|(_, device)| device) + } + fn get_device_mut(&mut self, address: u32) -> Option<&mut Box> { + self.devices + .iter_mut() + .find(|(range, _)| range.contains(&address)) + .map(|(_, device)| device) + } + + pub fn register_device(&mut self, range: Range, device: Box) { + self.devices.push((range, device)); + } + + pub fn read(&self, address: u32) -> Result { + if let Some(device) = self.get_device(address) { + device.read(address) + } else { + Err(()) + } + } + + pub fn write(&mut self, address: u32, value: u8) -> Result<(), ()> { + if let Some(device) = self.get_device_mut(address) { + device.write(address, value) + } else { + Err(()) + } + } + + pub fn read_halfword(&self, address: u32) -> Result { + let low = self.read(address)?; + let high = self.read(address + 1)?; + Ok((high as u16) << 8 | low as u16) + } + + pub fn write_halfword(&mut self, address: u32, value: u16) -> Result<(), ()> { + self.write(address + 1, (value >> 8) as u8)?; + self.write(address, (value & 0xFF) as u8)?; + Ok(()) + } + + pub fn read_word(&self, address: u32) -> Result { + let low = self.read_halfword(address)?; + let high = self.read_halfword(address + 2)?; + Ok((high as u32) << 16 | low as u32) + } + + pub fn write_word(&mut self, address: u32, value: u32) -> Result<(), ()> { + self.write_halfword(address + 2, (value >> 16) as u16)?; + self.write_halfword(address, (value & 0xFFFF) as u16) + } + + pub fn read_instruction(&self, address: u32) -> Result { + if let Some(device) = self.get_device(address) { + Ok(u32::from_le_bytes([ + device.read(address)?, + device.read(address + 1)?, + device.read(address + 2)?, + device.read(address + 3)?, + ])) + } else { + Err(()) + } + } +} + +pub struct LogicalMemory { + pub base: u32, + pub size: u32, + pub dram: Box<[u8]>, +} + +impl MemoryDevice for LogicalMemory { + fn read(&self, address: u32) -> Result { + if address - self.base > self.size { + Err(()) + } else { + Ok(self.dram[(address - self.base) as usize]) + } + } + fn write(&mut self, address: u32, value: u8) -> Result<(), ()> { + if address - self.base > self.size { + Err(()) + } else { + self.dram[(address - self.base) as usize] = value; + Ok(()) + } + } +} -- cgit v1.2.3