IT WORKS HELL YEAH.
This commit is contained in:
@@ -81,7 +81,7 @@ impl TryFrom<u8> for Register {
|
||||
type Error = RegisterParseError;
|
||||
|
||||
fn try_from(idx: u8) -> Result<Self, Self::Error> {
|
||||
if idx > 0x18 {
|
||||
if idx > 0x1C {
|
||||
return Err(RegisterParseError::InvalidIndex(idx));
|
||||
}
|
||||
|
||||
@@ -111,6 +111,11 @@ impl TryFrom<u8> for Register {
|
||||
0x15 => Self::Mmr,
|
||||
0x16 => Self::Zero,
|
||||
0x17 => Self::NoReg,
|
||||
0x18 => Self::Mar,
|
||||
0x19 => Self::Mdr,
|
||||
0x1A => Self::Sts,
|
||||
0x1B => Self::Cir,
|
||||
0x1C => Self::Pcx,
|
||||
_ => unreachable!("This is already checked for in top `if` branch."),
|
||||
})
|
||||
}
|
||||
@@ -145,6 +150,7 @@ impl TryFrom<&str> for Register {
|
||||
"mmr" => Ok(Self::Mmr),
|
||||
"zero" => Ok(Self::Zero),
|
||||
"null" => Ok(Self::NoReg),
|
||||
"pcx" => Ok(Self::Pcx),
|
||||
_ => Err(RegisterParseError::InvalidName(value.to_string())),
|
||||
}
|
||||
}
|
||||
@@ -248,6 +254,14 @@ pub enum Instruction {
|
||||
Interrupt(Interrupt) = 0x22,
|
||||
IntReturn = 0x23,
|
||||
Halt = 0x24,
|
||||
|
||||
// Immediate Arithmetic
|
||||
AddImmediate(args::ITypeArgs) = 0x25,
|
||||
SubImmediate(args::ITypeArgs) = 0x26,
|
||||
|
||||
// Fake Instructions
|
||||
Data(u32) = 0x3E,
|
||||
Segment(u32) = 0x3F,
|
||||
}
|
||||
|
||||
impl PartialEq for Instruction {
|
||||
@@ -319,6 +333,10 @@ impl Instruction {
|
||||
Self::Nand(_) => "nand",
|
||||
Self::Nor(_) => "nor",
|
||||
Self::Xnor(_) => "xnor",
|
||||
Self::Data(_) => "data",
|
||||
Self::AddImmediate(_) => "addi",
|
||||
Self::SubImmediate(_) => "subi",
|
||||
Self::Segment(_) => "[SEGMENT]",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,7 +373,11 @@ impl std::fmt::Display for Instruction {
|
||||
| Self::StoreByte(args)
|
||||
| Self::StoreHalfword(args)
|
||||
| Self::StoreWord(args) => {
|
||||
write!(f, " {:x}({}), {}", args.immediate, args.r1, args.r2)
|
||||
write!(
|
||||
f,
|
||||
" {}({:x}/{}), {}",
|
||||
args.r1, args.immediate, args.immediate, args.r2
|
||||
)
|
||||
}
|
||||
Self::Jump(args)
|
||||
| Self::JumpEq(args)
|
||||
@@ -364,10 +386,10 @@ impl std::fmt::Display for Instruction {
|
||||
| Self::JumpGe(args)
|
||||
| Self::JumpLt(args)
|
||||
| Self::JumpLe(args) => {
|
||||
write!(f, " ({:x}){}", args.immediate, args.r1)
|
||||
write!(f, " 0x{:x}/{}({})", args.immediate, args.immediate, args.r1)
|
||||
}
|
||||
Self::LoadLowerImmediate(args) | Self::LoadUpperImmediate(args) => {
|
||||
write!(f, " {}, {}, {}", args.immediate, args.r1, args.r2)
|
||||
write!(f, " 0x{:x}, {}, {}", args.immediate, args.r1, args.r2)
|
||||
}
|
||||
Self::Compare(args) | Self::Not(args) => {
|
||||
write!(f, " {}, {}", args.sr1, args.sr2)
|
||||
@@ -388,6 +410,8 @@ impl std::fmt::Display for Instruction {
|
||||
|
||||
Self::Increment(a) | Self::Decrement(a) => write!(f, " {}", a.dr),
|
||||
Self::Interrupt(a) => write!(f, " {}", a.as_u8()),
|
||||
Self::Data(a) => write!(f, " {}", a),
|
||||
Self::Segment(x) => write!(f, " [SEGMENT {}]", x),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
@@ -439,6 +463,9 @@ impl TryFrom<u32> for Instruction {
|
||||
0x22 => Ok(Self::Interrupt(Interrupt::from((data & 0xFF) as u8))),
|
||||
0x23 => Ok(Self::IntReturn),
|
||||
0x24 => Ok(Self::Halt),
|
||||
0x25 => Ok(Self::AddImmediate(ITypeArgs::try_from(data)?)),
|
||||
0x26 => Ok(Self::SubImmediate(ITypeArgs::try_from(data)?)),
|
||||
0x3F => Ok(Self::Segment(data as u8 as u32)),
|
||||
_ => Err(InstructionDecodeError::InvalidOpcode(opcode)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,3 +155,54 @@ impl TryFrom<u32> for RTypeArgs {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! args {
|
||||
// R-type arguments - allows omitting any field
|
||||
(R $(, $field:ident: $value:expr)* $(,)?) => {{
|
||||
let mut sr1: Option<Register> = None;
|
||||
let mut sr2: Option<Register> = None;
|
||||
let mut dr: Option<Register> = None;
|
||||
let mut shamt: Option<u8> = None;
|
||||
|
||||
$(
|
||||
args!(@assign_r_option sr1, sr2, dr, shamt, $field, $value);
|
||||
)*
|
||||
|
||||
RTypeArgs::new(sr1, sr2, dr, shamt)
|
||||
}};
|
||||
|
||||
// I-type arguments - requires immediate, allows omitting registers
|
||||
(I, immediate: $immediate:expr $(, $field:ident: $value:expr)* $(,)?) => {{
|
||||
let mut r1: Option<Register> = None;
|
||||
let mut r2: Option<Register> = None;
|
||||
|
||||
$(
|
||||
args!(@assign_i_option r1, r2, $field, $value);
|
||||
)*
|
||||
|
||||
ITypeArgs::new($immediate, r1, r2)
|
||||
}};
|
||||
|
||||
// Internal helpers (same as above for R-type)
|
||||
(@assign_r_option $sr1:ident, $sr2:ident, $dr:ident, $shamt:ident, sr1, $value:expr) => {
|
||||
$sr1 = Some($value);
|
||||
};
|
||||
(@assign_r_option $sr1:ident, $sr2:ident, $dr:ident, $shamt:ident, sr2, $value:expr) => {
|
||||
$sr2 = Some($value);
|
||||
};
|
||||
(@assign_r_option $sr1:ident, $sr2:ident, $dr:ident, $shamt:ident, dr, $value:expr) => {
|
||||
$dr = Some($value);
|
||||
};
|
||||
(@assign_r_option $sr1:ident, $sr2:ident, $dr:ident, $shamt:ident, shamt, $value:expr) => {
|
||||
$shamt = Some($value);
|
||||
};
|
||||
|
||||
// Internal helpers for I-type (without immediate handling)
|
||||
(@assign_i_option $r1:ident, $r2:ident, r1, $value:expr) => {
|
||||
$r1 = Some($value);
|
||||
};
|
||||
(@assign_i_option $r1:ident, $r2:ident, r2, $value:expr) => {
|
||||
$r2 = Some($value);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -49,11 +49,17 @@ impl Encode for Instruction {
|
||||
StoreWord, LoadLowerImmediate, LoadUpperImmediate, Jump,
|
||||
JumpEq, JumpNeq, JumpGt, JumpGe, JumpLt, JumpLe, Compare,
|
||||
Add, Sub, Increment, Decrement, ShiftLeft, ShiftRight,
|
||||
And, Or, Not, Xor, Nand, Nor, Xnor
|
||||
And, Or, Not, Xor, Nand, Nor, Xnor, AddImmediate, SubImmediate
|
||||
],
|
||||
no_args: [Nop, IntReturn, Halt],
|
||||
special: [
|
||||
Self::Interrupt(_) => todo!()
|
||||
Self::Interrupt(_) => todo!(),
|
||||
Self::Data(data) => data,
|
||||
Self::Segment(segment) => {
|
||||
let opcode = u32::from(self.opcode());
|
||||
let segment = segment as u8;
|
||||
(opcode << 26) | (segment as u32)
|
||||
}
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user