From c2ff461ae8ac7c541904eab54f08c95fe8f3b644 Mon Sep 17 00:00:00 2001 From: EliseZeroTwo Date: Sun, 28 Nov 2021 19:26:30 +0100 Subject: [PATCH] feat: push pop opcodes --- src/gameboy/cpu.rs | 8 ++++ src/gameboy/cpu/load_store_move.rs | 66 ++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/src/gameboy/cpu.rs b/src/gameboy/cpu.rs index 8cbf6a3..eff9468 100644 --- a/src/gameboy/cpu.rs +++ b/src/gameboy/cpu.rs @@ -239,9 +239,11 @@ pub fn tick_cpu(state: &mut Gameboy) { 0xAE => alu::xor_a_deref_hl, 0xAF => alu::xor_a_a, 0xC0 => flow::ret_nz, + 0xC1 => load_store_move::pop_bc, 0xC2 => flow::jp_nz_u16, 0xC3 => flow::jp_u16, 0xC4 => flow::call_nz_u16, + 0xC5 => load_store_move::push_bc, 0xC8 => flow::ret_z, 0xC9 => flow::ret, 0xCA => flow::jp_z_u16, @@ -249,20 +251,26 @@ pub fn tick_cpu(state: &mut Gameboy) { 0xCC => flow::call_z_u16, 0xCD => flow::call_u16, 0xD0 => flow::ret_nc, + 0xD1 => load_store_move::pop_de, 0xD2 => flow::jp_nc_u16, 0xD4 => flow::call_nc_u16, + 0xD5 => load_store_move::push_de, 0xD8 => flow::ret_c, 0xD9 => flow::reti, 0xDA => flow::jp_c_u16, 0xDC => flow::call_c_u16, 0xDE => alu::sbc_a_imm_u8, 0xE0 => load_store_move::ldh_imm_u8_a, + 0xE1 => load_store_move::pop_hl, 0xE2 => load_store_move::ldh_deref_c_a, + 0xE5 => load_store_move::push_hl, 0xE9 => flow::jp_hl, 0xEA => load_store_move::ld_deref_imm_u16_a, 0xEE => alu::xor_a_imm_u8, 0xF0 => load_store_move::ldh_a_imm_u8, + 0xF1 => load_store_move::pop_af, 0xF2 => load_store_move::ldh_a_deref_c, + 0xF5 => load_store_move::push_af, 0xF9 => load_store_move::ld_sp_hl, 0xFA => load_store_move::ld_a_deref_imm_u16, unknown => panic!("Unrecognized opcode: {:#X}\nRegisters: {:#?}", unknown, state.registers), diff --git a/src/gameboy/cpu/load_store_move.rs b/src/gameboy/cpu/load_store_move.rs index 956f1cb..614b955 100644 --- a/src/gameboy/cpu/load_store_move.rs +++ b/src/gameboy/cpu/load_store_move.rs @@ -381,7 +381,7 @@ pub fn ld_deref_imm_u16_a(state: &mut Gameboy) -> CycleResult { } } -macro_rules! define_ld_reg_imm_u8 { +macro_rules! define_ld_deref_hl_reg { ($lreg:ident) => { paste::paste! { pub fn [](state: &mut Gameboy) -> CycleResult { @@ -399,10 +399,60 @@ macro_rules! define_ld_reg_imm_u8 { }; } -define_ld_reg_imm_u8!(b); -define_ld_reg_imm_u8!(c); -define_ld_reg_imm_u8!(d); -define_ld_reg_imm_u8!(e); -define_ld_reg_imm_u8!(h); -define_ld_reg_imm_u8!(l); -define_ld_reg_imm_u8!(a); +define_ld_deref_hl_reg!(b); +define_ld_deref_hl_reg!(c); +define_ld_deref_hl_reg!(d); +define_ld_deref_hl_reg!(e); +define_ld_deref_hl_reg!(h); +define_ld_deref_hl_reg!(l); +define_ld_deref_hl_reg!(a); + +macro_rules! define_push_pop_reg { + ($reg:ident) => { + paste::paste! { + pub fn [](state: &mut Gameboy) -> CycleResult { + match state.registers.cycle { + 0 => CycleResult::NeedsMore, + 1 => { + state.cpu_push_stack((state.registers.[]() >> 8) as u8); + CycleResult::NeedsMore + }, + 2 => { + state.cpu_push_stack(state.registers.[]() as u8); + state.registers.opcode_bytecount = Some(1); + CycleResult::NeedsMore + }, + 3 => CycleResult::Finished, + _ => unreachable!(), + } + } + + pub fn [](state: &mut Gameboy) -> CycleResult { + match state.registers.cycle { + 0 => { + state.cpu_pop_stack(); + CycleResult::NeedsMore + }, + 1 => { + let lsb = state.registers.take_mem() as u16; + state.registers.set_hold(lsb); + state.cpu_pop_stack(); + CycleResult::NeedsMore + }, + 2 => { + let val = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); + state.registers.[](val); + state.registers.opcode_bytecount = Some(1); + CycleResult::Finished + }, + _ => unreachable!(), + } + } + } + }; +} + +define_push_pop_reg!(bc); +define_push_pop_reg!(de); +define_push_pop_reg!(hl); +define_push_pop_reg!(af); \ No newline at end of file