From e52093f9cd84392811aabba84eb1209c4966847e Mon Sep 17 00:00:00 2001 From: "J. Hinchliffe" Date: Sun, 15 Jun 2025 11:58:03 +0100 Subject: [PATCH] common: update Instruction tuples to hold common structs --- src/common/instructions.rs | 169 ++++++++++++++++++++++--------------- 1 file changed, 101 insertions(+), 68 deletions(-) diff --git a/src/common/instructions.rs b/src/common/instructions.rs index da30c15..c083885 100644 --- a/src/common/instructions.rs +++ b/src/common/instructions.rs @@ -154,6 +154,28 @@ impl std::fmt::Display for Register { } } +/// Used by instructions with no arguments. +struct NoArgs {} + +#[derive(Debug, Clone, Copy)] +/// Used by instructions with 2 registers and an immediate argument. +struct ITypeArgs { + immediate: u16, + r1: Register, + /// May not actually be used by some instructions taking an immediate e.g. LUI. This is solved by making the constructor take Options. + r2: Register, +} + +/// Used by instructions not using immediates (besides 5 bit shift values). +#[derive(Debug, Clone, Copy)] +struct RTypeArgs { + sr1: Register, + sr2: Register, + dr: Register, + /// 5 bit shift amount. + shamt: u8, +} + /// TODO: Turn argument tuples into simple structs like `TwoReg`, `TwoRegAndOff` /// etc just to make code a little cleaner. #[derive(Debug, Clone, Copy)] @@ -163,50 +185,50 @@ pub enum Instruction { Nop = 0x0, // Data transfer instructions - Mov(Register, Register) = 0x1, - MovSigned(Register, Register) = 0x2, + Mov(RTypeArgs) = 0x1, + MovSigned(RTypeArgs) = 0x2, - LoadByte(Register, Offset, Register) = 0x3, - LoadByteSigned(Register, Offset, Register) = 0x4, - LoadHalfword(Register, Offset, Register) = 0x5, - LoadHalfwordSigned(Register, Offset, Register) = 0x6, - LoadWord(Register, Offset, Register) = 0x7, + LoadByte(ITypeArgs) = 0x3, + LoadByteSigned(ITypeArgs) = 0x4, + LoadHalfword(ITypeArgs) = 0x5, + LoadHalfwordSigned(ITypeArgs) = 0x6, + LoadWord(ITypeArgs) = 0x7, - StoreByte(Register, Offset, Register) = 0x8, - StoreHalfword(Register, Offset, Register) = 0x9, - StoreWord(Register, Offset, Register) = 0xA, + StoreByte(ITypeArgs) = 0x8, + StoreHalfword(ITypeArgs) = 0x9, + StoreWord(ITypeArgs) = 0xA, - LoadLowerImmediate(Register, Immediate) = 0xB, - LoadUpperImmediate(Register, Immediate) = 0xC, + LoadLowerImmediate(ITypeArgs) = 0xB, + LoadUpperImmediate(ITypeArgs) = 0xC, // Jump Instructions - Jump(Register, Offset) = 0xD, - JumpEq(Register, Offset) = 0xE, - JumpNeq(Register, Offset) = 0xF, - JumpGt(Register, Offset) = 0x10, - JumpGe(Register, Offset) = 0x11, - JumpLt(Register, Offset) = 0x12, - JumpLe(Register, Offset) = 0x13, + Jump(ITypeArgs) = 0xD, + JumpEq(ITypeArgs) = 0xE, + JumpNeq(ITypeArgs) = 0xF, + JumpGt(ITypeArgs) = 0x10, + JumpGe(ITypeArgs) = 0x11, + JumpLt(ITypeArgs) = 0x12, + JumpLe(ITypeArgs) = 0x13, // Comparison - Compare(Register, Register) = 0x14, + Compare(RTypeArgs) = 0x14, // Arithmetic - Add(Register, Register, Register) = 0x19, - Sub(Register, Register, Register) = 0x1A, - Increment(Register) = 0x15, - Decrement(Register) = 0x16, - ShiftLeft(Register, Register, Immediate) = 0x17, - ShiftRight(Register, Register, Immediate) = 0x18, + Add(RTypeArgs) = 0x19, + Sub(RTypeArgs) = 0x1A, + Increment(RTypeArgs) = 0x15, + Decrement(RTypeArgs) = 0x16, + ShiftLeft(RTypeArgs) = 0x17, + ShiftRight(RTypeArgs) = 0x18, // Logical - And(Register, Register, Register) = 0x1B, - Or(Register, Register, Register) = 0x1C, - Not(Register, Register) = 0x1D, - Xor(Register, Register, Register) = 0x1E, - Nand(Register, Register, Register) = 0x1F, - Nor(Register, Register, Register) = 0x20, - Xnor(Register, Register, Register) = 0x21, + And(RTypeArgs) = 0x1B, + Or(RTypeArgs) = 0x1C, + Not(RTypeArgs) = 0x1D, + Xor(RTypeArgs) = 0x1E, + Nand(RTypeArgs) = 0x1F, + Nor(RTypeArgs) = 0x20, + Xnor(RTypeArgs) = 0x21, // Misc Interrupt(Interrupt) = 0x22, @@ -290,46 +312,57 @@ impl Instruction { impl std::fmt::Display for Instruction { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Nop => write!(f, "No Operation"), - Self::Mov(a, b) => write!(f, "MOV {a}, {b}"), - Self::MovSigned(a, b) => write!(f, "MOVS {a}, {b}"), - Self::LoadByte(a, b, c) => write!(f, "LDB {a}, {b}, {c}"), - Self::LoadByteSigned(a, b, c) => write!(f, "LDBS {a}, {b}, {c}"), - Self::LoadHalfword(a, b, c) => write!(f, "LDH {a}, {b}, {c}"), - Self::LoadHalfwordSigned(a, b, c) => write!(f, "LDHS {a}, {b}, {c}"), - Self::LoadWord(a, b, c) => write!(f, "LDW {a}, {b}, {c}"), + Self::Nop => write!(f, "NOP"), + Self::Mov(args) => write!(f, "MOV {}, {}", args.sr1, args.dr), + Self::MovSigned(args) => write!(f, "MOVS {}, {}", args.sr1, args.dr), + Self::LoadByte(args) => write!(f, "LDB {:x}({}), {}", args.immediate, args.r1, args.r2), + Self::LoadByteSigned(args) => { + write!(f, "LDBS {:x}({}), {}", args.immediate, args.r1, args.r2) + } + Self::LoadHalfword(args) => { + write!(f, "LDH {:x}({}), {}", args.immediate, args.r1, args.r2) + } + Self::LoadHalfwordSigned(args) => { + write!(f, "LDHS {:x}({}), {}", args.immediate, args.r1, args.r2) + } + Self::LoadWord(args) => write!(f, "LDW {:x}({}), {}", args.immediate, args.r1, args.r2), + Self::StoreByte(args) => { + write!(f, "STB {:x}({}), {}", args.immediate, args.r1, args.r2) + } + Self::StoreHalfword(args) => { + write!(f, "STH {:x}({}), {}", args.immediate, args.r1, args.r2) + } + Self::StoreWord(args) => { + write!(f, "STW {:x}({}), {}", args.immediate, args.r1, args.r2) + } - Self::StoreByte(a, b, c) => write!(f, "STB {a}, {b}, {c}"), - Self::StoreHalfword(a, b, c) => write!(f, "STH {a}, {b}, {c}"), - Self::StoreWord(a, b, c) => write!(f, "STW {a}, {b}, {c}"), + Self::LoadLowerImmediate(args) => write!(f, "LLI {}, {}", args.r1, args.r2), + Self::LoadUpperImmediate(args) => write!(f, "LUI {}, {}", args.r1, args.r2), - Self::LoadLowerImmediate(a, b) => write!(f, "LLI {a}, {b}"), - Self::LoadUpperImmediate(a, b) => write!(f, "LUI {a}, {b}"), + Self::Jump(args) => write!(f, "JMP ({:x}){}", args.immediate, args.r1), + Self::JumpEq(args) => write!(f, "JEQ ({:x}){}", args.immediate, args.r1), + Self::JumpNeq(args) => write!(f, "JNEQ ({:x}){}", args.immediate, args.r1), + Self::JumpGt(args) => write!(f, "JGT {:x}({})", args.immediate, args.r1), + Self::JumpGe(args) => write!(f, "JGE {:x}({})", args.immediate, args.r1), + Self::JumpLt(args) => write!(f, "JLT {:x}({})", args.immediate, args.r1), + Self::JumpLe(args) => write!(f, "JLE {:x}({})", args.immediate, args.r1), - Self::Jump(a, b) => write!(f, "JMP {a}, {b}"), - Self::JumpEq(a, b) => write!(f, "JEQ {a}, {b}"), - Self::JumpNeq(a, b) => write!(f, "JNEQ {a}, {b}"), - Self::JumpGt(a, b) => write!(f, "JGT {a}, {b}"), - Self::JumpGe(a, b) => write!(f, "JGE {a}, {b}"), - Self::JumpLt(a, b) => write!(f, "JLT {a}, {b}"), - Self::JumpLe(a, b) => write!(f, "JLE {a}, {b}"), + Self::Compare(args) => write!(f, "CMP {}, {}", args.sr1, args.sr2), - Self::Compare(a, b) => write!(f, "CMP {a}, {b}"), + Self::Add(args) => write!(f, "ADD {}, {}, {}", args.sr1, args.sr2, args.dr), + Self::Sub(args) => write!(f, "SUB {}, {}, {}", args.sr1, args.sr2, args.dr), + Self::Increment(a) => write!(f, "INC {}", a.dr), + Self::Decrement(a) => write!(f, "DEC {}", a.dr), + Self::ShiftLeft(args) => write!(f, "SHL {}, {}, {}", args.sr1, args.sr2, args.dr), + Self::ShiftRight(args) => write!(f, "SHR {}, {}, {}", args.sr1, args.sr2, args.dr), - Self::Add(a, b, c) => write!(f, "ADD {a}, {b}, {c}"), - Self::Sub(a, b, c) => write!(f, "SUB {a}, {b}, {c}"), - Self::Increment(a) => write!(f, "INC {a}"), - Self::Decrement(a) => write!(f, "DEC {a}"), - Self::ShiftLeft(a, b, c) => write!(f, "SHL {a}, {b}, {c}"), - Self::ShiftRight(a, b, c) => write!(f, "SHR {a}, {b}, {c}"), - - Self::And(a, b, c) => write!(f, "AND {a}, {b}, {c}"), - Self::Or(a, b, c) => write!(f, "OR {a}, {b}, {c}"), - Self::Not(a, b) => write!(f, "NOT {a}, {b}"), - Self::Xor(a, b, c) => write!(f, "XOR {a}, {b}, {c}"), - Self::Nand(a, b, c) => write!(f, "NAND {a}, {b}, {c}"), - Self::Nor(a, b, c) => write!(f, "NOR {a}, {b}, {c}"), - Self::Xnor(a, b, c) => write!(f, "XNOR {a}, {b}, {c}"), + Self::And(args) => write!(f, "AND {}, {}, {}", args.sr1, args.sr2, args.dr), + Self::Or(args) => write!(f, "OR {}, {}, {}", args.sr1, args.sr2, args.dr), + Self::Not(args) => write!(f, "NOT {}, {}", args.sr1, args.sr2), + Self::Xor(args) => write!(f, "XOR {}, {}, {}", args.sr1, args.sr2, args.dr), + Self::Nand(args) => write!(f, "NAND {}, {}, {}", args.sr1, args.sr2, args.dr), + Self::Nor(args) => write!(f, "NOR {}, {}, {}", args.sr1, args.sr2, args.dr), + Self::Xnor(args) => write!(f, "XNOR {}, {}, {}", args.sr1, args.sr2, args.dr), Self::Interrupt(a) => write!(f, "INT {}", a.as_u8()), Self::IntReturn => write!(f, "INTR"),