common: start writing encoding routines (todo!)

This commit is contained in:
2025-06-15 05:03:25 +01:00
parent e55a1fced5
commit 5494ff5803
+51 -40
View File
@@ -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 {