static CPU() { InstructionSet = new Dictionary <byte, OpcodeDef[]>() { // Bit manipulation/MOVEP/Immediate { CreateGroupEntry("0000"), new OpcodeDef[] { CreateDef("000000111100", "00000000????????", Opcode.ORItoCCR, 4), CreateDef("000001111100", Opcode.ORItoSR, 4), CreateDef("0000????????", Opcode.ORI, 6), CreateDef("001000111100", "00000000????????", Opcode.ANDItoCCR, 4), CreateDef("001001111100", Opcode.ANDItoSR, 4), CreateDef("0000????????", Opcode.ANDI, 6), CreateDef("0100????????", Opcode.SUBI, 6), CreateDef("01101100????", Opcode.RTM), CreateDef("011011??????", "00000000????????", Opcode.CALLM, 4), CreateDef("0110????????", Opcode.ADDI), CreateDef("0??011??????", "????000000000000", Opcode.CMP2, 4), CreateDef("0??011??????", "????100000000000", Opcode.CHK2, 4), CreateDef("101000111100", "00000000????????", Opcode.EORItoCCR, 4), CreateDef("101001111100", Opcode.EORItoSR, 4), CreateDef("1010????????", Opcode.EORI, 6), CreateDef("1100????????", Opcode.CMPI, 6), CreateDef("100000??????", "00000000????????", Opcode.BTST, 4), CreateDef("100001??????", "00000000????????", Opcode.BCHG, 4), CreateDef("100010??????", "00000000????????", Opcode.BCLR, 4), CreateDef("100011??????", "00000000????????", Opcode.BSET, 4), CreateDef("1110????????", "?????00000000000", Opcode.MOVES, 4), CreateDef("1??011111100", "????000???000???", Opcode.CAS2, 6), CreateDef("1??011??????", "0000000???000???", Opcode.CAS, 4), CreateDef("???100??????", Opcode.BTST), CreateDef("???101??????", Opcode.BCHG), CreateDef("???110??????", Opcode.BCLR), CreateDef("???111??????", Opcode.BSET), CreateDef("??????001???", Opcode.MOVEP, 4), } }, // Move byte { CreateGroupEntry("0001"), new OpcodeDef[] { CreateDef("????????????", Opcode.MOVE_BYTE), CreateDef("???001??????", Opcode.MOVEA_BYTE), } }, // Move long { CreateGroupEntry("0010"), new OpcodeDef[] { CreateDef("????????????", Opcode.MOVE_LONG), CreateDef("???001??????", Opcode.MOVEA_LONG), } }, // Move word { CreateGroupEntry("0011"), new OpcodeDef[] { CreateDef("????????????", Opcode.MOVE_WORD), CreateDef("???001??????", Opcode.MOVEA_WORD), } }, // Misc { CreateGroupEntry("0100"), new OpcodeDef[] { CreateDef("000011??????", Opcode.MOVEfromSR), CreateDef("001011??????", Opcode.MOVEfromCCR), CreateDef("0000????????", Opcode.NEGX), CreateDef("0010????????", Opcode.CLR), CreateDef("010011??????", Opcode.MOVEtoCCR), CreateDef("0100????????", Opcode.NEG), CreateDef("0110????????", Opcode.NOT), CreateDef("011011??????", Opcode.MOVEtoSR), CreateDef("100???000???", Opcode.EXT_EXTB), CreateDef("100000001???", Opcode.LINK_LONG, 2), CreateDef("100000??????", Opcode.NBCD), CreateDef("100001000???", Opcode.SWAP), CreateDef("100001001???", Opcode.BKPT), CreateDef("100001??????", Opcode.PEA), CreateDef("101011111010", Opcode.BGND), CreateDef("101011111100", Opcode.ILLEGAL), CreateDef("101011??????", Opcode.TAS), CreateDef("1010????????", Opcode.TST), CreateDef("110000??????", "0???0?0000000???", Opcode.MULU_LONG, 4), CreateDef("110000??????", "0???1?0000000???", Opcode.MULS_LONG, 4), CreateDef("110000??????", "0???0?0000000???", Opcode.DIVU_DIVUL_LONG, 4), CreateDef("110001??????", "0???1?0000000???", Opcode.DIVS_DIVSL_LONG, 4), CreateDef("11100100????", Opcode.TRAP), CreateDef("111001010???", Opcode.LINK_WORD, 2), CreateDef("111001011???", Opcode.UNLK), CreateDef("11100110????", Opcode.MOVE_USP), CreateDef("111001110000", Opcode.RESET), CreateDef("111001110001", Opcode.NOP), CreateDef("111001110010", Opcode.STOP, 4), CreateDef("111001110011", Opcode.RTE), CreateDef("111001110100", Opcode.RTD, 4), CreateDef("111001110101", Opcode.RTS), CreateDef("111001110110", Opcode.TRAPV), CreateDef("111001110111", Opcode.RTR), CreateDef("11100111101?", Opcode.MOVEC, 4), CreateDef("111010??????", Opcode.JSR), CreateDef("111011??????", Opcode.JMP), CreateDef("1?001???????", Opcode.MOVEM, 4), CreateDef("???111??????", Opcode.LEA), CreateDef("?????0??????", Opcode.CHK), } }, // ADDQ/SUBQ/Scc/DBcc/TRAPcc { CreateGroupEntry("0101"), new OpcodeDef[] { CreateDef("???0????????", Opcode.ADDQ), CreateDef("???1????????", Opcode.SUBQ), CreateDef("????11001???", Opcode.DBcc, 4), CreateDef("????11111???", Opcode.TRAPcc), CreateDef("????11??????", Opcode.Scc), } }, // Bcc/BSR/BRA { CreateGroupEntry("0110"), new OpcodeDef[] { CreateDef("0000????????", Opcode.BRA), CreateDef("0001????????", Opcode.BSR), CreateDef("????????????", Opcode.Bcc), } }, // MOVEQ { CreateGroupEntry("0111"), new OpcodeDef[] { CreateDef("???0????????", Opcode.MOVEQ), } }, // OR/DIV/SBCD { CreateGroupEntry("1000"), new OpcodeDef[] { CreateDef("???011??????", Opcode.DIVU_DIVUL_WORD), CreateDef("???10000????", Opcode.SBCD), CreateDef("???10100????", Opcode.PACK, 4), CreateDef("???11000????", Opcode.UNPK, 4), CreateDef("???111??????", Opcode.DIVS_DIVSL_WORD), CreateDef("????????????", Opcode.OR), } }, // SUB/SUBX { CreateGroupEntry("1001"), new OpcodeDef[] { CreateDef("???1??00????", Opcode.SUBX), CreateDef("????????????", Opcode.SUB_SUBA), } }, // Reserved { CreateGroupEntry("1010"), new OpcodeDef[] { OpcodeDef.Create(Opcode.UNIMPLEMENTED), } }, // CMP/EOR { CreateGroupEntry("1011"), new OpcodeDef[] { CreateDef("???1??001???", Opcode.CMPM), CreateDef("????????????", Opcode.CMP_CMPA_EOR), } }, // AND/MUL/ABCD/EXG { CreateGroupEntry("1100"), new OpcodeDef[] { CreateDef("???011??????", Opcode.MULU_WORD), CreateDef("???10000????", Opcode.ABCD), CreateDef("???111??????", Opcode.MULS_WORD), CreateDef("???1????????", Opcode.EXG), CreateDef("????????????", Opcode.AND), } }, // ADD/ADDX { CreateGroupEntry("1101"), new OpcodeDef[] { CreateDef("???1??00????", Opcode.ADDX), // bug; sixth bit not known CreateDef("????????????", Opcode.ADD_ADDA), } }, // Shift/Rotate/Bit Field { CreateGroupEntry("1110"), new OpcodeDef[] { CreateDef("000?11??????", Opcode.ASL_ASR_MEM_SHIFT), CreateDef("001?11??????", Opcode.LSL_LSR_MEM_SHIFT), CreateDef("010?11??????", Opcode.ROXL_ROXR_MEM_ROTATE), CreateDef("011?11??????", Opcode.ROL_ROR_MEM_ROTATE), CreateDef("100011??????", "0000????????????", Opcode.BFTST, 4), CreateDef("100111??????", "0???????????????", Opcode.BFEXTU, 4), CreateDef("101011??????", "0000????????????", Opcode.BFCHG, 4), CreateDef("101111??????", "0???????????????", Opcode.BFEXTS, 4), CreateDef("110011??????", "0000????????????", Opcode.BFCLR, 4), CreateDef("110111??????", "0???????????????", Opcode.BFFFO, 4), CreateDef("111011??????", "0000????????????", Opcode.BFSET, 4), CreateDef("111111??????", "0???????????????", Opcode.BFINS, 4), CreateDef("???????00???", Opcode.ASL_ASR_REG_SHIFT), CreateDef("???????01???", Opcode.LSL_LSR_REG_SHIFT), CreateDef("???????10???", Opcode.ROXL_ROXR_REG_ROTATE), CreateDef("???????11???", Opcode.ROL_ROR_REG_ROTATE), } }, // Coprocessor Interface/MC68040 and CPU32 Extensions { CreateGroupEntry("1111"), new OpcodeDef[] { OpcodeDef.Create(Opcode.UNIMPLEMENTED), } }, }; }
public virtual void Step() { if (TrapQueue.Count > 0) { int TrapVector = TrapQueue.Dequeue(); Console.WriteLine("Trap #{0}, not handled", TrapVector); } bool IncPC = true; ushort Word0 = Memory.Read16(PC + sizeof(ushort) * 0); ushort Word1 = Memory.Read16(PC + sizeof(ushort) * 1); ushort Word2 = Memory.Read16(PC + sizeof(ushort) * 2); ushort Word3 = Memory.Read16(PC + sizeof(ushort) * 3); ushort Word4 = Memory.Read16(PC + sizeof(ushort) * 4); uint Instr = (uint)((Word0 << 16) | Word1); ulong Instr2 = ((ulong)Word0 << 64) | ((ulong)Word1 << 48) | ((ulong)Word2 << 32) | ((ulong)Word3 << 16) | Word4; Opcode Opcode = MatchOpcode(Instr); InstrLen = 2; #if DEBUG /*Console.Write(" "); * for (int i = 16 - 1; i >= 0; i--) * Console.Write("{0:X}", i); * Console.WriteLine();*/ Console.ForegroundColor = ConsoleColor.White; Console.Write("0x{0:X8}: ", PC); Console.ResetColor(); OpcodeDef OpcodeDef = MatchOpcodeDef(Instr); if (OpcodeDef != null) { string Bin = Ext.ToBinary(Instr); string Pattern = OpcodeDef.Higher.Pattern + OpcodeDef.Lower.Pattern; Console.Write("0x{0:X8} ", Instr); for (int i = 0; i < Pattern.Length; i++) { if (Pattern[i] == '?') { Console.ForegroundColor = ConsoleColor.Green; } else { Console.ForegroundColor = ConsoleColor.Gray; } Console.Write(Bin[i]); } Console.ResetColor(); Console.Write(" {0}", Opcode); } else { Console.Write("0x{0:X8} {1} {2}", Instr, Ext.ToBinary(Instr), Opcode); } Console.WriteLine(); #endif switch (Opcode) { case Opcode.ILLEGAL_OPCODE: throw new InvalidOperationException(); case Opcode.UNIMPLEMENTED: throw new NotImplementedException(); case Opcode.ADDI: { ushort DstEAddr = Decode_EAddr(((ulong)Word0).GetBits(5, 0)); OpSize Size = Decode_Size(((ulong)Word0).GetBits(7, 6)); ulong Src = GetData(Size, MODE_IMMEDIATE); ulong Dest = GetData(Size, DstEAddr); SetData(Size, DstEAddr, Src + Dest); break; } case Opcode.MOVE_BYTE: { Move(OpSize.BYTE, Word0); break; } case Opcode.MOVE_WORD: { Move(OpSize.WORD, Word0); break; } case Opcode.MOVE_LONG: { Move(OpSize.LONG, Word0); break; } case Opcode.PEA: { ushort EAddr = Decode_EAddr(((ulong)Word0).GetBits(5, 0)); uint Val = (uint)GetData(OpSize.LONG, EAddr); DA[SP] -= 4; Memory.Write32(DA[SP], Val); break; } case Opcode.TRAP: { Trap(Word0.GetBits(3, 0)); break; } case Opcode.UNLK: { ulong Register = Word0.GetBits(2, 0); DA[SP] = (int)GetData(OpSize.LONG, MODE_REGISTER_A | Register); SetData(OpSize.LONG, MODE_REGISTER_A | Register, Memory.Read32(DA[SP])); DA[SP] += 4; break; } case Opcode.LINK_WORD: { ulong Register = Word0.GetBits(2, 0); int Immediate = (int)GetData(OpSize.WORD, MODE_IMMEDIATE); DA[SP] -= 4; Memory.Write32(DA[SP], (uint)GetData(OpSize.LONG, MODE_REGISTER_A | Register)); SetData(OpSize.LONG, MODE_REGISTER_A | Register, (ulong)DA[SP]); DA[SP] = DA[SP] + Immediate; break; } case Opcode.NOP: { break; } case Opcode.JMP: case Opcode.JSR: { ushort EAddr = Decode_EAddr(((ulong)Word0).GetBits(5, 0)); ulong Addr = GetData(OpSize.LONG, EAddr); if (Opcode == Opcode.JSR) { DA[SP] -= 4; Memory.Write32(DA[SP], (uint)(PC + InstrLen)); } PC = (int)Addr; IncPC = false; break; } case Opcode.RTS: { PC = (int)Memory.Read32(DA[SP]); DA[SP] += 4; IncPC = false; break; } case Opcode.MULU_WORD: case Opcode.MULU_LONG: case Opcode.MULS_WORD: case Opcode.MULS_LONG: { OpSize Size = (Opcode == Opcode.MULS_WORD || Opcode == Opcode.MULU_WORD) ? OpSize.WORD : OpSize.LONG; ulong SrcEAddr = Decode_EAddr(Word0.GetBits(5, 0)); ulong DstEAddr = Size == OpSize.LONG ? (MODE_REGISTER_D | Word1.GetBits(14, 12)) : (MODE_REGISTER_D | Word0.GetBits(11, 9)); if (Size == OpSize.LONG) { InstrLen += 2; } ulong Src = GetData(Size, SrcEAddr); ulong Dst = GetData(Size, DstEAddr); ulong Mul = (Opcode == Opcode.MULS_WORD || Opcode == Opcode.MULS_LONG) ? (ulong)((long)Src * (long)Dst) : Src * Dst; SetData(Size, DstEAddr, Mul & 0xFFFFFFFF); if (Size == OpSize.LONG && Word1.GetBit(10)) { ulong RegDh = MODE_REGISTER_D | Word1.GetBits(2, 0); ulong Dh = GetData(Size, RegDh); SetData(Size, RegDh, (Mul >> 32) & 0xFFFFFFFF); } break; } case Opcode.ADDQ: { ushort EAddr = Decode_EAddr(Word0.GetBits(5, 0)); OpSize Size = Decode_Size(Word0.GetBits(7, 6)); ulong Data = Word0.GetBits(11, 9); if (Data == 0) { Data = 8; } ulong Dest = GetData(Size, EAddr); SetData(Size, EAddr, Dest + Data); break; } case Opcode.ADD_ADDA: { ushort EAddr = Decode_EAddr(Word0.GetBits(5, 0)); ushort OpMode = Word0.GetBits(7, 6); OpSize Size = Decode_Size(OpMode); ulong Register = Word0.GetBits(11, 9); bool IsSource = !Word0.GetBit(8); // ADDA part ulong MODE_REGISTER = MODE_REGISTER_D; if (OpMode == 0x3 || OpMode == 0x7) { MODE_REGISTER = MODE_REGISTER_A; IsSource = true; if (OpMode == 0x3) { Size = OpSize.WORD; } else { Size = OpSize.LONG; } } ulong Src, Dst; ulong SetEAddr = MODE_REGISTER | Register; if (IsSource) { Src = GetData(Size, EAddr); Dst = GetData(Size, MODE_REGISTER | Register); } else { Src = GetData(Size, MODE_REGISTER_D | Register); Dst = GetData(Size, EAddr); SetEAddr = EAddr; } SetData(Size, SetEAddr, Src + Dst); break; } default: throw new NotImplementedException(); } if (IncPC) { PC += InstrLen; } }
private static OpcodeDef CreateDef(string Higher, Opcode Opcode, int Sizeof = 2) { return(OpcodeDef.Create("????" + Higher, Opcode, Sizeof)); }