diff --git a/src/main.rs b/src/main.rs index d970561..eb3b8d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -108,8 +108,7 @@ impl MachineState { return Self::new_with_state(memory, pages); } - fn get_page_table_entry(&mut self, address: usize) -> PageTableEntry { - let page = address >> PAGE_BITS; + fn get_page_table_entry(&self, page: usize) -> PageTableEntry { if page < self.pages.len() { return self.pages[page]; } else { @@ -117,38 +116,37 @@ impl MachineState { } } - fn set_page_table_entry(&mut self, address: usize, entry: PageTableEntry) { - let page = address >> PAGE_BITS; + fn set_page_table_entry(&mut self, page: usize, entry: PageTableEntry) { if page < self.pages.len() { - self.pages[address >> 12] = entry; + self.pages[page] = entry; } else { panic!("@fixme: handle attempts to expand address space"); } } - fn lb_physical(&mut self, address: usize) -> i64 { + fn lb_physical(&self, address: usize) -> i64 { return self.memory[address] as i8 as i64; } - fn lbu_physical(&mut self, address: usize) -> i64 { + fn lbu_physical(&self, address: usize) -> i64 { return self.memory[address] as u8 as i64; } - fn lh_physical(&mut self, address: usize) -> i64 { + fn lh_physical(&self, address: usize) -> i64 { return ( (self.memory[address ] as u16) | ((self.memory[address + 1] as u16) << 8) ) as i16 as i64; } - fn lhu_physical(&mut self, address: usize) -> i64 { + fn lhu_physical(&self, address: usize) -> i64 { return ( (self.memory[address ] as u16) | ((self.memory[address + 1] as u16) << 8) ) as i64; } - fn lw_physical(&mut self, address: usize) -> i64 { + fn lw_physical(&self, address: usize) -> i64 { return ( (self.memory[address ] as u32) | ((self.memory[address + 1] as u32) << 8) | @@ -157,7 +155,7 @@ impl MachineState { ) as i32 as i64; } - fn lwu_physical(&mut self, address: usize) -> i64 { + fn lwu_physical(&self, address: usize) -> i64 { return ( (self.memory[address ] as u32) | ((self.memory[address + 1] as u32) << 8) | @@ -166,7 +164,7 @@ impl MachineState { ) as u32 as i64; } - fn ld_physical(&mut self, address: usize) -> i64 { + fn ld_physical(&self, address: usize) -> i64 { return ( (self.memory[address ] as u64) | ((self.memory[address + 1] as u64) << 8) | @@ -270,6 +268,122 @@ impl CoreState { dirty: vec![0u8; machine.memory.len()] } } + + fn lb(&self, machine: &MachineState, address: i64) -> i64 { + let raw_page = (address as u64) >> PAGE_BITS; + if raw_page < machine.pages.len() as u64 { + let addr = address as usize; + let page = raw_page as usize; + let entry = machine.get_page_table_entry(page); + if entry.is_readable() { + return machine.lb_physical(address as usize); + } + } + panic!("@fixme: trap on read failure on page"); + } + + fn lbu(&self, machine: &MachineState, address: i64) -> i64 { + let raw_page = (address as u64) >> PAGE_BITS; + if raw_page < machine.pages.len() as u64 { + let addr = address as usize; + let page = raw_page as usize; + let entry = machine.get_page_table_entry(page); + if entry.is_readable() { + return machine.lbu_physical(addr); + } + } + panic!("@fixme: trap on read failure on page"); + } + + fn lh(&self, machine: &MachineState, address: i64) -> i64 { + let raw_page = (address as u64) >> PAGE_BITS; + if raw_page < machine.pages.len() as u64 { + let addr = address as usize; + let page = raw_page as usize; + let entry = machine.get_page_table_entry(page); + if entry.is_readable() { + let offset = addr & (PAGE_SIZE - 1); + if offset < (PAGE_SIZE - 2) || machine.get_page_table_entry(page + 1).is_readable() { + return machine.lh_physical(addr); + } else { + panic!("@fixme: trap on read failure on page + 1"); + } + } + } + panic!("@fixme: trap on read failure on page"); + } + + fn lhu(&self, machine: &MachineState, address: i64) -> i64 { + let raw_page = (address as u64) >> PAGE_BITS; + if raw_page < machine.pages.len() as u64 { + let addr = address as usize; + let page = raw_page as usize; + let entry = machine.get_page_table_entry(page); + if entry.is_readable() { + let offset = addr & (PAGE_SIZE - 1); + if offset < (PAGE_SIZE - 2) || machine.get_page_table_entry(page + 1).is_readable() { + return machine.lhu_physical(addr); + } else { + panic!("@fixme: trap on read failure on page + 1"); + } + } + } + panic!("@fixme: trap on read failure on page"); + } + + fn lw(&self, machine: &MachineState, address: i64) -> i64 { + let raw_page = (address as u64) >> PAGE_BITS; + if raw_page < machine.pages.len() as u64 { + let addr = address as usize; + let page = raw_page as usize; + let entry = machine.get_page_table_entry(page); + if entry.is_readable() { + let offset = addr & (PAGE_SIZE - 1); + if offset < (PAGE_SIZE - 4) || machine.get_page_table_entry(page + 1).is_readable() { + return machine.lw_physical(addr); + } else { + panic!("@fixme: trap on read failure on page + 1"); + } + } + } + panic!("@fixme: trap on read failure on page"); + } + + fn lwu(&self, machine: &MachineState, address: i64) -> i64 { + let raw_page = (address as u64) >> PAGE_BITS; + if raw_page < machine.pages.len() as u64 { + let addr = address as usize; + let page = raw_page as usize; + let entry = machine.get_page_table_entry(page); + if entry.is_readable() { + let offset = addr & (PAGE_SIZE - 1); + if offset < (PAGE_SIZE - 4) || machine.get_page_table_entry(page + 1).is_readable() { + return machine.lwu_physical(addr); + } else { + panic!("@fixme: trap on read failure on page + 1"); + } + } + } + panic!("@fixme: trap on read failure on page"); + } + + fn ld(&self, machine: &MachineState, address: i64) -> i64 { + let raw_page = (address as u64) >> PAGE_BITS; + if raw_page < machine.pages.len() as u64 { + let addr = address as usize; + let page = raw_page as usize; + let entry = machine.get_page_table_entry(page); + if entry.is_readable() { + let offset = addr & (PAGE_SIZE - 1); + if offset < (PAGE_SIZE - 8) || machine.get_page_table_entry(page + 1).is_readable() { + return machine.ld_physical(addr); + } else { + panic!("@fixme: trap on read failure on page + 1"); + } + } + } + panic!("@fixme: trap on read failure on page"); + } }