use crsn::asm::data::{Rd, Wr}; use crsn::asm::error::CrsnError; use crsn::asm::instr::op::OpKind; use crsn::asm::parse::arg_parser::TokenParser; use crsn::module::ParseRes; use crate::defs::ArithOp; pub(crate) fn parse<'a>(keyword: &str, mut args: TokenParser<'a>) -> Result, CrsnError> { Ok(ParseRes::ext(match keyword { "cmp" => { ArithOp::Compare { a: args.next_rd()?, b: args.next_rd()?, } } "tst" => { let arg = args.next_rd()?; ArithOp::Test { a: arg } } "inc" => { let dst = args.next_wr()?; ArithOp::Add { dst, a: dst.as_rd(), b: Rd::immediate(1), } } "dec" => { let dst = args.next_wr()?; ArithOp::Sub { dst, a: dst.as_rd(), b: Rd::immediate(1), } } "add" => { match args.len() { 3 => { ArithOp::Add { dst: args.next_wr()?, a: args.next_rd()?, b: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; ArithOp::Add { dst, a: dst.as_rd(), b: args.next_rd()?, } } _ => { return Err(CrsnError::Parse("Add requires 2 or 3 arguments".into())); } } } "sub" => { match args.len() { 3 => { ArithOp::Sub { dst: args.next_wr()?, a: args.next_rd()?, b: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; ArithOp::Sub { dst, a: dst.as_rd(), b: args.next_rd()?, } } _ => { return Err(CrsnError::Parse("Sub requires 2 or 3 arguments".into())); } } } "mul" => { match args.len() { 3 => { ArithOp::Mul { dst: args.next_wr()?, a: args.next_rd()?, b: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; ArithOp::Mul { dst, a: dst.as_rd(), b: args.next_rd()?, } } _ => { return Err(CrsnError::Parse("Mul requires 2 or 3 arguments".into())); } } } "divr" => { match args.len() { 3 => { let dst = args.next_wr()?; let rem = args.next_wr()?; let div = args.next_rd()?; ArithOp::Div { dst, rem, a: dst.as_rd(), div, } } 4 => { ArithOp::Div { dst: args.next_wr()?, rem: args.next_wr()?, a: args.next_rd()?, div: args.next_rd()?, } } _ => { return Err(CrsnError::Parse("DivR requires 3 or 4 arguments".into())); } } } "div" => { match args.len() { 3 => { ArithOp::Div { dst: args.next_wr()?, rem: Wr::discard(), a: args.next_rd()?, div: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; let div = args.next_rd()?; ArithOp::Div { dst, rem: Wr::discard(), a: dst.as_rd(), div, } } _ => { return Err(CrsnError::Parse("Div requires 2 or 3 arguments".into())); } } } "mod" => { match args.len() { 3 => { ArithOp::Mod { dst: args.next_wr()?, a: args.next_rd()?, div: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; let div = args.next_rd()?; ArithOp::Mod { dst, a: dst.as_rd(), div, } } _ => { return Err(CrsnError::Parse("Mod requires 2 or 3 arguments".into())); } } } "and" => { match args.len() { 3 => { ArithOp::And { dst: args.next_wr()?, a: args.next_rd()?, b: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; ArithOp::And { dst, a: dst.as_rd(), b: args.next_rd()?, } } _ => { return Err(CrsnError::Parse("And requires 2 or 3 arguments".into())); } } } "or" => { match args.len() { 3 => { ArithOp::Or { dst: args.next_wr()?, a: args.next_rd()?, b: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; ArithOp::Or { dst, a: dst.as_rd(), b: args.next_rd()?, } } _ => { return Err(CrsnError::Parse("Or requires 2 or 3 arguments".into())); } } } "xor" => { match args.len() { 3 => { ArithOp::Xor { dst: args.next_wr()?, a: args.next_rd()?, b: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; ArithOp::Xor { dst, a: dst.as_rd(), b: args.next_rd()?, } } _ => { return Err(CrsnError::Parse("Xor requires 2 or 3 arguments".into())); } } } "cpl" => { match args.len() { 2 => { ArithOp::Cpl { dst: args.next_wr()?, a: args.next_rd()?, } } 1 => { let dst = args.next_wr()?; ArithOp::Cpl { dst, a: dst.as_rd(), } } _ => { return Err(CrsnError::Parse("Cpl requires 1 or 2 arguments".into())); } } } "rol" => { match args.len() { 3 => { ArithOp::Rol { dst: args.next_wr()?, a: args.next_rd()?, n: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; ArithOp::Rol { dst, a: dst.as_rd(), n: args.next_rd()?, } } 1 => { let dst = args.next_wr()?; ArithOp::Rol { dst, a: dst.as_rd(), n: Rd::immediate(1), } } _ => { return Err(CrsnError::Parse("Rol requires 1, 2 or 3 arguments".into())); } } } "ror" => { match args.len() { 3 => { ArithOp::Ror { dst: args.next_wr()?, a: args.next_rd()?, n: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; ArithOp::Ror { dst, a: dst.as_rd(), n: args.next_rd()?, } } 1 => { let dst = args.next_wr()?; ArithOp::Ror { dst, a: dst.as_rd(), n: Rd::immediate(1), } } _ => { return Err(CrsnError::Parse("Ror requires 1, 2 or 3 arguments".into())); } } } "lsl" | "asl" => { match args.len() { 3 => { ArithOp::Lsl { dst: args.next_wr()?, a: args.next_rd()?, n: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; ArithOp::Lsl { dst, a: dst.as_rd(), n: args.next_rd()?, } } 1 => { let dst = args.next_wr()?; ArithOp::Lsl { dst, a: dst.as_rd(), n: Rd::immediate(1), } } _ => { return Err(CrsnError::Parse("Lsl requires 1, 2 or 3 arguments".into())); } } } "lsr" => { match args.len() { 3 => { ArithOp::Lsr { dst: args.next_wr()?, a: args.next_rd()?, n: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; ArithOp::Lsr { dst, a: dst.as_rd(), n: args.next_rd()?, } } 1 => { let dst = args.next_wr()?; ArithOp::Lsr { dst, a: dst.as_rd(), n: Rd::immediate(1), } } _ => { return Err(CrsnError::Parse("Lsr requires 1, 2 or 3 arguments".into())); } } } "asr" => { match args.len() { 3 => { ArithOp::Asr { dst: args.next_wr()?, a: args.next_rd()?, n: args.next_rd()?, } } 2 => { let dst = args.next_wr()?; ArithOp::Asr { dst, a: dst.as_rd(), n: args.next_rd()?, } } 1 => { let dst = args.next_wr()?; ArithOp::Asr { dst, a: dst.as_rd(), n: Rd::immediate(1), } } _ => { return Err(CrsnError::Parse("Asr requires 1, 2 or 3 arguments".into())); } } } _other => { return Ok(ParseRes::Unknown(args)); } })) }