diff options
| author | Nathan Lee <me@nwlee.tech> | 2026-06-10 22:10:59 -0500 |
|---|---|---|
| committer | Nathan Lee <me@nwlee.tech> | 2026-06-10 22:10:59 -0500 |
| commit | a37a07533fa9b8bd8962ca3c1aea082ae2548651 (patch) | |
| tree | c2ee061f6047eeda966ef9a4f3a7c26cf7da2061 /src/mem.rs | |
| parent | 615e98a616c851fb6230184029aa4297417cdf6e (diff) | |
move memory and cpu state into its own files
Diffstat (limited to 'src/mem.rs')
| -rw-r--r-- | src/mem.rs | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/mem.rs b/src/mem.rs new file mode 100644 index 0000000..297c54c --- /dev/null +++ b/src/mem.rs @@ -0,0 +1,105 @@ +const PAGE_SIZE: usize = 4 * 1024; +const PAGE_MASK: usize = !(PAGE_SIZE - 1); + +struct Page { + virtual_addr: usize, + real_addr: usize, + permission: usize, + allocated: usize, +} +pub struct Memory { + memory: Box<[u8]>, + pages: Vec<Page>, +} +impl Memory { + pub fn new(size: usize) -> Memory { + let mut pages: Vec<Page> = Vec::with_capacity(size / PAGE_SIZE); + for i in 0..size / PAGE_SIZE { + pages[i] = Page { + virtual_addr: usize::MAX, + real_addr: i * PAGE_SIZE, + permission: 0, + allocated: 0 + } + } + Memory { + memory: vec![0u8; size].into_boxed_slice(), + pages, + } + } + + pub fn create_page(&mut self, virtual_addr: usize, permission: usize) -> Option<usize> { + // Find first page that isn't allocated and set it to allocated + for (i, page) in self.pages.iter_mut().enumerate() { + if page.allocated == 0 { + page.virtual_addr = virtual_addr; + page.permission = permission; + page.allocated = 1; + return Some(i); + } + } + None + } + + pub fn lookup_page(&mut self, virtual_addr: usize, permission: usize) -> Option<usize> { + for (i, page) in self.pages.iter().enumerate() { + if page.virtual_addr == virtual_addr && permission >= page.permission && page.allocated == 1 { + return Some(i); + } + } + return self.create_page(virtual_addr, permission); + } + + pub fn ro_lookup(&self, virtual_addr: usize, permission: usize) -> Option<usize> { + for (i, page) in self.pages.iter().enumerate() { + if page.virtual_addr == virtual_addr && page.permission == permission && page.allocated == 1 { + return Some(i); + } + } + None + } + + pub fn write(&mut self, address: usize, permission: usize, value: u8) -> Result<(), ()> { + let page = address & PAGE_MASK; + let offset = address - page; + + if let Some(page) = self.lookup_page(address, permission) { + self.memory[self.pages[page].real_addr + offset] = value; + Ok(()) + } else { + Err(()) + } + } + + pub fn read(&self, address: usize, permission: usize) -> Result<u8, ()> { + let page = address & PAGE_MASK; + let offset = address - page; + + if let Some(page) = self.ro_lookup(address, permission) { + Ok(self.memory[self.pages[page].real_addr + offset]) + } else { + Err(()) + } + } + + pub fn read_multiple_bytes(&self, address: usize, size: usize, permission: usize) -> Result<Box<[u8]>, ()> { + let mut ret = []; + for addr in address..address+size { + if let Ok(byte) = self.read(addr, permission) { + ret[addr - address] = byte; + } else { + return Err(()); + } + } + Ok(Box::new(ret)) + } + + pub fn write_multiple_bytes(&mut self, address: usize, bytes: &[u8], permission: usize) -> Result<(), ()> { + for addr in address..address + bytes.len() { + if let Err(_) = self.write(addr, permission, bytes[addr - address]) { + return Err(()); + } + } + Ok(()) + } +}
\ No newline at end of file |
