better structure + no need for lifetime specifier in Error. TODO: figure out better name for aforementioned

This commit is contained in:
2026-08-19 22:28:21 +02:00
parent dd38da6dea
commit 81590e5f83
5 changed files with 45 additions and 58 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ pub trait Cpu {
fn fetch_then_advance(&mut self, _: &Memory) -> Option<Instruction> { fn fetch_then_advance(&mut self, _: &Memory) -> Option<Instruction> {
None None
} }
fn step(&mut self, mem: &Memory) -> Result<u32, Error<'_>>; fn step(&mut self, mem: &Memory) -> Result<u32, Error>;
fn advance(&mut self) -> bool { fn advance(&mut self) -> bool {
false false
} }
+2 -3
View File
@@ -5,8 +5,7 @@ use crate::core::{
}; };
use utils::{error::Error, instruction::Instruction}; use utils::{error::Error, instruction::Instruction};
pub mod decode; mod isa;
pub mod instructions;
pub struct Interpreter { pub struct Interpreter {
regs: Registers, regs: Registers,
@@ -65,7 +64,7 @@ impl Cpu for Interpreter {
Some(instr) Some(instr)
} }
fn step(&mut self, mem: &Memory) -> Result<u32, Error<'_>> { fn step(&mut self, mem: &Memory) -> Result<u32, Error> {
if let Some(instr) = self.fetch_then_advance(mem) { if let Some(instr) = self.fetch_then_advance(mem) {
self.decode_execute(instr)?; self.decode_execute(instr)?;
} }
-30
View File
@@ -1,30 +0,0 @@
use utils::{
error::{Error, Severity, Type::UnhandledInstruction},
instruction::Instruction,
};
use crate::core::interpreter::Interpreter;
impl Interpreter {
pub fn decode_special(&mut self, instr: Instruction) -> Result<(), Error<'_>> {
match instr.special() {
Instruction::SLL => Ok(self.sll(instr)),
Instruction::ADD => Ok(self.add(instr)),
Instruction::ADDU => Ok(self.addu(instr)),
_ => Err(Error {
severity: Severity::Fatal,
err_type: UnhandledInstruction("CPU::SpecialFunction", instr),
}),
}
}
pub fn decode_execute(&mut self, instr: Instruction) -> Result<(), Error<'_>> {
match instr.opcode() {
Instruction::SPECIAL => self.decode_special(instr),
_ => Err(Error {
severity: Severity::Error,
err_type: UnhandledInstruction("CPU::Opcode", instr),
}),
}
}
}
@@ -1,6 +1,3 @@
#![allow(dead_code)]
#![allow(unused)]
use utils::{ use utils::{
error::{Error, Severity, Type::UnhandledInstruction}, error::{Error, Severity, Type::UnhandledInstruction},
instruction::Instruction, instruction::Instruction,
@@ -9,7 +6,29 @@ use utils::{
use crate::core::interpreter::Interpreter; use crate::core::interpreter::Interpreter;
impl Interpreter { impl Interpreter {
pub fn add(&mut self, instr: Instruction) { fn decode_special(&mut self, instr: Instruction) -> Result<(), Error> {
match instr.special() {
Instruction::SLL => Ok(self.sll(instr)),
Instruction::ADD => Ok(self.add(instr)),
Instruction::ADDU => Ok(self.addu(instr)),
_ => Err(Error {
severity: Severity::Fatal,
err_type: UnhandledInstruction("CPU::SpecialFunction", instr),
}),
}
}
pub fn decode_execute(&mut self, instr: Instruction) -> Result<(), Error> {
match instr.opcode() {
Instruction::SPECIAL => self.decode_special(instr),
_ => Err(Error {
severity: Severity::Error,
err_type: UnhandledInstruction("CPU::Opcode", instr),
}),
}
}
fn add(&mut self, instr: Instruction) {
let rs = self.regs.read(instr.rs()) as u32; let rs = self.regs.read(instr.rs()) as u32;
let rt = self.regs.read(instr.rt()) as u32; let rt = self.regs.read(instr.rt()) as u32;
let (rd, overflow) = rs.overflowing_add(rt); let (rd, overflow) = rs.overflowing_add(rt);
@@ -20,13 +39,13 @@ impl Interpreter {
self.regs.write(instr.rd(), rd as i32); self.regs.write(instr.rd(), rd as i32);
} }
pub fn addu(&mut self, instr: Instruction) { fn addu(&mut self, instr: Instruction) {
let rs = self.regs.read(instr.rs()) as i32; let rs = self.regs.read(instr.rs()) as i32;
let rt = self.regs.read(instr.rt()) as i32; let rt = self.regs.read(instr.rt()) as i32;
self.regs.write(instr.rd(), rs + rt); self.regs.write(instr.rd(), rs + rt);
} }
pub fn addi(&mut self, instr: Instruction) { fn addi(&mut self, instr: Instruction) {
let rs = self.regs.read(instr.rs()) as u32; let rs = self.regs.read(instr.rs()) as u32;
let imm = instr.imm() as i16 as i32 as u32; let imm = instr.imm() as i16 as i32 as u32;
let (rt, overflow) = rs.overflowing_add(imm); let (rt, overflow) = rs.overflowing_add(imm);
@@ -36,14 +55,13 @@ impl Interpreter {
self.regs.write(instr.rt(), rt as i32); self.regs.write(instr.rt(), rt as i32);
} }
fn addiu(&mut self, instr: Instruction) {
pub fn addiu(&mut self, instr: Instruction) {
let rs = self.regs.read(instr.rs()) as i32; let rs = self.regs.read(instr.rs()) as i32;
let imm = instr.imm() as i16 as i32; let imm = instr.imm() as i16 as i32;
self.regs.write(instr.rt(), rs + imm); self.regs.write(instr.rt(), rs + imm);
} }
pub fn dadd(&mut self, instr: Instruction) { fn dadd(&mut self, instr: Instruction) {
let rs = self.regs.read(instr.rs()) as u64; let rs = self.regs.read(instr.rs()) as u64;
let rt = self.regs.read(instr.rt()) as u64; let rt = self.regs.read(instr.rt()) as u64;
let (rd, overflow) = rs.overflowing_add(rt); let (rd, overflow) = rs.overflowing_add(rt);
@@ -54,13 +72,13 @@ impl Interpreter {
self.regs.write(instr.rd(), rd as i64); self.regs.write(instr.rd(), rd as i64);
} }
pub fn daddu(&mut self, instr: Instruction) { fn daddu(&mut self, instr: Instruction) {
let rs = self.regs.read(instr.rs()) as i64; let rs = self.regs.read(instr.rs()) as i64;
let rt = self.regs.read(instr.rt()) as i64; let rt = self.regs.read(instr.rt()) as i64;
self.regs.write(instr.rd(), rs + rt); self.regs.write(instr.rd(), rs + rt);
} }
pub fn daddi(&mut self, instr: Instruction) { fn daddi(&mut self, instr: Instruction) {
let rs = self.regs.read(instr.rs()) as u64; let rs = self.regs.read(instr.rs()) as u64;
let imm = instr.imm() as i16 as i64 as u64; let imm = instr.imm() as i16 as i64 as u64;
let (rt, overflow) = rs.overflowing_add(imm); let (rt, overflow) = rs.overflowing_add(imm);
@@ -71,7 +89,7 @@ impl Interpreter {
self.regs.write(instr.rt(), rt as i64); self.regs.write(instr.rt(), rt as i64);
} }
pub fn daddiu(&mut self, instr: Instruction) { fn daddiu(&mut self, instr: Instruction) {
let rs = self.regs.read(instr.rs()); let rs = self.regs.read(instr.rs());
let imm = instr.imm() as i16 as i64; let imm = instr.imm() as i16 as i64;
self.regs.write(instr.rt(), rs + imm); self.regs.write(instr.rt(), rs + imm);
@@ -156,14 +174,14 @@ impl Interpreter {
self.regs.next_pc = addr; self.regs.next_pc = addr;
} }
pub fn b(&mut self, instr: Instruction, cond: bool) { fn b(&mut self, instr: Instruction, cond: bool) {
let imm = instr.imm() as i16; let imm = instr.imm() as i16;
let offset = (imm as i64) << 2; let offset = (imm as i64) << 2;
let address = self.regs.curr_pc + offset; let address = self.regs.curr_pc + offset;
self.branch(cond, address); self.branch(cond, address);
} }
pub fn blink(&mut self, instr: Instruction, cond: bool) { fn blink(&mut self, instr: Instruction, cond: bool) {
self.regs.write(31, self.regs.next_pc); self.regs.write(31, self.regs.next_pc);
let imm = instr.imm() as i16; let imm = instr.imm() as i16;
let offset = (imm as i64) << 2; let offset = (imm as i64) << 2;
@@ -171,14 +189,14 @@ impl Interpreter {
self.branch(cond, address); self.branch(cond, address);
} }
pub fn bl(&mut self, instr: Instruction, cond: bool) { fn bl(&mut self, instr: Instruction, cond: bool) {
let imm = instr.imm() as i16; let imm = instr.imm() as i16;
let offset = (imm as i64) << 2; let offset = (imm as i64) << 2;
let address = self.regs.curr_pc + offset; let address = self.regs.curr_pc + offset;
self.branch_likely(cond, address); self.branch_likely(cond, address);
} }
pub fn bllink(&mut self, instr: Instruction, cond: bool) { fn bllink(&mut self, instr: Instruction, cond: bool) {
self.regs.write(31, self.regs.next_pc); self.regs.write(31, self.regs.next_pc);
let imm = instr.imm() as i16; let imm = instr.imm() as i16;
let offset = (imm as i64) << 2; let offset = (imm as i64) << 2;
@@ -186,12 +204,12 @@ impl Interpreter {
self.branch_likely(cond, address); self.branch_likely(cond, address);
} }
pub fn lui(&mut self, instr: Instruction) { fn lui(&mut self, instr: Instruction) {
let imm = (instr.imm() as i16 as i64) << 16; let imm = (instr.imm() as i16 as i64) << 16;
self.regs.write(instr.rt(), imm); self.regs.write(instr.rt(), imm);
} }
pub fn sll(&mut self, instr: Instruction) { fn sll(&mut self, instr: Instruction) {
if instr.0 == 0 { if instr.0 == 0 {
return; return;
} }
+6 -6
View File
@@ -63,12 +63,12 @@ impl fmt::Display for AccessType {
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Type<'a> { pub enum Type {
UnhandledInstruction(&'a str, Instruction), UnhandledInstruction(&'static str, Instruction),
UnhandledMemoryAccess(u32, AccessType), UnhandledMemoryAccess(u32, AccessType),
} }
impl<'a> fmt::Display for Type<'a> { impl<'a> fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let err_type = match self { let err_type = match self {
Type::UnhandledInstruction(which_type, instr) => { Type::UnhandledInstruction(which_type, instr) => {
@@ -84,12 +84,12 @@ impl<'a> fmt::Display for Type<'a> {
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Error<'a> { pub struct Error {
pub severity: Severity, pub severity: Severity,
pub err_type: Type<'a>, pub err_type: Type,
} }
impl<'a> fmt::Display for Error<'a> { impl<'a> fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]: {}", self.severity, self.err_type) write!(f, "[{}]: {}", self.severity, self.err_type)
} }