ferris-boi/tests/cpu/arith16.rs

161 lines
5.7 KiB
Rust

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),
);
}
#[test_matrix(
[
(0x03, register::SixteenBit::Combined(register::Combined::BC)),
(0x13, register::SixteenBit::Combined(register::Combined::DE)),
(0x23, register::SixteenBit::Combined(register::Combined::HL)),
(0x33, register::SixteenBit::Single(register::SingleSixteenBit::StackPointer)),
],
[
(0xAAAA, 0xAAAB),
(0xFFFF, 0x0000),
(0x0000, 0x0001),
]
)]
fn test_increment((opcode, operand_register): (u8, register::SixteenBit), (start_value, expected): (u16, u16)) {
let mut processor = Processor::default();
processor.registers.set_16bit_register(operand_register, start_value);
processor.registers.set_raw_flag_bits(0xA0).expect("Failed to set flag bits");
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_16bit_register(operand_register));
// Flags are untouched
assert_eq!(0xA0, processor.registers.get_raw_flag_bits());
}
#[test_matrix(
[
(0x0B, register::SixteenBit::Combined(register::Combined::BC)),
(0x1B, register::SixteenBit::Combined(register::Combined::DE)),
(0x2B, register::SixteenBit::Combined(register::Combined::HL)),
(0x3B, register::SixteenBit::Single(register::SingleSixteenBit::StackPointer)),
],
[
(0xAAAB, 0xAAAA),
(0x0000, 0xFFFF),
(0x0001, 0x0000),
]
)]
fn test_decrement((opcode, operand_register): (u8, register::SixteenBit), (start_value, expected): (u16, u16)) {
let mut processor = Processor::default();
processor.registers.set_16bit_register(operand_register, start_value);
processor.registers.set_raw_flag_bits(0xA0).expect("Failed to set flag bits");
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_16bit_register(operand_register));
// Flags are untouched
assert_eq!(0xA0, processor.registers.get_raw_flag_bits());
}