// © 2023 John Breaux //! A [PrimaryOperand] contains the first [Register], addressing mode, and Extension //! Word for a [one-operand](Encoding::Single) or [two-operand](Encoding::Double) [instruction] use super::*; /// Contains the first [Register], addressing mode, and Extension Word for a /// [one-operand](Encoding::Single) or [two-operand](Encoding::Double) [instruction] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum PrimaryOperand { Direct(Register), Indirect(Register), PostInc(Register), Indexed(Register, Number), Absolute(Number), Immediate(Number), Four, Eight, Zero, One, Two, MinusOne, } impl PrimaryOperand { /// Returns the mode bits pub fn mode(&self) -> u16 { use PrimaryOperand::*; match self { Direct(_) | Zero => 0, Indexed(_, _) | Absolute(_) | One => 1 << 4, Indirect(_) | Two | Four => 2 << 4, PostInc(_) | Immediate(_) | MinusOne | Eight => 3 << 4, } } /// Gets the register pub fn register(&self) -> Register { use PrimaryOperand::*; match self { Direct(r) | Indexed(r, _) | Indirect(r) | PostInc(r) => *r, Immediate(_) => Register::pc, Absolute(_) | Four | Eight => Register::sr, Zero | One | Two | MinusOne => Register::cg, } } /// Gets the extension word, if present pub fn ext_word(&self) -> Option { use PrimaryOperand::*; match self { Indexed(_, w) | Absolute(w) | Immediate(w) => Some((*w).into()), _ => None, } } } impl Parsable for PrimaryOperand { // - Register // - Indirect // - Register // - PostInc? // - Number // - OpenIdx // - Register // - CloseIdx // - Absolute // - Number // - Immediate // - Number fn parse<'text, T>(p: &Parser, stream: &mut T) -> Result where T: crate::TokenStream<'text> { use PrimaryOperand::*; // 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)); } // Or directly match any of the valid prefix markers // Type::Register and Type::Number are included here to make error messages clearer. // their inclusion will cause a negligible slowdown when the next token is not a prefix marker // (a failure condition) let token = stream.expect_any_of([Type::Indirect, Type::Absolute, Type::Immediate, Type::Register, Type::Number])?; Ok(match token.variant() { Type::Indirect => { let reg = Register::parse(p, stream)?; match stream.expect(Type::Plus) { Ok(_) => PostInc(reg), Err(_) => Indirect(reg), } } Type::Absolute => Absolute(Number::parse(p, stream)?), Type::Immediate => { let number = Number::parse(p, stream)?; match number.into() { // There are two representations for the all-ones constant, since Number preserves // signedness. -1 | 0xffff => MinusOne, 0 => Zero, 1 => One, 2 => Two, 4 => Four, 8 => Eight, _ => Immediate(number), } } _ => unreachable!("Token {token:?} passed expectation but failed match!"), }) } } impl From for PrimaryOperand { fn from(value: SecondaryOperand) -> Self { match value { SecondaryOperand::Direct(r) => Self::Direct(r), SecondaryOperand::Indexed(r, n) => Self::Indexed(r, n), SecondaryOperand::Absolute(n) => Self::Absolute(n), SecondaryOperand::Zero => Self::Zero, SecondaryOperand::One => Self::One, } } } impl Display for PrimaryOperand { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Direct(r) => write!(f, "{r}"), Self::Indirect(r) => write!(f, "@{r}"), Self::PostInc(r) => write!(f, "@{r}+"), Self::Indexed(r, idx) => write!(f, "{idx}({r})"), Self::Absolute(n) => write!(f, "&{n}"), Self::Immediate(n) => write!(f, "#{n}"), Self::Four => write!(f, "#4"), Self::Eight => write!(f, "#8"), Self::Zero => write!(f, "#0"), Self::One => write!(f, "#1"), Self::Two => write!(f, "#2"), Self::MinusOne => write!(f, "#-1"), } } }