diff --git a/src/cpu/instructions/manip.rs b/src/cpu/instructions/manip.rs index 03d8622..23981fd 100644 --- a/src/cpu/instructions/manip.rs +++ b/src/cpu/instructions/manip.rs @@ -19,4 +19,8 @@ pub enum BitManipulationInstruction { operand: Operand, bit: u8, }, + TestIndividualBit { + operand: Operand, + bit: u8, + }, } diff --git a/src/cpu/parse/manip.rs b/src/cpu/parse/manip.rs index 529a825..778ee70 100644 --- a/src/cpu/parse/manip.rs +++ b/src/cpu/parse/manip.rs @@ -19,7 +19,9 @@ impl OpcodeParser for Parser { fn parse_opcode(data: &View) -> ParseResult { let opcode = parse::get_opcode_from_data(data); - parse_set_opcode(opcode).or_parse(parse_clear_opcode) + parse_set_opcode(opcode) + .or_parse(parse_clear_opcode) + .or_parse(parse_bit_test_opcode) } } @@ -31,11 +33,32 @@ fn parse_clear_opcode(opcode: Opcode) -> ParseResult { parse_individual_bit_operation(opcode, IndividualBitOperation::Clear, 0xCB_80..=0xCB_BF) } +fn parse_bit_test_opcode(opcode: Opcode) -> ParseResult { + let (operand, bit) = decompose_bit_action_opcode(opcode, 0xCB_40..=0xCB_7F)?; + let ins = BitManipulationInstruction::TestIndividualBit { operand, bit }; + + Ok((Instruction::BitManipulation(ins), 2)) +} + fn parse_individual_bit_operation( opcode: Opcode, operation: IndividualBitOperation, opcode_range: RangeInclusive, ) -> ParseResult { + let (operand, bit) = decompose_bit_action_opcode(opcode, opcode_range)?; + let ins = BitManipulationInstruction::ManipulateIndividualBit { + operation, + operand, + bit, + }; + + Ok((Instruction::BitManipulation(ins), 2)) +} + +fn decompose_bit_action_opcode( + opcode: Opcode, + opcode_range: RangeInclusive, +) -> Result<(Operand, u8), parse::Error> { let Opcode::SixteenBit(sixteen_bit_opcode) = opcode else { return Err(parse::Error::UnknownOpcode(opcode)); }; @@ -44,15 +67,10 @@ fn parse_individual_bit_operation( return Err(parse::Error::UnknownOpcode(opcode)); } - let bit = bit_for_opcode(sixteen_bit_opcode, opcode_range)?; let operand = operand_for_opcode(sixteen_bit_opcode)?; - let ins = BitManipulationInstruction::ManipulateIndividualBit { - operation, - operand, - bit, - }; + let bit = bit_for_opcode(sixteen_bit_opcode, opcode_range)?; - Ok((Instruction::BitManipulation(ins), 2)) + Ok((operand, bit)) } fn operand_for_opcode(opcode: u16) -> Result { diff --git a/src/cpu/run/manip.rs b/src/cpu/run/manip.rs index ac3e28c..9b4f620 100644 --- a/src/cpu/run/manip.rs +++ b/src/cpu/run/manip.rs @@ -33,6 +33,24 @@ impl Run for BitManipulationInstruction { Ok(Cycles(16)) } + + BitManipulationInstruction::TestIndividualBit { + operand: Operand::Register(register), + bit, + } => { + set_test_flag_bits(processor, Operand::Register(register), bit)?; + + Ok(Cycles(8)) + } + + BitManipulationInstruction::TestIndividualBit { + operand: Operand::HLValue, + bit, + } => { + set_test_flag_bits(processor, Operand::HLValue, bit)?; + + Ok(Cycles(12)) + } } } } @@ -106,3 +124,53 @@ fn transform_hl_value u8>( Ok(()) } + +fn set_test_flag_bits( + processor: &mut Processor, + operand: Operand, + bit: u8, +) -> Result<(), run::Error> { + assert!(bit < 8, "Cannot test a bit greater than 7"); + + let operand_val = get_operand_value(processor, operand)?; + let compare_mask = 0x1 << bit; + let zero_flag = (compare_mask & operand_val) == 0; + + processor + .registers + .set_flag_bit(register::Flag::Zero, zero_flag.into()); + + processor + .registers + .set_flag_bit(register::Flag::Subtract, 0); + processor + .registers + .set_flag_bit(register::Flag::HalfCarry, 1); + + Ok(()) +} + +fn get_operand_value(processor: &mut Processor, operand: Operand) -> Result { + let val = match operand { + Operand::Register(register) => processor.registers.get_single_8bit_register(register), + Operand::HLValue => { + let hl_addr = processor + .registers + .get_combined_register(register::Combined::HL); + + #[allow(clippy::match_wildcard_for_single_variants)] + processor + .memory + .get(hl_addr.into()) + .map_err(|err| match err { + memory::Error::GetInvalidAddress(addr) => run::Error::InvalidRegisterAddress( + register::SixteenBit::Combined(register::Combined::HL), + addr, + ), + err => run::Error::Unknown(Box::new(err)), + })? + } + }; + + Ok(val) +} diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 40.json b/tests/cpu/jsmoo/testdata/cb 40.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 40.json rename to tests/cpu/jsmoo/testdata/cb 40.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 41.json b/tests/cpu/jsmoo/testdata/cb 41.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 41.json rename to tests/cpu/jsmoo/testdata/cb 41.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 42.json b/tests/cpu/jsmoo/testdata/cb 42.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 42.json rename to tests/cpu/jsmoo/testdata/cb 42.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 43.json b/tests/cpu/jsmoo/testdata/cb 43.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 43.json rename to tests/cpu/jsmoo/testdata/cb 43.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 44.json b/tests/cpu/jsmoo/testdata/cb 44.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 44.json rename to tests/cpu/jsmoo/testdata/cb 44.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 45.json b/tests/cpu/jsmoo/testdata/cb 45.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 45.json rename to tests/cpu/jsmoo/testdata/cb 45.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 46.json b/tests/cpu/jsmoo/testdata/cb 46.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 46.json rename to tests/cpu/jsmoo/testdata/cb 46.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 47.json b/tests/cpu/jsmoo/testdata/cb 47.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 47.json rename to tests/cpu/jsmoo/testdata/cb 47.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 48.json b/tests/cpu/jsmoo/testdata/cb 48.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 48.json rename to tests/cpu/jsmoo/testdata/cb 48.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 49.json b/tests/cpu/jsmoo/testdata/cb 49.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 49.json rename to tests/cpu/jsmoo/testdata/cb 49.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 4a.json b/tests/cpu/jsmoo/testdata/cb 4a.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 4a.json rename to tests/cpu/jsmoo/testdata/cb 4a.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 4b.json b/tests/cpu/jsmoo/testdata/cb 4b.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 4b.json rename to tests/cpu/jsmoo/testdata/cb 4b.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 4c.json b/tests/cpu/jsmoo/testdata/cb 4c.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 4c.json rename to tests/cpu/jsmoo/testdata/cb 4c.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 4d.json b/tests/cpu/jsmoo/testdata/cb 4d.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 4d.json rename to tests/cpu/jsmoo/testdata/cb 4d.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 4e.json b/tests/cpu/jsmoo/testdata/cb 4e.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 4e.json rename to tests/cpu/jsmoo/testdata/cb 4e.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 4f.json b/tests/cpu/jsmoo/testdata/cb 4f.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 4f.json rename to tests/cpu/jsmoo/testdata/cb 4f.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 50.json b/tests/cpu/jsmoo/testdata/cb 50.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 50.json rename to tests/cpu/jsmoo/testdata/cb 50.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 51.json b/tests/cpu/jsmoo/testdata/cb 51.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 51.json rename to tests/cpu/jsmoo/testdata/cb 51.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 52.json b/tests/cpu/jsmoo/testdata/cb 52.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 52.json rename to tests/cpu/jsmoo/testdata/cb 52.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 53.json b/tests/cpu/jsmoo/testdata/cb 53.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 53.json rename to tests/cpu/jsmoo/testdata/cb 53.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 54.json b/tests/cpu/jsmoo/testdata/cb 54.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 54.json rename to tests/cpu/jsmoo/testdata/cb 54.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 55.json b/tests/cpu/jsmoo/testdata/cb 55.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 55.json rename to tests/cpu/jsmoo/testdata/cb 55.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 56.json b/tests/cpu/jsmoo/testdata/cb 56.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 56.json rename to tests/cpu/jsmoo/testdata/cb 56.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 57.json b/tests/cpu/jsmoo/testdata/cb 57.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 57.json rename to tests/cpu/jsmoo/testdata/cb 57.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 58.json b/tests/cpu/jsmoo/testdata/cb 58.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 58.json rename to tests/cpu/jsmoo/testdata/cb 58.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 59.json b/tests/cpu/jsmoo/testdata/cb 59.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 59.json rename to tests/cpu/jsmoo/testdata/cb 59.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 5a.json b/tests/cpu/jsmoo/testdata/cb 5a.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 5a.json rename to tests/cpu/jsmoo/testdata/cb 5a.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 5b.json b/tests/cpu/jsmoo/testdata/cb 5b.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 5b.json rename to tests/cpu/jsmoo/testdata/cb 5b.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 5c.json b/tests/cpu/jsmoo/testdata/cb 5c.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 5c.json rename to tests/cpu/jsmoo/testdata/cb 5c.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 5d.json b/tests/cpu/jsmoo/testdata/cb 5d.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 5d.json rename to tests/cpu/jsmoo/testdata/cb 5d.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 5e.json b/tests/cpu/jsmoo/testdata/cb 5e.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 5e.json rename to tests/cpu/jsmoo/testdata/cb 5e.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 5f.json b/tests/cpu/jsmoo/testdata/cb 5f.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 5f.json rename to tests/cpu/jsmoo/testdata/cb 5f.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 60.json b/tests/cpu/jsmoo/testdata/cb 60.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 60.json rename to tests/cpu/jsmoo/testdata/cb 60.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 61.json b/tests/cpu/jsmoo/testdata/cb 61.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 61.json rename to tests/cpu/jsmoo/testdata/cb 61.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 62.json b/tests/cpu/jsmoo/testdata/cb 62.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 62.json rename to tests/cpu/jsmoo/testdata/cb 62.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 63.json b/tests/cpu/jsmoo/testdata/cb 63.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 63.json rename to tests/cpu/jsmoo/testdata/cb 63.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 64.json b/tests/cpu/jsmoo/testdata/cb 64.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 64.json rename to tests/cpu/jsmoo/testdata/cb 64.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 65.json b/tests/cpu/jsmoo/testdata/cb 65.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 65.json rename to tests/cpu/jsmoo/testdata/cb 65.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 66.json b/tests/cpu/jsmoo/testdata/cb 66.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 66.json rename to tests/cpu/jsmoo/testdata/cb 66.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 67.json b/tests/cpu/jsmoo/testdata/cb 67.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 67.json rename to tests/cpu/jsmoo/testdata/cb 67.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 68.json b/tests/cpu/jsmoo/testdata/cb 68.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 68.json rename to tests/cpu/jsmoo/testdata/cb 68.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 69.json b/tests/cpu/jsmoo/testdata/cb 69.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 69.json rename to tests/cpu/jsmoo/testdata/cb 69.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 6a.json b/tests/cpu/jsmoo/testdata/cb 6a.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 6a.json rename to tests/cpu/jsmoo/testdata/cb 6a.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 6b.json b/tests/cpu/jsmoo/testdata/cb 6b.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 6b.json rename to tests/cpu/jsmoo/testdata/cb 6b.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 6c.json b/tests/cpu/jsmoo/testdata/cb 6c.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 6c.json rename to tests/cpu/jsmoo/testdata/cb 6c.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 6d.json b/tests/cpu/jsmoo/testdata/cb 6d.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 6d.json rename to tests/cpu/jsmoo/testdata/cb 6d.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 6e.json b/tests/cpu/jsmoo/testdata/cb 6e.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 6e.json rename to tests/cpu/jsmoo/testdata/cb 6e.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 6f.json b/tests/cpu/jsmoo/testdata/cb 6f.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 6f.json rename to tests/cpu/jsmoo/testdata/cb 6f.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 70.json b/tests/cpu/jsmoo/testdata/cb 70.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 70.json rename to tests/cpu/jsmoo/testdata/cb 70.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 71.json b/tests/cpu/jsmoo/testdata/cb 71.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 71.json rename to tests/cpu/jsmoo/testdata/cb 71.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 72.json b/tests/cpu/jsmoo/testdata/cb 72.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 72.json rename to tests/cpu/jsmoo/testdata/cb 72.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 73.json b/tests/cpu/jsmoo/testdata/cb 73.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 73.json rename to tests/cpu/jsmoo/testdata/cb 73.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 74.json b/tests/cpu/jsmoo/testdata/cb 74.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 74.json rename to tests/cpu/jsmoo/testdata/cb 74.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 75.json b/tests/cpu/jsmoo/testdata/cb 75.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 75.json rename to tests/cpu/jsmoo/testdata/cb 75.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 76.json b/tests/cpu/jsmoo/testdata/cb 76.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 76.json rename to tests/cpu/jsmoo/testdata/cb 76.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 77.json b/tests/cpu/jsmoo/testdata/cb 77.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 77.json rename to tests/cpu/jsmoo/testdata/cb 77.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 78.json b/tests/cpu/jsmoo/testdata/cb 78.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 78.json rename to tests/cpu/jsmoo/testdata/cb 78.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 79.json b/tests/cpu/jsmoo/testdata/cb 79.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 79.json rename to tests/cpu/jsmoo/testdata/cb 79.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 7a.json b/tests/cpu/jsmoo/testdata/cb 7a.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 7a.json rename to tests/cpu/jsmoo/testdata/cb 7a.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 7b.json b/tests/cpu/jsmoo/testdata/cb 7b.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 7b.json rename to tests/cpu/jsmoo/testdata/cb 7b.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 7c.json b/tests/cpu/jsmoo/testdata/cb 7c.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 7c.json rename to tests/cpu/jsmoo/testdata/cb 7c.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 7d.json b/tests/cpu/jsmoo/testdata/cb 7d.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 7d.json rename to tests/cpu/jsmoo/testdata/cb 7d.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 7e.json b/tests/cpu/jsmoo/testdata/cb 7e.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 7e.json rename to tests/cpu/jsmoo/testdata/cb 7e.json diff --git a/tests/cpu/jsmoo/testdata/disabled/cb 7f.json b/tests/cpu/jsmoo/testdata/cb 7f.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/cb 7f.json rename to tests/cpu/jsmoo/testdata/cb 7f.json diff --git a/tests/cpu/manip.rs b/tests/cpu/manip.rs index 479216c..95a2af5 100644 --- a/tests/cpu/manip.rs +++ b/tests/cpu/manip.rs @@ -1,8 +1,10 @@ use ferris_boi::{ cpu::{instructions::Instruction, Processor}, - register::{self, SingleEightBit}, + register::{self, Flag, SingleEightBit}, }; -use test_case::test_case; +use test_case::{test_case, test_matrix}; + +use crate::testutil; #[test_case(0xC0, register::SingleEightBit::B, 0b00000001)] #[test_case(0xC8, register::SingleEightBit::B, 0b00000010)] @@ -234,3 +236,163 @@ fn test_clear_hl_value_bit(opcode_variant: u8, expected: u8) { .expect("failed to get memory value") ); } + +#[test_matrix( + [0, 1], + [ + (0x40, SingleEightBit::B, 0), + (0x41, SingleEightBit::C, 0), + (0x42, SingleEightBit::D, 0), + (0x43, SingleEightBit::E, 0), + (0x44, SingleEightBit::H, 0), + (0x45, SingleEightBit::L, 0), + (0x47, SingleEightBit::A, 0), + + (0x48, SingleEightBit::B, 1), + (0x49, SingleEightBit::C, 1), + (0x4A, SingleEightBit::D, 1), + (0x4B, SingleEightBit::E, 1), + (0x4C, SingleEightBit::H, 1), + (0x4D, SingleEightBit::L, 1), + (0x4F, SingleEightBit::A, 1), + + (0x50, SingleEightBit::B, 2), + (0x51, SingleEightBit::C, 2), + (0x52, SingleEightBit::D, 2), + (0x53, SingleEightBit::E, 2), + (0x54, SingleEightBit::H, 2), + (0x55, SingleEightBit::L, 2), + (0x57, SingleEightBit::A, 2), + + (0x58, SingleEightBit::B, 3), + (0x59, SingleEightBit::C, 3), + (0x5A, SingleEightBit::D, 3), + (0x5B, SingleEightBit::E, 3), + (0x5C, SingleEightBit::H, 3), + (0x5D, SingleEightBit::L, 3), + (0x5F, SingleEightBit::A, 3), + + (0x60, SingleEightBit::B, 4), + (0x61, SingleEightBit::C, 4), + (0x62, SingleEightBit::D, 4), + (0x63, SingleEightBit::E, 4), + (0x64, SingleEightBit::H, 4), + (0x65, SingleEightBit::L, 4), + (0x67, SingleEightBit::A, 4), + + (0x68, SingleEightBit::B, 5), + (0x69, SingleEightBit::C, 5), + (0x6A, SingleEightBit::D, 5), + (0x6B, SingleEightBit::E, 5), + (0x6C, SingleEightBit::H, 5), + (0x6D, SingleEightBit::L, 5), + (0x6F, SingleEightBit::A, 5), + + (0x70, SingleEightBit::B, 6), + (0x71, SingleEightBit::C, 6), + (0x72, SingleEightBit::D, 6), + (0x73, SingleEightBit::E, 6), + (0x74, SingleEightBit::H, 6), + (0x75, SingleEightBit::L, 6), + (0x77, SingleEightBit::A, 6), + + (0x78, SingleEightBit::B, 7), + (0x79, SingleEightBit::C, 7), + (0x7A, SingleEightBit::D, 7), + (0x7B, SingleEightBit::E, 7), + (0x7C, SingleEightBit::H, 7), + (0x7D, SingleEightBit::L, 7), + (0x7F, SingleEightBit::A, 7), + ] +)] +fn test_test_register_bit_sets_zero_flag_to_opposite_of_bit( + bit_value: u8, + (opcode_variant, register, bit): (u8, SingleEightBit, u8), +) { + let mut processor = Processor::default(); + let expected_zero_flag = if bit_value == 0 { 1 } else { 0 }; + // Set all the register to the opposite we expect to ensure they all get set + testutil::set_opposite_of_expected_flags( + &mut processor, + ( + expected_zero_flag, + 0, + 1, + // value of carry does not matter + 0, + ), + ); + + processor + .registers + .set_single_8bit_register(register, bit_value << bit); + + let data = [0xCB, opcode_variant, 0x02]; + + let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction"); + assert_eq!(extra_data, &[0x02]); + + processor.run_instruction(ins); + + testutil::assert_flags_eq!( + processor, + (Flag::Zero, expected_zero_flag), + (Flag::Subtract, 0), + (Flag::HalfCarry, 1) + ); +} + +#[test_matrix( + [0, 1], + [ + (0x46, 0), + (0x4e, 1), + (0x56, 2), + (0x5e, 3), + (0x66, 4), + (0x6e, 5), + (0x76, 6), + (0x7e, 7), + ] +)] +fn test_test_hl_value_bit_sets_zero_flag_to_opposite_of_bit( + bit_value: u8, + (opcode_variant, bit): (u8, u8), +) { + let mut processor = Processor::default(); + let expected_zero_flag = if bit_value == 0 { 1 } else { 0 }; + // Set all the register to the opposite we expect to ensure they all get set + testutil::set_opposite_of_expected_flags( + &mut processor, + ( + expected_zero_flag, + 0, + 1, + // value of carry does not matter + 0, + ), + ); + + processor + .memory + .set(0xFF00, bit_value << bit) + .expect("failed to set memory value"); + + processor + .registers + .set_combined_register(register::Combined::HL, 0xFF00); + + let data = [0xCB, opcode_variant, 0x02]; + + let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction"); + assert_eq!(extra_data, &[0x02]); + + processor.run_instruction(ins); + + testutil::assert_flags_eq!( + processor, + (Flag::Zero, expected_zero_flag), + (Flag::Subtract, 0), + (Flag::HalfCarry, 1) + ); +}