Add object layout, object parsing, instruction layout
* Object layout and parsing are done in the vm::obj module * Add MemCursor, a wrapper around the std::io::Cursor type for walking through VM memory * Add vm::tick module for containing the Vm::tick() method implementation, since it's pretty big * Instructions are now variable-sized, and are read lazily, one-at-a-time directly from memory. * Add VM runtime error structure * Probably some other stuff I forgot Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
80
src/vm/mem.rs
Normal file
80
src/vm/mem.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
use crate::vm::{error::*, reg::*};
|
||||
use byteorder::{LE, ReadBytesExt};
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
io::Cursor,
|
||||
};
|
||||
|
||||
const R1_MASK: u16 = 0b1111_1100_0000_0000;
|
||||
const R2_MASK: u16 = 0b0000_0011_1111_0000;
|
||||
|
||||
pub struct MemCursor<'mem> {
|
||||
cursor: Cursor<&'mem [u8]>,
|
||||
}
|
||||
|
||||
impl<'mem> MemCursor<'mem> {
|
||||
pub fn new(mem: &'mem [u8]) -> Self {
|
||||
MemCursor {
|
||||
cursor: Cursor::new(mem)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursor(&self) -> &Cursor<&'mem [u8]> {
|
||||
&self.cursor
|
||||
}
|
||||
|
||||
pub fn cursor_mut(&mut self) -> &mut Cursor<&'mem [u8]> {
|
||||
&mut self.cursor
|
||||
}
|
||||
|
||||
pub fn next_u8(&mut self) -> Result<u8> {
|
||||
self.read_u8().map_err(|_| VmError::MemOutOfBounds {
|
||||
addr: self.position(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn next_u16(&mut self) -> Result<u16> {
|
||||
self.read_u16::<LE>().map_err(|_| VmError::MemOutOfBounds {
|
||||
addr: self.position(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn next_u32(&mut self) -> Result<u32> {
|
||||
self.read_u32::<LE>().map_err(|_| VmError::MemOutOfBounds {
|
||||
addr: self.position(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn next_u64(&mut self) -> Result<u64> {
|
||||
self.read_u64::<LE>().map_err(|_| VmError::MemOutOfBounds {
|
||||
addr: self.position(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn next_regs(&mut self) -> Result<(Reg, Reg)> {
|
||||
let next16 = self.next_u16()?;
|
||||
let r1 = ((R1_MASK & next16) >> 10) as Reg;
|
||||
let r2 = ((R2_MASK & next16) >> 4) as Reg;
|
||||
Ok((r1, r2))
|
||||
}
|
||||
|
||||
pub fn next_reg(&mut self) -> Result<Reg> {
|
||||
let next16 = self.next_u16()?;
|
||||
let r1 = ((R1_MASK & next16) >> 10) as Reg;
|
||||
Ok(r1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mem> Deref for MemCursor<'mem> {
|
||||
type Target = Cursor<&'mem [u8]>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.cursor()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mem> DerefMut for MemCursor<'mem> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.cursor_mut()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user