diff --git a/BizHawk.Emulation/CPUs/68000/Diassembler.cs b/BizHawk.Emulation/CPUs/68000/Diassembler.cs index bdfdecb312..39fe63119a 100644 --- a/BizHawk.Emulation/CPUs/68000/Diassembler.cs +++ b/BizHawk.Emulation/CPUs/68000/Diassembler.cs @@ -34,11 +34,14 @@ namespace BizHawk.Emulation.CPUs.M68000 else if (Opcodes[op] == PEA) PEA_Disasm(info); else if (Opcodes[op] == ANDI) ANDI_Disasm(info); + else if (Opcodes[op] == EORI) EORI_Disasm(info); else if (Opcodes[op] == ORI) ORI_Disasm(info); - else if (Opcodes[op] == LSLd) LSLd_Disasm(info); - else if (Opcodes[op] == LSRd) LSRd_Disasm(info); else if (Opcodes[op] == ASLd) ASLd_Disasm(info); else if (Opcodes[op] == ASRd) ASRd_Disasm(info); + else if (Opcodes[op] == LSLd) LSLd_Disasm(info); + else if (Opcodes[op] == LSRd) LSRd_Disasm(info); + else if (Opcodes[op] == ROXLd) ROXLd_Disasm(info); + else if (Opcodes[op] == ROXRd) ROXRd_Disasm(info); else if (Opcodes[op] == ROLd) ROLd_Disasm(info); else if (Opcodes[op] == RORd) RORd_Disasm(info); else if (Opcodes[op] == SWAP) SWAP_Disasm(info); diff --git a/BizHawk.Emulation/CPUs/68000/Instructions/BitArithemetic.cs b/BizHawk.Emulation/CPUs/68000/Instructions/BitArithemetic.cs index 65c5bf8936..b8c7f6318f 100644 --- a/BizHawk.Emulation/CPUs/68000/Instructions/BitArithemetic.cs +++ b/BizHawk.Emulation/CPUs/68000/Instructions/BitArithemetic.cs @@ -74,9 +74,7 @@ namespace BizHawk.Emulation.CPUs.M68000 V = false; C = false; - - throw new NotTestedException(); - + switch (size) { case 0: // Byte @@ -299,6 +297,85 @@ namespace BizHawk.Emulation.CPUs.M68000 info.Length = pc - info.PC; } + void EORI() + { + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + V = false; + C = false; + + switch (size) + { + case 0: // byte + { + sbyte immed = (sbyte) ReadWord(PC); PC += 2; + sbyte value = (sbyte) (PeekValueB(mode, reg) ^ immed); + WriteValueB(mode, reg, value); + N = (value & 0x80) != 0; + Z = value == 0; + PendingCycles -= mode == 0 ? 8 : 12 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + short immed = ReadWord(PC); PC += 2; + short value = (short)(PeekValueW(mode, reg) ^ immed); + WriteValueW(mode, reg, value); + N = (value & 0x8000) != 0; + Z = value == 0; + PendingCycles -= mode == 0 ? 8 : 12 + EACyclesBW[mode, reg]; + return; + } + case 2: // long + { + int immed = ReadLong(PC); PC += 4; + int value = PeekValueL(mode, reg) ^ immed; + WriteValueL(mode, reg, value); + N = (value & 0x80000000) != 0; + Z = value == 0; + PendingCycles -= mode == 0 ? 16 : 20 + EACyclesL[mode, reg]; + return; + } + } + } + + void EORI_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: // byte + { + info.Mnemonic = "eori.b"; + sbyte immed = (sbyte) ReadWord(pc); pc += 2; + info.Args = String.Format("${0:X}, {1}", immed, DisassembleValue(mode, reg, 1, ref pc)); + break; + } + case 1: // word + { + info.Mnemonic = "eori.w"; + short immed = ReadWord(pc); pc += 2; + info.Args = String.Format("${0:X}, {1}", immed, DisassembleValue(mode, reg, 2, ref pc)); + break; + } + case 2: // long + { + info.Mnemonic = "eori.l"; + int immed = ReadLong(pc); pc += 4; + info.Args = String.Format("${0:X}, {1}", immed, DisassembleValue(mode, reg, 4, ref pc)); + break; + } + } + + info.Length = pc - info.PC; + } + void OR0() // OR , Dn { int dstReg = (op >> 9) & 0x07; @@ -1003,6 +1080,152 @@ namespace BizHawk.Emulation.CPUs.M68000 info.Length = pc - info.PC; } + void ROXLd() + { + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + else if (m == 1) rot = D[rot].s32 & 63; + + C = X; + V = false; + + switch (size) + { + case 0: // byte + for (int i = 0; i < rot; i++) + { + C = (D[reg].u8 & 0x80) != 0; + D[reg].u8 = (byte)((D[reg].u8 << 1) | (X ? 1 : 0)); + X = C; + } + N = (D[reg].s8 & 0x80) != 0; + Z = D[reg].s8 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 1: // word + for (int i = 0; i < rot; i++) + { + C = (D[reg].u16 & 0x8000) != 0; + D[reg].u16 = (ushort)((D[reg].u16 << 1) | (X ? 1 : 0)); + X = C; + } + N = (D[reg].s16 & 0x8000) != 0; + Z = D[reg].s16 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 2: // long + for (int i = 0; i < rot; i++) + { + C = (D[reg].s32 & 0x80000000) != 0; + D[reg].s32 = ((D[reg].s32 << 1) | (X ? 1 : 0)); + X = C; + } + N = (D[reg].s32 & 0x80000000) != 0; + Z = D[reg].s32 == 0; + PendingCycles -= 8 + (rot * 2); + return; + } + } + + void ROXLd_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + + switch (size) + { + case 0: info.Mnemonic = "roxl.b"; break; + case 1: info.Mnemonic = "roxl.w"; break; + case 2: info.Mnemonic = "roxl.l"; break; + } + if (m == 0) info.Args = rot + ", D" + reg; + else info.Args = "D" + rot + ", D" + reg; + + info.Length = pc - info.PC; + } + + void ROXRd() + { + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + else if (m == 1) rot = D[rot].s32 & 63; + + C = X; + V = false; + + switch (size) + { + case 0: // byte + for (int i = 0; i < rot; i++) + { + C = (D[reg].u8 & 1) != 0; + D[reg].u8 = (byte)((D[reg].u8 >> 1) | (X ? 0x80 : 0)); + X = C; + } + N = (D[reg].s8 & 0x80) != 0; + Z = D[reg].s8 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 1: // word + for (int i = 0; i < rot; i++) + { + C = (D[reg].u16 & 1) != 0; + D[reg].u16 = (ushort)((D[reg].u16 >> 1) | (X ? 0x8000 : 0)); + X = C; + } + N = (D[reg].s16 & 0x8000) != 0; + Z = D[reg].s16 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 2: // long + for (int i = 0; i < rot; i++) + { + C = (D[reg].s32 & 1) != 0; + D[reg].u32 = ((D[reg].u32 >> 1) | (X ? 0x80000000 : 0)); + X = C; + } + N = (D[reg].s32 & 0x80000000) != 0; + Z = D[reg].s32 == 0; + PendingCycles -= 8 + (rot * 2); + return; + } + } + + void ROXRd_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + + switch (size) + { + case 0: info.Mnemonic = "roxr.b"; break; + case 1: info.Mnemonic = "roxr.w"; break; + case 2: info.Mnemonic = "roxr.l"; break; + } + if (m == 0) info.Args = rot + ", D" + reg; + else info.Args = "D" + rot + ", D" + reg; + + info.Length = pc - info.PC; + } + void SWAP() { int reg = op & 7; diff --git a/BizHawk.Emulation/CPUs/68000/Instructions/DataMovement.cs b/BizHawk.Emulation/CPUs/68000/Instructions/DataMovement.cs index 75b9b00de3..58f6229390 100644 --- a/BizHawk.Emulation/CPUs/68000/Instructions/DataMovement.cs +++ b/BizHawk.Emulation/CPUs/68000/Instructions/DataMovement.cs @@ -90,16 +90,19 @@ namespace BizHawk.Emulation.CPUs.M68000 case 2: PendingCycles -= 8; break; case 3: PendingCycles -= 8; break; case 4: PendingCycles -= 10; break; + case 5: PendingCycles -= 12; break; + case 6: PendingCycles -= 14; break; case 7: switch (srcReg) { case 0: PendingCycles -= 12; break; case 1: PendingCycles -= 16; break; + case 2: PendingCycles -= 12; break; + case 3: PendingCycles -= 14; break; case 4: PendingCycles -= 8; break; - default: throw new NotImplementedException(); + default: throw new InvalidOperationException(); } break; - default: throw new NotImplementedException(); } } else { // Long A[dstReg].s32 = ReadValueL(srcMode, srcReg); @@ -110,16 +113,19 @@ namespace BizHawk.Emulation.CPUs.M68000 case 2: PendingCycles -= 12; break; case 3: PendingCycles -= 12; break; case 4: PendingCycles -= 14; break; + case 5: PendingCycles -= 16; break; + case 6: PendingCycles -= 18; break; case 7: switch (srcReg) { case 0: PendingCycles -= 16; break; case 1: PendingCycles -= 20; break; + case 2: PendingCycles -= 16; break; + case 3: PendingCycles -= 18; break; case 4: PendingCycles -= 12; break; - default: throw new NotImplementedException(); + default: throw new InvalidOperationException(); } break; - default: throw new NotImplementedException(); } } } diff --git a/BizHawk.Emulation/CPUs/68000/Instructions/IntegerMath.cs b/BizHawk.Emulation/CPUs/68000/Instructions/IntegerMath.cs index 7fdd027c00..c3d3f7c0e7 100644 --- a/BizHawk.Emulation/CPUs/68000/Instructions/IntegerMath.cs +++ b/BizHawk.Emulation/CPUs/68000/Instructions/IntegerMath.cs @@ -169,7 +169,7 @@ namespace BizHawk.Emulation.CPUs.M68000 } case 2: // long { - int immed = ReadLong(PC); PC += 2; + int immed = ReadLong(PC); PC += 4; int value = PeekValueL(mode, reg); long result = value + immed; long uresult = (uint)value + (uint)immed; @@ -492,7 +492,7 @@ namespace BizHawk.Emulation.CPUs.M68000 } case 2: // long { - int immed = ReadLong(PC); PC += 2; + int immed = ReadLong(PC); PC += 4; int value = PeekValueL(mode, reg); long result = value - immed; long uresult = (uint)value - (uint)immed; diff --git a/BizHawk.Emulation/CPUs/68000/Memory.cs b/BizHawk.Emulation/CPUs/68000/Memory.cs index 542960aac6..700dd789c6 100644 --- a/BizHawk.Emulation/CPUs/68000/Memory.cs +++ b/BizHawk.Emulation/CPUs/68000/Memory.cs @@ -302,10 +302,7 @@ namespace BizHawk.Emulation.CPUs.M68000 case 2: return A[reg].s32; // (An) case 3: return A[reg].s32; // (An)+ case 4: return A[reg].s32; // -(An) - case 5: // (d16,An) - addr = A[reg].s32 + ReadWord(PC); - PC += 2; - return addr; + case 5: addr = A[reg].s32 + ReadWord(PC); PC += 2; return addr; // (d16,An) case 6: return A[reg].s32 + GetIndex(); // (d8,An,Xn) case 7: switch (reg) @@ -324,6 +321,7 @@ namespace BizHawk.Emulation.CPUs.M68000 string DisassembleValue(int mode, int reg, int size, ref int pc) { string value; + int addr; switch (mode) { case 0: return "D"+reg; // Dn @@ -331,33 +329,15 @@ namespace BizHawk.Emulation.CPUs.M68000 case 2: return "(A"+reg+")"; // (An) case 3: return "(A"+reg+")+"; // (An)+ case 4: return "-(A"+reg+")"; // -(An) - case 5: // (d16,An) - // TODO need to figure out how to print signed-hex - value = string.Format("(${0:X},A{1})", ReadWord(pc), reg); - pc += 2; - return value; - case 6: return "NOT IMPLEMENTED"; // (d8,An,Xn) - //return ReadByte(A[reg].Long + GetIndex()); + case 5: value = string.Format("(${0:X},A{1})", ReadWord(pc), reg); pc += 2; return value; // (d16,An) + case 6: addr = ReadWord(pc); pc += 2; return DisassembleIndex("A" + reg, (short) addr); // (d8,An,Xn) case 7: switch (reg) { - case 0: // (imm).W - value = String.Format("(${0:X})", ReadWord(pc)); - pc += 2; - return value; - case 1: // (imm).L - value = String.Format("(${0:X})", ReadLong(pc)); - pc += 4; - return value; - case 2: // (d16,PC) - value = String.Format("(${0:X})", pc + ReadWord(pc)); - pc += 2; - return value; - case 3: // (d8,PC,Xn) - return "NOT IMPLEMENTED"; - /* uint _pc = PC; - value = ReadByte((_pc + GetIndex())); - return value;*/ + case 0: value = String.Format("(${0:X})", ReadWord(pc)); pc += 2; return value; // (imm).W + case 1: value = String.Format("(${0:X})", ReadLong(pc)); pc += 4; return value; // (imm).L + case 2: value = String.Format("(${0:X})", pc + ReadWord(pc)); pc += 2; return value; // (d16,PC) + case 3: addr = ReadWord(pc); pc += 2; return DisassembleIndex("PC", (short)addr); // (d8,PC,Xn) case 4: switch (size) { @@ -400,18 +380,15 @@ namespace BizHawk.Emulation.CPUs.M68000 case 2: return "(A"+reg+")"; // (An) case 3: return "(A"+reg+")+"; // (An)+ case 4: return "-(A"+reg+")"; // -(An) - case 5: // (d16,An) - addr = ReadWord(pc); - pc += 2; - return String.Format("({0},A{1})", addr, reg); - case 6: return "NOT IMPLEMENTED"; // (d8,An,Xn) + case 5: addr = ReadWord(pc); pc += 2; return String.Format("({0},A{1})", addr, reg); // (d16,An) + case 6: addr = ReadWord(pc); pc += 2; return DisassembleIndex("A" + reg, (short)addr); // (d8,An,Xn) case 7: switch (reg) { case 0: addr = ReadWord(pc); pc += 2; return String.Format("${0:X}.w",addr); // (imm).w case 1: addr = ReadLong(pc); pc += 4; return String.Format("${0:X}.l",addr); // (imm).l case 2: addr = ReadWord(pc); pc += 2; return String.Format("(${0:X},PC)",addr); // (d16,PC) - case 3: return "NOT IMPLEMENTED"; // (d8,PC,Xn) + case 3: addr = ReadWord(pc); pc += 2; return DisassembleIndex("PC", (short)addr); // (d8,PC,Xn) case 4: return "INVALID"; // immediate } break; @@ -573,9 +550,9 @@ namespace BizHawk.Emulation.CPUs.M68000 short extension = ReadWord(PC); PC += 2; - int da = (extension >> 15) & 0x1; - int reg = (extension >> 12) & 0x7; - int size = (extension >> 11) & 0x1; + int da = (extension >> 15) & 0x1; + int reg = (extension >> 12) & 0x7; + int size = (extension >> 11) & 0x1; int scale = (extension >> 9) & 0x3; sbyte displacement = (sbyte)extension; @@ -622,5 +599,28 @@ namespace BizHawk.Emulation.CPUs.M68000 return displacement + indexReg; } + + string DisassembleIndex(string baseRegister, short extension) + { + int d_a = (extension >> 15) & 0x1; + int reg = (extension >> 12) & 0x7; + int size = (extension >> 11) & 0x1; + int scale = (extension >> 9) & 0x3; + sbyte displacement = (sbyte)extension; + + string scaleFactor; + switch (scale) + { + case 0: scaleFactor = ""; break; + case 1: scaleFactor = "2"; break; + case 2: scaleFactor = "4"; break; + default: scaleFactor = "8"; break; + } + + string offsetRegister = (d_a == 0) ? "D" : "A"; + string sizeStr = size == 0 ? ".w" : ".l"; + string displacementStr = displacement == 0 ? "" : ("," + displacement); + return string.Format("({0},{1}{2}{3}{4}{5})", baseRegister, scaleFactor, offsetRegister, reg, sizeStr, displacementStr); + } } } \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs b/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs index 730658d2fc..1322713508 100644 --- a/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs +++ b/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs @@ -21,11 +21,14 @@ namespace BizHawk.Emulation.CPUs.M68000 Assign("pea", PEA, "0100100001", "AmXn"); Assign("andi", ANDI, "00000010", "Size2_1", "AmXn"); + Assign("eori", EORI, "00001010", "Size2_1", "AmXn"); Assign("ori", ORI, "00000000", "Size2_1", "AmXn"); - Assign("lsl", LSLd, "1110", "Data3", "1", "Size2_1", "Data1", "01", "Xn"); - Assign("lsr", LSRd, "1110", "Data3", "0", "Size2_1", "Data1", "01", "Xn"); Assign("asl", ASLd, "1110", "Data3", "1", "Size2_1", "Data1", "00", "Xn"); Assign("asr", ASRd, "1110", "Data3", "0", "Size2_1", "Data1", "00", "Xn"); + Assign("lsl", LSLd, "1110", "Data3", "1", "Size2_1", "Data1", "01", "Xn"); + Assign("lsr", LSRd, "1110", "Data3", "0", "Size2_1", "Data1", "01", "Xn"); + Assign("roxl", ROXLd, "1110", "Data3", "1", "Size2_1", "Data1", "10", "Xn"); + Assign("roxr", ROXRd, "1110", "Data3", "0", "Size2_1", "Data1", "10", "Xn"); Assign("rol", ROLd, "1110", "Data3", "1", "Size2_1", "Data1", "11", "Xn"); Assign("ror", RORd, "1110", "Data3", "0", "Size2_1", "Data1", "11", "Xn"); Assign("swap", SWAP, "0100100001000","Xn"); @@ -107,7 +110,7 @@ namespace BizHawk.Emulation.CPUs.M68000 foreach (var opcode in opList) { int opc = Convert.ToInt32(opcode, 2); - if (Opcodes[opc] != null && instr.NotIn("movea","andi2sr","ori2sr","ext","dbcc","swap")) + if (Opcodes[opc] != null && instr.NotIn("movea","andi2sr","eori2sr","ori2sr","ext","dbcc","swap")) Console.WriteLine("Setting opcode for {0}, a handler is already set. overwriting. {1:X4}", instr, opc); Opcodes[opc] = exec; }