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:
127
src/vm/tick.rs
Normal file
127
src/vm/tick.rs
Normal file
@@ -0,0 +1,127 @@
|
||||
use crate::vm::{error::*, flags::Flags, inst::*, reg::*, vm::*};
|
||||
|
||||
impl Vm {
|
||||
pub fn tick(&mut self) -> Result<()> {
|
||||
let mut cursor = self.mem_cursor(self.ip() as usize);
|
||||
let op = cursor.next_u16()?;
|
||||
let next_ip;
|
||||
|
||||
macro_rules! math_inst {
|
||||
($mapping:expr) => {{
|
||||
let (r1, r2) = cursor.next_regs()?;
|
||||
next_ip = cursor.position();
|
||||
let value = ($mapping)(self.get_reg(r1), self.get_reg(r2));
|
||||
self.set_reg(r1, value);
|
||||
}}
|
||||
}
|
||||
match op {
|
||||
ADD => math_inst!(|w1: u64, w2: u64| w1.wrapping_add(w2)),
|
||||
MUL => math_inst!(|w1: u64, w2: u64| w1.wrapping_mul(w2)),
|
||||
DIV => math_inst!(|w1: u64, w2: u64| w1.wrapping_div(w2)),
|
||||
MOD => math_inst!(|w1: u64, w2: u64| w1 % w2),
|
||||
INEG => { todo!() }
|
||||
AND => math_inst!(|w1: u64, w2: u64| w1 & w2),
|
||||
OR => math_inst!(|w1: u64, w2: u64| w1 | w2),
|
||||
INV => {
|
||||
let r1 = cursor.next_reg()?;
|
||||
next_ip = cursor.position();
|
||||
let value = self.get_reg(r1);
|
||||
self.set_reg(r1, !value);
|
||||
}
|
||||
NOT => {
|
||||
let r1 = cursor.next_reg()?;
|
||||
next_ip = cursor.position();
|
||||
let value = self.get_reg(r1);
|
||||
self.set_reg(r1, (value == 0) as Word);
|
||||
}
|
||||
XOR => math_inst!(|w1: u64, w2: u64| w1 ^ w2),
|
||||
SHL => math_inst!(|w1: u64, w2: u64| w1 << w2),
|
||||
SHR => math_inst!(|w1: u64, w2: u64| w1 >> w2),
|
||||
CMPEQ => {
|
||||
let (r1, r2) = cursor.next_regs()?;
|
||||
next_ip = cursor.position();
|
||||
let cmp = self.get_reg(r1) == self.get_reg(r2);
|
||||
if cmp {
|
||||
self.insert_flags(Flags::COMPARE);
|
||||
} else {
|
||||
self.remove_flags(Flags::COMPARE);
|
||||
}
|
||||
}
|
||||
CMPLT => {
|
||||
let (r1, r2) = cursor.next_regs()?;
|
||||
next_ip = cursor.position();
|
||||
let cmp = self.get_reg(r1) < self.get_reg(r2);
|
||||
if cmp {
|
||||
self.insert_flags(Flags::COMPARE);
|
||||
} else {
|
||||
self.remove_flags(Flags::COMPARE);
|
||||
}
|
||||
}
|
||||
JMP => {
|
||||
let r1 = cursor.next_reg()?;
|
||||
next_ip = self.get_reg(r1);
|
||||
}
|
||||
JZ => {
|
||||
let r1 = cursor.next_reg()?;
|
||||
if !self.flags().contains(Flags::COMPARE) {
|
||||
next_ip = self.get_reg(r1);
|
||||
} else {
|
||||
next_ip = cursor.position();
|
||||
}
|
||||
}
|
||||
JNZ => {
|
||||
let r1 = cursor.next_reg()?;
|
||||
if self.flags().contains(Flags::COMPARE) {
|
||||
next_ip = self.get_reg(r1);
|
||||
} else {
|
||||
next_ip = cursor.position();
|
||||
}
|
||||
}
|
||||
LOAD => {
|
||||
let (r1, r2) = cursor.next_regs()?;
|
||||
next_ip = cursor.position();
|
||||
let value = self.load(r2);
|
||||
self.set_reg(r1, value);
|
||||
}
|
||||
REGCOPY => math_inst!(|_: u64, w2: u64| w2),
|
||||
STOREIMM64 => {
|
||||
let r1 = cursor.next_reg()?;
|
||||
// skip
|
||||
cursor.next_u32()?;
|
||||
let imm = cursor.next_u64()?;
|
||||
next_ip = cursor.position();
|
||||
self.set_reg(r1, imm);
|
||||
}
|
||||
STOREIMM32 => {
|
||||
let r1 = cursor.next_reg()?;
|
||||
let imm = cursor.next_u32()?;
|
||||
next_ip = cursor.position();
|
||||
self.set_reg(r1, imm as u64);
|
||||
}
|
||||
MEMCOPY => {
|
||||
let (r1, r2) = cursor.next_regs()?;
|
||||
next_ip = cursor.position();
|
||||
let value = self.load(r2);
|
||||
self.store(r1, value);
|
||||
}
|
||||
STORE => {
|
||||
let (r1, r2) = cursor.next_regs()?;
|
||||
next_ip = cursor.position();
|
||||
let value = self.get_reg(r1);
|
||||
self.store(r2, value);
|
||||
}
|
||||
HALT => {
|
||||
next_ip = cursor.position();
|
||||
self.insert_flags(Flags::HALT);
|
||||
}
|
||||
NOP => {
|
||||
next_ip = cursor.position();
|
||||
}
|
||||
_ => panic!("unknown instruction opcode: 0x{:04x}", op),
|
||||
}
|
||||
|
||||
self.set_reg(IP, next_ip);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user