Implemented HLT instruction

- Instructions are now detected automatically based on context
- Since MIPs can't decide if it wants to be open or not, Corten will be aiming to be more of a RISC-V VM in the long term.
This commit is contained in:
Anthony Foxclaw 2020-02-09 15:16:38 -05:00
parent 76af517a49
commit 86f060e0f5
10 changed files with 120 additions and 31 deletions

View file

@ -1,9 +1,8 @@
use nom::*;
use crate::assembler::Token;
use crate::assembler::opcode_parser::opcode_load;
use crate::assembler::opcode_parser::opcode;
use crate::assembler::operand_parser::integer_operand;
use crate::assembler::register_parser::register;
use crate::assembler::Token;
use nom::*;
use nom::types::CompleteStr;
#[derive(Debug, PartialEq)]
@ -30,7 +29,6 @@ impl AssemblerInstruction {
}
};
for operand in &[&self.operand1, &self.operand2, &self.operand3] {
if let Some(token) = operand {
AssemblerInstruction::extract_operand(token, &mut results)
@ -44,7 +42,7 @@ impl AssemblerInstruction {
match t {
Token::Register { reg_num } => {
results.push(*reg_num);
},
}
Token::Number { value } => {
let conv = *value as u16;
let byte1 = conv;
@ -52,19 +50,45 @@ impl AssemblerInstruction {
results.push(byte2 as u8);
results.push(byte1 as u8);
},
}
_ => {
println!("Opcode found in operand field");
std::process::exit(1);
}
};
}
}
named!(pub instruction_one<CompleteStr, AssemblerInstruction>,
named!(instruction_two<CompleteStr, AssemblerInstruction>,
do_parse!(
o: opcode_load >>
o: opcode >>
opt!(multispace) >>
(
AssemblerInstruction{
opcode: o,
operand1: None,
operand2: None,
operand3: None
}
)
)
);
named!(pub instruction<CompleteStr, AssemblerInstruction>,
do_parse!(
ins: alt!(
instruction_one |
instruction_two
) >>
(
ins
)
)
);
named!(instruction_one<CompleteStr, AssemblerInstruction>,
do_parse!(
o: opcode >>
r: register >>
i: integer_operand >>
(
@ -99,4 +123,21 @@ mod instruction_parser_test {
))
);
}
#[test]
fn test_parse_instruction_form_two() {
let result = instruction_two(CompleteStr("hlt\n"));
assert_eq!(
result,
Ok((
CompleteStr(""),
AssemblerInstruction {
opcode: Token::Opcode { code: Opcode::HLT },
operand1: None,
operand2: None,
operand3: None
}
))
);
}
}

View file

@ -1,11 +1,18 @@
#![allow(unused_imports)]
use nom::*;
use nom::{digit, types::CompleteStr};
use nom::{alpha1, digit, types::CompleteStr};
use crate::assembler::{Token, Opcode};
use crate::assembler::{Opcode, Token};
named!(pub opcode_load<CompleteStr, Token>,
do_parse!(tag!("load") >> (Token::Opcode{code: Opcode::LOAD}))
named!(pub opcode<CompleteStr, Token>,
do_parse!(
opcode: alpha1 >>
(
{
Token::Opcode{code: Opcode::from(opcode)}
}
)
)
);
#[cfg(test)]
@ -15,10 +22,13 @@ mod opcode_parser_test {
#[test]
fn test_parser_op_load() {
// Test that opcode is dected and parsed correctly
let result = opcode_load(CompleteStr("load"));
let result = opcode(CompleteStr("load"));
assert_eq!(result.is_ok(), true);
let (rest, token) = result.unwrap();
assert_eq!(token, Token::Opcode { code: Opcode::LOAD });
assert_eq!(rest, CompleteStr(""));
let result = opcode(CompleteStr("alod"));
let (_, token) = result.unwrap();
assert_eq!(token, Token::Opcode { code: Opcode::IGL });
}
}

View file

@ -21,7 +21,7 @@ mod reg_parser_test {
use super::*;
#[test]
fn test_opcode_load() {
fn test_opcode() {
let result = integer_operand(CompleteStr("#10"));
let (rest, value) = result.unwrap();
assert_eq!(rest, CompleteStr(""));

View file

@ -1,7 +1,7 @@
use nom::types::CompleteStr;
use nom::*;
use crate::assembler::instruction_parser::{instruction_one, AssemblerInstruction};
use crate::assembler::instruction_parser::{instruction, AssemblerInstruction};
#[derive(Debug, PartialEq)]
pub struct Program {
@ -20,7 +20,7 @@ impl Program {
named!(pub program<CompleteStr, Program>,
do_parse!(
instructions: many1!(instruction_one) >>
instructions: many1!(instruction) >>
(
Program {
instructions