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.
This commit is contained in:
Anthony Foxclaw 2020-02-08 15:14:37 -05:00
parent afb68e46b3
commit 853188b010
8 changed files with 92 additions and 66 deletions

View file

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

View file

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

View file

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

View file

@ -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<u8> 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<Opcode> 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,
}
}
}

View file

@ -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<CompleteStr, AssemblerInstruction>,
#[cfg(test)]
mod instruction_parser_test {
use super::*;
use crate::instruction::Opcode;
use crate::assembler::Opcode;
#[test]
fn test_parse_instruction_form_one() {

View file

@ -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<CompleteStr, Token>,
do_parse!(tag!("load") >> (Token::Opcode{code: Opcode::LOAD}))

View file

@ -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<u8> 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() {

View file

@ -1,5 +1,5 @@
#![allow(dead_code)]
use crate::instruction::Opcode;
use crate::assembler::Opcode;
pub struct VM {
/// Array that simulates the hardware register