Add exception values (what will go in mtval/stval)
This commit is contained in:
@@ -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,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
src/core.rs
30
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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_
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(())
|
||||
|
||||
@@ -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(),
|
||||
|
||||
10
src/main.rs
10
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(())
|
||||
}
|
||||
|
||||
253
src/mem.rs
253
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user