diff options
Diffstat (limited to 'src/rv32_cpu/rv32_cpu.rs')
| -rw-r--r-- | src/rv32_cpu/rv32_cpu.rs | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/rv32_cpu/rv32_cpu.rs b/src/rv32_cpu/rv32_cpu.rs new file mode 100644 index 0000000..aefd1c0 --- /dev/null +++ b/src/rv32_cpu/rv32_cpu.rs @@ -0,0 +1,89 @@ +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<Opcode, Box<dyn Instruction>>, + 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<T: Extension>(mut self) -> Self { + T::add_instructions(&mut self); + self + } + + pub fn add_decode(&mut self, key: Opcode, instruction: Box<dyn Instruction>) { + self.decoders.insert(key, instruction); + } + + fn decode(decoders: &HashMap<Opcode, Box<dyn Instruction>>, instruction: u32) -> Result<&Box<dyn Instruction>, Box<dyn Error>> { + 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<dyn Error>> { + let instr: &Box<dyn Instruction> = Self::decode(&self.decoders, instruction)?; + instr.execute(instruction, &mut self.state)?; + Ok(()) + } + +} |
