implement error type and new ideas
This commit is contained in:
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
pub mod access;
|
pub mod access;
|
||||||
|
pub mod error;
|
||||||
|
|||||||
Reference in New Issue
Block a user