diff --git a/src/main.rs b/src/main.rs index 9cf7426..3d8e21a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,18 +4,21 @@ mod common; //mod syn; mod vm; -use std::{ - convert::TryFrom, - io::{self, Read}, - process, -}; +use std::{convert::TryFrom, env, fs, io, process}; type Result = std::result::Result>; fn get_input_string() -> io::Result { - let mut buffer = String::new(); - io::stdin().read_to_string(&mut buffer)?; - Ok(buffer) + let args: Vec = env::args().collect(); + if args.len() <= 1 { + println!( + "usage: {} file.asm", + args.get(0).map(String::as_str).unwrap_or("rasp") + ); + process::exit(1); + } else { + fs::read_to_string(&args[1]) + } } fn main() -> Result<()> { @@ -29,6 +32,10 @@ fn main() -> Result<()> { } }; let obj = vm::obj::obj::Object::try_from(&ast)?; - println!("{:#?}", obj); + //println!("{:#?}", obj); + let mut vm = vm::vm::Vm::new(); + vm.load_object(obj, 1024 * 1024 * 64)?; // 64mb + let status = vm.run()?; + println!("status: {}", status); Ok(()) } diff --git a/src/vm/inst.rs b/src/vm/inst.rs index b91cc2b..9c2a33e 100644 --- a/src/vm/inst.rs +++ b/src/vm/inst.rs @@ -6,6 +6,15 @@ macro_rules! instructions { $( pub const $variant: InstOp = $value; )* + + pub fn inst_name(op: InstOp) -> Option<&'static str> { + match op { + $( + $value => Some(stringify!($variant)), + )* + _ => None, + } + } }; } pub type InstOp = u16; diff --git a/src/vm/tick.rs b/src/vm/tick.rs index 4a2dd0b..5d00d08 100644 --- a/src/vm/tick.rs +++ b/src/vm/tick.rs @@ -1,4 +1,5 @@ use crate::vm::{error::*, flags::Flags, inst::*, reg::*, vm::*}; +use std::io::stdin; impl Vm { pub fn tick(&mut self) -> Result<()> { @@ -120,6 +121,12 @@ impl Vm { _ => panic!("unknown instruction opcode: 0x{:04x}", op), } + println!("op: {:04x} {}", op, inst_name(op).unwrap()); + println!("ip: {:05x}", self.ip()); + println!("next_ip: {:05x}", next_ip); + let mut _line = String::new(); + stdin().read_line(&mut _line).unwrap(); + self.set_reg(IP, next_ip); Ok(()) diff --git a/src/vm/vm.rs b/src/vm/vm.rs index 53ab09b..e2e28b7 100644 --- a/src/vm/vm.rs +++ b/src/vm/vm.rs @@ -1,4 +1,4 @@ -use crate::vm::{error::*, flags::*, mem::*, reg::*}; +use crate::vm::{error::*, flags::*, mem::*, obj::obj::*, reg::*}; use byteorder::{WriteBytesExt, LE}; use std::{io::Cursor, mem}; @@ -13,12 +13,67 @@ pub struct Vm { } impl Vm { - pub fn new(mem: Vec, registers: Registers) -> Self { - Vm { mem, registers } + pub fn new() -> Self { + Vm { + mem: Default::default(), + registers: [0; 64], + } + } + + /// Loads an object into this VM, clearing out all previous memory and resetting the registers. + pub fn load_object(&mut self, object: Object, max_mem: usize) -> Result<()> { + self.registers = [0; 64]; + // determine memory spread + let mem_size = object + .sections + .iter() + .filter_map(|s| match s { + Section::Data { end, .. } | Section::Code { end, .. } => Some(*end), + Section::Meta { .. } => None, + }) + .max() + .unwrap_or(0); + if mem_size > (max_mem as u64) { + todo!("raise max memory error"); + } + self.mem = vec![0; mem_size as usize]; + + let mut entry = 0; + // write sections to memory + for section in object.sections.into_iter() { + match section { + Section::Data { + start, + contents, + .. + } + | Section::Code { + start, + contents, + .. + } => { + let start = start as usize; + for (value, dest) in contents.into_iter().zip(&mut self.mem[start..]) + { + *dest = value; + } + } + Section::Meta { entries } => { + if let Some(e) = entries.get("entry") { + // set the entry point + entry = *e; + } + } + } + } + self.set_reg(IP, entry); + Ok(()) } pub fn mem_cursor(&self, at: usize) -> MemCursor { - MemCursor::new(&self.mem[at..]) + let mut cursor = MemCursor::new(&self.mem); + cursor.set_position(at as u64); + cursor } pub fn run(&mut self) -> Result { diff --git a/test.asm b/test.asm index 31a40c8..87b1d44 100644 --- a/test.asm +++ b/test.asm @@ -13,9 +13,9 @@ code $0x0 { storeimm %r01, $0xDEADBEEF + cmpeq %r00, %r01 storeimm %r00, failure storeimm %r01, ok - cmpeq %r00, %r01 jz %r00 @@ -23,9 +23,8 @@ code $0x0 { failure: storeimm %status, $1 - halt - ok: + ok: halt .export main }