From e0745e149f81f0927e71168f78d5d5ad2bf57298 Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Sat, 18 Nov 2023 19:22:31 -0500 Subject: [PATCH] Add complement A register instruction --- src/cpu/instructions/misc.rs | 1 + src/cpu/parse/misc.rs | 11 +++++ src/cpu/run/misc.rs | 25 ++++++++++- .../cpu/jsmoo/testdata/{disabled => }/2f.json | 0 tests/cpu/misc.rs | 41 ++++++++++++++++++- 5 files changed, 75 insertions(+), 3 deletions(-) rename tests/cpu/jsmoo/testdata/{disabled => }/2f.json (100%) diff --git a/src/cpu/instructions/misc.rs b/src/cpu/instructions/misc.rs index 4815ac9..a2aadf6 100644 --- a/src/cpu/instructions/misc.rs +++ b/src/cpu/instructions/misc.rs @@ -4,4 +4,5 @@ pub enum MiscInstruction { SetCarryFlag, ComplementCarryFlag, + ComplementARegister, } diff --git a/src/cpu/parse/misc.rs b/src/cpu/parse/misc.rs index 967d81a..6d8a188 100644 --- a/src/cpu/parse/misc.rs +++ b/src/cpu/parse/misc.rs @@ -12,6 +12,7 @@ impl OpcodeParser for Parser { match opcode { 0x37 => Ok(build_set_carry_flag_data()), 0x3F => Ok(build_complement_carry_flag_data()), + 0x2F => Ok(build_complement_a_register_data()), _ => Err(super::Error::UnknownOpcode(opcode)), } } @@ -36,3 +37,13 @@ fn build_complement_carry_flag_data() -> ParseOutput { 1, ) } + +fn build_complement_a_register_data() -> ParseOutput { + ( + RunnableInstruction { + instruction: Instruction::Misc(MiscInstruction::ComplementARegister), + cycles: 4, + }, + 1, + ) +} diff --git a/src/cpu/run/misc.rs b/src/cpu/run/misc.rs index d4025ba..51563e1 100644 --- a/src/cpu/run/misc.rs +++ b/src/cpu/run/misc.rs @@ -16,6 +16,23 @@ impl Run for MiscInstruction { set_flags_in_carry_bit_instruction(processor, flipped); + Ok(()) + } + MiscInstruction::ComplementARegister => { + let current_value = processor + .registers + .get_single_8bit_register(register::SingleEightBit::A); + processor + .registers + .set_single_8bit_register(register::SingleEightBit::A, !current_value); + + processor + .registers + .set_flag_bit(register::Flag::HalfCarry, 1); + processor + .registers + .set_flag_bit(register::Flag::Subtract, 1); + Ok(()) } } @@ -27,6 +44,10 @@ fn set_flags_in_carry_bit_instruction(processor: &mut Processor, carry_flag: u8) .registers .set_flag_bit(register::Flag::Carry, carry_flag); - processor.registers.set_flag_bit(register::Flag::HalfCarry, 0); - processor.registers.set_flag_bit(register::Flag::Subtract, 0); + processor + .registers + .set_flag_bit(register::Flag::HalfCarry, 0); + processor + .registers + .set_flag_bit(register::Flag::Subtract, 0); } diff --git a/tests/cpu/jsmoo/testdata/disabled/2f.json b/tests/cpu/jsmoo/testdata/2f.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/2f.json rename to tests/cpu/jsmoo/testdata/2f.json diff --git a/tests/cpu/misc.rs b/tests/cpu/misc.rs index de1bd46..4c78db3 100644 --- a/tests/cpu/misc.rs +++ b/tests/cpu/misc.rs @@ -1,9 +1,9 @@ +use crate::testutil; use ferris_boi::{ cpu::{instructions::RunnableInstruction, Processor}, register, }; use test_case::test_case; -use crate::testutil; #[test_case(1)] #[test_case(0)] @@ -66,3 +66,42 @@ fn test_all_carry_bit_instructions_adjust_flags(opcode: u8) { (register::Flag::Zero, 1), ); } + +#[test] +fn test_complement_a_register_value() { + let mut processor = Processor::default(); + processor.registers.a = 0xF0; + + let data = [0x2F, 0x03]; + let (ins, extra_data) = + RunnableInstruction::from_data(&data).expect("could not parse instruction"); + + assert_eq!(extra_data, &[0x03]); + processor.run_instruction(&ins); + + assert_eq!(0x0F, processor.registers.a); +} + +#[test] +fn test_complement_a_register_flags() { + let mut processor = Processor::default(); + processor.registers.a = 0xF0; + testutil::set_opposite_of_expected_flags(&mut processor, (0, 1, 1, 0)); + + let data = [0x2F, 0x03]; + let (ins, extra_data) = + RunnableInstruction::from_data(&data).expect("could not parse instruction"); + + assert_eq!(extra_data, &[0x03]); + processor.run_instruction(&ins); + + testutil::assert_flags_eq!( + processor, + // Always 1 + (register::Flag::HalfCarry, 1), + (register::Flag::Subtract, 1), + // Value is preserved + (register::Flag::Carry, 1), + (register::Flag::Zero, 1), + ); +}