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/csn_asm/src/parse/parse_op.rs

114 lines
3.1 KiB

use crate::instr::{HLOp, Op};
use sexp::Sexp;
use crate::error::Error;
use crate::data::literal::{RoutineName, Label};
use crate::parse::sexp_expect::expect_string_atom;
use crate::parse::parse_data::{parse_rd, parse_wr, parse_label};
use crate::parse::parse_cond::parse_cond;
pub fn parse_op(keyword: &str, far : bool, mut arg_tokens: impl Iterator<Item=Sexp>) -> Result<HLOp, Error> {
Ok(match keyword {
"j" => {
let dest = parse_label(arg_tokens.next())?;
if far {
HLOp::L(Op::FarJump(dest))
} else {
HLOp::Jump(dest)
}
}
"call" => {
let dest = RoutineName(expect_string_atom(arg_tokens.next())?);
let mut args = vec![];
for t in arg_tokens {
args.push(parse_rd(Some(t))?);
}
HLOp::L(Op::Call(dest, args))
}
"ret" => {
let mut args = vec![];
for t in arg_tokens {
args.push(parse_rd(Some(t))?);
}
HLOp::L(Op::Ret(args))
}
"routine" => {
let dest = RoutineName(expect_string_atom(arg_tokens.next())?);
HLOp::L(Op::Routine(dest))
}
"sk" => {
HLOp::L(Op::Skip(parse_rd(arg_tokens.next())?))
}
"csk" => {
let cond = parse_cond(&expect_string_atom(arg_tokens.next())?)?;
let offs = parse_rd(arg_tokens.next())?;
HLOp::L(Op::SkipIf(cond, offs))
}
"cj" => {
let cond = parse_cond(&expect_string_atom(arg_tokens.next())?)?;
let dest = parse_label(arg_tokens.next())?;
HLOp::JumpIf(cond, dest)
}
"barrier" => {
HLOp::L(Op::Barrier(match arg_tokens.next() {
None => None,
Some(s) => Some(expect_string_atom(Some(s))?.into()),
}))
}
"fault" => {
HLOp::L(Op::Fault(match arg_tokens.next() {
None => None,
Some(s) => Some(expect_string_atom(Some(s))?.into()),
}))
}
"ld" => {
HLOp::L(Op::Mov(
parse_wr(arg_tokens.next())?,
parse_rd(arg_tokens.next())?
))
}
"cmp" => {
HLOp::L(Op::Cmp(
parse_rd(arg_tokens.next())?,
parse_rd(arg_tokens.next())?
))
}
"inc" => {
HLOp::L(Op::Inc(
parse_wr(arg_tokens.next())?
))
}
"dec" => {
HLOp::L(Op::Dec(
parse_wr(arg_tokens.next())?
))
}
// TODO more instructions
other => {
if let Some(label) = other.strip_prefix(':') {
let label = Label::Named(label.to_string());
if far {
HLOp::L(Op::FarLabel(label))
} else {
HLOp::Label(label)
}
} else {
return Err(Error::Parse(format!("Unknown instruction: {}", other).into()));
}
}
})
}