Finished LOAD, ADD, HUL and DIV implementation

This commit is contained in:
Anthony Foxclaw 2020-02-06 17:40:43 -05:00
parent d1340fe9fc
commit 223ce4c1bd
4 changed files with 66 additions and 38 deletions

View file

@ -1,3 +1,5 @@
use crate::instruction::Opcode::LOAD;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum Opcode { pub enum Opcode {
HLT, HLT,
@ -5,28 +7,30 @@ pub enum Opcode {
LOAD, LOAD,
ADD, ADD,
MUL, MUL,
DIV DIV,
} }
impl From<u8> for Opcode { impl From<u8> for Opcode {
fn from(vm: u8) -> Self { fn from(vm: u8) -> Self {
match vm { match vm {
0 => Opcode::HLT, 0 => Opcode::HLT,
_ => Opcode::IGL 1 => Opcode::LOAD,
2 => Opcode::ADD,
3 => Opcode::MUL,
4 => Opcode::DIV
_ => Opcode::IGL,
} }
} }
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Instruction { pub struct Instruction {
opcode: Opcode opcode: Opcode,
} }
impl Instruction { impl Instruction {
pub fn new(opcode: Opcode) -> Self { pub fn new(opcode: Opcode) -> Self {
Instruction { Instruction { opcode }
opcode
}
} }
} }
@ -45,4 +49,4 @@ mod instruction_tests {
let inst = Instruction::new(Opcode::HLT); let inst = Instruction::new(Opcode::HLT);
assert_eq!(inst.opcode, Opcode::HLT); assert_eq!(inst.opcode, Opcode::HLT);
} }
} }

View file

@ -1,2 +1,2 @@
mod instruction;
mod vm; mod vm;
mod instruction;

View file

@ -1,5 +1,3 @@
fn main() { fn main() {
println!("Hello, world!"); println!("Hello, world!");
} }

View file

@ -3,7 +3,8 @@ use crate::instruction::Opcode;
pub struct VM { pub struct VM {
registers: [i32; 32], registers: [i32; 32],
pc: usize, pc: usize,
program: Vec<u8> program: Vec<u8>,
remainder: u32,
} }
impl VM { impl VM {
@ -11,7 +12,8 @@ impl VM {
VM { VM {
registers: [0; 32], registers: [0; 32],
pc: 0, pc: 0,
program: vec![] program: vec![],
remainder: 0,
} }
} }
@ -28,36 +30,57 @@ impl VM {
} }
fn next_16_bits(&mut self) -> u16 { fn next_16_bits(&mut self) -> u16 {
let result = ((self.program[self.pc] as u16) << 8) | self.program[self.pc + 1] as u16; let result = ((self.program[self.pc] as u16) << 8) | self.program[self.pc + 1] as u16;
self.pc += 2; self.pc += 2;
result result
} }
pub fn run(&mut self) { pub fn run(&mut self) {
loop { let mut is_done = false;
if self.pc >= self.program.len() { while !is_done {
break; 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::HLT => {
Opcode::LOAD => { println!("HLT encountered");
let reg = self.next_8_bits() as usize; return false;
let num = self.next_16_bits() as u32; }
self.registers[reg] = num as i32; Opcode::IGL => {
} println!("Unrecognized opcode found! Terminating!");
Opcode::HLT => { }
println!("HLT encountered"); Opcode::ADD => {
return; let reg1 = self.registers[self.next_8_bits() as usize];
} let reg2 = self.registers[self.next_8_bits() as usize];
Opcode::IGL => { self.registers[self.next_8_bits() as usize] = reg1 + reg2;
println!("Unrecognized opcode found! Terminating!"); }
return; Opcode::MUL => {
} let reg1 = self.registers[self.next_8_bits() as usize];
Opcode::ADD => {} let reg2 = self.registers[self.next_8_bits() as usize];
Opcode::MUL => {} self.registers[self.next_8_bits() as usize] = reg1 * reg2;
Opcode::DIV => {} }
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] #[test]
fn test_opcode_hlt() { fn test_opcode_hlt() {
let mut test_vm = VM::new(); 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.program = test_bytes;
test_vm.run(); test_vm.run_once();
assert_eq!(test_vm.pc, 1); assert_eq!(test_vm.pc, 1);
} }
#[test] #[test]
fn test_opcode_igl() { fn test_opcode_igl() {
let mut test_vm = VM::new(); 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.program = test_bytes;
test_vm.run(); test_vm.run_once();
assert_eq!(test_vm.pc, 1); assert_eq!(test_vm.pc, 1);
} }
}
#[test]
fn test_load_opcode() {}
}