forked from MightyPork/crsn
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.
72 lines
2.4 KiB
72 lines
2.4 KiB
use sexp::{Sexp, Atom};
|
|
use crate::data::{DataDisp, Rd, Wr, DstDisp, SrcDisp, reg};
|
|
use crate::error::Error;
|
|
use crate::data::literal::{Value, Addr, Label};
|
|
use std::convert::TryFrom;
|
|
use crate::parse::sexp_expect::expect_string_atom;
|
|
|
|
/// Parse a label
|
|
pub fn parse_label(name : Option<Sexp>) -> Result<Label, Error> {
|
|
let name = expect_string_atom(name)?;
|
|
Ok(Label::Named(name.trim_start_matches(':').into()))
|
|
}
|
|
|
|
/// Parse data disposition (address/value, without the read/write restriction)
|
|
pub fn parse_data_disp(tok: Option<Sexp>) -> Result<DataDisp, Error> {
|
|
let tok = if let Some(tok) = tok {
|
|
tok
|
|
} else {
|
|
return Err(Error::Parse("Expected data disposition token".into()));
|
|
};
|
|
|
|
// TODO implement masks
|
|
|
|
match &tok {
|
|
Sexp::Atom(Atom::I(val)) => {
|
|
Ok(DataDisp::Immediate(Value(*val)))
|
|
},
|
|
Sexp::Atom(Atom::S(s)) => {
|
|
if let Some(reference) = s.strip_prefix('@') {
|
|
if reference.starts_with(|c : char| c.is_ascii_digit()) {
|
|
let val : u64 = parse_u64(reference)?;
|
|
Ok(DataDisp::ImmediatePtr(Addr(val)))
|
|
} else {
|
|
Ok(DataDisp::RegisterPtr(reg::parse_reg(reference)?))
|
|
}
|
|
} else if s.starts_with(|c : char| c.is_ascii_digit()) {
|
|
Ok(DataDisp::Immediate(Value(parse_i64(s)?)))
|
|
} else {
|
|
Ok(DataDisp::Register(reg::parse_reg(s)?))
|
|
}
|
|
},
|
|
_ => {
|
|
Err(Error::Parse(format!("bad data disp: {:?}", tok).into()))
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn parse_u64(literal : &str) -> anyhow::Result<u64> {
|
|
if let Some(hex) = literal.strip_prefix("0x") {
|
|
Ok(u64::from_str_radix(hex, 16)?)
|
|
} else if let Some(hex) = literal.strip_prefix("0b") {
|
|
Ok(u64::from_str_radix(hex, 2)?)
|
|
} else {
|
|
Ok(u64::from_str_radix(literal, 10)?)
|
|
}
|
|
}
|
|
|
|
pub fn parse_i64(literal : &str) -> anyhow::Result<i64> {
|
|
if let Some(_value) = literal.strip_prefix("-") {
|
|
Ok(-1 * i64::try_from(parse_u64(literal)?)?)
|
|
} else {
|
|
Ok(i64::try_from(parse_u64(literal)?)?)
|
|
}
|
|
}
|
|
|
|
pub fn parse_rd(tok: Option<Sexp>) -> anyhow::Result<Rd> {
|
|
Ok(Rd::new(SrcDisp::try_from(parse_data_disp(tok)?)?))
|
|
}
|
|
|
|
pub fn parse_wr(tok: Option<Sexp>) -> anyhow::Result<Wr> {
|
|
Ok(Wr::new(DstDisp::try_from(parse_data_disp(tok)?)?))
|
|
}
|
|
|