use binemit::CodeOffset;
use isa::constraints::{BranchRange, RecipeConstraints};
use std::fmt;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Encoding {
recipe: u16,
bits: u16,
}
impl Encoding {
pub fn new(recipe: u16, bits: u16) -> Self {
Self { recipe, bits }
}
pub fn recipe(self) -> usize {
self.recipe as usize
}
pub fn bits(self) -> u16 {
self.bits
}
pub fn is_legal(self) -> bool {
self != Self::default()
}
}
impl Default for Encoding {
fn default() -> Self {
Self::new(0xffff, 0xffff)
}
}
impl fmt::Display for Encoding {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.is_legal() {
write!(f, "{}#{:02x}", self.recipe, self.bits)
} else {
write!(f, "-")
}
}
}
pub struct DisplayEncoding {
pub encoding: Encoding,
pub recipe_names: &'static [&'static str],
}
impl fmt::Display for DisplayEncoding {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.encoding.is_legal() {
write!(
f,
"{}#{:02x}",
self.recipe_names[self.encoding.recipe()],
self.encoding.bits
)
} else {
write!(f, "-")
}
}
}
pub struct RecipeSizing {
pub bytes: u8,
pub branch_range: Option<BranchRange>,
}
#[derive(Clone)]
pub struct EncInfo {
pub constraints: &'static [RecipeConstraints],
pub sizing: &'static [RecipeSizing],
pub names: &'static [&'static str],
}
impl EncInfo {
pub fn operand_constraints(&self, enc: Encoding) -> Option<&'static RecipeConstraints> {
self.constraints.get(enc.recipe())
}
pub fn display(&self, enc: Encoding) -> DisplayEncoding {
DisplayEncoding {
encoding: enc,
recipe_names: self.names,
}
}
pub fn bytes(&self, enc: Encoding) -> CodeOffset {
self.sizing
.get(enc.recipe())
.map_or(0, |s| CodeOffset::from(s.bytes))
}
pub fn branch_range(&self, enc: Encoding) -> Option<BranchRange> {
self.sizing.get(enc.recipe()).and_then(|s| s.branch_range)
}
}