use crate::vm::{error::*, flags::*, mem::*, reg::*}; use byteorder::{ReadBytesExt, WriteBytesExt, LE}; use std::{io::Cursor, mem}; pub type Word = u64; pub type HalfWord = u32; pub type Registers = [Word; 64]; pub type Addr = u64; pub struct Vm { pub(super) mem: Vec, pub(super) registers: Registers, } impl Vm { pub fn new(mem: Vec, registers: Registers) -> Self { Vm { mem, registers } } pub fn mem_cursor(&self, at: usize) -> MemCursor { // TODO : MemCursor MemCursor::new(&self.mem[at..]) } pub fn run(&mut self) -> Result { while !self.is_halted() { self.tick()?; } Ok(self.get_reg(STATUS)) } pub fn resume(&mut self) { self.remove_flags(Flags::HALT); } pub fn is_halted(&self) -> bool { self.flags().contains(Flags::HALT) } pub fn get_word(&self, addr: Word) -> Word { let mut reader = Cursor::new(&self.mem[(addr as usize)..]); reader .read_u64::() .expect("word outside of address range") } pub fn get_halfword(&self, addr: Word) -> HalfWord { let mut reader = Cursor::new(&self.mem[(addr as usize)..]); reader .read_u32::() .expect("word outside of address range") } pub fn get_byte(&self, addr: Word) -> u8 { let mut reader = Cursor::new(&self.mem[(addr as usize)..]); reader.read_u8().expect("word outside of address range") } pub fn set_word(&mut self, addr: Word, value: Word) { let mut writer = Cursor::new(&mut self.mem[(addr as usize)..]); writer .write_u64::(value) .expect("word outside of address range"); } pub fn set_halfword(&mut self, addr: Word, value: HalfWord) { let mut writer = Cursor::new(&mut self.mem[(addr as usize)..]); writer .write_u32::(value) .expect("word outside of address range"); } pub fn set_byte(&mut self, addr: Word, value: u8) { let mut writer = Cursor::new(&mut self.mem[(addr as usize)..]); writer .write_u8(value) .expect("word outside of address range"); } pub fn load(&self, reg: Reg) -> Word { self.get_word(self.get_reg(reg)) } pub fn store(&mut self, reg: Reg, value: Word) { let addr = self.get_reg(reg); self.set_word(addr, value); } pub fn get_reg(&self, reg: Reg) -> Word { self.registers[reg as usize] } pub fn set_reg(&mut self, reg: Reg, value: Word) -> Word { mem::replace(&mut self.registers[reg as usize], value) } pub fn ip(&self) -> Word { self.get_reg(IP) } pub fn flags(&self) -> Flags { // this is safe because it's OK if there are random bits flipped - this shouldn't happen // anyway, but if it does, they're ignored unsafe { Flags::from_bits_unchecked(self.get_reg(FLAGS)) } } pub fn insert_flags(&mut self, flags: Flags) { let mut new_flags = self.flags(); new_flags.insert(flags); self.set_flags(new_flags); } pub fn remove_flags(&mut self, flags: Flags) { let mut new_flags = self.flags(); new_flags.remove(flags); self.set_flags(new_flags); } pub fn set_flags(&mut self, flags: Flags) { self.set_reg(FLAGS, flags.bits()); } }