implement error type and new ideas

This commit is contained in:
2026-08-17 21:32:01 +02:00
parent 34078089f1
commit c21c4af378
5 changed files with 246 additions and 135 deletions
+6 -3
View File
@@ -1,4 +1,7 @@
use crate::core::{instruction::Instruction, mem::Memory, registers::Registers}; use crate::{
core::{instruction::Instruction, mem::Memory, registers::Registers},
utils::error::Error,
};
pub enum CpuType { pub enum CpuType {
Interpreter, Interpreter,
@@ -16,11 +19,11 @@ pub trait Cpu {
fn fetch_then_advance(&mut self, _: &Memory) -> Option<Instruction> { fn fetch_then_advance(&mut self, _: &Memory) -> Option<Instruction> {
None None
} }
fn execute(&mut self, mem: &Memory) -> Result<u32, String>; fn step(&mut self, mem: &Memory) -> Result<u32, Error>;
fn advance(&mut self) -> bool { fn advance(&mut self) -> bool {
false false
} }
fn decode(&mut self, instr: Instruction) -> Result<(), String>; fn decode_execute(&mut self, instr: Instruction) -> Result<(), Error>;
fn reset(&mut self); fn reset(&mut self);
fn should_service_interrupt(&self) -> bool; fn should_service_interrupt(&self) -> bool;
fn update_compare_interrupt(&mut self); fn update_compare_interrupt(&mut self);
+127 -126
View File
@@ -1,7 +1,8 @@
use proc_bitfield::bitfield; use proc_bitfield::bitfield;
bitfield! { bitfield! {
pub struct Instruction(pub u32): Debug, FromStorage, IntoStorage, DerefStorage { #[derive(Clone, Copy, Debug)]
pub struct Instruction(pub u32): FromStorage, IntoStorage, DerefStorage {
pub special: u8 @ 0..6, pub special: u8 @ 0..6,
pub regimm: u8 @ 16..21, pub regimm: u8 @ 16..21,
pub rt: u8 @ 16..21, pub rt: u8 @ 16..21,
@@ -17,7 +18,7 @@ bitfield! {
} }
} }
enum BranchType { pub enum BranchType {
Pure, Pure,
Likely, Likely,
Link, Link,
@@ -25,7 +26,7 @@ enum BranchType {
} }
impl Instruction { impl Instruction {
fn get_branch(self) -> Option<BranchType> { pub fn get_branch(self) -> Option<BranchType> {
match self.opcode() { match self.opcode() {
Instruction::BEQ | Instruction::BNE | Instruction::BLEZ | Instruction::BGTZ => { Instruction::BEQ | Instruction::BNE | Instruction::BLEZ | Instruction::BGTZ => {
Some(BranchType::Pure) Some(BranchType::Pure)
@@ -55,129 +56,129 @@ impl Instruction {
} }
} }
const SPECIAL: u8 = 0b000000; pub const SPECIAL: u8 = 0b000000;
const REGIMM: u8 = 0b000001; pub const REGIMM: u8 = 0b000001;
const J: u8 = 0b000010; pub const J: u8 = 0b000010;
const JAL: u8 = 0b000011; pub const JAL: u8 = 0b000011;
const BEQ: u8 = 0b000100; pub const BEQ: u8 = 0b000100;
const BNE: u8 = 0b000101; pub const BNE: u8 = 0b000101;
const BLEZ: u8 = 0b000110; pub const BLEZ: u8 = 0b000110;
const BGTZ: u8 = 0b000111; pub const BGTZ: u8 = 0b000111;
const ADDI: u8 = 0b001000; pub const ADDI: u8 = 0b001000;
const ADDIU: u8 = 0b001001; pub const ADDIU: u8 = 0b001001;
const SLTI: u8 = 0b001010; pub const SLTI: u8 = 0b001010;
const SLTIU: u8 = 0b001011; pub const SLTIU: u8 = 0b001011;
const ANDI: u8 = 0b001100; pub const ANDI: u8 = 0b001100;
const ORI: u8 = 0b001101; pub const ORI: u8 = 0b001101;
const XORI: u8 = 0b001110; pub const XORI: u8 = 0b001110;
const LUI: u8 = 0b001111; pub const LUI: u8 = 0b001111;
const COP0: u8 = 0b010000; pub const COP0: u8 = 0b010000;
const COP1: u8 = 0b010001; pub const COP1: u8 = 0b010001;
const COP2: u8 = 0b010010; pub const COP2: u8 = 0b010010;
const BEQL: u8 = 0b010100; pub const BEQL: u8 = 0b010100;
const BNEL: u8 = 0b010101; pub const BNEL: u8 = 0b010101;
const BLEZL: u8 = 0b010110; pub const BLEZL: u8 = 0b010110;
const BGTZL: u8 = 0b010111; pub const BGTZL: u8 = 0b010111;
const DADDI: u8 = 0b011000; pub const DADDI: u8 = 0b011000;
const DADDIU: u8 = 0b011001; pub const DADDIU: u8 = 0b011001;
const LDL: u8 = 0b011010; pub const LDL: u8 = 0b011010;
const LDR: u8 = 0b011011; pub const LDR: u8 = 0b011011;
const LB: u8 = 0b100000; pub const LB: u8 = 0b100000;
const LH: u8 = 0b100001; pub const LH: u8 = 0b100001;
const LWL: u8 = 0b100010; pub const LWL: u8 = 0b100010;
const LW: u8 = 0b100011; pub const LW: u8 = 0b100011;
const LBU: u8 = 0b100100; pub const LBU: u8 = 0b100100;
const LHU: u8 = 0b100101; pub const LHU: u8 = 0b100101;
const LWR: u8 = 0b100110; pub const LWR: u8 = 0b100110;
const LWU: u8 = 0b100111; pub const LWU: u8 = 0b100111;
const SB: u8 = 0b101000; pub const SB: u8 = 0b101000;
const SH: u8 = 0b101001; pub const SH: u8 = 0b101001;
const SWL: u8 = 0b101010; pub const SWL: u8 = 0b101010;
const SW: u8 = 0b101011; pub const SW: u8 = 0b101011;
const SDL: u8 = 0b101100; pub const SDL: u8 = 0b101100;
const SDR: u8 = 0b101101; pub const SDR: u8 = 0b101101;
const SWR: u8 = 0b101110; pub const SWR: u8 = 0b101110;
const CACHE: u8 = 0b101111; pub const CACHE: u8 = 0b101111;
const LL: u8 = 0b110000; pub const LL: u8 = 0b110000;
const LWC1: u8 = 0b110001; pub const LWC1: u8 = 0b110001;
const LWC2: u8 = 0b110010; pub const LWC2: u8 = 0b110010;
const LLD: u8 = 0b110100; pub const LLD: u8 = 0b110100;
const LDC1: u8 = 0b110101; pub const LDC1: u8 = 0b110101;
const LDC2: u8 = 0b110110; pub const LDC2: u8 = 0b110110;
const LD: u8 = 0b110111; pub const LD: u8 = 0b110111;
const SC: u8 = 0b111000; pub const SC: u8 = 0b111000;
const SWC1: u8 = 0b111001; pub const SWC1: u8 = 0b111001;
const SWC2: u8 = 0b111010; pub const SWC2: u8 = 0b111010;
const SCD: u8 = 0b111100; pub const SCD: u8 = 0b111100;
const SDC1: u8 = 0b111101; pub const SDC1: u8 = 0b111101;
const SDC2: u8 = 0b111110; pub const SDC2: u8 = 0b111110;
const SD: u8 = 0b111111; pub const SD: u8 = 0b111111;
// special // special
const SLL: u8 = 0b000000; pub const SLL: u8 = 0b000000;
const SRL: u8 = 0b000010; pub const SRL: u8 = 0b000010;
const SRA: u8 = 0b000011; pub const SRA: u8 = 0b000011;
const SLLV: u8 = 0b000100; pub const SLLV: u8 = 0b000100;
const SRLV: u8 = 0b000110; pub const SRLV: u8 = 0b000110;
const SRAV: u8 = 0b000111; pub const SRAV: u8 = 0b000111;
const JR: u8 = 0b001000; pub const JR: u8 = 0b001000;
const JALR: u8 = 0b001001; pub const JALR: u8 = 0b001001;
const SYSCALL: u8 = 0b001100; pub const SYSCALL: u8 = 0b001100;
const BREAK: u8 = 0b001101; pub const BREAK: u8 = 0b001101;
const SYNC: u8 = 0b001111; pub const SYNC: u8 = 0b001111;
const MFHI: u8 = 0b010000; pub const MFHI: u8 = 0b010000;
const MTHI: u8 = 0b010001; pub const MTHI: u8 = 0b010001;
const MFLO: u8 = 0b010010; pub const MFLO: u8 = 0b010010;
const MTLO: u8 = 0b010011; pub const MTLO: u8 = 0b010011;
const DSLLV: u8 = 0b010100; pub const DSLLV: u8 = 0b010100;
const DSRLV: u8 = 0b010110; pub const DSRLV: u8 = 0b010110;
const DSRAV: u8 = 0b010111; pub const DSRAV: u8 = 0b010111;
const MULT: u8 = 0b011000; pub const MULT: u8 = 0b011000;
const MULTU: u8 = 0b011001; pub const MULTU: u8 = 0b011001;
const DIV: u8 = 0b011010; pub const DIV: u8 = 0b011010;
const DIVU: u8 = 0b011011; pub const DIVU: u8 = 0b011011;
const DMULT: u8 = 0b011100; pub const DMULT: u8 = 0b011100;
const DMULTU: u8 = 0b011101; pub const DMULTU: u8 = 0b011101;
const DDIV: u8 = 0b011110; pub const DDIV: u8 = 0b011110;
const DDIVU: u8 = 0b011111; pub const DDIVU: u8 = 0b011111;
const ADD: u8 = 0b100000; pub const ADD: u8 = 0b100000;
const ADDU: u8 = 0b100001; pub const ADDU: u8 = 0b100001;
const SUB: u8 = 0b100010; pub const SUB: u8 = 0b100010;
const SUBU: u8 = 0b100011; pub const SUBU: u8 = 0b100011;
const AND: u8 = 0b100100; pub const AND: u8 = 0b100100;
const OR: u8 = 0b100101; pub const OR: u8 = 0b100101;
const XOR: u8 = 0b100110; pub const XOR: u8 = 0b100110;
const NOR: u8 = 0b100111; pub const NOR: u8 = 0b100111;
const SLT: u8 = 0b101010; pub const SLT: u8 = 0b101010;
const SLTU: u8 = 0b101011; pub const SLTU: u8 = 0b101011;
const DADD: u8 = 0b101100; pub const DADD: u8 = 0b101100;
const DADDU: u8 = 0b101101; pub const DADDU: u8 = 0b101101;
const DSUB: u8 = 0b101110; pub const DSUB: u8 = 0b101110;
const DSUBU: u8 = 0b101111; pub const DSUBU: u8 = 0b101111;
const TGE: u8 = 0b110000; pub const TGE: u8 = 0b110000;
const TGEU: u8 = 0b110001; pub const TGEU: u8 = 0b110001;
const TLT: u8 = 0b110010; pub const TLT: u8 = 0b110010;
const TLTU: u8 = 0b110011; pub const TLTU: u8 = 0b110011;
const TEQ: u8 = 0b110100; pub const TEQ: u8 = 0b110100;
const TNE: u8 = 0b110110; pub const TNE: u8 = 0b110110;
const DSLL: u8 = 0b111000; pub const DSLL: u8 = 0b111000;
const DSRL: u8 = 0b111010; pub const DSRL: u8 = 0b111010;
const DSRA: u8 = 0b111011; pub const DSRA: u8 = 0b111011;
const DSLL32: u8 = 0b111100; pub const DSLL32: u8 = 0b111100;
const DSRL32: u8 = 0b111110; pub const DSRL32: u8 = 0b111110;
const DSRA32: u8 = 0b111111; pub const DSRA32: u8 = 0b111111;
// regimm // regimm
const BLTZ: u8 = 0b00000; pub const BLTZ: u8 = 0b00000;
const BGEZ: u8 = 0b00001; pub const BGEZ: u8 = 0b00001;
const BLTZL: u8 = 0b00010; pub const BLTZL: u8 = 0b00010;
const BGEZL: u8 = 0b00011; pub const BGEZL: u8 = 0b00011;
const TGEI: u8 = 0b01000; pub const TGEI: u8 = 0b01000;
const TGEIU: u8 = 0b01001; pub const TGEIU: u8 = 0b01001;
const TLTI: u8 = 0b01010; pub const TLTI: u8 = 0b01010;
const TLTIU: u8 = 0b01011; pub const TLTIU: u8 = 0b01011;
const TEQI: u8 = 0b01100; pub const TEQI: u8 = 0b01100;
const TNEI: u8 = 0b01110; pub const TNEI: u8 = 0b01110;
const BLTZAL: u8 = 0b10000; pub const BLTZAL: u8 = 0b10000;
const BGEZAL: u8 = 0b10001; pub const BGEZAL: u8 = 0b10001;
const BLTZALL: u8 = 0b10010; pub const BLTZALL: u8 = 0b10010;
const BGEZALL: u8 = 0b10011; pub const BGEZALL: u8 = 0b10011;
} }
+13 -5
View File
@@ -5,7 +5,10 @@ use crate::{
mem::Memory, mem::Memory,
registers::Registers, registers::Registers,
}, },
utils::access::is_address_error, utils::{
access::is_address_error,
error::{Error, Severity, Type::UnhandledInstruction},
},
}; };
pub struct Interpreter { pub struct Interpreter {
@@ -59,16 +62,21 @@ impl Cpu for Interpreter {
Some(instr) Some(instr)
} }
fn execute(&mut self, mem: &Memory) -> Result<u32, String> { 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(instr)?; self.decode_execute(instr)?;
} }
Ok(1) Ok(1)
} }
fn decode(&mut self, instr: Instruction) -> Result<(), String> { fn decode_execute(&mut self, instr: Instruction) -> Result<(), Error> {
todo!("decode") match instr.opcode() {
_ => Err(Error {
severity: Severity::Error,
err_type: UnhandledInstruction(instr),
}),
}
} }
fn reset(&mut self) { fn reset(&mut self) {
+98
View File
@@ -0,0 +1,98 @@
use crate::core::instruction::Instruction;
use std::fmt;
#[derive(Debug, Clone, Copy)]
pub enum Severity {
Warning,
Error,
Fatal,
}
impl fmt::Display for Severity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let sev = match self {
Self::Warning => "Warning",
Self::Error => "Error",
Self::Fatal => "Fatal",
};
write!(f, "{sev}")
}
}
#[derive(Debug, Clone, Copy)]
pub enum AccessType {
U8(Option<u8>),
U16(Option<u16>),
U32(Option<u32>),
U64(Option<u64>),
}
impl fmt::Display for AccessType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
&Self::U8(val) => {
if let Some(val) = val {
write!(f, "write8 with value {val:02X}")
} else {
write!(f, "read8")
}
}
&Self::U16(val) => {
if let Some(val) = val {
write!(f, "write16 with value {val:04X}")
} else {
write!(f, "read16")
}
}
&Self::U32(val) => {
if let Some(val) = val {
write!(f, "write32 with value {val:08X}")
} else {
write!(f, "read32")
}
}
&Self::U64(val) => {
if let Some(val) = val {
write!(f, "write64 with value {val:08X}")
} else {
write!(f, "read64")
}
}
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Type {
UnhandledInstruction(Instruction),
UnhandledMemoryAccess(u32, AccessType),
}
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let err_type = match self {
Type::UnhandledInstruction(instr) => {
format!("Unhandled instruction: {:02X}", instr.opcode())
}
Type::UnhandledMemoryAccess(addr, access) => {
format!("Unhandled addr @ {addr:08X} for {access}")
}
};
write!(f, "{err_type}")
}
}
type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Clone, Copy)]
pub struct Error {
pub severity: Severity,
pub err_type: Type,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]: {}", self.severity, self.err_type)
}
}
+2 -1
View File
@@ -1 +1,2 @@
pub mod access; pub mod access;
pub mod error;