Files
rasp/src/vm/vm.rs

123 lines
3.4 KiB
Rust
Raw Normal View History

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<u8>,
pub(super) registers: Registers,
}
impl Vm {
pub fn new(mem: Vec<u8>, 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<u64> {
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::<LE>()
.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::<LE>()
.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::<LE>(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::<LE>(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());
}
}