refactor 2 electric boogaloo

This commit is contained in:
2025-06-15 21:40:43 +01:00
parent 277f210b3e
commit 2b8281157e
30 changed files with 125 additions and 71 deletions
+63
View File
@@ -0,0 +1,63 @@
use crate::prelude::*;
/// Not to be used directly, just call [`Instruction::encode`].
pub trait Encode {
fn encode(self, opcode: u8) -> u32;
}
/// Encodes a zero argument instruction.
fn encode_no_args(opcode: u8) -> u32 {
let opcode = u32::from(opcode);
let sr1 = Register::NoReg as u32;
let sr2 = Register::NoReg as u32;
let dr = Register::NoReg as u32;
let shamt = 0;
(opcode << 26) | (sr1 << 21) | (sr2 << 16) | (dr << 11) | (shamt << 6)
}
/// Expands to a match statement that calls encode on instructions that implement [`Encode`]:
///
/// # Usage
///
/// ```rs
/// encode_instruction!(self, with_args: [...], no_args: [...], special: [...] )
/// ```
macro_rules! encode_instruction {
($self:expr, with_args: [$($variant:ident),+ $(,)?], no_args: [$($no_arg_variant:ident),* $(,)?] $(, special: [$($special:pat => $body:expr),* $(,)?])?) => {
match $self {
$(
Instruction::$variant(args) => args.encode($self.opcode()),
)+
$(
Instruction::$no_arg_variant => encode_no_args($self.opcode()),
)*
$($(
$special => $body,
)*)?
}
};
}
impl Encode for Instruction {
fn encode(self, _: u8) -> u32 {
encode_instruction!(
self,
with_args: [
Mov, MovSigned, LoadByte, LoadByteSigned, LoadHalfword,
LoadHalfwordSigned, LoadWord, StoreByte, StoreHalfword,
StoreWord, LoadLowerImmediate, LoadUpperImmediate, Jump,
JumpEq, JumpNeq, JumpGt, JumpGe, JumpLt, JumpLe, Compare,
Add, Sub, Increment, Decrement, ShiftLeft, ShiftRight,
And, Or, Not, Xor, Nand, Nor, Xnor
],
no_args: [Nop, IntReturn, Halt],
special: [
Self::Interrupt(_) => todo!()
]
)
}
}
#[cfg(test)]
mod tests;