summaryrefslogtreecommitdiff
path: root/src/rv32_cpu/rv32_cpu.rs
blob: aefd1c05cbff602196f83af757367dd5cbebb7aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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(())
    }

}