81 lines
2.0 KiB
Rust
81 lines
2.0 KiB
Rust
use crate::core::{
|
|
cpu::{Cpu, CpuType::*},
|
|
mem::Memory,
|
|
registers::Registers,
|
|
};
|
|
use utils::{
|
|
error::{Error, Severity, Type::UnhandledInstruction},
|
|
instruction::Instruction,
|
|
};
|
|
|
|
pub struct Interpreter {
|
|
regs: Registers,
|
|
delay_slot: bool,
|
|
prev_delay_slot: bool,
|
|
}
|
|
|
|
impl Cpu for Interpreter {
|
|
fn get_type() -> super::cpu::CpuType {
|
|
Interpreter
|
|
}
|
|
|
|
fn get_regs(&mut self) -> &mut Registers {
|
|
&mut self.regs
|
|
}
|
|
|
|
fn should_service_interrupt(&self) -> bool {
|
|
false
|
|
}
|
|
|
|
fn update_compare_interrupt(&mut self) {
|
|
todo!("update_compare_interrupt")
|
|
}
|
|
|
|
fn fetch(&self, _mem: &Memory, _vaddr: u64) -> Option<Instruction> {
|
|
todo!("translate vaddr to paddr and if it fails, throw the exception and return None");
|
|
// Some(mem.read<u32>(paddr).into())
|
|
}
|
|
|
|
fn fetch_then_advance(&mut self, mem: &Memory) -> Option<Instruction> {
|
|
self.update_compare_interrupt();
|
|
|
|
self.prev_delay_slot = self.delay_slot;
|
|
self.delay_slot = false;
|
|
|
|
todo!("is_address_error ? then throw exception and return None");
|
|
|
|
let instr = self.fetch(mem, self.regs.curr_pc as u64)?;
|
|
|
|
if self.should_service_interrupt() {
|
|
todo!("should_service_interrupt ? then throw exception and return None");
|
|
}
|
|
|
|
self.regs.old_pc = self.regs.curr_pc;
|
|
self.regs.curr_pc = self.regs.next_pc;
|
|
self.regs.next_pc += 4;
|
|
|
|
Some(instr)
|
|
}
|
|
|
|
fn step(&mut self, mem: &Memory) -> Result<u32, Error> {
|
|
if let Some(instr) = self.fetch_then_advance(mem) {
|
|
self.decode_execute(instr)?;
|
|
}
|
|
|
|
Ok(1)
|
|
}
|
|
|
|
fn decode_execute(&mut self, instr: Instruction) -> Result<(), Error> {
|
|
match instr.opcode() {
|
|
_ => Err(Error {
|
|
severity: Severity::Error,
|
|
err_type: UnhandledInstruction(instr),
|
|
}),
|
|
}
|
|
}
|
|
|
|
fn reset(&mut self) {
|
|
todo!("reset")
|
|
}
|
|
}
|