forked from MightyPork/crsn
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.
453 lines
16 KiB
453 lines
16 KiB
4 years ago
|
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<dyn OpParser> {
|
||
|
Box::new(Self {
|
||
|
_internal: ()
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl OpParser for ArithOpParser {
|
||
|
fn parse_op(&self, keyword: &str, _far: bool, arg_tokens_sl: Vec<Sexp>) -> Result<Box<dyn OpTrait>, 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));
|
||
|
}
|
||
|
}))
|
||
|
}
|
||
|
}
|