diff options
| Commit | 4b5ed8fb063f08ce399371e48c59665e59ceea47 (patch) | |
|---|---|---|
| Author | 2025-02-15 00:19:03 +0200 | |
| Committer | 2025-02-15 00:19:03 +0200 | |
| Files | eddf26834aeb1549fbe468f2d0f95484c544073c /assembler/src/parser/code_gen.rs | |
| tonkobali-4b5ed8fb063f08ce399371e48c59665e59ceea47.tar tonkobali-4b5ed8fb063f08ce399371e48c59665e59ceea47.tar.gz tonkobali-4b5ed8fb063f08ce399371e48c59665e59ceea47.zip | ||
| Parent | e683120089bd669019a240c7eb5d615fa92df075 (diff) | |
feat(assembler): Add support for two pass collapse instructions and implement subroutine instructions
1 files changed, 35 insertions, 9 deletions
| -rw-r--r-- | assembler/src/parser/code_gen.rs | 44 |
diff --git a/assembler/src/parser/code_gen.rs b/assembler/src/parser/code_gen.rs index ec4a2d2..2eaa34c 100644 --- a/assembler/src/parser/code_gen.rs +++ b/assembler/src/parser/code_gen.rs @@ -3,7 +3,6 @@ use super::{ Program, Address }; impl Program { /* Intermediate code generation */ - pub(crate) fn collapse_instructions(&mut self) { // Fix instruction addresses let mut offsets = Vec::new(); @@ -14,8 +13,14 @@ impl Program { for instr in &mut self.instructions { for arg in &mut instr.args { - if let Address::Instruction(num) = arg { - *arg = Address::Instruction(offsets[*num]); + match arg { + Address::Instruction(num) + => *arg = Address::Instruction(offsets[*num]), + Address::InstructionOffset(num, offset) + => *arg = Address::InstructionOffset(offsets[*num], *offset), + Address::InstructionConstant(num) + => *arg = Address::InstructionConstant(offsets[*num]), + _ => {}, } } } @@ -32,9 +37,27 @@ impl Program { /* Machine code generation */ - pub(crate) fn instructions_to_constants(&mut self, mut absolute_start: usize) { - absolute_start += 1; - let constlen = self.constants.len(); + pub(crate) fn instructions_to_constants(&mut self) { + let absolute_start = self.absolute_start + 1; + + let mut constlen = self.constants.len(); + for instr in &self.instructions { + for arg in &instr.args { + if let Address::InstructionConstant(_) = arg { + constlen += 1; + } + } + } + + for instr in &mut self.instructions { + for arg in &mut instr.args { + if let Address::InstructionConstant(num) = arg { + self.constants.push((constlen + absolute_start + *num * 3) as Word); + *arg = Address::Constants(self.constants.len() - 1); + } + } + } + self.constants.insert(0, (absolute_start + constlen) as Word); for instr in &mut self.instructions { @@ -42,7 +65,10 @@ impl Program { self.constants.push(match arg { Address::Memory(num) => *num, Address::Constants(num) => absolute_start + *num, - Address::Instruction(num) => constlen + absolute_start + *num * 3, + Address::Instruction(num) + => constlen + absolute_start + *num * 3, + Address::InstructionOffset(num, off) + => *off + constlen + absolute_start + *num * 3, _ => unreachable!("Definition addresses should've already been removed!"), } as Word); } @@ -50,9 +76,9 @@ impl Program { self.instructions.clear(); } - pub(crate) fn to_bytes(self, absolute_start: usize, pc: usize) -> Vec<u8> { + pub(crate) fn to_bytes(self, pc: usize) -> Vec<u8> { let mut res = Vec::new(); - res.resize(absolute_start, Default::default()); + res.resize(self.absolute_start, Default::default()); res[pc] = self.constants[0]; res.extend(self.constants); res |
