From 528b519ce98c21049705526442cbde1672495b49 Mon Sep 17 00:00:00 2001 From: taitep Date: Fri, 26 Dec 2025 14:20:27 +0100 Subject: (BIG CHANGE) memory handling has changed, MMIO is now a 2 level page table, misaligned access supported, addresses not internally split to page and offset immediately, all load/store instructions implemented. Might still have bugs --- src/instructions/rvi/mem.rs | 127 +++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 71 deletions(-) (limited to 'src/instructions/rvi') diff --git a/src/instructions/rvi/mem.rs b/src/instructions/rvi/mem.rs index ad938cb..bc02b7f 100644 --- a/src/instructions/rvi/mem.rs +++ b/src/instructions/rvi/mem.rs @@ -5,75 +5,63 @@ // See LICENSE file in the project root for full license text. use crate::{ - consts::{Addr, Byte, DWord, HWord, Word}, + consts::{Byte, DWord, HWord, Word}, core::Core, exceptions::ExceptionType, instructions::Instruction, - mem::PageNum, }; -// TODO: Support misaligned memory access pub fn sd(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s()); - - if !addr.is_multiple_of(std::mem::size_of::() as Addr) { - return Err(ExceptionType::StoreAmoAddressMisaligned); - } - - let page = (addr / 4096) as PageNum; - let offset = (addr / 8 & ((4096 / 8 as Addr) - 1)) as u16; let value = core.reg_read(instr.rs2()); - - core.mem.write_dword(page, offset, value)?; + core.mem + .write_dword(addr, value) + .map_err(|e| e.to_exception_store())?; core.advance_pc(); - Ok(()) } pub fn ld(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); - - if !addr.is_multiple_of(std::mem::size_of::() as Addr) { - return Err(ExceptionType::LoadAddressMisaligned); - } - - let page = (addr / 4096) as PageNum; - let offset = (addr / 8 & ((4096 / 8 as Addr) - 1)) as u16; - - core.reg_write(instr.rd(), core.mem.read_dword(page, offset)?); + core.reg_write( + instr.rd(), + core.mem + .read_dword(addr) + .map_err(|e| e.to_exception_load())?, + ); core.advance_pc(); Ok(()) } pub fn sw(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s()); - - if !addr.is_multiple_of(std::mem::size_of::() as Addr) { - return Err(ExceptionType::StoreAmoAddressMisaligned); - } - - let page = (addr / 4096) as PageNum; - let offset = (addr / 4 & ((4096 / 4 as Addr) - 1)) as u16; let value = core.reg_read(instr.rs2()) as Word; - - core.mem.write_word(page, offset, value)?; + core.mem + .write_word(addr, value) + .map_err(|e| e.to_exception_store())?; core.advance_pc(); Ok(()) } pub fn lw(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); + core.reg_write( + instr.rd(), + core.mem + .read_word(addr) + .map_err(|e| e.to_exception_load())? as i32 as i64 as DWord, + ); + core.advance_pc(); + Ok(()) +} - if !addr.is_multiple_of(std::mem::size_of::() as Addr) { - return Err(ExceptionType::LoadAddressMisaligned); - } - - let page = (addr / 4096) as PageNum; - let offset = (addr / 4 & ((4096 / 4 as Addr) - 1)) as u16; - +pub fn lwu(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { + let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); core.reg_write( instr.rd(), - core.mem.read_word(page, offset)? as i32 as i64 as DWord, + core.mem + .read_word(addr) + .map_err(|e| e.to_exception_load())? as DWord, ); core.advance_pc(); Ok(()) @@ -81,33 +69,33 @@ pub fn lw(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { pub fn sh(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s()); - - if !addr.is_multiple_of(std::mem::size_of::() as Addr) { - return Err(ExceptionType::StoreAmoAddressMisaligned); - } - - let page = (addr / 4096) as PageNum; - let offset = (addr / 2 & ((4096 / 2 as Addr) - 1)) as u16; let value = core.reg_read(instr.rs2()) as HWord; - - core.mem.write_hword(page, offset, value)?; + core.mem + .write_hword(addr, value) + .map_err(|e| e.to_exception_store())?; core.advance_pc(); Ok(()) } pub fn lh(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); + core.reg_write( + instr.rd(), + core.mem + .read_hword(addr) + .map_err(|e| e.to_exception_load())? as i16 as i64 as DWord, + ); + core.advance_pc(); + Ok(()) +} - if !addr.is_multiple_of(std::mem::size_of::() as Addr) { - return Err(ExceptionType::LoadAddressMisaligned); - } - - let page = (addr / 4096) as PageNum; - let offset = (addr / 2 & ((4096 / 2 as Addr) - 1)) as u16; - +pub fn lhu(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { + let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); core.reg_write( instr.rd(), - core.mem.read_hword(page, offset)? as i16 as i64 as DWord, + core.mem + .read_hword(addr) + .map_err(|e| e.to_exception_load())? as DWord, ); core.advance_pc(); Ok(()) @@ -115,25 +103,21 @@ pub fn lh(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { pub fn sb(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s()); - - let page = (addr / 4096) as PageNum; - let offset = (addr & (4096 as Addr - 1)) as u16; let value = core.reg_read(instr.rs2()) as Byte; - - core.mem.write_byte(page, offset, value)?; + core.mem + .write_byte(addr, value) + .map_err(|e| e.to_exception_store())?; core.advance_pc(); Ok(()) } pub fn lb(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); - - let page = (addr / 4096) as PageNum; - let offset = (addr & (4096 as Addr - 1)) as u16; - core.reg_write( instr.rd(), - core.mem.read_byte(page, offset)? as i8 as i64 as DWord, + core.mem + .read_byte(addr) + .map_err(|e| e.to_exception_load())? as i8 as i64 as DWord, ); core.advance_pc(); Ok(()) @@ -141,11 +125,12 @@ pub fn lb(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { pub fn lbu(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); - - let page = (addr / 4096) as PageNum; - let offset = (addr & (4096 as Addr - 1)) as u16; - - core.reg_write(instr.rd(), core.mem.read_byte(page, offset)? as DWord); + core.reg_write( + instr.rd(), + core.mem + .read_byte(addr) + .map_err(|e| e.to_exception_load())? as DWord, + ); core.advance_pc(); Ok(()) } -- cgit v1.2.3