diff --git a/src/cpu/decode.rs b/src/cpu/decode.rs index 78ceaba..ff61bac 100644 --- a/src/cpu/decode.rs +++ b/src/cpu/decode.rs @@ -157,7 +157,7 @@ impl CPU { InstParam::Register8Bit(Register8Bit::A), ), 0x3..=0x6 => self.decode_0x0_to_0x3_commons(opcode)?, - 0x7 => Instructions::RLC(InstParam::Register8Bit(Register8Bit::A)), + 0x7 => Instructions::RLCA(), 0x8 => Instructions::LD( InstParam::Number16Bit(self.get_16bit_from_pc()), InstParam::Register16Bit(Register16Bit::SP), @@ -168,7 +168,7 @@ impl CPU { InstParam::Register16Bit(Register16Bit::BC), ), 0xB..=0xE => self.decode_0x0_to_0x3_commons(opcode)?, - 0xF => Instructions::RRC(InstParam::Register8Bit(Register8Bit::A)), + 0xF => Instructions::RRCA(), _ => self.not_implemented(opcode)?, }, 0x1 => match tail { @@ -179,7 +179,7 @@ impl CPU { InstParam::Register8Bit(Register8Bit::A), ), 0x3..=0x6 => self.decode_0x0_to_0x3_commons(opcode)?, - 0x7 => Instructions::RL(InstParam::Register8Bit(Register8Bit::A)), + 0x7 => Instructions::RLA(), 0x8 => Instructions::JR( InstParam::ConditionCodes(InstructionCondition::SkipConditionCodes), InstParam::SignedNumber8Bit(self.get_8bit_from_pc() as i8), @@ -190,7 +190,7 @@ impl CPU { InstParam::Register16Bit(Register16Bit::DE), ), 0xB..=0xE => self.decode_0x0_to_0x3_commons(opcode)?, - 0xF => Instructions::RR(InstParam::Register8Bit(Register8Bit::A)), + 0xF => Instructions::RRA(), _ => self.not_implemented(opcode)?, }, 0x2 => match tail { diff --git a/src/cpu/instructions.rs b/src/cpu/instructions.rs index c760142..6a02fbc 100644 --- a/src/cpu/instructions.rs +++ b/src/cpu/instructions.rs @@ -124,9 +124,13 @@ pub enum Instructions { RST(InstParam), RL(InstParam), + RLA(), RLC(InstParam), + RLCA(), RR(InstParam), + RRA(), RRC(InstParam), + RRCA(), SLA(InstParam), SRL(InstParam), SRA(InstParam), diff --git a/src/cpu/instructions/arithmetic_and_logic/dec.rs b/src/cpu/instructions/arithmetic_and_logic/dec.rs index 03ebf6d..7c74edf 100644 --- a/src/cpu/instructions/arithmetic_and_logic/dec.rs +++ b/src/cpu/instructions/arithmetic_and_logic/dec.rs @@ -19,18 +19,17 @@ impl CPU { /// decrements the 8bit_register pub fn dec_r8(&mut self, register: Register8Bit) -> InstructionResult { let r8_value = self.get_8bit_register(register); - let (value,overflow) = r8_value.overflowing_sub(1); - let tail = r8_value & 0xF; - self.set_8bit_register(register, value); + let (result,_) = r8_value.overflowing_sub(1); + self.set_8bit_register(register, result); InstructionResult { cycles: 1, bytes: 1, condition_codes: ConditionCodes { - zero: if value == 0 {FlagState::Set} else {FlagState::Unset}, + zero: if result == 0 {FlagState::Set} else {FlagState::Unset}, subtract: FlagState::Set, - half_carry: if tail == 0 {FlagState::Set} else {FlagState::Unset}, + half_carry: if ((r8_value ^ 1) & 0x10) != (result & 0x10) {FlagState::Set} else {FlagState::Unset}, carry: FlagState::NotAffected, }, } @@ -39,17 +38,16 @@ impl CPU { pub fn dec_hl(&mut self) -> InstructionResult { let addr = self.get_16bit_register(Register16Bit::HL); let r8_value = self.memory.read_byte(addr); - let (value,overflow) = r8_value.overflowing_sub(1); - self.memory.write_byte(addr, value); - let tail = r8_value & 0xF; + let (result,_) = r8_value.overflowing_sub(1); + self.memory.write_byte(addr, result); InstructionResult { cycles: 3, bytes: 1, condition_codes: ConditionCodes { - zero: if value == 0 {FlagState::Set} else {FlagState::Unset}, + zero: if result == 0 {FlagState::Set} else {FlagState::Unset}, subtract: FlagState::Set, - half_carry: if tail == 0 {FlagState::Set} else {FlagState::Unset}, + half_carry: if ((r8_value ^ 1) & 0x10) != (result & 0x10) {FlagState::Set} else {FlagState::Unset}, carry: FlagState::NotAffected, }, } diff --git a/src/cpu/instructions/misc.rs b/src/cpu/instructions/misc.rs index 6e547bc..a03284e 100644 --- a/src/cpu/instructions/misc.rs +++ b/src/cpu/instructions/misc.rs @@ -91,13 +91,28 @@ impl CPU { pub fn daa(&mut self) -> InstructionResult { let mut value = self.get_8bit_register(Register8Bit::A); - let mut carry = false; - if (value & 0x0F) > 9 { - value = value.wrapping_add(6); //caused overflow on testrom 1, daa doesn't seem to work correctly yet + let mut daa_correction = 0; + let mut set_carry = false; + //currently set flags + let half_carry = self.is_half_carry_flag_set(); + let carry = self.is_carry_flag_set(); + let subtraction = self.is_subtraction_flag_set(); + + if half_carry || (!subtraction && (value & 0xf) > 9) { + daa_correction |= 0x6; } - if (value & 0xF0) > 0x90 || (self.is_carry_flag_set() && (value & 0x0F) > 9) { - (value, carry) = value.overflowing_add(0x60); + if carry || (!subtraction && value > 0x99) { + daa_correction |= 0x60; + set_carry = true; } + if subtraction { + (value,_) = value.overflowing_sub(daa_correction); + }else { + (value,_) = value.overflowing_add(daa_correction); + } + + + self.set_8bit_register(Register8Bit::A, value); InstructionResult { cycles: 1, @@ -110,7 +125,7 @@ impl CPU { }, subtract: FlagState::NotAffected, half_carry: FlagState::Unset, - carry: if carry { + carry: if set_carry { FlagState::Set } else { FlagState::Unset @@ -124,7 +139,7 @@ impl CPU { cycles: 1, bytes: 1, condition_codes: ConditionCodes { - zero: FlagState::Unset, + zero: FlagState::NotAffected, subtract: FlagState::Unset, half_carry: FlagState::Unset, carry: FlagState::Set, diff --git a/src/cpu/step.rs b/src/cpu/step.rs index 5f9db6f..f6073e0 100644 --- a/src/cpu/step.rs +++ b/src/cpu/step.rs @@ -242,35 +242,28 @@ impl CPU { } _ => return Err(format!("SWAP with {:?} not implemented", target)), }, + Instructions::RLA() =>self.rl_a(), Instructions::RL(target) => match target { - InstParam::Register8Bit(register) => match register { - Register8Bit::A => self.rl_a(), - _ => self.rl_r8(*register), - }, + InstParam::Register8Bit(register) => self.rl_r8(*register), InstParam::Register16Bit(Register16Bit::HL) => self.rl_hl(), _ => return Err(format!("SWAP with {:?} not implemented", target)), }, + + Instructions::RLCA() => self.rl_c_a(),//RLCA and RLC A are two different instructions Instructions::RLC(target) => match target { - InstParam::Register8Bit(register) => match register { - Register8Bit::A => self.rl_c_a(), - _ => self.rl_c_r8(*register), - }, + InstParam::Register8Bit(register) => self.rl_c_r8(*register), InstParam::Register16Bit(Register16Bit::HL) => self.rl_c_hl(), _ => return Err(format!("RLC with {:?} not implemented", target)), }, + Instructions::RRA() => self.rr_a(), Instructions::RR(target) => match target { - InstParam::Register8Bit(register) => match register { - Register8Bit::A => self.rr_a(), - _ => self.rr_r8(*register), - }, + InstParam::Register8Bit(register) => self.rr_r8(*register), InstParam::Register16Bit(Register16Bit::HL) => self.rr_hl(), _ => return Err(format!("SWAP with {:?} not implemented", target)), }, + Instructions::RRCA() => self.rr_c_a(),//RRCA and RRC A are two different instructions Instructions::RRC(target) => match target { - InstParam::Register8Bit(register) => match register { - Register8Bit::A => self.rr_c_a(), - _ => self.rr_c_r8(*register), - }, + InstParam::Register8Bit(register) => self.rr_c_r8(*register), InstParam::Register16Bit(Register16Bit::HL) => self.rr_c_hl(), _ => return Err(format!("SWAP with {:?} not implemented", target)), },