summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortaitep <taitep@taitep.se>2025-12-27 21:47:22 +0100
committertaitep <taitep@taitep.se>2025-12-27 21:47:22 +0100
commit8024af6b1348b5f47fabe5a1949de54607a33888 (patch)
tree4b9cbf86d2adc23eeb77eb8ed6c2d24ba7d57b32
parent5c008bfc0446e4631dbab64be61159af04f78dd1 (diff)
Implement ECALL and EBREAK, the final RV64I instructions!
-rw-r--r--README.md2
-rw-r--r--src/decode.rs5
-rw-r--r--src/exceptions.rs9
-rw-r--r--src/instructions.rs14
4 files changed, 29 insertions, 1 deletions
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),
}
}