added some base operations to the VM
This commit is contained in:
parent
3188361158
commit
3695f409db
2 changed files with 123 additions and 12 deletions
|
@ -130,6 +130,10 @@ fn main() {
|
||||||
println!("Compiled output: {:?}", compiled);
|
println!("Compiled output: {:?}", compiled);
|
||||||
let mut vm = Machine::new();
|
let mut vm = Machine::new();
|
||||||
vm.load(compiled);
|
vm.load(compiled);
|
||||||
|
vm.run();
|
||||||
|
println!("Registers: {:?}", vm.registers);
|
||||||
|
println!("Program Counter: {}", vm.pc);
|
||||||
|
println!("Memory: {:?}", vm.memory);
|
||||||
/*let mut executor = Executor::new(ast, 100);
|
/*let mut executor = Executor::new(ast, 100);
|
||||||
executor.resume();
|
executor.resume();
|
||||||
println!("\nFinished!");
|
println!("\nFinished!");
|
||||||
|
|
|
@ -2,32 +2,40 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
const ASXVERSION: [u8; 3] = [0,1,0];
|
const ASXVERSION: [u8; 3] = [0,1,0];
|
||||||
|
|
||||||
enum VMMemory {
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum VMMemory {
|
||||||
String(VMMemoryString),
|
String(VMMemoryString),
|
||||||
Number(VMMemoryNumber),
|
Number(VMMemoryNumber),
|
||||||
Boolean(VMMemoryBoolean),
|
Boolean(VMMemoryBoolean),
|
||||||
Null,
|
Null(VMMemoryNull),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
struct VMMemoryString {
|
struct VMMemoryString {
|
||||||
value: String,
|
value: String,
|
||||||
variable_id: u32,
|
variable_id: u32,
|
||||||
}
|
}
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
struct VMMemoryNumber {
|
struct VMMemoryNumber {
|
||||||
value: i64,
|
value: i64,
|
||||||
variable_id: u32,
|
variable_id: u32,
|
||||||
}
|
}
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
struct VMMemoryBoolean {
|
struct VMMemoryBoolean {
|
||||||
value: bool,
|
value: bool,
|
||||||
variable_id: u32,
|
variable_id: u32,
|
||||||
}
|
}
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct VMMemoryNull {
|
||||||
|
variable_id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
struct DecompiledFile {
|
struct DecompiledFile {
|
||||||
name: String,
|
name: String,
|
||||||
functions: Vec<DecompiledFunction>,
|
functions: Vec<DecompiledFunction>,
|
||||||
}
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
struct DecompiledFunction {
|
struct DecompiledFunction {
|
||||||
name: String,
|
name: String,
|
||||||
body: Vec<DecompiledOperation>,
|
body: Vec<DecompiledOperation>,
|
||||||
|
@ -35,7 +43,7 @@ struct DecompiledFunction {
|
||||||
strings: HashMap<u32, String>,
|
strings: HashMap<u32, String>,
|
||||||
functions: HashMap<u32, u32>
|
functions: HashMap<u32, u32>
|
||||||
}
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
struct DecompiledOperation {
|
struct DecompiledOperation {
|
||||||
opcode: u8,
|
opcode: u8,
|
||||||
arg1: u8,
|
arg1: u8,
|
||||||
|
@ -44,17 +52,17 @@ struct DecompiledOperation {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Register {
|
pub struct Register {
|
||||||
id: u8,
|
id: u8,
|
||||||
pointer: usize
|
pointer: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Machine {
|
pub struct Machine {
|
||||||
memory: Vec<VMMemory>,
|
pub memory: Vec<VMMemory>,
|
||||||
files: Vec<DecompiledFile>,
|
pub files: Vec<DecompiledFile>,
|
||||||
stack: Vec<VMMemory>,
|
pub stack: Vec<VMMemory>,
|
||||||
registers: Vec<Register>,
|
pub registers: Vec<Register>,
|
||||||
pc: usize,
|
pub pc: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_be_num(input: &[u8]) -> usize {
|
fn read_be_num(input: &[u8]) -> usize {
|
||||||
|
@ -110,6 +118,45 @@ fn bin_to_snum(bin: String) -> i64 {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_file_by_name(files: &Vec<DecompiledFile>, name: &str) -> Option<DecompiledFile> {
|
||||||
|
for file in files {
|
||||||
|
if file.name == name {
|
||||||
|
return Some(file.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_function_by_name(file: &DecompiledFile, name: &str) -> Option<DecompiledFunction> {
|
||||||
|
for function in &file.functions {
|
||||||
|
if function.name == name {
|
||||||
|
return Some(function.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_register_by_id(registers: &Vec<Register>, id: u8) -> Option<&Register> {
|
||||||
|
for reg in registers {
|
||||||
|
if reg.id == id {
|
||||||
|
return Some(reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_register(registers: &mut Vec<Register>, new_register: Register) {
|
||||||
|
if new_register.id == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i, reg) in registers.iter().enumerate() {
|
||||||
|
if reg.id == new_register.id {
|
||||||
|
registers[i] = new_register;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut registers = Vec::new();
|
let mut registers = Vec::new();
|
||||||
|
@ -120,7 +167,9 @@ impl Machine {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return Machine {
|
return Machine {
|
||||||
memory: Vec::new(),
|
memory: vec![
|
||||||
|
VMMemory::Null(VMMemoryNull { variable_id: 0 })
|
||||||
|
],
|
||||||
files: Vec::new(),
|
files: Vec::new(),
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
registers: registers,
|
registers: registers,
|
||||||
|
@ -202,4 +251,62 @@ impl Machine {
|
||||||
});
|
});
|
||||||
println!("Decompiled: {:?}", self.files[0]);
|
println!("Decompiled: {:?}", self.files[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self) {
|
||||||
|
let main = get_file_by_name(&self.files, "main.asl");
|
||||||
|
if main.is_none() {
|
||||||
|
panic!("Main file not found");
|
||||||
|
}
|
||||||
|
let main_func = get_function_by_name(&main.unwrap(), "main");
|
||||||
|
if main_func.is_none() {
|
||||||
|
panic!("Main function not found");
|
||||||
|
}
|
||||||
|
let main_func = main_func.unwrap();
|
||||||
|
while self.pc < main_func.body.len() {
|
||||||
|
let operation = &main_func.body[self.pc];
|
||||||
|
self.pc += 1;
|
||||||
|
match operation.opcode {
|
||||||
|
0 => {
|
||||||
|
//HLT
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
3 => {
|
||||||
|
//LDI
|
||||||
|
self.memory.push(VMMemory::Number(VMMemoryNumber { value: operation.arg2, variable_id: 0 }));
|
||||||
|
set_register(&mut self.registers, Register { id: operation.arg1, pointer: self.memory.len() - 1 });
|
||||||
|
},
|
||||||
|
7 => {
|
||||||
|
//ASS
|
||||||
|
let reg = get_register_by_id(&self.registers, operation.arg1);
|
||||||
|
if reg.is_none() {
|
||||||
|
panic!("Register {} not found", operation.arg1);
|
||||||
|
}
|
||||||
|
let reg = reg.unwrap();
|
||||||
|
if reg.pointer >= self.memory.len() || reg.pointer < 1 {
|
||||||
|
panic!("Register {} points to an invalid memory location", operation.arg1);
|
||||||
|
}
|
||||||
|
match &mut self.memory[reg.pointer] {
|
||||||
|
VMMemory::Number(num) => {
|
||||||
|
num.variable_id = operation.arg2 as u32;
|
||||||
|
},
|
||||||
|
VMMemory::String(str) => {
|
||||||
|
str.variable_id = operation.arg2 as u32;
|
||||||
|
},
|
||||||
|
VMMemory::Boolean(bool) => {
|
||||||
|
bool.variable_id = operation.arg2 as u32;
|
||||||
|
},
|
||||||
|
VMMemory::Null(null) => {
|
||||||
|
null.variable_id = operation.arg2 as u32;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
29 => {
|
||||||
|
//RET
|
||||||
|
//not implemented yet
|
||||||
|
},
|
||||||
|
_ => panic!("Unknown opcode: {}", main_func.body[self.pc].opcode),
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue