use std::convert::TryFrom; use std::fmt::{Debug, Display, Formatter}; use std::fmt; pub use rd::Rd; pub use rd::RdObj; pub use reg::Register; pub use wr::Wr; pub use rdwr::RdWr; use crate::asm::data::literal::{as_signed, is_negative, Value}; use super::error::AsmError; pub mod literal; pub mod reg; mod rd; mod wr; mod rdwr; /// Data source disposition #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum DataDisp { /// Constant value Immediate(Value), /// Object pointer with immediate value ImmObject(Value), /// Register Register(Register), /// Object pointer in register RegObject(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::RegObject(r) => { write!(f, "@{}", r) } DataDisp::ImmObject(r) => { write!(f, "@{:#x}", r) } DataDisp::Discard => { write!(f, "_") } } } } impl From for DataDisp { fn from(s: RdData) -> Self { match s { RdData::Immediate(x) => DataDisp::Immediate(x), RdData::Register(x) => DataDisp::Register(x), RdData::RegObject(x) => DataDisp::RegObject(x), RdData::ImmObject(x) => DataDisp::ImmObject(x), } } } impl From for DataDisp { fn from(s: WrData) -> Self { match s { WrData::Register(x) => DataDisp::Register(x), WrData::RegObject(x) => DataDisp::RegObject(x), WrData::ImmObject(x) => DataDisp::ImmObject(x), WrData::Discard => DataDisp::Discard, } } } impl From for DataDisp { fn from(s: Rd) -> Self { s.0.into() } } impl From for DataDisp { fn from(s: Wr) -> Self { s.0.into() } } impl From for DataDisp { fn from(s: RdWr) -> Self { s.0.into() } } impl From<&Rd> for DataDisp { fn from(s: &Rd) -> Self { s.0.into() } } impl From<&Wr> for DataDisp { fn from(s: &Wr) -> Self { s.0.into() } } impl From<&RdWr> for DataDisp { fn from(s: &RdWr) -> Self { s.0.into() } } pub trait DataDispEquals : Into { fn disp_equals>(self, other : T) -> bool; } impl> DataDispEquals for T { fn disp_equals>(self, other : X) -> bool { self.into() == other.into() } } /// Data source disposition #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum RdData { /// Constant value Immediate(Value), /// Pointer into memory, address immediate ImmObject(Value), /// Register Register(Register), /// Pointer into memory, stored in a numbered register RegObject(Register), } impl Display for RdData { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { RdData::Immediate(v) => { if is_negative(*v) { write!(f, "{}", as_signed(*v)) } else { write!(f, "{}", *v) } } RdData::Register(r) => write!(f, "{}", r), RdData::RegObject(r) => write!(f, "@{}", r), RdData::ImmObject(v) => write!(f, "@{:#x}", v), } } } impl TryFrom for RdData { type Error = AsmError; fn try_from(value: DataDisp) -> Result { match value { DataDisp::Immediate(x) => Ok(RdData::Immediate(x)), DataDisp::ImmObject(x) => Ok(RdData::ImmObject(x)), DataDisp::Register(x) => Ok(RdData::Register(x)), DataDisp::RegObject(x) => Ok(RdData::RegObject(x)), DataDisp::Discard => Err(AsmError::DiscardAsValue), } } } /// Data destination disposition #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum WrData { /// Pointer into memory, address immediate ImmObject(Value), /// Register Register(Register), /// Pointer into memory, stored in a numbered register RegObject(Register), /// Discard the written value Discard, } impl WrData { pub fn is_readable(self) -> bool { self != Self::Discard } } impl Display for WrData { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { WrData::Discard => f.write_str("_"), WrData::Register(r) => write!(f, "{}", r), WrData::RegObject(r) => write!(f, "@{}", r), WrData::ImmObject(v) => write!(f, "@{:#x}", v), } } } impl From for RdData { fn from(s: WrData) -> Self { match s { WrData::ImmObject(x) => RdData::ImmObject(x), WrData::Register(x) => RdData::Register(x), WrData::RegObject(x) => RdData::RegObject(x), WrData::Discard => RdData::Immediate(0), // this should not be allowed by the assembler } } } impl TryFrom for WrData { type Error = AsmError; fn try_from(value: DataDisp) -> Result { match value { DataDisp::Immediate(_x) => Err(AsmError::ValueAsOutput), DataDisp::ImmObject(x) => Ok(WrData::ImmObject(x)), DataDisp::Register(x) => Ok(WrData::Register(x)), DataDisp::RegObject(x) => Ok(WrData::RegObject(x)), DataDisp::Discard => Ok(WrData::Discard), } } }