use super::{Context, RtError::*, RtResult};
use crate::inst::Op::{self, *};
pub fn ldm(ctx: &mut Context, op: &Op) -> RtResult {
match op {
MultiOp(ops) => match ops[..] {
[ref op, Literal(val)] if op.is_register() => {
*ctx.get_mut_register(op) = val;
Ok(())
}
_ => Err(InvalidMultiOp),
},
&Literal(val) => {
ctx.acc = val;
Ok(())
}
Null => Err(NoOperand),
_ => Err(InvalidOperand),
}
}
pub fn ldd(ctx: &mut Context, op: &Op) -> RtResult {
match op {
Addr(addr) => {
ctx.acc = ctx.mem.get(addr).copied()?;
Ok(())
}
MultiOp(ops) => match ops[..] {
[ref reg, Addr(ref addr)] if reg.is_register() => {
*ctx.get_mut_register(reg) = ctx.mem.get(addr).copied()?;
Ok(())
}
_ => Err(InvalidMultiOp),
},
Null => Err(NoOperand),
_ => Err(InvalidOperand),
}
}
pub fn ldi(ctx: &mut Context, op: &Op) -> RtResult {
match op {
&Addr(addr) => {
let addr2 = ctx.mem.get(&addr)?;
ctx.acc = ctx
.mem
.get(addr2)
.copied()
.map_err(|_| InvalidIndirectAddr {
src: addr,
redirect: *addr2,
})?;
Ok(())
}
MultiOp(ops) => match ops[..] {
[ref reg, Addr(addr)] if reg.is_register() => {
let addr2 = ctx.mem.get(&addr)?;
*ctx.get_mut_register(reg) =
ctx.mem
.get(addr2)
.copied()
.map_err(|_| InvalidIndirectAddr {
src: addr,
redirect: *addr2,
})?;
Ok(())
}
_ => Err(InvalidMultiOp),
},
Null => Err(NoOperand),
_ => Err(InvalidOperand),
}
}
pub fn ldx(ctx: &mut Context, op: &Op) -> RtResult {
match op {
&Addr(addr) => {
ctx.acc = ctx
.mem
.get(&(addr + ctx.ix))
.copied()
.map_err(|_| InvalidIndexedAddr {
src: addr,
offset: ctx.ix,
})?;
Ok(())
}
MultiOp(ops) => match ops[..] {
[ref reg, Addr(addr)] if reg.is_register() => {
*ctx.get_mut_register(reg) =
ctx.mem
.get(&(addr + ctx.ix))
.copied()
.map_err(|_| InvalidIndexedAddr {
src: addr,
offset: ctx.ix,
})?;
Ok(())
}
_ => Err(InvalidMultiOp),
},
Null => Err(NoOperand),
_ => Err(InvalidOperand),
}
}
pub fn ldr(ctx: &mut Context, op: &Op) -> RtResult {
match op {
&Literal(val) => ctx.ix = val,
Null => return Err(NoOperand),
_ => return Err(InvalidOperand),
}
Ok(())
}
pub fn mov(ctx: &mut Context, op: &Op) -> RtResult {
match op {
MultiOp(ops) => match ops[..] {
[ref dest, ref src] if dest.is_read_write() && src.is_usizeable() => {
let src = ctx.read(src)?;
ctx.modify(dest, |val| *val = src)?;
}
_ => return Err(InvalidMultiOp),
},
reg if reg.is_register() => *ctx.get_mut_register(reg) = ctx.acc,
Null => return Err(NoOperand),
_ => return Err(InvalidOperand),
}
Ok(())
}
pub fn sto(ctx: &mut Context, op: &Op) -> RtResult {
match op {
Addr(x) => {
*ctx.mem.get_mut(x)? = ctx.acc;
Ok(())
}
Null => Err(NoOperand),
_ => Err(InvalidOperand),
}
}