From ee5f5a2ec41ed426440346ff47339b63c2cf7c1d Mon Sep 17 00:00:00 2001 From: taitep Date: Tue, 7 Oct 2025 20:23:59 +0200 Subject: [PATCH] FIRST INSTRUCTION WORKING --- src/instructions.rs | 26 ++++++++++++++++---------- src/instructions/gen_tools.rs | 22 ++++++++++++++++++++++ src/instructions/opcodes.rs | 6 ++++++ src/instructions/rvi.rs | 28 ++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 src/instructions/gen_tools.rs create mode 100644 src/instructions/opcodes.rs create mode 100644 src/instructions/rvi.rs diff --git a/src/instructions.rs b/src/instructions.rs index ed264f9..fc005e9 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -1,7 +1,16 @@ use once_cell::sync::Lazy; -static INSTRUCTIONS: Lazy<[Option; 32]> = Lazy::new(|| { - let mut instructions = std::array::from_fn(|_i| None); +mod gen_tools; +mod opcodes; +mod rvi; + +static INSTRUCTIONS: Lazy<[OpcodeHandler; 32]> = Lazy::new(|| { + let mut instructions = std::array::from_fn(|_i| OpcodeHandler { + handler: None, + splitter: None, + }); + + rvi::add_instrs(&mut instructions); instructions }); @@ -26,10 +35,7 @@ struct OpcodeHandler { pub fn find_runner(instruction: Instruction) -> Option { let opcode_handler = &INSTRUCTIONS[instruction.opcode_noncompressed() as usize]; - match opcode_handler { - Some(h) => h.find_runner(instruction), - None => None, - } + opcode_handler.find_runner(instruction) } impl OpcodeHandler { @@ -43,16 +49,16 @@ impl OpcodeHandler { } enum Splitter { - Funct3Splitter(Box<[Option; 8]>), + Funct3Splitter(Box<[OpcodeHandler; 8]>), GeneralSplitter(Box<[GeneralSplitterEntry]>), } impl Splitter { fn find_runner(&self, instruction: Instruction) -> Option { match self { - Splitter::Funct3Splitter(f3s) => f3s[instruction.funct3() as usize] - .as_ref() - .and_then(|h| h.find_runner(instruction)), + Splitter::Funct3Splitter(f3s) => { + f3s[instruction.funct3() as usize].find_runner(instruction) + } Splitter::GeneralSplitter(entries) => { for entry in entries { if instruction.0 & entry.mask == entry.value { diff --git a/src/instructions/gen_tools.rs b/src/instructions/gen_tools.rs new file mode 100644 index 0000000..ad9ad62 --- /dev/null +++ b/src/instructions/gen_tools.rs @@ -0,0 +1,22 @@ +use std::hint::unreachable_unchecked; + +use crate::instructions::{OpcodeHandler, Splitter}; + +pub fn insert_funct3_splitter(splitter: &mut Option) -> &mut [OpcodeHandler; 8] { + match splitter { + Some(Splitter::Funct3Splitter(s)) => s.as_mut(), + Some(_) => panic!("Unexpected splitter variant"), + None => { + *splitter = Some(Splitter::Funct3Splitter(Box::new(std::array::from_fn( + |_i| OpcodeHandler { + handler: None, + splitter: None, + }, + )))); + match splitter { + Some(Splitter::Funct3Splitter(s)) => s.as_mut(), + _ => unsafe { unreachable_unchecked() }, + } + } + } +} diff --git a/src/instructions/opcodes.rs b/src/instructions/opcodes.rs new file mode 100644 index 0000000..33f824d --- /dev/null +++ b/src/instructions/opcodes.rs @@ -0,0 +1,6 @@ +//! Includes opcodes, funct3 values, and match/mask values. +//! Opcodes (unless compressed) have the last 2 bits stripped off as they are always 1s for non-compressed instructions. + +pub(super) const OP_IMM: u8 = 0b00100; + +pub(super) const FUNCT3_ADDI: u8 = 0x0; diff --git a/src/instructions/rvi.rs b/src/instructions/rvi.rs new file mode 100644 index 0000000..8e7dade --- /dev/null +++ b/src/instructions/rvi.rs @@ -0,0 +1,28 @@ +use crate::{ + core::{Core, InstructionResult}, + decode::Instruction, + instructions::{ + OpcodeHandler, + gen_tools::insert_funct3_splitter, + opcodes::{FUNCT3_ADDI, OP_IMM}, + }, +}; + +pub(super) fn add_instrs(list: &mut [OpcodeHandler; 32]) { + let funct3_split_op_imm = insert_funct3_splitter(&mut list[OP_IMM as usize].splitter); + funct3_split_op_imm[FUNCT3_ADDI as usize].handler = + Some(super::InstructionHandler { runner: addi }); +} + +fn addi(core: &mut Core, instr: Instruction) -> InstructionResult { + eprintln!("Running ADDI"); + + core.reg_write( + instr.rd(), + core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()), + ); + + core.pc = core.pc.wrapping_add(4); + + InstructionResult::Normal +}