This commit is contained in:
Brooke Vibber 2025-12-29 15:33:58 -08:00
commit 339dbf0c23

View file

@ -108,8 +108,7 @@ impl MachineState {
return Self::new_with_state(memory, pages); return Self::new_with_state(memory, pages);
} }
fn get_page_table_entry(&mut self, address: usize) -> PageTableEntry { fn get_page_table_entry(&self, page: usize) -> PageTableEntry {
let page = address >> PAGE_BITS;
if page < self.pages.len() { if page < self.pages.len() {
return self.pages[page]; return self.pages[page];
} else { } else {
@ -117,38 +116,37 @@ impl MachineState {
} }
} }
fn set_page_table_entry(&mut self, address: usize, entry: PageTableEntry) { fn set_page_table_entry(&mut self, page: usize, entry: PageTableEntry) {
let page = address >> PAGE_BITS;
if page < self.pages.len() { if page < self.pages.len() {
self.pages[address >> 12] = entry; self.pages[page] = entry;
} else { } else {
panic!("@fixme: handle attempts to expand address space"); 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; 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; return self.memory[address] as u8 as i64;
} }
fn lh_physical(&mut self, address: usize) -> i64 { fn lh_physical(&self, address: usize) -> i64 {
return ( return (
(self.memory[address ] as u16) | (self.memory[address ] as u16) |
((self.memory[address + 1] as u16) << 8) ((self.memory[address + 1] as u16) << 8)
) as i16 as i64; ) as i16 as i64;
} }
fn lhu_physical(&mut self, address: usize) -> i64 { fn lhu_physical(&self, address: usize) -> i64 {
return ( return (
(self.memory[address ] as u16) | (self.memory[address ] as u16) |
((self.memory[address + 1] as u16) << 8) ((self.memory[address + 1] as u16) << 8)
) as i64; ) as i64;
} }
fn lw_physical(&mut self, address: usize) -> i64 { fn lw_physical(&self, address: usize) -> i64 {
return ( return (
(self.memory[address ] as u32) | (self.memory[address ] as u32) |
((self.memory[address + 1] as u32) << 8) | ((self.memory[address + 1] as u32) << 8) |
@ -157,7 +155,7 @@ impl MachineState {
) as i32 as i64; ) as i32 as i64;
} }
fn lwu_physical(&mut self, address: usize) -> i64 { fn lwu_physical(&self, address: usize) -> i64 {
return ( return (
(self.memory[address ] as u32) | (self.memory[address ] as u32) |
((self.memory[address + 1] as u32) << 8) | ((self.memory[address + 1] as u32) << 8) |
@ -166,7 +164,7 @@ impl MachineState {
) as u32 as i64; ) as u32 as i64;
} }
fn ld_physical(&mut self, address: usize) -> i64 { fn ld_physical(&self, address: usize) -> i64 {
return ( return (
(self.memory[address ] as u64) | (self.memory[address ] as u64) |
((self.memory[address + 1] as u64) << 8) | ((self.memory[address + 1] as u64) << 8) |
@ -270,6 +268,122 @@ impl CoreState {
dirty: vec![0u8; machine.memory.len()] 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");
}
} }