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); }
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); }
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)); }
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}"); } }
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); }
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); }
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)); }
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 }
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); }
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; } } } }