From 223ce4c1bd44296461b577c3debb442c2f1ae592 Mon Sep 17 00:00:00 2001 From: Anthony Foxclaw <35226681+tonytins@users.noreply.github.com> Date: Thu, 6 Feb 2020 17:40:43 -0500 Subject: [PATCH] Finished LOAD, ADD, HUL and DIV implementation --- src/instruction.rs | 18 ++++++---- src/lib.rs | 2 +- src/main.rs | 2 -- src/vm.rs | 82 ++++++++++++++++++++++++++++++---------------- 4 files changed, 66 insertions(+), 38 deletions(-) diff --git a/src/instruction.rs b/src/instruction.rs index e0a50f5..410cd81 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -1,3 +1,5 @@ +use crate::instruction::Opcode::LOAD; + #[derive(Debug, PartialEq)] pub enum Opcode { HLT, @@ -5,28 +7,30 @@ pub enum Opcode { LOAD, ADD, MUL, - DIV + DIV, } impl From for Opcode { fn from(vm: u8) -> Self { match vm { 0 => Opcode::HLT, - _ => Opcode::IGL + 1 => Opcode::LOAD, + 2 => Opcode::ADD, + 3 => Opcode::MUL, + 4 => Opcode::DIV + _ => Opcode::IGL, } } } #[derive(Debug, PartialEq)] pub struct Instruction { - opcode: Opcode + opcode: Opcode, } impl Instruction { pub fn new(opcode: Opcode) -> Self { - Instruction { - opcode - } + Instruction { opcode } } } @@ -45,4 +49,4 @@ mod instruction_tests { let inst = Instruction::new(Opcode::HLT); assert_eq!(inst.opcode, Opcode::HLT); } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 8594427..0ff6fdb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,2 @@ +mod instruction; mod vm; -mod instruction; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ed1ffda..e7a11a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,3 @@ - - fn main() { println!("Hello, world!"); } diff --git a/src/vm.rs b/src/vm.rs index 1420b2c..867ad5c 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -3,7 +3,8 @@ use crate::instruction::Opcode; pub struct VM { registers: [i32; 32], pc: usize, - program: Vec + program: Vec, + remainder: u32, } impl VM { @@ -11,7 +12,8 @@ impl VM { VM { registers: [0; 32], pc: 0, - program: vec![] + program: vec![], + remainder: 0, } } @@ -28,36 +30,57 @@ impl VM { } fn next_16_bits(&mut self) -> u16 { - let result = ((self.program[self.pc] as u16) << 8) | self.program[self.pc + 1] as u16; self.pc += 2; result } pub fn run(&mut self) { - loop { - if self.pc >= self.program.len() { - break; + let mut is_done = false; + while !is_done { + is_done = self.execute_instruction() + } + } + + pub fn run_once(&mut self) { + self.execute_instruction(); + } + + fn execute_instruction(&mut self) -> bool { + if self.pc >= self.program.len() { + return false; + } + match self.decode_opcode() { + Opcode::LOAD => { + let reg = self.next_8_bits() as usize; + let num = self.next_16_bits() as u32; + self.registers[reg] = num as i32; } - match self.decode_opcode() { - Opcode::LOAD => { - let reg = self.next_8_bits() as usize; - let num = self.next_16_bits() as u32; - self.registers[reg] = num as i32; - } - Opcode::HLT => { - println!("HLT encountered"); - return; - } - Opcode::IGL => { - println!("Unrecognized opcode found! Terminating!"); - return; - } - Opcode::ADD => {} - Opcode::MUL => {} - Opcode::DIV => {} + Opcode::HLT => { + println!("HLT encountered"); + return false; + } + Opcode::IGL => { + println!("Unrecognized opcode found! Terminating!"); + } + Opcode::ADD => { + let reg1 = self.registers[self.next_8_bits() as usize]; + let reg2 = self.registers[self.next_8_bits() as usize]; + self.registers[self.next_8_bits() as usize] = reg1 + reg2; + } + Opcode::MUL => { + let reg1 = self.registers[self.next_8_bits() as usize]; + let reg2 = self.registers[self.next_8_bits() as usize]; + self.registers[self.next_8_bits() as usize] = reg1 * reg2; + } + Opcode::DIV => { + let reg1 = self.registers[self.next_8_bits() as usize]; + let reg2 = self.registers[self.next_8_bits() as usize]; + self.registers[self.next_8_bits() as usize] = reg1 / reg2; + self.remainder = (reg1 % reg2) as u32; } } + true } } @@ -74,18 +97,21 @@ mod vm_tests { #[test] fn test_opcode_hlt() { let mut test_vm = VM::new(); - let test_bytes = vec![0,0,0,0]; + let test_bytes = vec![0, 0, 0, 0]; test_vm.program = test_bytes; - test_vm.run(); + test_vm.run_once(); assert_eq!(test_vm.pc, 1); } #[test] fn test_opcode_igl() { let mut test_vm = VM::new(); - let test_bytes = vec![200,0,0,0]; + let test_bytes = vec![200, 0, 0, 0]; test_vm.program = test_bytes; - test_vm.run(); + test_vm.run_once(); assert_eq!(test_vm.pc, 1); } -} \ No newline at end of file + + #[test] + fn test_load_opcode() {} +}