refactor the cpu logic to cpu module
This commit is contained in:
parent
4809d7159f
commit
798ac8ce75
113
src/cpu.rs
113
src/cpu.rs
|
|
@ -1,3 +1,5 @@
|
||||||
|
use crate::memory::{self, Memory};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CPU{
|
pub struct CPU{
|
||||||
|
|
@ -19,4 +21,115 @@ impl CPU {
|
||||||
pub fn inc_cp(&mut self) {
|
pub fn inc_cp(&mut self) {
|
||||||
self.pc += 1;
|
self.pc += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn halt(&mut self) {
|
||||||
|
self.halted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mov(&mut self, mem: &mut Memory) {
|
||||||
|
let reg = mem.read(self.pc); self.inc_cp();
|
||||||
|
let val = mem.read(self.pc); self.inc_cp();
|
||||||
|
|
||||||
|
match reg {
|
||||||
|
0 => self.a = val,
|
||||||
|
1 => self.b = val,
|
||||||
|
2 => self.c = val,
|
||||||
|
3 => self.d = val,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, mem:&mut Memory) {
|
||||||
|
|
||||||
|
let dest = mem.read(self.pc); self.pc += 1;
|
||||||
|
let src = mem.read(self.pc); self.pc += 1;
|
||||||
|
|
||||||
|
let (result, carry) = match (dest, src) {
|
||||||
|
// What the fuck do these tuples mean?
|
||||||
|
// so basically they are the numbers assigned to register
|
||||||
|
// 0 => A, 1 => B ....
|
||||||
|
// so when it is (0, 0), it basically says add the
|
||||||
|
// value of register B into register A,
|
||||||
|
// thats exactly whats replicated in the code below
|
||||||
|
(0, 0) => self.a.overflowing_add(self.a),
|
||||||
|
(0, 1) => self.a.overflowing_add(self.b),
|
||||||
|
(0, 2) => self.a.overflowing_add(self.c),
|
||||||
|
(0, 3) => self.a.overflowing_add(self.d),
|
||||||
|
|
||||||
|
(1, 0) => self.b.overflowing_add(self.a),
|
||||||
|
(1, 1) => self.b.overflowing_add(self.b),
|
||||||
|
(1, 2) => self.b.overflowing_add(self.c),
|
||||||
|
(1, 3) => self.b.overflowing_add(self.d),
|
||||||
|
|
||||||
|
(2, 0) => self.c.overflowing_add(self.a),
|
||||||
|
(2, 1) => self.c.overflowing_add(self.b),
|
||||||
|
(2, 2) => self.c.overflowing_add(self.c),
|
||||||
|
(2, 3) => self.c.overflowing_add(self.d),
|
||||||
|
|
||||||
|
(3, 0) => self.d.overflowing_add(self.a),
|
||||||
|
(3, 1) => self.d.overflowing_add(self.b),
|
||||||
|
(3, 2) => self.d.overflowing_add(self.c),
|
||||||
|
(3, 3) => self.d.overflowing_add(self.d),
|
||||||
|
|
||||||
|
_ => (0, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
match dest {
|
||||||
|
0 => self.a = result,
|
||||||
|
1 => self.b = result,
|
||||||
|
2 => self.c = result,
|
||||||
|
3 => self.d = result,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.zero = result == 0;
|
||||||
|
self.carry = carry;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sub(&mut self, mem: &mut Memory) {
|
||||||
|
let dest = mem.read(self.pc); self.pc += 1;
|
||||||
|
let src = mem.read(self.pc); self.pc += 1;
|
||||||
|
|
||||||
|
let (result, borrow) = match (dest, src) {
|
||||||
|
// What the fuck do these tuples mean?
|
||||||
|
// so basically they are the numbers assigned to register
|
||||||
|
// 0 => A, 1 => B ....
|
||||||
|
// so when it is (0, 0), it basically says add the
|
||||||
|
// value of register B into register A,
|
||||||
|
// thats exactly whats replicated in the code below
|
||||||
|
(0, 0) => self.a.overflowing_sub(self.a),
|
||||||
|
(0, 1) => self.a.overflowing_sub(self.b),
|
||||||
|
(0, 2) => self.a.overflowing_sub(self.c),
|
||||||
|
(0, 3) => self.a.overflowing_sub(self.d),
|
||||||
|
|
||||||
|
(1, 0) => self.b.overflowing_sub(self.a),
|
||||||
|
(1, 1) => self.b.overflowing_sub(self.b),
|
||||||
|
(1, 2) => self.b.overflowing_sub(self.c),
|
||||||
|
(1, 3) => self.b.overflowing_sub(self.d),
|
||||||
|
|
||||||
|
(2, 0) => self.c.overflowing_sub(self.a),
|
||||||
|
(2, 1) => self.c.overflowing_sub(self.b),
|
||||||
|
(2, 2) => self.c.overflowing_sub(self.c),
|
||||||
|
(2, 3) => self.c.overflowing_sub(self.d),
|
||||||
|
|
||||||
|
(3, 0) => self.d.overflowing_sub(self.a),
|
||||||
|
(3, 1) => self.d.overflowing_sub(self.b),
|
||||||
|
(3, 2) => self.d.overflowing_sub(self.c),
|
||||||
|
(3, 3) => self.d.overflowing_sub(self.d),
|
||||||
|
|
||||||
|
_ => (0, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
match dest {
|
||||||
|
0 => self.a = result,
|
||||||
|
1 => self.b = result,
|
||||||
|
2 => self.c = result,
|
||||||
|
3 => self.d = result,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.zero = result == 0;
|
||||||
|
self.carry = borrow;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
121
src/main.rs
121
src/main.rs
|
|
@ -20,7 +20,7 @@ fn main() {
|
||||||
// b = 2
|
// b = 2
|
||||||
mem.write(0x0003, Instruction::MOV as u8);
|
mem.write(0x0003, Instruction::MOV as u8);
|
||||||
mem.write(0x0004, 1);
|
mem.write(0x0004, 1);
|
||||||
mem.write(0x0005, 10);
|
mem.write(0x0005, 1);
|
||||||
|
|
||||||
// a = a + b
|
// a = a + b
|
||||||
mem.write(0x0006, Instruction::SUB as u8);
|
mem.write(0x0006, Instruction::SUB as u8);
|
||||||
|
|
@ -40,123 +40,12 @@ fn main() {
|
||||||
cpu.inc_cp();
|
cpu.inc_cp();
|
||||||
|
|
||||||
match opcode {
|
match opcode {
|
||||||
x if x == Instruction::MOV as u8 => {
|
x if x == Instruction::MOV as u8 => cpu.mov(&mut mem),
|
||||||
let reg = mem.read(cpu.pc); cpu.inc_cp();
|
x if x == Instruction::ADD as u8 => cpu.add(&mut mem),
|
||||||
let val = mem.read(cpu.pc); cpu.inc_cp();
|
x if x == Instruction::SUB as u8 => cpu.sub(&mut mem),
|
||||||
|
|
||||||
match reg {
|
|
||||||
0 => cpu.a = val,
|
|
||||||
1 => cpu.b = val,
|
|
||||||
2 => cpu.c = val,
|
|
||||||
3 => cpu.d = val,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
x if x == Instruction::ADD as u8 => {
|
|
||||||
let dest = mem.read(cpu.pc); cpu.pc += 1;
|
|
||||||
let src = mem.read(cpu.pc); cpu.pc += 1;
|
|
||||||
|
|
||||||
let (result, carry) = match (dest, src) {
|
|
||||||
// What the fuck do these tuples mean?
|
|
||||||
// so basically they are the numbers assigned to register
|
|
||||||
// 0 => A, 1 => B ....
|
|
||||||
// so when it is (0, 0), it basically says add the
|
|
||||||
// value of register B into register A,
|
|
||||||
// thats exactly whats replicated in the code below
|
|
||||||
(0, 0) => cpu.a.overflowing_add(cpu.a),
|
|
||||||
(0, 1) => cpu.a.overflowing_add(cpu.b),
|
|
||||||
(0, 2) => cpu.a.overflowing_add(cpu.c),
|
|
||||||
(0, 3) => cpu.a.overflowing_add(cpu.d),
|
|
||||||
|
|
||||||
(1, 0) => cpu.b.overflowing_add(cpu.a),
|
|
||||||
(1, 1) => cpu.b.overflowing_add(cpu.b),
|
|
||||||
(1, 2) => cpu.b.overflowing_add(cpu.c),
|
|
||||||
(1, 3) => cpu.b.overflowing_add(cpu.d),
|
|
||||||
|
|
||||||
(2, 0) => cpu.c.overflowing_add(cpu.a),
|
|
||||||
(2, 1) => cpu.c.overflowing_add(cpu.b),
|
|
||||||
(2, 2) => cpu.c.overflowing_add(cpu.c),
|
|
||||||
(2, 3) => cpu.c.overflowing_add(cpu.d),
|
|
||||||
|
|
||||||
(3, 0) => cpu.d.overflowing_add(cpu.a),
|
|
||||||
(3, 1) => cpu.d.overflowing_add(cpu.b),
|
|
||||||
(3, 2) => cpu.d.overflowing_add(cpu.c),
|
|
||||||
(3, 3) => cpu.d.overflowing_add(cpu.d),
|
|
||||||
|
|
||||||
_ => (0, false),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
match dest {
|
|
||||||
0 => cpu.a = result,
|
|
||||||
1 => cpu.b = result,
|
|
||||||
2 => cpu.c = result,
|
|
||||||
3 => cpu.d = result,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu.zero = result == 0;
|
|
||||||
cpu.carry = carry;
|
|
||||||
}
|
|
||||||
x if x == Instruction::SUB as u8 => {
|
|
||||||
let dest = mem.read(cpu.pc); cpu.pc += 1;
|
|
||||||
let src = mem.read(cpu.pc); cpu.pc += 1;
|
|
||||||
|
|
||||||
let (result, borrow) = match (dest, src) {
|
|
||||||
// What the fuck do these tuples mean?
|
|
||||||
// so basically they are the numbers assigned to register
|
|
||||||
// 0 => A, 1 => B ....
|
|
||||||
// so when it is (0, 0), it basically says add the
|
|
||||||
// value of register B into register A,
|
|
||||||
// thats exactly whats replicated in the code below
|
|
||||||
(0, 0) => cpu.a.overflowing_sub(cpu.a),
|
|
||||||
(0, 1) => cpu.a.overflowing_sub(cpu.b),
|
|
||||||
(0, 2) => cpu.a.overflowing_sub(cpu.c),
|
|
||||||
(0, 3) => cpu.a.overflowing_sub(cpu.d),
|
|
||||||
|
|
||||||
(1, 0) => cpu.b.overflowing_sub(cpu.a),
|
|
||||||
(1, 1) => cpu.b.overflowing_sub(cpu.b),
|
|
||||||
(1, 2) => cpu.b.overflowing_sub(cpu.c),
|
|
||||||
(1, 3) => cpu.b.overflowing_sub(cpu.d),
|
|
||||||
|
|
||||||
(2, 0) => cpu.c.overflowing_sub(cpu.a),
|
|
||||||
(2, 1) => cpu.c.overflowing_sub(cpu.b),
|
|
||||||
(2, 2) => cpu.c.overflowing_sub(cpu.c),
|
|
||||||
(2, 3) => cpu.c.overflowing_sub(cpu.d),
|
|
||||||
|
|
||||||
(3, 0) => cpu.d.overflowing_sub(cpu.a),
|
|
||||||
(3, 1) => cpu.d.overflowing_sub(cpu.b),
|
|
||||||
(3, 2) => cpu.d.overflowing_sub(cpu.c),
|
|
||||||
(3, 3) => cpu.d.overflowing_sub(cpu.d),
|
|
||||||
|
|
||||||
_ => (0, false),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
match dest {
|
|
||||||
0 => cpu.a = result,
|
|
||||||
1 => cpu.b = result,
|
|
||||||
2 => cpu.c = result,
|
|
||||||
3 => cpu.d = result,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu.zero = result == 0;
|
|
||||||
cpu.carry = borrow;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
x if x == Instruction::JMP as u8 => {}
|
x if x == Instruction::JMP as u8 => {}
|
||||||
|
|
||||||
x if x == Instruction::JZ as u8 => {}
|
x if x == Instruction::JZ as u8 => {}
|
||||||
|
x if x == Instruction::HLT as u8 => cpu.halt(),
|
||||||
x if x == Instruction::HLT as u8 => {
|
|
||||||
cpu.halted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => panic!("Unknown opcode {:02X}", opcode),
|
_ => panic!("Unknown opcode {:02X}", opcode),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue