|
|
|
@ -2,10 +2,12 @@ use sexp::{Sexp, SourcePosition}; |
|
|
|
|
|
|
|
|
|
use crate::asm::data::{Rd, RdData, RdObj, Wr, RdWr}; |
|
|
|
|
use crate::asm::error::CrsnError; |
|
|
|
|
use crate::asm::parse::parse_data::{parse_rd, parse_wr, parse_value}; |
|
|
|
|
use crate::asm::parse::parse_data::{parse_rd, parse_wr, parse_value, parse_rdwr_offset, parse_rdwr, parse_rd_offset, parse_wr_offset}; |
|
|
|
|
use crate::asm::parse::ParserContext; |
|
|
|
|
use crate::asm::parse::sexp_expect::expect_string_atom; |
|
|
|
|
use crate::asm::data::literal::Value; |
|
|
|
|
use crate::builtin::defs::BitMask; |
|
|
|
|
use crate::asm::patches::ErrWithPos; |
|
|
|
|
|
|
|
|
|
/// Utility for argument parsing
|
|
|
|
|
#[derive(Debug)] |
|
|
|
@ -21,7 +23,7 @@ impl<'a> IntoIterator for TokenParser<'a> { |
|
|
|
|
type IntoIter = std::vec::IntoIter<Sexp>; |
|
|
|
|
|
|
|
|
|
fn into_iter(mut self) -> Self::IntoIter { |
|
|
|
|
// The vec is reversed so we can call "pop", but here we will iterate it as slice so it
|
|
|
|
|
// The vec is reversed so we can call "pop", but here we will iterate it as a slice, so it
|
|
|
|
|
// must be reversed to its original direction.
|
|
|
|
|
self.args.reverse(); |
|
|
|
|
self.args.into_iter() |
|
|
|
@ -40,6 +42,16 @@ impl<'a> TokenParser<'a> { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Get error if not empty.
|
|
|
|
|
/// The argument is substituted into the phrase "Instruction needs ...!" - i.e. "one Wr argument and a list or string"
|
|
|
|
|
pub fn ensure_empty(&self, what_arguments : &str) -> Result<(), CrsnError> { |
|
|
|
|
if self.have_more() { |
|
|
|
|
Err(CrsnError::Parse(format!("Instruction needs {}!", what_arguments).into(), self.start_pos.clone())) |
|
|
|
|
} else { |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn have_more(&self) -> bool { |
|
|
|
|
self.len() > 0 |
|
|
|
|
} |
|
|
|
@ -121,13 +133,180 @@ impl<'a> TokenParser<'a> { |
|
|
|
|
/// Get the next entry as write location
|
|
|
|
|
pub fn next_rdwr(&mut self) -> Result<RdWr, CrsnError> { |
|
|
|
|
let next = self.next_or_err()?; |
|
|
|
|
let pos = next.pos().clone(); |
|
|
|
|
let wr = parse_wr(next, self.pcx)?; |
|
|
|
|
parse_rdwr(next, self.pcx) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if !wr.is_readable() { |
|
|
|
|
return Err(CrsnError::Parse("Argument is not readable!".into(), pos)); |
|
|
|
|
/// Get the next entry as write location with optional :offset
|
|
|
|
|
pub fn next_rdwr_offset(&mut self) -> Result<(RdWr, u32), CrsnError> { |
|
|
|
|
let next = self.next_or_err()?; |
|
|
|
|
parse_rdwr_offset(next, self.pcx) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn next_rd_offset(&mut self) -> Result<(Rd, u32), CrsnError> { |
|
|
|
|
let next = self.next_or_err()?; |
|
|
|
|
parse_rd_offset(next, self.pcx) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn next_wr_offset(&mut self) -> Result<(Wr, u32), CrsnError> { |
|
|
|
|
let next = self.next_or_err()?; |
|
|
|
|
parse_wr_offset(next, self.pcx) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(RdWr::new(wr.0)) |
|
|
|
|
/// Parse combining binary instruction operands (i.e. add) with bit masks
|
|
|
|
|
/// Accepts (Wr, Rd, Rd) and (RdWr, Rd)
|
|
|
|
|
pub fn parse_masked_wr_rd_rd(&mut self, keyword: &str, prefix: &str) -> Result<Option<(Wr, Rd, Rd, BitMask)>, CrsnError> { |
|
|
|
|
if let Some(s) = keyword.strip_prefix(prefix) { |
|
|
|
|
let width = if s.is_empty() { |
|
|
|
|
(std::mem::size_of::<Value>() as u32) * 8 |
|
|
|
|
} else { |
|
|
|
|
s.parse().err_pos(self.start_pos)? |
|
|
|
|
}; |
|
|
|
|
if self.len() == 2 { |
|
|
|
|
let (rw, dst_pos) = self.next_rdwr_offset()?; |
|
|
|
|
let (rd, src_pos) = self.next_rd_offset()?; |
|
|
|
|
|
|
|
|
|
let mask = BitMask { |
|
|
|
|
width, |
|
|
|
|
dst_pos, |
|
|
|
|
src_pos: dst_pos, |
|
|
|
|
src2_pos: src_pos, |
|
|
|
|
}; |
|
|
|
|
mask.validate(self.start_pos)?; |
|
|
|
|
|
|
|
|
|
Ok(Some((rw.wr(), rw.rd(), rd, mask))) |
|
|
|
|
} else if self.len() == 3 { |
|
|
|
|
let (wr, dst_pos) = self.next_wr_offset()?; |
|
|
|
|
let (rd1, src_pos) = self.next_rd_offset()?; |
|
|
|
|
let (rd2, src2_pos) = self.next_rd_offset()?; |
|
|
|
|
|
|
|
|
|
let mask = BitMask { |
|
|
|
|
width, |
|
|
|
|
dst_pos, |
|
|
|
|
src_pos, |
|
|
|
|
src2_pos, |
|
|
|
|
}; |
|
|
|
|
mask.validate(self.start_pos)?; |
|
|
|
|
|
|
|
|
|
Ok(Some((wr, rd1, rd2, mask))) |
|
|
|
|
} else { |
|
|
|
|
Err(CrsnError::Parse("Instruction needs 2 (RW Rd) or 3 (Wr Rd Rd) arguments!".into(), self.start_pos.clone())) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
Ok(None) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Parse unary instruction operands (i.e. complement) with bit masks.
|
|
|
|
|
/// Accepts (Wr, Rd) and (RdWr)
|
|
|
|
|
pub fn parse_masked_wr_rd(&mut self, keyword: &str, prefix: &'static str) -> Result<Option<(Wr, Rd, BitMask)>, CrsnError> { |
|
|
|
|
if let Some(s) = keyword.strip_prefix(prefix) { |
|
|
|
|
let width = if s.is_empty() { |
|
|
|
|
(std::mem::size_of::<Value>() as u32) * 8 |
|
|
|
|
} else { |
|
|
|
|
s.parse().err_pos(self.start_pos)? |
|
|
|
|
}; |
|
|
|
|
if self.len() == 1 { |
|
|
|
|
let (rw, dst_pos) = self.next_rdwr_offset()?; |
|
|
|
|
|
|
|
|
|
let mask = BitMask { |
|
|
|
|
width, |
|
|
|
|
dst_pos, |
|
|
|
|
src_pos: dst_pos, |
|
|
|
|
src2_pos: 0, |
|
|
|
|
}; |
|
|
|
|
mask.validate(self.start_pos)?; |
|
|
|
|
|
|
|
|
|
Ok(Some((rw.wr(), rw.rd(), mask))) |
|
|
|
|
} else if self.len() == 2 { |
|
|
|
|
let (wr, dst_pos) = self.next_wr_offset()?; |
|
|
|
|
let (rd, src_pos) = self.next_rd_offset()?; |
|
|
|
|
|
|
|
|
|
let mask = BitMask { |
|
|
|
|
width, |
|
|
|
|
dst_pos, |
|
|
|
|
src_pos, |
|
|
|
|
src2_pos: 0, |
|
|
|
|
}; |
|
|
|
|
mask.validate(self.start_pos)?; |
|
|
|
|
|
|
|
|
|
Ok(Some((wr, rd, mask))) |
|
|
|
|
} else { |
|
|
|
|
Err(CrsnError::Parse("Instruction needs 1 (RW) or 2 (Wr Rd) arguments!".into(), self.start_pos.clone())) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
Ok(None) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Parse a swap-type binary instruction operands (i.e. exchange) with bit masks
|
|
|
|
|
/// Accepts (RdWr, RdWr)
|
|
|
|
|
pub fn parse_masked_rdwr_rdwr(&mut self, keyword: &str, prefix: &str) -> Result<Option<(RdWr, RdWr, BitMask)>, CrsnError> { |
|
|
|
|
if let Some(s) = keyword.strip_prefix(prefix) { |
|
|
|
|
let width = if s.is_empty() { |
|
|
|
|
(std::mem::size_of::<Value>() as u32) * 8 |
|
|
|
|
} else { |
|
|
|
|
s.parse().err_pos(self.start_pos)? |
|
|
|
|
}; |
|
|
|
|
if self.len() == 2 { |
|
|
|
|
let (wr1, dst_pos) = self.next_rdwr_offset()?; |
|
|
|
|
let (wr2, src_pos) = self.next_rdwr_offset()?; |
|
|
|
|
|
|
|
|
|
let mask = BitMask { |
|
|
|
|
width, |
|
|
|
|
dst_pos, |
|
|
|
|
src_pos, |
|
|
|
|
src2_pos: 0, |
|
|
|
|
}; |
|
|
|
|
mask.validate(self.start_pos)?; |
|
|
|
|
|
|
|
|
|
Ok(Some((wr1, wr2, mask))) |
|
|
|
|
} else { |
|
|
|
|
Err(CrsnError::Parse("Instruction needs 2 (RW RW) arguments!".into(), self.start_pos.clone())) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
Ok(None) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Parse combining binary instruction operands (i.e. add) without masks
|
|
|
|
|
pub fn parse_wr_rd_rd(&mut self) -> Result<(Wr, Rd, Rd), CrsnError> { |
|
|
|
|
if self.len() == 2 { |
|
|
|
|
let rw = self.next_rdwr()?; |
|
|
|
|
let rd = self.next_rd()?; |
|
|
|
|
Ok((rw.wr(), rw.rd(), rd)) |
|
|
|
|
} else if self.len() == 3 { |
|
|
|
|
let wr = self.next_wr()?; |
|
|
|
|
let rd1 = self.next_rd()?; |
|
|
|
|
let rd2 = self.next_rd()?; |
|
|
|
|
Ok((wr, rd1, rd2)) |
|
|
|
|
} else { |
|
|
|
|
Err(CrsnError::Parse("Instruction needs 2 (RW Rd) or 3 (Wr Rd Rd) arguments!".into(), self.start_pos.clone())) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Parse unary instruction operands (i.e. complement) without masks
|
|
|
|
|
pub fn parse_wr_rd(&mut self) -> Result<(Wr, Rd), CrsnError> { |
|
|
|
|
if self.len() == 1 { |
|
|
|
|
let rw = self.next_rdwr()?; |
|
|
|
|
Ok((rw.wr(), rw.rd())) |
|
|
|
|
} else if self.len() == 2 { |
|
|
|
|
let wr = self.next_wr()?; |
|
|
|
|
let rd = self.next_rd()?; |
|
|
|
|
Ok((wr, rd)) |
|
|
|
|
} else { |
|
|
|
|
Err(CrsnError::Parse("Instruction needs 1 (RW) or 2 (Wr Rd) arguments!".into(), self.start_pos.clone())) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Parse a swap-type binary instruction operands (i.e. exchange) without masks
|
|
|
|
|
pub fn parse_rdwr_rdwr(&mut self, _keyword: &str, _prefix: &str, _pos: &SourcePosition) -> Result<(RdWr, RdWr), CrsnError> { |
|
|
|
|
if self.len() == 2 { |
|
|
|
|
let rw1 = self.next_rdwr()?; |
|
|
|
|
let rw2 = self.next_rdwr()?; |
|
|
|
|
Ok((rw1, rw2)) |
|
|
|
|
} else { |
|
|
|
|
Err(CrsnError::Parse("Instruction needs 2 (RW RW) arguments!".into(), self.start_pos.clone())) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|