summaryrefslogtreecommitdiff
path: root/src/rv32_cpu/rv32_cpu.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/rv32_cpu/rv32_cpu.rs')
-rw-r--r--src/rv32_cpu/rv32_cpu.rs89
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(())
+ }
+
+}