diff --git a/src/core.rs b/src/core.rs index 1628216..4c17070 100644 --- a/src/core.rs +++ b/src/core.rs @@ -7,7 +7,7 @@ use crate::{ consts::{Addr, RegId, RegValue}, decode::Instruction, - instructions::find_runner, + instructions::find_and_exec, mem::MemConfig, }; @@ -57,11 +57,9 @@ impl Core { let instr = Instruction(instr); - let runner = find_runner(instr); - - if let Some(runner) = runner { - let res = runner(self, instr); + let res = find_and_exec(instr, self); + if let Some(res) = res { match res { InstructionResult::Normal => {} InstructionResult::Exception(_e) => { diff --git a/src/instructions.rs b/src/instructions.rs index 2d18a2c..eead29f 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -4,82 +4,31 @@ // This file is part of TRVE (https://gitea.taitep.se/taitep/trve) // See LICENSE file in the project root for full license text. -use once_cell::sync::Lazy; - -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 -}); - use crate::{ - consts::Word, core::{Core, InstructionResult}, decode::Instruction, }; -type Runner = fn(&mut Core, Instruction) -> InstructionResult; - -#[derive(Clone, Copy)] -struct InstructionHandler { - runner: Runner, -} - -struct OpcodeHandler { - handler: Option, - splitter: Option, -} - -pub fn find_runner(instruction: Instruction) -> Option { - let opcode_handler = &INSTRUCTIONS[instruction.opcode_noncompressed() as usize]; - opcode_handler.find_runner(instruction) -} - -impl OpcodeHandler { - fn find_runner(&self, instruction: Instruction) -> Option { - if let Some(splitter) = &self.splitter { - splitter.find_runner(instruction) - } else { - self.handler.map(|h| h.runner) - } +pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Option { + match instr.opcode_noncompressed() { + 0b00100 => match instr.funct3() { + // OP_IMM + 0b000 => Some(rvi::addi(core, instr)), + _ => None, + }, + 0b00110 => match instr.funct3() { + // OP_IMM_32 + 0b000 => Some(rvi::addiw(core, instr)), + _ => None, + }, + 0b01000 => match instr.funct3() { + // STORE + 0b011 => Some(rvi::sd(core, instr)), + _ => None, + }, + 0b01101 => Some(rvi::lui(core, instr)), + _ => None, } } - -enum Splitter { - 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].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/instructions/gen_tools.rs b/src/instructions/gen_tools.rs deleted file mode 100644 index a3d45bc..0000000 --- a/src/instructions/gen_tools.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2025 taitep -// SPDX-License-Identifier: MIT -// -// This file is part of TRVE (https://gitea.taitep.se/taitep/trve) -// See LICENSE file in the project root for full license text. - -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 deleted file mode 100644 index b5613f9..0000000 --- a/src/instructions/opcodes.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! 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 OP_IMM_32: u8 = 0b00110; - -pub(super) const STORE: u8 = 0b01000; diff --git a/src/instructions/rvi.rs b/src/instructions/rvi.rs index 5597de4..feff85b 100644 --- a/src/instructions/rvi.rs +++ b/src/instructions/rvi.rs @@ -8,28 +8,10 @@ use crate::{ consts::{Addr, DWord}, core::{Core, InstructionResult}, decode::Instruction, - instructions::{ - OpcodeHandler, - gen_tools::insert_funct3_splitter, - opcodes::{OP_IMM, OP_IMM_32, STORE}, - }, mem::PageNum, }; -pub(super) fn add_instrs(list: &mut [OpcodeHandler; 32]) { - let funct3_splitter = insert_funct3_splitter(&mut list[OP_IMM as usize].splitter); // OP-IMM - funct3_splitter[0b000].handler = Some(super::InstructionHandler { runner: addi }); // ADDI - - let funct3_splitter = insert_funct3_splitter(&mut list[OP_IMM_32 as usize].splitter); // OP-IMM-32 - funct3_splitter[0b000].handler = Some(super::InstructionHandler { runner: addiw }); //ADDIW - - let funct3_splitter = insert_funct3_splitter(&mut list[STORE as usize].splitter); // STORE - funct3_splitter[0b011].handler = Some(super::InstructionHandler { runner: sd }); // SD - - list[0b01101].handler = Some(super::InstructionHandler { runner: lui }); //LUI -} - -fn addi(core: &mut Core, instr: Instruction) -> InstructionResult { +pub(super) fn addi(core: &mut Core, instr: Instruction) -> InstructionResult { core.reg_write( instr.rd(), core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()), @@ -40,7 +22,7 @@ fn addi(core: &mut Core, instr: Instruction) -> InstructionResult { InstructionResult::Normal } -fn addiw(core: &mut Core, instr: Instruction) -> InstructionResult { +pub(super) fn addiw(core: &mut Core, instr: Instruction) -> InstructionResult { let res = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i()) as i32; core.reg_write(instr.rd(), res as i64 as u64); @@ -51,7 +33,7 @@ fn addiw(core: &mut Core, instr: Instruction) -> InstructionResult { } // TODO: Support misaligned memory access -fn sd(core: &mut Core, instr: Instruction) -> InstructionResult { +pub(super) fn sd(core: &mut Core, instr: Instruction) -> InstructionResult { let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s()); if !addr.is_multiple_of(std::mem::size_of::() as Addr) { @@ -71,7 +53,7 @@ fn sd(core: &mut Core, instr: Instruction) -> InstructionResult { } } -fn lui(core: &mut Core, instr: Instruction) -> InstructionResult { +pub(super) fn lui(core: &mut Core, instr: Instruction) -> InstructionResult { core.reg_write(instr.rd(), instr.imm_u()); core.pc = core.pc.wrapping_add(4); InstructionResult::Normal