summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortaitep <taitep@taitep.se>2025-12-27 21:33:39 +0100
committertaitep <taitep@taitep.se>2025-12-27 21:33:39 +0100
commit5c008bfc0446e4631dbab64be61159af04f78dd1 (patch)
tree852f7ee883f675b4c67cf424b8f7d17357e7742d /src
parentb5d36b7969f2759147d58a80e0e5b62c215d2998 (diff)
Add exception values (what will go in mtval/stval)
Diffstat (limited to 'src')
-rw-r--r--src/basic_uart.rs16
-rw-r--r--src/core.rs30
-rw-r--r--src/exceptions.rs67
-rw-r--r--src/instructions.rs40
-rw-r--r--src/instructions/macros.rs6
-rw-r--r--src/instructions/rvi.rs10
-rw-r--r--src/instructions/rvi/mem.rs24
-rw-r--r--src/main.rs10
-rw-r--r--src/mem.rs253
9 files changed, 295 insertions, 161 deletions
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<Byte, MemoryExceptionType> {
+ fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryException> {
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::<Result<_, MemoryException>>()
+ .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<MemoryExceptionType> for MemoryException {
+ fn into(self) -> MemoryExceptionType {
+ self.type_
+ }
+}
+
+impl Into<ExceptionType> 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<DWord, MemoryExceptionType> {
+ pub fn read_dword(&self, addr: Addr) -> Result<DWord, MemoryException> {
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<Word, MemoryExceptionType> {
+ pub fn read_word(&self, addr: Addr) -> Result<Word, MemoryException> {
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<HWord, MemoryExceptionType> {
+ pub fn read_hword(&self, addr: Addr) -> Result<HWord, MemoryException> {
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<Byte, MemoryExceptionType> {
+ pub fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryException> {
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::<AtomicU64>()
.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::<AtomicU32>()
.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<DWord, MemoryExceptionType> {
+ pub fn read_dword(&self, addr: Addr) -> Result<DWord, MemoryException> {
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::<AtomicU64>()
.get(index)
- .ok_or(MemoryExceptionType::AccessFault)
+ .ok_or(MemoryException {
+ type_: MemoryExceptionType::AccessFault,
+ addr,
+ })
}?
.load(Relaxed))
}
#[inline]
- pub fn read_word(&self, addr: Addr) -> Result<Word, MemoryExceptionType> {
+ pub fn read_word(&self, addr: Addr) -> Result<Word, MemoryException> {
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::<AtomicU32>()
.get(index)
- .ok_or(MemoryExceptionType::AccessFault)
+ .ok_or(MemoryException {
+ type_: MemoryExceptionType::AccessFault,
+ addr,
+ })
}?
.load(Relaxed))
}
#[inline]
- pub fn read_hword(&self, addr: Addr) -> Result<HWord, MemoryExceptionType> {
+ pub fn read_hword(&self, addr: Addr) -> Result<HWord, MemoryException> {
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::<AtomicU16>()
.get(index)
- .ok_or(MemoryExceptionType::AccessFault)
+ .ok_or(MemoryException {
+ type_: MemoryExceptionType::AccessFault,
+ addr,
+ })
}?
.load(Relaxed))
}
#[inline]
- pub fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryExceptionType> {
+ pub fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryException> {
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::<AtomicU64>()
.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::<AtomicU32>()
.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::<AtomicU16>()
.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<DWord, MemoryExceptionType> {
- Err(MemoryExceptionType::AccessFault)
+ fn read_dword(&self, addr: Addr) -> Result<DWord, MemoryException> {
+ Err(MemoryException {
+ type_: MemoryExceptionType::AccessFault,
+ addr,
+ })
}
- fn read_word(&self, addr: Addr) -> Result<Word, MemoryExceptionType> {
- Err(MemoryExceptionType::AccessFault)
+ fn read_word(&self, addr: Addr) -> Result<Word, MemoryException> {
+ Err(MemoryException {
+ type_: MemoryExceptionType::AccessFault,
+ addr,
+ })
}
- fn read_hword(&self, addr: Addr) -> Result<HWord, MemoryExceptionType> {
- Err(MemoryExceptionType::AccessFault)
+ fn read_hword(&self, addr: Addr) -> Result<HWord, MemoryException> {
+ Err(MemoryException {
+ type_: MemoryExceptionType::AccessFault,
+ addr,
+ })
}
- fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryExceptionType> {
- Err(MemoryExceptionType::AccessFault)
+ fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryException> {
+ Err(MemoryException {
+ type_: MemoryExceptionType::AccessFault,
+ addr,
+ })
}
}