|
|
|
@ -3,52 +3,16 @@ use ferris_boi::{
|
|
|
|
|
register,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use crate::testutil;
|
|
|
|
|
|
|
|
|
|
use test_case::test_case;
|
|
|
|
|
|
|
|
|
|
fn set_opposite_of_expected_flags(
|
|
|
|
|
processor: &mut Processor,
|
|
|
|
|
(zero_flag, sub_flag, half_carry_flag, carry_flag): (u8, u8, u8, u8),
|
|
|
|
|
) {
|
|
|
|
|
let invert_flag = |value| {
|
|
|
|
|
if value == 0 {
|
|
|
|
|
1
|
|
|
|
|
} else if value == 1 {
|
|
|
|
|
0
|
|
|
|
|
} else {
|
|
|
|
|
panic!("invalid flag value of {value} ")
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
processor
|
|
|
|
|
.registers
|
|
|
|
|
.set_flag_bit(register::Flag::Zero, invert_flag(zero_flag));
|
|
|
|
|
|
|
|
|
|
processor
|
|
|
|
|
.registers
|
|
|
|
|
.set_flag_bit(register::Flag::HalfCarry, invert_flag(half_carry_flag));
|
|
|
|
|
|
|
|
|
|
processor
|
|
|
|
|
.registers
|
|
|
|
|
.set_flag_bit(register::Flag::Carry, invert_flag(carry_flag));
|
|
|
|
|
|
|
|
|
|
processor
|
|
|
|
|
.registers
|
|
|
|
|
.set_flag_bit(register::Flag::Subtract, invert_flag(sub_flag));
|
|
|
|
|
struct AdditionOperationFlags {
|
|
|
|
|
zero: u8,
|
|
|
|
|
half_carry: u8,
|
|
|
|
|
carry: u8,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! assert_flags_eq {
|
|
|
|
|
($processor: expr, $(($flag: path, $value: expr)),+ $(,)?) => {
|
|
|
|
|
$(
|
|
|
|
|
assert_eq!(
|
|
|
|
|
$value,
|
|
|
|
|
$processor.registers.get_flag_bit($flag),
|
|
|
|
|
"{:?} flag had unexpected value",
|
|
|
|
|
$flag
|
|
|
|
|
);
|
|
|
|
|
)+
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_add_a_to_itself() {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
@ -104,7 +68,10 @@ fn test_add_register_to_a_flags(
|
|
|
|
|
processor.registers.a = a_value;
|
|
|
|
|
|
|
|
|
|
// Set all the register to the opposite we expect to ensure they all get set
|
|
|
|
|
set_opposite_of_expected_flags(&mut processor, (zero_flag, 0, half_carry_flag, carry_flag));
|
|
|
|
|
testutil::set_opposite_of_expected_flags(
|
|
|
|
|
&mut processor,
|
|
|
|
|
(zero_flag, 0, half_carry_flag, carry_flag),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
processor.registers.set_single_8bit_register(src, src_value);
|
|
|
|
|
let data = [opcode, 0x02];
|
|
|
|
@ -115,7 +82,7 @@ fn test_add_register_to_a_flags(
|
|
|
|
|
|
|
|
|
|
processor.run(&ins);
|
|
|
|
|
|
|
|
|
|
assert_flags_eq!(
|
|
|
|
|
testutil::assert_flags_eq!(
|
|
|
|
|
processor,
|
|
|
|
|
(register::Flag::Zero, zero_flag),
|
|
|
|
|
(register::Flag::Subtract, 0),
|
|
|
|
@ -173,7 +140,10 @@ fn test_add_hl_addr_to_a_flags(
|
|
|
|
|
.expect("expected to set address 0xFF00 but could not");
|
|
|
|
|
|
|
|
|
|
// Set all the register to the opposite we expect to ensure they all get set
|
|
|
|
|
set_opposite_of_expected_flags(&mut processor, (zero_flag, 0, half_carry_flag, carry_flag));
|
|
|
|
|
testutil::set_opposite_of_expected_flags(
|
|
|
|
|
&mut processor,
|
|
|
|
|
(zero_flag, 0, half_carry_flag, carry_flag),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let data = [0x86, 0x01];
|
|
|
|
|
let (ins, extra_data) =
|
|
|
|
@ -182,7 +152,7 @@ fn test_add_hl_addr_to_a_flags(
|
|
|
|
|
|
|
|
|
|
processor.run(&ins);
|
|
|
|
|
|
|
|
|
|
assert_flags_eq!(
|
|
|
|
|
testutil::assert_flags_eq!(
|
|
|
|
|
processor,
|
|
|
|
|
(register::Flag::Zero, zero_flag),
|
|
|
|
|
(register::Flag::Subtract, 0),
|
|
|
|
@ -206,23 +176,25 @@ fn test_add_immediate_to_a_value() {
|
|
|
|
|
assert_eq!(69, processor.registers.a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0x00, 0x00, 1, 0, 0; "zero flag for zero value")]
|
|
|
|
|
#[test_case(0x00, 0x01, 0, 0, 0; "no zero flag for non-zero value")]
|
|
|
|
|
#[test_case(0x0F, 0x01, 0, 1, 0; "half carry flag")]
|
|
|
|
|
#[test_case(0x80, 0x80, 0, 0, 1; "full carry flag")]
|
|
|
|
|
#[test_case(0xFF, 0x01, 0, 1, 1; "both full and half carry flag")]
|
|
|
|
|
fn test_add_immediate_to_a_flags(
|
|
|
|
|
a_value: u8,
|
|
|
|
|
n: u8,
|
|
|
|
|
zero_flag: u8,
|
|
|
|
|
half_carry_flag: u8,
|
|
|
|
|
carry_flag: u8,
|
|
|
|
|
) {
|
|
|
|
|
#[test_case(0x00, 0x00, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "zero flag for zero value")]
|
|
|
|
|
#[test_case(0x00, 0x01, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no zero flag for non-zero value")]
|
|
|
|
|
#[test_case(0x0F, 0x01, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "half carry flag")]
|
|
|
|
|
#[test_case(0x80, 0x80, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "full carry flag")]
|
|
|
|
|
#[test_case(0xFF, 0x01, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "both full and half carry flag")]
|
|
|
|
|
fn test_add_immediate_to_a_flags(a_value: u8, n: u8, expected_flags: AdditionOperationFlags) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor.registers.a = a_value;
|
|
|
|
|
|
|
|
|
|
// Set all the register to the opposite we expect to ensure they all get set
|
|
|
|
|
set_opposite_of_expected_flags(&mut processor, (zero_flag, 0, half_carry_flag, carry_flag));
|
|
|
|
|
testutil::set_opposite_of_expected_flags(
|
|
|
|
|
&mut processor,
|
|
|
|
|
(
|
|
|
|
|
expected_flags.zero,
|
|
|
|
|
0,
|
|
|
|
|
expected_flags.half_carry,
|
|
|
|
|
expected_flags.carry,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let data = [0xC6, n, 0x01];
|
|
|
|
|
let (ins, extra_data) =
|
|
|
|
@ -231,12 +203,12 @@ fn test_add_immediate_to_a_flags(
|
|
|
|
|
|
|
|
|
|
processor.run(&ins);
|
|
|
|
|
|
|
|
|
|
assert_flags_eq!(
|
|
|
|
|
testutil::assert_flags_eq!(
|
|
|
|
|
processor,
|
|
|
|
|
(register::Flag::Zero, zero_flag),
|
|
|
|
|
(register::Flag::Zero, expected_flags.zero),
|
|
|
|
|
(register::Flag::Subtract, 0),
|
|
|
|
|
(register::Flag::HalfCarry, half_carry_flag),
|
|
|
|
|
(register::Flag::Carry, carry_flag),
|
|
|
|
|
(register::Flag::HalfCarry, expected_flags.half_carry),
|
|
|
|
|
(register::Flag::Carry, expected_flags.carry),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -280,74 +252,72 @@ fn test_add_with_carry_to_a_value(
|
|
|
|
|
|
|
|
|
|
// these parameters are like impossible to read but I can't think of a nicer way to do this right now
|
|
|
|
|
// B register
|
|
|
|
|
#[test_case(0x88, 0x12, 0, register::SingleEightBit::B, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register b")]
|
|
|
|
|
#[test_case(0x88, 0x12, 1, register::SingleEightBit::B, 0x5, 0, 0, 0; "carry bit set, results in no flags, register b")]
|
|
|
|
|
#[test_case(0x88, 0x00, 0, register::SingleEightBit::B, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register b")]
|
|
|
|
|
#[test_case(0x88, 0x00, 1, register::SingleEightBit::B, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register b")]
|
|
|
|
|
#[test_case(0x88, 0x0F, 0, register::SingleEightBit::B, 0x1, 0, 1, 0; "no carry bit, half carry, register b")]
|
|
|
|
|
#[test_case(0x88, 0x0F, 1, register::SingleEightBit::B, 0x1, 0, 1, 0; "carry bit, half carry, register b")]
|
|
|
|
|
#[test_case(0x88, 0x0F, 0, register::SingleEightBit::B, 0x0F, 0, 1, 0; "no carry bit, full carry, register b")]
|
|
|
|
|
#[test_case(0x88, 0x0F, 1, register::SingleEightBit::B, 0x0F, 0, 1, 0; "carry bit, full carry, register b")]
|
|
|
|
|
#[test_case(0x88, 0xFF, 1, register::SingleEightBit::B, 0xFF, 0, 1, 1; "carry bit, both carries, register b")]
|
|
|
|
|
#[test_case(0x88, 0x12, 0, register::SingleEightBit::B, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register b")]
|
|
|
|
|
#[test_case(0x88, 0x12, 1, register::SingleEightBit::B, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register b")]
|
|
|
|
|
#[test_case(0x88, 0x00, 0, register::SingleEightBit::B, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register b")]
|
|
|
|
|
#[test_case(0x88, 0x00, 1, register::SingleEightBit::B, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register b")]
|
|
|
|
|
#[test_case(0x88, 0x0F, 0, register::SingleEightBit::B, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register b")]
|
|
|
|
|
#[test_case(0x88, 0x0F, 1, register::SingleEightBit::B, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register b")]
|
|
|
|
|
#[test_case(0x88, 0x0F, 0, register::SingleEightBit::B, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register b")]
|
|
|
|
|
#[test_case(0x88, 0x0F, 1, register::SingleEightBit::B, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register b")]
|
|
|
|
|
#[test_case(0x88, 0xFF, 1, register::SingleEightBit::B, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register b")]
|
|
|
|
|
// C register
|
|
|
|
|
#[test_case(0x89, 0x12, 0, register::SingleEightBit::C, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register c")]
|
|
|
|
|
#[test_case(0x89, 0x12, 1, register::SingleEightBit::C, 0x5, 0, 0, 0; "carry bit set, results in no flags, register c")]
|
|
|
|
|
#[test_case(0x89, 0x00, 0, register::SingleEightBit::C, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register c")]
|
|
|
|
|
#[test_case(0x89, 0x00, 1, register::SingleEightBit::C, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register c")]
|
|
|
|
|
#[test_case(0x89, 0x0F, 0, register::SingleEightBit::C, 0x1, 0, 1, 0; "no carry bit, half carry, register c")]
|
|
|
|
|
#[test_case(0x89, 0x0F, 1, register::SingleEightBit::C, 0x1, 0, 1, 0; "carry bit, half carry, register c")]
|
|
|
|
|
#[test_case(0x89, 0x0F, 0, register::SingleEightBit::C, 0x0F, 0, 1, 0; "no carry bit, full carry, register c")]
|
|
|
|
|
#[test_case(0x89, 0x0F, 1, register::SingleEightBit::C, 0x0F, 0, 1, 0; "carry bit, full carry, register c")]
|
|
|
|
|
#[test_case(0x89, 0xFF, 1, register::SingleEightBit::C, 0xFF, 0, 1, 1; "carry bit, both carries, register c")]
|
|
|
|
|
#[test_case(0x89, 0x12, 0, register::SingleEightBit::C, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register c")]
|
|
|
|
|
#[test_case(0x89, 0x12, 1, register::SingleEightBit::C, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register c")]
|
|
|
|
|
#[test_case(0x89, 0x00, 0, register::SingleEightBit::C, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register c")]
|
|
|
|
|
#[test_case(0x89, 0x00, 1, register::SingleEightBit::C, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register c")]
|
|
|
|
|
#[test_case(0x89, 0x0F, 0, register::SingleEightBit::C, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register c")]
|
|
|
|
|
#[test_case(0x89, 0x0F, 1, register::SingleEightBit::C, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register c")]
|
|
|
|
|
#[test_case(0x89, 0x0F, 0, register::SingleEightBit::C, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register c")]
|
|
|
|
|
#[test_case(0x89, 0x0F, 1, register::SingleEightBit::C, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register c")]
|
|
|
|
|
#[test_case(0x89, 0xFF, 1, register::SingleEightBit::C, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register c")]
|
|
|
|
|
// D register
|
|
|
|
|
#[test_case(0x8A, 0x12, 0, register::SingleEightBit::D, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x12, 1, register::SingleEightBit::D, 0x5, 0, 0, 0; "carry bit set, results in no flags, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x00, 0, register::SingleEightBit::D, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x00, 1, register::SingleEightBit::D, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x0F, 0, register::SingleEightBit::D, 0x1, 0, 1, 0; "no carry bit, half carry, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x0F, 1, register::SingleEightBit::D, 0x1, 0, 1, 0; "carry bit, half carry, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x0F, 0, register::SingleEightBit::D, 0x0F, 0, 1, 0; "no carry bit, full carry, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x0F, 1, register::SingleEightBit::D, 0x0F, 0, 1, 0; "carry bit, full carry, register d")]
|
|
|
|
|
#[test_case(0x8A, 0xFF, 1, register::SingleEightBit::D, 0xFF, 0, 1, 1; "carry bit, both carries, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x12, 0, register::SingleEightBit::D, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x12, 1, register::SingleEightBit::D, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x00, 0, register::SingleEightBit::D, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x00, 1, register::SingleEightBit::D, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x0F, 0, register::SingleEightBit::D, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x0F, 1, register::SingleEightBit::D, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x0F, 0, register::SingleEightBit::D, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register d")]
|
|
|
|
|
#[test_case(0x8A, 0x0F, 1, register::SingleEightBit::D, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register d")]
|
|
|
|
|
#[test_case(0x8A, 0xFF, 1, register::SingleEightBit::D, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register d")]
|
|
|
|
|
// E register
|
|
|
|
|
#[test_case(0x8B, 0x12, 0, register::SingleEightBit::E, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x12, 1, register::SingleEightBit::E, 0x5, 0, 0, 0; "carry bit set, results in no flags, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x00, 0, register::SingleEightBit::E, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x00, 1, register::SingleEightBit::E, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x0F, 0, register::SingleEightBit::E, 0x1, 0, 1, 0; "no carry bit, half carry, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x0F, 1, register::SingleEightBit::E, 0x1, 0, 1, 0; "carry bit, half carry, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x0F, 0, register::SingleEightBit::E, 0x0F, 0, 1, 0; "no carry bit, full carry, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x0F, 1, register::SingleEightBit::E, 0x0F, 0, 1, 0; "carry bit, full carry, register e")]
|
|
|
|
|
#[test_case(0x8B, 0xFF, 1, register::SingleEightBit::E, 0xFF, 0, 1, 1; "carry bit, both carries, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x12, 0, register::SingleEightBit::E, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x12, 1, register::SingleEightBit::E, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x00, 0, register::SingleEightBit::E, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x00, 1, register::SingleEightBit::E, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x0F, 0, register::SingleEightBit::E, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x0F, 1, register::SingleEightBit::E, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x0F, 0, register::SingleEightBit::E, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register e")]
|
|
|
|
|
#[test_case(0x8B, 0x0F, 1, register::SingleEightBit::E, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register e")]
|
|
|
|
|
#[test_case(0x8B, 0xFF, 1, register::SingleEightBit::E, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register e")]
|
|
|
|
|
// H register
|
|
|
|
|
#[test_case(0x8C, 0x12, 0, register::SingleEightBit::H, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x12, 1, register::SingleEightBit::H, 0x5, 0, 0, 0; "carry bit set, results in no flags, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x00, 0, register::SingleEightBit::H, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x00, 1, register::SingleEightBit::H, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x0F, 0, register::SingleEightBit::H, 0x1, 0, 1, 0; "no carry bit, half carry, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x0F, 1, register::SingleEightBit::H, 0x1, 0, 1, 0; "carry bit, half carry, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x0F, 0, register::SingleEightBit::H, 0x0F, 0, 1, 0; "no carry bit, full carry, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x0F, 1, register::SingleEightBit::H, 0x0F, 0, 1, 0; "carry bit, full carry, register h")]
|
|
|
|
|
#[test_case(0x8C, 0xFF, 1, register::SingleEightBit::H, 0xFF, 0, 1, 1; "carry bit, both carries, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x12, 0, register::SingleEightBit::H, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x12, 1, register::SingleEightBit::H, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x00, 0, register::SingleEightBit::H, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x00, 1, register::SingleEightBit::H, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x0F, 0, register::SingleEightBit::H, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x0F, 1, register::SingleEightBit::H, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x0F, 0, register::SingleEightBit::H, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register h")]
|
|
|
|
|
#[test_case(0x8C, 0x0F, 1, register::SingleEightBit::H, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register h")]
|
|
|
|
|
#[test_case(0x8C, 0xFF, 1, register::SingleEightBit::H, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register h")]
|
|
|
|
|
// L register
|
|
|
|
|
#[test_case(0x8D, 0x12, 0, register::SingleEightBit::L, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x12, 1, register::SingleEightBit::L, 0x5, 0, 0, 0; "carry bit set, results in no flags, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x00, 0, register::SingleEightBit::L, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x00, 1, register::SingleEightBit::L, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x0F, 0, register::SingleEightBit::L, 0x1, 0, 1, 0; "no carry bit, half carry, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x0F, 1, register::SingleEightBit::L, 0x1, 0, 1, 0; "carry bit, half carry, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x0F, 0, register::SingleEightBit::L, 0x0F, 0, 1, 0; "no carry bit, full carry, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x0F, 1, register::SingleEightBit::L, 0x0F, 0, 1, 0; "carry bit, full carry, register l")]
|
|
|
|
|
#[test_case(0x8D, 0xFF, 1, register::SingleEightBit::L, 0xFF, 0, 1, 1; "carry bit, both carries, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x12, 0, register::SingleEightBit::L, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x12, 1, register::SingleEightBit::L, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x00, 0, register::SingleEightBit::L, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x00, 1, register::SingleEightBit::L, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x0F, 0, register::SingleEightBit::L, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x0F, 1, register::SingleEightBit::L, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x0F, 0, register::SingleEightBit::L, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register l")]
|
|
|
|
|
#[test_case(0x8D, 0x0F, 1, register::SingleEightBit::L, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register l")]
|
|
|
|
|
#[test_case(0x8D, 0xFF, 1, register::SingleEightBit::L, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register l")]
|
|
|
|
|
fn test_add_with_carry_to_a_flags(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
initial_value: u8,
|
|
|
|
|
carry_bit: u8,
|
|
|
|
|
operand_register: register::SingleEightBit,
|
|
|
|
|
operand: u8,
|
|
|
|
|
expected_zero_flag: u8,
|
|
|
|
|
expected_half_carry_flag: u8,
|
|
|
|
|
expected_carry_flag: u8,
|
|
|
|
|
expected_flags: AdditionOperationFlags,
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor.registers.a = initial_value;
|
|
|
|
@ -356,13 +326,13 @@ fn test_add_with_carry_to_a_flags(
|
|
|
|
|
.set_single_8bit_register(operand_register, operand);
|
|
|
|
|
|
|
|
|
|
// Set all the register to the opposite we expect to ensure they all get set
|
|
|
|
|
set_opposite_of_expected_flags(
|
|
|
|
|
testutil::set_opposite_of_expected_flags(
|
|
|
|
|
&mut processor,
|
|
|
|
|
(
|
|
|
|
|
expected_zero_flag,
|
|
|
|
|
expected_flags.zero,
|
|
|
|
|
0,
|
|
|
|
|
expected_half_carry_flag,
|
|
|
|
|
expected_carry_flag,
|
|
|
|
|
expected_flags.half_carry,
|
|
|
|
|
expected_flags.carry,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
@ -377,11 +347,11 @@ fn test_add_with_carry_to_a_flags(
|
|
|
|
|
assert_eq!(extra_data, &[0x01]);
|
|
|
|
|
processor.run(&ins);
|
|
|
|
|
|
|
|
|
|
assert_flags_eq!(
|
|
|
|
|
testutil::assert_flags_eq!(
|
|
|
|
|
processor,
|
|
|
|
|
(register::Flag::Zero, expected_zero_flag),
|
|
|
|
|
(register::Flag::Zero, expected_flags.zero),
|
|
|
|
|
(register::Flag::Subtract, 0),
|
|
|
|
|
(register::Flag::HalfCarry, expected_half_carry_flag),
|
|
|
|
|
(register::Flag::Carry, expected_carry_flag),
|
|
|
|
|
(register::Flag::HalfCarry, expected_flags.half_carry),
|
|
|
|
|
(register::Flag::Carry, expected_flags.carry),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|