Add assembler and execution logic
Most everything works, but there's one small bug with the execution involving jumps - still have to figure that one out. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
111
src/vm/mem.rs
111
src/vm/mem.rs
@@ -1,78 +1,65 @@
|
||||
use crate::vm::{addr::*, error::*, inst::*, reg::*};
|
||||
use std::{convert::TryInto, ops::Index, mem};
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt, LE};
|
||||
use std::io::Cursor;
|
||||
|
||||
pub struct MemCursor<T> {
|
||||
pos: Addr,
|
||||
mem: T,
|
||||
cursor: Cursor<T>,
|
||||
}
|
||||
|
||||
impl<T> MemCursor<T>
|
||||
where T: AsRef<[u8]>
|
||||
where Cursor<T>: ReadBytesExt,
|
||||
T: AsRef<[u8]>
|
||||
{
|
||||
pub fn new(mem: T) -> Self {
|
||||
MemCursor { pos: Addr(0), mem }
|
||||
MemCursor { cursor: Cursor::new(mem) }
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Addr {
|
||||
self.pos
|
||||
pub fn position(&self) -> u64 {
|
||||
self.cursor.position()
|
||||
}
|
||||
|
||||
pub fn set_position<P: Into<Addr>>(&mut self, position: P) {
|
||||
self.pos = position.into();
|
||||
self.cursor.set_position((position.into()).0)
|
||||
}
|
||||
|
||||
pub fn next_u8_unchecked(&mut self) -> u8 {
|
||||
let val = self[self.pos];
|
||||
self.pos += 1u64;
|
||||
val
|
||||
self.cursor.read_u8().unwrap()
|
||||
}
|
||||
|
||||
pub fn next_u8(&mut self) -> Result<u8> {
|
||||
self.check_addr(self.pos)
|
||||
self.check_addr(self.position())
|
||||
.map(|_| self.next_u8_unchecked())
|
||||
}
|
||||
|
||||
pub fn next_u16_unchecked(&mut self) -> u16 {
|
||||
let (int_bytes, _) = self.mem.as_ref()
|
||||
.split_at(mem::size_of::<u16>());
|
||||
let val = u16::from_le_bytes(int_bytes.try_into().unwrap());
|
||||
self.pos += 2u64;
|
||||
val
|
||||
self.cursor.read_u16::<LE>().unwrap()
|
||||
}
|
||||
|
||||
pub fn next_u16(&mut self) -> Result<u16> {
|
||||
self.check_addr(self.pos)
|
||||
self.check_addr(self.position())
|
||||
.map(|_| self.next_u16_unchecked())
|
||||
}
|
||||
|
||||
pub fn next_u32_unchecked(&mut self) -> u32 {
|
||||
let (int_bytes, _) = self.mem.as_ref()
|
||||
.split_at(mem::size_of::<u32>());
|
||||
let val = u32::from_le_bytes(int_bytes.try_into().unwrap());
|
||||
self.pos += 4u64;
|
||||
val
|
||||
self.cursor.read_u32::<LE>().unwrap()
|
||||
}
|
||||
|
||||
pub fn next_u32(&mut self) -> Result<u32> {
|
||||
self.check_addr(self.pos)
|
||||
self.check_addr(self.position())
|
||||
.map(|_| self.next_u32_unchecked())
|
||||
}
|
||||
|
||||
pub fn next_u64_unchecked(&mut self) -> u64 {
|
||||
let (int_bytes, _) = self.mem.as_ref()
|
||||
.split_at(mem::size_of::<u64>());
|
||||
let val = u64::from_le_bytes(int_bytes.try_into().unwrap());
|
||||
self.pos += 8u64;
|
||||
val
|
||||
self.cursor.read_u64::<LE>().unwrap()
|
||||
}
|
||||
|
||||
pub fn next_u64(&mut self) -> Result<u64> {
|
||||
self.check_addr(self.pos)
|
||||
self.check_addr(self.position())
|
||||
.map(|_| self.next_u64_unchecked())
|
||||
}
|
||||
|
||||
pub fn next_addr(&mut self) -> Result<Addr> {
|
||||
self.check_addr(self.pos)
|
||||
self.check_addr(self.position())
|
||||
.map(|_| self.next_addr_unchecked())
|
||||
}
|
||||
|
||||
@@ -81,6 +68,7 @@ impl<T> MemCursor<T>
|
||||
}
|
||||
|
||||
pub fn next_inst(&mut self) -> Result<Inst> {
|
||||
let start = self.position();
|
||||
let op = self.next_u16()?;
|
||||
|
||||
macro_rules! dest_source {
|
||||
@@ -102,7 +90,7 @@ impl<T> MemCursor<T>
|
||||
Ok(Inst::$variant(source))
|
||||
}};
|
||||
}
|
||||
match op {
|
||||
let inst = match op {
|
||||
ADD => dest_source!(Add),
|
||||
SUB => dest_source!(Sub),
|
||||
MUL => dest_source!(Mul),
|
||||
@@ -126,7 +114,11 @@ impl<T> MemCursor<T>
|
||||
NOP => Ok(Inst::Nop),
|
||||
DUMP => Ok(Inst::Dump),
|
||||
_ => Err(VmError::IllegalOp { op }),
|
||||
}
|
||||
}?;
|
||||
let end = self.position();
|
||||
let len = (end - start) as usize;
|
||||
assert_eq!(len, inst.len());
|
||||
Ok(inst)
|
||||
}
|
||||
|
||||
fn next_source_source(&mut self) -> Result<(Source, Source)> {
|
||||
@@ -181,16 +173,62 @@ impl<T> MemCursor<T>
|
||||
Ok(reg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_addr(&self, addr: Addr) -> Result<()> {
|
||||
if addr > self.mem.as_ref().len() {
|
||||
Err(VmError::MemOutOfBounds { addr })
|
||||
impl<T> MemCursor<T>
|
||||
where T: AsRef<[u8]>
|
||||
{
|
||||
fn check_addr(&self, addr: u64) -> Result<()> {
|
||||
if addr > (self.cursor.get_ref().as_ref().len() as u64) {
|
||||
Err(VmError::MemOutOfBounds { addr: Addr(addr) })
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MemCursor<T>
|
||||
where Cursor<T>: WriteBytesExt,
|
||||
T: AsRef<[u8]>
|
||||
{
|
||||
pub fn write_u8_unchecked(&mut self, value: u8) {
|
||||
self.cursor.write_u8(value).unwrap();
|
||||
}
|
||||
|
||||
pub fn write_u8(&mut self, value: u8) -> Result<()> {
|
||||
self.check_addr(self.position())
|
||||
.map(|_| self.write_u8_unchecked(value))
|
||||
}
|
||||
|
||||
pub fn write_u16_unchecked(&mut self, value: u16) {
|
||||
self.cursor.write_u16::<LE>(value).unwrap();
|
||||
}
|
||||
|
||||
pub fn write_u16(&mut self, value: u16) -> Result<()> {
|
||||
self.check_addr(self.position())
|
||||
.map(|_| self.write_u16_unchecked(value))
|
||||
}
|
||||
|
||||
pub fn write_u32_unchecked(&mut self, value: u32) {
|
||||
self.cursor.write_u32::<LE>(value).unwrap();
|
||||
}
|
||||
|
||||
pub fn write_u32(&mut self, value: u32) -> Result<()> {
|
||||
self.check_addr(self.position())
|
||||
.map(|_| self.write_u32_unchecked(value))
|
||||
}
|
||||
|
||||
pub fn write_u64_unchecked(&mut self, value: u64) {
|
||||
self.cursor.write_u64::<LE>(value).unwrap();
|
||||
}
|
||||
|
||||
pub fn write_u64(&mut self, value: u64) -> Result<()> {
|
||||
self.check_addr(self.position())
|
||||
.map(|_| self.write_u64_unchecked(value))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Index impl
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -217,3 +255,4 @@ impl<T: AsRef<[u8]>> Index<Addr> for MemCursor<T> {
|
||||
self.index(addr.0)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user