private static void Transfer(OpCode op, bool decrement, bool isOutput) { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(op); if (isOutput) { fixture.With(c => c.Mmu.Setup(x => x.ReadByte(c.Registers.HL)).Returns(c.Byte).Verifiable()); fixture.Assert(c => c.Io.Verify(x => x.WriteByteToPort(c.Registers.C, c.InitialRegisters.B, c.Byte))); } else { fixture.With(c => c.Io.Setup(x => x.ReadByteFromPort(c.Registers.C, c.InitialRegisters.B)).Returns(c.Byte).Verifiable()); fixture.Assert(c => c.Mmu.Verify(x => x.WriteByte(c.InitialRegisters.HL, c.Byte))); } fixture.Assert(c => c.Registers.B.ShouldBe(unchecked ((byte)(c.InitialRegisters.B - 1)))); fixture.AssertFlags(c => c.Registers.B, subtract: true, setResult: true); if (decrement) { fixture.Assert(c => c.Registers.HL.ShouldBe(unchecked ((ushort)(c.InitialRegister16(Operand.HL) - 1)))); } else { fixture.Assert(c => c.Registers.HL.ShouldBe(unchecked ((ushort)(c.InitialRegister16(Operand.HL) + 1)))); } } }
public void TransferRepeat(OpCode op, bool decrement) { var repeats = Rng.Word(2, 10); using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(op); fixture.RuntimeTiming((repeats - 1) * 5, (repeats - 1) * 21); const ushort HL = 100, DE = 1000; // Avoiding overflows. fixture.With(c => c.Registers.BC = repeats, c => c.Registers.HL = HL, c => c.Registers.DE = DE); if (decrement) { fixture.Assert(c => c.Mmu.Verify(x => x.TransferByte(It.Is <ushort>(b => b > HL - repeats && b <= HL), It.Is <ushort>(b => b > DE - repeats && b <= DE)), Times.Exactly(repeats))); fixture.Assert(c => c.Registers.HL.ShouldBe((ushort)(HL - repeats)), c => c.Registers.DE.ShouldBe((ushort)(DE - repeats))); } else { fixture.Assert(c => c.Mmu.Verify(x => x.TransferByte(It.Is <ushort>(b => b >= HL && b < HL + repeats), It.Is <ushort>(b => b >= DE && b < DE + repeats)), Times.Exactly(repeats))); fixture.Assert(c => c.Registers.HL.ShouldBe((ushort)(HL + repeats)), c => c.Registers.DE.ShouldBe((ushort)(DE + repeats))); } fixture.Assert(c => c.Registers.BC.ShouldBe((ushort)0)); } }
private static void TestHalt(OpCode op) { using (var fixture = new ExecuteFixture().DoNotHalt()) { fixture.Operation.OpCode(op); } }
public void JumpRelative() { using (var fixture = new ExecuteFixture().DoNotHalt()) { SetupRelativeJump(fixture, OpCode.JumpRelative, FlagTest.None); } }
private static void SetupJump(ExecuteFixture fixture, OpCode op, FlagTest test, bool success = true) { fixture.Operation.OpCode(op).Operands(Operand.nn).RandomLiterals().FlagTest(test); var times = success ? Times.Exactly(1) : Times.Never(); fixture.Assert(c => c.MockRegisters.VerifySet(r => r.ProgramCounter = c.Operation.WordLiteral, times)); }
private static void SetupRelativeJump(ExecuteFixture fixture, OpCode op, FlagTest test, bool success = true) { fixture.Operation.OpCode(op).RandomLiterals().FlagTest(test); var times = success ? Times.Exactly(1) : Times.Never(); fixture.Assert(c => c.MockRegisters.VerifySet(r => r.ProgramCounter = unchecked ((ushort)(c.InitialProgramCounter + c.BlockLength + c.Operation.Displacement)), times)); }
private static void TestCall(OpCode op) { using (var fixture = new ExecuteFixture().DoNotHalt()) { SetupCall(fixture, op, FlagTest.None); } }
private static void TestRepeat(OpCode op, bool decrement) { using (var fixture = new ExecuteFixture()) { const ushort HL = 100; // Change HL so we don't need to worry about overflow. var repeats = Rng.Word(2, 10); fixture.Operation.OpCode(op); fixture.With(c => c.Registers.BC = repeats, c => c.Registers.HL = HL); fixture.RuntimeTiming((repeats - 1) * 5, (repeats - 1) * 21); if (decrement) { fixture.With(c => c.Mmu.Setup(x => x.ReadByte(It.Is <ushort>(a => a <= HL && a > HL - repeats))).Returns <ushort>(a => (byte)(HL - a))); fixture.Assert(c => c.Mmu.Verify(x => x.ReadByte(It.Is <ushort>(a => a <= HL && a > HL - repeats)), Times.Exactly(repeats))); } else { fixture.With(c => c.Mmu.Setup(x => x.ReadByte(It.Is <ushort>(a => a >= HL && a < HL + repeats))).Returns <ushort>(a => (byte)(a - HL))); fixture.Assert(c => c.Mmu.Verify(x => x.ReadByte(It.Is <ushort>(a => a >= HL && a < HL + repeats)), Times.Exactly(repeats))); } fixture.Assert(c => c.Alu.Verify(x => x.Compare(c.Accumulator.A, It.Is <byte>(b => b < repeats)))); fixture.Assert(c => c.Registers.BC.ShouldBe((ushort)0)); } }
public void CallWithTest_Success(FlagTest test) { using (var fixture = new ExecuteFixture().DoNotHalt().RuntimeTiming(2, 7)) { fixture.With(c => c.Flags.Setup(GetFlagExpression(test)).Returns(GetPositiveValue(test))); SetupCall(fixture, OpCode.Call, test); } }
private static void SetupCall(ExecuteFixture fixture, OpCode op, FlagTest test, bool success = true) { SetupJump(fixture, op, test, success); var times = success ? Times.Exactly(1) : Times.Never(); fixture.Assert(c => c.MockRegisters.VerifySet(r => r.StackPointer = c.PushedStackPointer, times), c => c.Mmu.Verify(x => x.WriteWord(c.StackPointer, c.SyncedProgramCounter), times)); }
public void ReturnFromInterrupt() { using (var fixture = new ExecuteFixture().DoNotHalt()) { SetupReturn(fixture, OpCode.ReturnFromInterrupt, FlagTest.None); fixture.Assert(c => c.MockRegisters.VerifySet(x => x.InterruptFlipFlop1 = true)); } }
public void JumpWithTest_Fail(FlagTest test) { using (var fixture = new ExecuteFixture().DoNotHalt()) { fixture.With(c => c.Flags.Setup(GetFlagExpression(test)).Returns(!GetPositiveValue(test))); SetupJump(fixture, OpCode.Jump, test, false); } }
public void BitTest(Operand o, byte bit) { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(OpCode.BitTest).Operands(o).ByteLiteral(bit); fixture.With(c => c.Alu.Setup(x => x.BitTest(c.Operand8(o), bit)).Verifiable()); } }
private static void SetInterruptMode(OpCode op, InterruptMode mode) { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(op); fixture.Assert(c => c.MockRegisters.VerifySet(x => x.InterruptMode = mode)); } }
public void Decrement16() { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(OpCode.Decrement16).Random16BitRegister(out var o); fixture.Assert(c => c.Operand16(o).ShouldBe(unchecked ((ushort)(c.InitialRegister16(o) - 1)))); } }
private static void ManageInterrupts(OpCode o, bool value) { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(o); fixture.Assert(c => c.MockRegisters.VerifySet(r => r.InterruptFlipFlop1 = value), c => c.MockRegisters.VerifySet(r => r.InterruptFlipFlop2 = value)); } }
public void ExchangeGeneralPurpose() { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(OpCode.ExchangeGeneralPurpose); fixture.Assert(c => c.MockRegisters.Verify(x => x.SwitchToAlternativeGeneralPurposeRegisters(), Times.Once)); } }
public void When_writing_16bit_operands(Operand r) { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(OpCode.Load16).Operands(r).Random16BitRegister2(out var o).RandomLiterals(); fixture.Assert(c => c.Operand16(r).ShouldBe(c.Operand16(o))); } }
public void ExchangeAccumulatorAndFlags() { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(OpCode.ExchangeAccumulatorAndFlags); fixture.Assert(c => c.MockRegisters.Verify(x => x.SwitchToAlternativeAccumulatorAndFlagsRegisters(), Times.Once)); } }
public void JumpRelativeWithTest_Success(FlagTest test) { using (var fixture = new ExecuteFixture().DoNotHalt().RuntimeTiming(1, 5)) { fixture.With(c => c.Flags.Setup(GetFlagExpression(test)).Returns(GetPositiveValue(test))); SetupRelativeJump(fixture, OpCode.JumpRelative, test); } }
private static void TestCall(OpCode op, Expression <Action <IAlu, byte, byte> > f) { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(op).RandomRegister(out var o).RandomLiterals(); fixture.With(c => c.Alu.Setup(c.AluAction(f, Operand.A, o)).Verifiable()); } }
private static void FlagAflection(OpCode op, bool?sign = null, bool?zero = null, bool?halfCarry = null, bool?parityOverflow = null, bool?subtract = null, bool?carry = null) { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(op); fixture.AssertFlags(c => c.Accumulator.A, sign, zero, halfCarry, parityOverflow, subtract, carry); } }
public void NegateTwosComplement() { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(OpCode.NegateTwosComplement); fixture.With(c => c.Alu.Setup(alu => alu.Subtract(0, c.Accumulator.A)).Returns(c.Byte).Verifiable()); fixture.Assert(c => c.Accumulator.A.ShouldBe(c.Byte)); } }
public void DecimalArithmeticAdjust() { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(OpCode.DecimalArithmeticAdjust); fixture.With(c => c.Alu.Setup(alu => alu.DecimalAdjust(c.Accumulator.A, true)).Returns(c.Byte).Verifiable()); fixture.Assert(c => c.Accumulator.A.ShouldBe(c.Byte)); } }
public void DecrementJumpRelativeIfNonZero_Success() { using (var fixture = new ExecuteFixture().DoNotHalt().RuntimeTiming(1, 5)) { fixture.With(x => x.Registers.B = 2); SetupRelativeJump(fixture, OpCode.DecrementJumpRelativeIfNonZero, FlagTest.None); fixture.Assert(x => x.Registers.B.ShouldBe((byte)1)); } }
public void Exchange(Operand o0, Operand o1) { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(OpCode.Exchange).Operands(o0, o1); fixture.Assert(c => c.Operand16(o0).ShouldBe(c.InitialRegister16(o1)), c => c.Operand16(o1).ShouldBe(c.InitialRegister16(o0))); } }
public void BitReset(Operand o, byte bit) { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(OpCode.BitReset).Operands(o).ByteLiteral(bit); fixture.With(c => c.Alu.Setup(x => x.BitReset(c.Operand8(o), bit)).Returns(c.Byte).Verifiable()); fixture.Assert(c => c.Operand8(o).ShouldBe(c.Byte)); } }
private static void TestAssign(OpCode op, Expression <Func <IAlu, ushort, ushort, ushort> > f) { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(op).Random16BitRegisters(out var o1, out var o2); fixture.With(c => c.Alu.Setup(c.Alu16Call(f, o1, o2)).Returns(c.Word).Verifiable()); fixture.Assert(c => c.Operand16(o1).ShouldBe(c.Word)); } }
public void NegateOnesComplement() { using (var fixture = new ExecuteFixture()) { fixture.Operation.OpCode(OpCode.NegateOnesComplement); fixture.Assert(c => c.Accumulator.A.ShouldBe((byte)~c.InitialAccumulator.A)); fixture.AssertFlags(c => c.Accumulator.A, halfCarry: true, subtract: true); } }
public void DecrementJumpRelativeIfNonZero_Fail() { using (var fixture = new ExecuteFixture().DoNotHalt()) { fixture.With(x => x.Registers.B = 1); SetupRelativeJump(fixture, OpCode.DecrementJumpRelativeIfNonZero, FlagTest.None, false); fixture.Assert(x => x.Registers.B.ShouldBe((byte)0)); } }