use std::collections::HashMap; use std::error::Error; use crate::instruction::instruction::{Instruction, Opcode}; use crate::extension::extension::Extension; #[derive(Default)] pub struct GPRegisters { pub registers: [u32; 32] } #[derive(Default)] pub struct SMRegisters { sie: u32, stvec: u32, } #[derive(Default)] pub struct MMRegisters { pub mie: u32, pub mtvec: u32, pub mepc: u32, pub mcause: u32, pub mhart: u32, } #[derive(Default)] pub struct State { pub pc: u32, pub gp_regs: GPRegisters, pub sm_regs: SMRegisters, pub mm_regs: MMRegisters, } pub struct Rv32Cpu { decoders: HashMap>, state: State, } impl Rv32Cpu { pub fn new(id: u32) -> Self { let mut state = State::default(); state.mm_regs.mhart = id; Rv32Cpu { decoders: HashMap::new(), state } } pub fn add_extension(mut self) -> Self { T::add_instructions(&mut self); self } pub fn add_decode(&mut self, key: Opcode, instruction: Box) { self.decoders.insert(key, instruction); } fn decode(decoders: &HashMap>, instruction: u32) -> Result<&Box, Box> { if instruction & 0x3 != 0x3 { return Err("Invalid opcode".into()); } let op: [u32; 3] = [(instruction >> 2) & 0x1F, (instruction >> 12) & 0x7, (instruction >> 27) & 0x7F]; let key3 = Opcode{opcode6_2: op[0], opcode14_12: Some(op[1]), opcode31_27: Some(op[2])}; if let Some(x) = decoders.get(&key3) { return Ok(x); } let key2 = Opcode{opcode6_2: op[0], opcode14_12: Some(op[1]), opcode31_27: None}; if let Some(x) = decoders.get(&key2) { return Ok(x); } let key1 = Opcode{opcode6_2: op[0], opcode14_12: None, opcode31_27: None}; if let Some(x) = decoders.get(&key1) { return Ok(x); } Err("Invalid opcode".into()) } pub fn execute(&mut self, instruction: u32) -> Result<(), Box> { let instr: &Box = Self::decode(&self.decoders, instruction)?; instr.execute(instruction, &mut self.state)?; Ok(()) } }