ferris-boi/tests/cpu/arith16.rs

202 lines
5.9 KiB
Rust

use ferris_boi::{
cpu::{instructions::Instruction, 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) = Instruction::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) = Instruction::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) = Instruction::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) = Instruction::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) = Instruction::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());
}