From 08d1e9c797d928eb8b7d6cdbdbe1b8b19e8b96dc Mon Sep 17 00:00:00 2001 From: iris Date: Tue, 18 Aug 2026 10:01:06 +0200 Subject: [PATCH] Move utils to separate crate --- Cargo.lock | 8 + backend/Cargo.toml | 1 + backend/src/core.rs | 1 - backend/src/core/cpu.rs | 6 +- backend/src/core/interpreter.rs | 23 +-- backend/src/lib.rs | 1 - backend/src/utils/access.rs | 6 - backend/src/utils/mod.rs | 2 - utils/Cargo.toml | 7 + {backend/src/core => utils}/instruction.rs | 0 {backend/src/utils => utils/src}/error.rs | 194 ++++++++++----------- utils/src/instruction.rs | 184 +++++++++++++++++++ utils/src/lib.rs | 2 + 13 files changed, 309 insertions(+), 126 deletions(-) delete mode 100644 backend/src/utils/access.rs delete mode 100644 backend/src/utils/mod.rs create mode 100644 utils/Cargo.toml rename {backend/src/core => utils}/instruction.rs (100%) rename {backend/src/utils => utils/src}/error.rs (94%) create mode 100644 utils/src/instruction.rs create mode 100644 utils/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index e0af456..96fee29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,7 @@ name = "backend" version = "0.1.0" dependencies = [ "proc-bitfield", + "utils", ] [[package]] @@ -77,3 +78,10 @@ name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "utils" +version = "0.1.0" +dependencies = [ + "proc-bitfield", +] diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 31e8ba8..a3e896f 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -5,3 +5,4 @@ edition = "2024" [dependencies] proc-bitfield = "0.5.3" +utils = { path = "../utils" } diff --git a/backend/src/core.rs b/backend/src/core.rs index 0c17cac..d50eab0 100644 --- a/backend/src/core.rs +++ b/backend/src/core.rs @@ -1,5 +1,4 @@ pub mod cpu; -pub mod instruction; pub mod interpreter; pub mod mem; pub mod registers; diff --git a/backend/src/core/cpu.rs b/backend/src/core/cpu.rs index 7d12b4e..3ddcc1b 100644 --- a/backend/src/core/cpu.rs +++ b/backend/src/core/cpu.rs @@ -1,7 +1,5 @@ -use crate::{ - core::{instruction::Instruction, mem::Memory, registers::Registers}, - utils::error::Error, -}; +use crate::core::{mem::Memory, registers::Registers}; +use utils::{error::Error, instruction::Instruction}; pub enum CpuType { Interpreter, diff --git a/backend/src/core/interpreter.rs b/backend/src/core/interpreter.rs index a8d0608..edf5cfe 100644 --- a/backend/src/core/interpreter.rs +++ b/backend/src/core/interpreter.rs @@ -1,14 +1,11 @@ -use crate::{ - core::{ - cpu::{Cpu, CpuType::*}, - instruction::Instruction, - mem::Memory, - registers::Registers, - }, - utils::{ - access::is_address_error, - error::{Error, Severity, Type::UnhandledInstruction}, - }, +use crate::core::{ + cpu::{Cpu, CpuType::*}, + mem::Memory, + registers::Registers, +}; +use utils::{ + error::{Error, Severity, Type::UnhandledInstruction}, + instruction::Instruction, }; pub struct Interpreter { @@ -45,9 +42,7 @@ impl Cpu for Interpreter { self.prev_delay_slot = self.delay_slot; self.delay_slot = false; - if is_address_error(&self.regs, 0b11, self.regs.curr_pc) { - todo!("is_address_error ? then throw exception and return None"); - } + todo!("is_address_error ? then throw exception and return None"); let instr = self.fetch(mem, self.regs.curr_pc as u64)?; diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 920371e..a8f1ef4 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -2,4 +2,3 @@ pub mod core; pub mod scheduler; -pub mod utils; diff --git a/backend/src/utils/access.rs b/backend/src/utils/access.rs deleted file mode 100644 index 1354f71..0000000 --- a/backend/src/utils/access.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::core::registers::Registers; - -pub fn is_address_error(_regs: &Registers, mask: u8, vaddr: i64) -> bool { - vaddr & mask as i64 != 0 - // || (!regs.cop0.is64BitAddressing && s32(vaddr) != vaddr) -} diff --git a/backend/src/utils/mod.rs b/backend/src/utils/mod.rs deleted file mode 100644 index 92fe523..0000000 --- a/backend/src/utils/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod access; -pub mod error; diff --git a/utils/Cargo.toml b/utils/Cargo.toml new file mode 100644 index 0000000..f6c4395 --- /dev/null +++ b/utils/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "utils" +version = "0.1.0" +edition = "2024" + +[dependencies] +proc-bitfield = "0.5.3" diff --git a/backend/src/core/instruction.rs b/utils/instruction.rs similarity index 100% rename from backend/src/core/instruction.rs rename to utils/instruction.rs diff --git a/backend/src/utils/error.rs b/utils/src/error.rs similarity index 94% rename from backend/src/utils/error.rs rename to utils/src/error.rs index 5fa588f..c371506 100644 --- a/backend/src/utils/error.rs +++ b/utils/src/error.rs @@ -1,98 +1,96 @@ -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), - U16(Option), - U32(Option), - U64(Option), -} - -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 = std::result::Result; - -#[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) - } -} +use crate::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), + U16(Option), + U32(Option), + U64(Option), +} + +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}") + } +} + +#[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) + } +} diff --git a/utils/src/instruction.rs b/utils/src/instruction.rs new file mode 100644 index 0000000..dea63d6 --- /dev/null +++ b/utils/src/instruction.rs @@ -0,0 +1,184 @@ +use proc_bitfield::bitfield; + +bitfield! { + #[derive(Clone, Copy, Debug)] + pub struct Instruction(pub u32): FromStorage, IntoStorage, DerefStorage { + pub special: u8 @ 0..6, + pub regimm: u8 @ 16..21, + pub rt: u8 @ 16..21, + pub cop_rt: u8 @ 16..21, + pub rs: u8 @ 21..26, + pub cop_rs: u8 @ 21..26, + pub opcode: u8 @ 26..32, + pub imm: u16 @ 0..16, + pub target: u32 @ 0..26, + pub funct: u8 @ 0..6, + pub sa: u8 @ 6..11, + pub rd: u8 @ 11..16, + } +} + +pub enum BranchType { + Pure, + Likely, + Link, + LinkLikely, +} + +impl Instruction { + pub fn get_branch(self) -> Option { + match self.opcode() { + Instruction::BEQ | Instruction::BNE | Instruction::BLEZ | Instruction::BGTZ => { + Some(BranchType::Pure) + } + Instruction::BEQL | Instruction::BNEL | Instruction::BLEZL | Instruction::BGTZL => { + Some(BranchType::Likely) + } + Instruction::REGIMM => match self.regimm() { + Instruction::BLTZ | Instruction::BGEZ => Some(BranchType::Pure), + Instruction::BLTZAL | Instruction::BGEZAL => Some(BranchType::Link), + Instruction::BLTZL | Instruction::BGEZL => Some(BranchType::Likely), + Instruction::BLTZALL | Instruction::BGEZALL => Some(BranchType::LinkLikely), + _ => None, + }, + Instruction::COP1 => { + if self.cop_rs() == 8 { + match self.cop_rt() { + 0 | 1 => Some(BranchType::Pure), + 2 | 3 => Some(BranchType::Likely), + _ => None, + } + } else { + None + } + } + _ => None, + } + } + + pub const SPECIAL: u8 = 0b000000; + pub const REGIMM: u8 = 0b000001; + pub const J: u8 = 0b000010; + pub const JAL: u8 = 0b000011; + pub const BEQ: u8 = 0b000100; + pub const BNE: u8 = 0b000101; + pub const BLEZ: u8 = 0b000110; + pub const BGTZ: u8 = 0b000111; + pub const ADDI: u8 = 0b001000; + pub const ADDIU: u8 = 0b001001; + pub const SLTI: u8 = 0b001010; + pub const SLTIU: u8 = 0b001011; + pub const ANDI: u8 = 0b001100; + pub const ORI: u8 = 0b001101; + pub const XORI: u8 = 0b001110; + pub const LUI: u8 = 0b001111; + pub const COP0: u8 = 0b010000; + pub const COP1: u8 = 0b010001; + pub const COP2: u8 = 0b010010; + pub const BEQL: u8 = 0b010100; + pub const BNEL: u8 = 0b010101; + pub const BLEZL: u8 = 0b010110; + pub const BGTZL: u8 = 0b010111; + pub const DADDI: u8 = 0b011000; + pub const DADDIU: u8 = 0b011001; + pub const LDL: u8 = 0b011010; + pub const LDR: u8 = 0b011011; + pub const LB: u8 = 0b100000; + pub const LH: u8 = 0b100001; + pub const LWL: u8 = 0b100010; + pub const LW: u8 = 0b100011; + pub const LBU: u8 = 0b100100; + pub const LHU: u8 = 0b100101; + pub const LWR: u8 = 0b100110; + pub const LWU: u8 = 0b100111; + pub const SB: u8 = 0b101000; + pub const SH: u8 = 0b101001; + pub const SWL: u8 = 0b101010; + pub const SW: u8 = 0b101011; + pub const SDL: u8 = 0b101100; + pub const SDR: u8 = 0b101101; + pub const SWR: u8 = 0b101110; + pub const CACHE: u8 = 0b101111; + pub const LL: u8 = 0b110000; + pub const LWC1: u8 = 0b110001; + pub const LWC2: u8 = 0b110010; + pub const LLD: u8 = 0b110100; + pub const LDC1: u8 = 0b110101; + pub const LDC2: u8 = 0b110110; + pub const LD: u8 = 0b110111; + pub const SC: u8 = 0b111000; + pub const SWC1: u8 = 0b111001; + pub const SWC2: u8 = 0b111010; + pub const SCD: u8 = 0b111100; + pub const SDC1: u8 = 0b111101; + pub const SDC2: u8 = 0b111110; + pub const SD: u8 = 0b111111; + // special + pub const SLL: u8 = 0b000000; + pub const SRL: u8 = 0b000010; + pub const SRA: u8 = 0b000011; + pub const SLLV: u8 = 0b000100; + pub const SRLV: u8 = 0b000110; + pub const SRAV: u8 = 0b000111; + pub const JR: u8 = 0b001000; + pub const JALR: u8 = 0b001001; + pub const SYSCALL: u8 = 0b001100; + pub const BREAK: u8 = 0b001101; + pub const SYNC: u8 = 0b001111; + pub const MFHI: u8 = 0b010000; + pub const MTHI: u8 = 0b010001; + pub const MFLO: u8 = 0b010010; + pub const MTLO: u8 = 0b010011; + pub const DSLLV: u8 = 0b010100; + pub const DSRLV: u8 = 0b010110; + pub const DSRAV: u8 = 0b010111; + pub const MULT: u8 = 0b011000; + pub const MULTU: u8 = 0b011001; + pub const DIV: u8 = 0b011010; + pub const DIVU: u8 = 0b011011; + pub const DMULT: u8 = 0b011100; + pub const DMULTU: u8 = 0b011101; + pub const DDIV: u8 = 0b011110; + pub const DDIVU: u8 = 0b011111; + pub const ADD: u8 = 0b100000; + pub const ADDU: u8 = 0b100001; + pub const SUB: u8 = 0b100010; + pub const SUBU: u8 = 0b100011; + pub const AND: u8 = 0b100100; + pub const OR: u8 = 0b100101; + pub const XOR: u8 = 0b100110; + pub const NOR: u8 = 0b100111; + pub const SLT: u8 = 0b101010; + pub const SLTU: u8 = 0b101011; + pub const DADD: u8 = 0b101100; + pub const DADDU: u8 = 0b101101; + pub const DSUB: u8 = 0b101110; + pub const DSUBU: u8 = 0b101111; + pub const TGE: u8 = 0b110000; + pub const TGEU: u8 = 0b110001; + pub const TLT: u8 = 0b110010; + pub const TLTU: u8 = 0b110011; + pub const TEQ: u8 = 0b110100; + pub const TNE: u8 = 0b110110; + pub const DSLL: u8 = 0b111000; + pub const DSRL: u8 = 0b111010; + pub const DSRA: u8 = 0b111011; + pub const DSLL32: u8 = 0b111100; + pub const DSRL32: u8 = 0b111110; + pub const DSRA32: u8 = 0b111111; + // regimm + pub const BLTZ: u8 = 0b00000; + pub const BGEZ: u8 = 0b00001; + pub const BLTZL: u8 = 0b00010; + pub const BGEZL: u8 = 0b00011; + pub const TGEI: u8 = 0b01000; + pub const TGEIU: u8 = 0b01001; + pub const TLTI: u8 = 0b01010; + pub const TLTIU: u8 = 0b01011; + pub const TEQI: u8 = 0b01100; + pub const TNEI: u8 = 0b01110; + pub const BLTZAL: u8 = 0b10000; + pub const BGEZAL: u8 = 0b10001; + pub const BLTZALL: u8 = 0b10010; + pub const BGEZALL: u8 = 0b10011; +} diff --git a/utils/src/lib.rs b/utils/src/lib.rs new file mode 100644 index 0000000..4225301 --- /dev/null +++ b/utils/src/lib.rs @@ -0,0 +1,2 @@ +pub mod error; +pub mod instruction;