Croissant Runtime
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.
crsn/crsn_arith/src/parse.rs

457 lines
15 KiB

use crsn::asm::data::{Rd, Wr};
use crsn::asm::error::{AsmError, Error};
use crsn::asm::instr::op::{AsmModule, OpTrait, ParseOpResult};
use crsn::asm::parse::parse_data::{parse_rd, parse_wr};
use crsn::sexp::Sexp;
use crate::defs::ArithOp;
use crsn::asm::parse::arg_parser::ArgParser;
#[derive(Debug, Clone)]
pub struct ArithOpParser {
_internal: ()
}
impl ArithOpParser {
pub fn new() -> Box<dyn AsmModule> {
Box::new(Self {
_internal: ()
})
}
}
impl AsmModule for ArithOpParser {
fn name(&self) -> &'static str {
"arith"
}
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpResult, Error> {
Ok(ParseOpResult::Parsed(Box::new(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(Error::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(Error::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(Error::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(Error::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(Error::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(Error::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(Error::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(Error::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(Error::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(Error::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(Error::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(Error::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(Error::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(Error::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(Error::Parse("Asr requires 1, 2 or 3 arguments".into()));
}
}
}
_other => {
return Ok(ParseOpResult::Unknown(args));
}
})))
}
}