void Test_ADC(Setter set, Opcode op, bool extra) { const auto expectedCycles = extra ? op.Cycles + 1 : op.Cycles; auto tester = [&] (Byte a, Byte m, Flag c, Byte expA, Flag expC, Flag expZ, Flag expV, Flag expN) { set(m); cpu.A = a; cpu.C = c; cpu.PC = BASE_PC; cpu.Ticks = BASE_TICKS; cpu.Execute(op); EXPECT_EQ(BASE_PC + op.Bytes, cpu.PC); EXPECT_EQ(BASE_TICKS + expectedCycles, cpu.Ticks); EXPECT_EQ(expA, cpu.A); EXPECT_EQ(expC, cpu.C); EXPECT_EQ(expZ, cpu.Z); EXPECT_EQ(expV, cpu.V); EXPECT_EQ(expN, cpu.N); }; tester(0x10, 0x20, 0, 0x30, 0, 0, 0, 0); // pos pos > pos tester(0x10, 0x20, 1, 0x31, 0, 0, 0, 0); // pos pos C > pos tester(0x00, 0x00, 0, 0x00, 0, 1, 0, 0); // Zero tester(0x7F, 0x80, 1, 0x00, 1, 1, 0, 0); // Zero by carry tester(0x80, 0x80, 0, 0x00, 1, 1, 1, 0); // Zero by overflow tester(0x20, 0xF0, 0, 0x10, 1, 0, 0, 0); // Carry w/o overflow w/o sign change tester(0xF0, 0x20, 0, 0x10, 1, 0, 0, 0); // Carry w/o overflow w/ sign change tester(0xA0, 0xA0, 0, 0x40, 1, 0, 1, 0); // Carry with overflow tester(0x70, 0x10, 0, 0x80, 0, 0, 1, 1); // Overflow pos > neg tester(0xB0, 0xB0, 0, 0x60, 1, 0, 1, 0); // Overflow neg > pos tester(0x00, 0xF0, 0, 0xF0, 0, 0, 0, 1); // Negative }
void Test_SBC(Setter set, Opcode op, int extra) { auto tester = [&] (Byte a, Byte m, Flag c, Byte expA, Flag expC, Flag expZ, Flag expV, Flag expN) { set(m); cpu.A = a; cpu.C = c; cpu.PC = BASE_PC; cpu.Ticks = BASE_TICKS; cpu.Execute(op); EXPECT_EQ(BASE_PC + op.Bytes, cpu.PC); EXPECT_EQ(BASE_TICKS + op.Cycles + extra, cpu.Ticks); EXPECT_EQ(expA, cpu.A); EXPECT_EQ(expC, cpu.C); EXPECT_EQ(expZ, cpu.Z); EXPECT_EQ(expV, cpu.V); EXPECT_EQ(expN, cpu.N); }; tester(0x40, 0x20, 1, 0x20, 0, 0, 0, 0); // pos pos > pos tester(0x40, 0x1F, 0, 0x20, 0, 0, 0, 0); // pos pos C > pos tester(0x00, 0x00, 1, 0x00, 0, 1, 0, 0); // Zero tester(0x80, 0x7F, 0, 0x00, 0, 1, 1, 0); // Zero by overflow tester(0x00, 0xFF, 0, 0x00, 1, 1, 0, 0); // Zero by carry tester(0x20, 0x40, 1, 0xE0, 1, 0, 0, 1); // Carry w/o overflow tester(0x20, 0xA0, 1, 0x80, 1, 0, 1, 1); // Carry w/ overflow tester(0x00, 0x00, 0, 0xFF, 1, 0, 0, 1); // Carry by borrow tester(0x20, 0xA0, 1, 0x80, 1, 0, 1, 1); // Overflow pos > neg tester(0x80, 0x20, 1, 0x60, 0, 0, 1, 0); // Overflow neg > pos tester(0x80, 0x00, 1, 0x80, 0, 0, 0, 1); // Negative }
void Test_Transfer(Getter get, Setter set, Opcode op) { auto tester = [&] (Byte value, Flag expZ, Flag expN) { set(value); cpu.PC = BASE_PC; cpu.Ticks = BASE_TICKS; cpu.Execute(op); EXPECT_EQ(BASE_PC + op.Bytes, cpu.PC); EXPECT_EQ(BASE_TICKS + op.Cycles, cpu.Ticks); EXPECT_EQ(value, get()); EXPECT_EQ(expZ, cpu.Z); EXPECT_EQ(expN, cpu.N); }; tester(0x20, 0, 0); tester(0xA0, 0, 1); tester(0x00, 1, 0); }
void Test_Branch(Setter set, Flag success, Flag failure, Opcode op) { auto tester = [&] (Word pc, Byte offset, Flag c, Word expPC, int extra) { cpu.Memory.SetByteAt(pc, 0xFF); cpu.Memory.SetByteAt(pc + 1, offset); set(c); cpu.PC = pc; cpu.Ticks = BASE_TICKS; cpu.Execute(op); EXPECT_EQ(expPC, cpu.PC); EXPECT_EQ(BASE_TICKS + op.Cycles + extra, cpu.Ticks); }; tester(0x0080, 0x20, failure, 0x0082, 0); // Fail tester(0x0080, 0x20, success, 0x00A0, 1); // Success, positive offset tester(0x0080, 0xE0, success, 0x0060, 1); // Success, negative offset tester(0x00F0, 0x20, success, 0x0110, 3); // Success, positive offset, crossing page tester(0x0110, 0xE0, success, 0x00F0, 3); // Success, negative offset, crossing page }
void Test_Compare(SetterReg setR, SetterMem setM, Opcode op, int extra) { auto tester = [&] (Byte r, Byte m, Flag expC, Flag expZ, Flag expN) { setR(r); setM(m); cpu.PC = BASE_PC; cpu.Ticks = BASE_TICKS; cpu.Execute(op); EXPECT_EQ(BASE_PC + op.Bytes, cpu.PC); EXPECT_EQ(BASE_TICKS + op.Cycles + extra, cpu.Ticks); EXPECT_EQ(expC, cpu.C); EXPECT_EQ(expZ, cpu.Z); EXPECT_EQ(expN, cpu.N); }; tester(0x20, 0x10, 1, 0, 0); // Greater tester(0x20, 0x20, 1, 1, 0); // Equal tester(0x20, 0x40, 0, 0, 1); // Lower tester(0xF0, 0xE0, 1, 0, 0); // Greater tester(0xF0, 0xF0, 1, 1, 0); // Equal tester(0xF0, 0xF8, 0, 0, 1); // Lower }