use ferris_boi::{ cpu::{instructions::RunnableInstruction, Processor}, register, }; use test_case::test_matrix; use crate::testutil; struct AdditionOperationFlags { half_carry: u8, carry: u8, } #[test] fn test_add_hl_to_itself() { let mut processor = Processor::default(); processor.registers.set_16bit_register(register::SixteenBit::Combined(register::Combined::HL), 0x2244); let data = [0x29, 0x02]; let (ins, extra_data) = RunnableInstruction::from_data(&data).expect("could not parse instruction"); assert_eq!(extra_data, &[0x02]); processor.run_instruction(&ins); assert_eq!(0x4488, processor.registers.get_combined_register(register::Combined::HL)); } #[test_matrix( [ (0x09, register::SixteenBit::Combined(register::Combined::BC)), (0x19, register::SixteenBit::Combined(register::Combined::DE)), (0x39, register::SixteenBit::Single(register::SingleSixteenBit::StackPointer)), ], [ (0xAAAA, 0x1122, 0xBBCC), (0xFFFF, 0x0002, 0x0001), ] )] fn test_add_hl_to_registers_value((opcode, operand_register): (u8, register::SixteenBit), (hl_value, operand_value, expected): (u16, u16, u16)) { let mut processor = Processor::default(); processor.registers.set_16bit_register(register::SixteenBit::Combined(register::Combined::HL), hl_value); processor.registers.set_16bit_register(operand_register, operand_value); let data = [opcode, 0x02]; let (ins, extra_data) = RunnableInstruction::from_data(&data).expect("could not parse instruction"); assert_eq!(extra_data, &[0x02]); processor.run_instruction(&ins); assert_eq!(expected, processor.registers.get_combined_register(register::Combined::HL)); } #[test_matrix( [ (0x09, register::SixteenBit::Combined(register::Combined::BC)), (0x19, register::SixteenBit::Combined(register::Combined::DE)), (0x39, register::SixteenBit::Single(register::SingleSixteenBit::StackPointer)), ], [ (0xAAAA, 0x1122, AdditionOperationFlags{ half_carry: 0, carry: 0}), (0xAAAA, 0x0FFF, AdditionOperationFlags{ half_carry: 1, carry: 0}), (0xFFFF, 0x0001, AdditionOperationFlags{ half_carry: 1, carry: 1}), (0xFFFF, 0x0002, AdditionOperationFlags{ half_carry: 1, carry: 1}), (0x8000, 0xC000, AdditionOperationFlags{ half_carry: 0, carry: 1}), ] )] fn test_add_hl_to_registers_flags((opcode, operand_register): (u8, register::SixteenBit), (hl_value, operand_value, expected_flags): (u16, u16, AdditionOperationFlags)) { let mut processor = Processor::default(); processor.registers.set_16bit_register(register::SixteenBit::Combined(register::Combined::HL), hl_value); processor.registers.set_16bit_register(operand_register, operand_value); let data = [opcode, 0x02]; let (ins, extra_data) = RunnableInstruction::from_data(&data).expect("could not parse instruction"); assert_eq!(extra_data, &[0x02]); // Set all the register to the opposite we expect to ensure they all get set testutil::set_opposite_of_expected_flags( &mut processor, ( 0, 0, expected_flags.half_carry, expected_flags.carry, ), ); processor.run_instruction(&ins); testutil::assert_flags_eq!( processor, (register::Flag::Zero, 1), (register::Flag::Subtract, 0), (register::Flag::HalfCarry, expected_flags.half_carry), (register::Flag::Carry, expected_flags.carry), ); }