use super::{Context, PasmError::*, PasmResult};
use crate::inst::Op::{self, *};
pub fn jmp(ctx: &mut Context, op: &Op) -> PasmResult {
match op {
&Addr(x) => {
ctx.override_flow_control();
ctx.mar = x;
}
MultiOp(ops) => match ops[..] {
[Addr(eq), Addr(ne)] => {
ctx.override_flow_control();
if ctx.cmp {
ctx.mar = eq;
} else {
ctx.mar = ne;
}
}
_ => return Err(InvalidMultiOp),
},
Null => return Err(NoOperand),
_ => return Err(InvalidOperand),
}
Ok(())
}
pub fn cmp(ctx: &mut Context, op: &Op) -> PasmResult {
match op {
MultiOp(ops) => match ops[..] {
[ref a, ref b] if a.is_usizeable() && b.is_usizeable() => {
ctx.cmp = ctx.read(a)? == ctx.read(b)?;
}
_ => return Err(InvalidMultiOp),
},
val if val.is_usizeable() => ctx.cmp = ctx.acc == ctx.read(val)?,
Null => return Err(NoOperand),
_ => return Err(InvalidOperand),
}
Ok(())
}
pub fn cmi(ctx: &mut Context, op: &Op) -> PasmResult {
match op {
&Addr(addr) => {
let addr2 = ctx.mem.get(&addr)?;
ctx.cmp = ctx.acc
== ctx
.mem
.get(addr2)
.copied()
.map_err(|_| InvalidIndirectAddress(addr))?;
Ok(())
}
MultiOp(ops) => match ops[..] {
[ref dest, Addr(addr)] if dest.is_usizeable() => {
let addr2 = ctx.mem.get(&addr)?;
ctx.cmp = ctx.read(dest)?
== ctx
.mem
.get(addr2)
.copied()
.map_err(|_| InvalidIndirectAddress(addr))?;
Ok(())
}
_ => Err(InvalidMultiOp),
},
Null => Err(NoOperand),
_ => Err(InvalidOperand),
}
}
pub fn jpe(ctx: &mut Context, op: &Op) -> PasmResult {
match op {
&Addr(addr) => {
if ctx.cmp {
ctx.override_flow_control();
ctx.mar = addr;
}
Ok(())
}
Null => Err(NoOperand),
_ => Err(InvalidOperand),
}
}
pub fn jpn(ctx: &mut Context, op: &Op) -> PasmResult {
match op {
&Addr(addr) => {
if !ctx.cmp {
ctx.override_flow_control();
ctx.mar = addr;
}
Ok(())
}
Null => Err(NoOperand),
_ => Err(InvalidOperand),
}
}