Move utils to separate crate
This commit is contained in:
Generated
+8
@@ -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",
|
||||
]
|
||||
|
||||
@@ -5,3 +5,4 @@ edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
proc-bitfield = "0.5.3"
|
||||
utils = { path = "../utils" }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
pub mod cpu;
|
||||
pub mod instruction;
|
||||
pub mod interpreter;
|
||||
pub mod mem;
|
||||
pub mod registers;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
|
||||
@@ -2,4 +2,3 @@
|
||||
|
||||
pub mod core;
|
||||
pub mod scheduler;
|
||||
pub mod utils;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
pub mod access;
|
||||
pub mod error;
|
||||
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "utils"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
proc-bitfield = "0.5.3"
|
||||
@@ -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<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)
|
||||
}
|
||||
}
|
||||
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<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}")
|
||||
}
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
@@ -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<BranchType> {
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod error;
|
||||
pub mod instruction;
|
||||
Reference in New Issue
Block a user