You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
4.6 KiB
192 lines
4.6 KiB
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<SrcDisp> 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<DstDisp> 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<DataDisp> for SrcDisp {
|
|
type Error = AsmError;
|
|
|
|
fn try_from(value: DataDisp) -> Result<Self, Self::Error> {
|
|
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<DstDisp> 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<DataDisp> for DstDisp {
|
|
type Error = AsmError;
|
|
|
|
fn try_from(value: DataDisp) -> Result<Self, Self::Error> {
|
|
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, ")")
|
|
}
|
|
}
|
|
|