Пример #1
0
        public void TestStepNonMaskableInterrupt(bool initialIFF1, bool initialIFF2)
        {
            var initialState = new CPUConfig()
            {
                InterruptsEnabled = initialIFF1,
                InterruptsEnabledPreviousValue = initialIFF2,
                Registers = new CPURegisters()
                {
                    PC = 0x1234,
                    SP = 0x3FFF,
                },
            };

            var cpu = new CPU(initialState);

            var cycles = cpu.StepNonMaskableInterrupt();

            Assert.Equal(17, cycles);

            // We should've jumped to 0x0066.
            Assert.Equal(0x0066, cpu.Registers.PC);

            // Interrupts should be disabled (IFF1).
            Assert.False(cpu.InterruptsEnabled);

            // The previous value of IFF1 should have been preserved in IFF2.
            Assert.Equal(initialIFF1, cpu.InterruptsEnabledPreviousValue);

            // Ensure the previous program counter value was pushed onto the stack.
            Assert.Equal(0x3FFD, cpu.Registers.SP);
            Assert.Equal(0x12, cpu.Memory.Read(0x3FFE));
            Assert.Equal(0x34, cpu.Memory.Read(0x3FFD));
        }
Пример #2
0
        public void Test_LD_MRR_N_ToMemory()
        {
            var rom = AssembleSource($@"
                org 00h
                LD (HL), 42h
                HALT
            ");

            var registers = new CPURegisters();

            registers[Register.H] = 0x22;
            registers[Register.L] = 0x33;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x42, state.Memory[0x2233]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 10, state.Cycles);
            Assert.Equal(0x02, state.Registers.PC);
        }
        public void Test_IN_A_MN_DoesNotThrowExceptionIfNoHandlersPresent()
        {
            var rom = AssembleSource($@"
                org 00h
                IN A, (2)
                HALT
            ");

            var initialState = new CPUConfig();

            initialState.Registers = new CPURegisters()
            {
                A = 0x11,
            };

            var cpu = new CPU(initialState);

            var state = Execute(rom, cpu);

            Assert.Equal(0x00, state.Registers.A);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 10, state.Cycles);
            Assert.Equal(0x02, state.Registers.PC);
        }
Пример #4
0
        public void Test_INC_MIY_NoFlags(int offset)
        {
            var rom = AssembleSource($@"
                org 00h
                INC (IY {(offset < 0 ? '-' : '+')} {Math.Abs(offset)})
                HALT
            ");

            var registers = new CPURegisters()
            {
                IY = 0x2477,
            };

            var memory = new byte[16384];

            memory[0x2477 + offset] = 0x42;

            var initialState = new CPUConfig()
            {
                Registers = registers, Flags = new ConditionFlags()
                {
                    Subtract = true,
                },
            };

            var state = Execute(rom, memory, initialState);

            Assert.Equal(0x43, state.Memory[0x2477 + offset]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 23, state.Cycles);
            Assert.Equal(0x03, state.Registers.PC);
        }
Пример #5
0
        public void Test_ADD_A_N_OverflowFlag()
        {
            var rom = AssembleSource($@"
                org 00h
                ADD A, 2
                HALT
            ");

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    A = 127,
                },
            };

            var state = Execute(rom, initialState);

            Assert.Equal(129, state.Registers.A);

            Assert.True(state.Flags.Sign);
            Assert.False(state.Flags.Zero);
            Assert.True(state.Flags.HalfCarry);
            Assert.True(state.Flags.ParityOverflow);
            Assert.False(state.Flags.Subtract);
            Assert.False(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 7, state.Cycles);
            Assert.Equal(0x02, state.Registers.PC);
        }
        public void Test_IN_R_MC_DoesNotThrowExceptionIfNoHandlersPresent()
        {
            var rom = AssembleSource($@"
                org 00h
                IN B, (C)
                HALT
            ");

            var initialState = new CPUConfig();

            initialState.Registers   = new CPURegisters();
            initialState.Registers.C = 123;
            initialState.Registers.B = 44;

            var cpu = new CPU(initialState);

            var state = Execute(rom, cpu);

            Assert.Equal(0, state.Registers.B);

            Assert.False(state.Flags.Sign);
            Assert.True(state.Flags.Zero);
            Assert.True(state.Flags.ParityOverflow);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 12, state.Cycles);
            Assert.Equal(0x02, state.Registers.PC);
        }
Пример #7
0
        public void Test_DJNZ()
        {
            var rom = AssembleSource($@"
                org 00h
                NOP         ; $0000
                NOP         ; $0001
                DJNZ $+5    ; $0002
                NOP         ; $0004
                HALT        ; $0005
                HALT        ; $0006
                NOP         ; $0007
                JP $0002    ; $0008
                HALT        ; $0009
                HALT        ; $000A
            ");

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    B = 4,
                },
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x0000, state.Registers.SP);

            AssertFlagsFalse(state);

            Assert.Equal(14, state.Iterations);
            Assert.Equal(4 + (4 * 6) + (13 * 3) + (10 * 3) + 8, state.Cycles);
            Assert.Equal(0x0005, state.Registers.PC);
        }
Пример #8
0
        public void Test_JP_NC_Jumps()
        {
            var rom = AssembleSource($@"
                org 00h
                NOP         ; $0000
                NOP         ; $0001
                JP NC, 000Ah; $0002
                HALT        ; $0005
                NOP         ; $0006
                NOP         ; $0007
                NOP         ; $0008
                NOP         ; $0009
                HALT        ; $000A
            ");

            var initialState = new CPUConfig()
            {
                Flags = new ConditionFlags()
                {
                    Carry = false,
                },
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x0000, state.Registers.SP);

            AssertFlagsSame(initialState, state);

            Assert.Equal(4, state.Iterations);
            Assert.Equal(4 + (4 * 2) + 10, state.Cycles);
            Assert.Equal(0x000A, state.Registers.PC);
        }
        public void Test_LD_SP_HL()
        {
            var rom = AssembleSource($@"
                org 00h
                LD SP, HL
                HALT
            ");

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    HL = 0x2477,
                },
            };

            var state = Execute(rom, initialState);

            AssertFlagsFalse(state);

            Assert.Equal(0x2477, state.Registers.SP);
            Assert.Equal(0x2477, state.Registers.HL);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 6, state.Cycles);
            Assert.Equal(0x0001, state.Registers.PC);
        }
        public void Test_PUSH_IY()
        {
            var rom = AssembleSource($@"
                org 00h
                PUSH IY
                HALT
            ");

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    SP = 0x3000,
                    IY = 0x2477,
                },
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x2477, state.Registers.IY);
            Assert.Equal(0x00, state.Memory[0x3000]);
            Assert.Equal(0x24, state.Memory[0x2FFF]);
            Assert.Equal(0x77, state.Memory[0x2FFE]);
            Assert.Equal(0x2FFE, state.Registers.SP);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 15, state.Cycles);
            Assert.Equal(0x02, state.Registers.PC);
        }
        public void TestXCHG()
        {
            var rom = AssembleSource($@"
                org 00h
                EX DE, HL
                HALT
            ");

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    H = 0x42,
                    D = 0x99,
                    L = 0x77,
                    E = 0x88,
                },
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x99, state.Registers.H);
            Assert.Equal(0x42, state.Registers.D);
            Assert.Equal(0x88, state.Registers.L);
            Assert.Equal(0x77, state.Registers.E);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 4, state.Cycles);
            Assert.Equal(0x01, state.Registers.PC);
        }
        public void Test_LD_HL_MNN()
        {
            var rom = AssembleSource($@"
                org 00h
                LD HL, (2477h)
                HALT
            ");

            var memory = new byte[16384];

            memory[0x2477] = 0x77;
            memory[0x2478] = 0x66;

            var initialState = new CPUConfig()
            {
            };

            var state = Execute(rom, memory, initialState);

            Assert.Equal(0x66, state.Registers.H);
            Assert.Equal(0x77, state.Registers.L);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 16, state.Cycles);
            Assert.Equal(0x03, state.Registers.PC);
        }
Пример #13
0
        public void TestArithmeticAdditionSetsFlags(string valueA, string valueB, int expectedRegValue, int expectedRegSignedValue, ConditionFlags expected)
        {
            var rom = AssembleSource($@"
                org 00h
                LD A, {valueA}
                LD B, {valueB}
                ADD B
                HALT
            ");

            var initialState = new CPUConfig()
            {
                Flags = new ConditionFlags()
                {
                    Sign           = !expected.Sign,
                    Zero           = !expected.Zero,
                    HalfCarry      = !expected.HalfCarry,
                    ParityOverflow = !expected.ParityOverflow,
                    Subtract       = !expected.Subtract,
                    Carry          = !expected.Carry,
                },
            };

            var state = Execute(rom, initialState);

            Assert.Equal(expectedRegValue, state.Registers.A);
            Assert.Equal(expectedRegSignedValue, (sbyte)state.Registers.A);

            Assert.Equal(expected.Sign, state.Flags.Sign);
            Assert.Equal(expected.Zero, state.Flags.Zero);
            Assert.Equal(expected.HalfCarry, state.Flags.HalfCarry);
            Assert.Equal(expected.ParityOverflow, state.Flags.ParityOverflow);
            Assert.Equal(expected.Subtract, state.Flags.Subtract);
            Assert.Equal(expected.Carry, state.Flags.Carry);
        }
Пример #14
0
        public void TestStepMaskableInterrupt_Mode1()
        {
            var initialState = new CPUConfig()
            {
                InterruptsEnabled = true,
                InterruptMode     = InterruptMode.One,
                Registers         = new CPURegisters()
                {
                    PC = 0x1234,
                    SP = 0x3FFF,
                },
            };

            var cpu = new CPU(initialState);

            var cycles = cpu.StepMaskableInterrupt(0x00);

            Assert.Equal(11, cycles);

            // Interrupts should still be enabled (IFF1).
            Assert.True(cpu.InterruptsEnabled);

            // We should've jumped here.
            Assert.Equal(0x0038, cpu.Registers.PC);

            // Ensure the previous program counter value was pushed onto the stack.
            Assert.Equal(0x3FFD, cpu.Registers.SP);
            Assert.Equal(0x12, cpu.Memory.Read(0x3FFE));
            Assert.Equal(0x34, cpu.Memory.Read(0x3FFD));
        }
        public void Test_LD_MNN_HL()
        {
            // We have to assemble by hand here since LD (**), HL is a duplicate instruction
            // and the assembler will use the standard instruction instead of the undocumented
            // extended instruction.
            var rom = new byte[]
            {
                0xED, 0x63, // LD (NN), HL
                0x77, 0x24, // (2477h)
                0x76        // HALT
            };

            var memory = new byte[20490];

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    HL = 0x6677,
                },
            };

            var state = Execute(rom, memory, initialState);

            Assert.Equal(0x77, state.Memory[0x2477]);
            Assert.Equal(0x66, state.Memory[0x2478]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 20, state.Cycles);
            Assert.Equal(0x04, state.Registers.PC);
        }
Пример #16
0
        public void Test_ADC_A_N_NoFlags()
        {
            var rom = AssembleSource($@"
                org 00h
                ADC A, 18h
                HALT
            ");

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    A = 0x42,
                },
                Flags = new ConditionFlags()
                {
                    Carry = true,

                    // Ensure this is flipped to zero because this was an addition.
                    Subtract = true,
                },
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x5B, state.Registers.A);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 7, state.Cycles);
            Assert.Equal(0x02, state.Registers.PC);
        }
        public void Test_LD_MNN_RR(RegisterPair registerPair)
        {
            var rom = AssembleSource($@"
                org 00h
                LD (2477h), {registerPair}
                HALT
            ");

            var memory = new byte[20490];

            var initialState = new CPUConfig();

            initialState.Registers[registerPair] = 0x6677;

            var state = Execute(rom, memory, initialState);

            Assert.Equal(0x77, state.Memory[0x2477]);
            Assert.Equal(0x66, state.Memory[0x2478]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 20, state.Cycles);
            Assert.Equal(0x04, state.Registers.PC);
        }
Пример #18
0
        public void Test_DI()
        {
            var rom = AssembleSource($@"
                org 00h
                DI
                HALT
            ");

            var initialState = new CPUConfig()
            {
                InterruptsEnabled = true,
                InterruptsEnabledPreviousValue = true,
            };

            var state = Execute(rom, initialState);

            Assert.False(state.InterruptsEnabled);
            Assert.False(state.InterruptsEnabledPreviousValue);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 4, state.Cycles);
            Assert.Equal(0x01, state.Registers.PC);
        }
        public void Test_IN_R_MC_SetsFlags()
        {
            var rom = AssembleSource($@"
                org 00h
                IN (C)
                HALT
            ");

            var initialState = new CPUConfig();

            initialState.Registers   = new CPURegisters();
            initialState.Registers.C = 77;

            var cpu = new CPU(initialState);

            var actualDeviceId = -1;

            cpu.OnDeviceRead += (int deviceID) => {
                actualDeviceId = deviceID;
                return(213);
            };

            var state = Execute(rom, cpu);

            Assert.Equal(77, state.Registers.C);
            Assert.Equal(77, actualDeviceId);

            Assert.True(state.Flags.Sign);
            Assert.False(state.Flags.Zero);
            Assert.False(state.Flags.ParityOverflow);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 12, state.Cycles);
            Assert.Equal(0x02, state.Registers.PC);
        }
Пример #20
0
        public void Test_OR_A_NoFlags()
        {
            var rom = AssembleSource($@"
                org 00h
                OR A
                HALT
            ");

            var registers = new CPURegisters();

            registers.A = 0b01100100;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0b01100100, state.Registers.A);

            Assert.False(state.Flags.Sign);
            Assert.False(state.Flags.Zero);
            Assert.False(state.Flags.HalfCarry);
            Assert.False(state.Flags.ParityOverflow);
            Assert.False(state.Flags.Subtract);
            Assert.False(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 4, state.Cycles);
            Assert.Equal(0x01, state.Registers.PC);
        }
Пример #21
0
        public void Test_JP_HL()
        {
            var rom = AssembleSource($@"
                org 00h
                JP (HL) ; $0000
                NOP     ; $0001
                NOP     ; $0002
                HALT    ; $0003
            ");

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    HL = 0x003,
                },
            };

            var state = Execute(rom, initialState);

            AssertFlagsSame(initialState, state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 4, state.Cycles);
            Assert.Equal(0x0003, state.Registers.PC);
        }
        public void Test_ADD_A_MIY_ExampleFromManual()
        {
            var rom = AssembleSource($@"
                org 00h
                ADD A, (IY + 5h)
                HALT
            ");

            var memory = new byte[16 * 1024];

            memory[0x1005] = 0x22;

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    A  = 0x11,
                    IY = 0x1000,
                },
            };

            var state = Execute(rom, memory, initialState);

            Assert.Equal(0x33, state.Registers.A);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 19, state.Cycles);
            Assert.Equal(0x03, state.Registers.PC);
        }
Пример #23
0
        public void Test_EX_MSP_IY()
        {
            var rom = AssembleSource($@"
                org 00h
                EX (SP), IY
                HALT
            ");

            var memory = new byte[16384];

            memory[0x2222] = 0x99;
            memory[0x2223] = 0x88;

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    IY = 0x4277,
                    SP = 0x2222,
                },
            };

            var state = Execute(rom, memory, initialState);

            Assert.Equal(0x8899, state.Registers.IY);
            Assert.Equal(0x77, state.Memory[0x2222]);
            Assert.Equal(0x42, state.Memory[0x2223]);
            Assert.Equal(0x2222, state.Registers.SP);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 23, state.Cycles);
            Assert.Equal(0x02, state.Registers.PC);
        }
Пример #24
0
        public void Test_IM(int modeNumber, InterruptMode mode)
        {
            var rom = AssembleSource($@"
                org 00h
                IM {modeNumber}
                HALT
            ");

            var initialState = new CPUConfig()
            {
                InterruptsEnabled = false,
                InterruptsEnabledPreviousValue = false,
            };

            var cpu = new CPU(initialState);

            var state = Execute(rom, cpu);

            // Ensure the mode was set.
            Assert.Equal(mode, cpu.InterruptMode);

            // Setting mode does not enable interrupts.
            Assert.False(cpu.InterruptsEnabled);
            Assert.False(cpu.InterruptsEnabledPreviousValue);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 8, state.Cycles);
            Assert.Equal(0x02, state.Registers.PC);
        }
Пример #25
0
        public void Test_SUB_N_SignFlag()
        {
            var rom = AssembleSource($@"
                org 00h
                SUB 16h
                HALT
            ");

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    A = 0xFF,
                },
                Flags = new ConditionFlags()
                {
                    Subtract = false,
                },
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0xE9, state.Registers.A);

            Assert.True(state.Flags.Sign);
            Assert.False(state.Flags.Zero);
            Assert.False(state.Flags.HalfCarry);
            Assert.False(state.Flags.ParityOverflow);
            Assert.True(state.Flags.Subtract);
            Assert.False(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 7, state.Cycles);
            Assert.Equal(0x02, state.Registers.PC);
        }
Пример #26
0
        // [InlineData(Register.R, Register.A)] // TODO: Make specific tests for R register since it's special
        // [InlineData(Register.A, Register.R)]
        public void Test_LD(Register destReg, Register sourceReg)
        {
            var rom = AssembleSource($@"
                org 00h
                LD {destReg}, {sourceReg}
                HALT
            ");

            var initialState = new CPUConfig()
            {
                Registers = new CPURegisters()
                {
                    [sourceReg] = 0x42,
                    [destReg]   = 0x77,
                },
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x42, state.Registers[sourceReg]);
            Assert.Equal(0x42, state.Registers[destReg]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 9, state.Cycles);
            Assert.Equal(0x02, state.Registers.PC);
        }
Пример #27
0
        public void Test_SCF_SetsFalseToTrue()
        {
            var rom = AssembleSource($@"
                org 00h
                SCF
                HALT
            ");

            var initialState = new CPUConfig()
            {
                Flags = new ConditionFlags()
                {
                    Carry     = false,
                    Subtract  = true,
                    HalfCarry = true,
                },
            };

            var state = Execute(rom, initialState);

            Assert.False(state.Flags.Sign);
            Assert.False(state.Flags.Zero);
            Assert.False(state.Flags.HalfCarry);
            Assert.False(state.Flags.ParityOverflow);
            Assert.False(state.Flags.Subtract);
            Assert.True(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 4, state.Cycles);
            Assert.Equal(0x01, state.Registers.PC);
        }
        public void Test_LD_MNN_A()
        {
            var rom = AssembleSource($@"
                org 00h
                LD (2477h), A
                HALT
            ");

            var registers = new CPURegisters();

            registers.A = 0x42;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0x42, state.Memory[0x2477]);
            Assert.Equal(0x42, state.Registers.A);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 13, state.Cycles);
            Assert.Equal(0x03, state.Registers.PC);
        }
Пример #29
0
        public void Test_AND_ParityFlag(Register sourceReg)
        {
            var rom = AssembleSource($@"
                org 00h
                AND {sourceReg}
                HALT
            ");

            var registers = new CPURegisters();

            registers.A          = 0b11100101;
            registers[sourceReg] = 0b00101110;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, initialState);

            Assert.Equal(0b00100100, state.Registers.A);
            Assert.Equal(0b00101110, state.Registers[sourceReg]);

            Assert.False(state.Flags.Sign);
            Assert.False(state.Flags.Zero);
            Assert.True(state.Flags.HalfCarry);
            Assert.True(state.Flags.ParityOverflow);
            Assert.False(state.Flags.Subtract);
            Assert.False(state.Flags.Carry);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 4, state.Cycles);
            Assert.Equal(0x01, state.Registers.PC);
        }
Пример #30
0
        public void Test_LD_A_MRR(RegisterPair registerPair)
        {
            var rom = AssembleSource($@"
                org 00h
                LD A, ({registerPair})
                HALT
            ");

            var registers = new CPURegisters();

            registers[registerPair] = 0x2477;

            var memory = new byte[16384];

            memory[0x2477] = 0x42;

            var initialState = new CPUConfig()
            {
                Registers = registers,
            };

            var state = Execute(rom, memory, initialState);

            Assert.Equal(0x42, state.Memory[0x2477]);
            Assert.Equal(0x42, state.Registers.A);
            Assert.Equal(0x2477, state.Registers[registerPair]);

            AssertFlagsFalse(state);

            Assert.Equal(2, state.Iterations);
            Assert.Equal(4 + 7, state.Cycles);
            Assert.Equal(0x01, state.Registers.PC);
        }