Skip to content

Commit

Permalink
Add more 16 bit arithmetic instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
choffmann committed Nov 23, 2023
1 parent 6987ff5 commit 6120688
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 142 deletions.
124 changes: 101 additions & 23 deletions src/cpu/cpu.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::cpu::instructions::{JumpCondition, Target16Bit};
use crate::cpu::registers::{Register8BitName, Registers};
use crate::cpu::registers::Registers;
use crate::memory::Memory;

use super::instructions::Instruction;
use super::instructions::Target8Bit;
use super::instructions::{Instruction, Source16Bit};
use super::registers::Register16BitName;

pub struct CPU {
pub register: Registers,
Expand All @@ -20,6 +21,7 @@ impl CPU {
memory: Memory::new(boot_rom),
}
}

pub fn execute(&mut self, instructions: Instruction) -> u16 {
match instructions {
Instruction::ADD(target) => self.match_add(target, false),
Expand All @@ -36,33 +38,43 @@ impl CPU {
Instruction::JR(jmp_condition) => self.match_jmp_condition(jmp_condition),
Instruction::JPI => self.jump(true),
Instruction::NOP => self.pc.wrapping_add(1),
Instruction::LD(target, source) => {
Instruction::DEC16(target) => self.match_dec16(target),
Instruction::ADD16(target) => self.match_add16(target),
Instruction::INC16(target) => self.match_inc16(target),
Instruction::LD8(target, source) => {
println!("[CPU] LD {:?} to {:?}", source, target);
return self.pc.wrapping_add(1);
}
Instruction::LDN(target, source) => {
let value = self.register.get_16bit(source.into());
return self.match_16bit_load(&target, value);
Instruction::LD16(target, source) => {
let value = self.match_16bit_load_source(source);
return self.match_16bit_load(target, value);
}
Instruction::LDD => {
let value = self.register.read_a();
let address_value = self.register.get_16bit(&Register16BitName::HL);
self.memory.write_byte(address_value, value);
self.match_dec16(Target16Bit::HL);
return self.pc.wrapping_add(1);
}
}
}

fn match_8bit_load(&mut self, target: Target8Bit, value: u8) -> u16 {
match target {
Target8Bit::A => self.register.set_8bit(target.into(), value),
Target8Bit::B => self.register.set_8bit(target.into(), value),
Target8Bit::C => self.register.set_8bit(target.into(), value),
Target8Bit::D => self.register.set_8bit(target.into(), value),
Target8Bit::E => self.register.set_8bit(target.into(), value),
Target8Bit::H => self.register.set_8bit(target.into(), value),
Target8Bit::L => self.register.set_8bit(target.into(), value),
Target8Bit::A
| Target8Bit::B
| Target8Bit::C
| Target8Bit::D
| Target8Bit::E
| Target8Bit::H
| Target8Bit::L => self.register.set_8bit(target.into(), value),
Target8Bit::D8 => {}
Target8Bit::HLI => {}
}
return self.pc.wrapping_add(1);
}

fn match_16bit_load(&mut self, target: &Target16Bit, value: u16) -> u16 {
fn match_16bit_load(&mut self, target: Target16Bit, value: u16) -> u16 {
match target {
Target16Bit::BC => self.register.set_16bit(target.into(), value),
Target16Bit::DE => self.register.set_16bit(target.into(), value),
Expand All @@ -72,6 +84,17 @@ impl CPU {

return self.pc.wrapping_add(3);
}

fn match_16bit_load_source(&self, source: Source16Bit) -> u16 {
match source {
Source16Bit::SP
| Source16Bit::BC
| Source16Bit::DE
| Source16Bit::HL => self.register.get_16bit(source.into()),
Source16Bit::D16 => self.memory.read_next_word(self.pc),
}
}

fn match_jmp_condition(&mut self, jump_condition: JumpCondition) -> u16 {
let should_jump = match jump_condition {
JumpCondition::NotZero => !self.register.f.zero,
Expand All @@ -93,10 +116,24 @@ impl CPU {
| Target8Bit::H
| Target8Bit::L => self.exec_add(self.register.get_8bit(target.into()), with_carry),
Target8Bit::D8 => self.exec_add(self.read_next_mem(), with_carry),
Target8Bit::HLI => todo!("Not implemented"),
Target8Bit::HLI => self.exec_add(self.get_memory_by_hl(), with_carry),
}
}

fn match_add16(&mut self, target: Target16Bit) -> u16 {
match target {
Target16Bit::BC |
Target16Bit::DE |
Target16Bit::HL |
Target16Bit::SP => {
let register: &Register16BitName = target.into();
let value = self.register.get_16bit(register);
self.register.set_16bit(register, value);
}
}
return self.pc.wrapping_add(1);
}

fn match_inc(&mut self, target: Target8Bit) -> u16 {
match target {
Target8Bit::A
Expand All @@ -107,7 +144,7 @@ impl CPU {
| Target8Bit::H
| Target8Bit::L => self.exec_inc(self.register.get_8bit(target.into())),
Target8Bit::D8 => self.exec_inc(self.read_next_mem()),
Target8Bit::HLI => todo!("Not implemented"),
Target8Bit::HLI => self.exec_inc(self.get_memory_by_hl()),
}
}

Expand All @@ -121,10 +158,38 @@ impl CPU {
| Target8Bit::H
| Target8Bit::L => self.exec_dec(self.register.get_8bit(target.into())),
Target8Bit::D8 => self.exec_dec(self.read_next_mem()),
Target8Bit::HLI => todo!("Not implemented"),
Target8Bit::HLI => self.exec_dec(self.get_memory_by_hl()),
}
}

fn match_dec16(&mut self, target: Target16Bit) -> u16 {
match target {
Target16Bit::BC |
Target16Bit::DE |
Target16Bit::HL |
Target16Bit::SP => {
let register: &Register16BitName = target.into();
let value = self.register.get_16bit(register).wrapping_sub(1);
self.register.set_16bit(register, value)
}
}
return self.pc.wrapping_add(1);
}

fn match_inc16(&mut self, target: Target16Bit) -> u16 {
match target {
Target16Bit::BC |
Target16Bit::DE |
Target16Bit::HL |
Target16Bit::SP => {
let register: &Register16BitName = target.into();
let value = self.register.get_16bit(register).wrapping_add(1);
self.register.set_16bit(register, value);
}
}
return self.pc.wrapping_add(1);
}

fn match_sub(&mut self, target: Target8Bit, with_carry: bool) -> u16 {
match target {
Target8Bit::A
Expand All @@ -135,7 +200,7 @@ impl CPU {
| Target8Bit::H
| Target8Bit::L => self.exec_sub(self.register.get_8bit(target.into()), with_carry),
Target8Bit::D8 => self.exec_sub(self.read_next_mem(), with_carry),
Target8Bit::HLI => todo!("Not implemented"),
Target8Bit::HLI => self.exec_sub(self.get_memory_by_hl(), with_carry),
}
}

Expand All @@ -149,7 +214,7 @@ impl CPU {
| Target8Bit::H
| Target8Bit::L => self.exec_and(self.register.get_8bit(target.into())),
Target8Bit::D8 => self.exec_and(self.read_next_mem()),
Target8Bit::HLI => todo!("Not implemented"),
Target8Bit::HLI => self.exec_and(self.get_memory_by_hl()),
}
}

Expand All @@ -163,7 +228,7 @@ impl CPU {
| Target8Bit::H
| Target8Bit::L => self.exec_or(self.register.get_8bit(target.into())),
Target8Bit::D8 => self.exec_or(self.read_next_mem()),
Target8Bit::HLI => todo!("Not implemented"),
Target8Bit::HLI => self.exec_or(self.get_memory_by_hl()),
}
}

Expand All @@ -177,7 +242,7 @@ impl CPU {
| Target8Bit::H
| Target8Bit::L => self.exec_xor(self.register.get_8bit(target.into())),
Target8Bit::D8 => self.exec_xor(self.read_next_mem()),
Target8Bit::HLI => todo!("Not implemented"),
Target8Bit::HLI => self.exec_xor(self.get_memory_by_hl()),
}
}

Expand All @@ -191,10 +256,15 @@ impl CPU {
| Target8Bit::H
| Target8Bit::L => self.exec_compare(self.register.get_8bit(target.into())),
Target8Bit::D8 => self.exec_compare(self.read_next_mem()),
Target8Bit::HLI => todo!("Not implemented"),
Target8Bit::HLI => self.exec_compare(self.get_memory_by_hl()),
}
}

fn get_memory_by_hl(&self) -> u8 {
let value = self.register.get_16bit(&Register16BitName::HL);
return self.memory.read_byte(value);
}

pub fn step(&mut self) {
let mut instruction_byte = self.memory.read_byte(self.pc);
let prefixed = instruction_byte == 0xcb;
Expand Down Expand Up @@ -291,6 +361,14 @@ impl CPU {
return new_value;
}

fn add_16(&mut self, value: u16) -> u16 {
let (new_value, did_overflow) = self.register.get_16bit(&Register16BitName::HL).overflowing_add(value);
self.register.f.subtract = false;
self.register.f.carry = did_overflow;
self.register.f.half_carry = (self.register.get_16bit(&Register16BitName::HL) & 0xff) + (value & 0xff) > 0xff;
return new_value;
}

fn sub(&mut self, value: u8, add_carry: bool) -> u8 {
let carry_value = self.get_opt_carry_flag(add_carry);
let (sub, first_did_overflow) = self.register.read_a().overflowing_sub(value);
Expand Down Expand Up @@ -346,7 +424,7 @@ impl CPU {
}

fn compare(&mut self, value: u8) {
let register_a = self.register.get_8bit(Register8BitName::A);
let register_a = self.register.read_a();
self.register.f.zero = register_a == value;
self.register.f.subtract = true;
self.register.f.half_carry = (register_a & 0xf) < (value & 0xf);
Expand Down
Loading

0 comments on commit 6120688

Please sign in to comment.