Implement ECALL and EBREAK, the final RV64I instructions!

This commit is contained in:
2025-12-27 21:47:22 +01:00
parent 5c008bfc04
commit 8024af6b13
4 changed files with 29 additions and 1 deletions

View File

@@ -4,6 +4,8 @@ taitep's RISC-V Emulator.
The goal is to support at least RV64GC and be able to run Linux, The goal is to support at least RV64GC and be able to run Linux,
potentially more. No plans for RV32I or RV32/64E. potentially more. No plans for RV32I or RV32/64E.
Currently implemented RISC-V ISA: `RV64I`
## Current Use ## Current Use
Currently, the emulator is nowhere near complete, Currently, the emulator is nowhere near complete,
its not even at rv64i, but it does work for a subset of it. its not even at rv64i, but it does work for a subset of it.

View File

@@ -93,4 +93,9 @@ impl Instruction {
pub fn funct6(self) -> u8 { pub fn funct6(self) -> u8 {
(self.0 >> 26 & 0x3f) as u8 (self.0 >> 26 & 0x3f) as u8
} }
/// Mostly/only used for the SYSTEM opcode
pub fn funct12(self) -> u16 {
(self.0 >> 20) as u16
}
} }

View File

@@ -31,6 +31,15 @@ pub enum ExceptionType {
HardwareError = 19, HardwareError = 19,
} }
impl ExceptionType {
pub fn with_no_value(self) -> Exception {
Exception {
type_: self,
value: 0,
}
}
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Exception { pub struct Exception {
pub type_: ExceptionType, pub type_: ExceptionType,

View File

@@ -13,7 +13,10 @@ use crate::{
consts::DWord, consts::DWord,
core::Core, core::Core,
decode::Instruction, decode::Instruction,
exceptions::{Exception, ExceptionType::IllegalInstruction}, exceptions::{
Exception,
ExceptionType::{self, IllegalInstruction},
},
}; };
fn illegal(instr: Instruction) -> Result<(), Exception> { fn illegal(instr: Instruction) -> Result<(), Exception> {
@@ -130,6 +133,15 @@ pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Result<(), E
} }
_ => illegal(instr), _ => illegal(instr),
}, },
0b11100 => match (instr.funct3(), instr.funct12(), instr.rs1(), instr.rd()) {
(0b000, 0b000000000000, 0, 0) => {
// TODO: When privilege modes are added, make the exception raised by ecall
// depend on privilege mode
Err(ExceptionType::EnvironmentCallFromMMode.with_no_value())
}
(0b000, 0b000000000001, 0, 0) => Err(ExceptionType::Breakpoint.with_no_value()),
_ => illegal(instr),
},
_ => illegal(instr), _ => illegal(instr),
} }
} }