forked from MightyPork/crsn
renames, improve module API (avoid cloning)
This commit is contained in:
@@ -4,15 +4,15 @@ use std::sync::atomic::AtomicU32;
|
|||||||
use crate::asm::data::{Rd, SrcDisp};
|
use crate::asm::data::{Rd, SrcDisp};
|
||||||
use crate::asm::data::literal::{Label, Value};
|
use crate::asm::data::literal::{Label, Value};
|
||||||
use crate::asm::error::{AsmError, Error};
|
use crate::asm::error::{AsmError, Error};
|
||||||
use crate::asm::instr::{Cond, HLOp, Instr, Op, Routine};
|
use crate::asm::instr::{Cond, OpWrapper, Instr, Op, Routine};
|
||||||
|
|
||||||
/// A trait for something that can turn into multiple instructions
|
/// A trait for something that can turn into multiple instructions
|
||||||
pub trait Flatten {
|
pub trait Flatten {
|
||||||
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<HLOp>, Error>;
|
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<OpWrapper>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Flatten for Instr {
|
impl Flatten for Instr {
|
||||||
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<HLOp>, Error> {
|
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<OpWrapper>, Error> {
|
||||||
let mut ops = vec![self.op];
|
let mut ops = vec![self.op];
|
||||||
|
|
||||||
if let Some(branches) = self.branches {
|
if let Some(branches) = self.branches {
|
||||||
@@ -29,18 +29,18 @@ impl Flatten for Instr {
|
|||||||
} else {
|
} else {
|
||||||
Label::unique(label_num)
|
Label::unique(label_num)
|
||||||
};
|
};
|
||||||
ops.push(HLOp::JumpIf(!cond, next_lbl.clone()));
|
ops.push(OpWrapper::JumpIf(!cond, next_lbl.clone()));
|
||||||
|
|
||||||
for branch_instr in branch {
|
for branch_instr in branch {
|
||||||
ops.extend(branch_instr.flatten(label_num)?);
|
ops.extend(branch_instr.flatten(label_num)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if cnt != branch_count - 1 {
|
if cnt != branch_count - 1 {
|
||||||
ops.push(HLOp::Jump(end_lbl.clone()));
|
ops.push(OpWrapper::Jump(end_lbl.clone()));
|
||||||
ops.push(HLOp::Label(next_lbl));
|
ops.push(OpWrapper::Label(next_lbl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ops.push(HLOp::Label(end_lbl));
|
ops.push(OpWrapper::Label(end_lbl));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ops)
|
Ok(ops)
|
||||||
@@ -48,7 +48,7 @@ impl Flatten for Instr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Flatten for Routine {
|
impl Flatten for Routine {
|
||||||
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<HLOp>, Error> {
|
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<OpWrapper>, Error> {
|
||||||
let mut ops = vec![
|
let mut ops = vec![
|
||||||
Op::Routine(self.name.clone()).into(),
|
Op::Routine(self.name.clone()).into(),
|
||||||
];
|
];
|
||||||
@@ -63,10 +63,10 @@ impl Flatten for Routine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert jumps to relative skips
|
/// Convert jumps to relative skips
|
||||||
pub fn lower(ops: Vec<HLOp>) -> Result<Vec<Op>, Error> {
|
pub fn lower(ops: Vec<OpWrapper>) -> Result<Vec<Op>, Error> {
|
||||||
let mut label_positions = HashMap::<Label, usize>::new();
|
let mut label_positions = HashMap::<Label, usize>::new();
|
||||||
for (n, op) in ops.iter().enumerate() {
|
for (n, op) in ops.iter().enumerate() {
|
||||||
if let HLOp::Label(name) = op {
|
if let OpWrapper::Label(name) = op {
|
||||||
label_positions.insert(name.clone(), n - label_positions.len());
|
label_positions.insert(name.clone(), n - label_positions.len());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,10 +75,10 @@ pub fn lower(ops: Vec<HLOp>) -> Result<Vec<Op>, Error> {
|
|||||||
let mut skipped = 0;
|
let mut skipped = 0;
|
||||||
for (n, op) in ops.into_iter().enumerate() {
|
for (n, op) in ops.into_iter().enumerate() {
|
||||||
match op {
|
match op {
|
||||||
HLOp::Label(_) => {
|
OpWrapper::Label(_) => {
|
||||||
skipped += 1;
|
skipped += 1;
|
||||||
}
|
}
|
||||||
HLOp::Jump(target) => {
|
OpWrapper::Jump(target) => {
|
||||||
if let Some(dest) = label_positions.get(&target) {
|
if let Some(dest) = label_positions.get(&target) {
|
||||||
let skip = *dest as isize - n as isize + skipped;
|
let skip = *dest as isize - n as isize + skipped;
|
||||||
cleaned.push(Op::Skip(Rd::new(SrcDisp::Immediate(skip as Value))));
|
cleaned.push(Op::Skip(Rd::new(SrcDisp::Immediate(skip as Value))));
|
||||||
@@ -86,7 +86,7 @@ pub fn lower(ops: Vec<HLOp>) -> Result<Vec<Op>, Error> {
|
|||||||
return Err(Error::Asm(AsmError::LabelNotDefined(target)));
|
return Err(Error::Asm(AsmError::LabelNotDefined(target)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HLOp::JumpIf(cond, target) => {
|
OpWrapper::JumpIf(cond, target) => {
|
||||||
if let Some(dest) = label_positions.get(&target) {
|
if let Some(dest) = label_positions.get(&target) {
|
||||||
let skip = *dest as isize - n as isize + skipped;
|
let skip = *dest as isize - n as isize + skipped;
|
||||||
cleaned.push(Op::SkipIf(cond, Rd::new(SrcDisp::Immediate(skip as Value))));
|
cleaned.push(Op::SkipIf(cond, Rd::new(SrcDisp::Immediate(skip as Value))));
|
||||||
@@ -94,7 +94,7 @@ pub fn lower(ops: Vec<HLOp>) -> Result<Vec<Op>, Error> {
|
|||||||
return Err(Error::Asm(AsmError::LabelNotDefined(target)));
|
return Err(Error::Asm(AsmError::LabelNotDefined(target)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HLOp::L(op) => {
|
OpWrapper::Op(op) => {
|
||||||
cleaned.push(op);
|
cleaned.push(op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
pub use cond::Cond;
|
pub use cond::Cond;
|
||||||
pub use flatten::Flatten;
|
pub use flatten::Flatten;
|
||||||
pub use flatten::lower;
|
pub use flatten::lower;
|
||||||
pub use op::HLOp;
|
pub use op::OpWrapper;
|
||||||
pub use op::Op;
|
pub use op::Op;
|
||||||
|
|
||||||
use crate::asm::data::literal::RoutineName;
|
use crate::asm::data::literal::RoutineName;
|
||||||
@@ -13,7 +13,7 @@ mod flatten;
|
|||||||
/// A higher-level instruction
|
/// A higher-level instruction
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Instr {
|
pub struct Instr {
|
||||||
pub op: HLOp,
|
pub op: OpWrapper,
|
||||||
pub branches: Option<Vec<(Cond, Vec<Instr>)>>,
|
pub branches: Option<Vec<(Cond, Vec<Instr>)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ use crate::asm::instr::Cond;
|
|||||||
use crate::runtime::fault::Fault;
|
use crate::runtime::fault::Fault;
|
||||||
use crate::runtime::frame::{CallStack, StackFrame};
|
use crate::runtime::frame::{CallStack, StackFrame};
|
||||||
use crate::runtime::program::Program;
|
use crate::runtime::program::Program;
|
||||||
|
use crate::asm::parse::arg_parser::ArgParser;
|
||||||
|
|
||||||
/// A higher level simple opration
|
/// A higher level simple opration
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum HLOp {
|
pub enum OpWrapper {
|
||||||
/// Mark a jump target.
|
/// Mark a jump target.
|
||||||
Label(Label),
|
Label(Label),
|
||||||
/// Jump to a label
|
/// Jump to a label
|
||||||
@@ -25,7 +26,7 @@ pub enum HLOp {
|
|||||||
/// Jump to a label if a flag is set
|
/// Jump to a label if a flag is set
|
||||||
JumpIf(Cond, Label),
|
JumpIf(Cond, Label),
|
||||||
/// Low level op
|
/// Low level op
|
||||||
L(Op),
|
Op(Op),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A low level instruction
|
/// A low level instruction
|
||||||
@@ -65,9 +66,9 @@ pub enum Op {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Make "into" work
|
/// Make "into" work
|
||||||
impl From<Op> for HLOp {
|
impl From<Op> for OpWrapper {
|
||||||
fn from(op: Op) -> Self {
|
fn from(op: Op) -> Self {
|
||||||
HLOp::L(op)
|
OpWrapper::Op(op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +77,20 @@ pub trait OpTrait: Clone + Debug + Send + 'static {
|
|||||||
fn execute(&self, program: &Program, call_stack: &mut CallStack, frame: &mut StackFrame) -> Result<(), Fault>;
|
fn execute(&self, program: &Program, call_stack: &mut CallStack, frame: &mut StackFrame) -> Result<(), Fault>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ParseOpResult {
|
||||||
|
Parsed(Box<dyn OpTrait>),
|
||||||
|
Unknown(ArgParser),
|
||||||
|
}
|
||||||
|
|
||||||
#[clonable]
|
#[clonable]
|
||||||
pub trait OpParser: Clone + Debug + Send + 'static {
|
pub trait AsmModule: Clone + Debug + Send + 'static {
|
||||||
fn parse_op(&self, keyword: &str, far: bool, arg_tokens: Vec<Sexp>) -> Result<Box<dyn OpTrait>, Error>;
|
/// Get name of the module
|
||||||
|
fn name(&self) -> &'static str;
|
||||||
|
|
||||||
|
/// Parse an op.
|
||||||
|
/// If the keyword matches and the function decides to parse the instruction, it must consume
|
||||||
|
/// the argument list and either return Ok or Err.
|
||||||
|
///
|
||||||
|
/// If the instruction keyword is not recognized, return Unknown with the unchanged argument list.
|
||||||
|
fn parse_op(&self, keyword: &str, arg_tokens: ArgParser) -> Result<ParseOpResult, Error>;
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-49
@@ -1,5 +1,5 @@
|
|||||||
use crate::asm::instr::{lower, Op};
|
use crate::asm::instr::{lower, Op};
|
||||||
use crate::asm::instr::op::OpParser;
|
use crate::asm::instr::op::AsmModule;
|
||||||
|
|
||||||
pub mod data;
|
pub mod data;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
@@ -8,7 +8,7 @@ pub mod parse;
|
|||||||
pub mod patches;
|
pub mod patches;
|
||||||
|
|
||||||
/// Parse a program from string and assemble a low level instruction sequence from it.
|
/// Parse a program from string and assemble a low level instruction sequence from it.
|
||||||
pub fn assemble(source: &str, parsers: &[Box<dyn OpParser>]) -> Result<Vec<Op>, error::Error> {
|
pub fn assemble(source: &str, parsers: &[Box<dyn AsmModule>]) -> Result<Vec<Op>, error::Error> {
|
||||||
let parsed = parse::parse(source, parsers)?;
|
let parsed = parse::parse(source, parsers)?;
|
||||||
Ok(lower(parsed)?)
|
Ok(lower(parsed)?)
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ mod tests {
|
|||||||
|
|
||||||
use crate::asm::data::{DstDisp, Rd, Register, SrcDisp, Wr};
|
use crate::asm::data::{DstDisp, Rd, Register, SrcDisp, Wr};
|
||||||
use crate::asm::data::literal::{Addr, Label};
|
use crate::asm::data::literal::{Addr, Label};
|
||||||
use crate::asm::instr::{Flatten, HLOp, Instr, lower, Op};
|
use crate::asm::instr::{Flatten, OpWrapper, Instr, lower, Op};
|
||||||
use crate::asm::instr::Cond;
|
use crate::asm::instr::Cond;
|
||||||
use crate::asm::parse::{parse, parse_instructions};
|
use crate::asm::parse::{parse, parse_instructions};
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ mod tests {
|
|||||||
let parsed = parse("
|
let parsed = parse("
|
||||||
()
|
()
|
||||||
").unwrap();
|
").unwrap();
|
||||||
assert_eq!(Vec::<HLOp>::new(), parsed);
|
assert_eq!(Vec::<OpWrapper>::new(), parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -39,8 +39,8 @@ mod tests {
|
|||||||
)
|
)
|
||||||
").unwrap();
|
").unwrap();
|
||||||
assert_eq!(vec![
|
assert_eq!(vec![
|
||||||
HLOp::L(Op::Routine("hello".into())),
|
OpWrapper::Op(Op::Routine("hello".into())),
|
||||||
HLOp::L(Op::Barrier(Some("Routine \"hello\" overrun".into())))
|
OpWrapper::Op(Op::Barrier(Some("Routine \"hello\" overrun".into())))
|
||||||
], parsed);
|
], parsed);
|
||||||
|
|
||||||
let parsed = parse("
|
let parsed = parse("
|
||||||
@@ -50,10 +50,10 @@ mod tests {
|
|||||||
)
|
)
|
||||||
").unwrap();
|
").unwrap();
|
||||||
assert_eq!(vec![
|
assert_eq!(vec![
|
||||||
HLOp::L(Op::Routine("hello".into())),
|
OpWrapper::Op(Op::Routine("hello".into())),
|
||||||
HLOp::L(Op::Barrier(Some("Routine \"hello\" overrun".into()))),
|
OpWrapper::Op(Op::Barrier(Some("Routine \"hello\" overrun".into()))),
|
||||||
HLOp::L(Op::Routine("world".into())),
|
OpWrapper::Op(Op::Routine("world".into())),
|
||||||
HLOp::L(Op::Barrier(Some("Routine \"world\" overrun".into())))
|
OpWrapper::Op(Op::Barrier(Some("Routine \"world\" overrun".into())))
|
||||||
], parsed);
|
], parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,73 +79,73 @@ mod tests {
|
|||||||
)
|
)
|
||||||
").unwrap();
|
").unwrap();
|
||||||
assert_eq!(vec![
|
assert_eq!(vec![
|
||||||
HLOp::L(Op::Routine("move".into())),
|
OpWrapper::Op(Op::Routine("move".into())),
|
||||||
// (mov r0 r1)
|
// (mov r0 r1)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(0))),
|
Wr::new(DstDisp::Register(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
||||||
)),
|
)),
|
||||||
// (mov r15 7)
|
// (mov r15 7)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(15))),
|
Wr::new(DstDisp::Register(Register::Gen(15))),
|
||||||
Rd::new(SrcDisp::Immediate(7)),
|
Rd::new(SrcDisp::Immediate(7)),
|
||||||
)),
|
)),
|
||||||
// (mov r15 0xabcd)
|
// (mov r15 0xabcd)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(15))),
|
Wr::new(DstDisp::Register(Register::Gen(15))),
|
||||||
Rd::new(SrcDisp::Immediate(0xabcd)),
|
Rd::new(SrcDisp::Immediate(0xabcd)),
|
||||||
)),
|
)),
|
||||||
// (mov r7 0b11110000)
|
// (mov r7 0b11110000)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(7))),
|
Wr::new(DstDisp::Register(Register::Gen(7))),
|
||||||
Rd::new(SrcDisp::Immediate(0b11110000)),
|
Rd::new(SrcDisp::Immediate(0b11110000)),
|
||||||
)),
|
)),
|
||||||
// (mov r7 arg1)
|
// (mov r7 arg1)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(7))),
|
Wr::new(DstDisp::Register(Register::Gen(7))),
|
||||||
Rd::new(SrcDisp::Register(Register::Arg(1))),
|
Rd::new(SrcDisp::Register(Register::Arg(1))),
|
||||||
)),
|
)),
|
||||||
// (mov r255 arg255)
|
// (mov r255 arg255)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(255))),
|
Wr::new(DstDisp::Register(Register::Gen(255))),
|
||||||
Rd::new(SrcDisp::Register(Register::Arg(255))),
|
Rd::new(SrcDisp::Register(Register::Arg(255))),
|
||||||
)),
|
)),
|
||||||
// (mov r7 res0)
|
// (mov r7 res0)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(7))),
|
Wr::new(DstDisp::Register(Register::Gen(7))),
|
||||||
Rd::new(SrcDisp::Register(Register::Res(0))),
|
Rd::new(SrcDisp::Register(Register::Res(0))),
|
||||||
)),
|
)),
|
||||||
// (mov r7 res255)
|
// (mov r7 res255)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(7))),
|
Wr::new(DstDisp::Register(Register::Gen(7))),
|
||||||
Rd::new(SrcDisp::Register(Register::Res(255))),
|
Rd::new(SrcDisp::Register(Register::Res(255))),
|
||||||
)),
|
)),
|
||||||
// (mov @r0 @r0)
|
// (mov @r0 @r0)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::RegisterPtr(Register::Gen(0))),
|
Wr::new(DstDisp::RegisterPtr(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::RegisterPtr(Register::Gen(0))),
|
Rd::new(SrcDisp::RegisterPtr(Register::Gen(0))),
|
||||||
)),
|
)),
|
||||||
// (mov @r0 @arg0)
|
// (mov @r0 @arg0)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::RegisterPtr(Register::Gen(0))),
|
Wr::new(DstDisp::RegisterPtr(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::RegisterPtr(Register::Arg(0))),
|
Rd::new(SrcDisp::RegisterPtr(Register::Arg(0))),
|
||||||
)),
|
)),
|
||||||
// (mov @r0 @res0)
|
// (mov @r0 @res0)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::RegisterPtr(Register::Gen(0))),
|
Wr::new(DstDisp::RegisterPtr(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::RegisterPtr(Register::Res(0))),
|
Rd::new(SrcDisp::RegisterPtr(Register::Res(0))),
|
||||||
)),
|
)),
|
||||||
// (mov @123456 @0x123456)
|
// (mov @123456 @0x123456)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::ImmediatePtr(Addr(123456))),
|
Wr::new(DstDisp::ImmediatePtr(Addr(123456))),
|
||||||
Rd::new(SrcDisp::ImmediatePtr(Addr(0x123456))),
|
Rd::new(SrcDisp::ImmediatePtr(Addr(0x123456))),
|
||||||
)),
|
)),
|
||||||
// (mov @0b010101 @0b010101)
|
// (mov @0b010101 @0b010101)
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::ImmediatePtr(Addr(0b010101))),
|
Wr::new(DstDisp::ImmediatePtr(Addr(0b010101))),
|
||||||
Rd::new(SrcDisp::ImmediatePtr(Addr(0b010101))),
|
Rd::new(SrcDisp::ImmediatePtr(Addr(0b010101))),
|
||||||
)),
|
)),
|
||||||
HLOp::L(Op::Barrier(Some("Routine \"move\" overrun".into()))),
|
OpWrapper::Op(Op::Barrier(Some("Routine \"move\" overrun".into()))),
|
||||||
], parsed);
|
], parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ mod tests {
|
|||||||
Ok(parse_instructions(vec![sexp::parse(src)?])?.remove(0))
|
Ok(parse_instructions(vec![sexp::parse(src)?])?.remove(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_single_op(src: &str) -> anyhow::Result<Vec<HLOp>> {
|
fn parse_single_op(src: &str) -> anyhow::Result<Vec<OpWrapper>> {
|
||||||
let num = AtomicU32::new(0);
|
let num = AtomicU32::new(0);
|
||||||
Ok(parse_single_instr(src)?.flatten(&num)?)
|
Ok(parse_single_instr(src)?.flatten(&num)?)
|
||||||
}
|
}
|
||||||
@@ -162,7 +162,7 @@ mod tests {
|
|||||||
fn test_parse_single() {
|
fn test_parse_single() {
|
||||||
let parsed = parse_single_op("(mov r0 r1)").unwrap();
|
let parsed = parse_single_op("(mov r0 r1)").unwrap();
|
||||||
assert_eq!(vec![
|
assert_eq!(vec![
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(0))),
|
Wr::new(DstDisp::Register(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
||||||
)),
|
)),
|
||||||
@@ -176,7 +176,7 @@ mod tests {
|
|||||||
").unwrap();
|
").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Instr {
|
Instr {
|
||||||
op: HLOp::L(Op::Cmp(
|
op: OpWrapper::Op(Op::Cmp(
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
||||||
)),
|
)),
|
||||||
@@ -185,14 +185,14 @@ mod tests {
|
|||||||
Cond::Equal,
|
Cond::Equal,
|
||||||
vec![
|
vec![
|
||||||
Instr {
|
Instr {
|
||||||
op: HLOp::L(Op::Mov(
|
op: OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(0))),
|
Wr::new(DstDisp::Register(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
||||||
)),
|
)),
|
||||||
branches: None,
|
branches: None,
|
||||||
},
|
},
|
||||||
Instr {
|
Instr {
|
||||||
op: HLOp::L(Op::Mov(
|
op: OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(1))),
|
Wr::new(DstDisp::Register(Register::Gen(1))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(2))),
|
Rd::new(SrcDisp::Register(Register::Gen(2))),
|
||||||
)),
|
)),
|
||||||
@@ -204,14 +204,14 @@ mod tests {
|
|||||||
Cond::Greater,
|
Cond::Greater,
|
||||||
vec![
|
vec![
|
||||||
Instr {
|
Instr {
|
||||||
op: HLOp::L(Op::Mov(
|
op: OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(0))),
|
Wr::new(DstDisp::Register(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
||||||
)),
|
)),
|
||||||
branches: None,
|
branches: None,
|
||||||
},
|
},
|
||||||
Instr {
|
Instr {
|
||||||
op: HLOp::L(Op::Mov(
|
op: OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(1))),
|
Wr::new(DstDisp::Register(Register::Gen(1))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
||||||
)),
|
)),
|
||||||
@@ -237,31 +237,31 @@ mod tests {
|
|||||||
").unwrap();
|
").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
HLOp::L(Op::Cmp(
|
OpWrapper::Op(Op::Cmp(
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
||||||
)),
|
)),
|
||||||
HLOp::JumpIf(Cond::NotEqual, Label::Numbered(1)),
|
OpWrapper::JumpIf(Cond::NotEqual, Label::Numbered(1)),
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(0))),
|
Wr::new(DstDisp::Register(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
||||||
)),
|
)),
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(1))),
|
Wr::new(DstDisp::Register(Register::Gen(1))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(2))),
|
Rd::new(SrcDisp::Register(Register::Gen(2))),
|
||||||
)),
|
)),
|
||||||
HLOp::Jump(Label::Numbered(0)),
|
OpWrapper::Jump(Label::Numbered(0)),
|
||||||
HLOp::Label(Label::Numbered(1)),
|
OpWrapper::Label(Label::Numbered(1)),
|
||||||
HLOp::JumpIf(Cond::LowerOrEqual, Label::Numbered(0)),
|
OpWrapper::JumpIf(Cond::LowerOrEqual, Label::Numbered(0)),
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(0))),
|
Wr::new(DstDisp::Register(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
||||||
)),
|
)),
|
||||||
HLOp::L(Op::Mov(
|
OpWrapper::Op(Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(1))),
|
Wr::new(DstDisp::Register(Register::Gen(1))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
Rd::new(SrcDisp::Register(Register::Gen(1))),
|
||||||
)),
|
)),
|
||||||
HLOp::Label(Label::Numbered(0)),
|
OpWrapper::Label(Label::Numbered(0)),
|
||||||
], parsed);
|
], parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,15 +286,15 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
Op::Routine("foo".into()).into(),
|
Op::Routine("foo".into()).into(),
|
||||||
HLOp::Label(Label::Named("foo".to_string())),
|
OpWrapper::Label(Label::Named("foo".to_string())),
|
||||||
HLOp::Label(Label::Named("unused".to_string())),
|
OpWrapper::Label(Label::Named("unused".to_string())),
|
||||||
HLOp::Label(Label::Named("whatever".to_string())),
|
OpWrapper::Label(Label::Named("whatever".to_string())),
|
||||||
Op::Mov(
|
Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(0))),
|
Wr::new(DstDisp::Register(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
||||||
).into(),
|
).into(),
|
||||||
HLOp::Jump(Label::Named("foo".to_string())),
|
OpWrapper::Jump(Label::Named("foo".to_string())),
|
||||||
HLOp::Jump(Label::Named("foo".to_string())),
|
OpWrapper::Jump(Label::Named("foo".to_string())),
|
||||||
Op::Mov(
|
Op::Mov(
|
||||||
Wr::new(DstDisp::Register(Register::Gen(0))),
|
Wr::new(DstDisp::Register(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
||||||
@@ -303,8 +303,8 @@ mod tests {
|
|||||||
Wr::new(DstDisp::Register(Register::Gen(0))),
|
Wr::new(DstDisp::Register(Register::Gen(0))),
|
||||||
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
Rd::new(SrcDisp::Register(Register::Gen(0))),
|
||||||
).into(),
|
).into(),
|
||||||
HLOp::Jump(Label::Named("whatever".to_string())),
|
OpWrapper::Jump(Label::Named("whatever".to_string())),
|
||||||
HLOp::JumpIf(Cond::Equal, Label::Named("whatever".to_string())),
|
OpWrapper::JumpIf(Cond::Equal, Label::Named("whatever".to_string())),
|
||||||
Op::Barrier(Some("Routine \"foo\" overrun".into())).into(),
|
Op::Barrier(Some("Routine \"foo\" overrun".into())).into(),
|
||||||
], parsed);
|
], parsed);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
use sexp::Sexp;
|
||||||
|
use crate::asm::data::{Rd, Wr};
|
||||||
|
use crate::asm::parse::parse_data::{parse_rd, parse_wr};
|
||||||
|
use crate::asm::parse::sexp_expect::expect_string_atom;
|
||||||
|
|
||||||
|
/// Utility for argument parsing
|
||||||
|
pub struct ArgParser {
|
||||||
|
orig_len: usize,
|
||||||
|
args: Vec<Sexp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for ArgParser {
|
||||||
|
type Item = Sexp;
|
||||||
|
type IntoIter = std::vec::IntoIter<Sexp>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.args.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArgParser {
|
||||||
|
/// Create a new argument parser
|
||||||
|
pub fn new(mut args: Vec<Sexp>) -> Self {
|
||||||
|
args.reverse();
|
||||||
|
Self {
|
||||||
|
orig_len: args.len(),
|
||||||
|
args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get remaining items count
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.args.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get len before parsing started
|
||||||
|
pub fn orig_len(&self) -> usize {
|
||||||
|
self.orig_len
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if parsing started
|
||||||
|
pub fn parsing_started(&self) -> bool {
|
||||||
|
self.args.len() != self.orig_len
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the next entry
|
||||||
|
pub fn next(&mut self) -> Option<Sexp> {
|
||||||
|
self.args.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the next string entry
|
||||||
|
pub fn next_string(&mut self) -> anyhow::Result<String> {
|
||||||
|
Ok(expect_string_atom(self.next())?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the next entry as read location
|
||||||
|
pub fn next_rd(&mut self) -> anyhow::Result<Rd> {
|
||||||
|
parse_rd(self.next())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the next entry as write location
|
||||||
|
pub fn next_wr(&mut self) -> anyhow::Result<Wr> {
|
||||||
|
parse_wr(self.next())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,8 +4,8 @@ pub use parse_instr::parse_instructions;
|
|||||||
use parse_routines::parse_routines;
|
use parse_routines::parse_routines;
|
||||||
|
|
||||||
use crate::asm::error::Error;
|
use crate::asm::error::Error;
|
||||||
use crate::asm::instr::{Flatten, HLOp, Routine};
|
use crate::asm::instr::{Flatten, OpWrapper, Routine};
|
||||||
use crate::asm::instr::op::OpParser;
|
use crate::asm::instr::op::AsmModule;
|
||||||
use crate::asm::parse::sexp_expect::expect_list;
|
use crate::asm::parse::sexp_expect::expect_list;
|
||||||
|
|
||||||
mod parse_cond;
|
mod parse_cond;
|
||||||
@@ -15,7 +15,9 @@ mod parse_routines;
|
|||||||
pub mod sexp_expect;
|
pub mod sexp_expect;
|
||||||
mod parse_op;
|
mod parse_op;
|
||||||
|
|
||||||
pub fn parse(source: &str, parsers: &[Box<dyn OpParser>]) -> Result<Vec<HLOp>, Error> {
|
pub mod arg_parser;
|
||||||
|
|
||||||
|
pub fn parse(source: &str, parsers: &[Box<dyn AsmModule>]) -> Result<Vec<OpWrapper>, Error> {
|
||||||
let root = sexp::parse(source)?;
|
let root = sexp::parse(source)?;
|
||||||
|
|
||||||
let subs: Vec<Routine> = parse_routines(expect_list(Some(root), true)?, parsers)?;
|
let subs: Vec<Routine> = parse_routines(expect_list(Some(root), true)?, parsers)?;
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ use sexp::Sexp;
|
|||||||
|
|
||||||
use crate::asm::error::Error;
|
use crate::asm::error::Error;
|
||||||
use crate::asm::instr::{Cond, cond, Instr};
|
use crate::asm::instr::{Cond, cond, Instr};
|
||||||
use crate::asm::instr::op::OpParser;
|
use crate::asm::instr::op::AsmModule;
|
||||||
use crate::asm::parse::parse_instr::parse_instructions;
|
use crate::asm::parse::parse_instr::parse_instructions;
|
||||||
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
||||||
use crate::asm::patches::TryRemove;
|
use crate::asm::patches::TryRemove;
|
||||||
|
|
||||||
pub fn parse_cond_branch(tok: Sexp, parsers: &[Box<dyn OpParser>]) -> Result<(Cond, Vec<Instr>), Error> {
|
pub fn parse_cond_branch(tok: Sexp, parsers: &[Box<dyn AsmModule>]) -> Result<(Cond, Vec<Instr>), Error> {
|
||||||
let mut list = expect_list(Some(tok), false)?;
|
let mut list = expect_list(Some(tok), false)?;
|
||||||
let kw = expect_string_atom(list.try_remove(0))?;
|
let kw = expect_string_atom(list.try_remove(0))?;
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,15 @@ use sexp::Sexp;
|
|||||||
|
|
||||||
use crate::asm::error::Error;
|
use crate::asm::error::Error;
|
||||||
use crate::asm::instr::Instr;
|
use crate::asm::instr::Instr;
|
||||||
use crate::asm::instr::op::OpParser;
|
use crate::asm::instr::op::AsmModule;
|
||||||
use crate::asm::parse::parse_cond::parse_cond_branch;
|
use crate::asm::parse::parse_cond::parse_cond_branch;
|
||||||
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
||||||
use crate::asm::patches::SexpIsA;
|
use crate::asm::patches::SexpIsA;
|
||||||
|
|
||||||
use super::parse_op::parse_op;
|
use super::parse_op::parse_op;
|
||||||
|
use crate::asm::parse::arg_parser::ArgParser;
|
||||||
|
|
||||||
pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn OpParser>]) -> Result<Vec<Instr>, Error> {
|
pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn AsmModule>]) -> Result<Vec<Instr>, Error> {
|
||||||
let mut parsed = vec![];
|
let mut parsed = vec![];
|
||||||
for expr in instrs {
|
for expr in instrs {
|
||||||
let tokens = expect_list(Some(expr), false)?;
|
let tokens = expect_list(Some(expr), false)?;
|
||||||
@@ -25,7 +26,7 @@ pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn OpParser>]) -> R
|
|||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
let arg_tokens = toki.clone().take_while(|e| e.is_atom()).collect::<Vec<_>>();
|
let arg_tokens = ArgParser::new(toki.clone().take_while(|e| e.is_atom()).collect());
|
||||||
let branch_tokens = toki
|
let branch_tokens = toki
|
||||||
.skip_while(|e| e.is_atom())
|
.skip_while(|e| e.is_atom())
|
||||||
.take_while(|e| e.is_list());
|
.take_while(|e| e.is_list());
|
||||||
|
|||||||
@@ -2,33 +2,33 @@ use sexp::Sexp;
|
|||||||
|
|
||||||
use crate::asm::data::literal::{Label, RoutineName};
|
use crate::asm::data::literal::{Label, RoutineName};
|
||||||
use crate::asm::error::{AsmError, Error};
|
use crate::asm::error::{AsmError, Error};
|
||||||
use crate::asm::instr::{HLOp, Op};
|
use crate::asm::instr::{OpWrapper, Op};
|
||||||
use crate::asm::instr::cond::parse_cond;
|
use crate::asm::instr::cond::parse_cond;
|
||||||
use crate::asm::instr::op::OpParser;
|
use crate::asm::instr::op::{AsmModule, ParseOpResult};
|
||||||
use crate::asm::parse::parse_data::{parse_label, parse_rd, parse_wr};
|
use crate::asm::parse::parse_data::{parse_label, parse_rd, parse_wr};
|
||||||
use crate::asm::parse::sexp_expect::expect_string_atom;
|
use crate::asm::parse::sexp_expect::expect_string_atom;
|
||||||
|
use crate::asm::parse::arg_parser::ArgParser;
|
||||||
|
|
||||||
pub fn parse_op(keyword: &str, far: bool, arg_tokens_slice: Vec<Sexp>, parsers: &[Box<dyn OpParser>]) -> Result<HLOp, Error> {
|
pub fn parse_op(keyword: &str, far: bool, mut arg_tokens: ArgParser, parsers: &[Box<dyn AsmModule>]) -> Result<OpWrapper, Error> {
|
||||||
let mut arg_tokens = arg_tokens_slice.clone().into_iter();
|
|
||||||
|
|
||||||
Ok(match keyword {
|
Ok(match keyword {
|
||||||
"j" => {
|
"j" => {
|
||||||
let dest = parse_label(arg_tokens.next())?;
|
let dest = parse_label(arg_tokens.next())?;
|
||||||
if far {
|
if far {
|
||||||
HLOp::L(Op::FarJump(dest))
|
OpWrapper::Op(Op::FarJump(dest))
|
||||||
} else {
|
} else {
|
||||||
HLOp::Jump(dest)
|
OpWrapper::Jump(dest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"call" => {
|
"call" => {
|
||||||
let dest = RoutineName(expect_string_atom(arg_tokens.next())?);
|
let dest = RoutineName(arg_tokens.next_string()?);
|
||||||
|
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
for t in arg_tokens {
|
for t in arg_tokens {
|
||||||
args.push(parse_rd(Some(t))?);
|
args.push(parse_rd(Some(t))?);
|
||||||
}
|
}
|
||||||
HLOp::L(Op::Call(dest, args))
|
OpWrapper::Op(Op::Call(dest, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
"ret" => {
|
"ret" => {
|
||||||
@@ -36,48 +36,48 @@ pub fn parse_op(keyword: &str, far: bool, arg_tokens_slice: Vec<Sexp>, parsers:
|
|||||||
for t in arg_tokens {
|
for t in arg_tokens {
|
||||||
args.push(parse_rd(Some(t))?);
|
args.push(parse_rd(Some(t))?);
|
||||||
}
|
}
|
||||||
HLOp::L(Op::Ret(args))
|
OpWrapper::Op(Op::Ret(args))
|
||||||
}
|
}
|
||||||
|
|
||||||
"routine" => {
|
"routine" => {
|
||||||
let dest = RoutineName(expect_string_atom(arg_tokens.next())?);
|
let dest = RoutineName(arg_tokens.next_string()?);
|
||||||
HLOp::L(Op::Routine(dest))
|
OpWrapper::Op(Op::Routine(dest))
|
||||||
}
|
}
|
||||||
|
|
||||||
"s" => {
|
"s" => {
|
||||||
HLOp::L(Op::Skip(parse_rd(arg_tokens.next())?))
|
OpWrapper::Op(Op::Skip(arg_tokens.next_rd()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
"sif" => {
|
"sif" => {
|
||||||
let cond = parse_cond(&expect_string_atom(arg_tokens.next())?)?;
|
let cond = parse_cond(&arg_tokens.next_string()?)?;
|
||||||
let offs = parse_rd(arg_tokens.next())?;
|
let offs = arg_tokens.next_rd()?;
|
||||||
HLOp::L(Op::SkipIf(cond, offs))
|
OpWrapper::Op(Op::SkipIf(cond, offs))
|
||||||
}
|
}
|
||||||
|
|
||||||
"jif" => {
|
"jif" => {
|
||||||
let cond = parse_cond(&expect_string_atom(arg_tokens.next())?)?;
|
let cond = parse_cond(&arg_tokens.next_string()?)?;
|
||||||
let dest = parse_label(arg_tokens.next())?;
|
let dest = parse_label(arg_tokens.next())?;
|
||||||
HLOp::JumpIf(cond, dest)
|
OpWrapper::JumpIf(cond, dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
"barrier" => {
|
"barrier" => {
|
||||||
HLOp::L(Op::Barrier(match arg_tokens.next() {
|
OpWrapper::Op(Op::Barrier(match arg_tokens.next() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(s) => Some(expect_string_atom(Some(s))?.into()),
|
Some(s) => Some(expect_string_atom(Some(s))?.into()),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
"fault" => {
|
"fault" => {
|
||||||
HLOp::L(Op::Fault(match arg_tokens.next() {
|
OpWrapper::Op(Op::Fault(match arg_tokens.next() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(s) => Some(expect_string_atom(Some(s))?.into()),
|
Some(s) => Some(expect_string_atom(Some(s))?.into()),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
"ld" => {
|
"ld" => {
|
||||||
HLOp::L(Op::Move {
|
OpWrapper::Op(Op::Move {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: arg_tokens.next_wr()?,
|
||||||
src: parse_rd(arg_tokens.next())?,
|
src: arg_tokens.next_rd()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,19 +85,22 @@ pub fn parse_op(keyword: &str, far: bool, arg_tokens_slice: Vec<Sexp>, parsers:
|
|||||||
if let Some(label) = other.strip_prefix(':') {
|
if let Some(label) = other.strip_prefix(':') {
|
||||||
let label = Label::Named(label.to_string());
|
let label = Label::Named(label.to_string());
|
||||||
if far {
|
if far {
|
||||||
HLOp::L(Op::FarLabel(label))
|
OpWrapper::Op(Op::FarLabel(label))
|
||||||
} else {
|
} else {
|
||||||
HLOp::Label(label)
|
OpWrapper::Label(label)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for p in parsers {
|
for p in parsers {
|
||||||
match p.parse_op(keyword, far, arg_tokens_slice.clone()) {
|
arg_tokens = match p.parse_op(keyword, arg_tokens) {
|
||||||
Ok(op) => return Ok(HLOp::L(Op::Extension(op))),
|
Ok(ParseOpResult::Parsed(op)) => return Ok(OpWrapper::Op(Op::Extension(op))),
|
||||||
Err(Error::Asm(AsmError::UnknownInstruction)) => {
|
Ok(ParseOpResult::Unknown(to_reuse)) => {
|
||||||
/* ok, try another */
|
if to_reuse.parsing_started() {
|
||||||
|
panic!("Module \"{}\" started parsing {}, but returned Unknown!", p.name(), keyword);
|
||||||
}
|
}
|
||||||
Err(other) => {
|
to_reuse
|
||||||
return Err(other);
|
}
|
||||||
|
Err(err) => {
|
||||||
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ use sexp::Sexp;
|
|||||||
|
|
||||||
use crate::asm::data::literal::RoutineName;
|
use crate::asm::data::literal::RoutineName;
|
||||||
use crate::asm::error::Error;
|
use crate::asm::error::Error;
|
||||||
use crate::asm::instr::op::OpParser;
|
use crate::asm::instr::op::AsmModule;
|
||||||
use crate::asm::instr::Routine;
|
use crate::asm::instr::Routine;
|
||||||
use crate::asm::parse::parse_instr::parse_instructions;
|
use crate::asm::parse::parse_instr::parse_instructions;
|
||||||
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
||||||
use crate::asm::patches::TryRemove;
|
use crate::asm::patches::TryRemove;
|
||||||
|
|
||||||
pub fn parse_routines(routines: Vec<Sexp>, parsers: &[Box<dyn OpParser>]) -> Result<Vec<Routine>, Error> {
|
pub fn parse_routines(routines: Vec<Sexp>, parsers: &[Box<dyn AsmModule>]) -> Result<Vec<Routine>, Error> {
|
||||||
let mut parsed = vec![];
|
let mut parsed = vec![];
|
||||||
for rt in routines {
|
for rt in routines {
|
||||||
let mut def = expect_list(Some(rt), false)?;
|
let mut def = expect_list(Some(rt), false)?;
|
||||||
|
|||||||
+112
-108
@@ -1,10 +1,11 @@
|
|||||||
use crsn::asm::data::{Rd, Wr};
|
use crsn::asm::data::{Rd, Wr};
|
||||||
use crsn::asm::error::{AsmError, Error};
|
use crsn::asm::error::{AsmError, Error};
|
||||||
use crsn::asm::instr::op::{OpParser, OpTrait};
|
use crsn::asm::instr::op::{AsmModule, OpTrait, ParseOpResult};
|
||||||
use crsn::asm::parse::parse_data::{parse_rd, parse_wr};
|
use crsn::asm::parse::parse_data::{parse_rd, parse_wr};
|
||||||
use crsn::sexp::Sexp;
|
use crsn::sexp::Sexp;
|
||||||
|
|
||||||
use crate::defs::ArithOp;
|
use crate::defs::ArithOp;
|
||||||
|
use crsn::asm::parse::arg_parser::ArgParser;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ArithOpParser {
|
pub struct ArithOpParser {
|
||||||
@@ -12,31 +13,34 @@ pub struct ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ArithOpParser {
|
impl ArithOpParser {
|
||||||
pub fn new() -> Box<dyn OpParser> {
|
pub fn new() -> Box<dyn AsmModule> {
|
||||||
Box::new(Self {
|
Box::new(Self {
|
||||||
_internal: ()
|
_internal: ()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpParser for ArithOpParser {
|
impl AsmModule for ArithOpParser {
|
||||||
fn parse_op(&self, keyword: &str, _far: bool, arg_tokens_sl: Vec<Sexp>) -> Result<Box<dyn OpTrait>, Error> {
|
fn name(&self) -> &'static str {
|
||||||
let mut arg_tokens = arg_tokens_sl.into_iter();
|
"arith"
|
||||||
Ok(Box::new(match keyword {
|
}
|
||||||
|
|
||||||
|
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpResult, Error> {
|
||||||
|
Ok(ParseOpResult::Parsed(Box::new(match keyword {
|
||||||
"cmp" => {
|
"cmp" => {
|
||||||
ArithOp::Compare {
|
ArithOp::Compare {
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"tst" => {
|
"tst" => {
|
||||||
let arg = parse_rd(arg_tokens.next())?;
|
let arg = args.next_rd()?;
|
||||||
ArithOp::Test { a: arg }
|
ArithOp::Test { a: arg }
|
||||||
}
|
}
|
||||||
|
|
||||||
"inc" => {
|
"inc" => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Add {
|
ArithOp::Add {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
@@ -45,7 +49,7 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"dec" => {
|
"dec" => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Sub {
|
ArithOp::Sub {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
@@ -54,20 +58,20 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"add" => {
|
"add" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Add {
|
ArithOp::Add {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Add {
|
ArithOp::Add {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -77,20 +81,20 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"sub" => {
|
"sub" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Sub {
|
ArithOp::Sub {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Sub {
|
ArithOp::Sub {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -100,20 +104,20 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"mul" => {
|
"mul" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Mul {
|
ArithOp::Mul {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Mul {
|
ArithOp::Mul {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -123,11 +127,11 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"divr" => {
|
"divr" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
let rem = parse_wr(arg_tokens.next())?;
|
let rem = args.next_wr()?;
|
||||||
let div = parse_rd(arg_tokens.next())?;
|
let div = args.next_rd()?;
|
||||||
ArithOp::Div {
|
ArithOp::Div {
|
||||||
dst,
|
dst,
|
||||||
rem,
|
rem,
|
||||||
@@ -137,10 +141,10 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
4 => {
|
4 => {
|
||||||
ArithOp::Div {
|
ArithOp::Div {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
rem: parse_wr(arg_tokens.next())?,
|
rem: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
div: parse_rd(arg_tokens.next())?,
|
div: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -150,18 +154,18 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"div" => {
|
"div" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Div {
|
ArithOp::Div {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
rem: Wr::discard(),
|
rem: Wr::discard(),
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
div: parse_rd(arg_tokens.next())?,
|
div: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
let div = parse_rd(arg_tokens.next())?;
|
let div = args.next_rd()?;
|
||||||
ArithOp::Div {
|
ArithOp::Div {
|
||||||
dst,
|
dst,
|
||||||
rem: Wr::discard(),
|
rem: Wr::discard(),
|
||||||
@@ -176,17 +180,17 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"mod" => {
|
"mod" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Mod {
|
ArithOp::Mod {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
div: parse_rd(arg_tokens.next())?,
|
div: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
let div = parse_rd(arg_tokens.next())?;
|
let div = args.next_rd()?;
|
||||||
ArithOp::Mod {
|
ArithOp::Mod {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
@@ -200,20 +204,20 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"and" => {
|
"and" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::And {
|
ArithOp::And {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::And {
|
ArithOp::And {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -223,20 +227,20 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"or" => {
|
"or" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Or {
|
ArithOp::Or {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Or {
|
ArithOp::Or {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -246,20 +250,20 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"xor" => {
|
"xor" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Xor {
|
ArithOp::Xor {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Xor {
|
ArithOp::Xor {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
b: parse_rd(arg_tokens.next())?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -269,15 +273,15 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"cpl" => {
|
"cpl" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
2 => {
|
2 => {
|
||||||
ArithOp::Cpl {
|
ArithOp::Cpl {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Cpl {
|
ArithOp::Cpl {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
@@ -290,24 +294,24 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"rol" => {
|
"rol" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Rol {
|
ArithOp::Rol {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
n: parse_rd(arg_tokens.next())?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Rol {
|
ArithOp::Rol {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
n: parse_rd(arg_tokens.next())?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Rol {
|
ArithOp::Rol {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
@@ -321,24 +325,24 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"ror" => {
|
"ror" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Ror {
|
ArithOp::Ror {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
n: parse_rd(arg_tokens.next())?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Ror {
|
ArithOp::Ror {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
n: parse_rd(arg_tokens.next())?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Ror {
|
ArithOp::Ror {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
@@ -352,24 +356,24 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"lsl" | "asl" => {
|
"lsl" | "asl" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Lsl {
|
ArithOp::Lsl {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
n: parse_rd(arg_tokens.next())?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Lsl {
|
ArithOp::Lsl {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
n: parse_rd(arg_tokens.next())?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Lsl {
|
ArithOp::Lsl {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
@@ -383,24 +387,24 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"lsr" => {
|
"lsr" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Lsr {
|
ArithOp::Lsr {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
n: parse_rd(arg_tokens.next())?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Lsr {
|
ArithOp::Lsr {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
n: parse_rd(arg_tokens.next())?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Lsr {
|
ArithOp::Lsr {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
@@ -414,24 +418,24 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"asr" => {
|
"asr" => {
|
||||||
match arg_tokens.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
ArithOp::Asr {
|
ArithOp::Asr {
|
||||||
dst: parse_wr(arg_tokens.next())?,
|
dst: args.next_wr()?,
|
||||||
a: parse_rd(arg_tokens.next())?,
|
a: args.next_rd()?,
|
||||||
n: parse_rd(arg_tokens.next())?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Asr {
|
ArithOp::Asr {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
n: parse_rd(arg_tokens.next())?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = parse_wr(arg_tokens.next())?;
|
let dst = args.next_wr()?;
|
||||||
ArithOp::Asr {
|
ArithOp::Asr {
|
||||||
dst,
|
dst,
|
||||||
a: dst.as_rd(),
|
a: dst.as_rd(),
|
||||||
@@ -445,8 +449,8 @@ impl OpParser for ArithOpParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_other => {
|
_other => {
|
||||||
return Err(Error::Asm(AsmError::UnknownInstruction));
|
return Ok(ParseOpResult::Unknown(args));
|
||||||
}
|
}
|
||||||
}))
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user