diff --git a/BizHawk.Emulation/CPUs/68000/Diassembler.cs b/BizHawk.Emulation/CPUs/68000/Diassembler.cs index b2b4a0f99c..b6d39d05e4 100644 --- a/BizHawk.Emulation/CPUs/68000/Diassembler.cs +++ b/BizHawk.Emulation/CPUs/68000/Diassembler.cs @@ -56,6 +56,7 @@ namespace BizHawk.Emulation.CPUs.M68000 else if (Opcodes[op] == BSR) BSR_Disasm(info); else if (Opcodes[op] == DBcc) DBcc_Disasm(info); else if (Opcodes[op] == Scc) Scc_Disasm(info); + else if (Opcodes[op] == RTE) RTE_Disasm(info); else if (Opcodes[op] == RTS) RTS_Disasm(info); else if (Opcodes[op] == TST) TST_Disasm(info); else if (Opcodes[op] == BTSTi) BTSTi_Disasm(info); @@ -67,6 +68,7 @@ namespace BizHawk.Emulation.CPUs.M68000 else if (Opcodes[op] == BSETi) BSETi_Disasm(info); else if (Opcodes[op] == BSETr) BSETr_Disasm(info); else if (Opcodes[op] == LINK) LINK_Disasm(info); + else if (Opcodes[op] == UNLK) UNLK_Disasm(info); else if (Opcodes[op] == NOP) NOP_Disasm(info); else if (Opcodes[op] == ADD0) ADD_Disasm(info); @@ -86,7 +88,10 @@ namespace BizHawk.Emulation.CPUs.M68000 else if (Opcodes[op] == MOVEtSR) MOVEtSR_Disasm(info); else if (Opcodes[op] == MOVEfSR) MOVEfSR_Disasm(info); else if (Opcodes[op] == MOVEUSP) MOVEUSP_Disasm(info); + else if (Opcodes[op] == ANDI_SR) ANDI_SR_Disasm(info); + else if (Opcodes[op] == EORI_SR) EORI_SR_Disasm(info); else if (Opcodes[op] == ORI_SR) ORI_SR_Disasm(info); + else if (Opcodes[op] == TRAP) TRAP_Disasm(info); var sb = new StringBuilder(); for (int p = info.PC; p < info.PC + info.Length; p++) diff --git a/BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs b/BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs index 9f5cc16f1b..50bfa7a53d 100644 --- a/BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs +++ b/BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs @@ -204,6 +204,22 @@ namespace BizHawk.Emulation.CPUs.M68000 info.Args = ""; } + void RTE() + { + short newSR = ReadWord(A[7].s32); + A[7].s32 += 2; + PC = ReadLong(A[7].s32); + A[7].s32 += 4; + SR = newSR; + PendingCycles -= 20; + } + + void RTE_Disasm(DisassemblyInfo info) + { + info.Mnemonic = "rte"; + info.Args = ""; + } + void TST() { int size = (op >> 6) & 3; @@ -625,6 +641,23 @@ namespace BizHawk.Emulation.CPUs.M68000 info.Length = pc - info.PC; } + void UNLK() + { + int reg = op & 7; + A[7].s32 = A[reg].s32; + A[reg].s32 = ReadLong(A[7].s32); + A[7].s32 += 4; + PendingCycles -= 12; + } + + void UNLK_Disasm(DisassemblyInfo info) + { + int reg = op & 7; + info.Mnemonic = "unlk"; + info.Args = "A" + reg; + info.Length = 2; + } + void NOP() { PendingCycles -= 4; diff --git a/BizHawk.Emulation/CPUs/68000/Instructions/Supervisor.cs b/BizHawk.Emulation/CPUs/68000/Instructions/Supervisor.cs index ecb9b2f057..2b17658342 100644 --- a/BizHawk.Emulation/CPUs/68000/Instructions/Supervisor.cs +++ b/BizHawk.Emulation/CPUs/68000/Instructions/Supervisor.cs @@ -67,6 +67,38 @@ namespace BizHawk.Emulation.CPUs.M68000 info.Length = pc - info.PC; } + void ANDI_SR() + { + if (S == false) + throw new Exception("trap!"); + SR &= ReadWord(PC); PC += 2; + PendingCycles -= 20; + } + + void ANDI_SR_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + info.Mnemonic = "andi"; + info.Args = DisassembleImmediate(2, ref pc) + ", SR"; + info.Length = pc - info.PC; + } + + void EORI_SR() + { + if (S == false) + throw new Exception("trap!"); + SR ^= ReadWord(PC); PC += 2; + PendingCycles -= 20; + } + + void EORI_SR_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + info.Mnemonic = "eori"; + info.Args = DisassembleImmediate(2, ref pc) + ", SR"; + info.Length = pc - info.PC; + } + void ORI_SR() { if (S == false) @@ -82,5 +114,29 @@ namespace BizHawk.Emulation.CPUs.M68000 info.Args = DisassembleImmediate(2, ref pc) + ", SR"; info.Length = pc - info.PC; } + + void TRAP() + { + int vector = 32 + (op & 0x0F); + TrapVector(vector); + PendingCycles -= 26; + } + + void TRAP_Disasm(DisassemblyInfo info) + { + info.Mnemonic = "trap"; + info.Args = string.Format("${0:X}", op & 0xF); + } + + void TrapVector(int vector) + { + short sr = (short)SR; // capture current SR. + S = true; // switch to supervisor mode, if not already in it. + A[7].s32 -= 4; // Push PC on stack + WriteLong(A[7].s32, PC); + A[7].s32 -= 2; // Push SR on stack + WriteWord(A[7].s32, sr); + PC = ReadLong(vector * 4); // Jump to vector + } } -} +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/68000/M68000.cs b/BizHawk.Emulation/CPUs/68000/M68000.cs index 9ac3f2ac94..edb873aa9b 100644 --- a/BizHawk.Emulation/CPUs/68000/M68000.cs +++ b/BizHawk.Emulation/CPUs/68000/M68000.cs @@ -55,11 +55,11 @@ namespace BizHawk.Emulation.CPUs.M68000 public bool C; /// Status Register - public int SR + public short SR { get { - int value = 0; + short value = 0; if (C) value |= 0x0001; if (V) value |= 0x0002; if (Z) value |= 0x0004; @@ -67,7 +67,7 @@ namespace BizHawk.Emulation.CPUs.M68000 if (X) value |= 0x0010; if (M) value |= 0x1000; if (S) value |= 0x2000; - value |= (InterruptMaskLevel & 7) << 8; + value |= (short) ((InterruptMaskLevel & 7) << 8); return value; } set @@ -128,13 +128,14 @@ namespace BizHawk.Emulation.CPUs.M68000 { if (Interrupt > 0 && (Interrupt > InterruptMaskLevel || Interrupt > 7)) { + // TODO: Entering interrupt is not free. how many cycles does it take? Log.Error("CPU","****** ENTER INTERRUPT {0} *******", Interrupt); - int sr = SR; // capture current SR. + short sr = (short) SR; // capture current SR. S = true; // switch to supervisor mode, if not already in it. A[7].s32 -= 4; // Push PC on stack WriteLong(A[7].s32, PC); A[7].s32 -= 2; // Push SR on stack - WriteLong(A[7].s32, sr); + WriteWord(A[7].s32, sr); PC = ReadLong((24 + Interrupt) * 4); // Jump to interrupt vector InterruptMaskLevel = Interrupt; // Set interrupt mask to level currently being entered Interrupt = 0; // "ack" interrupt. Note: this is wrong. diff --git a/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs b/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs index 10f7c71ba3..92cbb982cf 100644 --- a/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs +++ b/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs @@ -43,6 +43,7 @@ namespace BizHawk.Emulation.CPUs.M68000 Assign("bsr", BSR, "01100001", "Data8"); Assign("scc", Scc, "0101", "CondAll", "11","AmXn"); Assign("dbcc", DBcc, "0101", "CondAll", "11001", "Xn"); + Assign("rte", RTE, "0100111001110011"); Assign("rts", RTS, "0100111001110101"); Assign("tst", TST, "01001010", "Size2_1", "AmXn"); Assign("btst", BTSTi, "0000100000", "AmXn"); @@ -54,6 +55,7 @@ namespace BizHawk.Emulation.CPUs.M68000 Assign("bset", BSETi, "0000100011", "AmXn"); Assign("bset", BSETr, "0000", "Xn", "111", "AmXn"); Assign("link", LINK, "0100111001010", "Xn"); + Assign("unlk", UNLK, "0100111001011", "Xn"); Assign("nop", NOP, "0100111001110001"); Assign("add", ADD0, "1101", "Xn", "0", "Size2_1", "AmXn"); @@ -73,7 +75,10 @@ namespace BizHawk.Emulation.CPUs.M68000 Assign("move2sr", MOVEtSR, "0100011011", "AmXn"); Assign("movefsr", MOVEfSR, "0100000011", "AmXn"); Assign("moveusp", MOVEUSP, "010011100110", "Data1", "Xn"); + Assign("andi2sr", ANDI_SR, "0000001001111100"); + Assign("eori2sr", EORI_SR, "0000101001111100"); Assign("ori2sr", ORI_SR, "0000000001111100"); + Assign("trap", TRAP, "010011100100", "Data4"); } void Assign(string instr, Action exec, string root, params string[] bitfield) @@ -93,6 +98,7 @@ namespace BizHawk.Emulation.CPUs.M68000 else if (component == "CondMain") opList = AppendPermutations(opList, ConditionMain); else if (component == "CondAll") opList = AppendPermutations(opList, ConditionAll); else if (component == "Data1") opList = AppendData(opList, 1); + else if (component == "Data4") opList = AppendData(opList, 4); else if (component == "Data3") opList = AppendData(opList, 3); else if (component == "Data8") opList = AppendData(opList, 8); } @@ -100,7 +106,7 @@ namespace BizHawk.Emulation.CPUs.M68000 foreach (var opcode in opList) { int opc = Convert.ToInt32(opcode, 2); - if (Opcodes[opc] != null && instr.NotIn("movea","ori2sr","ext","dbcc","swap")) + if (Opcodes[opc] != null && instr.NotIn("movea","andi2sr","ori2sr","ext","dbcc","swap")) Console.WriteLine("Setting opcode for {0}, a handler is already set. overwriting. {1:X4}", instr, opc); Opcodes[opc] = exec; }