From 8024af6b1348b5f47fabe5a1949de54607a33888 Mon Sep 17 00:00:00 2001 From: taitep Date: Sat, 27 Dec 2025 21:47:22 +0100 Subject: [PATCH] Implement ECALL and EBREAK, the final RV64I instructions! --- README.md | 2 ++ src/decode.rs | 5 +++++ src/exceptions.rs | 9 +++++++++ src/instructions.rs | 14 +++++++++++++- 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index de9ca7f..697c0f2 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ taitep's RISC-V Emulator. The goal is to support at least RV64GC and be able to run Linux, potentially more. No plans for RV32I or RV32/64E. +Currently implemented RISC-V ISA: `RV64I` + ## Current Use Currently, the emulator is nowhere near complete, its not even at rv64i, but it does work for a subset of it. diff --git a/src/decode.rs b/src/decode.rs index d520151..e24bac0 100644 --- a/src/decode.rs +++ b/src/decode.rs @@ -93,4 +93,9 @@ impl Instruction { pub fn funct6(self) -> u8 { (self.0 >> 26 & 0x3f) as u8 } + + /// Mostly/only used for the SYSTEM opcode + pub fn funct12(self) -> u16 { + (self.0 >> 20) as u16 + } } diff --git a/src/exceptions.rs b/src/exceptions.rs index 5e3f02f..6bc21f2 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -31,6 +31,15 @@ pub enum ExceptionType { HardwareError = 19, } +impl ExceptionType { + pub fn with_no_value(self) -> Exception { + Exception { + type_: self, + value: 0, + } + } +} + #[derive(Debug, Clone, Copy)] pub struct Exception { pub type_: ExceptionType, diff --git a/src/instructions.rs b/src/instructions.rs index fe79684..99df830 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -13,7 +13,10 @@ use crate::{ consts::DWord, core::Core, decode::Instruction, - exceptions::{Exception, ExceptionType::IllegalInstruction}, + exceptions::{ + Exception, + ExceptionType::{self, IllegalInstruction}, + }, }; 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), }, + 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), } }