use std::convert::TryFrom; use std::fmt::{Debug, Display, Formatter}; use std::fmt; use literal::Addr; pub use mask::Mask; pub use reg::Register; use crate::asm::data::literal::{as_signed, Value}; use super::error::AsmError; pub mod literal; pub mod reg; pub mod mask; /// Data source disposition #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum DataDisp { /// Constant value Immediate(Value), /// Register Register(Register), /// Object pointer ObjectPtr(Register), /// Discard the written value Discard, } impl Display for DataDisp { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { DataDisp::Immediate(v) => { write!(f, "{}", as_signed(*v)) } DataDisp::Register(r) => { write!(f, "{}", r) } DataDisp::ObjectPtr(r) => { write!(f, "%{}", r) } DataDisp::Discard => { write!(f, "_") } } } } impl From for DataDisp { fn from(s: SrcDisp) -> Self { match s { SrcDisp::Immediate(x) => DataDisp::Immediate(x), SrcDisp::Register(x) => DataDisp::Register(x), SrcDisp::ObjectPtr(x) => DataDisp::ObjectPtr(x), } } } impl From for DataDisp { fn from(s: DstDisp) -> Self { match s { DstDisp::Register(x) => DataDisp::Register(x), DstDisp::ObjectPtr(x) => DataDisp::ObjectPtr(x), DstDisp::Discard => DataDisp::Discard, } } } /// Data source disposition #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum SrcDisp { /// Constant value Immediate(Value), /// Register Register(Register), /// Pointer into memory, stored in a numbered register ObjectPtr(Register), } impl TryFrom for SrcDisp { type Error = AsmError; fn try_from(value: DataDisp) -> Result { match value { DataDisp::Immediate(x) => Ok(SrcDisp::Immediate(x)), DataDisp::Register(x) => Ok(SrcDisp::Register(x)), DataDisp::ObjectPtr(x) => Ok(SrcDisp::ObjectPtr(x)), DataDisp::Discard => Err(AsmError::DiscardAsValue), } } } /// Data destination disposition #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum DstDisp { /// Register Register(Register), /// Pointer into memory, stored in a numbered register ObjectPtr(Register), /// Discard the written value Discard, } impl From for SrcDisp { fn from(s: DstDisp) -> Self { match s { DstDisp::Register(x) => SrcDisp::Register(x), DstDisp::ObjectPtr(x) => SrcDisp::ObjectPtr(x), DstDisp::Discard => SrcDisp::Immediate(0), } } } impl TryFrom for DstDisp { type Error = AsmError; fn try_from(value: DataDisp) -> Result { match value { DataDisp::Immediate(_x) => Err(AsmError::ValueAsOutput), DataDisp::Register(x) => Ok(DstDisp::Register(x)), DataDisp::ObjectPtr(x) => Ok(DstDisp::ObjectPtr(x)), DataDisp::Discard => Ok(DstDisp::Discard), } } } /// Data source argument (read-only) #[derive(Clone, Copy, Eq, PartialEq)] pub struct Rd(SrcDisp, Mask); impl Rd { pub fn new(src: SrcDisp) -> Self { Rd(src, Mask::default()) } pub fn d(self) -> SrcDisp { self.0 } pub fn mask(self) -> Mask { self.1 } pub fn immediate(val: Value) -> Rd { Rd(SrcDisp::Immediate(val), Mask::default()) } } /// Data destination argument (read-write) #[derive(Clone, Copy, Eq, PartialEq)] pub struct Wr(DstDisp, Mask); impl Wr { pub fn new(dst: DstDisp) -> Self { Wr(dst, Mask::default()) } pub fn d(self) -> DstDisp { self.0 } pub fn mask(self) -> Mask { self.1 } pub fn as_rd(&self) -> Rd { Rd(self.0.into(), self.1) } pub fn discard() -> Wr { Wr(DstDisp::Discard, Mask::default()) } } impl Debug for Rd { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "Rd(")?; let disp: DataDisp = self.0.into(); write!(f, "{}", disp)?; if !self.mask().is_default() { write!(f, ",{:?}", self.mask())?; } write!(f, ")") } } impl Debug for Wr { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "Wr(")?; let disp: DataDisp = self.0.into(); write!(f, "{}", disp)?; if !self.mask().is_default() { write!(f, ",{:?}", self.mask())?; } write!(f, ")") } }