Krolyxon
Commit 3372e77

Branches

Tags

Refs →

bench513372e77

add MUL & DIV

Author
krolxon
Date
2026-01-08 18:47 +0530
Parent
68d8540
Commit
3372e774e9505acdc3778a8155476cca4bfbd3e8

+74 −3

6 files changed

  1. M README.md +2 −0
  2. A examples/div.asm +4 −0
  3. A examples/mul.asm +4 −0
  4. M src/assembler.rs +20 −1
  5. M src/cpu.rs +40 −2
  6. M src/instructions.rs +4 −0
M README.md View
@@ -47,6 +47,8 @@ cargo run -- --f <examples/filename.asc>
4747 - [x] Add label support (supporting JMP/JZ/JNZ)
4848 - [ ] Add instructions
4949 - [x] CMP
50+ - [x] MUL
51+ - [x] DIV
5052 - [ ] CALL
5153 - [ ] RET
5254 - [ ] Error handling
A examples/div.asm View
@@ -0,0 +1,4 @@
1+mov a, 10
2+mov b, 2
3+div a, b
4+hlt
A examples/mul.asm View
@@ -0,0 +1,4 @@
1+mov a, 99
2+mov b, 99
3+mul a, b
4+hlt
M src/assembler.rs View
@@ -25,7 +25,7 @@ fn is_reg(s: &str) -> bool {
2525
2626 fn instr_size(tokens: &[String]) -> u16 {
2727 match tokens[0].as_str() {
28− "mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" => 3,
28+ "mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" | "mul" | "div" => 3,
2929 "hlt" => 1,
3030 _ => panic!("Unknown instruction {}", tokens[0]),
3131 }
@@ -153,6 +153,25 @@ pub fn assembler(source: &str) -> Vec<u8> {
153153 }
154154 }
155155
156+ "mul" => {
157+ let r1 = parse_reg(&tokens[1]);
158+ let r2 = parse_reg(&tokens[2]);
159+
160+ bytes.push(Instruction::MUL as u8);
161+ bytes.push(r1);
162+ bytes.push(r2);
163+
164+ }
165+
166+ "div" => {
167+ let r1 = parse_reg(&tokens[1]);
168+ let r2 = parse_reg(&tokens[2]);
169+
170+ bytes.push(Instruction::DIV as u8);
171+ bytes.push(r1);
172+ bytes.push(r2);
173+ }
174+
156175 "hlt" => {
157176 bytes.push(Instruction::HLT as u8);
158177 }
M src/cpu.rs View
@@ -51,6 +51,8 @@ impl CPU {
5151 x if x == Instruction::JNZ as u8 => self.jnz(mem),
5252 x if x == Instruction::CMP_RI as u8 => self.cmp_ri(mem),
5353 x if x == Instruction::CMP_RR as u8 => self.cmp_rr(mem),
54+ x if x == Instruction::MUL as u8 => self.mul(mem),
55+ x if x == Instruction::DIV as u8 => self.div(mem),
5456 x if x == Instruction::HLT as u8 => self.halt(),
5557 _ => panic!("Unknown opcode {:02X}", opcode),
5658 }
@@ -298,6 +300,42 @@ impl CPU {
298300 self.carry = borrow;
299301 }
300302
303+ pub fn mul(&mut self, mem: &Memory) {
304+ let dest = mem.read(self.pc); self.inc_pc();
305+ let src = mem.read(self.pc); self.inc_pc();
306+
307+ let lhs = self.get_reg(dest);
308+ let rhs = self.get_reg(src);
309+
310+ let result16 = (lhs as u16) * (rhs as u16);
311+ let result8 = (result16 & 0xFF) as u8;
312+
313+ self.set_reg(dest, result8);
314+
315+ self.zero = result8 == 0;
316+ self.carry = result16 > 0xFF;
317+ }
318+
319+ pub fn div(&mut self, mem: &Memory) {
320+ let dest = mem.read(self.pc); self.inc_pc();
321+ let src = mem.read(self.pc); self.inc_pc();
322+
323+ let lhs = self.get_reg(dest);
324+ let rhs = self.get_reg(src);
325+
326+ if rhs == 0 {
327+ panic!("Division by zero");
328+ // OR: set halted = true
329+ // OR: define a syscall/exception later
330+ }
331+
332+ let result = lhs / rhs;
333+
334+ self.set_reg(dest, result);
335+
336+ self.zero = result == 0;
337+ // carry unchanged
338+ }
301339
302340 fn get_reg(&self, r: u8) -> u8 {
303341 match r {
@@ -305,7 +343,7 @@ impl CPU {
305343 1 => self.b,
306344 2 => self.c,
307345 3 => self.d,
308− _ => 0,
346+ _ => panic!("Invalid Register"),
309347 }
310348 }
311349
@@ -315,7 +353,7 @@ impl CPU {
315353 1 => self.b = val,
316354 2 => self.c = val,
317355 3 => self.d = val,
318− _ => {},
356+ _ => panic!("Invalid register"),
319357 }
320358 }
321359
M src/instructions.rs View
@@ -12,6 +12,8 @@ pub enum Instruction {
1212 JNZ = 0x06,
1313 CMP_RI = 0x07,
1414 CMP_RR = 0x09,
15+ MUL = 0x0C,
16+ DIV = 0x0D,
1517 HLT = 0xFF,
1618 }
1719
@@ -25,6 +27,8 @@ impl Instruction {
2527 0x05 => "JZ",
2628 0x06 => "JNZ",
2729 0x07 | 0x09 => "CMP",
30+ 0x0C => "MUL",
31+ 0x0D => "DIV",
2832 0xFF => "HLT",
2933 _ => "???",
3034 }