|
|
|
@ -5,7 +5,7 @@ use ferris_boi::{
|
|
|
|
|
|
|
|
|
|
use crate::testutil;
|
|
|
|
|
|
|
|
|
|
use test_case::test_case;
|
|
|
|
|
use test_case::{test_case, test_matrix};
|
|
|
|
|
|
|
|
|
|
struct AdditionOperationFlags {
|
|
|
|
|
zero: u8,
|
|
|
|
@ -55,18 +55,26 @@ fn test_add_to_a_value(opcode: u8, src: register::SingleEightBit) {
|
|
|
|
|
assert_eq!(30, processor.registers.a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0x80, register::SingleEightBit::B, 0x00, 0x00, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "zero flag for zero value")]
|
|
|
|
|
#[test_case(0x80, register::SingleEightBit::B, 0x00, 0x01, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no zero flag for non-zero value")]
|
|
|
|
|
#[test_case(0x81, register::SingleEightBit::C, 0x0F, 0x01, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "half carry flag")]
|
|
|
|
|
#[test_case(0x81, register::SingleEightBit::C, 0x80, 0x80, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 1}; "full carry flag")]
|
|
|
|
|
#[test_case(0x81, register::SingleEightBit::C, 0xFF, 0x01, AdditionOperationFlags{zero: 1, half_carry: 1, carry: 1}; "all flags")]
|
|
|
|
|
// 0000 1111
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0x00, 0x00, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}),
|
|
|
|
|
(0x00, 0x01, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}),
|
|
|
|
|
(0x0F, 0x01, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}),
|
|
|
|
|
(0x80, 0x80, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 1}),
|
|
|
|
|
(0xFF, 0x01, AdditionOperationFlags{zero: 1, half_carry: 1, carry: 1})
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0x80, register::SingleEightBit::B),
|
|
|
|
|
(0x81, register::SingleEightBit::C),
|
|
|
|
|
(0x82, register::SingleEightBit::D),
|
|
|
|
|
(0x83, register::SingleEightBit::E),
|
|
|
|
|
(0x84, register::SingleEightBit::H),
|
|
|
|
|
(0x85, register::SingleEightBit::L),
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_add_register_to_a_flags(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
src: register::SingleEightBit,
|
|
|
|
|
a_value: u8,
|
|
|
|
|
src_value: u8,
|
|
|
|
|
expected_flags: AdditionOperationFlags,
|
|
|
|
|
(a_value, src_value, expected_flags): (u8, u8, AdditionOperationFlags),
|
|
|
|
|
(opcode, src): (u8, register::SingleEightBit),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor.registers.a = a_value;
|
|
|
|
@ -224,25 +232,23 @@ fn test_add_immediate_to_a_flags(a_value: u8, n: u8, expected_flags: AdditionOpe
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0x88, 0x12, 0, register::SingleEightBit::B, 0x5, 0x17; "no carry to register b")]
|
|
|
|
|
#[test_case(0x88, 0x12, 1, register::SingleEightBit::B, 0x5, 0x18; "carry to register b")]
|
|
|
|
|
#[test_case(0x89, 0x12, 0, register::SingleEightBit::C, 0x5, 0x17; "no carry to register c")]
|
|
|
|
|
#[test_case(0x89, 0x12, 1, register::SingleEightBit::C, 0x5, 0x18; "carry to register c")]
|
|
|
|
|
#[test_case(0x8A, 0x12, 0, register::SingleEightBit::D, 0x5, 0x17; "no carry to register d")]
|
|
|
|
|
#[test_case(0x8A, 0x12, 1, register::SingleEightBit::D, 0x5, 0x18; "carry to register d")]
|
|
|
|
|
#[test_case(0x8B, 0x12, 0, register::SingleEightBit::E, 0x5, 0x17; "no carry to register e")]
|
|
|
|
|
#[test_case(0x8B, 0x12, 1, register::SingleEightBit::E, 0x5, 0x18; "carry to register e")]
|
|
|
|
|
#[test_case(0x8C, 0x12, 0, register::SingleEightBit::H, 0x5, 0x17; "no carry to register h")]
|
|
|
|
|
#[test_case(0x8C, 0x12, 1, register::SingleEightBit::H, 0x5, 0x18; "carry to register h")]
|
|
|
|
|
#[test_case(0x8D, 0x12, 0, register::SingleEightBit::L, 0x5, 0x17; "no carry to register l")]
|
|
|
|
|
#[test_case(0x8D, 0x12, 1, register::SingleEightBit::L, 0x5, 0x18; "carry to register l")]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0x88, register::SingleEightBit::B),
|
|
|
|
|
(0x89, register::SingleEightBit::C),
|
|
|
|
|
(0x8A, register::SingleEightBit::D),
|
|
|
|
|
(0x8B, register::SingleEightBit::E),
|
|
|
|
|
(0x8C, register::SingleEightBit::H),
|
|
|
|
|
(0x8D, register::SingleEightBit::L),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0x12, 0x05, 0, 0x17),
|
|
|
|
|
(0x12, 0x05, 1, 0x18)
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_add_register_with_carry_to_a_value(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
initial_value: u8,
|
|
|
|
|
carry_bit: u8,
|
|
|
|
|
operand_register: register::SingleEightBit,
|
|
|
|
|
operand: u8,
|
|
|
|
|
expected_value: u8,
|
|
|
|
|
(opcode, operand_register): (u8, register::SingleEightBit),
|
|
|
|
|
(initial_value, operand, carry_bit, expected_value): (u8, u8, u8, u8),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor.registers.a = initial_value;
|
|
|
|
@ -262,74 +268,37 @@ fn test_add_register_with_carry_to_a_value(
|
|
|
|
|
assert_eq!(expected_value, processor.registers.a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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, 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, 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, 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, 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, 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, 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")]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0x88, register::SingleEightBit::B),
|
|
|
|
|
(0x89, register::SingleEightBit::C),
|
|
|
|
|
(0x8A, register::SingleEightBit::D),
|
|
|
|
|
(0x8B, register::SingleEightBit::E),
|
|
|
|
|
(0x8C, register::SingleEightBit::H),
|
|
|
|
|
(0x8D, register::SingleEightBit::L),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0x12, 0x05, 0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}),
|
|
|
|
|
(0x12, 0x05, 1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}),
|
|
|
|
|
|
|
|
|
|
(0x00, 0x00, 0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}),
|
|
|
|
|
(0x00, 0x00, 1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}),
|
|
|
|
|
|
|
|
|
|
(0x0F, 0x01, 0, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}),
|
|
|
|
|
(0x0F, 0x01, 1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}),
|
|
|
|
|
(0x0F, 0x0F, 0, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}),
|
|
|
|
|
(0x0F, 0x0F, 1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}),
|
|
|
|
|
|
|
|
|
|
(0x80, 0x82, 0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}),
|
|
|
|
|
(0x80, 0x82, 1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}),
|
|
|
|
|
|
|
|
|
|
(0x0F, 0xFF, 0, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}),
|
|
|
|
|
(0x7F, 0x80, 1, AdditionOperationFlags{zero: 1, half_carry: 1, carry: 1}),
|
|
|
|
|
]
|
|
|
|
|
) ]
|
|
|
|
|
fn test_add_register_with_carry_to_a_flags(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
initial_value: u8,
|
|
|
|
|
carry_bit: u8,
|
|
|
|
|
operand_register: register::SingleEightBit,
|
|
|
|
|
operand: u8,
|
|
|
|
|
expected_flags: AdditionOperationFlags,
|
|
|
|
|
(opcode, operand_register): (u8, register::SingleEightBit),
|
|
|
|
|
(initial_value, operand, carry_bit, expected_flags): (u8, u8, u8, AdditionOperationFlags),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor.registers.a = initial_value;
|
|
|
|
@ -572,18 +541,23 @@ fn test_add_hl_addr_to_a_with_carry_flags(
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0x90, 0xFF, 0x0F, register::SingleEightBit::B, 0xF0; "subtract B")]
|
|
|
|
|
#[test_case(0x91, 0xFF, 0x0F, register::SingleEightBit::C, 0xF0; "subtract C")]
|
|
|
|
|
#[test_case(0x92, 0xFF, 0x0F, register::SingleEightBit::D, 0xF0; "subtract D")]
|
|
|
|
|
#[test_case(0x93, 0xFF, 0x0F, register::SingleEightBit::E, 0xF0; "subtract E")]
|
|
|
|
|
#[test_case(0x94, 0xFF, 0x0F, register::SingleEightBit::H, 0xF0; "subtract H")]
|
|
|
|
|
#[test_case(0x95, 0xFF, 0x0F, register::SingleEightBit::L, 0xF0; "subtract L")]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0x90, register::SingleEightBit::B),
|
|
|
|
|
(0x91, register::SingleEightBit::C),
|
|
|
|
|
(0x92, register::SingleEightBit::D),
|
|
|
|
|
(0x93, register::SingleEightBit::E),
|
|
|
|
|
(0x94, register::SingleEightBit::H),
|
|
|
|
|
(0x95, register::SingleEightBit::L),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0xFF, 0x0F, 0xF0),
|
|
|
|
|
(0x00, 0x03, 0xFD),
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_sub_register_from_a_value(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
a_value: u8,
|
|
|
|
|
operand: u8,
|
|
|
|
|
operand_register: register::SingleEightBit,
|
|
|
|
|
expected: u8,
|
|
|
|
|
(opcode, operand_register): (u8, register::SingleEightBit),
|
|
|
|
|
(a_value, operand, expected): (u8, u8, u8),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor.registers.a = a_value;
|
|
|
|
@ -601,36 +575,25 @@ fn test_sub_register_from_a_value(
|
|
|
|
|
assert_eq!(processor.registers.a, expected);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0x90, 0xFF, 0x0F, register::SingleEightBit::B, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 0 }; "no flags from B")]
|
|
|
|
|
#[test_case(0x90, 0xF0, 0x0F, register::SingleEightBit::B, AdditionOperationFlags { zero: 0, half_carry: 1, carry: 0 }; "half carry from B")]
|
|
|
|
|
#[test_case(0x90, 0x0F, 0xF0, register::SingleEightBit::B, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 1 }; "full carry from B")]
|
|
|
|
|
#[test_case(0x90, 0x01, 0x01, register::SingleEightBit::B, AdditionOperationFlags { zero: 1, half_carry: 0, carry: 0 }; "zero from B")]
|
|
|
|
|
#[test_case(0x91, 0xFF, 0x0F, register::SingleEightBit::C, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 0 }; "no flags from C")]
|
|
|
|
|
#[test_case(0x91, 0xF0, 0x0F, register::SingleEightBit::C, AdditionOperationFlags { zero: 0, half_carry: 1, carry: 0 }; "half carry from C")]
|
|
|
|
|
#[test_case(0x91, 0x0F, 0xF0, register::SingleEightBit::C, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 1 }; "full carry from C")]
|
|
|
|
|
#[test_case(0x91, 0x01, 0x01, register::SingleEightBit::C, AdditionOperationFlags { zero: 1, half_carry: 0, carry: 0 }; "zero from C")]
|
|
|
|
|
#[test_case(0x92, 0xFF, 0x0F, register::SingleEightBit::D, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 0 }; "no flags from D")]
|
|
|
|
|
#[test_case(0x92, 0xF0, 0x0F, register::SingleEightBit::D, AdditionOperationFlags { zero: 0, half_carry: 1, carry: 0 }; "half carry from D")]
|
|
|
|
|
#[test_case(0x92, 0x0F, 0xF0, register::SingleEightBit::D, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 1 }; "full carry from D")]
|
|
|
|
|
#[test_case(0x92, 0x01, 0x01, register::SingleEightBit::D, AdditionOperationFlags { zero: 1, half_carry: 0, carry: 0 }; "zero from D")]
|
|
|
|
|
#[test_case(0x93, 0xFF, 0x0F, register::SingleEightBit::E, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 0 }; "no flags from E")]
|
|
|
|
|
#[test_case(0x93, 0xF0, 0x0F, register::SingleEightBit::E, AdditionOperationFlags { zero: 0, half_carry: 1, carry: 0 }; "half carry from E")]
|
|
|
|
|
#[test_case(0x93, 0x0F, 0xF0, register::SingleEightBit::E, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 1 }; "full carry from E")]
|
|
|
|
|
#[test_case(0x93, 0x01, 0x01, register::SingleEightBit::E, AdditionOperationFlags { zero: 1, half_carry: 0, carry: 0 }; "zero from E")]
|
|
|
|
|
#[test_case(0x94, 0xFF, 0x0F, register::SingleEightBit::H, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 0 }; "no flags from H")]
|
|
|
|
|
#[test_case(0x94, 0xF0, 0x0F, register::SingleEightBit::H, AdditionOperationFlags { zero: 0, half_carry: 1, carry: 0 }; "half carry from H")]
|
|
|
|
|
#[test_case(0x94, 0x0F, 0xF0, register::SingleEightBit::H, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 1 }; "full carry from H")]
|
|
|
|
|
#[test_case(0x94, 0x01, 0x01, register::SingleEightBit::H, AdditionOperationFlags { zero: 1, half_carry: 0, carry: 0 }; "zero from H")]
|
|
|
|
|
#[test_case(0x95, 0xFF, 0x0F, register::SingleEightBit::L, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 0 }; "no flags from L")]
|
|
|
|
|
#[test_case(0x95, 0xF0, 0x0F, register::SingleEightBit::L, AdditionOperationFlags { zero: 0, half_carry: 1, carry: 0 }; "half carry from L")]
|
|
|
|
|
#[test_case(0x95, 0x0F, 0xF0, register::SingleEightBit::L, AdditionOperationFlags { zero: 0, half_carry: 0, carry: 1 }; "full carry from L")]
|
|
|
|
|
#[test_case(0x95, 0x01, 0x01, register::SingleEightBit::L, AdditionOperationFlags { zero: 1, half_carry: 0, carry: 0 }; "zero from L")]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0x90, register::SingleEightBit::B),
|
|
|
|
|
(0x91, register::SingleEightBit::C),
|
|
|
|
|
(0x92, register::SingleEightBit::D),
|
|
|
|
|
(0x93, register::SingleEightBit::E),
|
|
|
|
|
(0x94, register::SingleEightBit::H),
|
|
|
|
|
(0x95, register::SingleEightBit::L),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0xFF, 0x0F, AdditionOperationFlags{ zero: 0, half_carry: 0, carry: 0 }),
|
|
|
|
|
(0xF0, 0x0F, AdditionOperationFlags{ zero: 0, half_carry: 1, carry: 0 }),
|
|
|
|
|
(0x0F, 0xF0, AdditionOperationFlags{ zero: 0, half_carry: 0, carry: 1 }),
|
|
|
|
|
(0x01, 0x01, AdditionOperationFlags{ zero: 1, half_carry: 0, carry: 0 })
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_sub_register_from_a_flags(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
a_value: u8,
|
|
|
|
|
operand: u8,
|
|
|
|
|
operand_register: register::SingleEightBit,
|
|
|
|
|
expected_flags: AdditionOperationFlags,
|
|
|
|
|
(opcode, operand_register): (u8, register::SingleEightBit),
|
|
|
|
|
(a_value, operand, expected_flags): (u8, u8, AdditionOperationFlags),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor.registers.a = a_value;
|
|
|
|
@ -689,25 +652,23 @@ fn test_sub_a_from_itself() {
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0x98, 0xFF, 0x0F, 0, register::SingleEightBit::B, 0xF0; "subtract B with no carry")]
|
|
|
|
|
#[test_case(0x98, 0xFF, 0x0F, 1, register::SingleEightBit::B, 0xEF; "subtract B with carry")]
|
|
|
|
|
#[test_case(0x99, 0xFF, 0x0F, 0, register::SingleEightBit::C, 0xF0; "subtract C with no carry")]
|
|
|
|
|
#[test_case(0x99, 0xFF, 0x0F, 1, register::SingleEightBit::C, 0xEF; "subtract C with carry")]
|
|
|
|
|
#[test_case(0x9A, 0xFF, 0x0F, 0, register::SingleEightBit::D, 0xF0; "subtract D with no carry")]
|
|
|
|
|
#[test_case(0x9A, 0xFF, 0x0F, 1, register::SingleEightBit::D, 0xEF; "subtract D with carry")]
|
|
|
|
|
#[test_case(0x9B, 0xFF, 0x0F, 0, register::SingleEightBit::E, 0xF0; "subtract E with no carry")]
|
|
|
|
|
#[test_case(0x9B, 0xFF, 0x0F, 1, register::SingleEightBit::E, 0xEF; "subtract E with carry")]
|
|
|
|
|
#[test_case(0x9C, 0xFF, 0x0F, 0, register::SingleEightBit::H, 0xF0; "subtract H with no carry")]
|
|
|
|
|
#[test_case(0x9C, 0xFF, 0x0F, 1, register::SingleEightBit::H, 0xEF; "subtract H with carry")]
|
|
|
|
|
#[test_case(0x9D, 0xFF, 0x0F, 0, register::SingleEightBit::L, 0xF0; "subtract L with no carry")]
|
|
|
|
|
#[test_case(0x9D, 0xFF, 0x0F, 1, register::SingleEightBit::L, 0xEF; "subtract L with carry")]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0x98, register::SingleEightBit::B),
|
|
|
|
|
(0x99, register::SingleEightBit::C),
|
|
|
|
|
(0x9A, register::SingleEightBit::D),
|
|
|
|
|
(0x9B, register::SingleEightBit::E),
|
|
|
|
|
(0x9C, register::SingleEightBit::H),
|
|
|
|
|
(0x9D, register::SingleEightBit::L),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0xFF, 0x0F, 0, 0xF0),
|
|
|
|
|
(0xFF, 0x0F, 1, 0xEF)
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_sub_register_with_carry_from_a_value(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
a_value: u8,
|
|
|
|
|
operand: u8,
|
|
|
|
|
carry_bit: u8,
|
|
|
|
|
operand_register: register::SingleEightBit,
|
|
|
|
|
expected: u8,
|
|
|
|
|
(opcode, operand_register): (u8, register::SingleEightBit),
|
|
|
|
|
(a_value, operand, carry_bit, expected): (u8, u8, u8, u8),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor.registers.a = a_value;
|
|
|
|
@ -727,74 +688,33 @@ fn test_sub_register_with_carry_from_a_value(
|
|
|
|
|
processor.run_instruction(&ins);
|
|
|
|
|
assert_eq!(processor.registers.a, expected);
|
|
|
|
|
}
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0x98, register::SingleEightBit::B),
|
|
|
|
|
(0x99, register::SingleEightBit::C),
|
|
|
|
|
(0x9A, register::SingleEightBit::D),
|
|
|
|
|
(0x9B, register::SingleEightBit::E),
|
|
|
|
|
(0x9C, register::SingleEightBit::H),
|
|
|
|
|
(0x9D, register::SingleEightBit::L),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0xFE, 0x01, 0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}),
|
|
|
|
|
(0xFE, 0x01, 1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}),
|
|
|
|
|
|
|
|
|
|
// Register B
|
|
|
|
|
#[test_case(0x98, 0xFE, 0, register::SingleEightBit::B, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register b")]
|
|
|
|
|
#[test_case(0x98, 0xFE, 1, register::SingleEightBit::B, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register b")]
|
|
|
|
|
#[test_case(0x98, 0x00, 0, register::SingleEightBit::B, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "all zero operands give zero flag, register b")]
|
|
|
|
|
#[test_case(0x98, 0x01, 1, register::SingleEightBit::B, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 1 gives zero flag with carry bit, register b")]
|
|
|
|
|
#[test_case(0x98, 0x02, 0, register::SingleEightBit::B, 0x2, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 2 gives zero flag with no, register b")]
|
|
|
|
|
#[test_case(0x98, 0xF0, 0, register::SingleEightBit::B, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit set, half carry bit, register b")]
|
|
|
|
|
#[test_case(0x98, 0x0F, 0, register::SingleEightBit::B, 0xF0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "no carry bit set, full carry bit, register b")]
|
|
|
|
|
#[test_case(0x98, 0xF0, 1, register::SingleEightBit::B, 0x0E, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit set, half carry bit, register b")]
|
|
|
|
|
#[test_case(0x98, 0x0F, 1, register::SingleEightBit::B, 0xEE, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "carry bit set, full carry bit, register b")]
|
|
|
|
|
// Register C
|
|
|
|
|
#[test_case(0x99, 0xFE, 0, register::SingleEightBit::C, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register c")]
|
|
|
|
|
#[test_case(0x99, 0xFE, 1, register::SingleEightBit::C, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register c")]
|
|
|
|
|
#[test_case(0x99, 0x00, 0, register::SingleEightBit::C, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "all zero operands give zero flag, register c")]
|
|
|
|
|
#[test_case(0x99, 0x01, 1, register::SingleEightBit::C, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 1 gives zero flag with carry bit, register c")]
|
|
|
|
|
#[test_case(0x99, 0x02, 0, register::SingleEightBit::C, 0x2, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 2 gives zero flag with no, register c")]
|
|
|
|
|
#[test_case(0x99, 0xF0, 0, register::SingleEightBit::C, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit set, half carry bit, register c")]
|
|
|
|
|
#[test_case(0x99, 0x0F, 0, register::SingleEightBit::C, 0xF0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "no carry bit set, full carry bit, register c")]
|
|
|
|
|
#[test_case(0x99, 0xF0, 1, register::SingleEightBit::C, 0x0E, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit set, half carry bit, register c")]
|
|
|
|
|
#[test_case(0x99, 0x0F, 1, register::SingleEightBit::C, 0xEE, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "carry bit set, full carry bit, register c")]
|
|
|
|
|
// Register D
|
|
|
|
|
#[test_case(0x9A, 0xFE, 0, register::SingleEightBit::D, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register d")]
|
|
|
|
|
#[test_case(0x9A, 0xFE, 1, register::SingleEightBit::D, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register d")]
|
|
|
|
|
#[test_case(0x9A, 0x00, 0, register::SingleEightBit::D, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "all zero operands give zero flag, register d")]
|
|
|
|
|
#[test_case(0x9A, 0x01, 1, register::SingleEightBit::D, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 1 gives zero flag with carry bit, register d")]
|
|
|
|
|
#[test_case(0x9A, 0x02, 0, register::SingleEightBit::D, 0x2, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 2 gives zero flag with no, register d")]
|
|
|
|
|
#[test_case(0x9A, 0xF0, 0, register::SingleEightBit::D, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit set, half carry bit, register d")]
|
|
|
|
|
#[test_case(0x9A, 0x0F, 0, register::SingleEightBit::D, 0xF0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "no carry bit set, full carry bit, register d")]
|
|
|
|
|
#[test_case(0x9A, 0xF0, 1, register::SingleEightBit::D, 0x0E, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit set, half carry bit, register d")]
|
|
|
|
|
#[test_case(0x9A, 0x0F, 1, register::SingleEightBit::D, 0xEE, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "carry bit set, full carry bit, register d")]
|
|
|
|
|
// Register E
|
|
|
|
|
#[test_case(0x9B, 0xFE, 0, register::SingleEightBit::E, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register e")]
|
|
|
|
|
#[test_case(0x9B, 0xFE, 1, register::SingleEightBit::E, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register e")]
|
|
|
|
|
#[test_case(0x9B, 0x00, 0, register::SingleEightBit::E, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "all zero operands give zero flag, register e")]
|
|
|
|
|
#[test_case(0x9B, 0x01, 1, register::SingleEightBit::E, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 1 gives zero flag with carry bit, register e")]
|
|
|
|
|
#[test_case(0x9B, 0x02, 0, register::SingleEightBit::E, 0x2, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 2 gives zero flag with no, register e")]
|
|
|
|
|
#[test_case(0x9B, 0xF0, 0, register::SingleEightBit::E, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit set, half carry bit, register e")]
|
|
|
|
|
#[test_case(0x9B, 0x0F, 0, register::SingleEightBit::E, 0xF0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "no carry bit set, full carry bit, register e")]
|
|
|
|
|
#[test_case(0x9B, 0xF0, 1, register::SingleEightBit::E, 0x0E, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit set, half carry bit, register e")]
|
|
|
|
|
#[test_case(0x9B, 0x0F, 1, register::SingleEightBit::E, 0xEE, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "carry bit set, full carry bit, register e")]
|
|
|
|
|
// Register H
|
|
|
|
|
#[test_case(0x9C, 0xFE, 0, register::SingleEightBit::H, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register h")]
|
|
|
|
|
#[test_case(0x9C, 0xFE, 1, register::SingleEightBit::H, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register h")]
|
|
|
|
|
#[test_case(0x9C, 0x00, 0, register::SingleEightBit::H, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "all zero operands give zero flag, register h")]
|
|
|
|
|
#[test_case(0x9C, 0x01, 1, register::SingleEightBit::H, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 1 gives zero flag with carry bit, register h")]
|
|
|
|
|
#[test_case(0x9C, 0x02, 0, register::SingleEightBit::H, 0x2, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 2 gives zero flag with no, register h")]
|
|
|
|
|
#[test_case(0x9C, 0xF0, 0, register::SingleEightBit::H, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit set, half carry bit, register h")]
|
|
|
|
|
#[test_case(0x9C, 0x0F, 0, register::SingleEightBit::H, 0xF0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "no carry bit set, full carry bit, register h")]
|
|
|
|
|
#[test_case(0x9C, 0xF0, 1, register::SingleEightBit::H, 0x0E, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit set, half carry bit, register h")]
|
|
|
|
|
#[test_case(0x9C, 0x0F, 1, register::SingleEightBit::H, 0xEE, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "carry bit set, full carry bit, register h")]
|
|
|
|
|
// Register L
|
|
|
|
|
#[test_case(0x9D, 0xFE, 0, register::SingleEightBit::L, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register l")]
|
|
|
|
|
#[test_case(0x9D, 0xFE, 1, register::SingleEightBit::L, 0x1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register l")]
|
|
|
|
|
#[test_case(0x9D, 0x00, 0, register::SingleEightBit::L, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "all zero operands give zero flag, register l")]
|
|
|
|
|
#[test_case(0x9D, 0x01, 1, register::SingleEightBit::L, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 1 gives zero flag with carry bit, register l")]
|
|
|
|
|
#[test_case(0x9D, 0x02, 0, register::SingleEightBit::L, 0x2, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "subtracting from 2 gives zero flag with no, register l")]
|
|
|
|
|
#[test_case(0x9D, 0xF0, 0, register::SingleEightBit::L, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit set, half carry bit, register l")]
|
|
|
|
|
#[test_case(0x9D, 0x0F, 0, register::SingleEightBit::L, 0xF0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "no carry bit set, full carry bit, register l")]
|
|
|
|
|
#[test_case(0x9D, 0xF0, 1, register::SingleEightBit::L, 0x0E, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit set, half carry bit, register l")]
|
|
|
|
|
#[test_case(0x9D, 0x0F, 1, register::SingleEightBit::L, 0xEE, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "carry bit set, full carry bit, register l")]
|
|
|
|
|
(0x00, 0x00, 0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}),
|
|
|
|
|
(0x01, 0x00, 1, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}),
|
|
|
|
|
(0x02, 0x02, 0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}),
|
|
|
|
|
|
|
|
|
|
(0xF0, 0x0F, 0, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}),
|
|
|
|
|
(0x0F, 0xF0, 0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}),
|
|
|
|
|
|
|
|
|
|
(0xF0, 0x0E, 1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}),
|
|
|
|
|
(0x0F, 0xEE, 1, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}),
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_sub_register_from_carry_from_a_flags(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
initial_value: u8,
|
|
|
|
|
carry_bit: u8,
|
|
|
|
|
operand_register: register::SingleEightBit,
|
|
|
|
|
operand: u8,
|
|
|
|
|
expected_flags: AdditionOperationFlags,
|
|
|
|
|
(opcode, operand_register): (u8, register::SingleEightBit),
|
|
|
|
|
(initial_value, operand, carry_bit, expected_flags): (u8, u8, u8, AdditionOperationFlags),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor.registers.a = initial_value;
|
|
|
|
@ -1191,20 +1111,21 @@ fn test_and_single_register_with_a_value(
|
|
|
|
|
assert_eq!(expected_value, processor.registers.a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0xA0, 0xFA, register::SingleEightBit::B, 0x0F, 0; "AND with B, not zero")]
|
|
|
|
|
#[test_case(0xA0, 0xFA, register::SingleEightBit::B, 0x00, 1; "AND with B, zero")]
|
|
|
|
|
#[test_case(0xA1, 0xFA, register::SingleEightBit::C, 0x0F, 0; "AND with C, not zero")]
|
|
|
|
|
#[test_case(0xA1, 0xFA, register::SingleEightBit::C, 0x00, 1; "AND with C, zero")]
|
|
|
|
|
#[test_case(0xA2, 0xFA, register::SingleEightBit::D, 0x0F, 0; "AND with D, not zero")]
|
|
|
|
|
#[test_case(0xA2, 0xFA, register::SingleEightBit::D, 0x00, 1; "AND with D, zero")]
|
|
|
|
|
#[test_case(0xA3, 0xFA, register::SingleEightBit::E, 0x0F, 0; "AND with E, not zero")]
|
|
|
|
|
#[test_case(0xA3, 0xFA, register::SingleEightBit::E, 0x00, 1; "AND with E, zero")]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0xA0, register::SingleEightBit::B),
|
|
|
|
|
(0xA1, register::SingleEightBit::C),
|
|
|
|
|
(0xA2, register::SingleEightBit::D),
|
|
|
|
|
(0xA3, register::SingleEightBit::E),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0xFA, 0x0F, 0),
|
|
|
|
|
(0xFA, 0x00, 1),
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_and_single_register_with_a_flags(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
a_value: u8,
|
|
|
|
|
operand_register: register::SingleEightBit,
|
|
|
|
|
operand: u8,
|
|
|
|
|
expected_zero_flag: u8,
|
|
|
|
|
(opcode, operand_register): (u8, register::SingleEightBit),
|
|
|
|
|
(a_value, operand, expected_zero_flag): (u8, u8, u8),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
// Set all the register to the opposite we expect to ensure they all get set
|
|
|
|
@ -1357,12 +1278,12 @@ fn test_and_immediate_with_a_flags(a_value: u8, operand: u8, expected_zero_flag:
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0xA8, 0xFF, register::SingleEightBit::B, 0xCC, 0x33; "register b")]
|
|
|
|
|
#[test_case(0xA9, 0xFF, register::SingleEightBit::C, 0x33, 0xCC; "register c")]
|
|
|
|
|
#[test_case(0xAA, 0xFF, register::SingleEightBit::D, 0xCC, 0x33; "register d")]
|
|
|
|
|
#[test_case(0xAB, 0xFF, register::SingleEightBit::E, 0x33, 0xCC; "register e")]
|
|
|
|
|
#[test_case(0xAC, 0xFF, register::SingleEightBit::H, 0xCC, 0x33; "register h")]
|
|
|
|
|
#[test_case(0xAD, 0xFF, register::SingleEightBit::L, 0x33, 0xCC; "register l")]
|
|
|
|
|
#[test_case(0xA8, 0xFF, register::SingleEightBit::B, 0xCC, 0x33; "register B")]
|
|
|
|
|
#[test_case(0xA9, 0xFF, register::SingleEightBit::C, 0x33, 0xCC; "register C")]
|
|
|
|
|
#[test_case(0xAA, 0xFF, register::SingleEightBit::D, 0xCC, 0x33; "register D")]
|
|
|
|
|
#[test_case(0xAB, 0xFF, register::SingleEightBit::E, 0x33, 0xCC; "register E")]
|
|
|
|
|
#[test_case(0xAC, 0xFF, register::SingleEightBit::H, 0xCC, 0x33; "register H")]
|
|
|
|
|
#[test_case(0xAD, 0xFF, register::SingleEightBit::L, 0x33, 0xCC; "register L")]
|
|
|
|
|
fn test_xor_register_with_a_value(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
a_value: u8,
|
|
|
|
@ -1387,24 +1308,23 @@ fn test_xor_register_with_a_value(
|
|
|
|
|
assert_eq!(expected_value, processor.registers.a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0xA8, 0xFF, register::SingleEightBit::B, 0xCC, 0; "register b, not zero")]
|
|
|
|
|
#[test_case(0xA8, 0xCC, register::SingleEightBit::B, 0xCC, 1; "register b, zero")]
|
|
|
|
|
#[test_case(0xA9, 0xFF, register::SingleEightBit::C, 0x33, 0; "register c, not zero")]
|
|
|
|
|
#[test_case(0xA9, 0x33, register::SingleEightBit::C, 0x33, 1; "register c, zero")]
|
|
|
|
|
#[test_case(0xAA, 0xFF, register::SingleEightBit::D, 0xCC, 0; "register d, not zero")]
|
|
|
|
|
#[test_case(0xAA, 0xCC, register::SingleEightBit::D, 0xCC, 1; "register d, zero")]
|
|
|
|
|
#[test_case(0xAB, 0xFF, register::SingleEightBit::E, 0x33, 0; "register e, not zero")]
|
|
|
|
|
#[test_case(0xAB, 0x33, register::SingleEightBit::E, 0x33, 1; "register e, zero")]
|
|
|
|
|
#[test_case(0xAC, 0xFF, register::SingleEightBit::H, 0xCC, 0; "register h, not zero")]
|
|
|
|
|
#[test_case(0xAC, 0xCC, register::SingleEightBit::H, 0xCC, 1; "register h, zero")]
|
|
|
|
|
#[test_case(0xAD, 0xFF, register::SingleEightBit::L, 0x33, 0; "register l, not zero")]
|
|
|
|
|
#[test_case(0xAD, 0x33, register::SingleEightBit::L, 0x33, 1; "register l, zero")]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0xA8, register::SingleEightBit::B),
|
|
|
|
|
(0xA9, register::SingleEightBit::C),
|
|
|
|
|
(0xAA, register::SingleEightBit::D),
|
|
|
|
|
(0xAB, register::SingleEightBit::E),
|
|
|
|
|
(0xAC, register::SingleEightBit::H),
|
|
|
|
|
(0xAD, register::SingleEightBit::L),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0xFF, 0xCC, 0),
|
|
|
|
|
(0xCC, 0xCC, 1),
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_xor_register_with_a_flags(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
a_value: u8,
|
|
|
|
|
operand_register: register::SingleEightBit,
|
|
|
|
|
operand: u8,
|
|
|
|
|
expected_zero_flag: u8,
|
|
|
|
|
(opcode, operand_register): (u8, register::SingleEightBit),
|
|
|
|
|
(a_value, operand, expected_zero_flag): (u8, u8, u8),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
// Set all the register to the opposite we expect to ensure they all get set
|
|
|
|
@ -1562,18 +1482,23 @@ fn test_xor_immediate_value_with_a_flags(a_value: u8, operand: u8, expected_zero
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0xB0, 0xCC, register::SingleEightBit::B, 0x11, 0xDD; "register b")]
|
|
|
|
|
#[test_case(0xB1, 0xCC, register::SingleEightBit::C, 0x11, 0xDD; "register c")]
|
|
|
|
|
#[test_case(0xB2, 0xCC, register::SingleEightBit::D, 0x11, 0xDD; "register d")]
|
|
|
|
|
#[test_case(0xB3, 0xCC, register::SingleEightBit::E, 0x11, 0xDD; "register e")]
|
|
|
|
|
#[test_case(0xB4, 0xCC, register::SingleEightBit::H, 0x11, 0xDD; "register h")]
|
|
|
|
|
#[test_case(0xB5, 0xCC, register::SingleEightBit::L, 0x11, 0xDD; "register l")]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0xB0, register::SingleEightBit:: B),
|
|
|
|
|
(0xB1, register::SingleEightBit:: C),
|
|
|
|
|
(0xB2, register::SingleEightBit:: D),
|
|
|
|
|
(0xB3, register::SingleEightBit:: E),
|
|
|
|
|
(0xB4, register::SingleEightBit:: H),
|
|
|
|
|
(0xB5, register::SingleEightBit:: L),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0xCC, 0x11, 0xDD),
|
|
|
|
|
(0x00, 0x1F, 0x1F)
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_or_register_with_a_value(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
a_value: u8,
|
|
|
|
|
operand_register: register::SingleEightBit,
|
|
|
|
|
operand: u8,
|
|
|
|
|
expected_value: u8,
|
|
|
|
|
(opcode, operand_register): (u8, register::SingleEightBit),
|
|
|
|
|
(a_value, operand, expected_value): (u8, u8, u8),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor
|
|
|
|
@ -1592,24 +1517,23 @@ fn test_or_register_with_a_value(
|
|
|
|
|
assert_eq!(expected_value, processor.registers.a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0xB0, 0xCC, register::SingleEightBit::B, 0x22, 0; "register b, not zero")]
|
|
|
|
|
#[test_case(0xB0, 0x00, register::SingleEightBit::B, 0x00, 1; "register b, zero")]
|
|
|
|
|
#[test_case(0xB1, 0xCC, register::SingleEightBit::C, 0x22, 0; "register c, not zero")]
|
|
|
|
|
#[test_case(0xB1, 0x00, register::SingleEightBit::C, 0x00, 1; "register c, zero")]
|
|
|
|
|
#[test_case(0xB2, 0xCC, register::SingleEightBit::D, 0x22, 0; "register d, not zero")]
|
|
|
|
|
#[test_case(0xB2, 0x00, register::SingleEightBit::D, 0x00, 1; "register d, zero")]
|
|
|
|
|
#[test_case(0xB3, 0xCC, register::SingleEightBit::E, 0x22, 0; "register e, not zero")]
|
|
|
|
|
#[test_case(0xB3, 0x00, register::SingleEightBit::E, 0x00, 1; "register e, zero")]
|
|
|
|
|
#[test_case(0xB4, 0xCC, register::SingleEightBit::H, 0x22, 0; "register h, not zero")]
|
|
|
|
|
#[test_case(0xB4, 0x00, register::SingleEightBit::H, 0x00, 1; "register h, zero")]
|
|
|
|
|
#[test_case(0xB5, 0xCC, register::SingleEightBit::L, 0x22, 0; "register l, not zero")]
|
|
|
|
|
#[test_case(0xB5, 0x00, register::SingleEightBit::L, 0x00, 1; "register l, zero")]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0xB0, register::SingleEightBit::B),
|
|
|
|
|
(0xB1, register::SingleEightBit::C),
|
|
|
|
|
(0xB2, register::SingleEightBit::D),
|
|
|
|
|
(0xB3, register::SingleEightBit::E),
|
|
|
|
|
(0xB4, register::SingleEightBit::H),
|
|
|
|
|
(0xB5, register::SingleEightBit::L),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0xCC, 0x22, 0),
|
|
|
|
|
(0x00, 0x00, 1),
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_or_register_with_a_flags(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
a_value: u8,
|
|
|
|
|
operand_register: register::SingleEightBit,
|
|
|
|
|
operand: u8,
|
|
|
|
|
expected_zero_flag: u8,
|
|
|
|
|
(opcode, operand_register): (u8, register::SingleEightBit),
|
|
|
|
|
(a_value, operand, expected_zero_flag): (u8, u8, u8),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
// Set all the register to the opposite we expect to ensure they all get set
|
|
|
|
@ -2136,40 +2060,41 @@ fn test_comparing_immediate_value_to_a(
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0x04, register::SingleEightBit::B, 0x05, 0x06; "add one, register B")]
|
|
|
|
|
#[test_case(0x04, register::SingleEightBit::B, 0xFF, 0x00; "add one with wrapping, register B")]
|
|
|
|
|
#[test_case(0x0C, register::SingleEightBit::C, 0x05, 0x06; "add one, register C")]
|
|
|
|
|
#[test_case(0x0C, register::SingleEightBit::C, 0xFF, 0x00; "add one with wrapping, register C")]
|
|
|
|
|
#[test_case(0x14, register::SingleEightBit::D, 0x05, 0x06; "add one, register D")]
|
|
|
|
|
#[test_case(0x14, register::SingleEightBit::D, 0xFF, 0x00; "add one with wrapping, register D")]
|
|
|
|
|
#[test_case(0x1C, register::SingleEightBit::E, 0x05, 0x06; "add one, register E")]
|
|
|
|
|
#[test_case(0x1C, register::SingleEightBit::E, 0xFF, 0x00; "add one with wrapping, register E")]
|
|
|
|
|
#[test_case(0x24, register::SingleEightBit::H, 0x05, 0x06; "add one, register H")]
|
|
|
|
|
#[test_case(0x24, register::SingleEightBit::H, 0xFF, 0x00; "add one with wrapping, register H")]
|
|
|
|
|
#[test_case(0x2C, register::SingleEightBit::L, 0x05, 0x06; "add one, register L")]
|
|
|
|
|
#[test_case(0x2C, register::SingleEightBit::L, 0xFF, 0x00; "add one with wrapping, register L")]
|
|
|
|
|
#[test_case(0x3C, register::SingleEightBit::A, 0x05, 0x06; "add one, register A")]
|
|
|
|
|
#[test_case(0x3C, register::SingleEightBit::A, 0xFF, 0x00; "add one with wrapping, register A")]
|
|
|
|
|
// increment
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0x04, register::SingleEightBit:: B),
|
|
|
|
|
(0x0C, register::SingleEightBit:: C),
|
|
|
|
|
(0x14, register::SingleEightBit:: D),
|
|
|
|
|
(0x1C, register::SingleEightBit:: E),
|
|
|
|
|
(0x24, register::SingleEightBit:: H),
|
|
|
|
|
(0x2C, register::SingleEightBit:: L),
|
|
|
|
|
(0x3C, register::SingleEightBit:: A),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0x05, 0x06),
|
|
|
|
|
(0xFF, 0x00),
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
// decrement
|
|
|
|
|
#[test_case(0x05, register::SingleEightBit::B, 0x05, 0x04; "sub one, register B")]
|
|
|
|
|
#[test_case(0x05, register::SingleEightBit::B, 0x00, 0xFF; "sub one with wrapping, register B")]
|
|
|
|
|
#[test_case(0x0D, register::SingleEightBit::C, 0x05, 0x04; "sub one, register C")]
|
|
|
|
|
#[test_case(0x0D, register::SingleEightBit::C, 0x00, 0xFF; "sub one with wrapping, register C")]
|
|
|
|
|
#[test_case(0x15, register::SingleEightBit::D, 0x05, 0x04; "sub one, register D")]
|
|
|
|
|
#[test_case(0x15, register::SingleEightBit::D, 0x00, 0xFF; "sub one with wrapping, register D")]
|
|
|
|
|
#[test_case(0x1D, register::SingleEightBit::E, 0x05, 0x04; "sub one, register E")]
|
|
|
|
|
#[test_case(0x1D, register::SingleEightBit::E, 0x00, 0xFF; "sub one with wrapping, register E")]
|
|
|
|
|
#[test_case(0x25, register::SingleEightBit::H, 0x05, 0x04; "sub one, register H")]
|
|
|
|
|
#[test_case(0x25, register::SingleEightBit::H, 0x00, 0xFF; "sub one with wrapping, register H")]
|
|
|
|
|
#[test_case(0x2D, register::SingleEightBit::L, 0x05, 0x04; "sub one, register L")]
|
|
|
|
|
#[test_case(0x2D, register::SingleEightBit::L, 0x00, 0xFF; "sub one with wrapping, register L")]
|
|
|
|
|
#[test_case(0x3D, register::SingleEightBit::A, 0x05, 0x04; "sub one, register A")]
|
|
|
|
|
#[test_case(0x3D, register::SingleEightBit::A, 0x00, 0xFF; "sub one with wrapping, register A")]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0x05, register::SingleEightBit:: B),
|
|
|
|
|
(0x0D, register::SingleEightBit:: C),
|
|
|
|
|
(0x15, register::SingleEightBit:: D),
|
|
|
|
|
(0x1D, register::SingleEightBit:: E),
|
|
|
|
|
(0x25, register::SingleEightBit:: H),
|
|
|
|
|
(0x2D, register::SingleEightBit:: L),
|
|
|
|
|
(0x3D, register::SingleEightBit:: A),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0x05, 0x04),
|
|
|
|
|
(0x00, 0xFF),
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_increment_decrement_single_register_value(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
register: register::SingleEightBit,
|
|
|
|
|
initial_value: u8,
|
|
|
|
|
expected_value: u8,
|
|
|
|
|
(opcode, register): (u8, register::SingleEightBit),
|
|
|
|
|
(initial_value, expected_value): (u8, u8),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor
|
|
|
|
@ -2188,61 +2113,42 @@ fn test_increment_decrement_single_register_value(
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test_case(0x04, register::SingleEightBit::B, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 0}; "increment, register B")]
|
|
|
|
|
#[test_case(0x04, register::SingleEightBit::B, 0xFF, IncrementOperationFlags { zero: 1, half_carry: 1, subtract: 0}; "increment with wrapping, register B")]
|
|
|
|
|
#[test_case(0x04, register::SingleEightBit::B, 0x0F, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 0 }; "increment with half carry, register B")]
|
|
|
|
|
#[test_case(0x0C, register::SingleEightBit::C, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 0 }; "increment, register C")]
|
|
|
|
|
#[test_case(0x0C, register::SingleEightBit::C, 0xFF, IncrementOperationFlags { zero: 1, half_carry: 1, subtract: 0 }; "increment with wrapping, register C")]
|
|
|
|
|
#[test_case(0x0C, register::SingleEightBit::C, 0x0F, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 0 }; "increment with half carry, register C")]
|
|
|
|
|
#[test_case(0x14, register::SingleEightBit::D, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 0 }; "increment, register D")]
|
|
|
|
|
#[test_case(0x14, register::SingleEightBit::D, 0xFF, IncrementOperationFlags { zero: 1, half_carry: 1, subtract: 0 }; "increment with wrapping, register D")]
|
|
|
|
|
#[test_case(0x14, register::SingleEightBit::D, 0x0F, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 0 }; "increment with half carry, register D")]
|
|
|
|
|
#[test_case(0x1C, register::SingleEightBit::E, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 0 }; "increment, register E")]
|
|
|
|
|
#[test_case(0x1C, register::SingleEightBit::E, 0xFF, IncrementOperationFlags { zero: 1, half_carry: 1, subtract: 0 }; "increment with wrapping, register E")]
|
|
|
|
|
#[test_case(0x1C, register::SingleEightBit::E, 0x0F, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 0 }; "increment with half carry, register E")]
|
|
|
|
|
#[test_case(0x24, register::SingleEightBit::H, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 0 }; "increment, register H")]
|
|
|
|
|
#[test_case(0x24, register::SingleEightBit::H, 0xFF, IncrementOperationFlags { zero: 1, half_carry: 1, subtract: 0 }; "increment with wrapping, register H")]
|
|
|
|
|
#[test_case(0x24, register::SingleEightBit::H, 0x0F, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 0 }; "increment with half carry, register H")]
|
|
|
|
|
#[test_case(0x2C, register::SingleEightBit::L, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 0 }; "increment, register L")]
|
|
|
|
|
#[test_case(0x2C, register::SingleEightBit::L, 0xFF, IncrementOperationFlags { zero: 1, half_carry: 1, subtract: 0 }; "increment with wrapping, register L")]
|
|
|
|
|
#[test_case(0x2C, register::SingleEightBit::L, 0x0F, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 0 }; "increment with half carry, register L")]
|
|
|
|
|
#[test_case(0x3C, register::SingleEightBit::A, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 0 }; "increment, register A")]
|
|
|
|
|
#[test_case(0x3C, register::SingleEightBit::A, 0xFF, IncrementOperationFlags { zero: 1, half_carry: 1, subtract: 0 }; "increment with wrapping, register A")]
|
|
|
|
|
#[test_case(0x3C, register::SingleEightBit::A, 0x0F, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 0 }; "increment with half carry, register A")]
|
|
|
|
|
// decrement
|
|
|
|
|
#[test_case(0x05, register::SingleEightBit::B, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 1}; "decrement, register B")]
|
|
|
|
|
#[test_case(0x05, register::SingleEightBit::B, 0x00, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with wrapping, register B")]
|
|
|
|
|
#[test_case(0x05, register::SingleEightBit::B, 0x01, IncrementOperationFlags { zero: 1, half_carry: 0, subtract: 1}; "decrement to zero, register B")]
|
|
|
|
|
#[test_case(0x05, register::SingleEightBit::B, 0x10, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with half carry, register B")]
|
|
|
|
|
#[test_case(0x0D, register::SingleEightBit::C, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 1}; "decrement, register C")]
|
|
|
|
|
#[test_case(0x0D, register::SingleEightBit::C, 0x00, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with wrapping, register C")]
|
|
|
|
|
#[test_case(0x0D, register::SingleEightBit::C, 0x01, IncrementOperationFlags { zero: 1, half_carry: 0, subtract: 1}; "decrement to zero, register C")]
|
|
|
|
|
#[test_case(0x0D, register::SingleEightBit::C, 0x10, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with half carry, register C")]
|
|
|
|
|
#[test_case(0x15, register::SingleEightBit::D, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 1}; "decrement, register D")]
|
|
|
|
|
#[test_case(0x15, register::SingleEightBit::D, 0x00, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with wrapping, register D")]
|
|
|
|
|
#[test_case(0x15, register::SingleEightBit::D, 0x01, IncrementOperationFlags { zero: 1, half_carry: 0, subtract: 1}; "decrement to zero, register D")]
|
|
|
|
|
#[test_case(0x15, register::SingleEightBit::D, 0x10, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with half carry, register D")]
|
|
|
|
|
#[test_case(0x1D, register::SingleEightBit::E, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 1}; "decrement, register E")]
|
|
|
|
|
#[test_case(0x1D, register::SingleEightBit::E, 0x00, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with wrapping, register E")]
|
|
|
|
|
#[test_case(0x1D, register::SingleEightBit::E, 0x01, IncrementOperationFlags { zero: 1, half_carry: 0, subtract: 1}; "decrement to zero, register E")]
|
|
|
|
|
#[test_case(0x1D, register::SingleEightBit::E, 0x10, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with half carry, register E")]
|
|
|
|
|
#[test_case(0x25, register::SingleEightBit::H, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 1}; "decrement, register H")]
|
|
|
|
|
#[test_case(0x25, register::SingleEightBit::H, 0x00, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with wrapping, register H")]
|
|
|
|
|
#[test_case(0x25, register::SingleEightBit::H, 0x01, IncrementOperationFlags { zero: 1, half_carry: 0, subtract: 1}; "decrement to zero, register H")]
|
|
|
|
|
#[test_case(0x25, register::SingleEightBit::H, 0x10, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with half carry, register H")]
|
|
|
|
|
#[test_case(0x2D, register::SingleEightBit::L, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 1}; "decrement, register L")]
|
|
|
|
|
#[test_case(0x2D, register::SingleEightBit::L, 0x00, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with wrapping, register L")]
|
|
|
|
|
#[test_case(0x2D, register::SingleEightBit::L, 0x01, IncrementOperationFlags { zero: 1, half_carry: 0, subtract: 1}; "decrement to zero, register L")]
|
|
|
|
|
#[test_case(0x2D, register::SingleEightBit::L, 0x10, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with half carry, register L")]
|
|
|
|
|
#[test_case(0x3D, register::SingleEightBit::A, 0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 1}; "decrement, register A")]
|
|
|
|
|
#[test_case(0x3D, register::SingleEightBit::A, 0x00, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with wrapping, register A")]
|
|
|
|
|
#[test_case(0x3D, register::SingleEightBit::A, 0x01, IncrementOperationFlags { zero: 1, half_carry: 0, subtract: 1}; "decrement to zero, register A")]
|
|
|
|
|
#[test_case(0x3D, register::SingleEightBit::A, 0x10, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with half carry, register A")]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0x04, register::SingleEightBit::B),
|
|
|
|
|
(0x0C, register::SingleEightBit::C),
|
|
|
|
|
(0x14, register::SingleEightBit::D),
|
|
|
|
|
(0x1C, register::SingleEightBit::E),
|
|
|
|
|
(0x24, register::SingleEightBit::H),
|
|
|
|
|
(0x2C, register::SingleEightBit::L),
|
|
|
|
|
(0x3C, register::SingleEightBit::A),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 0}),
|
|
|
|
|
(0xFF, IncrementOperationFlags { zero: 1, half_carry: 1, subtract: 0}),
|
|
|
|
|
(0x0F, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 0}),
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
#[test_matrix(
|
|
|
|
|
[
|
|
|
|
|
(0x05, register::SingleEightBit::B),
|
|
|
|
|
(0x0D, register::SingleEightBit::C),
|
|
|
|
|
(0x15, register::SingleEightBit::D),
|
|
|
|
|
(0x1D, register::SingleEightBit::E),
|
|
|
|
|
(0x25, register::SingleEightBit::H),
|
|
|
|
|
(0x2D, register::SingleEightBit::L),
|
|
|
|
|
(0x3D, register::SingleEightBit::A),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
(0x05, IncrementOperationFlags { zero: 0, half_carry: 0, subtract: 1}),
|
|
|
|
|
(0x01, IncrementOperationFlags { zero: 1, half_carry: 0, subtract: 1}),
|
|
|
|
|
(0x10, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}),
|
|
|
|
|
(0x00, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}),
|
|
|
|
|
]
|
|
|
|
|
)]
|
|
|
|
|
fn test_increment_decrement_single_register_flags(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
register: register::SingleEightBit,
|
|
|
|
|
initial_value: u8,
|
|
|
|
|
expected_flags: IncrementOperationFlags,
|
|
|
|
|
(opcode, register): (u8, register::SingleEightBit),
|
|
|
|
|
(initial_value, expected_flags): (u8, IncrementOperationFlags),
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor
|
|
|
|
@ -2313,7 +2219,11 @@ fn test_increment_decrement_hl_value(opcode: u8, initial_value: u8, expected_val
|
|
|
|
|
#[test_case(0x35, 0x01, IncrementOperationFlags { zero: 1, half_carry: 0, subtract: 1}; "decrement to zero")]
|
|
|
|
|
#[test_case(0x35, 0x00, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with wrapping")]
|
|
|
|
|
#[test_case(0x35, 0x10, IncrementOperationFlags { zero: 0, half_carry: 1, subtract: 1}; "decrement with half carry")]
|
|
|
|
|
fn test_increment_decrement_hl_flags(opcode: u8, initial_value: u8, expected_flags: IncrementOperationFlags) {
|
|
|
|
|
fn test_increment_decrement_hl_flags(
|
|
|
|
|
opcode: u8,
|
|
|
|
|
initial_value: u8,
|
|
|
|
|
expected_flags: IncrementOperationFlags,
|
|
|
|
|
) {
|
|
|
|
|
let mut processor = Processor::default();
|
|
|
|
|
processor
|
|
|
|
|
.registers
|
|
|
|
|