Esempio n. 1
0
 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),
           } },
     };
 }
Esempio n. 2
0
        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;
            }
        }
Esempio n. 3
0
 private static OpcodeDef CreateDef(string Higher, Opcode Opcode, int Sizeof = 2)
 {
     return(OpcodeDef.Create("????" + Higher, Opcode, Sizeof));
 }