implement fetch-execute loop

This commit is contained in:
dogeystamp 2024-01-05 22:17:21 -05:00
parent fb7b17a7fe
commit 60ad020d14
Signed by: dogeystamp
GPG Key ID: 7225FE3592EFFA38
3 changed files with 72 additions and 8 deletions

View File

@ -9,4 +9,5 @@ fn main() {
let mut vm = VM::new();
vm.read_program(&"programs/hello-world.obj".to_string());
vm.execute();
}

View File

@ -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) {}

View File

@ -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;
}
}
}
}