Beispiel #1
0
        public void TestTasBroken()
        {
            TAS.EmulateBrokenTAS = true;
            bus.WriteWord(4, 0x4AC0); //TAS D0
            cpu.SetPC(4);
            cpu.SetDataRegisterLong(0, 0);

            cpu.Execute();
            int res = cpu.GetDataRegisterLong(0);

            Assert.Equal(0, (res & 0xFF) >> 7);
        }
Beispiel #2
0
        public void TestBitwiseOperations()
        {
            // AND, OR, etc.
            var m68k = new MC68000();

            m68k.Execute(0x203C, 0x50); // D0: $50

            // ORI.L #$10,D0
            m68k.Execute(0x80, 0x12);

            Assert.AreEqual(0x52u, m68k.D0);
        }
Beispiel #3
0
        public void TestADD()
        {
            cpu.SetPC(4);
            cpu.SetDataRegisterByte(0, 0x40);
            cpu.SetDataRegisterByte(1, 0x80);
            bus.WriteWord(4, 0xd001); // add.b d1,d0
            int ticks = cpu.Execute();

            Assert.Equal(6, cpu.GetPC());
            Assert.Equal(0xc0, cpu.GetDataRegisterByte(0));
            Assert.Equal(0x80, cpu.GetDataRegisterByte(1));
            Assert.Equal(4, ticks);
            Assert.False(cpu.IsFlagSet(cpu.CFlag));
            Assert.False(cpu.IsFlagSet(cpu.VFlag));
            Assert.False(cpu.IsFlagSet(cpu.ZFlag));
            Assert.True(cpu.IsFlagSet(cpu.NFlag));
            Assert.False(cpu.IsFlagSet(cpu.XFlag));

            cpu.SetPC(4);
            cpu.SetDataRegisterWord(0, 0x8000);
            cpu.SetDataRegisterWord(1, 0x8500);
            bus.WriteWord(4, 0xd041); // add.w d1,d0
            ticks = cpu.Execute();
            Assert.Equal(6, cpu.GetPC());
            Assert.Equal(0x0500, cpu.GetDataRegisterWord(0));
            Assert.Equal(0x8500, cpu.GetDataRegisterWord(1));
            Assert.Equal(4, ticks);
            Assert.True(cpu.IsFlagSet(cpu.CFlag));
            Assert.True(cpu.IsFlagSet(cpu.VFlag));
            Assert.False(cpu.IsFlagSet(cpu.ZFlag));
            Assert.False(cpu.IsFlagSet(cpu.NFlag));
            Assert.True(cpu.IsFlagSet(cpu.XFlag));

            cpu.SetPC(4);
            cpu.SetDataRegisterLong(0, -4);
            cpu.SetDataRegisterLong(1, 0x04);
            bus.WriteWord(4, 0xd081); // add.l d1,d0
            ticks = cpu.Execute();
            Assert.Equal(6, cpu.GetPC());
            Assert.Equal(0, cpu.GetDataRegisterLong(0));
            Assert.Equal(0x04, cpu.GetDataRegisterWord(1));
            Assert.Equal(6, ticks);
            Assert.True(cpu.IsFlagSet(cpu.CFlag));
            Assert.False(cpu.IsFlagSet(cpu.VFlag));
            Assert.True(cpu.IsFlagSet(cpu.ZFlag));
            Assert.False(cpu.IsFlagSet(cpu.NFlag));
            Assert.True(cpu.IsFlagSet(cpu.XFlag));
        }
Beispiel #4
0
        public static void Run()
        {
            var m68k = new MC68000();
            var r    = new Random();

            while (true)
            {
                System.Threading.Thread.Sleep(150);

                // Operation code
                var op = (ushort)r.Next(ushort.MaxValue);
                // Operand
                var opr = (uint)r.Next(int.MaxValue);

                m68k.Execute(op, opr);

                Clear();

                WriteLine($" D0={m68k.D0:X8}  D1={m68k.D1:X8}  D2={m68k.D2:X8}  D3={m68k.D3:X8}");
                WriteLine($" D4={m68k.D4:X8}  D5={m68k.D5:X8}  D6={m68k.D6:X8}  D7={m68k.D7:X8}");
                WriteLine($" A0={m68k.A0:X8}  A1={m68k.A1:X8}  A2={m68k.A2:X8}  A3={m68k.A3:X8}");
                WriteLine($" A4={m68k.A4:X8}  A5={m68k.A5:X8}  A6={m68k.A6:X8}");
                WriteLine($"USP={m68k.USP:X6}  SSP={m68k.SSP:X6}  SR={m68k.SR:X4}");
                WriteLine();
                WriteLine($"{m68k.PC:X8}  {op:X4}  {opr:X8}");
            }
        }
Beispiel #5
0
        public void TestAddition()
        {
            var m68k = new MC68000();

            // Move immidiate value long 4 into register D0
            m68k.Execute(0x203C, 4);
            // Add immidiate value long 8 with register D0
            // ADD.L #8,D0
            m68k.Execute(0xD0BC, 8);

            Assert.AreEqual(12u, m68k.D0);

            // Move immidiate value long 10 into register D1 and
            // Move immidiate value long 11 into register D2
            m68k.Execute(0x223C, 10);
            m68k.Execute(0x243C, 11);
            // Add D1 with the value of D2 (long)
            // ADD.L D2,D1
            m68k.Execute(0xD382);

            Assert.AreEqual(21u, m68k.D1);

            // ADDQ.L 4,D1
            m68k.Execute(0x5881);

            Assert.AreEqual(25u, m68k.D1);

            // ADDQ.L 8,D0
            m68k.Execute(0x5080);

            Assert.AreEqual(20u, m68k.D0);
        }
Beispiel #6
0
        public void TestSubtraction()
        {
            var m68k = new MC68000();

            // Move immidiate value long 73 into register D0
            m68k.Execute(0x203C, 73);
            // Subtract immidiate value long 4 with register D0
            m68k.Execute(0x90BC, 4);

            Assert.AreEqual(69u, m68k.D0);

            // Move immidiate value long 63 into register D1 and
            // Move immidiate value long 21 into register D2
            m68k.Execute(0x223C, 63);
            m68k.Execute(0x243C, 21);
            // Subtract D1 with the value of D2 (long)
            m68k.Execute(0x9282);

            Assert.AreEqual(42u, m68k.D1);

            // SUBQ.L 4,D1
            m68k.Execute(0x5981);

            Assert.AreEqual(38u, m68k.D1);

            // SUBQ.L 8,D1
            m68k.Execute(0x5181);

            Assert.AreEqual(30u, m68k.D1);
        }
Beispiel #7
0
 private void TestSUBByteZeroFlag(MC68000 cpu, bool expectedZFlag, long d2_pre, long d2_post)
 {
     cpu.SetPC(4);
     cpu.SetDataRegisterLong(2, (int)d2_pre);
     cpu.Execute();
     Assert.Equal(d2_post, cpu.GetDataRegisterLong(2));
     Assert.Equal(0x00, cpu.GetDataRegisterByte(2));
     Assert.Equal(expectedZFlag, cpu.IsFlagSet(cpu.ZFlag));
 }
Beispiel #8
0
        public void TestBitShifting()
        {
            var m68k = new MC68000();

            // Move immidiate value long 4 into register D0
            m68k.Execute(0x203C, 4);

            // Rotate long D0 to the left for 4 bits immidiately
            // ROXL 4,D0
            m68k.Execute(0xE990);

            Assert.AreEqual(64u, m68k.D0); //  4 << 4 = 64

            m68k.Execute(0x223C, 2);       // 2 -> D1

            // Rotate long D0 to the right from D1 (2 bits)
            // ROXL D1,D0
            m68k.Execute(0xE2B0);

            Assert.AreEqual(16u, m68k.D0); // 64 >> 2 = 16
        }
Beispiel #9
0
        public void TestRegisters()
        {
            var m68k = new MC68000();

            // Data
            m68k.Execute(0x203C, 1);
            Assert.AreEqual(1u, m68k.D0);
            m68k.Execute(0x223C, 2);
            Assert.AreEqual(2u, m68k.D1);
            m68k.Execute(0x243C, 3);
            Assert.AreEqual(3u, m68k.D2);
            m68k.Execute(0x263C, 4);
            Assert.AreEqual(4u, m68k.D3);
            m68k.Execute(0x283C, 5);
            Assert.AreEqual(5u, m68k.D4);
            m68k.Execute(0x2A3C, 6);
            Assert.AreEqual(6u, m68k.D5);
            m68k.Execute(0x2C3C, 7);
            Assert.AreEqual(7u, m68k.D6);
            m68k.Execute(0x2E3C, 8);
            Assert.AreEqual(8u, m68k.D7);

            // Address
            m68k.Execute(0x20BC, 11);
            Assert.AreEqual(11u, m68k.A0);
            m68k.Execute(0x22BC, 12);
            Assert.AreEqual(12u, m68k.A1);
            m68k.Execute(0x24BC, 13);
            Assert.AreEqual(13u, m68k.A2);
            m68k.Execute(0x26BC, 14);
            Assert.AreEqual(14u, m68k.A3);
            m68k.Execute(0x28BC, 15);
            Assert.AreEqual(15u, m68k.A4);
            m68k.Execute(0x2ABC, 16);
            Assert.AreEqual(16u, m68k.A5);
            m68k.Execute(0x2CBC, 17);
            Assert.AreEqual(17u, m68k.A6);

            /*m68k.Execute(0x2CBC, 18);
             * Assert.AreEqual(17u, m68k.A7);*/

            // The next two instructions is from a manual (mbsd_l2.pdf) from
            // Ricardo Gutierrez-Osuna, Wright State University

            // MOVE.L #$12,d0 | 00 10 000 000 111 100 | 203C 00000012
            m68k.Execute(0x203C, 0x12);
            Assert.AreEqual(0x12u, m68k.D0);

            // MOVE.B data,d1 | 00 01 001 000 111 001 | 1239 00002000
            // self note: This goes at the address 2000 stored in data (a variable?) and
            //            loads 24h into D1 (manually?)
            //            Is this due to a higher language?
            //m68k.Execute(0x1239, 0x2000);
            //Assert.AreEqual(24u, m68k.D1);
        }
Beispiel #10
0
        public static void Enter()
        {
            var    m68k = new MC68000();
            string n;
            var    c = true; // Continue

            while (c)
            {
                n = null;
                do
                {
                    Write(">");
                    n = ReadLine();
                } while (n == null || n.Length == 0);

                if (!n.StartsWith("#")) // Remark/Comment
                {
                    switch (n[0])
                    {
                    case 'p':     // Print
                    {
                        var s = n.Split(
                            new[] { ' ' },
                            StringSplitOptions.RemoveEmptyEntries
                            );

                        switch (s.Length)
                        {
                        case 1:
                            WriteLine("No idea what to print.");
                            break;

                        case 2:
                            switch (s[1])         // Lazy..
                            {
                            case "d0":
                                WriteLine($"{m68k.D0:X8}");
                                break;

                            case "d1":
                                WriteLine($"{m68k.D1:X8}");
                                break;

                            case "d2":
                                WriteLine($"{m68k.D2:X8}");
                                break;

                            case "d3":
                                WriteLine($"{m68k.D3:X8}");
                                break;

                            case "d4":
                                WriteLine($"{m68k.D4:X8}");
                                break;

                            case "d5":
                                WriteLine($"{m68k.D5:X8}");
                                break;

                            case "d6":
                                WriteLine($"{m68k.D6:X8}");
                                break;

                            case "d7":
                                WriteLine($"{m68k.D7:X8}");
                                break;

                            case "a0":
                                WriteLine($"{m68k.A0:X8}");
                                break;

                            case "a1":
                                WriteLine($"{m68k.A1:X8}");
                                break;

                            case "a2":
                                WriteLine($"{m68k.A2:X8}");
                                break;

                            case "a3":
                                WriteLine($"{m68k.A3:X8}");
                                break;

                            case "a4":
                                WriteLine($"{m68k.A4:X8}");
                                break;

                            case "a5":
                                WriteLine($"{m68k.A5:X8}");
                                break;

                            case "a6":
                                WriteLine($"{m68k.A6:X8}");
                                break;

                            /*case "a7": // Already a TODO
                             * WriteLine($"{m68k.A7:X8}");
                             *  break;*/
                            case "sr":
                                WriteLine($"{m68k.SR:X4}");
                                break;

                            case "ssp":
                                WriteLine($"{m68k.SSP:X6}");
                                break;

                            case "usp":
                                WriteLine($"{m68k.USP:X6}");
                                break;

                            case "pc":
                                WriteLine($"{m68k.PC:X6}");
                                break;
                            /* MSP, IRP already a TODO */

                            default:
                                WriteLine("Unknown p argument.");
                                break;
                            }
                            break;

                        default:
                            WriteLine("Unsupported number of p arguments.");
                            break;
                        }
                    }
                    break;

                    case 't':     // Trace
                        WriteLine($" D0={m68k.D0:X8}  D1={m68k.D1:X8}  D2={m68k.D2:X8}  D3={m68k.D3:X8}");
                        WriteLine($" D4={m68k.D4:X8}  D5={m68k.D5:X8}  D6={m68k.D6:X8}  D7={m68k.D7:X8}");
                        WriteLine($" A0={m68k.A0:X8}  A1={m68k.A1:X8}  A2={m68k.A2:X8}  A3={m68k.A3:X8}");
                        WriteLine($" A4={m68k.A4:X8}  A5={m68k.A5:X8}  A6={m68k.A6:X8}");
                        WriteLine($" USP={m68k.USP:X6}  SSP={m68k.SSP:X6}  SR={m68k.SR:X4}");
                        WriteLine();
                        WriteLine($" PC={m68k.PC:X6}");
                        break;

                    case 'q':     // Quit
                        c = false;
                        break;

                    case 'h':     // Help
                    case '?':
                        WriteLine(" Usage:");
                        WriteLine("  <COMMAND> or <OPCODE> [<OPERAND>]");
                        WriteLine(" Note: Hexadecimal numbers must have the 0x prefix.");
                        WriteLine();
                        WriteLine(" COMMANDS:");
                        WriteLine("p <REGISTER>...Print register.");
                        WriteLine("t..............Print all registers.");
                        WriteLine();
                        WriteLine("?.........Brings this screen.");
                        WriteLine("q.........Quits.");
                        break;

                    default:
                    {
                        var s = n.Split(
                            new[] { ' ' },
                            StringSplitOptions.RemoveEmptyEntries
                            );

                        switch (s.Length)
                        {
                        // Case 0 is handled earlier.

                        case 1:
                            try
                            {
                                m68k.Execute(s[0].HexStringToUInt());
                            }
                            catch
                            {
                                WriteLine("Couldn't parse operation code.");
                            }
                            break;

                        case 2:
                        {
                            try
                            {
                                m68k.Execute(
                                    s[0].HexStringToUInt(),
                                    s[1].HexStringToUInt()
                                    );
                            }
                            catch
                            {
                                WriteLine("Couldn't parse operation code or operand.");
                            }
                        }
                        break;

                        default:
                            WriteLine("Too many operands");
                            break;
                        }
                    }
                    break;
                    }
                }
            }
        }