use crsn::asm::data::{Rd, Wr}; use crsn::asm::error::{AsmError, Error}; use crsn::asm::instr::op::{OpParser, OpTrait}; use crsn::asm::parse::parse_data::{parse_rd, parse_wr}; use crsn::sexp::Sexp; use crate::defs::ArithOp; #[derive(Debug, Clone)] pub struct ArithOpParser { _internal: () } impl ArithOpParser { pub fn new() -> Box { Box::new(Self { _internal: () }) } } impl OpParser for ArithOpParser { fn parse_op(&self, keyword: &str, _far: bool, arg_tokens_sl: Vec) -> Result, Error> { let mut arg_tokens = arg_tokens_sl.into_iter(); Ok(Box::new(match keyword { "cmp" => { ArithOp::Compare { a: parse_rd(arg_tokens.next())?, b: parse_rd(arg_tokens.next())?, } } "tst" => { let arg = parse_rd(arg_tokens.next())?; ArithOp::Test { a: arg } } "inc" => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Add { dst, a: dst.as_rd(), b: Rd::immediate(1), } } "dec" => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Sub { dst, a: dst.as_rd(), b: Rd::immediate(1), } } "add" => { match arg_tokens.len() { 3 => { ArithOp::Add { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, b: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Add { dst, a: dst.as_rd(), b: parse_rd(arg_tokens.next())?, } } _ => { return Err(Error::Parse("Add requires 2 or 3 arguments".into())); } } } "sub" => { match arg_tokens.len() { 3 => { ArithOp::Sub { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, b: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Sub { dst, a: dst.as_rd(), b: parse_rd(arg_tokens.next())?, } } _ => { return Err(Error::Parse("Sub requires 2 or 3 arguments".into())); } } } "mul" => { match arg_tokens.len() { 3 => { ArithOp::Mul { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, b: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Mul { dst, a: dst.as_rd(), b: parse_rd(arg_tokens.next())?, } } _ => { return Err(Error::Parse("Mul requires 2 or 3 arguments".into())); } } } "divr" => { match arg_tokens.len() { 3 => { let dst = parse_wr(arg_tokens.next())?; let rem = parse_wr(arg_tokens.next())?; let div = parse_rd(arg_tokens.next())?; ArithOp::Div { dst, rem, a: dst.as_rd(), div, } } 4 => { ArithOp::Div { dst: parse_wr(arg_tokens.next())?, rem: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, div: parse_rd(arg_tokens.next())?, } } _ => { return Err(Error::Parse("DivR requires 3 or 4 arguments".into())); } } } "div" => { match arg_tokens.len() { 3 => { ArithOp::Div { dst: parse_wr(arg_tokens.next())?, rem: Wr::discard(), a: parse_rd(arg_tokens.next())?, div: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; let div = parse_rd(arg_tokens.next())?; ArithOp::Div { dst, rem: Wr::discard(), a: dst.as_rd(), div, } } _ => { return Err(Error::Parse("Div requires 2 or 3 arguments".into())); } } } "mod" => { match arg_tokens.len() { 3 => { ArithOp::Mod { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, div: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; let div = parse_rd(arg_tokens.next())?; ArithOp::Mod { dst, a: dst.as_rd(), div, } } _ => { return Err(Error::Parse("Mod requires 2 or 3 arguments".into())); } } } "and" => { match arg_tokens.len() { 3 => { ArithOp::And { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, b: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::And { dst, a: dst.as_rd(), b: parse_rd(arg_tokens.next())?, } } _ => { return Err(Error::Parse("And requires 2 or 3 arguments".into())); } } } "or" => { match arg_tokens.len() { 3 => { ArithOp::Or { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, b: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Or { dst, a: dst.as_rd(), b: parse_rd(arg_tokens.next())?, } } _ => { return Err(Error::Parse("Or requires 2 or 3 arguments".into())); } } } "xor" => { match arg_tokens.len() { 3 => { ArithOp::Xor { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, b: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Xor { dst, a: dst.as_rd(), b: parse_rd(arg_tokens.next())?, } } _ => { return Err(Error::Parse("Xor requires 2 or 3 arguments".into())); } } } "cpl" => { match arg_tokens.len() { 2 => { ArithOp::Cpl { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, } } 1 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Cpl { dst, a: dst.as_rd(), } } _ => { return Err(Error::Parse("Cpl requires 1 or 2 arguments".into())); } } } "rol" => { match arg_tokens.len() { 3 => { ArithOp::Rol { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, n: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Rol { dst, a: dst.as_rd(), n: parse_rd(arg_tokens.next())?, } } 1 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Rol { dst, a: dst.as_rd(), n: Rd::immediate(1), } } _ => { return Err(Error::Parse("Rol requires 1, 2 or 3 arguments".into())); } } } "ror" => { match arg_tokens.len() { 3 => { ArithOp::Ror { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, n: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Ror { dst, a: dst.as_rd(), n: parse_rd(arg_tokens.next())?, } } 1 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Ror { dst, a: dst.as_rd(), n: Rd::immediate(1), } } _ => { return Err(Error::Parse("Ror requires 1, 2 or 3 arguments".into())); } } } "lsl" | "asl" => { match arg_tokens.len() { 3 => { ArithOp::Lsl { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, n: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Lsl { dst, a: dst.as_rd(), n: parse_rd(arg_tokens.next())?, } } 1 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Lsl { dst, a: dst.as_rd(), n: Rd::immediate(1), } } _ => { return Err(Error::Parse("Lsl requires 1, 2 or 3 arguments".into())); } } } "lsr" => { match arg_tokens.len() { 3 => { ArithOp::Lsr { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, n: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Lsr { dst, a: dst.as_rd(), n: parse_rd(arg_tokens.next())?, } } 1 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Lsr { dst, a: dst.as_rd(), n: Rd::immediate(1), } } _ => { return Err(Error::Parse("Lsr requires 1, 2 or 3 arguments".into())); } } } "asr" => { match arg_tokens.len() { 3 => { ArithOp::Asr { dst: parse_wr(arg_tokens.next())?, a: parse_rd(arg_tokens.next())?, n: parse_rd(arg_tokens.next())?, } } 2 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Asr { dst, a: dst.as_rd(), n: parse_rd(arg_tokens.next())?, } } 1 => { let dst = parse_wr(arg_tokens.next())?; ArithOp::Asr { dst, a: dst.as_rd(), n: Rd::immediate(1), } } _ => { return Err(Error::Parse("Asr requires 1, 2 or 3 arguments".into())); } } } _other => { return Err(Error::Asm(AsmError::UnknownInstruction)); } })) } }