From e770cfccab079f0276e4eb9016fbdde3eed0b6f1 Mon Sep 17 00:00:00 2001 From: pcasaretto Date: Wed, 10 Apr 2024 14:08:15 -0300 Subject: [PATCH] adc_mem_at_hl --- src/instructions/adc.rs | 124 ++++++++++++++++++++++++++++++++++++++-- src/instructions/mod.rs | 1 + 2 files changed, 121 insertions(+), 4 deletions(-) diff --git a/src/instructions/adc.rs b/src/instructions/adc.rs index ffd28d7..ad1a0aa 100644 --- a/src/instructions/adc.rs +++ b/src/instructions/adc.rs @@ -2,18 +2,36 @@ use super::super::*; pub fn adc(target: RegisterTarget) -> impl Fn(&mut CPU) { move |cpu: &mut CPU| { - let mut target_value = cpu.registers.get_u8(target); + let mut addend = cpu.registers.get_u8(target); let current_value = cpu.registers.a; if cpu.registers.f.carry { - target_value += 1; + addend += 1; } - let (new_value, did_overflow) = current_value.overflowing_add(target_value); + let (new_value, did_overflow) = current_value.overflowing_add(addend); cpu.registers.a = new_value; cpu.registers.f.carry = did_overflow; cpu.registers.f.subtract = false; cpu.registers.f.zero = new_value == 0; - cpu.registers.f.half_carry = (current_value & 0xF) + (target_value & 0xF) > 0xF; + cpu.registers.f.half_carry = (current_value & 0xF) + (addend & 0xF) > 0xF; + } +} + +pub fn adc_mem_at_hl() -> impl Fn(&mut CPU) { + move |cpu: &mut CPU| { + let addr = cpu.registers.get_u16(Register16bTarget::HL); + let mut addend = cpu.bus.read_byte(addr); + let current_value = cpu.registers.get_u8(RegisterTarget::A); + if cpu.registers.f.carry { + addend += 1; + } + let (new_value, did_overflow) = current_value.overflowing_add(addend); + cpu.registers.set_u8(RegisterTarget::A, new_value); + + cpu.registers.f.carry = did_overflow; + cpu.registers.f.subtract = false; + cpu.registers.f.zero = new_value == 0; + cpu.registers.f.half_carry = (current_value & 0xF) + (addend & 0xF) > 0xF; } } @@ -131,4 +149,102 @@ mod tests { adc(RegisterTarget::C)(&mut cpu); assert!(cpu.registers.f.half_carry); } + + #[test] + fn test_adc_mem_at_r16() { + let mut cpu = CPU { + registers: Registers { + a: 34, + h: 0xFF, + l: 0xDA, + ..Default::default() + }, + ..Default::default() + }; + cpu.bus.write_byte(0xFFDA, 13); + adc_mem_at_hl()(&mut cpu); + assert_eq!(cpu.registers.a, 47); + } + + #[test] + fn test_adc_mem_at_r16_carry() { + let mut cpu = CPU { + registers: Registers { + a: 34, + h: 0xFF, + l: 0xDA, + ..Default::default() + }, + ..Default::default() + }; + cpu.registers.f.carry = true; + cpu.bus.write_byte(0xFFDA, 13); + adc_mem_at_hl()(&mut cpu); + assert_eq!(cpu.registers.a, 48); + } + + #[test] + fn test_adc_mem_at_hl_carry_flag() { + let mut cpu = CPU { + registers: Registers { + a: 0xFF, + h: 0xFF, + l: 0xDA, + ..Default::default() + }, + ..Default::default() + }; + cpu.bus.write_byte(0xFFDA, 13); + adc_mem_at_hl()(&mut cpu); + assert!(cpu.registers.f.carry); + } + + #[test] + fn test_adc_mem_at_hl_zero_flag() { + let mut cpu = CPU { + registers: Registers { + a: 0xF0, + h: 0xFF, + l: 0xDA, + ..Default::default() + }, + ..Default::default() + }; + cpu.bus.write_byte(0xFFDA, 0x10); + adc_mem_at_hl()(&mut cpu); + assert!(cpu.registers.f.zero); + } + + #[test] + fn test_adc_mem_at_hl_substract_flag() { + let mut cpu = CPU { + registers: Registers { + a: 0xF0, + h: 0xFF, + l: 0xDA, + ..Default::default() + }, + ..Default::default() + }; + cpu.registers.f.subtract = true; + cpu.bus.write_byte(0xFFDA, 0x10); + adc_mem_at_hl()(&mut cpu); + assert!(!cpu.registers.f.subtract); + } + + #[test] + fn test_adc_mem_at_hl_half_carry_flag() { + let mut cpu = CPU { + registers: Registers { + a: 0x0F, + h: 0xFF, + l: 0xDA, + ..Default::default() + }, + ..Default::default() + }; + cpu.bus.write_byte(0xFFDA, 1); + adc_mem_at_hl()(&mut cpu); + assert!(cpu.registers.f.half_carry); + } } diff --git a/src/instructions/mod.rs b/src/instructions/mod.rs index 7f5cc5b..4c5d700 100644 --- a/src/instructions/mod.rs +++ b/src/instructions/mod.rs @@ -134,6 +134,7 @@ pub fn from_byte(byte: u8) -> Box { 0x83 => Box::new(add::add(RegisterTarget::E)), 0x84 => Box::new(add::add(RegisterTarget::H)), 0x85 => Box::new(add::add(RegisterTarget::L)), + 0x8E => Box::new(adc::adc_mem_at_hl()), 0x8F => Box::new(adc::adc(RegisterTarget::A)), 0x88 => Box::new(adc::adc(RegisterTarget::B)), 0x89 => Box::new(adc::adc(RegisterTarget::C)),