From 853188b01068ee93c8a6a107dfa57111ef079244 Mon Sep 17 00:00:00 2001 From: Anthony Foxclaw <35226681+tonytins@users.noreply.github.com> Date: Sat, 8 Feb 2020 15:14:37 -0500 Subject: [PATCH] Fixed bug with VM assigning wrong opcode - Fixed a bug with VM assigning wrong opcode. After doing a little digging into the Iridium 1 source code (skipping to the next part of the tutorial), I discovered I had to have implement from() function in both directions. I.e. the Opcode outputs integer and integer outputs an Opcode. Derp moment in retrospective since I already had it done for the former but this is a learning experience. - Moved Opcode enum to assembler module. --- README.md | 2 +- docs/README.md | 2 +- docs/spec.md | 2 +- src/assembler.rs | 84 ++++++++++++++++++++++++++++- src/assembler/instruction_parser.rs | 5 +- src/assembler/opcode_parser.rs | 3 +- src/instruction.rs | 58 +------------------- src/vm.rs | 2 +- 8 files changed, 92 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index e6b7fab..347b4f3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Corten -Corten is a stack-based virtual machine written in Rust as a hobby. It's based on the [Iridium 1](docs/spec.md#Iridium) architecture from Fletcher Haynes's [So you want to build a language VM](https://blog.subnetzero.io/post/building-language-vm-part-01/). +Corten is a Corten [MIPS64 Release 6](https://en.wikipedia.org/wiki/MIPS_architecture#MIPS32/MIPS64_Release_6) virtual machine written in Rust as a hobby based on Fletcher Haynes's [So you want to build a language VM](https://blog.subnetzero.io/post/building-language-vm-part-01/). ## Build Status diff --git a/docs/README.md b/docs/README.md index e33b8b7..7129a22 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # Welcome -Corten is a stack-based virtual machine written in Rust as a hobby. It's based on the [Iridium 1](spec.md#Iridium) architecture from Fletcher Haynes's [So you want to build a language VM](https://blog.subnetzero.io/post/building-language-vm-part-01/). +Corten is a Corten [MIPS64 Release 6](https://en.wikipedia.org/wiki/MIPS_architecture#MIPS32/MIPS64_Release_6) virtual machine written in Rust as a hobby based on Fletcher Haynes's [So you want to build a language VM](https://blog.subnetzero.io/post/building-language-vm-part-01/). ## Specifications diff --git a/docs/spec.md b/docs/spec.md index 3f62c7d..f7ed161 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -2,7 +2,7 @@ ## Iridium -Corten is based on Fletcher Haynes's [So you want to build a language VM](https://blog.subnetzero.io/post/building-language-vm-part-01/) tutorial. His virtual machine used for the tutorial is known as [Iridium](https://github.com/fhaynes/iridium) and is based on the [MIPS64 Release 6](https://en.wikipedia.org/wiki/MIPS_architecture#MIPS32/MIPS64_Release_6) architecture. Corten aims to be Iridium 1-compatible. +Corten [MIPS64 Release 6](https://en.wikipedia.org/wiki/MIPS_architecture#MIPS32/MIPS64_Release_6) virtual machine based on Fletcher Haynes's [So you want to build a language VM](https://blog.subnetzero.io/post/building-language-vm-part-01/) tutorial. ## Instruction Set diff --git a/src/assembler.rs b/src/assembler.rs index 67d7908..834bbe9 100644 --- a/src/assembler.rs +++ b/src/assembler.rs @@ -5,11 +5,91 @@ pub mod operand_parser; pub mod program_parser; pub mod register_parser; -use crate::instruction::Opcode; - #[derive(Debug, PartialEq, Clone)] pub enum Token { Opcode { code: Opcode }, Register { reg_num: u8 }, Number { value: i32 }, } + +#[derive(Debug, PartialEq, Clone)] +pub enum Opcode { + HLT, + IGL, + LOAD, + ADD, + SUB, + MUL, + DIV, + /// Equal + EQ, + /// Not equal + NEQ, + /// Greater then + GT, + /// Less then + LT, + /// Greater then or equal to + GTE, + /// less then or equal + LTE, + /// jump if equal + JMPE, + /// Jump + JMP, + /// Jump forward + JMPF, + /// Jump backward + JMPB, + NOP, +} + +impl From for Opcode { + fn from(vm: u8) -> Self { + match vm { + 0 => Opcode::LOAD, + 1 => Opcode::ADD, + 2 => Opcode::SUB, + 3 => Opcode::MUL, + 4 => Opcode::DIV, + 5 => Opcode::HLT, + 6 => Opcode::JMP, + 7 => Opcode::JMPF, + 8 => Opcode::JMPB, + 9 => Opcode::EQ, + 10 => Opcode::NEQ, + 11 => Opcode::GTE, + 12 => Opcode::GT, + 13 => Opcode::LTE, + 14 => Opcode::LT, + 15 => Opcode::JMPE, + 16 => Opcode::NOP, + _ => Opcode::IGL, + } + } +} + +impl From for u8 { + fn from(op: Opcode) -> Self { + match op { + Opcode::LOAD => 0, + Opcode::ADD => 1, + Opcode::SUB => 2, + Opcode::MUL => 3, + Opcode::DIV => 4, + Opcode::HLT => 5, + Opcode::JMP => 6, + Opcode::JMPF => 7, + Opcode::JMPB => 8, + Opcode::EQ => 9, + Opcode::NEQ => 10, + Opcode::GTE => 11, + Opcode::LTE => 12, + Opcode::LT => 13, + Opcode::GT => 14, + Opcode::JMPE => 15, + Opcode::NOP => 16, + Opcode::IGL => 100, + } + } +} \ No newline at end of file diff --git a/src/assembler/instruction_parser.rs b/src/assembler/instruction_parser.rs index 7f77d5f..4d78796 100644 --- a/src/assembler/instruction_parser.rs +++ b/src/assembler/instruction_parser.rs @@ -21,7 +21,7 @@ impl AssemblerInstruction { match self.opcode.to_owned() { Token::Opcode { code } => match code { _ => { - results.push(code as u8); + results.push(code.into()); } }, _ => { @@ -30,6 +30,7 @@ impl AssemblerInstruction { } }; + for operand in vec![&self.op1, &self.op2, &self.op3] { match operand { Some(t) => AssemblerInstruction::extract_operand(t, &mut results), @@ -81,7 +82,7 @@ named!(pub instruction_one, #[cfg(test)] mod instruction_parser_test { use super::*; - use crate::instruction::Opcode; + use crate::assembler::Opcode; #[test] fn test_parse_instruction_form_one() { diff --git a/src/assembler/opcode_parser.rs b/src/assembler/opcode_parser.rs index 65f2386..8d4406f 100644 --- a/src/assembler/opcode_parser.rs +++ b/src/assembler/opcode_parser.rs @@ -2,8 +2,7 @@ use nom::*; use nom::{digit, types::CompleteStr}; -use crate::assembler::Token; -use crate::instruction::Opcode; +use crate::assembler::{Token, Opcode}; named!(pub opcode_load, do_parse!(tag!("load") >> (Token::Opcode{code: Opcode::LOAD})) diff --git a/src/instruction.rs b/src/instruction.rs index 44a24af..e84f5af 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -1,61 +1,6 @@ #![allow(dead_code)] -#[derive(Debug, PartialEq, Clone)] -pub enum Opcode { - HLT, - IGL, - LOAD, - ADD, - SUB, - MUL, - DIV, - /// Equal - EQ, - /// Not equal - NEQ, - /// Greater then - GT, - /// Less then - LT, - /// Greater then or equal to - GTE, - /// less then or equal - LTE, - /// jump if equal - JMPE, - /// Jump - JMP, - /// Jump forward - JMPF, - /// Jump backward - JMPB, - NOP, -} - -impl From for Opcode { - fn from(vm: u8) -> Self { - match vm { - 0 => Opcode::LOAD, - 1 => Opcode::ADD, - 2 => Opcode::SUB, - 3 => Opcode::MUL, - 4 => Opcode::DIV, - 5 => Opcode::HLT, - 6 => Opcode::JMP, - 7 => Opcode::JMPF, - 8 => Opcode::JMPB, - 9 => Opcode::EQ, - 10 => Opcode::NEQ, - 11 => Opcode::GTE, - 12 => Opcode::GT, - 13 => Opcode::LTE, - 14 => Opcode::LT, - 15 => Opcode::JMPE, - 16 => Opcode::NOP, - _ => Opcode::IGL, - } - } -} +use crate::assembler::Opcode; #[derive(Debug, PartialEq)] pub struct Instruction { @@ -71,6 +16,7 @@ impl Instruction { #[cfg(test)] mod instruction_tests { use crate::instruction::*; + use crate::assembler::Opcode; #[test] fn test_crate_hlt() { diff --git a/src/vm.rs b/src/vm.rs index d76209c..6bb1595 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,5 +1,5 @@ #![allow(dead_code)] -use crate::instruction::Opcode; +use crate::assembler::Opcode; pub struct VM { /// Array that simulates the hardware register