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

749 lines
22 KiB

use crsn::asm::data::{Rd, Wr};
4 years ago
use crsn::asm::error::CrsnError;
use crsn::asm::instr::op::OpKind;
use crsn::asm::parse::arg_parser::TokenParser;
use crsn::module::ParseRes;
use crsn::sexp::SourcePosition;
use crate::defs::ArithOp;
pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
Ok(ParseRes::ext(match keyword {
4 years ago
"cmp" => {
ArithOp::Compare {
a: args.next_rd()?,
b: args.next_rd()?,
}
}
"rcmp" => {
ArithOp::RangeTest {
val: args.next_rd()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
4 years ago
"tst" => {
let arg = args.next_rd()?;
ArithOp::Test { a: arg }
}
"rng" => {
match args.len() {
1 => {
ArithOp::Rng {
dst: args.next_wr()?,
min: Rd::immediate(0),
max: Rd::immediate(u64::MAX),
}
}
2 => {
ArithOp::Rng {
dst: args.next_wr()?,
min: Rd::immediate(0),
max: args.next_rd()?,
}
}
3 => {
ArithOp::Rng {
dst: args.next_wr()?,
min: args.next_rd()?,
max: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Rng requires 1, 2 or 3 arguments".into(), pos.clone()));
}
}
}
4 years ago
"inc" => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Add {
dst: dst.wr(),
a: dst.rd(),
4 years ago
b: Rd::immediate(1),
}
4 years ago
}
4 years ago
"dec" => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Sub {
dst: dst.wr(),
a: dst.rd(),
4 years ago
b: Rd::immediate(1),
}
4 years ago
}
4 years ago
"add" => {
match args.len() {
3 => {
ArithOp::Add {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
4 years ago
2 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Add {
dst: dst.wr(),
a: dst.rd(),
4 years ago
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Add requires 2 or 3 arguments".into(), pos.clone()));
}
}
4 years ago
}
4 years ago
"sub" => {
match args.len() {
3 => {
ArithOp::Sub {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Sub {
dst: dst.wr(),
a: dst.rd(),
4 years ago
b: args.next_rd()?,
}
}
4 years ago
_ => {
return Err(CrsnError::Parse("Sub requires 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"mul" => {
match args.len() {
3 => {
ArithOp::Mul {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Mul {
dst: dst.wr(),
a: dst.rd(),
4 years ago
b: args.next_rd()?,
}
}
4 years ago
_ => {
return Err(CrsnError::Parse("Mul requires 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"divr" => {
match args.len() {
3 => {
let dst = args.next_rdwr()?;
4 years ago
let rem = args.next_wr()?;
let div = args.next_rd()?;
ArithOp::Div {
dst: dst.wr(),
4 years ago
rem,
a: dst.rd(),
4 years ago
div,
}
}
4 years ago
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(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"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_rdwr()?;
4 years ago
let div = args.next_rd()?;
ArithOp::Div {
dst: dst.wr(),
4 years ago
rem: Wr::discard(),
a: dst.rd(),
4 years ago
div,
}
}
4 years ago
_ => {
return Err(CrsnError::Parse("Div requires 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"mod" => {
match args.len() {
3 => {
ArithOp::Mod {
dst: args.next_wr()?,
a: args.next_rd()?,
div: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
4 years ago
let div = args.next_rd()?;
ArithOp::Mod {
dst: dst.wr(),
a: dst.rd(),
4 years ago
div,
}
}
4 years ago
_ => {
return Err(CrsnError::Parse("Mod requires 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"and" => {
match args.len() {
3 => {
ArithOp::And {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::And {
dst: dst.wr(),
a: dst.rd(),
4 years ago
b: args.next_rd()?,
}
}
4 years ago
_ => {
return Err(CrsnError::Parse("And requires 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"or" => {
match args.len() {
3 => {
ArithOp::Or {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
4 years ago
2 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Or {
dst: dst.wr(),
a: dst.rd(),
4 years ago
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Or requires 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"xor" => {
match args.len() {
3 => {
ArithOp::Xor {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
4 years ago
2 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Xor {
dst: dst.wr(),
a: dst.rd(),
4 years ago
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Xor requires 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"cpl" => {
match args.len() {
2 => {
ArithOp::Cpl {
dst: args.next_wr()?,
a: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Cpl {
dst: dst.wr(),
a: dst.rd(),
}
}
4 years ago
_ => {
return Err(CrsnError::Parse("Cpl requires 1 or 2 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"rol" => {
match args.len() {
3 => {
ArithOp::Rol {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
4 years ago
}
2 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Rol {
dst: dst.wr(),
a: dst.rd(),
4 years ago
n: args.next_rd()?,
}
4 years ago
}
1 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Rol {
dst: dst.wr(),
a: dst.rd(),
4 years ago
n: Rd::immediate(1),
}
}
4 years ago
_ => {
return Err(CrsnError::Parse("Rol requires 1, 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"ror" => {
match args.len() {
3 => {
ArithOp::Ror {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
4 years ago
2 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Ror {
dst: dst.wr(),
a: dst.rd(),
4 years ago
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Ror {
dst: dst.wr(),
a: dst.rd(),
4 years ago
n: Rd::immediate(1),
}
}
4 years ago
_ => {
return Err(CrsnError::Parse("Ror requires 1, 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"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_rdwr()?;
4 years ago
ArithOp::Lsl {
dst: dst.wr(),
a: dst.rd(),
4 years ago
n: args.next_rd()?,
}
}
4 years ago
1 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Lsl {
dst: dst.wr(),
a: dst.rd(),
4 years ago
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Lsl requires 1, 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"lsr" => {
match args.len() {
3 => {
ArithOp::Lsr {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Lsr {
dst: dst.wr(),
a: dst.rd(),
4 years ago
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Lsr {
dst: dst.wr(),
a: dst.rd(),
4 years ago
n: Rd::immediate(1),
}
}
4 years ago
_ => {
return Err(CrsnError::Parse("Lsr requires 1, 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
4 years ago
"asr" => {
match args.len() {
3 => {
ArithOp::Asr {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
4 years ago
2 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Asr {
dst: dst.wr(),
a: dst.rd(),
4 years ago
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
4 years ago
ArithOp::Asr {
dst: dst.wr(),
a: dst.rd(),
4 years ago
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Asr requires 1, 2 or 3 arguments".into(), pos.clone()));
4 years ago
}
}
4 years ago
}
"sw32" => {
match args.len() {
2 => {
ArithOp::Sw32 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Sw32 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("SW32 requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"sw16" => {
match args.len() {
2 => {
ArithOp::Sw16 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Sw16 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("SW16 requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"sw8" => {
match args.len() {
2 => {
ArithOp::Sw8 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Sw8 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("SW8 requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"rev" => {
match args.len() {
2 => {
ArithOp::Rev {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Rev {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("REV requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"rbit" => {
match args.len() {
2 => {
ArithOp::Rbit {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Rbit {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("RBIT requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"clz" => {
match args.len() {
2 => {
ArithOp::Clz {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Clz {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("Clz requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"clz32" => {
match args.len() {
2 => {
ArithOp::Clz32 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Clz32 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("Clz32 requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"clz16" => {
match args.len() {
2 => {
ArithOp::Clz16 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Clz16 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("Clz16 requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"clz8" => {
match args.len() {
2 => {
ArithOp::Clz8 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Clz8 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("Clz8 requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"clo" => {
match args.len() {
2 => {
ArithOp::Clo {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Clo {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("Clo requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"clo32" => {
match args.len() {
2 => {
ArithOp::Clo32 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Clo32 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("Clo32 requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"clo16" => {
match args.len() {
2 => {
ArithOp::Clo16 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Clo16 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("Clo16 requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
"clo8" => {
match args.len() {
2 => {
ArithOp::Clo8 {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Clo8 {
dst: dst.wr(),
src: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("Clo8 requires 1 or 2 arguments".into(), pos.clone()));
}
}
}
4 years ago
_other => {
return Ok(ParseRes::Unknown(args));
4 years ago
}
}))
}
4 years ago