DRY arithmetic parsing

floats
Ondřej Hruška 4 years ago
parent 3999c51eb7
commit e560fc5657
Signed by untrusted user: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 35
      crsn/src/asm/parse/arg_parser.rs
  2. 488
      crsn_arith/src/parse.rs

@ -189,7 +189,7 @@ impl<'a> TokenParser<'a> {
Ok(Some((wr, rd1, rd2, mask))) Ok(Some((wr, rd1, rd2, mask)))
} else { } else {
Err(CrsnError::Parse("Instruction needs 2 (RW Rd) or 3 (Wr Rd Rd) arguments!".into(), self.start_pos.clone())) Err(CrsnError::Parse("Instruction needs 2 (RW,Rd) or 3 (Wr,Rd,Rd) arguments!".into(), self.start_pos.clone()))
} }
} else { } else {
Ok(None) Ok(None)
@ -232,7 +232,7 @@ impl<'a> TokenParser<'a> {
Ok(Some((wr, rd, mask))) Ok(Some((wr, rd, mask)))
} else { } else {
Err(CrsnError::Parse("Instruction needs 1 (RW) or 2 (Wr Rd) arguments!".into(), self.start_pos.clone())) Err(CrsnError::Parse("Instruction needs 1 (RW) or 2 (Wr,Rd) arguments!".into(), self.start_pos.clone()))
} }
} else { } else {
Ok(None) Ok(None)
@ -262,7 +262,7 @@ impl<'a> TokenParser<'a> {
Ok(Some((wr1, wr2, mask))) Ok(Some((wr1, wr2, mask)))
} else { } else {
Err(CrsnError::Parse("Instruction needs 2 (RW RW) arguments!".into(), self.start_pos.clone())) Err(CrsnError::Parse("Instruction needs 2 (RW,RW) arguments!".into(), self.start_pos.clone()))
} }
} else { } else {
Ok(None) Ok(None)
@ -270,6 +270,7 @@ impl<'a> TokenParser<'a> {
} }
/// Parse combining binary instruction operands (i.e. add) without masks /// Parse combining binary instruction operands (i.e. add) without masks
/// Accepts (Wr, Rd, Rd) and (RdWr, Rd)
pub fn parse_wr_rd_rd(&mut self) -> Result<(Wr, Rd, Rd), CrsnError> { pub fn parse_wr_rd_rd(&mut self) -> Result<(Wr, Rd, Rd), CrsnError> {
if self.len() == 2 { if self.len() == 2 {
let rw = self.next_rdwr()?; let rw = self.next_rdwr()?;
@ -281,11 +282,32 @@ impl<'a> TokenParser<'a> {
let rd2 = self.next_rd()?; let rd2 = self.next_rd()?;
Ok((wr, rd1, rd2)) Ok((wr, rd1, rd2))
} else { } else {
Err(CrsnError::Parse("Instruction needs 2 (RW Rd) or 3 (Wr Rd Rd) arguments!".into(), self.start_pos.clone())) Err(CrsnError::Parse("Instruction needs 2 (RW,Rd) or 3 (Wr,Rd,Rd) arguments!".into(), self.start_pos.clone()))
}
}
/// Parse combining binary instruction operands (i.e. add) without masks
/// Accepts (Wr, Rd, Rd) and (RdWr, Rd)
pub fn parse_wr_rd_rd_or_n(&mut self, n : Value) -> Result<(Wr, Rd, Rd), CrsnError> {
if self.len() == 1 {
let rw = self.next_rdwr()?;
Ok((rw.wr(), rw.rd(), Rd::immediate(n)))
} else if self.len() == 2 {
let rw = self.next_rdwr()?;
let rd = self.next_rd()?;
Ok((rw.wr(), rw.rd(), rd))
} else if self.len() == 3 {
let wr = self.next_wr()?;
let rd1 = self.next_rd()?;
let rd2 = self.next_rd()?;
Ok((wr, rd1, rd2))
} else {
Err(CrsnError::Parse("Instruction needs 1 (RW,1), 2 (RW,Rd) or 3 (Wr,Rd,Rd) arguments!".into(), self.start_pos.clone()))
} }
} }
/// Parse unary instruction operands (i.e. complement) without masks /// Parse unary instruction operands (i.e. complement) without masks
/// Accepts (Wr, Rd) and (RdWr)
pub fn parse_wr_rd(&mut self) -> Result<(Wr, Rd), CrsnError> { pub fn parse_wr_rd(&mut self) -> Result<(Wr, Rd), CrsnError> {
if self.len() == 1 { if self.len() == 1 {
let rw = self.next_rdwr()?; let rw = self.next_rdwr()?;
@ -295,18 +317,19 @@ impl<'a> TokenParser<'a> {
let rd = self.next_rd()?; let rd = self.next_rd()?;
Ok((wr, rd)) Ok((wr, rd))
} else { } else {
Err(CrsnError::Parse("Instruction needs 1 (RW) or 2 (Wr Rd) arguments!".into(), self.start_pos.clone())) Err(CrsnError::Parse("Instruction needs 1 (RW) or 2 (Wr,Rd) arguments!".into(), self.start_pos.clone()))
} }
} }
/// Parse a swap-type binary instruction operands (i.e. exchange) without masks /// Parse a swap-type binary instruction operands (i.e. exchange) without masks
/// Accepts (RdWr, RdWr)
pub fn parse_rdwr_rdwr(&mut self, _keyword: &str, _prefix: &str, _pos: &SourcePosition) -> Result<(RdWr, RdWr), CrsnError> { pub fn parse_rdwr_rdwr(&mut self, _keyword: &str, _prefix: &str, _pos: &SourcePosition) -> Result<(RdWr, RdWr), CrsnError> {
if self.len() == 2 { if self.len() == 2 {
let rw1 = self.next_rdwr()?; let rw1 = self.next_rdwr()?;
let rw2 = self.next_rdwr()?; let rw2 = self.next_rdwr()?;
Ok((rw1, rw2)) Ok((rw1, rw2))
} else { } else {
Err(CrsnError::Parse("Instruction needs 2 (RW RW) arguments!".into(), self.start_pos.clone())) Err(CrsnError::Parse("Instruction needs 2 (RW,RW) arguments!".into(), self.start_pos.clone()))
} }
} }
} }

@ -11,27 +11,25 @@ use crate::defs::ArithOp;
pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> { pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
Ok(ParseRes::ext(match keyword { Ok(ParseRes::ext(match keyword {
"cmp" => { "cmp" => {
ArithOp::Compare { let parsed = ArithOp::Compare { a: args.next_rd()?, b: args.next_rd()? };
a: args.next_rd()?, args.ensure_empty("two input arguments")?;
b: args.next_rd()?, parsed
}
} }
"rcmp" => { "rcmp" => {
ArithOp::RangeTest { let parsed = ArithOp::RangeTest { val: args.next_rd()?, a: args.next_rd()?, b: args.next_rd()? };
val: args.next_rd()?, args.ensure_empty("3 arguments (value, min, max)")?;
a: args.next_rd()?, parsed
b: args.next_rd()?,
}
} }
"tst" => { "tst" => {
let arg = args.next_rd()?; let arg = args.next_rd()?;
args.ensure_empty("1 input argument")?;
ArithOp::Test { a: arg } ArithOp::Test { a: arg }
} }
"rng" => { "rng" => {
match args.len() { let parsed = match args.len() {
1 => { 1 => {
ArithOp::Rng { ArithOp::Rng {
dst: args.next_wr()?, dst: args.next_wr()?,
@ -56,94 +54,34 @@ pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenP
_ => { _ => {
return Err(CrsnError::Parse("Rng requires 1, 2 or 3 arguments".into(), op_pos.clone())); return Err(CrsnError::Parse("Rng requires 1, 2 or 3 arguments".into(), op_pos.clone()));
} }
} };
args.ensure_empty("1 (dst) or 3 (dst, min, max) arguments")?;
parsed
} }
"inc" => { "inc" => {
let dst = args.next_rdwr()?; let (dst, a) = args.parse_wr_rd()?;
ArithOp::Add { ArithOp::Add { dst, a, b: Rd::immediate(1) }
dst: dst.wr(),
a: dst.rd(),
b: Rd::immediate(1),
}
} }
"dec" => { "dec" => {
let dst = args.next_rdwr()?; let (dst, a) = args.parse_wr_rd()?;
ArithOp::Sub { ArithOp::Sub { dst, a, b: Rd::immediate(1) }
dst: dst.wr(),
a: dst.rd(),
b: Rd::immediate(1),
}
} }
"add" => { "add" => {
match args.len() { let (dst, a, b) = args.parse_wr_rd_rd()?;
3 => { ArithOp::Add { dst, a, b }
ArithOp::Add {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Add {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Add requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"sub" => { "sub" => {
match args.len() { let (dst, a, b) = args.parse_wr_rd_rd()?;
3 => { ArithOp::Sub { dst, a, b }
ArithOp::Sub {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Sub {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Sub requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"mul" => { "mul" => {
match args.len() { let (dst, a, b) = args.parse_wr_rd_rd()?;
3 => { ArithOp::Mul { dst, a, b }
ArithOp::Mul {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Mul {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Mul requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"divr" => { "divr" => {
@ -174,403 +112,83 @@ pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenP
} }
"div" => { "div" => {
match args.len() { let (dst, a, div) = args.parse_wr_rd_rd()?;
3 => { ArithOp::Div { dst, rem: Wr::discard(), a, div }
ArithOp::Div {
dst: args.next_wr()?,
rem: Wr::discard(),
a: args.next_rd()?,
div: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
let div = args.next_rd()?;
ArithOp::Div {
dst: dst.wr(),
rem: Wr::discard(),
a: dst.rd(),
div,
}
}
_ => {
return Err(CrsnError::Parse("Div requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"mod" => { "mod" => {
match args.len() { let (dst, a, div) = args.parse_wr_rd_rd()?;
3 => { ArithOp::Mod { dst, a, div }
ArithOp::Mod {
dst: args.next_wr()?,
a: args.next_rd()?,
div: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
let div = args.next_rd()?;
ArithOp::Mod {
dst: dst.wr(),
a: dst.rd(),
div,
}
}
_ => {
return Err(CrsnError::Parse("Mod requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"and" => { "and" => {
match args.len() { let (dst, a, b) = args.parse_wr_rd_rd()?;
3 => { ArithOp::And { dst, a, b }
ArithOp::And {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::And {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("And requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"or" => { "or" => {
match args.len() { let (dst, a, b) = args.parse_wr_rd_rd()?;
3 => { ArithOp::Or { dst, a, b }
ArithOp::Or {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Or {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Or requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"xor" => { "xor" => {
match args.len() { let (dst, a, b) = args.parse_wr_rd_rd()?;
3 => { ArithOp::Xor { dst, a, b }
ArithOp::Xor {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Xor {
dst: dst.wr(),
a: dst.rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Xor requires 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"cpl" => { "cpl" => {
match args.len() { let (dst, a) = args.parse_wr_rd()?;
2 => { ArithOp::Cpl { dst, a }
ArithOp::Cpl {
dst: args.next_wr()?,
a: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Cpl {
dst: dst.wr(),
a: dst.rd(),
}
}
_ => {
return Err(CrsnError::Parse("Cpl requires 1 or 2 arguments".into(), op_pos.clone()));
}
}
} }
"rol" => { "rol" => {
match args.len() { let (dst, a, n) = args.parse_wr_rd_rd_or_n(1)?;
3 => { ArithOp::Rol { dst, a, n }
ArithOp::Rol {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Rol {
dst: dst.wr(),
a: dst.rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Rol {
dst: dst.wr(),
a: dst.rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Rol requires 1, 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"ror" => { "ror" => {
match args.len() { let (dst, a, n) = args.parse_wr_rd_rd_or_n(1)?;
3 => { ArithOp::Ror { dst, a, n }
ArithOp::Ror {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Ror {
dst: dst.wr(),
a: dst.rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Ror {
dst: dst.wr(),
a: dst.rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Ror requires 1, 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"lsl" | "asl" => { "lsl" | "asl" => {
match args.len() { let (dst, a, n) = args.parse_wr_rd_rd_or_n(1)?;
3 => { ArithOp::Lsl { dst, a, n }
ArithOp::Lsl {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Lsl {
dst: dst.wr(),
a: dst.rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Lsl {
dst: dst.wr(),
a: dst.rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Lsl requires 1, 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"lsr" => { "lsr" => {
match args.len() { let (dst, a, n) = args.parse_wr_rd_rd_or_n(1)?;
3 => { ArithOp::Lsr { dst, a, n }
ArithOp::Lsr {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Lsr {
dst: dst.wr(),
a: dst.rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Lsr {
dst: dst.wr(),
a: dst.rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Lsr requires 1, 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"asr" => { "asr" => {
match args.len() { let (dst, a, n) = args.parse_wr_rd_rd_or_n(1)?;
3 => { ArithOp::Asr { dst, a, n }
ArithOp::Asr {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_rdwr()?;
ArithOp::Asr {
dst: dst.wr(),
a: dst.rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_rdwr()?;
ArithOp::Asr {
dst: dst.wr(),
a: dst.rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Asr requires 1, 2 or 3 arguments".into(), op_pos.clone()));
}
}
} }
"sw32" => { "sw32" => {
match args.len() { let (dst, src) = args.parse_wr_rd()?;
2 => { ArithOp::Sw32 { dst, src }
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(), op_pos.clone()));
}
}
} }
"sw16" => { "sw16" => {
match args.len() { let (dst, src) = args.parse_wr_rd()?;
2 => { ArithOp::Sw16 { dst, src }
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(), op_pos.clone()));
}
}
} }
"sw8" => { "sw8" => {
match args.len() { let (dst, src) = args.parse_wr_rd()?;
2 => { ArithOp::Sw8 { dst, src }
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(), op_pos.clone()));
}
}
} }
"rev" => { "rev" => {
match args.len() { let (dst, src) = args.parse_wr_rd()?;
2 => { ArithOp::Rev { dst, src }
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(), op_pos.clone()));
}
}
} }
"rbit" => { "rbit" => {
match args.len() { let (dst, src) = args.parse_wr_rd()?;
2 => { ArithOp::Rbit { dst, src }
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(), op_pos.clone()));
}
}
} }
other => { other => {

Loading…
Cancel
Save