Finished LOAD, ADD, HUL and DIV implementation
This commit is contained in:
parent
d1340fe9fc
commit
223ce4c1bd
4 changed files with 66 additions and 38 deletions
|
@ -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<u8> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
mod instruction;
|
||||
mod vm;
|
||||
mod instruction;
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
|
|
82
src/vm.rs
82
src/vm.rs
|
@ -3,7 +3,8 @@ use crate::instruction::Opcode;
|
|||
pub struct VM {
|
||||
registers: [i32; 32],
|
||||
pc: usize,
|
||||
program: Vec<u8>
|
||||
program: Vec<u8>,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_load_opcode() {}
|
||||
}
|
||||
|
|
Reference in a new issue