add explicit retval arg to all instrs (can be shortened), add Wr::discard()
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::convert::TryFrom;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::borrow::Cow;
|
||||
|
||||
|
||||
+17
-5
@@ -11,7 +11,7 @@ use literal::Addr;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use crate::data::literal::{Value, is_negative, as_signed};
|
||||
use crate::data::literal::{Value, as_signed};
|
||||
use std::fmt::{Debug, Formatter, Display};
|
||||
use std::fmt;
|
||||
|
||||
@@ -64,6 +64,7 @@ impl From<DstDisp> for DataDisp {
|
||||
DstDisp::ImmediatePtr(x) => DataDisp::ImmediatePtr(x),
|
||||
DstDisp::Register(x) => DataDisp::Register(x),
|
||||
DstDisp::RegisterPtr(x) => DataDisp::RegisterPtr(x),
|
||||
DstDisp::Discard => DataDisp::Immediate(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,6 +104,8 @@ pub enum DstDisp {
|
||||
Register(Register),
|
||||
/// Pointer into memory, stored in a numbered register
|
||||
RegisterPtr(Register),
|
||||
/// Discard the written value
|
||||
Discard,
|
||||
}
|
||||
|
||||
impl From<DstDisp> for SrcDisp {
|
||||
@@ -111,6 +114,7 @@ impl From<DstDisp> for SrcDisp {
|
||||
DstDisp::ImmediatePtr(x) => SrcDisp::ImmediatePtr(x),
|
||||
DstDisp::Register(x) => SrcDisp::Register(x),
|
||||
DstDisp::RegisterPtr(x) => SrcDisp::RegisterPtr(x),
|
||||
DstDisp::Discard => SrcDisp::Immediate(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,6 +146,10 @@ impl Rd {
|
||||
pub fn mask(self) -> Mask {
|
||||
self.1
|
||||
}
|
||||
|
||||
pub fn immediate(val : Value) -> Rd {
|
||||
Rd(SrcDisp::Immediate(val), Mask::default())
|
||||
}
|
||||
}
|
||||
|
||||
/// Data destination argument (read-write)
|
||||
@@ -161,15 +169,19 @@ impl Wr {
|
||||
pub fn as_rd(&self) -> Rd {
|
||||
Rd(self.0.into(), self.1)
|
||||
}
|
||||
|
||||
pub fn discard() -> Wr {
|
||||
Wr(DstDisp::Discard, Mask::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Rd {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Rd(")?;
|
||||
let disp : DataDisp = self.0.into();
|
||||
write!(f, "{}", disp);
|
||||
write!(f, "{}", disp)?;
|
||||
if !self.mask().is_default() {
|
||||
write!(f, ",{:?}", self.mask());
|
||||
write!(f, ",{:?}", self.mask())?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
@@ -179,9 +191,9 @@ impl Debug for Wr {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Wr(")?;
|
||||
let disp : DataDisp = self.0.into();
|
||||
write!(f, "{}", disp);
|
||||
write!(f, "{}", disp)?;
|
||||
if !self.mask().is_default() {
|
||||
write!(f, ",{:?}", self.mask());
|
||||
write!(f, ",{:?}", self.mask())?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ pub enum Cond {
|
||||
NonNegative,
|
||||
Overflow,
|
||||
NotOverflow,
|
||||
Invalid,
|
||||
Valid,
|
||||
Carry,
|
||||
NotCarry,
|
||||
}
|
||||
@@ -37,9 +39,11 @@ impl Display for Cond {
|
||||
Cond::NonPositive => "npos",
|
||||
Cond::NonNegative => "nneg",
|
||||
Cond::Overflow => "ov",
|
||||
Cond::NotOverflow => "nov",
|
||||
Cond::Carry => "c",
|
||||
Cond::NotCarry => "nc",
|
||||
Cond::NotOverflow => "nov"
|
||||
Cond::Invalid => "inval",
|
||||
Cond::Valid => "ok",
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -68,6 +72,9 @@ impl Not for Cond {
|
||||
Cond::Greater => Cond::LowerOrEqual,
|
||||
Cond::LowerOrEqual => Cond::Greater,
|
||||
Cond::GreaterOrEqual => Cond::Lower,
|
||||
|
||||
Cond::Invalid => Cond::Valid,
|
||||
Cond::Valid => Cond::Invalid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-28
@@ -46,36 +46,29 @@ pub enum Op {
|
||||
/// Generate a run-time fault with a debugger message
|
||||
Fault(Option<DebugMsg>),
|
||||
|
||||
/* Arithmetic */
|
||||
Move { dst: Wr, src: Rd },
|
||||
Test { a: Rd },
|
||||
Compare { a: Rd, b: Rd },
|
||||
StoreStatus { dst: Wr },
|
||||
LoadStatus { src: Rd },
|
||||
|
||||
/// Copy a value
|
||||
Mov(Wr, Rd),
|
||||
/// Compare two values and set conditional flags.
|
||||
/// If the values are identical, evaluate if they are zero, positive, or negative (the "tst" op)
|
||||
Cmp(Rd, 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 },
|
||||
|
||||
// Arithmetic
|
||||
Inc(Wr),
|
||||
Dec(Wr),
|
||||
Add(Wr, Rd),
|
||||
Sub(Wr, Rd),
|
||||
Mul(Wr, Rd),
|
||||
Div(Wr, Rd),
|
||||
Mod(Wr, Rd),
|
||||
DivRem(Wr, /*rem*/Wr, Rd),
|
||||
|
||||
// /// Bitwise
|
||||
And(Wr, Rd),
|
||||
Or(Wr, Rd),
|
||||
Xor(Wr, Rd),
|
||||
Cpl(Wr),
|
||||
Rol(Wr, Rd), // Rotate (with wrap-around)
|
||||
Ror(Wr, Rd),
|
||||
Lsl(Wr, Rd), // Shift
|
||||
Lsr(Wr, Rd),
|
||||
Asr(Wr, Rd),
|
||||
|
||||
// TODO arithmetics, bit manipulation, byte operations
|
||||
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 },
|
||||
}
|
||||
|
||||
/// Make "into" work
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use sexp::{Sexp, Atom};
|
||||
use crate::data::{DataDisp, Rd, Wr, DstDisp, SrcDisp, reg};
|
||||
use crate::error::Error;
|
||||
use crate::data::literal::{Value, Addr, Label};
|
||||
use crate::data::literal::{Addr, Label};
|
||||
use std::convert::TryFrom;
|
||||
use crate::parse::sexp_expect::expect_string_atom;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ pub fn parse_instructions(instrs: Vec<Sexp>) -> Result<Vec<Instr>, Error> {
|
||||
false
|
||||
};
|
||||
|
||||
let arg_tokens = toki.clone().take_while(|e| e.is_atom());
|
||||
let arg_tokens = toki.clone().take_while(|e| e.is_atom()).collect::<Vec<_>>();
|
||||
let branch_tokens = toki
|
||||
.skip_while(|e| e.is_atom())
|
||||
.take_while(|e| e.is_list());
|
||||
@@ -42,7 +42,7 @@ pub fn parse_instructions(instrs: Vec<Sexp>) -> Result<Vec<Instr>, Error> {
|
||||
};
|
||||
|
||||
parsed.push(Instr {
|
||||
op: parse_op(name.as_str(), far, arg_tokens)?,
|
||||
op: parse_op(name.as_str(), far, arg_tokens.into_iter())?,
|
||||
branches
|
||||
});
|
||||
}
|
||||
|
||||
+375
-84
@@ -5,8 +5,9 @@ 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;
|
||||
use crate::data::{Rd, Wr};
|
||||
|
||||
pub fn parse_op(keyword: &str, far : bool, mut arg_tokens: impl Iterator<Item=Sexp>) -> Result<HLOp, Error> {
|
||||
pub fn parse_op(keyword: &str, far: bool, mut arg_tokens: impl ExactSizeIterator<Item=Sexp> + Clone) -> Result<HLOp, Error> {
|
||||
Ok(match keyword {
|
||||
"j" => {
|
||||
let dest = parse_label(arg_tokens.next())?;
|
||||
@@ -71,143 +72,433 @@ pub fn parse_op(keyword: &str, far : bool, mut arg_tokens: impl Iterator<Item=Se
|
||||
}
|
||||
|
||||
"ld" => {
|
||||
HLOp::L(Op::Mov(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(Op::Move {
|
||||
dst: parse_wr(arg_tokens.next())?,
|
||||
src: parse_rd(arg_tokens.next())?,
|
||||
})
|
||||
}
|
||||
|
||||
"cmp" => {
|
||||
HLOp::L(Op::Cmp(
|
||||
parse_rd(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(Op::Compare {
|
||||
a: parse_rd(arg_tokens.next())?,
|
||||
b: parse_rd(arg_tokens.next())?,
|
||||
})
|
||||
}
|
||||
|
||||
"tst" => {
|
||||
let arg = parse_rd(arg_tokens.next())?;
|
||||
HLOp::L(Op::Cmp(arg, arg))
|
||||
HLOp::L(Op::Test { a: arg })
|
||||
}
|
||||
|
||||
"inc" => {
|
||||
HLOp::L(Op::Inc(
|
||||
parse_wr(arg_tokens.next())?
|
||||
))
|
||||
let dst = parse_wr(arg_tokens.next())?;
|
||||
HLOp::L(Op::Add {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
b: Rd::immediate(1),
|
||||
})
|
||||
}
|
||||
|
||||
"dec" => {
|
||||
HLOp::L(Op::Dec(
|
||||
parse_wr(arg_tokens.next())?
|
||||
))
|
||||
let dst = parse_wr(arg_tokens.next())?;
|
||||
HLOp::L(Op::Sub {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
b: Rd::immediate(1),
|
||||
})
|
||||
}
|
||||
|
||||
"add" => {
|
||||
HLOp::L(Op::Add(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Add {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
b: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Add requires 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"sub" => {
|
||||
HLOp::L(Op::Sub(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Sub {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
b: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Sub requires 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"mul" => {
|
||||
HLOp::L(Op::Mul(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
}
|
||||
|
||||
"div" => {
|
||||
HLOp::L(Op::Div(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
}
|
||||
|
||||
"mod" => {
|
||||
HLOp::L(Op::Mod(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Mul {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
b: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Mul requires 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"divr" => {
|
||||
HLOp::L(Op::DivRem(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(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())?;
|
||||
Op::Div {
|
||||
dst,
|
||||
rem,
|
||||
a: dst.as_rd(),
|
||||
div,
|
||||
}
|
||||
}
|
||||
4 => {
|
||||
Op::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" => {
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Div {
|
||||
dst,
|
||||
rem: Wr::discard(),
|
||||
a: dst.as_rd(),
|
||||
div,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Div requires 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"mod" => {
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Mod {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
div,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Mod requires 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"and" => {
|
||||
HLOp::L(Op::And(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::And {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
b: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("And requires 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"or" => {
|
||||
HLOp::L(Op::Or(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Or {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
b: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Or requires 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"xor" => {
|
||||
HLOp::L(Op::Xor(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Xor {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
b: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Xor requires 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"cpl" => {
|
||||
HLOp::L(Op::Cpl(
|
||||
parse_wr(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
2 => {
|
||||
Op::Cpl {
|
||||
dst: parse_wr(arg_tokens.next())?,
|
||||
a: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = parse_wr(arg_tokens.next())?;
|
||||
Op::Cpl {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Cpl requires 1 or 2 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"rol" => {
|
||||
HLOp::L(Op::Rol(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Rol {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
n: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = parse_wr(arg_tokens.next())?;
|
||||
Op::Rol {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
n: Rd::immediate(1),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Rol requires 1, 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"ror" => {
|
||||
HLOp::L(Op::Ror(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Ror {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
n: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = parse_wr(arg_tokens.next())?;
|
||||
Op::Ror {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
n: Rd::immediate(1),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Ror requires 1, 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"lsl" | "asl" => {
|
||||
HLOp::L(Op::Lsl(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Lsl {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
n: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = parse_wr(arg_tokens.next())?;
|
||||
Op::Lsl {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
n: Rd::immediate(1),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Lsl requires 1, 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"lsr" => {
|
||||
HLOp::L(Op::Lsr(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Lsr {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
n: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = parse_wr(arg_tokens.next())?;
|
||||
Op::Lsr {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
n: Rd::immediate(1),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Lsr requires 1, 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
"asr" => {
|
||||
HLOp::L(Op::Asr(
|
||||
parse_wr(arg_tokens.next())?,
|
||||
parse_rd(arg_tokens.next())?
|
||||
))
|
||||
HLOp::L(match arg_tokens.len() {
|
||||
3 => {
|
||||
Op::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())?;
|
||||
Op::Asr {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
n: parse_rd(arg_tokens.next())?,
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let dst = parse_wr(arg_tokens.next())?;
|
||||
Op::Asr {
|
||||
dst,
|
||||
a: dst.as_rd(),
|
||||
n: Rd::immediate(1),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Parse("Asr requires 1, 2 or 3 arguments".into()));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TODO more instructions
|
||||
|
||||
other => {
|
||||
if let Some(label) = other.strip_prefix(':') {
|
||||
let label = Label::Named(label.to_string());
|
||||
|
||||
Reference in New Issue
Block a user