Skip to content

Commit

Permalink
binary ggeneration as well
Browse files Browse the repository at this point in the history
  • Loading branch information
hargoniX committed Nov 28, 2020
1 parent fc46719 commit 03a55b4
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 1 deletion.
3 changes: 3 additions & 0 deletions examples/add_number.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
LDA #1
ADD #3
STA (8)
83 changes: 83 additions & 0 deletions src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,86 @@ pub enum ArgumentInstruction {
ADD(Argument),
SUB(Argument),
}

pub struct BinaryInstruction {
pub opcode: u8,
pub argument: u8,
}

impl<'a> Into<BinaryInstruction> for NoArgumentInstruction {
fn into(self) -> BinaryInstruction {
match self {
NoArgumentInstruction::NOP => BinaryInstruction {
opcode: 0,
argument: 0,
},
}
}
}

impl<'a> Into<BinaryInstruction> for MemoryLocationInstruction {
fn into(self) -> BinaryInstruction {
match self {
MemoryLocationInstruction::STA(arg) => BinaryInstruction {
opcode: 3,
argument: arg,
},
}
}
}

impl<'a> Into<BinaryInstruction> for ConstantArgumentInstruction {
fn into(self) -> BinaryInstruction {
match self {
ConstantArgumentInstruction::BRZ(arg) => BinaryInstruction {
opcode: 9,
argument: arg,
},
ConstantArgumentInstruction::BRC(arg) => BinaryInstruction {
opcode: 10,
argument: arg,
},
ConstantArgumentInstruction::BRN(arg) => BinaryInstruction {
opcode: 11,
argument: arg,
},
}
}
}

impl<'a> Into<BinaryInstruction> for ArgumentInstruction {
fn into(self) -> BinaryInstruction {
match self {
ArgumentInstruction::LDA(arg) => match arg {
Argument::MemoryLocation(arg) => BinaryInstruction {
opcode: 2,
argument: arg,
},
Argument::Constant(arg) => BinaryInstruction {
opcode: 1,
argument: arg,
},
},
ArgumentInstruction::ADD(arg) => match arg {
Argument::MemoryLocation(arg) => BinaryInstruction {
opcode: 5,
argument: arg,
},
Argument::Constant(arg) => BinaryInstruction {
opcode: 4,
argument: arg,
},
},
ArgumentInstruction::SUB(arg) => match arg {
Argument::MemoryLocation(arg) => BinaryInstruction {
opcode: 7,
argument: arg,
},
Argument::Constant(arg) => BinaryInstruction {
opcode: 6,
argument: arg,
},
},
}
}
}
88 changes: 88 additions & 0 deletions src/generate.rs
Original file line number Diff line number Diff line change
@@ -1 +1,89 @@
use crate::asm::*;
use std::collections::HashMap;
use std::fmt;

pub struct Program {
data_memory: [u8; 16],
program_memory: [u8; 16],
}

impl fmt::Display for Program {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Data Memory:")?;
for chunk in self.data_memory.chunks(4) {
writeln!(
f,
"{:x} {:x} {:x} {:x}",
chunk[0], chunk[1], chunk[2], chunk[3]
)?;
}

writeln!(f, "Program Memory:")?;
for chunk in self.program_memory.chunks(4) {
writeln!(
f,
"{:x} {:x} {:x} {:x}",
chunk[0], chunk[1], chunk[2], chunk[3]
)?;
}
writeln!(f, "And that's your program!")
}
}

pub fn generate_binary(instructions: Vec<Instruction>) -> Program {
let mut labels: HashMap<&str, u8> = HashMap::new();
let mut data_memory: [u8; 16] = [0; 16];
let mut program_memory: [u8; 16] = [0; 16];

// collect all labels
for instruction in instructions.iter() {
match instruction {
Instruction::NoArgumentInstruction(_, label)
| Instruction::MemoryLocationInstruction(_, label)
| Instruction::ConstantArgumentInstruction(_, label)
| Instruction::ArgumentInstruction(_, label)
| Instruction::Jump(_, label) => {
insert_label(&mut labels, label);
}
}
}

for (c, instruction) in instructions.iter().enumerate() {
let binary_instruction: BinaryInstruction = match instruction {
Instruction::NoArgumentInstruction(instruction, _) => (*instruction).into(),
Instruction::MemoryLocationInstruction(instruction, _) => (*instruction).into(),
Instruction::ConstantArgumentInstruction(instruction, _) => (*instruction).into(),
Instruction::ArgumentInstruction(instruction, _) => (*instruction).into(),
Instruction::Jump(argument, _) => match argument {
JumpArgument::Location(arg) => BinaryInstruction {
opcode: 8,
argument: *arg,
},
JumpArgument::Label(arg) => {
if let Some(address) = labels.get(*arg) {
BinaryInstruction {
opcode: 8,
argument: *address,
}
} else {
panic!("Tried to JMP to label: {}, which does not exist", arg);
}
}
},
};

program_memory[c] = binary_instruction.opcode;
data_memory[c] = binary_instruction.argument;
}

Program {
data_memory,
program_memory,
}
}

fn insert_label<'a>(hashmap: &mut HashMap<&'a str, u8>, label: &Option<Label<'a>>) {
if let Some(label) = label {
hashmap.insert(label.name, label.location);
}
}
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod asm;
mod generate;
mod parse;

use generate::generate_binary;
use parse::{parse_asm, AsmParser};

fn main() {
Expand All @@ -28,5 +29,6 @@ fn main() {
let instructions = parse_asm(
AsmParser::parse(parse::Rule::program, &file_content).unwrap_or_else(|e| panic!("{}", e)),
);
println!("{:#?}", instructions);
let binary = generate_binary(instructions);
println!("{}", binary);
}

0 comments on commit 03a55b4

Please sign in to comment.