add MUL & DIV
This commit is contained in:
parent
68d85406ef
commit
3372e774e9
|
|
@ -47,6 +47,8 @@ cargo run -- --f <examples/filename.asc>
|
||||||
- [x] Add label support (supporting JMP/JZ/JNZ)
|
- [x] Add label support (supporting JMP/JZ/JNZ)
|
||||||
- [ ] Add instructions
|
- [ ] Add instructions
|
||||||
- [x] CMP
|
- [x] CMP
|
||||||
|
- [x] MUL
|
||||||
|
- [x] DIV
|
||||||
- [ ] CALL
|
- [ ] CALL
|
||||||
- [ ] RET
|
- [ ] RET
|
||||||
- [ ] Error handling
|
- [ ] Error handling
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
mov a, 10
|
||||||
|
mov b, 2
|
||||||
|
div a, b
|
||||||
|
hlt
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
mov a, 99
|
||||||
|
mov b, 99
|
||||||
|
mul a, b
|
||||||
|
hlt
|
||||||
|
|
@ -25,7 +25,7 @@ fn is_reg(s: &str) -> bool {
|
||||||
|
|
||||||
fn instr_size(tokens: &[String]) -> u16 {
|
fn instr_size(tokens: &[String]) -> u16 {
|
||||||
match tokens[0].as_str() {
|
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,
|
"hlt" => 1,
|
||||||
_ => panic!("Unknown instruction {}", tokens[0]),
|
_ => panic!("Unknown instruction {}", tokens[0]),
|
||||||
}
|
}
|
||||||
|
|
@ -153,6 +153,25 @@ pub fn assembler(source: &str) -> Vec<u8> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"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" => {
|
"hlt" => {
|
||||||
bytes.push(Instruction::HLT as u8);
|
bytes.push(Instruction::HLT as u8);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
src/cpu.rs
42
src/cpu.rs
|
|
@ -51,6 +51,8 @@ impl CPU {
|
||||||
x if x == Instruction::JNZ as u8 => self.jnz(mem),
|
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_RI as u8 => self.cmp_ri(mem),
|
||||||
x if x == Instruction::CMP_RR as u8 => self.cmp_rr(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(),
|
x if x == Instruction::HLT as u8 => self.halt(),
|
||||||
_ => panic!("Unknown opcode {:02X}", opcode),
|
_ => panic!("Unknown opcode {:02X}", opcode),
|
||||||
}
|
}
|
||||||
|
|
@ -298,6 +300,42 @@ impl CPU {
|
||||||
self.carry = borrow;
|
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 {
|
fn get_reg(&self, r: u8) -> u8 {
|
||||||
match r {
|
match r {
|
||||||
|
|
@ -305,7 +343,7 @@ impl CPU {
|
||||||
1 => self.b,
|
1 => self.b,
|
||||||
2 => self.c,
|
2 => self.c,
|
||||||
3 => self.d,
|
3 => self.d,
|
||||||
_ => 0,
|
_ => panic!("Invalid Register"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -315,7 +353,7 @@ impl CPU {
|
||||||
1 => self.b = val,
|
1 => self.b = val,
|
||||||
2 => self.c = val,
|
2 => self.c = val,
|
||||||
3 => self.d = val,
|
3 => self.d = val,
|
||||||
_ => {},
|
_ => panic!("Invalid register"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ pub enum Instruction {
|
||||||
JNZ = 0x06,
|
JNZ = 0x06,
|
||||||
CMP_RI = 0x07,
|
CMP_RI = 0x07,
|
||||||
CMP_RR = 0x09,
|
CMP_RR = 0x09,
|
||||||
|
MUL = 0x0C,
|
||||||
|
DIV = 0x0D,
|
||||||
HLT = 0xFF,
|
HLT = 0xFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,6 +27,8 @@ impl Instruction {
|
||||||
0x05 => "JZ",
|
0x05 => "JZ",
|
||||||
0x06 => "JNZ",
|
0x06 => "JNZ",
|
||||||
0x07 | 0x09 => "CMP",
|
0x07 | 0x09 => "CMP",
|
||||||
|
0x0C => "MUL",
|
||||||
|
0x0D => "DIV",
|
||||||
0xFF => "HLT",
|
0xFF => "HLT",
|
||||||
_ => "???",
|
_ => "???",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue