From 5494ff5803623fc64683084a1de19e0e1704b4e3 Mon Sep 17 00:00:00 2001 From: "J. Hinchliffe" Date: Sun, 15 Jun 2025 05:03:25 +0100 Subject: [PATCH] common: start writing encoding routines (todo!) --- src/common/instructions.rs | 91 +++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/src/common/instructions.rs b/src/common/instructions.rs index b66a650..da30c15 100644 --- a/src/common/instructions.rs +++ b/src/common/instructions.rs @@ -154,6 +154,8 @@ impl std::fmt::Display for Register { } } +/// TODO: Turn argument tuples into simple structs like `TwoReg`, `TwoRegAndOff` +/// etc just to make code a little cleaner. #[derive(Debug, Clone, Copy)] #[repr(u8)] pub enum Instruction { @@ -212,6 +214,7 @@ pub enum Instruction { Halt = 0x24, } +#[expect(clippy::missing_const_for_fn)] impl Instruction { /// Returns the opcode of an instruction. /// @@ -226,48 +229,56 @@ impl Instruction { #[must_use] #[allow(unused)] pub fn encode(&self) -> u32 { - match self { - Self::Nop => todo!(), - Self::Mov(src, dst) => todo!(), - Self::MovSigned(register, register1) => todo!(), - Self::LoadByte(register, _, register1) => todo!(), - Self::LoadByteSigned(register, _, register1) => todo!(), - Self::LoadHalfword(register, _, register1) => todo!(), - Self::LoadHalfwordSigned(register, _, register1) => todo!(), - Self::LoadWord(register, _, register1) => todo!(), - Self::StoreByte(register, _, register1) => todo!(), - Self::StoreHalfword(register, _, register1) => todo!(), - Self::StoreWord(register, _, register1) => todo!(), - Self::LoadLowerImmediate(register, _) => todo!(), - Self::LoadUpperImmediate(register, _) => todo!(), - Self::Jump(register, _) => todo!(), - Self::JumpEq(register, _) => todo!(), - Self::JumpNeq(register, _) => todo!(), - Self::JumpGt(register, _) => todo!(), - Self::JumpGe(register, _) => todo!(), - Self::JumpLt(register, _) => todo!(), - Self::JumpLe(register, _) => todo!(), - Self::Compare(register, register1) => todo!(), - Self::Add(register, register1, register2) => todo!(), - Self::Sub(register, register1, register2) => todo!(), - Self::Increment(register) => todo!(), - Self::Decrement(register) => todo!(), - Self::ShiftLeft(register, register1, _) => todo!(), - Self::ShiftRight(register, register1, _) => todo!(), - Self::And(register, register1, register2) => todo!(), - Self::Or(register, register1, register2) => todo!(), - Self::Not(register, register1) => todo!(), - Self::Xor(register, register1, register2) => todo!(), - Self::Nand(register, register1, register2) => todo!(), - Self::Nor(register, register1, register2) => todo!(), - Self::Xnor(register, register1, register2) => todo!(), - Self::Interrupt(interrupt) => todo!(), - Self::IntReturn => todo!(), - Self::Halt => todo!(), - } + // match self { + // _ => todo!(), + // } + + // Note to Harry, I will finish this encode/decode shit in a few hours. + + 21 } - const fn _encode_mov() {} + /// Encodes an R-type instruction from its fields. These must have unused high-order + /// bits set to 0 else the bit shifting logic is fucked. + /// + /// # Arguments + /// + /// - `shamt`: The amount to shift value (used only in shift instructions, otherwise 0). + #[must_use] + pub const fn encode_r_type(opcode: u8, sr1: u8, sr2: u8, dr: u8, shamt: u8) -> u32 { + let opcode = opcode as u32; + let sr1 = sr1 as u32; + let sr2 = sr2 as u32; + let dr = dr as u32; + let shamt = shamt as u32; + + (opcode << 26) | (sr1 << 21) | (sr2 << 16) | (dr << 11) | (shamt << 6) + } + + /// Encodes an I-type instruction from its fields. These must have some unused high-order + /// bits set to 0 else the bit shifting logic gets fucked. + #[must_use] + pub const fn encode_i_type(opcode: u8, sr1: u8, dr: u8, immediate: u16) -> u32 { + let opcode = opcode as u32; + let sr1 = sr1 as u32; + let dr = dr as u32; + let immediate = immediate as u32; + + (opcode << 26) | (sr1 << 21) | (dr << 16) | immediate + } + + #[must_use] + #[deprecated = "I am a little confused as to whether we keep these around for jumps."] + /// Encodes a J-type instruction from its fields. These must have some unused high-order + /// bits set to 0 else the bit shifting logic gets fucked. + /// + /// Note: the address argument is passed as-is, caller is responsible for resolving this + /// address properly. + pub const fn _encode_j_type(opcode: u8, addr: u32) -> u32 { + let opcode = opcode as u32; + + (opcode << 26) | addr + } #[must_use] pub const fn decode(_data: u32) -> Self {