예제 #1
0
        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))));
                }
            }
        }
예제 #2
0
        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));
            }
        }
예제 #3
0
        private static void TransferRepeat(OpCode op, bool decrement, bool isOutput)
        {
            using (var fixture = new ExecuteFixture())
            {
                const ushort HL      = 100; // Change HL so we don't need to worry about overflow.
                var          repeats = Rng.Byte(2, 10);
                fixture.Operation.OpCode(op);
                fixture.With(c => c.Registers.B = repeats, c => c.Registers.HL = HL);
                fixture.RuntimeTiming((repeats - 1) * 5, (repeats - 1) * 21);

                if (decrement)
                {
                    if (isOutput)
                    {
                        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.Assert(c => c.Mmu.Verify(x => x.WriteByte(It.Is <ushort>(a => a <= HL && a > HL - repeats), It.Is <byte>(b => b < repeats)), Times.Exactly(repeats)));
                    }
                }
                else
                {
                    if (isOutput)
                    {
                        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)));
                    }
                    else
                    {
                        fixture.Assert(c => c.Mmu.Verify(x => x.WriteByte(It.Is <ushort>(a => a >= HL && a < HL + repeats), It.Is <byte>(b => b < repeats)), Times.Exactly(repeats)));
                    }
                }

                if (isOutput)
                {
                    fixture.Assert(c => c.Io.Verify(x => x.WriteByteToPort(c.Registers.C, It.Is <byte>(b => b > 0 && b <= repeats), It.Is <byte>(b => b < repeats))));
                }
                else
                {
                    fixture.With(c => c.Io.Setup(x => x.ReadByteFromPort(c.Registers.C, It.Is <byte>(b => b > 0 && b <= repeats)))
                                 .Returns <byte, byte>((p, b) => (byte)(b - 1)));
                    fixture.Assert(c => c.Io.Verify(x => x.ReadByteFromPort(c.Registers.C, It.Is <byte>(b => b > 0 && b <= repeats)), Times.Exactly(repeats)));
                }

                fixture.Assert(c => c.Registers.B.ShouldBe((byte)0));
            }
        }
예제 #4
0
        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));
            }
        }
예제 #5
0
 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);
     }
 }
예제 #6
0
 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());
     }
 }
예제 #7
0
 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);
     }
 }
예제 #8
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);
     }
 }
예제 #9
0
 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());
     }
 }
예제 #10
0
 private static void TestAccumulatorAssign(OpCode op, Expression <Func <IAlu, byte, byte, byte> > f)
 {
     using (var fixture = new ExecuteFixture())
     {
         fixture.Operation.OpCode(op).RandomRegister(out var o).RandomLiterals();
         fixture.With(c => c.Alu.Setup(c.Alu8Call(f, Operand.A, o)).Returns(c.Byte).Verifiable());
         fixture.Assert(c => c.Accumulator.A.ShouldBe(c.Byte));
     }
 }
예제 #11
0
 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));
     }
 }
예제 #12
0
 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));
     }
 }
예제 #13
0
 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));
     }
 }
예제 #14
0
 public void ReturnFromNonmaskableInterrupt()
 {
     using (var fixture = new ExecuteFixture().DoNotHalt())
     {
         SetupReturn(fixture, OpCode.ReturnFromNonmaskableInterrupt, FlagTest.None);
         fixture.With(c => c.MockRegisters.Setup(x => x.InterruptFlipFlop2).Returns(true));
         fixture.Assert(c => c.MockRegisters.VerifySet(x => x.InterruptFlipFlop1 = true));
     }
 }
예제 #15
0
 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));
     }
 }
예제 #16
0
 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));
     }
 }
예제 #17
0
 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));
     }
 }
예제 #18
0
        private static void Test(OpCode op, Operand o, bool isOutput)
        {
            var addressMsb = o == Operand.n ? Operand.A : Operand.B;

            using (var fixture = new ExecuteFixture())
            {
                fixture.Operation.OpCode(op).RandomRegister(out var r).Operand2(o).RandomLiterals();

                if (isOutput)
                {
                    fixture.With(c => c.Io.Setup(x => x.WriteByteToPort(c.Operand8(o), c.InitialRegister8(addressMsb), c.Operand8(r))).Verifiable());
                }
                else
                {
                    fixture.With(c => c.Io.Setup(x => x.ReadByteFromPort(c.Operand8(o), c.InitialRegister8(addressMsb))).Returns(c.Byte).Verifiable());
                    fixture.Assert(c => c.Operand8(r).ShouldBe(c.Byte));
                }
            }
        }
예제 #19
0
파일: LoadTests.cs 프로젝트: jrp7/Alizarin
        public void When_reading_8bit_operands(Operand r)
        {
            using (var fixture = new ExecuteFixture())
            {
                fixture.Operation.OpCode(OpCode.Load).RandomRegister(out var o).Operand2(r).RandomLiterals();

                var value = Rng.Byte();
                fixture.With(c =>
                {
                    switch (c.Operation.Operand2)
                    {
                    case Operand.mHL:
                        c.Mmu.Setup(m => m.ReadByte(It.Is <ushort>(a => a == c.Registers.HL))).Returns(value).Verifiable();
                        break;

                    case Operand.mIXd:
                        c.Mmu.Setup(m => m.ReadByte(It.Is <ushort>(a => a == c.MockRegisters.Object.IX + c.Operation.Displacement))).Returns(value).Verifiable();
                        break;

                    case Operand.mIYd:
                        c.Mmu.Setup(m => m.ReadByte(It.Is <ushort>(a => a == c.MockRegisters.Object.IY + c.Operation.Displacement))).Returns(value).Verifiable();
                        break;

                    case Operand.mnn:
                        c.Mmu.Setup(m => m.ReadByte(It.Is <ushort>(a => a == c.Operation.WordLiteral))).Returns(value).Verifiable();
                        break;

                    case Operand.mCl:
                        c.Mmu.Setup(m => m.ReadByte(It.Is <ushort>(a => a == c.Registers.C + 0xff00))).Returns(value).Verifiable();
                        break;

                    case Operand.mnl:
                        c.Mmu.Setup(m => m.ReadByte(It.Is <ushort>(a => a == c.Operation.ByteLiteral + 0xff00))).Returns(value).Verifiable();
                        break;

                    case Operand.mBC:
                        c.Mmu.Setup(m => m.ReadByte(It.Is <ushort>(a => a == c.Registers.BC))).Returns(value).Verifiable();
                        break;

                    case Operand.mDE:
                        c.Mmu.Setup(m => m.ReadByte(It.Is <ushort>(a => a == c.Registers.DE))).Returns(value).Verifiable();
                        break;

                    case Operand.mSP:
                        c.Mmu.Setup(m => m.ReadByte(It.Is <ushort>(a => a == c.MockRegisters.Object.StackPointer))).Returns(value).Verifiable();
                        break;

                    default:
                        value = c.Operand8(c.Operation.Operand2);
                        break;
                    }
                });
                fixture.Assert(c => c.Operand8(o).ShouldBe(value));
            }
        }
예제 #20
0
 public void RotateRightDigit()
 {
     using (var fixture = new ExecuteFixture())
     {
         var result = RngFactory.Build <AccumulatorAndResult>()();
         fixture.Operation.OpCode(OpCode.RotateRightDigit);
         fixture.With(c => c.Mmu.Setup(x => x.ReadByte(c.Registers.HL)).Returns(c.Byte).Verifiable(),
                      c => c.Alu.Setup(x => x.RotateRightDigit(c.InitialAccumulator.A, c.Byte)).Returns(result).Verifiable());
         fixture.Assert(c => c.Accumulator.A.ShouldBe(result.Accumulator),
                        c => c.Mmu.Verify(x => x.WriteByte(c.Registers.HL, result.Result)));
     }
 }
예제 #21
0
        private static void TestCallAssign(OpCode op, Expression <Func <IAlu, byte, byte> > f, bool alternativeFlags = false)
        {
            using (var fixture = new ExecuteFixture())
            {
                fixture.Operation.OpCode(op).RandomRegister(out var o).RandomLiterals().UseAlternativeFlagAffection(alternativeFlags);
                fixture.With(c => c.Alu.Setup(c.Alu8Call(f, o)).Returns(c.Byte).Verifiable());
                fixture.Assert(c => c.Operand8(o).ShouldBe(c.Byte));

                if (alternativeFlags)
                {
                    fixture.AssertFlags(zero: false, sign: false);
                }
            }
        }
예제 #22
0
 private static void SetupReturn(ExecuteFixture fixture, OpCode op, FlagTest test, bool success = true)
 {
     fixture.Operation.OpCode(op).FlagTest(test);
     if (success)
     {
         fixture.With(c => c.Mmu.Setup(x => x.ReadWord(c.InitialStackPointer)).Returns(c.Word).Verifiable());
         fixture.Assert(c => c.MockRegisters.VerifySet(r => r.StackPointer   = c.PoppedStackPointer),
                        c => c.MockRegisters.VerifySet(r => r.ProgramCounter = c.Word));
     }
     else
     {
         fixture.Assert(c => c.Mmu.Verify(x => x.ReadWord(c.InitialStackPointer), Times.Never),
                        c => c.MockRegisters.VerifySet(r => r.StackPointer = c.PoppedStackPointer, Times.Never));
     }
 }
예제 #23
0
        private static void Test(OpCode op, bool decrement)
        {
            using (var fixture = new ExecuteFixture())
            {
                fixture.Operation.OpCode(op);
                fixture.With(c => c.Mmu.Setup(x => x.ReadByte(c.Registers.HL)).Returns(c.Byte).Verifiable());
                fixture.Assert(c => c.Alu.Verify(x => x.Compare(c.Accumulator.A, c.Byte)),
                               c => c.Registers.BC.ShouldBe(unchecked ((ushort)(c.InitialRegister16(Operand.BC) - 1))));

                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))));
                }
            }
        }
예제 #24
0
파일: LoadTests.cs 프로젝트: jrp7/Alizarin
        private static void LoadIndexRead(OpCode o)
        {
            using (var fixture = new ExecuteFixture())
            {
                fixture.Operation.OpCode(o).Operands(Operand.A, Operand.mHL);
                fixture.With(c => c.Mmu.Setup(x => x.ReadByte(c.InitialRegisters.HL)).Returns(c.Byte).Verifiable());
                fixture.Assert(c => c.Accumulator.A.ShouldBe(c.Byte));

                switch (o)
                {
                case OpCode.LoadIncrement:
                    fixture.Assert(c => c.Registers.HL.ShouldBe(unchecked ((ushort)(c.InitialRegisters.HL + 1))));
                    break;

                case OpCode.LoadDecrement:
                    fixture.Assert(c => c.Registers.HL.ShouldBe(unchecked ((ushort)(c.InitialRegisters.HL - 1))));
                    break;
                }
            }
        }
예제 #25
0
파일: LoadTests.cs 프로젝트: jrp7/Alizarin
        public void When_reading_16bit_operands(Operand r)
        {
            using (var fixture = new ExecuteFixture())
            {
                fixture.Operation.OpCode(OpCode.Load16).Random16BitRegister(out var o).Operand2(r).RandomLiterals();

                var value = Rng.Word();
                fixture.With(c =>
                {
                    if (r == Operand.SPd)
                    {
                        c.Alu.Setup(a => a.AddDisplacement(c.MockRegisters.Object.StackPointer, c.Operation.Displacement)).Returns(value);
                    }
                    else
                    {
                        value = c.Operand16(r);
                    }
                });

                fixture.Assert(c => c.Operand16(o).ShouldBe(value));
            }
        }
예제 #26
0
        public void Transfer(OpCode op, bool decrement, bool overflow)
        {
            using (var fixture = new ExecuteFixture())
            {
                fixture.Operation.OpCode(op);
                fixture.With(c => c.Registers.BC = (ushort)(overflow ? 2 : 1));
                fixture.Assert(c => c.Mmu.Verify(x => x.TransferByte(c.InitialRegisters.HL, c.InitialRegisters.DE)),
                               c => c.Registers.BC.ShouldBe((ushort)(overflow ? 1 : 0)));

                if (decrement)
                {
                    fixture.Assert(c => c.Registers.HL.ShouldBe(unchecked ((ushort)(c.InitialRegisters.HL - 1))),
                                   c => c.Registers.DE.ShouldBe(unchecked ((ushort)(c.InitialRegisters.DE - 1))));
                }
                else
                {
                    fixture.Assert(c => c.Registers.HL.ShouldBe(unchecked ((ushort)(c.InitialRegisters.HL + 1))),
                                   c => c.Registers.DE.ShouldBe(unchecked ((ushort)(c.InitialRegisters.DE + 1))));
                }

                fixture.AssertFlags(halfCarry: false, parityOverflow: overflow, subtract: false);
            }
        }