From 3372e774e9505acdc3778a8155476cca4bfbd3e8 Mon Sep 17 00:00:00 2001 From: krolxon Date: Thu, 8 Jan 2026 18:47:07 +0530 Subject: [PATCH] add MUL & DIV --- README.md | 2 ++ examples/div.asm | 4 ++++ examples/mul.asm | 4 ++++ src/assembler.rs | 21 ++++++++++++++++++++- src/cpu.rs | 42 ++++++++++++++++++++++++++++++++++++++++-- src/instructions.rs | 4 ++++ 6 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 examples/div.asm create mode 100644 examples/mul.asm diff --git a/README.md b/README.md index 0fda2d6..fd391d2 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,8 @@ cargo run -- --f - [x] Add label support (supporting JMP/JZ/JNZ) - [ ] Add instructions - [x] CMP + - [x] MUL + - [x] DIV - [ ] CALL - [ ] RET - [ ] Error handling diff --git a/examples/div.asm b/examples/div.asm new file mode 100644 index 0000000..f07766c --- /dev/null +++ b/examples/div.asm @@ -0,0 +1,4 @@ +mov a, 10 +mov b, 2 +div a, b +hlt diff --git a/examples/mul.asm b/examples/mul.asm new file mode 100644 index 0000000..a818dfd --- /dev/null +++ b/examples/mul.asm @@ -0,0 +1,4 @@ +mov a, 99 +mov b, 99 +mul a, b +hlt diff --git a/src/assembler.rs b/src/assembler.rs index e7aa305..1b9c85b 100644 --- a/src/assembler.rs +++ b/src/assembler.rs @@ -25,7 +25,7 @@ fn is_reg(s: &str) -> bool { fn instr_size(tokens: &[String]) -> u16 { match tokens[0].as_str() { - "mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" => 3, + "mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" | "mul" | "div" => 3, "hlt" => 1, _ => panic!("Unknown instruction {}", tokens[0]), } @@ -153,6 +153,25 @@ pub fn assembler(source: &str) -> Vec { } } + "mul" => { + let r1 = parse_reg(&tokens[1]); + let r2 = parse_reg(&tokens[2]); + + bytes.push(Instruction::MUL as u8); + bytes.push(r1); + bytes.push(r2); + + } + + "div" => { + let r1 = parse_reg(&tokens[1]); + let r2 = parse_reg(&tokens[2]); + + bytes.push(Instruction::DIV as u8); + bytes.push(r1); + bytes.push(r2); + } + "hlt" => { bytes.push(Instruction::HLT as u8); } diff --git a/src/cpu.rs b/src/cpu.rs index d0365ba..9416783 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -51,6 +51,8 @@ impl CPU { x if x == Instruction::JNZ as u8 => self.jnz(mem), x if x == Instruction::CMP_RI as u8 => self.cmp_ri(mem), x if x == Instruction::CMP_RR as u8 => self.cmp_rr(mem), + x if x == Instruction::MUL as u8 => self.mul(mem), + x if x == Instruction::DIV as u8 => self.div(mem), x if x == Instruction::HLT as u8 => self.halt(), _ => panic!("Unknown opcode {:02X}", opcode), } @@ -298,6 +300,42 @@ impl CPU { self.carry = borrow; } + pub fn mul(&mut self, mem: &Memory) { + let dest = mem.read(self.pc); self.inc_pc(); + let src = mem.read(self.pc); self.inc_pc(); + + let lhs = self.get_reg(dest); + let rhs = self.get_reg(src); + + let result16 = (lhs as u16) * (rhs as u16); + let result8 = (result16 & 0xFF) as u8; + + self.set_reg(dest, result8); + + self.zero = result8 == 0; + self.carry = result16 > 0xFF; + } + + pub fn div(&mut self, mem: &Memory) { + let dest = mem.read(self.pc); self.inc_pc(); + let src = mem.read(self.pc); self.inc_pc(); + + let lhs = self.get_reg(dest); + let rhs = self.get_reg(src); + + if rhs == 0 { + panic!("Division by zero"); + // OR: set halted = true + // OR: define a syscall/exception later + } + + let result = lhs / rhs; + + self.set_reg(dest, result); + + self.zero = result == 0; + // carry unchanged + } fn get_reg(&self, r: u8) -> u8 { match r { @@ -305,7 +343,7 @@ impl CPU { 1 => self.b, 2 => self.c, 3 => self.d, - _ => 0, + _ => panic!("Invalid Register"), } } @@ -315,7 +353,7 @@ impl CPU { 1 => self.b = val, 2 => self.c = val, 3 => self.d = val, - _ => {}, + _ => panic!("Invalid register"), } } diff --git a/src/instructions.rs b/src/instructions.rs index bfc4fc6..9f81b9a 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -12,6 +12,8 @@ pub enum Instruction { JNZ = 0x06, CMP_RI = 0x07, CMP_RR = 0x09, + MUL = 0x0C, + DIV = 0x0D, HLT = 0xFF, } @@ -25,6 +27,8 @@ impl Instruction { 0x05 => "JZ", 0x06 => "JNZ", 0x07 | 0x09 => "CMP", + 0x0C => "MUL", + 0x0D => "DIV", 0xFF => "HLT", _ => "???", }