40 lines
1.2 KiB
Rust
40 lines
1.2 KiB
Rust
|
// © 2023 John Breaux
|
||
|
//! A [JumpTarget] contains the [pc-relative offset](Number) or [Identifier]
|
||
|
//! for a [Jump instruction encoding](Encoding::Jump)
|
||
|
use super::*;
|
||
|
|
||
|
/// The target of a [Jump](Encoding::Jump)
|
||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||
|
pub struct JumpTarget(Number);
|
||
|
|
||
|
impl JumpTarget {
|
||
|
pub fn word(&self) -> u16 { u16::from(self.0) & 0x3ff }
|
||
|
}
|
||
|
|
||
|
impl Parsable for JumpTarget {
|
||
|
/// - Identifier
|
||
|
/// - Number
|
||
|
/// - Negative
|
||
|
/// - Number
|
||
|
fn parse<'text, T>(p: &Parser, stream: &mut T) -> Result<Self, Error>
|
||
|
where T: crate::TokenStream<'text> {
|
||
|
// Try to parse a number
|
||
|
let target = Number::parse(p, stream)?;
|
||
|
match target.into() {
|
||
|
i if i % 2 != 0 => Err(Error::JumpedOdd(i).context(stream.context()))?,
|
||
|
i if (-1024..=1022).contains(&(i - 2)) => Ok(Self((target - 2) >> 1)),
|
||
|
i => Err(Error::JumpedTooFar(i).context(stream.context()))?,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl From<JumpTarget> for u16 {
|
||
|
fn from(value: JumpTarget) -> Self { value.0.into() }
|
||
|
}
|
||
|
|
||
|
impl Display for JumpTarget {
|
||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||
|
write!(f, "{}", (1 + isize::from(self.0)) << 1)
|
||
|
}
|
||
|
}
|