Add execution to VM via file, starting to iron out bugs
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
25
src/main.rs
25
src/main.rs
@@ -4,18 +4,21 @@ mod common;
|
|||||||
//mod syn;
|
//mod syn;
|
||||||
mod vm;
|
mod vm;
|
||||||
|
|
||||||
use std::{
|
use std::{convert::TryFrom, env, fs, io, process};
|
||||||
convert::TryFrom,
|
|
||||||
io::{self, Read},
|
|
||||||
process,
|
|
||||||
};
|
|
||||||
|
|
||||||
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
fn get_input_string() -> io::Result<String> {
|
fn get_input_string() -> io::Result<String> {
|
||||||
let mut buffer = String::new();
|
let args: Vec<String> = env::args().collect();
|
||||||
io::stdin().read_to_string(&mut buffer)?;
|
if args.len() <= 1 {
|
||||||
Ok(buffer)
|
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<()> {
|
fn main() -> Result<()> {
|
||||||
@@ -29,6 +32,10 @@ fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let obj = vm::obj::obj::Object::try_from(&ast)?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,15 @@ macro_rules! instructions {
|
|||||||
$(
|
$(
|
||||||
pub const $variant: InstOp = $value;
|
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;
|
pub type InstOp = u16;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::vm::{error::*, flags::Flags, inst::*, reg::*, vm::*};
|
use crate::vm::{error::*, flags::Flags, inst::*, reg::*, vm::*};
|
||||||
|
use std::io::stdin;
|
||||||
|
|
||||||
impl Vm {
|
impl Vm {
|
||||||
pub fn tick(&mut self) -> Result<()> {
|
pub fn tick(&mut self) -> Result<()> {
|
||||||
@@ -120,6 +121,12 @@ impl Vm {
|
|||||||
_ => panic!("unknown instruction opcode: 0x{:04x}", op),
|
_ => 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);
|
self.set_reg(IP, next_ip);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
63
src/vm/vm.rs
63
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 byteorder::{WriteBytesExt, LE};
|
||||||
use std::{io::Cursor, mem};
|
use std::{io::Cursor, mem};
|
||||||
|
|
||||||
@@ -13,12 +13,67 @@ pub struct Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Vm {
|
impl Vm {
|
||||||
pub fn new(mem: Vec<u8>, registers: Registers) -> Self {
|
pub fn new() -> Self {
|
||||||
Vm { mem, registers }
|
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 {
|
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<u64> {
|
pub fn run(&mut self) -> Result<u64> {
|
||||||
|
|||||||
5
test.asm
5
test.asm
@@ -13,9 +13,9 @@ code $0x0 {
|
|||||||
|
|
||||||
storeimm %r01, $0xDEADBEEF
|
storeimm %r01, $0xDEADBEEF
|
||||||
|
|
||||||
|
cmpeq %r00, %r01
|
||||||
storeimm %r00, failure
|
storeimm %r00, failure
|
||||||
storeimm %r01, ok
|
storeimm %r01, ok
|
||||||
cmpeq %r00, %r01
|
|
||||||
|
|
||||||
jz %r00
|
jz %r00
|
||||||
|
|
||||||
@@ -23,9 +23,8 @@ code $0x0 {
|
|||||||
|
|
||||||
failure:
|
failure:
|
||||||
storeimm %status, $1
|
storeimm %status, $1
|
||||||
halt
|
|
||||||
|
|
||||||
ok:
|
ok: halt
|
||||||
|
|
||||||
.export main
|
.export main
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user