From 8952ff3546692b79170677a952d6b06cd84fa55b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com> Date: Sat, 25 Jun 2022 17:23:07 +0100 Subject: [PATCH] feat: more instructions added --- src/cpu.rs | 202 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 164 insertions(+), 38 deletions(-) diff --git a/src/cpu.rs b/src/cpu.rs index f655d593..7034b441 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -1,10 +1,17 @@ pub const RAM_SIZE: usize = 8192; -pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 4] = [ +pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 11] = [ // 0x0 opcodes (nop, 4, "NOP"), (ld_bc_u16, 12, "LD BC, NN"), - (ld_bc_a, 8, "LD BC, A"), + (ld_mbc_a, 8, "LD [BC], A"), + (inc_bc, 8, "INC BC"), + (inc_b, 4, "INC B"), + (dec_b, 4, "DEC B"), + (ld_b_u8, 8, "LD B, N"), + (rlca, 4, "RLCA"), + (ld_mu16_sp, 20, "LD [u16], SP"), + (add_hl_bc, 8, "ADD HL, BC"), // 0x2 opcodes (ld_sp_u16, 12, "LD SP, NN"), ]; @@ -12,14 +19,17 @@ pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 4] = [ pub struct Cpu { pc: u16, sp: u16, - reg_a: u8, - reg_b: u8, - reg_c: u8, - reg_d: u8, - reg_e: u8, - reg_f: u8, - reg_h: u8, - reg_l: u8, + a: u8, + b: u8, + c: u8, + d: u8, + e: u8, + h: u8, + l: u8, + zero: bool, + sub: bool, + half_carry: bool, + carry: bool, ram: [u8; RAM_SIZE], } @@ -28,14 +38,17 @@ impl Cpu { Cpu { pc: 0x0, sp: 0x0, - reg_a: 0x0, - reg_b: 0x0, - reg_c: 0x0, - reg_d: 0x0, - reg_e: 0x0, - reg_f: 0x0, - reg_h: 0x0, - reg_l: 0x0, + a: 0x0, + b: 0x0, + c: 0x0, + d: 0x0, + e: 0x0, + h: 0x0, + l: 0x0, + zero: false, + sub: false, + half_carry: false, + carry: false, ram: [0u8; RAM_SIZE], } } @@ -43,74 +56,187 @@ impl Cpu { pub fn clock(&mut self) { // fetches the current instruction and increments // the PC (program counter) accordingly - let instruction = self.ram[self.pc as usize]; + let _instruction = self.ram[self.pc as usize]; self.pc += 1; } #[inline(always)] - fn reg_af(&self) -> u16 { - (self.reg_a as u16) << 8 | self.reg_f as u16 + fn af(&self) -> u16 { + (self.a as u16) << 8 | self.f() as u16 } #[inline(always)] - fn reg_bc(&self) -> u16 { - (self.reg_b as u16) << 8 | self.reg_c as u16 + fn bc(&self) -> u16 { + (self.b as u16) << 8 | self.c as u16 } #[inline(always)] - fn reg_de(&self) -> u16 { - (self.reg_d as u16) << 8 | self.reg_e as u16 + fn f(&self) -> u8 { + let mut f = 0x0u8; + if self.zero { + f |= 0x80; + } + if self.sub { + f |= 0x40; + } + if self.half_carry { + f |= 0x20; + } + if self.carry { + f |= 0x10; + } + f + } + + #[inline(always)] + fn set_bc(&mut self, value: u16) { + self.b = (value >> 8) as u8; + self.c = value as u8; + } + + #[inline(always)] + fn de(&self) -> u16 { + (self.d as u16) << 8 | self.e as u16 + } + + #[inline(always)] + fn set_de(&mut self, value: u16) { + self.d = (value >> 8) as u8; + self.e = value as u8; } #[inline(always)] - fn reg_hl(&self) -> u16 { - (self.reg_h as u16) << 8 | self.reg_l as u16 + fn hl(&self) -> u16 { + (self.h as u16) << 8 | self.l as u16 + } + + #[inline(always)] + fn set_hl(&mut self, value: u16) { + self.h = (value >> 8) as u8; + self.l = value as u8; } #[inline(always)] fn read_u8(&mut self) -> u8 { let byte = self.ram[self.pc as usize]; - self.pc += 1; + self.pc = self.pc.wrapping_add(1); byte } #[inline(always)] fn read_u16(&mut self) -> u16 { - let word = (self.ram[self.pc as usize] as u16) << 8 | self.ram[self.pc as usize + 1] as u16; - self.pc += 2; + let byte1 = self.read_u8(); + let byte2 = self.read_u8(); + let word = byte1 as u16 | ((byte2 as u16) << 8); word } #[inline(always)] fn get_zero(&self) -> bool { - self.reg_f & 0x40 == 1 + self.zero + } + + #[inline(always)] + fn set_zero(&mut self, value: bool) { + self.zero = value } #[inline(always)] fn get_sub(&self) -> bool { - self.reg_f & 0x20 == 1 + self.sub + } + + #[inline(always)] + fn set_sub(&mut self, value: bool) { + self.sub = value; } #[inline(always)] fn get_half_carry(&self) -> bool { - self.reg_f & 0x10 == 1 + self.half_carry + } + + #[inline(always)] + fn set_half_carry(&mut self, value: bool) { + self.half_carry = value } #[inline(always)] fn get_carry(&self) -> bool { - self.reg_f & 0x08 == 1 + self.carry + } + + #[inline(always)] + fn set_carry(&mut self, value: bool) { + self.carry = value; } } fn nop(_cpu: &mut Cpu) {} fn ld_bc_u16(cpu: &mut Cpu) { - cpu.reg_b = cpu.read_u8(); - cpu.reg_c = cpu.read_u8(); + let word = cpu.read_u16(); + cpu.set_bc(word); +} + +fn ld_mbc_a(cpu: &mut Cpu) { + cpu.ram[cpu.bc() as usize] = cpu.a; +} + +fn inc_bc(cpu: &mut Cpu) { + cpu.set_bc(cpu.bc().wrapping_add(1)); } -fn ld_bc_a(cpu: &mut Cpu) { - cpu.ram[cpu.reg_bc() as usize] = cpu.reg_a; +fn inc_b(cpu: &mut Cpu) { + let value = cpu.b.wrapping_add(1); + + cpu.set_sub(false); + cpu.set_zero(value == 0); + cpu.set_half_carry((value & 0xf) == 0xf); + + cpu.b = value; +} + +fn dec_b(cpu: &mut Cpu) { + let value = cpu.b.wrapping_sub(1); + + cpu.set_sub(true); + cpu.set_zero(value == 0); + cpu.set_half_carry((value & 0xf) == 0xf); + + cpu.b = value; +} + +fn ld_b_u8(cpu: &mut Cpu) { + let byte = cpu.read_u8(); + cpu.b = byte; +} + +fn rlca(cpu: &mut Cpu) { + let carry = cpu.a >> 7; + + cpu.a = cpu.a << 1 | carry; + + cpu.set_sub(false); + cpu.set_zero(false); + cpu.set_half_carry(false); + cpu.set_carry(carry == 1); +} + +fn ld_mu16_sp(cpu: &mut Cpu) { + let word = cpu.read_u16(); + cpu.ram[word as usize] = cpu.sp as u8; + cpu.ram[word as usize + 1] = (cpu.sp >> 8) as u8; +} + +fn add_hl_bc(cpu: &mut Cpu) { + let value = cpu.hl() as u32 + cpu.bc() as u32; + + cpu.set_sub(false); + cpu.set_carry(value & 0x1000 == 0x1000); + cpu.set_half_carry((value & 0xff) == 0xff); //@todo I'm not sure about this one + + cpu.set_hl(value as u16); } fn ld_sp_u16(cpu: &mut Cpu) { -- GitLab