use crate::vm::{error::*, flags::Flags, inst::*, reg::*, vm::*, visit::*, mem::MemCursor}; use std::io::stdin; impl Vm { pub fn tick(&mut self) -> Result<()> { let next_ip = visit_inst(self)?; self.set_reg(IP, next_ip); Ok(()) } fn next_ip(&self) -> Result { let ip = self.ip(); let op = self.get_inst_op(ip)?; Ok(ip + (inst_len(op) as u64)) } fn with_regs(&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) } } impl InstAcceptor for Vm { type Out = Addr; fn cursor(&self) -> MemCursor { self.mem_cursor(self.ip() as usize) } fn add(&mut self, r1: Reg, r2: Reg) -> Result { 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 { 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 { // 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 { // 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 { 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 { 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 { 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 { let w1 = self.get_reg(r1); self.set_reg(r1, !w1); self.next_ip() } fn not(&mut self, r1: Reg) -> Result { 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 { 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 { 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 { 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 { let cmp = self.with_regs(r1, r2, |w1, w2| w1 == w2); if cmp { self.insert_flags(Flags::COMPARE); } else { self.remove_flags(Flags::COMPARE); } self.next_ip() } fn cmplt(&mut self, r1: Reg, r2: Reg) -> Result { let cmp = self.with_regs(r1, r2, |w1, w2| w1 < w2); if cmp { self.insert_flags(Flags::COMPARE); } else { self.remove_flags(Flags::COMPARE); } self.next_ip() } fn jmp(&mut self, r1: Reg) -> Result { let addr = self.get_reg(r1); Ok(addr) } fn jz(&mut self, r1: Reg) -> Result { if !self.flags().contains(Flags::COMPARE) { Ok(self.get_reg(r1)) } else { self.next_ip() } } fn jnz(&mut self, r1: Reg) -> Result { if self.flags().contains(Flags::COMPARE) { Ok(self.get_reg(r1)) } else { self.next_ip() } } fn load(&mut self, r1: Reg, r2: Reg) -> Result { let value = Vm::load(self, r2)?; self.set_reg_checked(r1, value)?; self.next_ip() } fn regcopy(&mut self, r1: Reg, r2: Reg) -> Result { 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.set_reg_checked(r1, w1)?; self.next_ip() } fn storeimm32(&mut self, r1: Reg, w1: HalfWord) -> Result { self.set_reg_checked(r1, w1 as Word)?; self.next_ip() } fn memcopy(&mut self, r1: Reg, r2: Reg) -> Result { let value = Vm::load(self, r2)?; self.store(r1, value)?; self.next_ip() } fn store(&mut self, r1: Reg, r2: Reg) -> Result { let value = self.get_reg_checked(r1)?; self.store(r2, value)?; self.next_ip() } fn halt(&mut self) -> Result { self.insert_flags(Flags::HALT); self.next_ip() } fn nop(&mut self) -> Result { self.next_ip() } }