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.
225 lines
5.6 KiB
225 lines
5.6 KiB
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<RdData> 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<WrData> 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<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()
|
|
}
|
|
}
|
|
|
|
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<DataDisp> {
|
|
fn disp_equals<T : Into<DataDisp>>(self, other : T) -> bool;
|
|
}
|
|
|
|
impl<T : Into<DataDisp>> DataDispEquals for T {
|
|
fn disp_equals<X : Into<DataDisp>>(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<DataDisp> for RdData {
|
|
type Error = AsmError;
|
|
|
|
fn try_from(value: DataDisp) -> Result<Self, Self::Error> {
|
|
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<WrData> 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<DataDisp> for WrData {
|
|
type Error = AsmError;
|
|
|
|
fn try_from(value: DataDisp) -> Result<Self, Self::Error> {
|
|
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),
|
|
}
|
|
}
|
|
}
|
|
|
|
|