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:
parent
afb68e46b3
commit
853188b010
8 changed files with 92 additions and 66 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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}))
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![allow(dead_code)]
|
||||
use crate::instruction::Opcode;
|
||||
use crate::assembler::Opcode;
|
||||
|
||||
pub struct VM {
|
||||
/// Array that simulates the hardware register
|
||||
|
|
Reference in a new issue