bench513372e77
add MUL & DIV
+74 −3
6 files changed
- M README.md +2 −0
- A examples/div.asm +4 −0
- A examples/mul.asm +4 −0
- M src/assembler.rs +20 −1
- M src/cpu.rs +40 −2
- M src/instructions.rs +4 −0
| @@ -47,6 +47,8 @@ cargo run -- --f <examples/filename.asc> | |||
| 47 | 47 | - [x] Add label support (supporting JMP/JZ/JNZ) | |
| 48 | 48 | - [ ] Add instructions | |
| 49 | 49 | - [x] CMP | |
| 50 | + | - [x] MUL | |
| 51 | + | - [x] DIV | |
| 50 | 52 | - [ ] CALL | |
| 51 | 53 | - [ ] RET | |
| 52 | 54 | - [ ] Error handling | |
| @@ -0,0 +1,4 @@ | |||
| 1 | + | mov a, 10 | |
| 2 | + | mov b, 2 | |
| 3 | + | div a, b | |
| 4 | + | hlt | |
| @@ -0,0 +1,4 @@ | |||
| 1 | + | mov a, 99 | |
| 2 | + | mov b, 99 | |
| 3 | + | mul a, b | |
| 4 | + | hlt | |
| @@ -25,7 +25,7 @@ fn is_reg(s: &str) -> bool { | |||
| 25 | 25 | ||
| 26 | 26 | fn instr_size(tokens: &[String]) -> u16 { | |
| 27 | 27 | 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, | |
| 29 | 29 | "hlt" => 1, | |
| 30 | 30 | _ => panic!("Unknown instruction {}", tokens[0]), | |
| 31 | 31 | } | |
| @@ -153,6 +153,25 @@ pub fn assembler(source: &str) -> Vec<u8> { | |||
| 153 | 153 | } | |
| 154 | 154 | } | |
| 155 | 155 | ||
| 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 | + | ||
| 156 | 175 | "hlt" => { | |
| 157 | 176 | bytes.push(Instruction::HLT as u8); | |
| 158 | 177 | } | |
| @@ -51,6 +51,8 @@ impl CPU { | |||
| 51 | 51 | x if x == Instruction::JNZ as u8 => self.jnz(mem), | |
| 52 | 52 | x if x == Instruction::CMP_RI as u8 => self.cmp_ri(mem), | |
| 53 | 53 | 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), | |
| 54 | 56 | x if x == Instruction::HLT as u8 => self.halt(), | |
| 55 | 57 | _ => panic!("Unknown opcode {:02X}", opcode), | |
| 56 | 58 | } | |
| @@ -298,6 +300,42 @@ impl CPU { | |||
| 298 | 300 | self.carry = borrow; | |
| 299 | 301 | } | |
| 300 | 302 | ||
| 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 | + | } | |
| 301 | 339 | ||
| 302 | 340 | fn get_reg(&self, r: u8) -> u8 { | |
| 303 | 341 | match r { | |
| @@ -305,7 +343,7 @@ impl CPU { | |||
| 305 | 343 | 1 => self.b, | |
| 306 | 344 | 2 => self.c, | |
| 307 | 345 | 3 => self.d, | |
| 308 | − | _ => 0, | |
| 346 | + | _ => panic!("Invalid Register"), | |
| 309 | 347 | } | |
| 310 | 348 | } | |
| 311 | 349 | ||
| @@ -315,7 +353,7 @@ impl CPU { | |||
| 315 | 353 | 1 => self.b = val, | |
| 316 | 354 | 2 => self.c = val, | |
| 317 | 355 | 3 => self.d = val, | |
| 318 | − | _ => {}, | |
| 356 | + | _ => panic!("Invalid register"), | |
| 319 | 357 | } | |
| 320 | 358 | } | |
| 321 | 359 | ||
| @@ -12,6 +12,8 @@ pub enum Instruction { | |||
| 12 | 12 | JNZ = 0x06, | |
| 13 | 13 | CMP_RI = 0x07, | |
| 14 | 14 | CMP_RR = 0x09, | |
| 15 | + | MUL = 0x0C, | |
| 16 | + | DIV = 0x0D, | |
| 15 | 17 | HLT = 0xFF, | |
| 16 | 18 | } | |
| 17 | 19 | ||
| @@ -25,6 +27,8 @@ impl Instruction { | |||
| 25 | 27 | 0x05 => "JZ", | |
| 26 | 28 | 0x06 => "JNZ", | |
| 27 | 29 | 0x07 | 0x09 => "CMP", | |
| 30 | + | 0x0C => "MUL", | |
| 31 | + | 0x0D => "DIV", | |
| 28 | 32 | 0xFF => "HLT", | |
| 29 | 33 | _ => "???", | |
| 30 | 34 | } | |