Add exception values (what will go in mtval/stval)

This commit is contained in:
2025-12-27 21:33:39 +01:00
parent b5d36b7969
commit 5c008bfc04
9 changed files with 295 additions and 161 deletions

View File

@@ -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,
}),
}
}
}

View File

@@ -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);
}

View File

@@ -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_
}
}

View File

@@ -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),
}
}

View File

@@ -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);

View File

@@ -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(())

View File

@@ -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(),

View File

@@ -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(())
}

View File

@@ -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,
})
}
}