Implemented more of the assembler
This commit is contained in:
parent
4bfde58cc5
commit
fe69c0d0c8
4 changed files with 68 additions and 4 deletions
|
@ -7,7 +7,7 @@ pub mod register_parser;
|
|||
|
||||
use crate::instruction::Opcode;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Token {
|
||||
Opcode { code: Opcode },
|
||||
Register { reg_num: u8 },
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::assembler::operand_parser::integer_operand;
|
|||
use crate::assembler::register_parser::register;
|
||||
|
||||
use nom::types::CompleteStr;
|
||||
use nom::*;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct AssemblerInstruction {
|
||||
|
@ -15,6 +14,53 @@ pub struct AssemblerInstruction {
|
|||
op3: Option<Token>,
|
||||
}
|
||||
|
||||
impl AssemblerInstruction {
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut results = vec![];
|
||||
|
||||
match self.opcode.clone() {
|
||||
Token::Opcode { code } => match code {
|
||||
_ => {
|
||||
results.push(code as u8);
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
println!("Incorrect opcode!");
|
||||
std::process::exit(0);
|
||||
}
|
||||
};
|
||||
|
||||
for operand in vec![&self.op1, &self.op2, &self.op3] {
|
||||
match operand {
|
||||
Some(t) => AssemblerInstruction::extract_operand(t, &mut results),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
results
|
||||
}
|
||||
|
||||
fn extract_operand(t: &Token, results: &mut Vec<u8>) {
|
||||
match t {
|
||||
Token::Register { reg_num } => {
|
||||
results.push(*reg_num);
|
||||
},
|
||||
Token::Number { value } => {
|
||||
let conv = *value as u16;
|
||||
let byte1 = conv;
|
||||
let byte2 = conv >> 8;
|
||||
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>,
|
||||
do_parse!(
|
||||
o: opcode_load >>
|
||||
|
|
|
@ -8,6 +8,16 @@ pub struct Program {
|
|||
instructions: Vec<AssemblerInstruction>,
|
||||
}
|
||||
|
||||
impl Program {
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut prog = vec![];
|
||||
for instruction in &self.instructions {
|
||||
prog.append(&mut instruction.to_bytes());
|
||||
}
|
||||
prog
|
||||
}
|
||||
}
|
||||
|
||||
named!(pub program<CompleteStr, Program>,
|
||||
do_parse!(
|
||||
instructions: many1!(instruction_one) >>
|
||||
|
@ -22,7 +32,6 @@ named!(pub program<CompleteStr, Program>,
|
|||
#[cfg(test)]
|
||||
mod instruction_parser_test {
|
||||
use super::*;
|
||||
use crate::instruction::Opcode;
|
||||
|
||||
#[test]
|
||||
fn test_parse_instruction() {
|
||||
|
@ -31,4 +40,13 @@ mod instruction_parser_test {
|
|||
assert_eq!(leftover, CompleteStr(""));
|
||||
assert_eq!(1, p.instructions.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_program_to_bytes() {
|
||||
let result = program(CompleteStr("load $0 #100\n"));
|
||||
let (_, prog) = result.unwrap();
|
||||
let bytecode = prog.to_bytes();
|
||||
assert_eq!(bytecode.len(), 4);
|
||||
println!("{:?}", bytecode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Opcode {
|
||||
HLT,
|
||||
IGL,
|
||||
|
|
Reference in a new issue