use core::fmt;
use super::inst::Mnemonic;
use super::reg::Reg;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum EncodeError {
NoForm {
mnemonic: Mnemonic,
},
ImmediateOutOfRange {
value: i64,
},
TargetOutOfRange {
offset: i64,
},
HighByteWithRex,
BaseNotQword {
base: Reg,
},
IndexNotQword {
index: Reg,
},
RspIndex,
RipWithIndex,
}
impl fmt::Display for EncodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
EncodeError::NoForm { mnemonic } => {
write!(f, "no `{mnemonic}` form takes these operands")
}
EncodeError::ImmediateOutOfRange { value } => {
f.write_str("immediate ")?;
super::fmt::hex(f, *value)?;
f.write_str(" does not fit any form for these operands")
}
EncodeError::TargetOutOfRange { offset } => {
f.write_str("branch target $")?;
super::fmt::signed_hex(f, *offset)?;
f.write_str(" is out of reach of a 32-bit displacement")
}
EncodeError::HighByteWithRex => f.write_str(
"ah, ch, dh, and bh cannot be used in an instruction that needs a REX prefix",
),
EncodeError::BaseNotQword { base } => {
write!(f, "memory base `{base}` is not a 64-bit register")
}
EncodeError::IndexNotQword { index } => {
write!(f, "memory index `{index}` is not a 64-bit register")
}
EncodeError::RspIndex => f.write_str("rsp cannot be an index register"),
EncodeError::RipWithIndex => {
f.write_str("a rip-relative memory operand cannot have an index register")
}
}
}
}
impl core::error::Error for EncodeError {}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum DecodeError {
Truncated {
at: usize,
},
UnsupportedPrefix {
at: usize,
byte: u8,
},
RepeatedPrefix {
at: usize,
},
MisplacedRex {
at: usize,
},
UnknownOpcode {
at: usize,
escaped: bool,
opcode: u8,
},
InvalidOperandSize {
at: usize,
},
UnknownExtension {
at: usize,
ext: u8,
},
RegisterOperand {
at: usize,
},
UnusedRex {
at: usize,
},
}
impl DecodeError {
#[must_use]
pub const fn at(&self) -> usize {
match *self {
DecodeError::Truncated { at }
| DecodeError::UnsupportedPrefix { at, .. }
| DecodeError::RepeatedPrefix { at }
| DecodeError::MisplacedRex { at }
| DecodeError::UnknownOpcode { at, .. }
| DecodeError::InvalidOperandSize { at }
| DecodeError::UnknownExtension { at, .. }
| DecodeError::RegisterOperand { at }
| DecodeError::UnusedRex { at } => at,
}
}
}
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
DecodeError::Truncated { at } => {
write!(
f,
"instruction is cut off: byte {at} is past the end of the input"
)
}
DecodeError::UnsupportedPrefix { at, byte } => {
write!(f, "unsupported prefix {byte:02x} at byte {at}")
}
DecodeError::RepeatedPrefix { at } => {
write!(f, "repeated operand-size prefix at byte {at}")
}
DecodeError::MisplacedRex { at } => {
write!(
f,
"REX prefix at byte {at} is not immediately before the opcode"
)
}
DecodeError::UnknownOpcode {
at,
escaped,
opcode,
} => {
let escape = if escaped { "0f " } else { "" };
write!(f, "unknown opcode {escape}{opcode:02x} at byte {at}")
}
DecodeError::InvalidOperandSize { at } => {
write!(f, "opcode at byte {at} has no form with this operand size")
}
DecodeError::UnknownExtension { at, ext } => {
write!(
f,
"opcode extension /{ext} in the ModRM byte at {at} is not defined"
)
}
DecodeError::RegisterOperand { at } => {
write!(
f,
"ModRM byte at {at} names a register where memory is required"
)
}
DecodeError::UnusedRex { at } => {
write!(f, "REX prefix at byte {at} sets a bit no operand uses")
}
}
}
}
impl core::error::Error for DecodeError {}