Exemple #1
0
        public void PHP_Has_No_Side_Effects_On_Current_PS()
        {
            var test = new TestSpec()
            {
                SP        = 0xff,
                C         = false,      // Status bit 0
                Z         = true,
                I         = false,
                D         = true,
                B         = false,
                U         = true,
                V         = false,
                N         = true,       // Status bit 7
                OpCode    = OpCodeId.PHP,
                ExpectedC = false,      // Status bit 0
                ExpectedZ = true,
                ExpectedI = false,
                ExpectedD = true,
                ExpectedB = false,
                ExpectedU = true,
                ExpectedV = false,
                ExpectedN = true,       // Status bit 7
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #2
0
        public void RTI_Pops_PS_From_Stack_And_Clears_Break_And_Unknown_Flags()
        {
            byte psOnStack = 0x01;

            psOnStack.SetBit(StatusFlagBits.Break);  // The processor status on the stack will always (?) have Break flag set by the BRK instruction.
            psOnStack.SetBit(StatusFlagBits.Unused); // The processor status on the stack will always (?) have Unused flag set by the BRK instruction.

            byte expectedPSAfterInstruction = psOnStack;

            expectedPSAfterInstruction.ClearBit(StatusFlagBits.Break);  // The when poping the PS from stack, the instruction also clears Break flag
            expectedPSAfterInstruction.ClearBit(StatusFlagBits.Unused); // The when poping the PS from stack, the instruction also clears Break flag

            var test = new TestSpec()
            {
                SP         = 0xfc,
                PS         = 0x33,
                OpCode     = OpCodeId.RTI,
                ExpectedPS = expectedPSAfterInstruction,
                ExpectedSP = 0xfc + 3           // 1 byte for processor status, 2 bytes for return address
            };

            var mem = test.TestContext.Computer.Mem;

            // The processor status pushed to stack by BRK instruction (it was written last, but will be read in reverse order when it's popped)
            // The current SP always points to the next free location. So the last location that was used (by the BRK instruction) is one up (remember stack goes downwards)
            mem[(ushort)(CPU.StackBaseAddress + test.SP + 1)] = psOnStack;

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #3
0
        public void PHP_Pushes_Copy_Of_PS_To_Stack_With_Break_And_Unused_Flag_Set()
        {
            var test = new TestSpec()
            {
                SP     = 0xff,
                C      = false,         // Status bit 0
                Z      = true,
                I      = false,
                D      = true,
                B      = false,         // Status bit 4 (Break) clear when we start
                U      = false,         // Status bit 5 (Unused) clear when we start
                V      = false,
                N      = true,          // Status bit 7
                OpCode = OpCodeId.PHP,
            };

            test.Execute_And_Verify(AddrMode.Implied);

            // Verify that stack (the previous position) contains value of Status register.
            // Remember that stack works downwards (0xff-0x00), points to the next free location, and is located at address 0x0100 + SP
            ushort stackPointerFullAddress = CPU.StackBaseAddress + 0xfe + 1;
            byte   expectedPSOnStack       = test.PS.Value;

            expectedPSOnStack.SetBit(StatusFlagBits.Break);
            expectedPSOnStack.SetBit(StatusFlagBits.Unused);
            Assert.Equal(expectedPSOnStack, test.TestContext.Computer.Mem[stackPointerFullAddress]);
        }
Exemple #4
0
        public void PLP_Pops_Correct_Byte_From_Stack_When_SP_Wraps_Around_Byte_Limit()
        {
            byte expectedValueFromStack = 0x42;

            // We'll try to pop a byte from stack when it's at the top (nothing should be on stack then.).
            // This should lead to we pop the byte at 0x0100, and not 0x0200.
            var test = new TestSpec()
            {
                SP         = 0xff,
                PS         = 0x00,
                OpCode     = OpCodeId.PLP,
                ExpectedSP = 0x00,
                ExpectedPS = expectedValueFromStack,
            };

            // Prepare a value on the stack (one address higher than the current SP we use in test)
            // Remember that stack works downwards (0xff-0x00), points to the next free location, and is located at address 0x0100 + SP
            byte   SPToReadFrom = (byte)(test.SP + 1);
            ushort stackPointerFullAddressShouldPopFrom = (ushort)(CPU.StackBaseAddress + SPToReadFrom);

            test.TestContext.Computer.Mem[stackPointerFullAddressShouldPopFrom] = expectedValueFromStack;
            // The incorrect memory position with another value
            test.TestContext.Computer.Mem[(ushort)(CPU.StackBaseAddress + test.SP + 1)] = (byte)(expectedValueFromStack - 1);

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #5
0
        public void NOP_Executes_With_No_Side_Effects_Other_Than_PC_Changed_To_Next_Instruction()
        {
            var test = new TestSpec()
            {
                A          = 0xa3,
                X          = 0x38,
                Y          = 0xf2,
                SP         = 0xff,
                C          = false,
                Z          = false,
                I          = false,
                D          = false,
                B          = false,
                U          = false,
                V          = false,
                N          = false,
                OpCode     = OpCodeId.NOP,
                ExpectedA  = 0xa3,
                ExpectedX  = 0x38,
                ExpectedY  = 0xf2,
                ExpectedSP = 0xff,
                ExpectedC  = false,
                ExpectedZ  = false,
                ExpectedI  = false,
                ExpectedD  = false,
                ExpectedB  = false,
                ExpectedU  = false,
                ExpectedV  = false,
                ExpectedN  = false,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #6
0
        public void BRK_Sets_Interrupt_Flag_And_Nothing_Else()
        {
            var test = new TestSpec()
            {
                C         = false,      // Status bit 0
                Z         = true,
                I         = false,      // Status bit 4 (Interrupt) clear when we start
                D         = true,
                B         = false,
                U         = false,
                V         = false,
                N         = true,       // Status bit 7
                OpCode    = OpCodeId.BRK,
                ExpectedC = false,      // Unchanged.
                ExpectedZ = true,       // Unchanged
                ExpectedI = true,       // Status bit 4 (Interrupt) set after instruction
                ExpectedD = true,       // Unchanged
                ExpectedB = false,      // B flag should only be set on the copy of the status register that was pushed to stack
                ExpectedU = false,      // U flag should only be set on the copy of the status register that was pushed to stack
                ExpectedV = false,      // Unchanged
                ExpectedN = true,       // Unchanged
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #7
0
        public void PHA_Executes_With_No_Side_Effects_Other_Than_Pushing_A_To_Stack()
        {
            var test = new TestSpec()
            {
                SP         = 0xff,
                C          = false,
                Z          = false,
                I          = false,
                D          = false,
                B          = false,
                U          = false,
                V          = false,
                N          = false,
                OpCode     = OpCodeId.PHA,
                A          = 0x12,
                ExpectedSP = 0xfe,
                ExpectedC  = false,
                ExpectedZ  = false,
                ExpectedI  = false,
                ExpectedD  = false,
                ExpectedB  = false,
                ExpectedU  = false,
                ExpectedV  = false,
                ExpectedN  = false,
            };

            test.Execute_And_Verify(AddrMode.Implied);

            // Verify that stack (the previous position) contains value of A register.
            // Remember that stack works downwards (0xff-0x00), points to the next free location, and is located at address 0x0100 + SP
            ushort stackPointerFullAddress = CPU.StackBaseAddress + 0xfe + 1;

            Assert.Equal(test.A, test.TestContext.Computer.Mem[stackPointerFullAddress]);
        }
Exemple #8
0
        public void RTI_Takes_6_Cycles()
        {
            var test = new TestSpec()
            {
                OpCode         = OpCodeId.RTI,
                ExpectedCycles = 6,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #9
0
        public void BRK_Takes_Takes_7_Cycles()
        {
            var test = new TestSpec()
            {
                OpCode         = OpCodeId.BRK,
                ExpectedCycles = 7,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #10
0
        public void CLD_Takes_2_Cycles()
        {
            var test = new TestSpec()
            {
                OpCode         = OpCodeId.CLD,
                ExpectedCycles = 2,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #11
0
        public void PHA_Takes_3_Cycles()
        {
            var test = new TestSpec()
            {
                OpCode         = OpCodeId.PHA,
                ExpectedCycles = 3,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #12
0
        public void LSR_ACC_Takes_2_Cycles()
        {
            var test = new TestSpec()
            {
                OpCode         = OpCodeId.LSR_ACC,
                ExpectedCycles = 2,
            };

            test.Execute_And_Verify(AddrMode.Accumulator);
        }
Exemple #13
0
        public void INX_Increases_Register()
        {
            var test = new TestSpec()
            {
                X         = 0x01,
                OpCode    = OpCodeId.INX,
                ExpectedX = 0x02,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #14
0
        public void DEY_Decreases_Register()
        {
            var test = new TestSpec()
            {
                Y         = 0x02,
                OpCode    = OpCodeId.DEY,
                ExpectedY = 0x01,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #15
0
        public void STA_ZP_Takes_3_Cycles()
        {
            var test = new TestSpec()
            {
                InsEffect      = InstrEffect.Mem,
                OpCode         = OpCodeId.STA_ZP,
                ExpectedCycles = 3,
            };

            test.Execute_And_Verify(AddrMode.ZP);
        }
Exemple #16
0
        public void BIT_I_Takes_3_Cycles()
        {
            var test = new TestSpec()
            {
                OpCode         = OpCodeId.BIT_ZP,
                FinalValue     = 0,
                ExpectedCycles = 3,
            };

            test.Execute_And_Verify(AddrMode.ZP);
        }
Exemple #17
0
        public void SEI_Sets_InterruptDisable_Flag()
        {
            var test = new TestSpec()
            {
                I         = false,
                OpCode    = OpCodeId.SEI,
                ExpectedI = true,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #18
0
        public void CLV_Clears_Overflow_Flag()
        {
            var test = new TestSpec()
            {
                V         = true,
                OpCode    = OpCodeId.CLV,
                ExpectedV = false,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #19
0
        public void SEC_Sets_Carry_Flag()
        {
            var test = new TestSpec()
            {
                C         = false,
                OpCode    = OpCodeId.SEC,
                ExpectedC = true,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #20
0
        public void LDY_I_Sets_N_If_Result_Is_Negative()
        {
            var test = new TestSpec()
            {
                OpCode     = OpCodeId.LDY_I,
                FinalValue = 0xff,
                ExpectedN  = true,
            };

            test.Execute_And_Verify(AddrMode.I);
        }
Exemple #21
0
        public void ADC_Takes_2_Cycles()
        {
            var test = new TestSpec
            {
                OpCode         = OpCodeId.ADC_I,
                FinalValue     = 0x01,
                ExpectedCycles = 2,
            };

            test.Execute_And_Verify(AddrMode.I);
        }
Exemple #22
0
        public void LDY_I_Takes_2_Cycles()
        {
            var test = new TestSpec()
            {
                OpCode         = OpCodeId.LDY_I,
                FinalValue     = 0,
                ExpectedCycles = 2,
            };

            test.Execute_And_Verify(AddrMode.I);
        }
Exemple #23
0
        public void LDY_I_Sets_Z_If_Result_Is_0()
        {
            var test = new TestSpec()
            {
                OpCode     = OpCodeId.LDY_I,
                FinalValue = 0x00,
                ExpectedZ  = true,
            };

            test.Execute_And_Verify(AddrMode.I);
        }
Exemple #24
0
        public void LDY_I_Clears_N_If_Result_Is_Positive()
        {
            var test = new TestSpec()
            {
                OpCode     = OpCodeId.LDY_I,
                FinalValue = 0x10,
                ExpectedN  = false,
            };

            test.Execute_And_Verify(AddrMode.I);
        }
Exemple #25
0
        public void LDY_I_Clears_Z_If_Result_Is_Not_0()
        {
            var test = new TestSpec()
            {
                OpCode     = OpCodeId.LDY_I,
                FinalValue = 0x01,
                ExpectedZ  = false,
            };

            test.Execute_And_Verify(AddrMode.I);
        }
Exemple #26
0
        public void CLD_Clears_Decimal_Flag()
        {
            var test = new TestSpec()
            {
                D         = true,
                OpCode    = OpCodeId.CLD,
                ExpectedD = false,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #27
0
        public void LDY_I_Does_Correct_Logic_Operation3()
        {
            var test = new TestSpec
            {
                Y          = 0xff,
                OpCode     = OpCodeId.LDY_I,
                FinalValue = 0xab,
                ExpectedY  = 0xab,
            };

            test.Execute_And_Verify(AddrMode.I);
        }
Exemple #28
0
        public void INX_Clears_Zero_Flag_If_Result_Is_Not_Zero()
        {
            var test = new TestSpec()
            {
                X         = 0x00,
                OpCode    = OpCodeId.INX,
                ExpectedX = 0x01,
                ExpectedZ = false,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #29
0
        public void INX_Sets_Negative_Flag_If_Result_Is_Negative()
        {
            var test = new TestSpec()
            {
                X         = 0xfe,
                OpCode    = OpCodeId.INX,
                ExpectedX = 0xff,
                ExpectedN = true,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }
Exemple #30
0
        public void INX_Clears_Negative_Flag_If_Result_Is_Positive()
        {
            var test = new TestSpec()
            {
                X         = 0x01,
                OpCode    = OpCodeId.INX,
                ExpectedX = 0x02,
                ExpectedN = false,
            };

            test.Execute_And_Verify(AddrMode.Implied);
        }