summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml1
-rw-r--r--src/instructions.rs69
-rw-r--r--src/lib.rs1
4 files changed, 78 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bb7ba3e..ee3da81 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,8 +18,15 @@ dependencies = [
]
[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
name = "rvem"
version = "0.1.0"
dependencies = [
"memmap2",
+ "once_cell",
]
diff --git a/Cargo.toml b/Cargo.toml
index f844555..1bb7d29 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,3 +5,4 @@ edition = "2024"
[dependencies]
memmap2 = "0.9.8"
+once_cell = "1.21.3"
diff --git a/src/instructions.rs b/src/instructions.rs
new file mode 100644
index 0000000..9f3a544
--- /dev/null
+++ b/src/instructions.rs
@@ -0,0 +1,69 @@
+use once_cell::sync::Lazy;
+
+static INSTRUCTIONS: Lazy<[Option<OpcodeHandler>; 32]> = Lazy::new(|| {
+ let mut instructions = std::array::from_fn(|_i| None);
+
+ instructions
+});
+
+use crate::{consts::Word, core::Core, decode::Instruction};
+
+type Runner = fn(&mut Core, Instruction) -> Result<(), ()>;
+
+#[derive(Clone, Copy)]
+struct InstructionHandler {
+ runner: Runner,
+}
+
+struct OpcodeHandler {
+ handler: Option<InstructionHandler>,
+ splitter: Option<Splitter>,
+}
+
+pub fn find_runner(instruction: Instruction) -> Option<Runner> {
+ let opcode_handler = &INSTRUCTIONS[instruction.opcode_noncompressed() as usize];
+ match opcode_handler {
+ Some(h) => h.find_runner(instruction),
+ None => None,
+ }
+}
+
+impl OpcodeHandler {
+ fn find_runner(&self, instruction: Instruction) -> Option<Runner> {
+ if let Some(splitter) = &self.splitter {
+ splitter.find_runner(instruction)
+ } else {
+ self.handler.map(|h| h.runner)
+ }
+ }
+}
+
+enum Splitter {
+ Funct3Splitter(Box<[Option<OpcodeHandler>; 8]>),
+ GeneralSplitter(Box<[GeneralSplitterEntry]>),
+}
+
+impl Splitter {
+ fn find_runner(&self, instruction: Instruction) -> Option<Runner> {
+ match self {
+ Splitter::Funct3Splitter(f3s) => f3s[instruction.funct3() as usize]
+ .as_ref()
+ .and_then(|h| h.find_runner(instruction)),
+ Splitter::GeneralSplitter(entries) => {
+ for entry in entries {
+ if instruction.0 & entry.mask == entry.value {
+ return Some(entry.handler.runner);
+ }
+ }
+
+ None
+ }
+ }
+ }
+}
+
+struct GeneralSplitterEntry {
+ mask: Word,
+ value: Word,
+ handler: InstructionHandler,
+}
diff --git a/src/lib.rs b/src/lib.rs
index 4020af3..3cc8c0b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,5 @@
mod consts;
pub mod core;
mod decode;
+mod instructions;
pub mod mem;