re-arrange modules, add "plug-in" system so instructions can be defined in multiple crates
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
use crsn::asm::data::{Rd, Wr};
|
||||
|
||||
/// A low level instruction
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ArithOp {
|
||||
Test { a: Rd },
|
||||
Compare { a: Rd, b: Rd },
|
||||
|
||||
Add { dst: Wr, a: Rd, b: Rd },
|
||||
Sub { dst: Wr, a: Rd, b: Rd },
|
||||
Mul { dst: Wr, a: Rd, b: Rd },
|
||||
Div { dst: Wr, rem: Wr, a: Rd, div: Rd },
|
||||
// "Mod" is functionally equivalent to "Div" with the result discarded,
|
||||
// but status flags are updated by the remainder
|
||||
Mod { dst: Wr, a: Rd, div: Rd },
|
||||
|
||||
And { dst: Wr, a: Rd, b: Rd },
|
||||
Or { dst: Wr, a: Rd, b: Rd },
|
||||
Xor { dst: Wr, a: Rd, b: Rd },
|
||||
Cpl { dst: Wr, a: Rd },
|
||||
Rol { dst: Wr, a: Rd, n: Rd },
|
||||
// Rotate (with wrap-around)
|
||||
Ror { dst: Wr, a: Rd, n: Rd },
|
||||
Lsl { dst: Wr, a: Rd, n: Rd },
|
||||
// Shift
|
||||
Lsr { dst: Wr, a: Rd, n: Rd },
|
||||
Asr { dst: Wr, a: Rd, n: Rd },
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
use std::ops::Rem;
|
||||
|
||||
use num_traits::PrimInt;
|
||||
|
||||
use crsn::asm::instr::op::OpTrait;
|
||||
use crsn::runtime::fault::Fault;
|
||||
use crsn::runtime::frame::{CallStack, StackFrame};
|
||||
use crsn::runtime::program::Program;
|
||||
|
||||
use crate::defs::ArithOp;
|
||||
|
||||
impl OpTrait for ArithOp {
|
||||
fn execute(&self, _program: &Program, _call_stack: &mut CallStack, frame: &mut StackFrame) -> Result<(), Fault> {
|
||||
match self {
|
||||
ArithOp::Test { a } => {
|
||||
frame.status.clear();
|
||||
let res = frame.read(*a)?;
|
||||
frame.status.update(res);
|
||||
}
|
||||
ArithOp::Compare { a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
frame.status.equal = x == y;
|
||||
frame.status.lower = x < y;
|
||||
frame.status.greater = x > y;
|
||||
// Test flags are set when both arguments have the property
|
||||
if x == y {
|
||||
frame.status.update(x);
|
||||
}
|
||||
}
|
||||
ArithOp::Add { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
let (res, ov) = if let Some(v) = x.checked_add(y) {
|
||||
(v, false)
|
||||
} else {
|
||||
(x.wrapping_add(y), true)
|
||||
};
|
||||
frame.status.update(res);
|
||||
frame.status.overflow = ov;
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Sub { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
let (res, ov) = if let Some(v) = x.checked_sub(y) {
|
||||
(v, false)
|
||||
} else {
|
||||
(x.wrapping_sub(y), true)
|
||||
};
|
||||
frame.status.update(res);
|
||||
frame.status.overflow = ov;
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Mul { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
let (res, ov) = if let Some(v) = x.checked_mul(y) {
|
||||
(v, false)
|
||||
} else {
|
||||
(x.wrapping_mul(y), true)
|
||||
};
|
||||
frame.status.update(res);
|
||||
frame.status.overflow = ov;
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Div { dst, rem, a, div } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let d = frame.read(*div)?;
|
||||
if d == 0 {
|
||||
frame.status.invalid = true;
|
||||
} else {
|
||||
let (res, remainder, ov) = if let Some(v) = x.checked_div(d) {
|
||||
(v, x.rem(d), false)
|
||||
} else {
|
||||
(x.wrapping_div(d), x.wrapping_rem(d), true)
|
||||
};
|
||||
frame.status.update(res);
|
||||
frame.status.overflow = ov;
|
||||
frame.write(*dst, res)?;
|
||||
frame.write(*rem, remainder)?;
|
||||
}
|
||||
}
|
||||
ArithOp::Mod { dst, a, div } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let d = frame.read(*div)?;
|
||||
if d == 0 {
|
||||
frame.status.invalid = true;
|
||||
} else {
|
||||
let (remainder, ov) = if let Some(v) = x.checked_rem(d) {
|
||||
(v, false)
|
||||
} else {
|
||||
(x.wrapping_rem(d), true)
|
||||
};
|
||||
frame.status.update(remainder);
|
||||
frame.status.overflow = ov;
|
||||
frame.write(*dst, remainder)?;
|
||||
}
|
||||
}
|
||||
ArithOp::And { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
let res = x & y;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Or { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
let res = x | y;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Xor { dst, a, b } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*b)?;
|
||||
let res = x ^ y;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Cpl { dst, a } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let res = !x;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Rol { dst, a, n } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*n)?;
|
||||
if y > u32::MAX as u64 {
|
||||
frame.status.invalid = true;
|
||||
} else {
|
||||
let res = x.rotate_left(y as u32);
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
}
|
||||
ArithOp::Ror { dst, a, n } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*n)?;
|
||||
if y > u32::MAX as u64 {
|
||||
frame.status.invalid = true;
|
||||
} else {
|
||||
let res = x.rotate_right(y as u32);
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
}
|
||||
ArithOp::Lsl { dst, a, n } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*n)?;
|
||||
let res = x << y;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Lsr { dst, a, n } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*n)?;
|
||||
let res = x >> y;
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
ArithOp::Asr { dst, a, n } => {
|
||||
frame.status.clear();
|
||||
let x = frame.read(*a)?;
|
||||
let y = frame.read(*n)?;
|
||||
if y > u32::MAX as u64 {
|
||||
frame.status.invalid = true;
|
||||
} else {
|
||||
let res = x.signed_shr(y as u32);
|
||||
frame.status.update(res);
|
||||
frame.write(*dst, res)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
//
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
pub use parse::ArithOpParser;
|
||||
|
||||
mod defs;
|
||||
mod parse;
|
||||
mod exec;
|
||||
|
||||
@@ -0,0 +1,452 @@
|
||||
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));
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user