diff --git a/src/basic_uart.rs b/src/basic_uart.rs index d7a11be..e5b91f3 100644 --- a/src/basic_uart.rs +++ b/src/basic_uart.rs @@ -14,7 +14,7 @@ use std::time::Duration; use nix::fcntl::fcntl; use nix::fcntl::{FcntlArg, OFlag}; use trve::consts::{Addr, Byte}; -use trve::exceptions::MemoryExceptionType; +use trve::exceptions::{MemoryException, MemoryExceptionType}; use trve::mem::MemDeviceInterface; /// byte 0: rx/tx @@ -78,20 +78,26 @@ impl BasicUart { } impl MemDeviceInterface for BasicUart { - fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryExceptionType> { + fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryException> { match addr { 0 => { self.write(value); Ok(()) } - _ => Err(MemoryExceptionType::AccessFault), + _ => Err(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }), } } - fn read_byte(&self, addr: Addr) -> Result { + fn read_byte(&self, addr: Addr) -> Result { match addr { 0 => Ok(self.read()), 1 => Ok(1 | (self.can_read() as u8) << 1), - _ => Err(MemoryExceptionType::AccessFault), + _ => Err(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }), } } } diff --git a/src/core.rs b/src/core.rs index 8d51947..eb0549f 100644 --- a/src/core.rs +++ b/src/core.rs @@ -10,7 +10,7 @@ use crate::{ consts::{Addr, RegId, RegValue}, core::commands::CoreCmd, decode::Instruction, - exceptions::ExceptionType, + exceptions::{Exception, ExceptionType, MemoryException}, gdb::{self, DebugCommand, DebugStream, StopReason}, instructions::find_and_exec, mem::MemConfig, @@ -86,7 +86,8 @@ impl Core { } => { let data = (0..len) .map(|offset| self.mem.read_byte(addr + offset)) - .collect(); + .collect::>() + .map_err(Into::into); responder.send(data)?; } @@ -101,7 +102,7 @@ impl Core { Ok(_) => gdb::StopReason::Step, Err(e) => { self.throw_exception(e); - gdb::StopReason::Exception(e) + gdb::StopReason::Exception(e.into()) } })?; } @@ -132,14 +133,17 @@ impl Core { if let Err(e) = self.step() { self.throw_exception(e); - return StopReason::Exception(e); + return StopReason::Exception(e.into()); } } } - pub(crate) fn step(&mut self) -> Result<(), ExceptionType> { + pub(crate) fn step(&mut self) -> Result<(), Exception> { if !self.pc.is_multiple_of(4) { - self.throw_exception(ExceptionType::InstructionAddressMisaligned); + self.throw_exception(Exception { + type_: ExceptionType::InstructionAddressMisaligned, + value: self.pc, + }); } let instr = match self.mem.read_word(self.pc) { @@ -149,13 +153,13 @@ impl Core { } }; - if instr == 0 { - return Err(ExceptionType::IllegalInstruction); - } - if instr & 3 != 3 { // Compressed instruction - (currently) unsupported - return Err(ExceptionType::IllegalInstruction); + // Could also be zero instruction, that also matches this + return Err(Exception { + type_: ExceptionType::IllegalInstruction, + value: instr as u64, + }); } let instr = Instruction(instr); @@ -168,8 +172,8 @@ impl Core { Ok(()) } - fn throw_exception(&mut self, exception_type: ExceptionType) { - eprintln!("Exception: {exception_type:?}"); + fn throw_exception(&mut self, exception: Exception) { + eprintln!("Exception: {exception:?}"); dbg!(self.pc, self.x_regs); } diff --git a/src/exceptions.rs b/src/exceptions.rs index 9a84edc..5e3f02f 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -6,6 +6,8 @@ use int_enum::IntEnum; +use crate::consts::{Addr, DWord}; + #[repr(u8)] #[allow(dead_code)] #[derive(Debug, Clone, Copy, PartialEq, Eq, IntEnum)] @@ -29,6 +31,12 @@ pub enum ExceptionType { HardwareError = 19, } +#[derive(Debug, Clone, Copy)] +pub struct Exception { + pub type_: ExceptionType, + pub value: DWord, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MemoryExceptionType { AddressMisaligned, @@ -36,28 +44,55 @@ pub enum MemoryExceptionType { PageFault, } -impl MemoryExceptionType { - pub(crate) fn to_exception_store(&self) -> ExceptionType { - match self { - Self::AddressMisaligned => ExceptionType::StoreAmoAddressMisaligned, - Self::AccessFault => ExceptionType::StoreAmoAccessFault, - Self::PageFault => ExceptionType::StoreAmoPageFault, +#[derive(Debug, Clone, Copy)] +pub struct MemoryException { + pub type_: MemoryExceptionType, + pub addr: Addr, +} + +impl MemoryException { + pub(crate) fn to_exception_store(&self) -> Exception { + Exception { + type_: match self.type_ { + MemoryExceptionType::AddressMisaligned => ExceptionType::StoreAmoAddressMisaligned, + MemoryExceptionType::AccessFault => ExceptionType::StoreAmoAccessFault, + MemoryExceptionType::PageFault => ExceptionType::StoreAmoPageFault, + }, + value: self.addr, } } - pub(crate) fn to_exception_instr(&self) -> ExceptionType { - match self { - Self::AddressMisaligned => ExceptionType::InstructionAddressMisaligned, - Self::AccessFault => ExceptionType::InstructionAccessFault, - Self::PageFault => ExceptionType::InstructionPageFault, + pub(crate) fn to_exception_instr(&self) -> Exception { + Exception { + type_: match self.type_ { + MemoryExceptionType::AddressMisaligned => ExceptionType::InstructionAccessFault, + MemoryExceptionType::AccessFault => ExceptionType::InstructionAccessFault, + MemoryExceptionType::PageFault => ExceptionType::InstructionPageFault, + }, + value: self.addr, } } - pub(crate) fn to_exception_load(&self) -> ExceptionType { - match self { - Self::AddressMisaligned => ExceptionType::LoadAddressMisaligned, - Self::AccessFault => ExceptionType::LoadAccessFault, - Self::PageFault => ExceptionType::LoadPageFault, + pub(crate) fn to_exception_load(&self) -> Exception { + Exception { + type_: match self.type_ { + MemoryExceptionType::AddressMisaligned => ExceptionType::LoadAddressMisaligned, + MemoryExceptionType::AccessFault => ExceptionType::LoadAccessFault, + MemoryExceptionType::PageFault => ExceptionType::LoadPageFault, + }, + value: self.addr, } } } + +impl Into for MemoryException { + fn into(self) -> MemoryExceptionType { + self.type_ + } +} + +impl Into for Exception { + fn into(self) -> ExceptionType { + self.type_ + } +} diff --git a/src/instructions.rs b/src/instructions.rs index e7b95f1..fe79684 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -10,12 +10,20 @@ mod macros; mod rvi; use crate::{ + consts::DWord, core::Core, decode::Instruction, - exceptions::ExceptionType::{self, IllegalInstruction}, + exceptions::{Exception, ExceptionType::IllegalInstruction}, }; -pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), ExceptionType> { +fn illegal(instr: Instruction) -> Result<(), Exception> { + Err(Exception { + type_: IllegalInstruction, + value: instr.0 as DWord, + }) +} + +pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), Exception> { match instr.opcode_noncompressed() { 0b01100 => match (instr.funct3(), instr.funct7()) { // OP @@ -29,7 +37,7 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E (0b111, 0b0000000) => rvi::and(core, instr), (0b100, 0b0000000) => rvi::xor(core, instr), (0b110, 0b0000000) => rvi::or(core, instr), - _ => Err(IllegalInstruction), + _ => illegal(instr), }, 0b01110 => match (instr.funct3(), instr.funct7()) { // OP_32 @@ -38,7 +46,7 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E (0b001, 0b0000000) => rvi::sllw(core, instr), (0b101, 0b0000000) => rvi::srlw(core, instr), (0b101, 0b0100000) => rvi::sraw(core, instr), - _ => Err(IllegalInstruction), + _ => illegal(instr), }, 0b00100 => match instr.funct3() { // OP_IMM @@ -47,31 +55,31 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E 0b011 => rvi::sltiu(core, instr), 0b001 => match instr.funct6() { 0 => rvi::slli(core, instr), - _ => Err(IllegalInstruction), + _ => illegal(instr), }, 0b101 => match instr.funct6() { 0b000000 => rvi::srli(core, instr), 0b010000 => rvi::srai(core, instr), - _ => Err(IllegalInstruction), + _ => illegal(instr), }, 0b100 => rvi::xori(core, instr), 0b110 => rvi::ori(core, instr), 0b111 => rvi::andi(core, instr), - _ => Err(IllegalInstruction), + _ => illegal(instr), }, 0b00110 => match instr.funct3() { // OP_IMM_32 0b000 => rvi::addiw(core, instr), 0b001 => match instr.funct7() { 0 => rvi::slliw(core, instr), - _ => Err(IllegalInstruction), + _ => illegal(instr), }, 0b101 => match instr.funct7() { 0b0000000 => rvi::srliw(core, instr), 0b0100000 => rvi::sraiw(core, instr), - _ => Err(IllegalInstruction), + _ => illegal(instr), }, - _ => Err(IllegalInstruction), + _ => illegal(instr), }, 0b01000 => match instr.funct3() { // STORE @@ -79,7 +87,7 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E 0b001 => rvi::sh(core, instr), 0b010 => rvi::sw(core, instr), 0b011 => rvi::sd(core, instr), - _ => Err(IllegalInstruction), + _ => illegal(instr), }, 0b00000 => match instr.funct3() { // LOAD @@ -90,7 +98,7 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E 0b010 => rvi::lw(core, instr), 0b110 => rvi::lwu(core, instr), 0b011 => rvi::ld(core, instr), - _ => Err(IllegalInstruction), + _ => illegal(instr), }, 0b11000 => match instr.funct3() { // BRANCH @@ -100,7 +108,7 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E 0b101 => rvi::bge(core, instr), 0b110 => rvi::bltu(core, instr), 0b111 => rvi::bgeu(core, instr), - _ => Err(IllegalInstruction), + _ => illegal(instr), }, 0b01101 => rvi::lui(core, instr), 0b00101 => rvi::auipc(core, instr), @@ -109,7 +117,7 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E if instr.funct3() == 0 { rvi::jalr(core, instr) } else { - Err(IllegalInstruction) + illegal(instr) } } 0b00011 => match instr.funct3() { @@ -120,8 +128,8 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E std::sync::atomic::fence(std::sync::atomic::Ordering::SeqCst); Ok(()) } - _ => Err(IllegalInstruction), + _ => illegal(instr), }, - _ => Err(IllegalInstruction), + _ => illegal(instr), } } diff --git a/src/instructions/macros.rs b/src/instructions/macros.rs index 98cf63d..c8fa8f1 100644 --- a/src/instructions/macros.rs +++ b/src/instructions/macros.rs @@ -7,7 +7,7 @@ #[macro_export] macro_rules! instr_branch { ($name:ident, $cond:expr) => { - pub fn $name(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { + pub fn $name(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let a = core.reg_read(instr.rs1()); let b = core.reg_read(instr.rs2()); if $cond(a, b) { @@ -30,7 +30,7 @@ macro_rules! instr_branch_signed { #[macro_export] macro_rules! instr_op_r { ($name:ident, $op:expr) => { - pub fn $name(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { + pub fn $name(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let a = core.reg_read(instr.rs1()); let b = core.reg_read(instr.rs2()); let res = $op(a, b); @@ -44,7 +44,7 @@ macro_rules! instr_op_r { #[macro_export] macro_rules! instr_op_i { ($name:ident, $op:expr) => { - pub fn $name(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { + pub fn $name(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let a = core.reg_read(instr.rs1()); let b = instr.imm_i(); let res = $op(a, b); diff --git a/src/instructions/rvi.rs b/src/instructions/rvi.rs index 5e2faa4..9f34fb1 100644 --- a/src/instructions/rvi.rs +++ b/src/instructions/rvi.rs @@ -4,7 +4,7 @@ // This file is part of TRVE (https://gitea.taitep.se/taitep/trve) // See LICENSE file in the project root for full license text. -use crate::{consts::RegValue, core::Core, decode::Instruction, exceptions::ExceptionType}; +use crate::{consts::RegValue, core::Core, decode::Instruction, exceptions::Exception}; use std::ops::{BitAnd, BitOr, BitXor}; @@ -49,25 +49,25 @@ instr_op!( instr_op!(sltu, sltiu, |a, b| (a < b) as RegValue); instr_op!(slt, slti, |a, b| ((a as i64) < (b as i64)) as RegValue); -pub fn lui(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn lui(core: &mut Core, instr: Instruction) -> Result<(), Exception> { core.reg_write(instr.rd(), instr.imm_u()); core.advance_pc(); Ok(()) } -pub fn auipc(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn auipc(core: &mut Core, instr: Instruction) -> Result<(), Exception> { core.reg_write(instr.rd(), core.pc.wrapping_add(instr.imm_u())); core.advance_pc(); Ok(()) } -pub fn jal(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn jal(core: &mut Core, instr: Instruction) -> Result<(), Exception> { core.reg_write(instr.rd(), core.pc.wrapping_add(4)); core.pc = core.pc.wrapping_add(instr.imm_j()); Ok(()) } -pub fn jalr(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn jalr(core: &mut Core, instr: Instruction) -> Result<(), Exception> { core.reg_write(instr.rd(), core.pc.wrapping_add(4)); core.pc = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); Ok(()) diff --git a/src/instructions/rvi/mem.rs b/src/instructions/rvi/mem.rs index 73e4179..071fa79 100644 --- a/src/instructions/rvi/mem.rs +++ b/src/instructions/rvi/mem.rs @@ -7,11 +7,11 @@ use crate::{ consts::{Byte, DWord, HWord, Word}, core::Core, - exceptions::ExceptionType, + exceptions::Exception, instructions::Instruction, }; -pub fn sd(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn sd(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s()); let value = core.reg_read(instr.rs2()); core.mem @@ -21,7 +21,7 @@ pub fn sd(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { Ok(()) } -pub fn ld(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn ld(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); core.reg_write( instr.rd(), @@ -33,7 +33,7 @@ pub fn ld(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { Ok(()) } -pub fn sw(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn sw(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s()); let value = core.reg_read(instr.rs2()) as Word; core.mem @@ -43,7 +43,7 @@ pub fn sw(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { Ok(()) } -pub fn lw(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn lw(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); core.reg_write( instr.rd(), @@ -55,7 +55,7 @@ pub fn lw(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { Ok(()) } -pub fn lwu(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn lwu(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); core.reg_write( instr.rd(), @@ -67,7 +67,7 @@ pub fn lwu(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { Ok(()) } -pub fn sh(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn sh(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s()); let value = core.reg_read(instr.rs2()) as HWord; core.mem @@ -77,7 +77,7 @@ pub fn sh(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { Ok(()) } -pub fn lh(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn lh(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); core.reg_write( instr.rd(), @@ -89,7 +89,7 @@ pub fn lh(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { Ok(()) } -pub fn lhu(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn lhu(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); core.reg_write( instr.rd(), @@ -101,7 +101,7 @@ pub fn lhu(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { Ok(()) } -pub fn sb(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn sb(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s()); let value = core.reg_read(instr.rs2()) as Byte; core.mem @@ -111,7 +111,7 @@ pub fn sb(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { Ok(()) } -pub fn lb(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn lb(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); core.reg_write( instr.rd(), @@ -123,7 +123,7 @@ pub fn lb(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { Ok(()) } -pub fn lbu(core: &mut Core, instr: Instruction) -> Result<(), ExceptionType> { +pub fn lbu(core: &mut Core, instr: Instruction) -> Result<(), Exception> { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()); core.reg_write( instr.rd(), diff --git a/src/main.rs b/src/main.rs index 53c2938..780534f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ use clap::Parser; use trve::{ consts::{Addr, Byte, DWord, HWord, Word}, core::Core, - exceptions::MemoryExceptionType, + exceptions::MemoryException, gdb, mem::{MemConfig, MemDeviceInterface, MmioRoot, Ram}, }; @@ -70,22 +70,22 @@ mod basic_uart; struct DbgOut; impl MemDeviceInterface for DbgOut { - fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryExceptionType> { + fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryException> { eprintln!("Wrote DWord {value:016x} to Debug-Out address {addr:x}"); Ok(()) } - fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryExceptionType> { + fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryException> { eprintln!("Wrote Word {value:08x} to Debug-Out address {addr:x}"); Ok(()) } - fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryExceptionType> { + fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryException> { eprintln!("Wrote HWord {value:04x} to Debug-Out address {addr:x}"); Ok(()) } - fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryExceptionType> { + fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryException> { eprintln!("Wrote Byte {value:02x} to Debug-Out address {addr:x}"); Ok(()) } diff --git a/src/mem.rs b/src/mem.rs index 6aae337..95a0eb2 100644 --- a/src/mem.rs +++ b/src/mem.rs @@ -13,7 +13,7 @@ use memmap2::MmapMut; use crate::{ consts::{Addr, Byte, DWord, HWord, Word}, - exceptions::MemoryExceptionType, + exceptions::{MemoryException, MemoryExceptionType}, }; pub type PageNum = usize; @@ -37,119 +37,140 @@ impl MemConfig { } } - pub fn read_dword(&self, addr: Addr) -> Result { + pub fn read_dword(&self, addr: Addr) -> Result { if addr >= RAM_START { self.ram.read_dword(addr - RAM_START) } else { if !addr.is_multiple_of(8) && self.mmio_root.crosses_boundary(addr, 8) { - return Err(MemoryExceptionType::AddressMisaligned); + return Err(MemoryException { + type_: MemoryExceptionType::AddressMisaligned, + addr, + }); } - let (interface, addr) = self - .mmio_root - .get_device(addr) - .ok_or(MemoryExceptionType::AccessFault)?; + let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + })?; interface.read_dword(addr) } } - pub fn read_word(&self, addr: Addr) -> Result { + pub fn read_word(&self, addr: Addr) -> Result { if addr >= RAM_START { self.ram.read_word(addr - RAM_START) } else { if !addr.is_multiple_of(4) && self.mmio_root.crosses_boundary(addr, 4) { - return Err(MemoryExceptionType::AddressMisaligned); + return Err(MemoryException { + type_: MemoryExceptionType::AddressMisaligned, + addr, + }); } - let (interface, addr) = self - .mmio_root - .get_device(addr) - .ok_or(MemoryExceptionType::AccessFault)?; + let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + })?; interface.read_word(addr) } } - pub fn read_hword(&self, addr: Addr) -> Result { + pub fn read_hword(&self, addr: Addr) -> Result { if addr >= RAM_START { self.ram.read_hword(addr - RAM_START) } else { if !addr.is_multiple_of(2) && self.mmio_root.crosses_boundary(addr, 2) { - return Err(MemoryExceptionType::AddressMisaligned); + return Err(MemoryException { + type_: MemoryExceptionType::AddressMisaligned, + addr, + }); } - let (interface, addr) = self - .mmio_root - .get_device(addr) - .ok_or(MemoryExceptionType::AccessFault)?; + let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + })?; interface.read_hword(addr) } } - pub fn read_byte(&self, addr: Addr) -> Result { + pub fn read_byte(&self, addr: Addr) -> Result { if addr >= RAM_START { self.ram.read_byte(addr - RAM_START) } else { - let (interface, addr) = self - .mmio_root - .get_device(addr) - .ok_or(MemoryExceptionType::AccessFault)?; + let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + })?; interface.read_byte(addr) } } - pub fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryExceptionType> { + pub fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryException> { if addr >= RAM_START { self.ram.write_dword(addr - RAM_START, value) } else { if !addr.is_multiple_of(8) && self.mmio_root.crosses_boundary(addr, 8) { - return Err(MemoryExceptionType::AddressMisaligned); + return Err(MemoryException { + type_: MemoryExceptionType::AddressMisaligned, + addr, + }); } - let (interface, addr) = self - .mmio_root - .get_device(addr) - .ok_or(MemoryExceptionType::AccessFault)?; + let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + })?; interface.write_dword(addr, value) } } - pub fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryExceptionType> { + pub fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryException> { if addr >= RAM_START { self.ram.write_word(addr - RAM_START, value) } else { if !addr.is_multiple_of(4) && self.mmio_root.crosses_boundary(addr, 4) { - return Err(MemoryExceptionType::AddressMisaligned); + return Err(MemoryException { + type_: MemoryExceptionType::AddressMisaligned, + addr, + }); } - let (interface, addr) = self - .mmio_root - .get_device(addr) - .ok_or(MemoryExceptionType::AccessFault)?; + let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + })?; interface.write_word(addr, value) } } - pub fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryExceptionType> { + pub fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryException> { if addr >= RAM_START { self.ram.write_hword(addr - RAM_START, value) } else { if !addr.is_multiple_of(2) && self.mmio_root.crosses_boundary(addr, 2) { - return Err(MemoryExceptionType::AddressMisaligned); + return Err(MemoryException { + type_: MemoryExceptionType::AddressMisaligned, + addr, + }); } - let (interface, addr) = self - .mmio_root - .get_device(addr) - .ok_or(MemoryExceptionType::AccessFault)?; + let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + })?; interface.write_hword(addr, value) } } - pub fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryExceptionType> { + pub fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryException> { if addr >= RAM_START { self.ram.write_byte(addr - RAM_START, value) } else { - let (interface, addr) = self - .mmio_root - .get_device(addr) - .ok_or(MemoryExceptionType::AccessFault)?; + let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + })?; interface.write_byte(addr, value) } } - pub fn get_atomic_dword(&self, addr: Addr) -> Result<&AtomicU64, MemoryExceptionType> { + pub fn get_atomic_dword(&self, addr: Addr) -> Result<&AtomicU64, MemoryException> { if !addr.is_multiple_of(8) { - return Err(MemoryExceptionType::AddressMisaligned); + return Err(MemoryException { + type_: MemoryExceptionType::AddressMisaligned, + addr, + }); } let index = ((addr - RAM_START) / 8) as usize; @@ -157,16 +178,25 @@ impl MemConfig { self.ram .buf_transmuted::() .get(index) - .ok_or(MemoryExceptionType::AccessFault) + .ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) } } - pub fn get_atomic_word(&self, addr: Addr) -> Result<&AtomicU32, MemoryExceptionType> { + pub fn get_atomic_word(&self, addr: Addr) -> Result<&AtomicU32, MemoryException> { if !addr.is_multiple_of(4) { - return Err(MemoryExceptionType::AddressMisaligned); + return Err(MemoryException { + type_: MemoryExceptionType::AddressMisaligned, + addr, + }); } if addr < RAM_START { - return Err(MemoryExceptionType::AccessFault); + return Err(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }); } let index = ((addr - RAM_START) / 4) as usize; @@ -174,7 +204,10 @@ impl MemConfig { self.ram .buf_transmuted::() .get(index) - .ok_or(MemoryExceptionType::AccessFault) + .ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) } } } @@ -229,7 +262,7 @@ impl Ram { } #[inline] - pub fn read_dword(&self, addr: Addr) -> Result { + pub fn read_dword(&self, addr: Addr) -> Result { if !addr.is_multiple_of(8) { let high_word_addr = addr.wrapping_add(4); @@ -243,12 +276,15 @@ impl Ram { Ok(unsafe { self.buf_transmuted::() .get(index) - .ok_or(MemoryExceptionType::AccessFault) + .ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) }? .load(Relaxed)) } #[inline] - pub fn read_word(&self, addr: Addr) -> Result { + pub fn read_word(&self, addr: Addr) -> Result { if !addr.is_multiple_of(4) { let high_hword_addr = addr.wrapping_add(2); @@ -262,12 +298,15 @@ impl Ram { Ok(unsafe { self.buf_transmuted::() .get(index) - .ok_or(MemoryExceptionType::AccessFault) + .ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) }? .load(Relaxed)) } #[inline] - pub fn read_hword(&self, addr: Addr) -> Result { + pub fn read_hword(&self, addr: Addr) -> Result { if !addr.is_multiple_of(2) { let high_byte_addr = addr.wrapping_add(1); @@ -281,21 +320,27 @@ impl Ram { Ok(unsafe { self.buf_transmuted::() .get(index) - .ok_or(MemoryExceptionType::AccessFault) + .ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) }? .load(Relaxed)) } #[inline] - pub fn read_byte(&self, addr: Addr) -> Result { + pub fn read_byte(&self, addr: Addr) -> Result { Ok(self .buf_atomic() .get(addr as usize) - .ok_or(MemoryExceptionType::AccessFault)? + .ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + })? .load(Relaxed)) } #[inline] - pub fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryExceptionType> { + pub fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryException> { if !addr.is_multiple_of(8) { let low_word = value as Word; let high_word = (value >> 32) as Word; @@ -311,13 +356,16 @@ impl Ram { unsafe { self.buf_transmuted::() .get(index) - .ok_or(MemoryExceptionType::AccessFault) + .ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) }? .store(value, Relaxed); Ok(()) } #[inline] - pub fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryExceptionType> { + pub fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryException> { if !addr.is_multiple_of(4) { let low_hword = value as HWord; let high_hword = (value >> 16) as HWord; @@ -333,13 +381,16 @@ impl Ram { unsafe { self.buf_transmuted::() .get(index) - .ok_or(MemoryExceptionType::AccessFault) + .ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) }? .store(value, Relaxed); Ok(()) } #[inline] - pub fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryExceptionType> { + pub fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryException> { if !addr.is_multiple_of(2) { let low_byte = value as Byte; let high_byte = (value >> 8) as Byte; @@ -355,16 +406,22 @@ impl Ram { unsafe { self.buf_transmuted::() .get(index) - .ok_or(MemoryExceptionType::AccessFault) + .ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) }? .store(value, Relaxed); Ok(()) } #[inline] - pub fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryExceptionType> { + pub fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryException> { self.buf_atomic() .get(addr as usize) - .ok_or(MemoryExceptionType::AccessFault)? + .ok_or(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + })? .store(value, Relaxed); Ok(()) } @@ -477,29 +534,53 @@ impl Default for MmioSecondLevel { #[allow(unused_variables)] pub trait MemDeviceInterface { - fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryExceptionType> { - Err(MemoryExceptionType::AccessFault) + fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryException> { + Err(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) } - fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryExceptionType> { - Err(MemoryExceptionType::AccessFault) + fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryException> { + Err(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) } - fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryExceptionType> { - Err(MemoryExceptionType::AccessFault) + fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryException> { + Err(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) } - fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryExceptionType> { - Err(MemoryExceptionType::AccessFault) + fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryException> { + Err(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) } - fn read_dword(&self, addr: Addr) -> Result { - Err(MemoryExceptionType::AccessFault) + fn read_dword(&self, addr: Addr) -> Result { + Err(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) } - fn read_word(&self, addr: Addr) -> Result { - Err(MemoryExceptionType::AccessFault) + fn read_word(&self, addr: Addr) -> Result { + Err(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) } - fn read_hword(&self, addr: Addr) -> Result { - Err(MemoryExceptionType::AccessFault) + fn read_hword(&self, addr: Addr) -> Result { + Err(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) } - fn read_byte(&self, addr: Addr) -> Result { - Err(MemoryExceptionType::AccessFault) + fn read_byte(&self, addr: Addr) -> Result { + Err(MemoryException { + type_: MemoryExceptionType::AccessFault, + addr, + }) } }