73 lines
2.3 KiB
Rust
73 lines
2.3 KiB
Rust
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::Null as u32;
|
|
let sr2 = Register::Null as u32;
|
|
let dr = Register::Null 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, AddImmediate, SubImmediate
|
|
],
|
|
no_args: [Nop, IntReturn, Halt],
|
|
special: [
|
|
Self::Data(data) => data,
|
|
Self::Interrupt(interrupt) => {
|
|
let opcode = u32::from(self.opcode());
|
|
(opcode << 26) | u32::from(interrupt.as_u8())
|
|
},
|
|
Self::Segment(segment) => {
|
|
let opcode = u32::from(self.opcode());
|
|
(opcode << 26) | u32::from(segment as u8)
|
|
}
|
|
]
|
|
)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|