diff --git a/src/main.rs b/src/main.rs index 8912464..5e0d957 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,4 +9,5 @@ fn main() { let mut vm = VM::new(); vm.read_program(&"programs/hello-world.obj".to_string()); + vm.execute(); } diff --git a/src/vm/instruction.rs b/src/vm/instruction.rs index 5d36b3f..316dc5a 100644 --- a/src/vm/instruction.rs +++ b/src/vm/instruction.rs @@ -2,7 +2,9 @@ ////// instruction execution ////////////////////////////// -enum OpCodes { +use crate::vm::VM; + +enum OpCode { // branch BR = 0, // add @@ -35,6 +37,56 @@ enum OpCodes { LEA, // trap TRAP, + // no-operation (not a real opcode) + NOOP, } +fn get_opcode(instruction: u16) -> OpCode { + // the opcode is stored in the left 4 bits + match instruction >> 12 { + 0 => OpCode::BR, + 1 => OpCode::ADD, + 2 => OpCode::LD, + 3 => OpCode::ST, + 4 => OpCode::JSR, + 5 => OpCode::AND, + 6 => OpCode::LDR, + 7 => OpCode::STR, + 8 => OpCode::RTI, + 9 => OpCode::NOT, + 10 => OpCode::LDI, + 11 => OpCode::STI, + 12 => OpCode::JMP, + 13 => OpCode::RES, + 14 => OpCode::LEA, + 15 => OpCode::TRAP, + _ => OpCode::NOOP, + } +} +pub fn execute_instruction(vm: &mut VM) { + let instruction: u16 = vm.mem.get_mem(vm.registers.pc); + let opcode = get_opcode(instruction); + + match opcode { + OpCode::BR => no_op(vm), + OpCode::ADD => no_op(vm), + OpCode::LD => no_op(vm), + OpCode::ST => no_op(vm), + OpCode::JSR => no_op(vm), + OpCode::AND => no_op(vm), + OpCode::LDR => no_op(vm), + OpCode::STR => no_op(vm), + OpCode::RTI => no_op(vm), + OpCode::NOT => no_op(vm), + OpCode::LDI => no_op(vm), + OpCode::STI => no_op(vm), + OpCode::JMP => no_op(vm), + OpCode::RES => no_op(vm), + OpCode::LEA => no_op(vm), + OpCode::TRAP => no_op(vm), + OpCode::NOOP => no_op(vm), + } +} + +fn no_op(vm: &mut VM) {} diff --git a/src/vm/mod.rs b/src/vm/mod.rs index d84aed8..f0a0c3a 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -10,6 +10,7 @@ use byteorder::{BigEndian, ReadBytesExt}; use std::{fs::File, io::BufReader}; + mod instruction; //////////////// @@ -59,6 +60,7 @@ impl Registers { } } + /// Map an integer index to its register fn register_reference(&mut self, idx: u16) -> &mut u16 { match idx { 0 => &mut self.r0, @@ -75,11 +77,11 @@ impl Registers { } } - pub fn set_reg(&mut self, idx: u16, val: u16) { + fn set_reg(&mut self, idx: u16, val: u16) { *self.register_reference(idx) = val; } - pub fn get_reg(&mut self, idx: u16) -> u16 { + fn get_reg(&mut self, idx: u16) -> u16 { let reg = &*self.register_reference(idx); *reg } @@ -97,7 +99,7 @@ impl Registers { } } - pub fn set_reg_with_cond(&mut self, idx: u16, val: u16) { + fn set_reg_with_cond(&mut self, idx: u16, val: u16) { self.set_reg(idx, val); self.set_cond(idx); } @@ -120,11 +122,11 @@ impl Memory { } } - pub fn set_mem(&mut self, addr: u16, val: u16) { + fn set_mem(&mut self, addr: u16, val: u16) { self.data[addr as usize] = val; } - pub fn get_mem(&self, addr: u16) -> u16 { + fn get_mem(&self, addr: u16) -> u16 { return self.data[addr as usize]; } } @@ -185,8 +187,17 @@ impl VM { } pub fn execute(&mut self) { - loop { - self.registers.pc += 1; + let mut running: bool = true; + + while running { + instruction::execute_instruction(self); + + // disallow reading past memory bounds + if self.registers.pc as usize == MEM_SIZE - 1 { + running = false + } else { + self.registers.pc += 1; + } } } }