2020-02-10 13:22:54 -05:00
|
|
|
use crate::vm::{error::*, flags::Flags, inst::*, reg::*, vm::*, visit::*, mem::MemCursor};
|
2020-02-03 17:56:32 -05:00
|
|
|
|
|
|
|
|
impl Vm {
|
|
|
|
|
pub fn tick(&mut self) -> Result<()> {
|
2020-02-10 16:31:08 -05:00
|
|
|
let next_ip = self.visit_inst()?;
|
2020-02-10 13:22:54 -05:00
|
|
|
self.set_reg(IP, next_ip);
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn next_ip(&self) -> Result<Addr> {
|
|
|
|
|
let ip = self.ip();
|
|
|
|
|
let op = self.get_inst_op(ip)?;
|
|
|
|
|
Ok(ip + (inst_len(op) as u64))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn with_regs<F, B>(&mut self, r1: Reg, r2: Reg, mapping: F) -> B
|
|
|
|
|
where F: FnOnce(Word, Word) -> B
|
|
|
|
|
{
|
|
|
|
|
let w1 = self.get_reg(r1);
|
|
|
|
|
let w2 = self.get_reg(r2);
|
|
|
|
|
(mapping)(w1, w2)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-10 16:31:08 -05:00
|
|
|
impl VisitInst for Vm {
|
2020-02-10 13:22:54 -05:00
|
|
|
type Out = Addr;
|
|
|
|
|
|
|
|
|
|
fn cursor(&self) -> MemCursor {
|
|
|
|
|
self.mem_cursor(self.ip() as usize)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn add(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let out = self.with_regs(r1, r2, |w1, w2| w1.wrapping_add(w2));
|
|
|
|
|
self.set_reg(r1, out);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn mul(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let out = self.with_regs(r1, r2, |w1, w2| w1.wrapping_mul(w2));
|
|
|
|
|
self.set_reg(r1, out);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn div(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
// TODO : check w2 == 0 and throw error/exception
|
|
|
|
|
let out = self.with_regs(r1, r2, |w1, w2| w1 / w2);
|
|
|
|
|
self.set_reg(r1, out);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn mod_(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
// TODO : check w2 == 0 and throw error/exception
|
|
|
|
|
let out = self.with_regs(r1, r2, |w1, w2| w1 % w2);
|
|
|
|
|
self.set_reg(r1, out);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn ineg(&mut self, r1: Reg) -> Result<Self::Out> {
|
|
|
|
|
let w1 = self.get_reg(r1);
|
|
|
|
|
self.set_reg(r1, (!w1).wrapping_add(1));
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn and(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let out = self.with_regs(r1, r2, |w1, w2| w1 & w2);
|
|
|
|
|
self.set_reg(r1, out);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn or(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let out = self.with_regs(r1, r2, |w1, w2| w1 | w2);
|
|
|
|
|
self.set_reg(r1, out);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn inv(&mut self, r1: Reg) -> Result<Self::Out> {
|
|
|
|
|
let w1 = self.get_reg(r1);
|
|
|
|
|
self.set_reg(r1, !w1);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn not(&mut self, r1: Reg) -> Result<Self::Out> {
|
|
|
|
|
let w1 = self.get_reg(r1);
|
|
|
|
|
self.set_reg(r1, (w1 == 0) as Word);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn xor(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let out = self.with_regs(r1, r2, |w1, w2| w1 ^ w2);
|
|
|
|
|
self.set_reg(r1, out);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn shl(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let out = self.with_regs(r1, r2, |w1, w2| w1 << w2);
|
|
|
|
|
self.set_reg(r1, out);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn shr(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let out = self.with_regs(r1, r2, |w1, w2| w1 >> w2);
|
|
|
|
|
self.set_reg(r1, out);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn cmpeq(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let cmp = self.with_regs(r1, r2, |w1, w2| w1 == w2);
|
|
|
|
|
if cmp {
|
|
|
|
|
self.insert_flags(Flags::COMPARE);
|
|
|
|
|
} else {
|
|
|
|
|
self.remove_flags(Flags::COMPARE);
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
2020-02-10 13:22:54 -05:00
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn cmplt(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let cmp = self.with_regs(r1, r2, |w1, w2| w1 < w2);
|
|
|
|
|
if cmp {
|
|
|
|
|
self.insert_flags(Flags::COMPARE);
|
|
|
|
|
} else {
|
|
|
|
|
self.remove_flags(Flags::COMPARE);
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
2020-02-10 13:22:54 -05:00
|
|
|
self.next_ip()
|
|
|
|
|
}
|
2020-02-03 17:56:32 -05:00
|
|
|
|
2020-02-10 13:22:54 -05:00
|
|
|
fn jmp(&mut self, r1: Reg) -> Result<Self::Out> {
|
|
|
|
|
let addr = self.get_reg(r1);
|
|
|
|
|
Ok(addr)
|
|
|
|
|
}
|
2020-02-03 17:56:32 -05:00
|
|
|
|
2020-02-10 13:22:54 -05:00
|
|
|
fn jz(&mut self, r1: Reg) -> Result<Self::Out> {
|
|
|
|
|
if !self.flags().contains(Flags::COMPARE) {
|
|
|
|
|
Ok(self.get_reg(r1))
|
|
|
|
|
} else {
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn jnz(&mut self, r1: Reg) -> Result<Self::Out> {
|
|
|
|
|
if self.flags().contains(Flags::COMPARE) {
|
|
|
|
|
Ok(self.get_reg(r1))
|
|
|
|
|
} else {
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn load(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let value = Vm::load(self, r2)?;
|
|
|
|
|
self.set_reg_checked(r1, value)?;
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn regcopy(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let value = self.get_reg_checked(r2)?;
|
|
|
|
|
self.set_reg_checked(r1, value)?;
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn storeimm64(&mut self, r1: Reg, w1: Word) -> Result<Self::Out> {
|
|
|
|
|
self.set_reg_checked(r1, w1)?;
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn storeimm32(&mut self, r1: Reg, w1: HalfWord) -> Result<Self::Out> {
|
|
|
|
|
self.set_reg_checked(r1, w1 as Word)?;
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn memcopy(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let value = Vm::load(self, r2)?;
|
|
|
|
|
self.store(r1, value)?;
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn store(&mut self, r1: Reg, r2: Reg) -> Result<Self::Out> {
|
|
|
|
|
let value = self.get_reg_checked(r1)?;
|
|
|
|
|
self.store(r2, value)?;
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn halt(&mut self) -> Result<Self::Out> {
|
|
|
|
|
self.insert_flags(Flags::HALT);
|
|
|
|
|
self.next_ip()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn nop(&mut self) -> Result<Self::Out> {
|
|
|
|
|
self.next_ip()
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
}
|