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