96 lines
3.0 KiB
Rust
96 lines
3.0 KiB
Rust
// © 2023 John Breaux
|
|
//! A [SecondaryOperand] contains the second [Register], addressing mode, and Extension
|
|
//! Word for a [two-operand](Encoding::Double) [instruction]
|
|
use super::*;
|
|
|
|
/// The destination of a [Double](Encoding::Double)
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
pub enum SecondaryOperand {
|
|
Direct(Register),
|
|
Indexed(Register, Number),
|
|
Absolute(Number),
|
|
// Joke encodings?
|
|
Zero,
|
|
One,
|
|
}
|
|
|
|
impl SecondaryOperand {
|
|
pub fn mode(&self) -> u16 {
|
|
use SecondaryOperand::*;
|
|
match self {
|
|
Direct(_) | Zero => 0,
|
|
Indexed(_, _) | Absolute(_) | One => 1 << 7,
|
|
}
|
|
}
|
|
pub fn register(&self) -> Register {
|
|
use SecondaryOperand::*;
|
|
match self {
|
|
Direct(r) | Indexed(r, _) => *r,
|
|
Absolute(_) => Register::sr,
|
|
Zero | One => Register::cg,
|
|
}
|
|
}
|
|
/// This is the only way to have an extension word
|
|
pub fn ext_word(&self) -> Option<u16> {
|
|
use SecondaryOperand::*;
|
|
match self {
|
|
Indexed(_, w) | Absolute(w) => Some((*w).into()),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Parsable for SecondaryOperand {
|
|
// Separator
|
|
// - Register => Direct
|
|
// - Number => Indexed
|
|
// - OpenIdx
|
|
// - Register
|
|
// - CloseIdx
|
|
// - Absolute
|
|
// - Number
|
|
// - Immediate
|
|
// - Number == 0, 1
|
|
fn parse<'text, T>(p: &Parser, stream: &mut T) -> Result<Self, crate::Error>
|
|
where T: crate::TokenStream<'text> {
|
|
use SecondaryOperand::*;
|
|
stream.allow(Type::Separator);
|
|
// Try parsing as Register Direct
|
|
if let Some(r) = Register::try_parse(p, stream)? {
|
|
return Ok(Self::Direct(r));
|
|
}
|
|
// Try parsing as Number Indexed
|
|
if let Some(idx) = Number::try_parse(p, stream)? {
|
|
stream.expect(Type::LParen)?;
|
|
let reg = Register::parse(p, stream)?;
|
|
stream.expect(Type::RParen)?;
|
|
return Ok(Self::Indexed(reg, idx));
|
|
}
|
|
let token = stream.expect_any_of([Type::Absolute, Type::Immediate])?;
|
|
Ok(match token.variant() {
|
|
Type::Absolute => Absolute(Number::parse(p, stream)?),
|
|
Type::Immediate => {
|
|
let number = Number::parse(p, stream)?;
|
|
match number.into() {
|
|
0 => Zero,
|
|
1 => One,
|
|
n => Err(Error::FatSecondaryImmediate(n as isize).context(stream.context()))?,
|
|
}
|
|
}
|
|
_ => unreachable!("Token {token:?} passed expectation but failed match!"),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Display for SecondaryOperand {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Direct(r) => write!(f, "{r}"),
|
|
Self::Indexed(r, idx) => write!(f, "{idx}({r})"),
|
|
Self::Absolute(n) => write!(f, "&{n}"),
|
|
Self::Zero => write!(f, "#0"),
|
|
Self::One => write!(f, "#1"),
|
|
}
|
|
}
|
|
}
|