renames, improve module API (avoid cloning)

pull/21/head
Ondřej Hruška 4 years ago
parent f015104b95
commit 44e7cd3a8f
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 28
      crsn/src/asm/instr/flatten.rs
  2. 4
      crsn/src/asm/instr/mod.rs
  3. 26
      crsn/src/asm/instr/op.rs
  4. 98
      crsn/src/asm/mod.rs
  5. 65
      crsn/src/asm/parse/arg_parser.rs
  6. 8
      crsn/src/asm/parse/mod.rs
  7. 4
      crsn/src/asm/parse/parse_cond.rs
  8. 7
      crsn/src/asm/parse/parse_instr.rs
  9. 63
      crsn/src/asm/parse/parse_op.rs
  10. 4
      crsn/src/asm/parse/parse_routines.rs
  11. 220
      crsn_arith/src/parse.rs

@ -4,15 +4,15 @@ use std::sync::atomic::AtomicU32;
use crate::asm::data::{Rd, SrcDisp}; use crate::asm::data::{Rd, SrcDisp};
use crate::asm::data::literal::{Label, Value}; use crate::asm::data::literal::{Label, Value};
use crate::asm::error::{AsmError, Error}; use crate::asm::error::{AsmError, Error};
use crate::asm::instr::{Cond, HLOp, Instr, Op, Routine}; use crate::asm::instr::{Cond, OpWrapper, Instr, Op, Routine};
/// A trait for something that can turn into multiple instructions /// A trait for something that can turn into multiple instructions
pub trait Flatten { pub trait Flatten {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<HLOp>, Error>; fn flatten(self, label_num: &AtomicU32) -> Result<Vec<OpWrapper>, Error>;
} }
impl Flatten for Instr { impl Flatten for Instr {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<HLOp>, Error> { fn flatten(self, label_num: &AtomicU32) -> Result<Vec<OpWrapper>, Error> {
let mut ops = vec![self.op]; let mut ops = vec![self.op];
if let Some(branches) = self.branches { if let Some(branches) = self.branches {
@ -29,18 +29,18 @@ impl Flatten for Instr {
} else { } else {
Label::unique(label_num) Label::unique(label_num)
}; };
ops.push(HLOp::JumpIf(!cond, next_lbl.clone())); ops.push(OpWrapper::JumpIf(!cond, next_lbl.clone()));
for branch_instr in branch { for branch_instr in branch {
ops.extend(branch_instr.flatten(label_num)?); ops.extend(branch_instr.flatten(label_num)?);
} }
if cnt != branch_count - 1 { if cnt != branch_count - 1 {
ops.push(HLOp::Jump(end_lbl.clone())); ops.push(OpWrapper::Jump(end_lbl.clone()));
ops.push(HLOp::Label(next_lbl)); ops.push(OpWrapper::Label(next_lbl));
} }
} }
ops.push(HLOp::Label(end_lbl)); ops.push(OpWrapper::Label(end_lbl));
} }
Ok(ops) Ok(ops)
@ -48,7 +48,7 @@ impl Flatten for Instr {
} }
impl Flatten for Routine { impl Flatten for Routine {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<HLOp>, Error> { fn flatten(self, label_num: &AtomicU32) -> Result<Vec<OpWrapper>, Error> {
let mut ops = vec![ let mut ops = vec![
Op::Routine(self.name.clone()).into(), Op::Routine(self.name.clone()).into(),
]; ];
@ -63,10 +63,10 @@ impl Flatten for Routine {
} }
/// Convert jumps to relative skips /// Convert jumps to relative skips
pub fn lower(ops: Vec<HLOp>) -> Result<Vec<Op>, Error> { pub fn lower(ops: Vec<OpWrapper>) -> Result<Vec<Op>, Error> {
let mut label_positions = HashMap::<Label, usize>::new(); let mut label_positions = HashMap::<Label, usize>::new();
for (n, op) in ops.iter().enumerate() { for (n, op) in ops.iter().enumerate() {
if let HLOp::Label(name) = op { if let OpWrapper::Label(name) = op {
label_positions.insert(name.clone(), n - label_positions.len()); label_positions.insert(name.clone(), n - label_positions.len());
} }
} }
@ -75,10 +75,10 @@ pub fn lower(ops: Vec<HLOp>) -> Result<Vec<Op>, Error> {
let mut skipped = 0; let mut skipped = 0;
for (n, op) in ops.into_iter().enumerate() { for (n, op) in ops.into_iter().enumerate() {
match op { match op {
HLOp::Label(_) => { OpWrapper::Label(_) => {
skipped += 1; skipped += 1;
} }
HLOp::Jump(target) => { OpWrapper::Jump(target) => {
if let Some(dest) = label_positions.get(&target) { if let Some(dest) = label_positions.get(&target) {
let skip = *dest as isize - n as isize + skipped; let skip = *dest as isize - n as isize + skipped;
cleaned.push(Op::Skip(Rd::new(SrcDisp::Immediate(skip as Value)))); cleaned.push(Op::Skip(Rd::new(SrcDisp::Immediate(skip as Value))));
@ -86,7 +86,7 @@ pub fn lower(ops: Vec<HLOp>) -> Result<Vec<Op>, Error> {
return Err(Error::Asm(AsmError::LabelNotDefined(target))); return Err(Error::Asm(AsmError::LabelNotDefined(target)));
} }
} }
HLOp::JumpIf(cond, target) => { OpWrapper::JumpIf(cond, target) => {
if let Some(dest) = label_positions.get(&target) { if let Some(dest) = label_positions.get(&target) {
let skip = *dest as isize - n as isize + skipped; let skip = *dest as isize - n as isize + skipped;
cleaned.push(Op::SkipIf(cond, Rd::new(SrcDisp::Immediate(skip as Value)))); cleaned.push(Op::SkipIf(cond, Rd::new(SrcDisp::Immediate(skip as Value))));
@ -94,7 +94,7 @@ pub fn lower(ops: Vec<HLOp>) -> Result<Vec<Op>, Error> {
return Err(Error::Asm(AsmError::LabelNotDefined(target))); return Err(Error::Asm(AsmError::LabelNotDefined(target)));
} }
} }
HLOp::L(op) => { OpWrapper::Op(op) => {
cleaned.push(op); cleaned.push(op);
} }
} }

@ -1,7 +1,7 @@
pub use cond::Cond; pub use cond::Cond;
pub use flatten::Flatten; pub use flatten::Flatten;
pub use flatten::lower; pub use flatten::lower;
pub use op::HLOp; pub use op::OpWrapper;
pub use op::Op; pub use op::Op;
use crate::asm::data::literal::RoutineName; use crate::asm::data::literal::RoutineName;
@ -13,7 +13,7 @@ mod flatten;
/// A higher-level instruction /// A higher-level instruction
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Instr { pub struct Instr {
pub op: HLOp, pub op: OpWrapper,
pub branches: Option<Vec<(Cond, Vec<Instr>)>>, pub branches: Option<Vec<(Cond, Vec<Instr>)>>,
} }

@ -14,10 +14,11 @@ use crate::asm::instr::Cond;
use crate::runtime::fault::Fault; use crate::runtime::fault::Fault;
use crate::runtime::frame::{CallStack, StackFrame}; use crate::runtime::frame::{CallStack, StackFrame};
use crate::runtime::program::Program; use crate::runtime::program::Program;
use crate::asm::parse::arg_parser::ArgParser;
/// A higher level simple opration /// A higher level simple opration
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum HLOp { pub enum OpWrapper {
/// Mark a jump target. /// Mark a jump target.
Label(Label), Label(Label),
/// Jump to a label /// Jump to a label
@ -25,7 +26,7 @@ pub enum HLOp {
/// Jump to a label if a flag is set /// Jump to a label if a flag is set
JumpIf(Cond, Label), JumpIf(Cond, Label),
/// Low level op /// Low level op
L(Op), Op(Op),
} }
/// A low level instruction /// A low level instruction
@ -65,9 +66,9 @@ pub enum Op {
} }
/// Make "into" work /// Make "into" work
impl From<Op> for HLOp { impl From<Op> for OpWrapper {
fn from(op: Op) -> Self { fn from(op: Op) -> Self {
HLOp::L(op) OpWrapper::Op(op)
} }
} }
@ -76,7 +77,20 @@ pub trait OpTrait: Clone + Debug + Send + 'static {
fn execute(&self, program: &Program, call_stack: &mut CallStack, frame: &mut StackFrame) -> Result<(), Fault>; fn execute(&self, program: &Program, call_stack: &mut CallStack, frame: &mut StackFrame) -> Result<(), Fault>;
} }
pub enum ParseOpResult {
Parsed(Box<dyn OpTrait>),
Unknown(ArgParser),
}
#[clonable] #[clonable]
pub trait OpParser: Clone + Debug + Send + 'static { pub trait AsmModule: Clone + Debug + Send + 'static {
fn parse_op(&self, keyword: &str, far: bool, arg_tokens: Vec<Sexp>) -> Result<Box<dyn OpTrait>, Error>; /// Get name of the module
fn name(&self) -> &'static str;
/// Parse an op.
/// If the keyword matches and the function decides to parse the instruction, it must consume
/// the argument list and either return Ok or Err.
///
/// If the instruction keyword is not recognized, return Unknown with the unchanged argument list.
fn parse_op(&self, keyword: &str, arg_tokens: ArgParser) -> Result<ParseOpResult, Error>;
} }

@ -1,5 +1,5 @@
use crate::asm::instr::{lower, Op}; use crate::asm::instr::{lower, Op};
use crate::asm::instr::op::OpParser; use crate::asm::instr::op::AsmModule;
pub mod data; pub mod data;
pub mod error; pub mod error;
@ -8,7 +8,7 @@ pub mod parse;
pub mod patches; pub mod patches;
/// Parse a program from string and assemble a low level instruction sequence from it. /// Parse a program from string and assemble a low level instruction sequence from it.
pub fn assemble(source: &str, parsers: &[Box<dyn OpParser>]) -> Result<Vec<Op>, error::Error> { pub fn assemble(source: &str, parsers: &[Box<dyn AsmModule>]) -> Result<Vec<Op>, error::Error> {
let parsed = parse::parse(source, parsers)?; let parsed = parse::parse(source, parsers)?;
Ok(lower(parsed)?) Ok(lower(parsed)?)
} }
@ -19,7 +19,7 @@ mod tests {
use crate::asm::data::{DstDisp, Rd, Register, SrcDisp, Wr}; use crate::asm::data::{DstDisp, Rd, Register, SrcDisp, Wr};
use crate::asm::data::literal::{Addr, Label}; use crate::asm::data::literal::{Addr, Label};
use crate::asm::instr::{Flatten, HLOp, Instr, lower, Op}; use crate::asm::instr::{Flatten, OpWrapper, Instr, lower, Op};
use crate::asm::instr::Cond; use crate::asm::instr::Cond;
use crate::asm::parse::{parse, parse_instructions}; use crate::asm::parse::{parse, parse_instructions};
@ -28,7 +28,7 @@ mod tests {
let parsed = parse(" let parsed = parse("
() ()
").unwrap(); ").unwrap();
assert_eq!(Vec::<HLOp>::new(), parsed); assert_eq!(Vec::<OpWrapper>::new(), parsed);
} }
#[test] #[test]
@ -39,8 +39,8 @@ mod tests {
) )
").unwrap(); ").unwrap();
assert_eq!(vec![ assert_eq!(vec![
HLOp::L(Op::Routine("hello".into())), OpWrapper::Op(Op::Routine("hello".into())),
HLOp::L(Op::Barrier(Some("Routine \"hello\" overrun".into()))) OpWrapper::Op(Op::Barrier(Some("Routine \"hello\" overrun".into())))
], parsed); ], parsed);
let parsed = parse(" let parsed = parse("
@ -50,10 +50,10 @@ mod tests {
) )
").unwrap(); ").unwrap();
assert_eq!(vec![ assert_eq!(vec![
HLOp::L(Op::Routine("hello".into())), OpWrapper::Op(Op::Routine("hello".into())),
HLOp::L(Op::Barrier(Some("Routine \"hello\" overrun".into()))), OpWrapper::Op(Op::Barrier(Some("Routine \"hello\" overrun".into()))),
HLOp::L(Op::Routine("world".into())), OpWrapper::Op(Op::Routine("world".into())),
HLOp::L(Op::Barrier(Some("Routine \"world\" overrun".into()))) OpWrapper::Op(Op::Barrier(Some("Routine \"world\" overrun".into())))
], parsed); ], parsed);
} }
@ -79,73 +79,73 @@ mod tests {
) )
").unwrap(); ").unwrap();
assert_eq!(vec![ assert_eq!(vec![
HLOp::L(Op::Routine("move".into())), OpWrapper::Op(Op::Routine("move".into())),
// (mov r0 r1) // (mov r0 r1)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(0))), Wr::new(DstDisp::Register(Register::Gen(0))),
Rd::new(SrcDisp::Register(Register::Gen(1))), Rd::new(SrcDisp::Register(Register::Gen(1))),
)), )),
// (mov r15 7) // (mov r15 7)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(15))), Wr::new(DstDisp::Register(Register::Gen(15))),
Rd::new(SrcDisp::Immediate(7)), Rd::new(SrcDisp::Immediate(7)),
)), )),
// (mov r15 0xabcd) // (mov r15 0xabcd)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(15))), Wr::new(DstDisp::Register(Register::Gen(15))),
Rd::new(SrcDisp::Immediate(0xabcd)), Rd::new(SrcDisp::Immediate(0xabcd)),
)), )),
// (mov r7 0b11110000) // (mov r7 0b11110000)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(7))), Wr::new(DstDisp::Register(Register::Gen(7))),
Rd::new(SrcDisp::Immediate(0b11110000)), Rd::new(SrcDisp::Immediate(0b11110000)),
)), )),
// (mov r7 arg1) // (mov r7 arg1)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(7))), Wr::new(DstDisp::Register(Register::Gen(7))),
Rd::new(SrcDisp::Register(Register::Arg(1))), Rd::new(SrcDisp::Register(Register::Arg(1))),
)), )),
// (mov r255 arg255) // (mov r255 arg255)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(255))), Wr::new(DstDisp::Register(Register::Gen(255))),
Rd::new(SrcDisp::Register(Register::Arg(255))), Rd::new(SrcDisp::Register(Register::Arg(255))),
)), )),
// (mov r7 res0) // (mov r7 res0)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(7))), Wr::new(DstDisp::Register(Register::Gen(7))),
Rd::new(SrcDisp::Register(Register::Res(0))), Rd::new(SrcDisp::Register(Register::Res(0))),
)), )),
// (mov r7 res255) // (mov r7 res255)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(7))), Wr::new(DstDisp::Register(Register::Gen(7))),
Rd::new(SrcDisp::Register(Register::Res(255))), Rd::new(SrcDisp::Register(Register::Res(255))),
)), )),
// (mov @r0 @r0) // (mov @r0 @r0)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), Wr::new(DstDisp::RegisterPtr(Register::Gen(0))),
Rd::new(SrcDisp::RegisterPtr(Register::Gen(0))), Rd::new(SrcDisp::RegisterPtr(Register::Gen(0))),
)), )),
// (mov @r0 @arg0) // (mov @r0 @arg0)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), Wr::new(DstDisp::RegisterPtr(Register::Gen(0))),
Rd::new(SrcDisp::RegisterPtr(Register::Arg(0))), Rd::new(SrcDisp::RegisterPtr(Register::Arg(0))),
)), )),
// (mov @r0 @res0) // (mov @r0 @res0)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), Wr::new(DstDisp::RegisterPtr(Register::Gen(0))),
Rd::new(SrcDisp::RegisterPtr(Register::Res(0))), Rd::new(SrcDisp::RegisterPtr(Register::Res(0))),
)), )),
// (mov @123456 @0x123456) // (mov @123456 @0x123456)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::ImmediatePtr(Addr(123456))), Wr::new(DstDisp::ImmediatePtr(Addr(123456))),
Rd::new(SrcDisp::ImmediatePtr(Addr(0x123456))), Rd::new(SrcDisp::ImmediatePtr(Addr(0x123456))),
)), )),
// (mov @0b010101 @0b010101) // (mov @0b010101 @0b010101)
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::ImmediatePtr(Addr(0b010101))), Wr::new(DstDisp::ImmediatePtr(Addr(0b010101))),
Rd::new(SrcDisp::ImmediatePtr(Addr(0b010101))), Rd::new(SrcDisp::ImmediatePtr(Addr(0b010101))),
)), )),
HLOp::L(Op::Barrier(Some("Routine \"move\" overrun".into()))), OpWrapper::Op(Op::Barrier(Some("Routine \"move\" overrun".into()))),
], parsed); ], parsed);
} }
@ -153,7 +153,7 @@ mod tests {
Ok(parse_instructions(vec![sexp::parse(src)?])?.remove(0)) Ok(parse_instructions(vec![sexp::parse(src)?])?.remove(0))
} }
fn parse_single_op(src: &str) -> anyhow::Result<Vec<HLOp>> { fn parse_single_op(src: &str) -> anyhow::Result<Vec<OpWrapper>> {
let num = AtomicU32::new(0); let num = AtomicU32::new(0);
Ok(parse_single_instr(src)?.flatten(&num)?) Ok(parse_single_instr(src)?.flatten(&num)?)
} }
@ -162,7 +162,7 @@ mod tests {
fn test_parse_single() { fn test_parse_single() {
let parsed = parse_single_op("(mov r0 r1)").unwrap(); let parsed = parse_single_op("(mov r0 r1)").unwrap();
assert_eq!(vec![ assert_eq!(vec![
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(0))), Wr::new(DstDisp::Register(Register::Gen(0))),
Rd::new(SrcDisp::Register(Register::Gen(1))), Rd::new(SrcDisp::Register(Register::Gen(1))),
)), )),
@ -176,7 +176,7 @@ mod tests {
").unwrap(); ").unwrap();
assert_eq!( assert_eq!(
Instr { Instr {
op: HLOp::L(Op::Cmp( op: OpWrapper::Op(Op::Cmp(
Rd::new(SrcDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))),
Rd::new(SrcDisp::Register(Register::Gen(1))), Rd::new(SrcDisp::Register(Register::Gen(1))),
)), )),
@ -185,14 +185,14 @@ mod tests {
Cond::Equal, Cond::Equal,
vec![ vec![
Instr { Instr {
op: HLOp::L(Op::Mov( op: OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(0))), Wr::new(DstDisp::Register(Register::Gen(0))),
Rd::new(SrcDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))),
)), )),
branches: None, branches: None,
}, },
Instr { Instr {
op: HLOp::L(Op::Mov( op: OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(1))), Wr::new(DstDisp::Register(Register::Gen(1))),
Rd::new(SrcDisp::Register(Register::Gen(2))), Rd::new(SrcDisp::Register(Register::Gen(2))),
)), )),
@ -204,14 +204,14 @@ mod tests {
Cond::Greater, Cond::Greater,
vec![ vec![
Instr { Instr {
op: HLOp::L(Op::Mov( op: OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(0))), Wr::new(DstDisp::Register(Register::Gen(0))),
Rd::new(SrcDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))),
)), )),
branches: None, branches: None,
}, },
Instr { Instr {
op: HLOp::L(Op::Mov( op: OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(1))), Wr::new(DstDisp::Register(Register::Gen(1))),
Rd::new(SrcDisp::Register(Register::Gen(1))), Rd::new(SrcDisp::Register(Register::Gen(1))),
)), )),
@ -237,31 +237,31 @@ mod tests {
").unwrap(); ").unwrap();
assert_eq!( assert_eq!(
vec![ vec![
HLOp::L(Op::Cmp( OpWrapper::Op(Op::Cmp(
Rd::new(SrcDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))),
Rd::new(SrcDisp::Register(Register::Gen(1))), Rd::new(SrcDisp::Register(Register::Gen(1))),
)), )),
HLOp::JumpIf(Cond::NotEqual, Label::Numbered(1)), OpWrapper::JumpIf(Cond::NotEqual, Label::Numbered(1)),
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(0))), Wr::new(DstDisp::Register(Register::Gen(0))),
Rd::new(SrcDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))),
)), )),
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(1))), Wr::new(DstDisp::Register(Register::Gen(1))),
Rd::new(SrcDisp::Register(Register::Gen(2))), Rd::new(SrcDisp::Register(Register::Gen(2))),
)), )),
HLOp::Jump(Label::Numbered(0)), OpWrapper::Jump(Label::Numbered(0)),
HLOp::Label(Label::Numbered(1)), OpWrapper::Label(Label::Numbered(1)),
HLOp::JumpIf(Cond::LowerOrEqual, Label::Numbered(0)), OpWrapper::JumpIf(Cond::LowerOrEqual, Label::Numbered(0)),
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(0))), Wr::new(DstDisp::Register(Register::Gen(0))),
Rd::new(SrcDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))),
)), )),
HLOp::L(Op::Mov( OpWrapper::Op(Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(1))), Wr::new(DstDisp::Register(Register::Gen(1))),
Rd::new(SrcDisp::Register(Register::Gen(1))), Rd::new(SrcDisp::Register(Register::Gen(1))),
)), )),
HLOp::Label(Label::Numbered(0)), OpWrapper::Label(Label::Numbered(0)),
], parsed); ], parsed);
} }
@ -286,15 +286,15 @@ mod tests {
assert_eq!( assert_eq!(
vec![ vec![
Op::Routine("foo".into()).into(), Op::Routine("foo".into()).into(),
HLOp::Label(Label::Named("foo".to_string())), OpWrapper::Label(Label::Named("foo".to_string())),
HLOp::Label(Label::Named("unused".to_string())), OpWrapper::Label(Label::Named("unused".to_string())),
HLOp::Label(Label::Named("whatever".to_string())), OpWrapper::Label(Label::Named("whatever".to_string())),
Op::Mov( Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(0))), Wr::new(DstDisp::Register(Register::Gen(0))),
Rd::new(SrcDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))),
).into(), ).into(),
HLOp::Jump(Label::Named("foo".to_string())), OpWrapper::Jump(Label::Named("foo".to_string())),
HLOp::Jump(Label::Named("foo".to_string())), OpWrapper::Jump(Label::Named("foo".to_string())),
Op::Mov( Op::Mov(
Wr::new(DstDisp::Register(Register::Gen(0))), Wr::new(DstDisp::Register(Register::Gen(0))),
Rd::new(SrcDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))),
@ -303,8 +303,8 @@ mod tests {
Wr::new(DstDisp::Register(Register::Gen(0))), Wr::new(DstDisp::Register(Register::Gen(0))),
Rd::new(SrcDisp::Register(Register::Gen(0))), Rd::new(SrcDisp::Register(Register::Gen(0))),
).into(), ).into(),
HLOp::Jump(Label::Named("whatever".to_string())), OpWrapper::Jump(Label::Named("whatever".to_string())),
HLOp::JumpIf(Cond::Equal, Label::Named("whatever".to_string())), OpWrapper::JumpIf(Cond::Equal, Label::Named("whatever".to_string())),
Op::Barrier(Some("Routine \"foo\" overrun".into())).into(), Op::Barrier(Some("Routine \"foo\" overrun".into())).into(),
], parsed); ], parsed);

@ -0,0 +1,65 @@
use sexp::Sexp;
use crate::asm::data::{Rd, Wr};
use crate::asm::parse::parse_data::{parse_rd, parse_wr};
use crate::asm::parse::sexp_expect::expect_string_atom;
/// Utility for argument parsing
pub struct ArgParser {
orig_len: usize,
args: Vec<Sexp>,
}
impl IntoIterator for ArgParser {
type Item = Sexp;
type IntoIter = std::vec::IntoIter<Sexp>;
fn into_iter(self) -> Self::IntoIter {
self.args.into_iter()
}
}
impl ArgParser {
/// Create a new argument parser
pub fn new(mut args: Vec<Sexp>) -> Self {
args.reverse();
Self {
orig_len: args.len(),
args
}
}
/// Get remaining items count
pub fn len(&self) -> usize {
self.args.len()
}
/// Get len before parsing started
pub fn orig_len(&self) -> usize {
self.orig_len
}
/// Check if parsing started
pub fn parsing_started(&self) -> bool {
self.args.len() != self.orig_len
}
/// Get the next entry
pub fn next(&mut self) -> Option<Sexp> {
self.args.pop()
}
/// Get the next string entry
pub fn next_string(&mut self) -> anyhow::Result<String> {
Ok(expect_string_atom(self.next())?)
}
/// Get the next entry as read location
pub fn next_rd(&mut self) -> anyhow::Result<Rd> {
parse_rd(self.next())
}
/// Get the next entry as write location
pub fn next_wr(&mut self) -> anyhow::Result<Wr> {
parse_wr(self.next())
}
}

@ -4,8 +4,8 @@ pub use parse_instr::parse_instructions;
use parse_routines::parse_routines; use parse_routines::parse_routines;
use crate::asm::error::Error; use crate::asm::error::Error;
use crate::asm::instr::{Flatten, HLOp, Routine}; use crate::asm::instr::{Flatten, OpWrapper, Routine};
use crate::asm::instr::op::OpParser; use crate::asm::instr::op::AsmModule;
use crate::asm::parse::sexp_expect::expect_list; use crate::asm::parse::sexp_expect::expect_list;
mod parse_cond; mod parse_cond;
@ -15,7 +15,9 @@ mod parse_routines;
pub mod sexp_expect; pub mod sexp_expect;
mod parse_op; mod parse_op;
pub fn parse(source: &str, parsers: &[Box<dyn OpParser>]) -> Result<Vec<HLOp>, Error> { pub mod arg_parser;
pub fn parse(source: &str, parsers: &[Box<dyn AsmModule>]) -> Result<Vec<OpWrapper>, Error> {
let root = sexp::parse(source)?; let root = sexp::parse(source)?;
let subs: Vec<Routine> = parse_routines(expect_list(Some(root), true)?, parsers)?; let subs: Vec<Routine> = parse_routines(expect_list(Some(root), true)?, parsers)?;

@ -2,12 +2,12 @@ use sexp::Sexp;
use crate::asm::error::Error; use crate::asm::error::Error;
use crate::asm::instr::{Cond, cond, Instr}; use crate::asm::instr::{Cond, cond, Instr};
use crate::asm::instr::op::OpParser; use crate::asm::instr::op::AsmModule;
use crate::asm::parse::parse_instr::parse_instructions; use crate::asm::parse::parse_instr::parse_instructions;
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom}; use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
use crate::asm::patches::TryRemove; use crate::asm::patches::TryRemove;
pub fn parse_cond_branch(tok: Sexp, parsers: &[Box<dyn OpParser>]) -> Result<(Cond, Vec<Instr>), Error> { pub fn parse_cond_branch(tok: Sexp, parsers: &[Box<dyn AsmModule>]) -> Result<(Cond, Vec<Instr>), Error> {
let mut list = expect_list(Some(tok), false)?; let mut list = expect_list(Some(tok), false)?;
let kw = expect_string_atom(list.try_remove(0))?; let kw = expect_string_atom(list.try_remove(0))?;

@ -2,14 +2,15 @@ use sexp::Sexp;
use crate::asm::error::Error; use crate::asm::error::Error;
use crate::asm::instr::Instr; use crate::asm::instr::Instr;
use crate::asm::instr::op::OpParser; use crate::asm::instr::op::AsmModule;
use crate::asm::parse::parse_cond::parse_cond_branch; use crate::asm::parse::parse_cond::parse_cond_branch;
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom}; use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
use crate::asm::patches::SexpIsA; use crate::asm::patches::SexpIsA;
use super::parse_op::parse_op; use super::parse_op::parse_op;
use crate::asm::parse::arg_parser::ArgParser;
pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn OpParser>]) -> Result<Vec<Instr>, Error> { pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn AsmModule>]) -> Result<Vec<Instr>, Error> {
let mut parsed = vec![]; let mut parsed = vec![];
for expr in instrs { for expr in instrs {
let tokens = expect_list(Some(expr), false)?; let tokens = expect_list(Some(expr), false)?;
@ -25,7 +26,7 @@ pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn OpParser>]) -> R
false false
}; };
let arg_tokens = toki.clone().take_while(|e| e.is_atom()).collect::<Vec<_>>(); let arg_tokens = ArgParser::new(toki.clone().take_while(|e| e.is_atom()).collect());
let branch_tokens = toki let branch_tokens = toki
.skip_while(|e| e.is_atom()) .skip_while(|e| e.is_atom())
.take_while(|e| e.is_list()); .take_while(|e| e.is_list());

@ -2,33 +2,33 @@ use sexp::Sexp;
use crate::asm::data::literal::{Label, RoutineName}; use crate::asm::data::literal::{Label, RoutineName};
use crate::asm::error::{AsmError, Error}; use crate::asm::error::{AsmError, Error};
use crate::asm::instr::{HLOp, Op}; use crate::asm::instr::{OpWrapper, Op};
use crate::asm::instr::cond::parse_cond; use crate::asm::instr::cond::parse_cond;
use crate::asm::instr::op::OpParser; use crate::asm::instr::op::{AsmModule, ParseOpResult};
use crate::asm::parse::parse_data::{parse_label, parse_rd, parse_wr}; use crate::asm::parse::parse_data::{parse_label, parse_rd, parse_wr};
use crate::asm::parse::sexp_expect::expect_string_atom; use crate::asm::parse::sexp_expect::expect_string_atom;
use crate::asm::parse::arg_parser::ArgParser;
pub fn parse_op(keyword: &str, far: bool, arg_tokens_slice: Vec<Sexp>, parsers: &[Box<dyn OpParser>]) -> Result<HLOp, Error> { pub fn parse_op(keyword: &str, far: bool, mut arg_tokens: ArgParser, parsers: &[Box<dyn AsmModule>]) -> Result<OpWrapper, Error> {
let mut arg_tokens = arg_tokens_slice.clone().into_iter();
Ok(match keyword { Ok(match keyword {
"j" => { "j" => {
let dest = parse_label(arg_tokens.next())?; let dest = parse_label(arg_tokens.next())?;
if far { if far {
HLOp::L(Op::FarJump(dest)) OpWrapper::Op(Op::FarJump(dest))
} else { } else {
HLOp::Jump(dest) OpWrapper::Jump(dest)
} }
} }
"call" => { "call" => {
let dest = RoutineName(expect_string_atom(arg_tokens.next())?); let dest = RoutineName(arg_tokens.next_string()?);
let mut args = vec![]; let mut args = vec![];
for t in arg_tokens { for t in arg_tokens {
args.push(parse_rd(Some(t))?); args.push(parse_rd(Some(t))?);
} }
HLOp::L(Op::Call(dest, args)) OpWrapper::Op(Op::Call(dest, args))
} }
"ret" => { "ret" => {
@ -36,48 +36,48 @@ pub fn parse_op(keyword: &str, far: bool, arg_tokens_slice: Vec<Sexp>, parsers:
for t in arg_tokens { for t in arg_tokens {
args.push(parse_rd(Some(t))?); args.push(parse_rd(Some(t))?);
} }
HLOp::L(Op::Ret(args)) OpWrapper::Op(Op::Ret(args))
} }
"routine" => { "routine" => {
let dest = RoutineName(expect_string_atom(arg_tokens.next())?); let dest = RoutineName(arg_tokens.next_string()?);
HLOp::L(Op::Routine(dest)) OpWrapper::Op(Op::Routine(dest))
} }
"s" => { "s" => {
HLOp::L(Op::Skip(parse_rd(arg_tokens.next())?)) OpWrapper::Op(Op::Skip(arg_tokens.next_rd()?))
} }
"sif" => { "sif" => {
let cond = parse_cond(&expect_string_atom(arg_tokens.next())?)?; let cond = parse_cond(&arg_tokens.next_string()?)?;
let offs = parse_rd(arg_tokens.next())?; let offs = arg_tokens.next_rd()?;
HLOp::L(Op::SkipIf(cond, offs)) OpWrapper::Op(Op::SkipIf(cond, offs))
} }
"jif" => { "jif" => {
let cond = parse_cond(&expect_string_atom(arg_tokens.next())?)?; let cond = parse_cond(&arg_tokens.next_string()?)?;
let dest = parse_label(arg_tokens.next())?; let dest = parse_label(arg_tokens.next())?;
HLOp::JumpIf(cond, dest) OpWrapper::JumpIf(cond, dest)
} }
"barrier" => { "barrier" => {
HLOp::L(Op::Barrier(match arg_tokens.next() { OpWrapper::Op(Op::Barrier(match arg_tokens.next() {
None => None, None => None,
Some(s) => Some(expect_string_atom(Some(s))?.into()), Some(s) => Some(expect_string_atom(Some(s))?.into()),
})) }))
} }
"fault" => { "fault" => {
HLOp::L(Op::Fault(match arg_tokens.next() { OpWrapper::Op(Op::Fault(match arg_tokens.next() {
None => None, None => None,
Some(s) => Some(expect_string_atom(Some(s))?.into()), Some(s) => Some(expect_string_atom(Some(s))?.into()),
})) }))
} }
"ld" => { "ld" => {
HLOp::L(Op::Move { OpWrapper::Op(Op::Move {
dst: parse_wr(arg_tokens.next())?, dst: arg_tokens.next_wr()?,
src: parse_rd(arg_tokens.next())?, src: arg_tokens.next_rd()?,
}) })
} }
@ -85,19 +85,22 @@ pub fn parse_op(keyword: &str, far: bool, arg_tokens_slice: Vec<Sexp>, parsers:
if let Some(label) = other.strip_prefix(':') { if let Some(label) = other.strip_prefix(':') {
let label = Label::Named(label.to_string()); let label = Label::Named(label.to_string());
if far { if far {
HLOp::L(Op::FarLabel(label)) OpWrapper::Op(Op::FarLabel(label))
} else { } else {
HLOp::Label(label) OpWrapper::Label(label)
} }
} else { } else {
for p in parsers { for p in parsers {
match p.parse_op(keyword, far, arg_tokens_slice.clone()) { arg_tokens = match p.parse_op(keyword, arg_tokens) {
Ok(op) => return Ok(HLOp::L(Op::Extension(op))), Ok(ParseOpResult::Parsed(op)) => return Ok(OpWrapper::Op(Op::Extension(op))),
Err(Error::Asm(AsmError::UnknownInstruction)) => { Ok(ParseOpResult::Unknown(to_reuse)) => {
/* ok, try another */ if to_reuse.parsing_started() {
panic!("Module \"{}\" started parsing {}, but returned Unknown!", p.name(), keyword);
} }
Err(other) => { to_reuse
return Err(other); }
Err(err) => {
return Err(err);
} }
} }
} }

@ -2,13 +2,13 @@ use sexp::Sexp;
use crate::asm::data::literal::RoutineName; use crate::asm::data::literal::RoutineName;
use crate::asm::error::Error; use crate::asm::error::Error;
use crate::asm::instr::op::OpParser; use crate::asm::instr::op::AsmModule;
use crate::asm::instr::Routine; use crate::asm::instr::Routine;
use crate::asm::parse::parse_instr::parse_instructions; use crate::asm::parse::parse_instr::parse_instructions;
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom}; use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
use crate::asm::patches::TryRemove; use crate::asm::patches::TryRemove;
pub fn parse_routines(routines: Vec<Sexp>, parsers: &[Box<dyn OpParser>]) -> Result<Vec<Routine>, Error> { pub fn parse_routines(routines: Vec<Sexp>, parsers: &[Box<dyn AsmModule>]) -> Result<Vec<Routine>, Error> {
let mut parsed = vec![]; let mut parsed = vec![];
for rt in routines { for rt in routines {
let mut def = expect_list(Some(rt), false)?; let mut def = expect_list(Some(rt), false)?;

@ -1,10 +1,11 @@
use crsn::asm::data::{Rd, Wr}; use crsn::asm::data::{Rd, Wr};
use crsn::asm::error::{AsmError, Error}; use crsn::asm::error::{AsmError, Error};
use crsn::asm::instr::op::{OpParser, OpTrait}; use crsn::asm::instr::op::{AsmModule, OpTrait, ParseOpResult};
use crsn::asm::parse::parse_data::{parse_rd, parse_wr}; use crsn::asm::parse::parse_data::{parse_rd, parse_wr};
use crsn::sexp::Sexp; use crsn::sexp::Sexp;
use crate::defs::ArithOp; use crate::defs::ArithOp;
use crsn::asm::parse::arg_parser::ArgParser;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ArithOpParser { pub struct ArithOpParser {
@ -12,31 +13,34 @@ pub struct ArithOpParser {
} }
impl ArithOpParser { impl ArithOpParser {
pub fn new() -> Box<dyn OpParser> { pub fn new() -> Box<dyn AsmModule> {
Box::new(Self { Box::new(Self {
_internal: () _internal: ()
}) })
} }
} }
impl OpParser for ArithOpParser { impl AsmModule for ArithOpParser {
fn parse_op(&self, keyword: &str, _far: bool, arg_tokens_sl: Vec<Sexp>) -> Result<Box<dyn OpTrait>, Error> { fn name(&self) -> &'static str {
let mut arg_tokens = arg_tokens_sl.into_iter(); "arith"
Ok(Box::new(match keyword { }
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpResult, Error> {
Ok(ParseOpResult::Parsed(Box::new(match keyword {
"cmp" => { "cmp" => {
ArithOp::Compare { ArithOp::Compare {
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
"tst" => { "tst" => {
let arg = parse_rd(arg_tokens.next())?; let arg = args.next_rd()?;
ArithOp::Test { a: arg } ArithOp::Test { a: arg }
} }
"inc" => { "inc" => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Add { ArithOp::Add {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
@ -45,7 +49,7 @@ impl OpParser for ArithOpParser {
} }
"dec" => { "dec" => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Sub { ArithOp::Sub {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
@ -54,20 +58,20 @@ impl OpParser for ArithOpParser {
} }
"add" => { "add" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Add { ArithOp::Add {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Add { ArithOp::Add {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
_ => { _ => {
@ -77,20 +81,20 @@ impl OpParser for ArithOpParser {
} }
"sub" => { "sub" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Sub { ArithOp::Sub {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Sub { ArithOp::Sub {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
_ => { _ => {
@ -100,20 +104,20 @@ impl OpParser for ArithOpParser {
} }
"mul" => { "mul" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Mul { ArithOp::Mul {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Mul { ArithOp::Mul {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
_ => { _ => {
@ -123,11 +127,11 @@ impl OpParser for ArithOpParser {
} }
"divr" => { "divr" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
let rem = parse_wr(arg_tokens.next())?; let rem = args.next_wr()?;
let div = parse_rd(arg_tokens.next())?; let div = args.next_rd()?;
ArithOp::Div { ArithOp::Div {
dst, dst,
rem, rem,
@ -137,10 +141,10 @@ impl OpParser for ArithOpParser {
} }
4 => { 4 => {
ArithOp::Div { ArithOp::Div {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
rem: parse_wr(arg_tokens.next())?, rem: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
div: parse_rd(arg_tokens.next())?, div: args.next_rd()?,
} }
} }
_ => { _ => {
@ -150,18 +154,18 @@ impl OpParser for ArithOpParser {
} }
"div" => { "div" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Div { ArithOp::Div {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
rem: Wr::discard(), rem: Wr::discard(),
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
div: parse_rd(arg_tokens.next())?, div: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
let div = parse_rd(arg_tokens.next())?; let div = args.next_rd()?;
ArithOp::Div { ArithOp::Div {
dst, dst,
rem: Wr::discard(), rem: Wr::discard(),
@ -176,17 +180,17 @@ impl OpParser for ArithOpParser {
} }
"mod" => { "mod" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Mod { ArithOp::Mod {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
div: parse_rd(arg_tokens.next())?, div: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
let div = parse_rd(arg_tokens.next())?; let div = args.next_rd()?;
ArithOp::Mod { ArithOp::Mod {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
@ -200,20 +204,20 @@ impl OpParser for ArithOpParser {
} }
"and" => { "and" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::And { ArithOp::And {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::And { ArithOp::And {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
_ => { _ => {
@ -223,20 +227,20 @@ impl OpParser for ArithOpParser {
} }
"or" => { "or" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Or { ArithOp::Or {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Or { ArithOp::Or {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
_ => { _ => {
@ -246,20 +250,20 @@ impl OpParser for ArithOpParser {
} }
"xor" => { "xor" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Xor { ArithOp::Xor {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Xor { ArithOp::Xor {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
b: parse_rd(arg_tokens.next())?, b: args.next_rd()?,
} }
} }
_ => { _ => {
@ -269,15 +273,15 @@ impl OpParser for ArithOpParser {
} }
"cpl" => { "cpl" => {
match arg_tokens.len() { match args.len() {
2 => { 2 => {
ArithOp::Cpl { ArithOp::Cpl {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
} }
} }
1 => { 1 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Cpl { ArithOp::Cpl {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
@ -290,24 +294,24 @@ impl OpParser for ArithOpParser {
} }
"rol" => { "rol" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Rol { ArithOp::Rol {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
n: parse_rd(arg_tokens.next())?, n: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Rol { ArithOp::Rol {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
n: parse_rd(arg_tokens.next())?, n: args.next_rd()?,
} }
} }
1 => { 1 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Rol { ArithOp::Rol {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
@ -321,24 +325,24 @@ impl OpParser for ArithOpParser {
} }
"ror" => { "ror" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Ror { ArithOp::Ror {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
n: parse_rd(arg_tokens.next())?, n: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Ror { ArithOp::Ror {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
n: parse_rd(arg_tokens.next())?, n: args.next_rd()?,
} }
} }
1 => { 1 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Ror { ArithOp::Ror {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
@ -352,24 +356,24 @@ impl OpParser for ArithOpParser {
} }
"lsl" | "asl" => { "lsl" | "asl" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Lsl { ArithOp::Lsl {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
n: parse_rd(arg_tokens.next())?, n: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Lsl { ArithOp::Lsl {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
n: parse_rd(arg_tokens.next())?, n: args.next_rd()?,
} }
} }
1 => { 1 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Lsl { ArithOp::Lsl {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
@ -383,24 +387,24 @@ impl OpParser for ArithOpParser {
} }
"lsr" => { "lsr" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Lsr { ArithOp::Lsr {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
n: parse_rd(arg_tokens.next())?, n: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Lsr { ArithOp::Lsr {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
n: parse_rd(arg_tokens.next())?, n: args.next_rd()?,
} }
} }
1 => { 1 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Lsr { ArithOp::Lsr {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
@ -414,24 +418,24 @@ impl OpParser for ArithOpParser {
} }
"asr" => { "asr" => {
match arg_tokens.len() { match args.len() {
3 => { 3 => {
ArithOp::Asr { ArithOp::Asr {
dst: parse_wr(arg_tokens.next())?, dst: args.next_wr()?,
a: parse_rd(arg_tokens.next())?, a: args.next_rd()?,
n: parse_rd(arg_tokens.next())?, n: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Asr { ArithOp::Asr {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
n: parse_rd(arg_tokens.next())?, n: args.next_rd()?,
} }
} }
1 => { 1 => {
let dst = parse_wr(arg_tokens.next())?; let dst = args.next_wr()?;
ArithOp::Asr { ArithOp::Asr {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
@ -445,8 +449,8 @@ impl OpParser for ArithOpParser {
} }
_other => { _other => {
return Err(Error::Asm(AsmError::UnknownInstruction)); return Ok(ParseOpResult::Unknown(args));
} }
})) })))
} }
} }

Loading…
Cancel
Save