jpl: 1 Add documentation to instructions 1 files changed, 46 insertions(+), 0 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~tmpod/toasty-lc3-vm/patches/34356/mbox | git am -3Learn more about email & git
--- vm/src/cpu.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/vm/src/cpu.rs b/vm/src/cpu.rs index 2fb8310..68cb32b 100644 --- a/vm/src/cpu.rs +++ b/vm/src/cpu.rs @@ -43,12 +43,19 @@ impl CPU { instruction: Instruction, ) -> Result<()> { match instruction { + // Branch + // Offsets the Program Counter (PC) by the given offset + // if the condition is met. Instruction::BR(cond, offset) => { if cond & self.registers[Register::COND] != 0 { let sum = self.registers[Register::PC].wrapping_add(offset); self.registers[Register::PC] = sum; } } + // Addition + // Adds the value in the first register with + // either the value in a second register, or + // an immediate Instruction::ADD(dest, first, mode) => { let second_val = match mode { AddMode::Register(reg) => self.registers[reg], @@ -57,15 +64,27 @@ impl CPU { self.registers[dest] = self.registers[first].wrapping_add(second_val); self.registers.update_cond_codes(dest); } + // Load + // Loads a value from memory into a destination register + // at an address offset from the PC Instruction::LD(dest, offset) => { let addr = self.registers[Register::PC].wrapping_add(offset); self.registers[dest] = memory.read(addr); self.registers.update_cond_codes(dest); } + // Store + // Loads a value into memory from a source register + // at an address offset from the PC Instruction::ST(source, offset) => { let addr = self.registers[Register::PC].wrapping_add(offset); memory.write(addr, self.registers[source]); } + // Jump Sub-Routine + // Sets the PC to the base register + // or offsets it by an immediate. + // The previous value of the PC is stored + // in R7 to allow jumping back to when + // the sub-routine was called. Instruction::JSR(mode) => { let tmp = self.registers[Register::PC]; let new_pc = match mode { @@ -75,6 +94,10 @@ impl CPU { self.registers[Register::PC] = new_pc; self.registers[Register::R7] = tmp; } + // Bit-wise AND + // Performs the bit-wise AND of the value in + // the first register with either the value in + // a second register, or an immediate Instruction::AND(dest, first, mode) => { let second_val = match mode { AndMode::Register(reg) => self.registers[reg], @@ -84,11 +107,17 @@ impl CPU { self.registers[dest] = self.registers[first] & second_val; self.registers.update_cond_codes(dest); } + // Load Register + // Loads a value from memory into a destination register + // at an address offset from the base register Instruction::LDR(dest, base, offset) => { let addr = self.registers[base].wrapping_add(offset); self.registers[dest] = memory.read(addr); self.registers.update_cond_codes(dest); } + // Store + // Loads a value into memory from a source register + // at an address offset from the base register Instruction::STR(source, base, offset) => { let addr = self.registers[base].wrapping_add(offset); memory.write(addr, self.registers[source]); @@ -100,21 +129,38 @@ impl CPU { self.registers[dest] = !self.registers[source]; self.registers.update_cond_codes(dest); } + // Load Immediate + // Loads a value from memory into a destination register + // by performing a double memory access on the PC + // offset by the immediate. + // + // dest = mem[mem[PC + offset]] Instruction::LDI(dest, offset) => { let addr = self.registers[Register::PC].wrapping_add(offset); let addr_final = memory.read(addr); self.registers[dest] = memory.read(addr_final); self.registers.update_cond_codes(dest); } + // Store Immediate + // Stores a value in memory from a source register + // by performing a double memory access on the PC + // offset by the immediate. + // + // mem[mem[PC + offset]] = source Instruction::STI(source, offset) => { let addr = self.registers[Register::PC].wrapping_add(offset); let addr_final = memory.read(addr); memory.write(addr_final, self.registers[source]); } + // Jump + // Sets the PC to the value of the base register. Instruction::JMP(base) => self.registers[Register::PC] = self.registers[base], Instruction::RES => { // NO-OP } + // Load Effective Address + // Sets the destination register to the PC offset + // by an immediate. Instruction::LEA(dest, offset) => { let val = self.registers[Register::PC].wrapping_add(offset); self.registers[dest] = val; -- 2.37.1 Decided to add some documentation to the instructions, based on the LC3 ISA. It should make it easier to reason about the implementation, detect any deviations from the ISA, be they harmful or improvements. If you find any mistakes, particularly naming the instructions, let me know that I'll patch it. Still need to doc the Traps, though.
This is nice, thank you! I think it would be better to add those short descriptions to the already existing triple-slash comments on the enum variants, instead of having them sit on those match arms. Send a new patch version with that fixed, as well as the traps if you wouldn't mind :3