2020-02-17 16:22:15 -05:00
|
|
|
use crate::vm::{addr::*, error::*, inst::*, reg::*};
|
2020-02-18 17:44:41 -05:00
|
|
|
use byteorder::{ReadBytesExt, WriteBytesExt, LE};
|
|
|
|
|
use std::io::Cursor;
|
2020-02-17 16:15:06 -05:00
|
|
|
|
|
|
|
|
pub struct MemCursor<T> {
|
2020-02-18 17:44:41 -05:00
|
|
|
cursor: Cursor<T>,
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
2020-02-17 16:15:06 -05:00
|
|
|
impl<T> MemCursor<T>
|
2020-02-18 17:44:41 -05:00
|
|
|
where Cursor<T>: ReadBytesExt,
|
|
|
|
|
T: AsRef<[u8]>
|
2020-02-17 16:15:06 -05:00
|
|
|
{
|
|
|
|
|
pub fn new(mem: T) -> Self {
|
2020-02-18 17:44:41 -05:00
|
|
|
MemCursor { cursor: Cursor::new(mem) }
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
2020-02-18 17:44:41 -05:00
|
|
|
pub fn position(&self) -> u64 {
|
|
|
|
|
self.cursor.position()
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
2020-02-17 16:15:06 -05:00
|
|
|
pub fn set_position<P: Into<Addr>>(&mut self, position: P) {
|
2020-02-18 17:44:41 -05:00
|
|
|
self.cursor.set_position((position.into()).0)
|
2020-02-17 16:15:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn next_u8_unchecked(&mut self) -> u8 {
|
2020-02-18 17:44:41 -05:00
|
|
|
self.cursor.read_u8().unwrap()
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn next_u8(&mut self) -> Result<u8> {
|
2020-02-18 17:44:41 -05:00
|
|
|
self.check_addr(self.position())
|
2020-02-17 16:15:06 -05:00
|
|
|
.map(|_| self.next_u8_unchecked())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn next_u16_unchecked(&mut self) -> u16 {
|
2020-02-18 17:44:41 -05:00
|
|
|
self.cursor.read_u16::<LE>().unwrap()
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn next_u16(&mut self) -> Result<u16> {
|
2020-02-18 17:44:41 -05:00
|
|
|
self.check_addr(self.position())
|
2020-02-17 16:15:06 -05:00
|
|
|
.map(|_| self.next_u16_unchecked())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn next_u32_unchecked(&mut self) -> u32 {
|
2020-02-18 17:44:41 -05:00
|
|
|
self.cursor.read_u32::<LE>().unwrap()
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn next_u32(&mut self) -> Result<u32> {
|
2020-02-18 17:44:41 -05:00
|
|
|
self.check_addr(self.position())
|
2020-02-17 16:15:06 -05:00
|
|
|
.map(|_| self.next_u32_unchecked())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn next_u64_unchecked(&mut self) -> u64 {
|
2020-02-18 17:44:41 -05:00
|
|
|
self.cursor.read_u64::<LE>().unwrap()
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn next_u64(&mut self) -> Result<u64> {
|
2020-02-18 17:44:41 -05:00
|
|
|
self.check_addr(self.position())
|
2020-02-17 16:15:06 -05:00
|
|
|
.map(|_| self.next_u64_unchecked())
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
2020-02-17 16:15:06 -05:00
|
|
|
pub fn next_addr(&mut self) -> Result<Addr> {
|
2020-02-18 17:44:41 -05:00
|
|
|
self.check_addr(self.position())
|
2020-02-17 16:15:06 -05:00
|
|
|
.map(|_| self.next_addr_unchecked())
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
2020-02-17 16:15:06 -05:00
|
|
|
pub fn next_addr_unchecked(&mut self) -> Addr {
|
|
|
|
|
Addr(self.next_u64_unchecked())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn next_inst(&mut self) -> Result<Inst> {
|
2020-02-18 17:44:41 -05:00
|
|
|
let start = self.position();
|
2020-02-17 16:15:06 -05:00
|
|
|
let op = self.next_u16()?;
|
|
|
|
|
|
|
|
|
|
macro_rules! dest_source {
|
|
|
|
|
($variant:ident) => {{
|
|
|
|
|
let (d, s) = self.next_dest_source()?;
|
|
|
|
|
Ok(Inst::$variant(d, s))
|
|
|
|
|
}};
|
|
|
|
|
}
|
|
|
|
|
macro_rules! source_source {
|
|
|
|
|
($variant:ident) => {{
|
|
|
|
|
let (s1, s2) = self.next_source_source()?;
|
|
|
|
|
Ok(Inst::$variant(s1, s2))
|
|
|
|
|
}};
|
|
|
|
|
}
|
|
|
|
|
macro_rules! source {
|
|
|
|
|
($variant:ident) => {{
|
|
|
|
|
let spec = (self.next_u8()? & 0xF0) >> 4;
|
|
|
|
|
let source = self.next_source(spec)?;
|
|
|
|
|
Ok(Inst::$variant(source))
|
|
|
|
|
}};
|
|
|
|
|
}
|
2020-02-26 10:14:48 -05:00
|
|
|
macro_rules! dest {
|
|
|
|
|
($variant:ident) => {{
|
|
|
|
|
let spec = (self.next_u8()? & 0xF0) >> 4;
|
|
|
|
|
let dest = self.next_dest(spec)?;
|
|
|
|
|
Ok(Inst::$variant(dest))
|
|
|
|
|
}};
|
|
|
|
|
}
|
2020-02-18 17:44:41 -05:00
|
|
|
let inst = match op {
|
2020-02-17 16:15:06 -05:00
|
|
|
ADD => dest_source!(Add),
|
|
|
|
|
SUB => dest_source!(Sub),
|
|
|
|
|
MUL => dest_source!(Mul),
|
|
|
|
|
DIV => dest_source!(Div),
|
2020-02-25 13:44:03 -05:00
|
|
|
IDIV => dest_source!(IDiv),
|
2020-02-17 16:15:06 -05:00
|
|
|
MOD => dest_source!(Mod),
|
|
|
|
|
AND => dest_source!(And),
|
|
|
|
|
OR => dest_source!(Or),
|
|
|
|
|
XOR => dest_source!(Xor),
|
|
|
|
|
SHL => dest_source!(Shl),
|
|
|
|
|
SHR => dest_source!(Shr),
|
|
|
|
|
INEG => dest_source!(INeg),
|
|
|
|
|
INV => dest_source!(Inv),
|
|
|
|
|
NOT => dest_source!(Not),
|
|
|
|
|
CMPEQ => source_source!(CmpEq),
|
|
|
|
|
CMPLT => source_source!(CmpLt),
|
|
|
|
|
JMP => source!(Jmp),
|
|
|
|
|
JZ => source!(Jz),
|
|
|
|
|
JNZ => source!(Jnz),
|
2020-02-26 10:14:48 -05:00
|
|
|
CALL => source!(Call),
|
|
|
|
|
RET => Ok(Inst::Ret),
|
|
|
|
|
PUSH => source!(Push),
|
|
|
|
|
POP => dest!(Pop),
|
2020-02-17 16:15:06 -05:00
|
|
|
MOV => dest_source!(Mov),
|
|
|
|
|
HALT => Ok(Inst::Halt),
|
|
|
|
|
NOP => Ok(Inst::Nop),
|
|
|
|
|
DUMP => Ok(Inst::Dump),
|
|
|
|
|
_ => Err(VmError::IllegalOp { op }),
|
2020-02-18 17:44:41 -05:00
|
|
|
}?;
|
|
|
|
|
let end = self.position();
|
|
|
|
|
let len = (end - start) as usize;
|
|
|
|
|
assert_eq!(len, inst.len());
|
|
|
|
|
Ok(inst)
|
2020-02-17 16:15:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn next_source_source(&mut self) -> Result<(Source, Source)> {
|
|
|
|
|
let spec = self.next_u8()?;
|
|
|
|
|
let s1_spec = (spec & 0xF0) >> 4;
|
|
|
|
|
let s2_spec = spec & 0x0F;
|
|
|
|
|
let s1 = self.next_source(s1_spec)?;
|
|
|
|
|
let s2 = self.next_source(s2_spec)?;
|
|
|
|
|
Ok((s1, s2))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn next_dest_source(&mut self) -> Result<(Dest, Source)> {
|
|
|
|
|
let spec = self.next_u8()?;
|
|
|
|
|
let dest_spec = (spec & 0xF0) >> 4;
|
|
|
|
|
let source_spec = spec & 0x0F;
|
|
|
|
|
let dest = self.next_dest(dest_spec)?;
|
|
|
|
|
let source = self.next_source(source_spec)?;
|
|
|
|
|
Ok((dest, source))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn next_dest(&mut self, spec: u8) -> Result<Dest> {
|
|
|
|
|
match spec {
|
|
|
|
|
DEST_ADDR64 => Ok(Dest::Addr64(self.next_addr()?)),
|
|
|
|
|
DEST_ADDR32 => Ok(Dest::Addr32(self.next_addr()?)),
|
|
|
|
|
DEST_ADDR16 => Ok(Dest::Addr16(self.next_addr()?)),
|
|
|
|
|
DEST_ADDR8 => Ok(Dest::Addr8(self.next_addr()?)),
|
2020-02-25 12:07:24 -05:00
|
|
|
DEST_REG_ADDR64 => Ok(Dest::RegAddr64(self.next_reg()?)),
|
|
|
|
|
DEST_REG_ADDR32 => Ok(Dest::RegAddr32(self.next_reg()?)),
|
|
|
|
|
DEST_REG_ADDR16 => Ok(Dest::RegAddr16(self.next_reg()?)),
|
|
|
|
|
DEST_REG_ADDR8 => Ok(Dest::RegAddr8(self.next_reg()?)),
|
2020-02-17 16:15:06 -05:00
|
|
|
DEST_REG => Ok(Dest::Reg(self.next_reg()?)),
|
|
|
|
|
_ => Err(VmError::IllegalDestSpec { spec }),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn next_source(&mut self, spec: u8) -> Result<Source> {
|
|
|
|
|
match spec {
|
|
|
|
|
SOURCE_ADDR64 => Ok(Source::Addr64(self.next_addr()?)),
|
|
|
|
|
SOURCE_ADDR32 => Ok(Source::Addr32(self.next_addr()?)),
|
|
|
|
|
SOURCE_ADDR16 => Ok(Source::Addr16(self.next_addr()?)),
|
|
|
|
|
SOURCE_ADDR8 => Ok(Source::Addr8(self.next_addr()?)),
|
2020-02-25 12:07:24 -05:00
|
|
|
SOURCE_REG_ADDR64 => Ok(Source::RegAddr64(self.next_reg()?)),
|
|
|
|
|
SOURCE_REG_ADDR32 => Ok(Source::RegAddr32(self.next_reg()?)),
|
|
|
|
|
SOURCE_REG_ADDR16 => Ok(Source::RegAddr16(self.next_reg()?)),
|
|
|
|
|
SOURCE_REG_ADDR8 => Ok(Source::RegAddr8(self.next_reg()?)),
|
2020-02-17 16:15:06 -05:00
|
|
|
SOURCE_REG => Ok(Source::Reg(self.next_reg()?)),
|
|
|
|
|
SOURCE_IMM64 => Ok(Source::Imm(self.next_u64()?)),
|
|
|
|
|
SOURCE_IMM32 => Ok(Source::Imm(self.next_u32()? as u64)),
|
|
|
|
|
SOURCE_IMM16 => Ok(Source::Imm(self.next_u16()? as u64)),
|
|
|
|
|
SOURCE_IMM8 => Ok(Source::Imm(self.next_u8()? as u64)),
|
|
|
|
|
_ => Err(VmError::IllegalSourceSpec { spec }),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn next_reg(&mut self) -> Result<Reg> {
|
|
|
|
|
let reg = self.next_u8()?;
|
|
|
|
|
if (reg as usize) >= NUM_REGS {
|
|
|
|
|
Err(VmError::IllegalReg { reg })
|
|
|
|
|
} else {
|
|
|
|
|
Ok(reg)
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-18 17:44:41 -05:00
|
|
|
}
|
2020-02-17 16:15:06 -05:00
|
|
|
|
2020-02-18 17:44:41 -05:00
|
|
|
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) })
|
2020-02-17 16:15:06 -05:00
|
|
|
} else {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-18 17:44:41 -05:00
|
|
|
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))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-02-17 16:15:06 -05:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Index impl
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
impl<T: AsRef<[u8]>> Index<usize> for MemCursor<T> {
|
|
|
|
|
type Output = u8;
|
2020-02-03 17:56:32 -05:00
|
|
|
|
2020-02-17 16:15:06 -05:00
|
|
|
fn index(&self, addr: usize) -> &Self::Output {
|
|
|
|
|
self.mem.as_ref().index(addr)
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-17 16:15:06 -05:00
|
|
|
impl<T: AsRef<[u8]>> Index<u64> for MemCursor<T> {
|
|
|
|
|
type Output = u8;
|
|
|
|
|
|
|
|
|
|
fn index(&self, addr: u64) -> &Self::Output {
|
|
|
|
|
self.index(addr as usize)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: AsRef<[u8]>> Index<Addr> for MemCursor<T> {
|
|
|
|
|
type Output = u8;
|
|
|
|
|
|
|
|
|
|
fn index(&self, addr: Addr) -> &Self::Output {
|
|
|
|
|
self.index(addr.0)
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
|
|
|
|
}
|
2020-02-18 17:44:41 -05:00
|
|
|
*/
|