binary ggeneration as well
This commit is contained in:
3
examples/add_number.asm
Normal file
3
examples/add_number.asm
Normal file
@@ -0,0 +1,3 @@
|
||||
LDA #1
|
||||
ADD #3
|
||||
STA (8)
|
||||
83
src/asm.rs
83
src/asm.rs
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ mod asm;
|
||||
mod generate;
|
||||
mod parse;
|
||||
|
||||
use generate::generate_binary;
|
||||
use parse::{parse_asm, AsmParser};
|
||||
|
||||
fn main() {
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user